From ef2e26c91b80556af033d3335e55f5dfa6fff31d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Aug 2003 01:53:07 +0000 Subject: first public release of samba4 code (This used to be commit b0510b5428b3461aeb9bbe3cc95f62fc73e2b97f) --- source4/lib/.cvsignore | 3 + source4/lib/account_pol.c | 169 ++ source4/lib/adt_tree.c | 464 ++++++ source4/lib/bitmap.c | 163 ++ source4/lib/charcnv.c | 925 +++++++++++ source4/lib/cmdline/popt_common.c | 327 ++++ source4/lib/cmdline/readline.c | 159 ++ source4/lib/crc32.c | 71 + source4/lib/crypto/crc32.c | 71 + source4/lib/crypto/hmacmd5.c | 134 ++ source4/lib/crypto/md4.c | 175 ++ source4/lib/crypto/md5.c | 247 +++ source4/lib/data_blob.c | 141 ++ source4/lib/debug.c | 157 ++ source4/lib/dmallocmsg.c | 72 + source4/lib/dprintf.c | 113 ++ source4/lib/events.c | 372 +++++ source4/lib/fault.c | 107 ++ source4/lib/fsusage.c | 148 ++ source4/lib/gencache.c | 372 +++++ source4/lib/genparser.c | 786 +++++++++ source4/lib/genparser_samba.c | 200 +++ source4/lib/genrand.c | 267 ++++ source4/lib/getsmbpass.c | 156 ++ source4/lib/hmacmd5.c | 134 ++ source4/lib/iconv.c | 526 ++++++ source4/lib/interface.c | 333 ++++ source4/lib/interfaces.c | 407 +++++ source4/lib/ldap_escape.c | 90 ++ source4/lib/md4.c | 175 ++ source4/lib/md5.c | 247 +++ source4/lib/messages.c | 566 +++++++ source4/lib/module.c | 128 ++ source4/lib/ms_fnmatch.c | 226 +++ source4/lib/mutex.c | 142 ++ source4/lib/pam_errors.c | 126 ++ source4/lib/pidfile.c | 109 ++ source4/lib/popt/CHANGES | 43 + source4/lib/popt/COPYING | 22 + source4/lib/popt/README | 18 + source4/lib/popt/dummy.in | 0 source4/lib/popt/findme.c | 46 + source4/lib/popt/findme.h | 10 + source4/lib/popt/popt.c | 782 +++++++++ source4/lib/popt/popt.h | 130 ++ source4/lib/popt/poptconfig.c | 142 ++ source4/lib/popt/popthelp.c | 301 ++++ source4/lib/popt/poptint.h | 71 + source4/lib/popt/poptparse.c | 102 ++ source4/lib/popt/system.h | 53 + source4/lib/popt_common.c | 327 ++++ source4/lib/readline.c | 159 ++ source4/lib/replace.c | 467 ++++++ source4/lib/select.c | 159 ++ source4/lib/sendfile.c | 382 +++++ source4/lib/server_mutex.c | 58 + source4/lib/signal.c | 139 ++ source4/lib/smbpasswd.c | 200 +++ source4/lib/smbrun.c | 171 ++ source4/lib/snprintf.c | 978 ++++++++++++ source4/lib/substitute.c | 188 +++ source4/lib/sysacls.c | 3198 +++++++++++++++++++++++++++++++++++++ source4/lib/system.c | 1114 +++++++++++++ source4/lib/system_smbd.c | 119 ++ source4/lib/talloc.c | 515 ++++++ source4/lib/tallocmsg.c | 58 + source4/lib/talloctort.c | 65 + source4/lib/tdb/README | 167 ++ source4/lib/tdb/spinlock.c | 430 +++++ source4/lib/tdb/spinlock.h | 55 + source4/lib/tdb/tdb.c | 2020 +++++++++++++++++++++++ source4/lib/tdb/tdb.h | 144 ++ source4/lib/tdb/tdb.magic | 10 + source4/lib/tdb/tdbutil.c | 687 ++++++++ source4/lib/tdb/tdbutil.h | 37 + source4/lib/time.c | 754 +++++++++ source4/lib/username.c | 537 +++++++ source4/lib/util.c | 1000 ++++++++++++ source4/lib/util_file.c | 531 ++++++ source4/lib/util_getent.c | 306 ++++ source4/lib/util_pw.c | 89 ++ source4/lib/util_seaccess.c | 486 ++++++ source4/lib/util_sid.c | 631 ++++++++ source4/lib/util_smbd.c | 65 + source4/lib/util_sock.c | 631 ++++++++ source4/lib/util_str.c | 1619 +++++++++++++++++++ source4/lib/util_unistr.c | 838 ++++++++++ source4/lib/util_uuid.c | 104 ++ source4/lib/wins_srv.c | 361 +++++ source4/lib/xfile.c | 378 +++++ 90 files changed, 30905 insertions(+) create mode 100644 source4/lib/.cvsignore create mode 100644 source4/lib/account_pol.c create mode 100644 source4/lib/adt_tree.c create mode 100644 source4/lib/bitmap.c create mode 100644 source4/lib/charcnv.c create mode 100644 source4/lib/cmdline/popt_common.c create mode 100644 source4/lib/cmdline/readline.c create mode 100644 source4/lib/crc32.c create mode 100644 source4/lib/crypto/crc32.c create mode 100644 source4/lib/crypto/hmacmd5.c create mode 100644 source4/lib/crypto/md4.c create mode 100644 source4/lib/crypto/md5.c create mode 100644 source4/lib/data_blob.c create mode 100644 source4/lib/debug.c create mode 100644 source4/lib/dmallocmsg.c create mode 100644 source4/lib/dprintf.c create mode 100644 source4/lib/events.c create mode 100644 source4/lib/fault.c create mode 100644 source4/lib/fsusage.c create mode 100644 source4/lib/gencache.c create mode 100644 source4/lib/genparser.c create mode 100644 source4/lib/genparser_samba.c create mode 100644 source4/lib/genrand.c create mode 100644 source4/lib/getsmbpass.c create mode 100644 source4/lib/hmacmd5.c create mode 100644 source4/lib/iconv.c create mode 100644 source4/lib/interface.c create mode 100644 source4/lib/interfaces.c create mode 100644 source4/lib/ldap_escape.c create mode 100644 source4/lib/md4.c create mode 100644 source4/lib/md5.c create mode 100644 source4/lib/messages.c create mode 100644 source4/lib/module.c create mode 100644 source4/lib/ms_fnmatch.c create mode 100644 source4/lib/mutex.c create mode 100644 source4/lib/pam_errors.c create mode 100644 source4/lib/pidfile.c create mode 100644 source4/lib/popt/CHANGES create mode 100644 source4/lib/popt/COPYING create mode 100644 source4/lib/popt/README create mode 100644 source4/lib/popt/dummy.in create mode 100644 source4/lib/popt/findme.c create mode 100644 source4/lib/popt/findme.h create mode 100644 source4/lib/popt/popt.c create mode 100644 source4/lib/popt/popt.h create mode 100644 source4/lib/popt/poptconfig.c create mode 100644 source4/lib/popt/popthelp.c create mode 100644 source4/lib/popt/poptint.h create mode 100644 source4/lib/popt/poptparse.c create mode 100644 source4/lib/popt/system.h create mode 100644 source4/lib/popt_common.c create mode 100644 source4/lib/readline.c create mode 100644 source4/lib/replace.c create mode 100644 source4/lib/select.c create mode 100644 source4/lib/sendfile.c create mode 100644 source4/lib/server_mutex.c create mode 100644 source4/lib/signal.c create mode 100644 source4/lib/smbpasswd.c create mode 100644 source4/lib/smbrun.c create mode 100644 source4/lib/snprintf.c create mode 100644 source4/lib/substitute.c create mode 100644 source4/lib/sysacls.c create mode 100644 source4/lib/system.c create mode 100644 source4/lib/system_smbd.c create mode 100644 source4/lib/talloc.c create mode 100644 source4/lib/tallocmsg.c create mode 100644 source4/lib/talloctort.c create mode 100644 source4/lib/tdb/README create mode 100644 source4/lib/tdb/spinlock.c create mode 100644 source4/lib/tdb/spinlock.h create mode 100644 source4/lib/tdb/tdb.c create mode 100644 source4/lib/tdb/tdb.h create mode 100644 source4/lib/tdb/tdb.magic create mode 100644 source4/lib/tdb/tdbutil.c create mode 100644 source4/lib/tdb/tdbutil.h create mode 100644 source4/lib/time.c create mode 100644 source4/lib/username.c create mode 100644 source4/lib/util.c create mode 100644 source4/lib/util_file.c create mode 100644 source4/lib/util_getent.c create mode 100644 source4/lib/util_pw.c create mode 100644 source4/lib/util_seaccess.c create mode 100644 source4/lib/util_sid.c create mode 100644 source4/lib/util_smbd.c create mode 100644 source4/lib/util_sock.c create mode 100644 source4/lib/util_str.c create mode 100644 source4/lib/util_unistr.c create mode 100644 source4/lib/util_uuid.c create mode 100644 source4/lib/wins_srv.c create mode 100644 source4/lib/xfile.c (limited to 'source4/lib') diff --git a/source4/lib/.cvsignore b/source4/lib/.cvsignore new file mode 100644 index 0000000000..07da2225c7 --- /dev/null +++ b/source4/lib/.cvsignore @@ -0,0 +1,3 @@ +*.po +*.po32 + diff --git a/source4/lib/account_pol.c b/source4/lib/account_pol.c new file mode 100644 index 0000000000..df1479da3a --- /dev/null +++ b/source4/lib/account_pol.c @@ -0,0 +1,169 @@ +/* + * Unix SMB/CIFS implementation. + * account policy storage + * Copyright (C) Jean Fran�ois Micouleau 1998-2001. + * Copyright (C) Andrew Bartlett 2002 + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +static TDB_CONTEXT *tdb; /* used for driver files */ + +#define DATABASE_VERSION 1 + +/**************************************************************************** + Open the account policy tdb. +****************************************************************************/ + +BOOL init_account_policy(void) +{ + static pid_t local_pid; + const char *vstring = "INFO/version"; + uint32 version; + TALLOC_CTX *mem_ctx; + + if (tdb && local_pid == getpid()) + return True; + mem_ctx = talloc_init("init_account_policy"); + if (!mem_ctx) { + DEBUG(0,("No memory to open account policy database\n")); + return False; + } + tdb = tdb_open_log(lock_path(mem_ctx, "account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + talloc_destroy(mem_ctx); + if (!tdb) { + DEBUG(0,("Failed to open account policy database\n")); + return False; + } + + local_pid = getpid(); + + /* handle a Samba upgrade */ + tdb_lock_bystring(tdb, vstring,0); + if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { + tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); + tdb_store_uint32(tdb, vstring, DATABASE_VERSION); + + account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */ + account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */ + account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, 0); /* don't force user to logon */ + account_policy_set(AP_MAX_PASSWORD_AGE, MAX_PASSWORD_AGE); /* 21 days */ + account_policy_set(AP_MIN_PASSWORD_AGE, 0); /* 0 days */ + account_policy_set(AP_LOCK_ACCOUNT_DURATION, 0); /* lockout for 0 minutes */ + account_policy_set(AP_RESET_COUNT_TIME, 0); /* reset immediatly */ + account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, 0); /* don't lockout */ + account_policy_set(AP_TIME_TO_LOGOUT, -1); /* don't force logout */ + } + tdb_unlock_bystring(tdb, vstring); + + return True; +} + +static const struct { + int field; + const char *string; +} account_policy_names[] = { + {AP_MIN_PASSWORD_LEN, "min password length"}, + {AP_PASSWORD_HISTORY, "password history"}, + {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"}, + {AP_MAX_PASSWORD_AGE, "maximum password age"}, + {AP_MIN_PASSWORD_AGE,"minimum password age"}, + {AP_LOCK_ACCOUNT_DURATION, "lockout duration"}, + {AP_RESET_COUNT_TIME, "reset count minutes"}, + {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"}, + {AP_TIME_TO_LOGOUT, "disconnect time"}, + {0, NULL} +}; + +/**************************************************************************** +Get the account policy name as a string from its #define'ed number +****************************************************************************/ + +static const char *decode_account_policy_name(int field) +{ + int i; + for (i=0; account_policy_names[i].string; i++) { + if (field == account_policy_names[i].field) + return account_policy_names[i].string; + } + return NULL; + +} + +/**************************************************************************** +Get the account policy name as a string from its #define'ed number +****************************************************************************/ + +int account_policy_name_to_fieldnum(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 0; + +} + + +/**************************************************************************** +****************************************************************************/ +BOOL account_policy_get(int field, uint32 *value) +{ + fstring name; + + init_account_policy(); + + *value = 0; + + fstrcpy(name, decode_account_policy_name(field)); + if (!*name) { + DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); + return False; + } + if (!tdb_fetch_uint32(tdb, name, value)) { + DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for efild %d (%s), returning 0", field, name)); + return False; + } + DEBUG(10,("account_policy_get: %s:%d\n", name, *value)); + return True; +} + + +/**************************************************************************** +****************************************************************************/ +BOOL account_policy_set(int field, uint32 value) +{ + fstring name; + + init_account_policy(); + + fstrcpy(name, decode_account_policy_name(field)); + if (!*name) { + DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field)); + return False; + } + + if (!tdb_store_uint32(tdb, name, value)) { + DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value)); + return False; + } + + DEBUG(10,("account_policy_set: %s:%d\n", name, value)); + + return True; +} + diff --git a/source4/lib/adt_tree.c b/source4/lib/adt_tree.c new file mode 100644 index 0000000000..0bc224ec23 --- /dev/null +++ b/source4/lib/adt_tree.c @@ -0,0 +1,464 @@ +/* + * Unix SMB/CIFS implementation. + * Generic Abstract Data Types + * Copyright (C) Gerald Carter 2002. + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + + +/************************************************************************** + Initialize the tree's root. The cmp_fn is a callback function used + for comparision of two children + *************************************************************************/ + +static BOOL trim_tree_keypath( char *path, char **base, char **new_path ) +{ + char *p; + + *new_path = *base = NULL; + + if ( !path ) + return False; + + *base = path; + + p = strchr( path, '/' ); + + if ( p ) { + *p = '\0'; + *new_path = p+1; + } + + return True; +} + + +/************************************************************************** + Initialize the tree's root. The cmp_fn is a callback function used + for comparision of two children + *************************************************************************/ + +SORTED_TREE* sorted_tree_init( void *data_p, + int (cmp_fn)(void*, void*), + void (free_fn)(void*) ) +{ + SORTED_TREE *tree = NULL; + + if ( !(tree = (SORTED_TREE*)malloc( sizeof(SORTED_TREE) )) ) + return NULL; + + ZERO_STRUCTP( tree ); + + tree->compare = cmp_fn; + tree->free = free_fn; + + if ( !(tree->root = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) { + SAFE_FREE( tree ); + return NULL; + } + + ZERO_STRUCTP( tree->root ); + tree->root->data_p = data_p; + + return tree; +} + + +/************************************************************************** + Delete a tree and free all allocated memory + *************************************************************************/ + +static void sorted_tree_destroy_children( TREE_NODE *root ) +{ + int i; + + if ( !root ) + return; + + for ( i=0; inum_children; i++ ) + { + sorted_tree_destroy_children( root->children[i] ); + } + + SAFE_FREE( root->children ); + SAFE_FREE( root->key ); + + return; +} + +/************************************************************************** + Delete a tree and free all allocated memory + *************************************************************************/ + +void sorted_tree_destroy( SORTED_TREE *tree ) +{ + if ( tree->root ) + sorted_tree_destroy_children( tree->root ); + + if ( tree->free ) + tree->free( tree->root ); + + SAFE_FREE( tree ); +} + +/************************************************************************** + Find the next child given a key string + *************************************************************************/ + +static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key ) +{ + TREE_NODE *infant = NULL; + TREE_NODE **siblings; + int i; + + if ( !(infant = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) + return NULL; + + ZERO_STRUCTP( infant ); + + infant->key = strdup( key ); + infant->parent = node; + + siblings = Realloc( node->children, sizeof(TREE_NODE*)*(node->num_children+1) ); + + if ( siblings ) + node->children = siblings; + + node->num_children++; + + /* first child */ + + if ( node->num_children == 1 ) { + DEBUG(11,("sorted_tree_birth_child: First child of node [%s]! [%s]\n", + node->key ? node->key : "NULL", infant->key )); + node->children[0] = infant; + } + else + { + /* + * multiple siblings .... (at least 2 children) + * + * work from the end of the list forward + * The last child is not set at this point + * Insert the new infanct in ascending order + * from left to right + */ + + for ( i = node->num_children-1; i>=1; i-- ) + { + DEBUG(11,("sorted_tree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n", + infant->key, node->children[i-1]->key)); + + /* the strings should never match assuming that we + have called sorted_tree_find_child() first */ + + if ( StrCaseCmp( infant->key, node->children[i-1]->key ) > 0 ) { + DEBUG(11,("sorted_tree_birth_child: storing infant in i == [%d]\n", + i)); + node->children[i] = infant; + break; + } + + /* bump everything towards the end on slot */ + + node->children[i] = node->children[i-1]; + } + + DEBUG(11,("sorted_tree_birth_child: Exiting loop (i == [%d])\n", i )); + + /* if we haven't found the correct slot yet, the child + will be first in the list */ + + if ( i == 0 ) + node->children[0] = infant; + } + + return infant; +} + +/************************************************************************** + Find the next child given a key string + *************************************************************************/ + +static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key ) +{ + TREE_NODE *next = NULL; + int i, result; + + if ( !node ) { + DEBUG(0,("sorted_tree_find_child: NULL node passed into function!\n")); + return NULL; + } + + if ( !key ) { + DEBUG(0,("sorted_tree_find_child: NULL key string passed into function!\n")); + return NULL; + } + + for ( i=0; inum_children; i++ ) + { + DEBUG(11,("sorted_tree_find_child: child key => [%s]\n", + node->children[i]->key)); + + result = StrCaseCmp( node->children[i]->key, key ); + + if ( result == 0 ) + next = node->children[i]; + + /* if result > 0 then we've gone to far because + the list of children is sorted by key name + If result == 0, then we have a match */ + + if ( result > 0 ) + break; + } + + DEBUG(11,("sorted_tree_find_child: %s [%s]\n", + next ? "Found" : "Did not find", key )); + + return next; +} + +/************************************************************************** + Add a new node into the tree given a key path and a blob of data + *************************************************************************/ + +BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p ) +{ + char *str, *base, *path2; + TREE_NODE *current, *next; + BOOL ret = True; + + DEBUG(8,("sorted_tree_add: Enter\n")); + + if ( !path || *path != '/' ) { + DEBUG(0,("sorted_tree_add: Attempt to add a node with a bad path [%s]\n", + path ? path : "NULL" )); + return False; + } + + if ( !tree ) { + DEBUG(0,("sorted_tree_add: Attempt to add a node to an uninitialized tree!\n")); + return False; + } + + /* move past the first '/' */ + + path++; + path2 = strdup( path ); + if ( !path2 ) { + DEBUG(0,("sorted_tree_add: strdup() failed on string [%s]!?!?!\n", path)); + return False; + } + + + /* + * this works sort of like a 'mkdir -p' call, possibly + * creating an entire path to the new node at once + * The path should be of the form ///... + */ + + base = path2; + str = path2; + current = tree->root; + + do { + /* break off the remaining part of the path */ + + str = strchr( str, '/' ); + if ( str ) + *str = '\0'; + + /* iterate to the next child--birth it if necessary */ + + next = sorted_tree_find_child( current, base ); + if ( !next ) { + next = sorted_tree_birth_child( current, base ); + if ( !next ) { + DEBUG(0,("sorted_tree_add: Failed to create new child!\n")); + ret = False; + goto done; + } + } + current = next; + + /* setup the next part of the path */ + + base = str; + if ( base ) { + *base = '/'; + base++; + str = base; + } + + } while ( base != NULL ); + + current->data_p = data_p; + + DEBUG(10,("sorted_tree_add: Successfully added node [%s] to tree\n", + path )); + + DEBUG(8,("sorted_tree_add: Exit\n")); + +done: + SAFE_FREE( path2 ); + return ret; +} + + +/************************************************************************** + Recursive routine to print out all children of a TREE_NODE + *************************************************************************/ + +static void sorted_tree_print_children( TREE_NODE *node, int debug, const char *path ) +{ + int i; + int num_children; + pstring path2; + + if ( !node ) + return; + + + if ( node->key ) + DEBUG(debug,("%s: [%s] (%s)\n", path ? path : "NULL", node->key, + node->data_p ? "data" : "NULL" )); + + *path2 = '\0'; + if ( path ) + pstrcpy( path2, path ); + pstrcat( path2, node->key ? node->key : "NULL" ); + pstrcat( path2, "/" ); + + num_children = node->num_children; + for ( i=0; ichildren[i], debug, path2 ); + + +} + +/************************************************************************** + Dump the kys for a tree to the log file + *************************************************************************/ + +void sorted_tree_print_keys( SORTED_TREE *tree, int debug ) +{ + int i; + int num_children = tree->root->num_children; + + if ( tree->root->key ) + DEBUG(debug,("ROOT/: [%s] (%s)\n", tree->root->key, + tree->root->data_p ? "data" : "NULL" )); + + for ( i=0; iroot->children[i], debug, + tree->root->key ? tree->root->key : "ROOT/" ); + } + +} + +/************************************************************************** + return the data_p for for the node in tree matching the key string + The key string is the full path. We must break it apart and walk + the tree + *************************************************************************/ + +void* sorted_tree_find( SORTED_TREE *tree, char *key ) +{ + char *keystr, *base, *str, *p; + TREE_NODE *current; + void *result = NULL; + + DEBUG(10,("sorted_tree_find: Enter [%s]\n", key ? key : "NULL" )); + + /* sanity checks first */ + + if ( !key ) { + DEBUG(0,("sorted_tree_find: Attempt to search tree using NULL search string!\n")); + return NULL; + } + + if ( !tree ) { + DEBUG(0,("sorted_tree_find: Attempt to search an uninitialized tree using string [%s]!\n", + key ? key : "NULL" )); + return NULL; + } + + if ( !tree->root ) + return NULL; + + /* make a copy to play with */ + + if ( *key == '/' ) + keystr = strdup( key+1 ); + else + keystr = strdup( key ); + + if ( !keystr ) { + DEBUG(0,("sorted_tree_find: strdup() failed on string [%s]!?!?!\n", key)); + return NULL; + } + + /* start breaking the path apart */ + + p = keystr; + current = tree->root; + + if ( tree->root->data_p ) + result = tree->root->data_p; + + do + { + /* break off the remaining part of the path */ + + trim_tree_keypath( p, &base, &str ); + + DEBUG(11,("sorted_tree_find: [loop] base => [%s], new_path => [%s]\n", + base, str)); + + /* iterate to the next child */ + + current = sorted_tree_find_child( current, base ); + + /* + * the idea is that the data_p for a parent should + * be inherited by all children, but allow it to be + * overridden farther down + */ + + if ( current && current->data_p ) + result = current->data_p; + + /* reset the path pointer 'p' to the remaining part of the key string */ + + p = str; + + } while ( str && current ); + + /* result should be the data_p from the lowest match node in the tree */ + if ( result ) + DEBUG(11,("sorted_tree_find: Found data_p!\n")); + + SAFE_FREE( keystr ); + + DEBUG(10,("sorted_tree_find: Exit\n")); + + return result; +} + + diff --git a/source4/lib/bitmap.c b/source4/lib/bitmap.c new file mode 100644 index 0000000000..1023dd6541 --- /dev/null +++ b/source4/lib/bitmap.c @@ -0,0 +1,163 @@ +/* + Unix SMB/CIFS implementation. + simple bitmap functions + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* these functions provide a simple way to allocate integers from a + pool without repetition */ + +/**************************************************************************** +allocate a bitmap of the specified size +****************************************************************************/ +struct bitmap *bitmap_allocate(int n) +{ + struct bitmap *bm; + + bm = (struct bitmap *)malloc(sizeof(*bm)); + + if (!bm) return NULL; + + bm->n = n; + bm->b = (uint32 *)malloc(sizeof(bm->b[0])*(n+31)/32); + if (!bm->b) { + SAFE_FREE(bm); + return NULL; + } + + memset(bm->b, 0, sizeof(bm->b[0])*(n+31)/32); + + return bm; +} + +/**************************************************************************** +free a bitmap. +****************************************************************************/ + +void bitmap_free(struct bitmap *bm) +{ + if (!bm) + return; + + SAFE_FREE(bm->b); + SAFE_FREE(bm); +} + +/**************************************************************************** +talloc a bitmap +****************************************************************************/ +struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n) +{ + struct bitmap *bm; + + if (!mem_ctx) return NULL; + + bm = (struct bitmap *)talloc(mem_ctx, sizeof(*bm)); + + if (!bm) return NULL; + + bm->n = n; + bm->b = (uint32 *)talloc(mem_ctx, sizeof(bm->b[0])*(n+31)/32); + if (!bm->b) { + return NULL; + } + + memset(bm->b, 0, sizeof(bm->b[0])*(n+31)/32); + + return bm; +} + +/**************************************************************************** +set a bit in a bitmap +****************************************************************************/ +BOOL bitmap_set(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) { + DEBUG(0,("Setting invalid bitmap entry %d (of %d)\n", + i, bm->n)); + return False; + } + bm->b[i/32] |= (1<<(i%32)); + return True; +} + +/**************************************************************************** +clear a bit in a bitmap +****************************************************************************/ +BOOL bitmap_clear(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) { + DEBUG(0,("clearing invalid bitmap entry %d (of %d)\n", + i, bm->n)); + return False; + } + bm->b[i/32] &= ~(1<<(i%32)); + return True; +} + +/**************************************************************************** +query a bit in a bitmap +****************************************************************************/ +BOOL bitmap_query(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) return False; + if (bm->b[i/32] & (1<<(i%32))) { + return True; + } + return False; +} + +/**************************************************************************** +find a zero bit in a bitmap starting at the specified offset, with +wraparound +****************************************************************************/ +int bitmap_find(struct bitmap *bm, unsigned ofs) +{ + unsigned int i, j; + + if (ofs > bm->n) ofs = 0; + + i = ofs; + while (i < bm->n) { + if (~(bm->b[i/32])) { + j = i; + do { + if (!bitmap_query(bm, j)) return j; + j++; + } while (j & 31 && j < bm->n); + } + i += 32; + i &= ~31; + } + + i = 0; + while (i < ofs) { + if (~(bm->b[i/32])) { + j = i; + do { + if (!bitmap_query(bm, j)) return j; + j++; + } while (j & 31 && j < bm->n); + } + i += 32; + i &= ~31; + } + + return -1; +} diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c new file mode 100644 index 0000000000..90ddbb4d53 --- /dev/null +++ b/source4/lib/charcnv.c @@ -0,0 +1,925 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include "includes.h" + +/** + * @file + * + * @brief Character-set conversion routines built on our iconv. + * + * @note Samba's internal character set (at least in the 3.0 series) + * is always the same as the one for the Unix filesystem. It is + * not necessarily UTF-8 and may be different on machines that + * need i18n filenames to be compatible with Unix software. It does + * have to be a superset of ASCII. All multibyte sequences must start + * with a byte with the high bit set. + * + * @sa lib/iconv.c + */ + +static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; + + +/** + * Return the name of a charset to give to iconv(). + **/ +static const char *charset_name(charset_t ch) +{ + const char *ret = NULL; + + if (ch == CH_UCS2) ret = "UCS-2LE"; + else if (ch == CH_UNIX) ret = lp_unix_charset(); + else if (ch == CH_DOS) ret = lp_dos_charset(); + else if (ch == CH_DISPLAY) ret = lp_display_charset(); + else if (ch == CH_UTF8) ret = "UTF8"; + + if (!ret || !*ret) ret = "ASCII"; + return ret; +} + +static void lazy_initialize_conv(void) +{ + static int initialized = False; + + if (!initialized) { + initialized = True; + load_case_tables(); + init_iconv(); + init_valid_table(); + } +} + +/** + Initialize iconv conversion descriptors. +**/ + +void init_iconv(void) +{ + int c1, c2; + BOOL did_reload = False; + + /* so that charset_name() works we need to get the UNIX<->UCS2 going + first */ + if (!conv_handles[CH_UNIX][CH_UCS2]) + conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII"); + + if (!conv_handles[CH_UCS2][CH_UNIX]) + conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE"); + + for (c1=0;c1from_name) == 0 && + strcmp(n2, conv_handles[c1][c2]->to_name) == 0) + continue; + + did_reload = True; + + if (conv_handles[c1][c2]) + smb_iconv_close(conv_handles[c1][c2]); + + conv_handles[c1][c2] = smb_iconv_open(n2,n1); + if (conv_handles[c1][c2] == (smb_iconv_t)-1) { + DEBUG(0,("Conversion from %s to %s not supported\n", + charset_name((charset_t)c1), charset_name((charset_t)c2))); + conv_handles[c1][c2] = NULL; + } + } + } + + if (did_reload) { + init_valid_table(); + } +} + +/** + * Convert string from one encoding to another, making error checking etc + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @returns the number of bytes occupied in the destination + **/ +ssize_t convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen) +{ + size_t i_len, o_len; + size_t retval; + const char* inbuf = (const char*)src; + char* outbuf = (char*)dest; + smb_iconv_t descriptor; + + if (srclen == (size_t)-1) + srclen = strlen(src)+1; + + lazy_initialize_conv(); + + descriptor = conv_handles[from][to]; + + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + /* conversion not supported, use as is */ + size_t len = MIN(srclen,destlen); + memcpy(dest,src,len); + return len; + } + + i_len=srclen; + o_len=destlen; + retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); + if(retval==(size_t)-1) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + break; + case E2BIG: + reason="No more room"; + DEBUG(0, ("convert_string: Required %d, available %d\n", + srclen, destlen)); + /* we are not sure we need srclen bytes, + may be more, may be less. + We only know we need more than destlen + bytes ---simo */ + break; + case EILSEQ: + reason="Illegal multibyte sequence"; + break; + } + /* smb_panic(reason); */ + } + return destlen-o_len; +} + +/** + * Convert between character sets, allocating a new buffer for the result. + * + * @param srclen length of source buffer. + * @param dest always set at least to NULL + * @note -1 is not accepted for srclen. + * + * @returns Size in bytes of the converted string; or -1 in case of error. + **/ + +ssize_t convert_string_allocate(charset_t from, charset_t to, + void const *src, size_t srclen, void **dest) +{ + size_t i_len, o_len, destlen; + size_t retval; + const char *inbuf = (const char *)src; + char *outbuf, *ob; + smb_iconv_t descriptor; + + *dest = NULL; + + if (src == NULL || srclen == (size_t)-1 || srclen == 0) + return (size_t)-1; + + lazy_initialize_conv(); + + descriptor = conv_handles[from][to]; + + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + /* conversion not supported, return -1*/ + DEBUG(3, ("convert_string_allocate: conversion not supported!\n")); + return -1; + } + + destlen = MAX(srclen, 512); + outbuf = NULL; +convert: + destlen = destlen * 2; + ob = (char *)realloc(outbuf, destlen); + if (!ob) { + DEBUG(0, ("convert_string_allocate: realloc failed!\n")); + SAFE_FREE(outbuf); + return (size_t)-1; + } + else + outbuf = ob; + i_len = srclen; + o_len = destlen; + retval = smb_iconv(descriptor, + &inbuf, &i_len, + &outbuf, &o_len); + if(retval == (size_t)-1) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + break; + case E2BIG: + goto convert; + case EILSEQ: + reason="Illegal multibyte sequence"; + break; + } + DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); + /* smb_panic(reason); */ + return (size_t)-1; + } + + destlen = destlen - o_len; + *dest = (char *)Realloc(ob,destlen); + if (!*dest) { + DEBUG(0, ("convert_string_allocate: out of memory!\n")); + SAFE_FREE(ob); + return (size_t)-1; + } + + return destlen; +} + + +/** + * Convert between character sets, allocating a new buffer using talloc for the result. + * + * @param srclen length of source buffer. + * @param dest always set at least to NULL + * @note -1 is not accepted for srclen. + * + * @returns Size in bytes of the converted string; or -1 in case of error. + **/ +ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, + void const *src, size_t srclen, const void **dest) +{ + void *alloced_string; + size_t dest_len; + void *dst; + + *dest = NULL; + dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string); + if (dest_len == (size_t)-1) + return (size_t)-1; + dst = talloc(ctx, dest_len + 2); + /* we want to be absolutely sure that the result is terminated */ + memcpy(dst, alloced_string, dest_len); + SSVAL(dst, dest_len, 0); + SAFE_FREE(alloced_string); + if (dst == NULL) + return -1; + *dest = dst; + return dest_len; +} + +size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) +{ + size_t size; + smb_ucs2_t *buffer; + + size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, + (void **) &buffer); + if (size == -1) { + smb_panic("failed to create UCS2 buffer"); + } + if (!strupper_w(buffer) && (dest == src)) { + free(buffer); + return srclen; + } + + size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen); + free(buffer); + return size; +} + +size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) +{ + size_t size; + smb_ucs2_t *buffer; + + size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, + (void **) &buffer); + if (size == -1) { + smb_panic("failed to create UCS2 buffer"); + } + if (!strlower_w(buffer) && (dest == src)) { + free(buffer); + return srclen; + } + size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen); + free(buffer); + return size; +} + +size_t ucs2_align(const void *base_ptr, const void *p, int flags) +{ + if (flags & (STR_NOALIGN|STR_ASCII)) + return 0; + return PTR_DIFF(p, base_ptr) & 1; +} + + +/** + * Copy a string from a char* unix src to a dos codepage string destination. + * + * @return the number of bytes occupied by the string in the destination. + * + * @param flags can include + *
+ *
STR_TERMINATE
means include the null termination
+ *
STR_UPPER
means uppercase in the destination
+ *
+ * + * @param dest_len the maximum length in bytes allowed in the + * destination. If @p dest_len is -1 then no maximum is used. + **/ +ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t src_len = strlen(src); + pstring tmpbuf; + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_UPPER) { + pstrcpy(tmpbuf, src); + strupper(tmpbuf); + src = tmpbuf; + } + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) + src_len++; + + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); +} + +ssize_t push_ascii_fstring(void *dest, const char *src) +{ + return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE); +} + +ssize_t push_ascii_pstring(void *dest, const char *src) +{ + return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); +} + +ssize_t push_pstring(void *dest, const char *src) +{ + return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); +} + +/** + * Copy a string from a dos codepage source to a unix char* destination. + * + * The resulting string in "dest" is always null terminated. + * + * @param flags can have: + *
+ *
STR_TERMINATE
+ *
STR_TERMINATE means the string in @p src + * is null terminated, and src_len is ignored.
+ *
+ * + * @param src_len is the length of the source area in bytes. + * @returns the number of bytes occupied by the string in @p src. + **/ +ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = strlen(src) + 1; + } else { + size_t len = strnlen(src, src_len); + if (len < src_len) + len++; + src_len = len; + } + } + + ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); + + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +ssize_t pull_ascii_pstring(char *dest, const void *src) +{ + return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE); +} + +ssize_t pull_ascii_fstring(char *dest, const void *src) +{ + return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE); +} + +/** + * Copy a string from a char* src to a unicode destination. + * + * @returns the number of bytes occupied by the string in the destination. + * + * @param flags can have: + * + *
+ *
STR_TERMINATE
means include the null termination. + *
STR_UPPER
means uppercase in the destination. + *
STR_NOALIGN
means don't do alignment. + *
+ * + * @param dest_len is the maximum length allowed in the + * destination. If dest_len is -1 then no maxiumum is used. + **/ +ssize_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) +{ + size_t len=0; + size_t src_len = strlen(src); + pstring tmpbuf; + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_UPPER) { + pstrcpy(tmpbuf, src); + strupper(tmpbuf); + src = tmpbuf; + } + + if (flags & STR_TERMINATE) + src_len++; + + if (ucs2_align(base_ptr, dest, flags)) { + *(char *)dest = 0; + dest = (void *)((char *)dest + 1); + if (dest_len) dest_len--; + len++; + } + + /* ucs2 is always a multiple of 2 bytes */ + dest_len &= ~1; + + len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len); + return len; +} + + +/** + * Copy a string from a unix char* src to a UCS2 destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (const void **)dest); +} + + +/** + * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ + +ssize_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest); +} + +/** + Copy a string from a char* src to a UTF-8 destination. + Return the number of bytes occupied by the string in the destination + Flags can have: + STR_TERMINATE means include the null termination + STR_UPPER means uppercase in the destination + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maxiumum is used. +**/ + +ssize_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t src_len = strlen(src); + pstring tmpbuf; + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_UPPER) { + pstrcpy(tmpbuf, src); + strupper(tmpbuf); + src = tmpbuf; + } + + if (flags & STR_TERMINATE) + src_len++; + + return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len); +} + +ssize_t push_utf8_fstring(void *dest, const char *src) +{ + return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE); +} + +ssize_t push_utf8_pstring(void *dest, const char *src) +{ + return push_utf8(dest, src, sizeof(pstring), STR_TERMINATE); +} + +/** + * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (const void **)dest); +} + +/** + * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t push_utf8_allocate(char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest); +} + +/** + Copy a string from a ucs2 source to a unix char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_NOALIGN means don't try to align. + if STR_TERMINATE is set then src_len is ignored if it is -1. + src_len is the length of the source area in bytes + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (ucs2_align(base_ptr, src, flags)) { + src = (const void *)((const char *)src + 1); + if (src_len > 0) + src_len--; + } + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = strlen_w(src)*2 + 2; + } else { + size_t len = strnlen_w(src, src_len/2); + if (len < src_len/2) + len++; + src_len = len*2; + } + } + + /* ucs2 is always a multiple of 2 bytes */ + if (src_len != (size_t)-1) + src_len &= ~1; + + ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len); + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +ssize_t pull_ucs2_pstring(char *dest, const void *src) +{ + return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE); +} + +ssize_t pull_ucs2_fstring(char *dest, const void *src) +{ + return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE); +} + +/** + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src) +{ + size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); + *dest = NULL; + return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (const void **)dest); +} + +/** + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_ucs2_allocate(void **dest, const smb_ucs2_t *src) +{ + size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); + *dest = NULL; + return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, dest); +} + +/** + Copy a string from a utf-8 source to a unix char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + if STR_TERMINATE is set then src_len is ignored. + src_len is the length of the source area in bytes + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +ssize_t pull_utf8(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = strlen(src) + 1; + } else { + size_t len = strnlen(src, src_len); + if (len < src_len) + len++; + src_len = len; + } + } + + ret = convert_string(CH_UTF8, CH_UNIX, src, src_len, dest, dest_len); + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +ssize_t pull_utf8_pstring(char *dest, const void *src) +{ + return pull_utf8(dest, src, sizeof(pstring), -1, STR_TERMINATE); +} + +ssize_t pull_utf8_fstring(char *dest, const void *src) +{ + return pull_utf8(dest, src, sizeof(fstring), -1, STR_TERMINATE); +} + +/** + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (const void **)dest); +} + +/** + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_utf8_allocate(void **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest); +} + +/** + Copy a string from a char* src to a unicode or ascii + dos codepage destination choosing unicode or ascii based on the + flags in the SMB buffer starting at base_ptr. + Return the number of bytes occupied by the string in the destination. + flags can have: + STR_TERMINATE means include the null termination. + STR_UPPER means uppercase in the destination. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maxiumum is used. +**/ + +ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) +{ + if (!(flags & STR_ASCII) && \ + ((flags & STR_UNICODE || \ + (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { + return push_ucs2(base_ptr, dest, src, dest_len, flags); + } + return push_ascii(dest, src, dest_len, flags); +} + + +/** + Copy a string from a unicode or ascii source (depending on + the packet flags) to a char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_UNICODE means to force as unicode. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + if STR_TERMINATE is set then src_len is ignored is it is -1 + src_len is the length of the source area in bytes. + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +ssize_t pull_string(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + if (!(flags & STR_ASCII) && \ + ((flags & STR_UNICODE || \ + (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { + return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags); + } + return pull_ascii(dest, src, dest_len, src_len, flags); +} + +ssize_t align_string(const void *base_ptr, const char *p, int flags) +{ + if (!(flags & STR_ASCII) && \ + ((flags & STR_UNICODE || \ + (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { + return ucs2_align(base_ptr, p, flags); + } + return 0; +} + +/** + Copy a string from a unicode or ascii source (depending on + the packet flags) to a TALLOC'ed destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_UNICODE means to force as unicode. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + if STR_TERMINATE is set then src_len is ignored is it is -1 + src_len is the length of the source area in bytes. + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +ssize_t pull_string_talloc(TALLOC_CTX *ctx, char **dest, const void *src, size_t src_len, int flags) +{ + if (!(flags & STR_ASCII) && \ + (flags & STR_UNICODE)) { + return pull_ucs2_talloc(ctx, dest, src); + } + *dest = NULL; + if (flags & STR_TERMINATE) { + *dest = talloc_strdup(ctx, src); + return strlen(*dest); + } + *dest = talloc_strndup(ctx, src, src_len); + return src_len; +} + +/** + Convert from ucs2 to unix charset and return the + allocated and converted string or NULL if an error occurred. + You must provide a zero terminated string. + The returning string will be zero terminated. +**/ + +char *acnv_u2ux(const smb_ucs2_t *src) +{ + size_t slen; + size_t dlen; + void *dest; + + slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t); + dlen = convert_string_allocate(CH_UCS2, CH_UNIX, src, slen, &dest); + if (dlen == (size_t)-1) + return NULL; + else + return dest; +} + +/** + Convert from unix to ucs2 charset and return the + allocated and converted string or NULL if an error occurred. + You must provide a zero terminated string. + The returning string will be zero terminated. +**/ + +smb_ucs2_t *acnv_uxu2(const char *src) +{ + size_t slen; + size_t dlen; + void *dest; + + slen = strlen(src) + 1; + dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest); + if (dlen == (size_t)-1) + return NULL; + else + return dest; +} + +/** + Convert from ucs2 to dos charset and return the + allocated and converted string or NULL if an error occurred. + You must provide a zero terminated string. + The returning string will be zero terminated. +**/ + +char *acnv_u2dos(const smb_ucs2_t *src) +{ + size_t slen; + size_t dlen; + void *dest; + + slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t); + dlen = convert_string_allocate(CH_UCS2, CH_DOS, src, slen, &dest); + if (dlen == (size_t)-1) + return NULL; + else + return dest; +} + +/** + Convert from dos to ucs2 charset and return the + allocated and converted string or NULL if an error occurred. + You must provide a zero terminated string. + The returning string will be zero terminated. +**/ + +smb_ucs2_t *acnv_dosu2(const char *src) +{ + size_t slen; + size_t dlen; + void *dest; + + slen = strlen(src) + 1; + dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest); + if (dlen == (size_t)-1) + return NULL; + else + return dest; +} diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c new file mode 100644 index 0000000000..ccdecc91cc --- /dev/null +++ b/source4/lib/cmdline/popt_common.c @@ -0,0 +1,327 @@ +/* + Unix SMB/CIFS implementation. + Common popt routines + + Copyright (C) Tim Potter 2001,2002 + Copyright (C) Jelmer Vernooij 2002,2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* Handle command line options: + * -d,--debuglevel + * -s,--configfile + * -O,--socket-options + * -V,--version + * -l,--log-base + * -n,--netbios-name + * -W,--workgroup + * -i,--scope + */ + +extern pstring user_socket_options; +extern BOOL AllowDebugChange; + +struct user_auth_info cmdline_auth_info; + +static void popt_common_callback(poptContext con, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) +{ + pstring logfile; + const char *pname; + + /* Find out basename of current program */ + pname = strrchr_m(poptGetInvocationName(con),'/'); + + if (!pname) + pname = poptGetInvocationName(con); + else + pname++; + + if (reason == POPT_CALLBACK_REASON_PRE) { + pstr_sprintf(logfile, "%s/log.%s", dyn_LOGFILEBASE, pname); + lp_set_cmdline("log file", logfile); + return; + } + + switch(opt->val) { + case 'd': + lp_set_cmdline("log level", arg); + break; + + case 'V': + printf( "Version %s\n", SAMBA_VERSION ); + exit(0); + break; + + case 's': + if (arg) { + pstrcpy(dyn_CONFIGFILE, arg); + } + break; + + case 'l': + if (arg) { + pstr_sprintf(logfile, "%s/log.%s", arg, pname); + lp_set_cmdline("log file", logfile); + } + break; + + case 'W': + lp_set_cmdline("workgroup", arg); + break; + + case 'n': + lp_set_cmdline("netbios name", arg); + break; + + case 'i': + lp_set_cmdline("netbios scope", arg); + break; + } +} + +struct poptOption popt_common_connection[] = { + { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", + "SOCKETOPTIONS" }, + { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, + { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, + { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + POPT_TABLEEND +}; + +struct poptOption popt_common_samba[] = { + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, + { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, + { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, + { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, + { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, + POPT_TABLEEND +}; + +struct poptOption popt_common_version[] = { + { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, + POPT_TABLEEND +}; + + + +/**************************************************************************** + * get a password from a a file or file descriptor + * exit on failure + * ****************************************************************************/ +static void get_password_file(struct user_auth_info *a) +{ + int fd = -1; + char *p; + BOOL close_it = False; + pstring spec; + char pass[128]; + + if ((p = getenv("PASSWD_FD")) != NULL) { + pstrcpy(spec, "descriptor "); + pstrcat(spec, p); + sscanf(p, "%d", &fd); + close_it = False; + } else if ((p = getenv("PASSWD_FILE")) != NULL) { + fd = sys_open(p, O_RDONLY, 0); + pstrcpy(spec, p); + if (fd < 0) { + fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", + spec, strerror(errno)); + exit(1); + } + close_it = True; + } + + for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ + p && p - pass < sizeof(pass);) { + switch (read(fd, p, 1)) { + case 1: + if (*p != '\n' && *p != '\0') { + *++p = '\0'; /* advance p, and null-terminate pass */ + break; + } + case 0: + if (p - pass) { + *p = '\0'; /* null-terminate it, just in case... */ + p = NULL; /* then force the loop condition to become false */ + break; + } else { + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, "empty password\n"); + exit(1); + } + + default: + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, strerror(errno)); + exit(1); + } + } + pstrcpy(a->password, pass); + if (close_it) + close(fd); +} + +static void get_credentials_file(const char *file, struct user_auth_info *info) +{ + XFILE *auth; + fstring buf; + uint16 len = 0; + char *ptr, *val, *param; + + if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) + { + /* fail if we can't open the credentials file */ + d_printf("ERROR: Unable to open credentials file!\n"); + exit(-1); + } + + while (!x_feof(auth)) + { + /* get a line from the file */ + if (!x_fgets(buf, sizeof(buf), auth)) + continue; + len = strlen(buf); + + if ((len) && (buf[len-1]=='\n')) + { + buf[len-1] = '\0'; + len--; + } + if (len == 0) + continue; + + /* break up the line into parameter & value. + * will need to eat a little whitespace possibly */ + param = buf; + if (!(ptr = strchr_m (buf, '='))) + continue; + + val = ptr+1; + *ptr = '\0'; + + /* eat leading white space */ + while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) + val++; + + if (strwicmp("password", param) == 0) + { + pstrcpy(info->password, val); + info->got_pass = True; + } + else if (strwicmp("username", param) == 0) + pstrcpy(info->username, val); + //else if (strwicmp("domain", param) == 0) + // set_global_myworkgroup(val); + memset(buf, 0, sizeof(buf)); + } + x_fclose(auth); +} + +/* Handle command line options: + * -U,--user + * -A,--authentication-file + * -k,--use-kerberos + * -N,--no-pass + */ + + +static void popt_common_credentials_callback(poptContext con, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) +{ + char *p; + + if (reason == POPT_CALLBACK_REASON_PRE) { + cmdline_auth_info.use_kerberos = False; + cmdline_auth_info.got_pass = False; + pstrcpy(cmdline_auth_info.username, "GUEST"); + + if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); + + if (getenv("USER")) { + pstrcpy(cmdline_auth_info.username,getenv("USER")); + + if ((p = strchr_m(cmdline_auth_info.username,'%'))) { + *p = 0; + pstrcpy(cmdline_auth_info.password,p+1); + cmdline_auth_info.got_pass = True; + memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); + } + } + + if (getenv("PASSWD")) { + pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); + cmdline_auth_info.got_pass = True; + } + + if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { + get_password_file(&cmdline_auth_info); + cmdline_auth_info.got_pass = True; + } + + return; + } + + switch(opt->val) { + case 'U': + { + char *lp; + + pstrcpy(cmdline_auth_info.username,arg); + if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { + *lp = 0; + pstrcpy(cmdline_auth_info.password,lp+1); + cmdline_auth_info.got_pass = True; + memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); + } + } + break; + + case 'A': + get_credentials_file(arg, &cmdline_auth_info); + break; + + case 'k': +#ifndef HAVE_KRB5 + d_printf("No kerberos support compiled in\n"); + exit(1); +#else + cmdline_auth_info.use_kerberos = True; + cmdline_auth_info.got_pass = True; +#endif + break; + } +} + + + +struct poptOption popt_common_credentials[] = { + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, + { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, + { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, + POPT_TABLEEND +}; diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c new file mode 100644 index 0000000000..c5da88b3e0 --- /dev/null +++ b/source4/lib/cmdline/readline.c @@ -0,0 +1,159 @@ +/* + Unix SMB/CIFS implementation. + Samba readline wrapper implementation + Copyright (C) Simo Sorce 2001 + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifdef HAVE_LIBREADLINE +# ifdef HAVE_READLINE_READLINE_H +# include +# ifdef HAVE_READLINE_HISTORY_H +# include +# endif +# else +# ifdef HAVE_READLINE_H +# include +# ifdef HAVE_HISTORY_H +# include +# endif +# else +# undef HAVE_LIBREADLINE +# endif +# endif +#endif + +#ifdef HAVE_NEW_LIBREADLINE +# define RL_COMPLETION_CAST (rl_completion_func_t *) +#else +/* This type is missing from libreadline<4.0 (approximately) */ +# define RL_COMPLETION_CAST +#endif /* HAVE_NEW_LIBREADLINE */ + +/**************************************************************************** + Display the prompt and wait for input. Call callback() regularly +****************************************************************************/ + +static char *smb_readline_replacement(const char *prompt, void (*callback)(void), + char **(completion_fn)(const char *text, int start, int end)) +{ + fd_set fds; + static pstring line; + struct timeval timeout; + int fd = x_fileno(x_stdin); + char *ret; + + do_debug("%s", prompt); + + while (1) { + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(fd,&fds); + + if (sys_select_intr(fd+1,&fds,NULL,NULL,&timeout) == 1) { + ret = x_fgets(line, sizeof(line), x_stdin); + return ret; + } + if (callback) + callback(); + } +} + +/**************************************************************************** + Display the prompt and wait for input. Call callback() regularly. +****************************************************************************/ + +char *smb_readline(const char *prompt, void (*callback)(void), + char **(completion_fn)(const char *text, int start, int end)) +{ +#if HAVE_LIBREADLINE + if (isatty(x_fileno(x_stdin))) { + char *ret; + + /* Aargh! Readline does bizzare things with the terminal width + that mucks up expect(1). Set CLI_NO_READLINE in the environment + to force readline not to be used. */ + + if (getenv("CLI_NO_READLINE")) + return smb_readline_replacement(prompt, callback, completion_fn); + + if (completion_fn) { + /* The callback prototype has changed slightly between + different versions of Readline, so the same function + works in all of them to date, but we get compiler + warnings in some. */ + rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; + } + + if (callback) + rl_event_hook = (Function *)callback; + ret = readline(prompt); + if (ret && *ret) + add_history(ret); + return ret; + } else +#endif + return smb_readline_replacement(prompt, callback, completion_fn); +} + +/**************************************************************************** + * return line buffer text + ****************************************************************************/ +const char *smb_readline_get_line_buffer(void) +{ +#if defined(HAVE_LIBREADLINE) + return rl_line_buffer; +#else + return NULL; +#endif +} + +/**************************************************************************** + * set completion append character + ***************************************************************************/ +void smb_readline_ca_char(char c) +{ +#if defined(HAVE_LIBREADLINE) + rl_completion_append_character = c; +#endif +} + + +/**************************************************************************** +history +****************************************************************************/ +int cmd_history(void) +{ +#if defined(HAVE_LIBREADLINE) + HIST_ENTRY **hlist; + int i; + + hlist = history_list(); + + for (i = 0; hlist && hlist[i]; i++) { + DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); + } +#else + DEBUG(0,("no history without readline support\n")); +#endif + + return 0; +} diff --git a/source4/lib/crc32.c b/source4/lib/crc32.c new file mode 100644 index 0000000000..86b0bb6fd9 --- /dev/null +++ b/source4/lib/crc32.c @@ -0,0 +1,71 @@ +/* + Unix SMB/CIFS implementation. + crc32 implementation + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* table generated using algorithm from Mark Adler */ +static const uint32 crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + + +/* + see PNG specification or ISO-3309 for details +*/ +uint32 crc32_buffer(const uint8 *buf, int n) +{ + int i; + uint32 ret; + for (ret=~0, i=0;i> 8); + } + return ~ret; +} diff --git a/source4/lib/crypto/crc32.c b/source4/lib/crypto/crc32.c new file mode 100644 index 0000000000..86b0bb6fd9 --- /dev/null +++ b/source4/lib/crypto/crc32.c @@ -0,0 +1,71 @@ +/* + Unix SMB/CIFS implementation. + crc32 implementation + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* table generated using algorithm from Mark Adler */ +static const uint32 crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + + +/* + see PNG specification or ISO-3309 for details +*/ +uint32 crc32_buffer(const uint8 *buf, int n) +{ + int i; + uint32 ret; + for (ret=~0, i=0;i> 8); + } + return ~ret; +} diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c new file mode 100644 index 0000000000..f436fd30c0 --- /dev/null +++ b/source4/lib/crypto/hmacmd5.c @@ -0,0 +1,134 @@ +/* + Unix SMB/CIFS implementation. + HMAC MD5 code for use in NTLMv2 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Andrew Tridgell 1992-2000 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* taken direct from rfc2104 implementation and modified for suitable use + * for ntlmv2. + */ + +#include "includes.h" + +/*********************************************************************** + the rfc 2104 version of hmac_md5 initialisation. +***********************************************************************/ +void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) +{ + int i; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) + { + uchar tk[16]; + struct MD5Context tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* start out by storing key in pads */ + ZERO_STRUCT(ctx->k_ipad); + ZERO_STRUCT(ctx->k_opad); + memcpy( ctx->k_ipad, key, key_len); + memcpy( ctx->k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) + { + ctx->k_ipad[i] ^= 0x36; + ctx->k_opad[i] ^= 0x5c; + } + + MD5Init(&ctx->ctx); + MD5Update(&ctx->ctx, ctx->k_ipad, 64); +} + +/*********************************************************************** + the microsoft version of hmac_md5 initialisation. +***********************************************************************/ +void hmac_md5_init_limK_to_64(const uchar* key, int key_len, + HMACMD5Context *ctx) +{ + int i; + + /* if key is longer than 64 bytes truncate it */ + if (key_len > 64) + { + key_len = 64; + } + + /* start out by storing key in pads */ + ZERO_STRUCT(ctx->k_ipad); + ZERO_STRUCT(ctx->k_opad); + memcpy( ctx->k_ipad, key, key_len); + memcpy( ctx->k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + ctx->k_ipad[i] ^= 0x36; + ctx->k_opad[i] ^= 0x5c; + } + + MD5Init(&ctx->ctx); + MD5Update(&ctx->ctx, ctx->k_ipad, 64); +} + +/*********************************************************************** + update hmac_md5 "inner" buffer +***********************************************************************/ +void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) +{ + MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ +} + +/*********************************************************************** + finish off hmac_md5 "inner" buffer and generate outer one. +***********************************************************************/ +void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) + +{ + struct MD5Context ctx_o; + + MD5Final(digest, &ctx->ctx); + + MD5Init(&ctx_o); + MD5Update(&ctx_o, ctx->k_opad, 64); + MD5Update(&ctx_o, digest, 16); + MD5Final(digest, &ctx_o); +} + +/*********************************************************** + single function to calculate an HMAC MD5 digest from data. + use the microsoft hmacmd5 init method because the key is 16 bytes. +************************************************************/ +void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest) +{ + HMACMD5Context ctx; + hmac_md5_init_limK_to_64(key, 16, &ctx); + if (data_len != 0) + { + hmac_md5_update(data, data_len, &ctx); + } + hmac_md5_final(digest, &ctx); +} + diff --git a/source4/lib/crypto/md4.c b/source4/lib/crypto/md4.c new file mode 100644 index 0000000000..417e87bd8e --- /dev/null +++ b/source4/lib/crypto/md4.c @@ -0,0 +1,175 @@ +/* + Unix SMB/CIFS implementation. + a implementation of MD4 designed for use in the SMB authentication protocol + Copyright (C) Andrew Tridgell 1997-1998. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* NOTE: This code makes no attempt to be fast! + + It assumes that a int is at least 32 bits long +*/ + +struct mdfour_state { + uint32 A, B, C, D; +}; + +static uint32 F(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | ((~X)&Z); +} + +static uint32 G(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | (X&Z) | (Y&Z); +} + +static uint32 H(uint32 X, uint32 Y, uint32 Z) +{ + return X^Y^Z; +} + +static uint32 lshift(uint32 x, int s) +{ + x &= 0xFFFFFFFF; + return ((x<>(32-s)); +} + +#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64(struct mdfour_state *s, uint32 *M) +{ + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; + + for (j=0;j<16;j++) + X[j] = M[j]; + + AA = s->A; BB = s->B; CC = s->C; DD = s->D; + + ROUND1(s->A,s->B,s->C,s->D, 0, 3); ROUND1(s->D,s->A,s->B,s->C, 1, 7); + ROUND1(s->C,s->D,s->A,s->B, 2, 11); ROUND1(s->B,s->C,s->D,s->A, 3, 19); + ROUND1(s->A,s->B,s->C,s->D, 4, 3); ROUND1(s->D,s->A,s->B,s->C, 5, 7); + ROUND1(s->C,s->D,s->A,s->B, 6, 11); ROUND1(s->B,s->C,s->D,s->A, 7, 19); + ROUND1(s->A,s->B,s->C,s->D, 8, 3); ROUND1(s->D,s->A,s->B,s->C, 9, 7); + ROUND1(s->C,s->D,s->A,s->B, 10, 11); ROUND1(s->B,s->C,s->D,s->A, 11, 19); + ROUND1(s->A,s->B,s->C,s->D, 12, 3); ROUND1(s->D,s->A,s->B,s->C, 13, 7); + ROUND1(s->C,s->D,s->A,s->B, 14, 11); ROUND1(s->B,s->C,s->D,s->A, 15, 19); + + ROUND2(s->A,s->B,s->C,s->D, 0, 3); ROUND2(s->D,s->A,s->B,s->C, 4, 5); + ROUND2(s->C,s->D,s->A,s->B, 8, 9); ROUND2(s->B,s->C,s->D,s->A, 12, 13); + ROUND2(s->A,s->B,s->C,s->D, 1, 3); ROUND2(s->D,s->A,s->B,s->C, 5, 5); + ROUND2(s->C,s->D,s->A,s->B, 9, 9); ROUND2(s->B,s->C,s->D,s->A, 13, 13); + ROUND2(s->A,s->B,s->C,s->D, 2, 3); ROUND2(s->D,s->A,s->B,s->C, 6, 5); + ROUND2(s->C,s->D,s->A,s->B, 10, 9); ROUND2(s->B,s->C,s->D,s->A, 14, 13); + ROUND2(s->A,s->B,s->C,s->D, 3, 3); ROUND2(s->D,s->A,s->B,s->C, 7, 5); + ROUND2(s->C,s->D,s->A,s->B, 11, 9); ROUND2(s->B,s->C,s->D,s->A, 15, 13); + + ROUND3(s->A,s->B,s->C,s->D, 0, 3); ROUND3(s->D,s->A,s->B,s->C, 8, 9); + ROUND3(s->C,s->D,s->A,s->B, 4, 11); ROUND3(s->B,s->C,s->D,s->A, 12, 15); + ROUND3(s->A,s->B,s->C,s->D, 2, 3); ROUND3(s->D,s->A,s->B,s->C, 10, 9); + ROUND3(s->C,s->D,s->A,s->B, 6, 11); ROUND3(s->B,s->C,s->D,s->A, 14, 15); + ROUND3(s->A,s->B,s->C,s->D, 1, 3); ROUND3(s->D,s->A,s->B,s->C, 9, 9); + ROUND3(s->C,s->D,s->A,s->B, 5, 11); ROUND3(s->B,s->C,s->D,s->A, 13, 15); + ROUND3(s->A,s->B,s->C,s->D, 3, 3); ROUND3(s->D,s->A,s->B,s->C, 11, 9); + ROUND3(s->C,s->D,s->A,s->B, 7, 11); ROUND3(s->B,s->C,s->D,s->A, 15, 15); + + s->A += AA; + s->B += BB; + s->C += CC; + s->D += DD; + + s->A &= 0xFFFFFFFF; + s->B &= 0xFFFFFFFF; + s->C &= 0xFFFFFFFF; + s->D &= 0xFFFFFFFF; + + for (j=0;j<16;j++) + X[j] = 0; +} + +static void copy64(uint32 *M, const unsigned char *in) +{ + int i; + + for (i=0;i<16;i++) + M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | + (in[i*4+1]<<8) | (in[i*4+0]<<0); +} + +static void copy4(unsigned char *out, uint32 x) +{ + out[0] = x&0xFF; + out[1] = (x>>8)&0xFF; + out[2] = (x>>16)&0xFF; + out[3] = (x>>24)&0xFF; +} + +/* produce a md4 message digest from data of length n bytes */ +void mdfour(unsigned char *out, const unsigned char *in, int n) +{ + unsigned char buf[128]; + uint32 M[16]; + uint32 b = n * 8; + int i; + struct mdfour_state state; + + state.A = 0x67452301; + state.B = 0xefcdab89; + state.C = 0x98badcfe; + state.D = 0x10325476; + + while (n > 64) { + copy64(M, in); + mdfour64(&state, M); + in += 64; + n -= 64; + } + + for (i=0;i<128;i++) + buf[i] = 0; + memcpy(buf, in, n); + buf[n] = 0x80; + + if (n <= 55) { + copy4(buf+56, b); + copy64(M, buf); + mdfour64(&state, M); + } else { + copy4(buf+120, b); + copy64(M, buf); + mdfour64(&state, M); + copy64(M, buf+64); + mdfour64(&state, M); + } + + for (i=0;i<128;i++) + buf[i] = 0; + copy64(M, buf); + + copy4(out, state.A); + copy4(out+4, state.B); + copy4(out+8, state.C); + copy4(out+12, state.D); +} + + diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c new file mode 100644 index 0000000000..2121b17047 --- /dev/null +++ b/source4/lib/crypto/md5.c @@ -0,0 +1,247 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* This code slightly modified to fit into Samba by + abartlet@samba.org Jun 2001 */ + +#include "includes.h" + +#include "md5.h" + +static void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + register uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memmove(p, buf, len); + return; + } + memmove(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memmove(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memmove(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned int count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memmove(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c new file mode 100644 index 0000000000..8e7df52bef --- /dev/null +++ b/source4/lib/data_blob.c @@ -0,0 +1,141 @@ +/* + Unix SMB/CIFS implementation. + Easy management of byte-length data + Copyright (C) Andrew Tridgell 2001 + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/******************************************************************* + free() a data blob +*******************************************************************/ +static void free_data_blob(DATA_BLOB *d) +{ + if ((d) && (d->free)) { + SAFE_FREE(d->data); + } +} + +/******************************************************************* + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +*******************************************************************/ +DATA_BLOB data_blob(const void *p, size_t length) +{ + DATA_BLOB ret; + + if (!length) { + ZERO_STRUCT(ret); + return ret; + } + + if (p) { + ret.data = smb_xmemdup(p, length); + } else { + ret.data = smb_xmalloc(length); + } + ret.length = length; + ret.free = free_data_blob; + return ret; +} + +/******************************************************************* + construct a data blob, using supplied TALLOC_CTX +*******************************************************************/ +DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) +{ + DATA_BLOB ret; + + if (length == 0) { + ZERO_STRUCT(ret); + return ret; + } + + if (p == NULL) { + ret.data = talloc(mem_ctx, length); + if (ret.data == NULL) { + smb_panic("data_blob_talloc: talloc_memdup failed.\n"); + } + ret.length = length; + memset(ret.data, 0, ret.length); + return ret; + } + + ret.data = talloc_memdup(mem_ctx, p, length); + if (ret.data == NULL) { + smb_panic("data_blob_talloc: talloc_memdup failed.\n"); + } + + ret.length = length; + ret.free = NULL; + return ret; +} + +/******************************************************************* +free a data blob +*******************************************************************/ +void data_blob_free(DATA_BLOB *d) +{ + if (d) { + if (d->free) { + (d->free)(d); + } + d->length = 0; + } +} + +/******************************************************************* +clear a DATA_BLOB's contents +*******************************************************************/ +void data_blob_clear(DATA_BLOB *d) +{ + if (d->data) { + memset(d->data, 0, d->length); + } +} + +/******************************************************************* +free a data blob and clear its contents +*******************************************************************/ +void data_blob_clear_free(DATA_BLOB *d) +{ + data_blob_clear(d); + data_blob_free(d); +} + + +/******************************************************************* +check if two data blobs are equal +*******************************************************************/ +BOOL data_blob_equal(DATA_BLOB *d1, DATA_BLOB *d2) +{ + if (d1->length != d2->length) { + return False; + } + if (d1->data == d2->data) { + return True; + } + if (d1->data == NULL || d2->data == NULL) { + return False; + } + if (memcmp(d1->data, d2->data, d1->length) == 0) { + return True; + } + return False; +} + diff --git a/source4/lib/debug.c b/source4/lib/debug.c new file mode 100644 index 0000000000..37f93b9ae5 --- /dev/null +++ b/source4/lib/debug.c @@ -0,0 +1,157 @@ +/* + Unix SMB/CIFS implementation. + Samba debug functions + Copyright (C) Andrew Tridgell 2003 + Copyright (C) James J Myers 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* this global variable determines what messages are printed */ +int DEBUGLEVEL; + + +/* the registered mutex handlers */ +static struct { + const char *name; + struct debug_ops ops; +} debug_handlers; + +/* state variables for the debug system */ +static struct { + int fd; + enum debug_logtype logtype; + const char *prog_name; +} state; + +/* + the backend for debug messages. Note that the DEBUG() macro has already + ensured that the log level has been met before this is called +*/ +void do_debug(const char *format, ...) +{ + va_list ap; + char *s = NULL; + + if (state.fd == 0) { + reopen_logs(); + } + + if (state.fd <= 0) return; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + write(state.fd, s, strlen(s)); + free(s); +} + +/* + reopen the log file (usually called because the log file name might have changed) +*/ +void reopen_logs(void) +{ + char *logfile = lp_logfile(); + char *fname = NULL; + int old_fd = state.fd; + + state.fd = 0; + + switch (state.logtype) { + case DEBUG_STDOUT: + state.fd = 1; + break; + + case DEBUG_STDERR: + state.fd = 2; + break; + + case DEBUG_FILE: + if ((*logfile) == '/') { + fname = strdup(logfile); + } else { + asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, logfile); + } + if (fname) { + state.fd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0644); + free(fname); + } + break; + } + + if (old_fd > 2) { + close(old_fd); + } +} + +/* + control the name of the logfile and whether logging will be to stdout, stderr + or a file +*/ +void setup_logging(const char *prog_name, enum debug_logtype new_logtype) +{ + state.logtype = new_logtype; + state.prog_name = prog_name; + reopen_logs(); +} + +/* + return a string constant containing n tabs + no more than 10 tabs are returned +*/ +const char *do_debug_tab(uint_t n) +{ + const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", + "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", + "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"}; + return tabs[MIN(n, 10)]; +} + + +/* + log/print suspicious usage - print comments and backtrace +*/ +void log_suspicious_usage(const char *from, const char *info) +{ + if (debug_handlers.ops.log_suspicious_usage) { + return debug_handlers.ops.log_suspicious_usage(from, info); + } +} +void print_suspicious_usage(const char* from, const char* info) +{ + if (debug_handlers.ops.print_suspicious_usage) { + return debug_handlers.ops.print_suspicious_usage(from, info); + } +} + +uint32 get_task_id(void) +{ + if (debug_handlers.ops.get_task_id) { + return debug_handlers.ops.get_task_id(); + } + return getpid(); +} + +/* + register a set of debug handlers. +*/ +void register_debug_handlers(const char *name, struct debug_ops *ops) +{ + debug_handlers.name = name; + debug_handlers.ops = *ops; +} diff --git a/source4/lib/dmallocmsg.c b/source4/lib/dmallocmsg.c new file mode 100644 index 0000000000..a83ed518d7 --- /dev/null +++ b/source4/lib/dmallocmsg.c @@ -0,0 +1,72 @@ +/* + samba -- Unix SMB/CIFS implementation. + Copyright (C) 2002 by Martin Pool + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * @file dmallocmsg.c + * + * Glue code to cause dmalloc info to come out when we receive a prod + * over samba messaging. + **/ + +#ifdef ENABLE_DMALLOC +static unsigned long our_dm_mark = 0; +#endif /* ENABLE_DMALLOC */ + + +/** + * Respond to a POOL_USAGE message by sending back string form of memory + * usage stats. + **/ +static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid), + void *UNUSED(buf), size_t UNUSED(len)) +{ +#ifdef ENABLE_DMALLOC + our_dm_mark = dmalloc_mark(); + DEBUG(2,("Got MSG_REQ_DMALLOC_MARK: mark set\n")); +#else + DEBUG(2,("Got MSG_REQ_DMALLOC_MARK but dmalloc not in this process\n")); +#endif +} + + + +static void msg_req_dmalloc_log_changed(int UNUSED(msg_type), + pid_t UNUSED(src_pid), + void *UNUSED(buf), size_t UNUSED(len)) +{ +#ifdef ENABLE_DMALLOC + dmalloc_log_changed(our_dm_mark, True, True, True); + DEBUG(2,("Got MSG_REQ_DMALLOC_LOG_CHANGED: done\n")); +#else + DEBUG(2,("Got MSG_REQ_DMALLOC_LOG_CHANGED but dmalloc not in this process\n")); +#endif +} + + +/** + * Register handler for MSG_REQ_POOL_USAGE + **/ +void register_dmalloc_msgs(void) +{ + message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark); + message_register(MSG_REQ_DMALLOC_LOG_CHANGED, msg_req_dmalloc_log_changed); + DEBUG(2, ("Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED\n")); +} diff --git a/source4/lib/dprintf.c b/source4/lib/dprintf.c new file mode 100644 index 0000000000..70387bbd61 --- /dev/null +++ b/source4/lib/dprintf.c @@ -0,0 +1,113 @@ +/* + Unix SMB/CIFS implementation. + display print functions + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* + this module provides functions for printing internal strings in the "display charset" + This charset may be quite different from the chosen unix charset + + Eventually these functions will need to take care of column count constraints + + The d_ prefix on print functions in Samba refers to the display character set + conversion +*/ + +#include "includes.h" + + int d_vfprintf(FILE *f, const char *format, va_list ap) +{ + char *p, *p2; + int ret, maxlen, clen; + const char *msgstr; + va_list ap2; + + /* do any message translations */ + msgstr = lang_msg(format); + if (!msgstr) return -1; + + VA_COPY(ap2, ap); + + ret = vasprintf(&p, msgstr, ap2); + + lang_msg_free(msgstr); + + if (ret <= 0) return ret; + + /* now we have the string in unix format, convert it to the display + charset, but beware of it growing */ + maxlen = ret*2; +again: + p2 = malloc(maxlen); + if (!p2) { + SAFE_FREE(p); + return -1; + } + clen = convert_string(CH_UNIX, CH_DISPLAY, p, ret, p2, maxlen); + + if (clen >= maxlen) { + /* it didn't fit - try a larger buffer */ + maxlen *= 2; + SAFE_FREE(p2); + goto again; + } + + /* good, its converted OK */ + SAFE_FREE(p); + ret = fwrite(p2, 1, clen, f); + SAFE_FREE(p2); + + return ret; +} + + + int d_fprintf(FILE *f, const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = d_vfprintf(f, format, ap); + va_end(ap); + + return ret; +} + +static FILE *outfile; + + int d_printf(const char *format, ...) +{ + int ret; + va_list ap; + + if (!outfile) outfile = stdout; + + va_start(ap, format); + ret = d_vfprintf(outfile, format, ap); + va_end(ap); + + return ret; +} + +/* interactive programs need a way of tell d_*() to write to stderr instead + of stdout */ +void display_set_stderr(void) +{ + outfile = stderr; +} diff --git a/source4/lib/events.c b/source4/lib/events.c new file mode 100644 index 0000000000..f95028b731 --- /dev/null +++ b/source4/lib/events.c @@ -0,0 +1,372 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 4 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. When they are called the handler can choose to set the time + for the next event. If next_event is not set then the event is removed. + + 3) an event that happens every time through the select loop. These + sorts of events should be very fast, as they will occur a + lot. Mostly used for things like destroying a talloc context or + checking a signal flag. + + 4) an event triggered by a signal. These can be one shot or + repeated. You can have more than one handler registered for a + single signal if you want to. + + To setup a set of events you first need to create a event_context + structure using the function event_context_init(); This returns a + 'struct event_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using event_add_*() and event_remove_*(). + + Finally, you call event_loop_wait() to block waiting for one of the + events to occor. In normal operation event_loop_wait() will loop + forever, unless you call event_loop_exit() from inside one of your + handler functions. + +*/ + +#include "includes.h" + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct event_context *event_context_init(void) +{ + struct event_context *ev; + + ev = malloc(sizeof(*ev)); + if (!ev) return NULL; + + /* start off with no events */ + ZERO_STRUCTP(ev); + + return ev; +} + + + +/* + add a fd based event + return False on failure (memory allocation error) +*/ +BOOL event_add_fd(struct event_context *ev, struct fd_event *e) +{ + e = memdup(e, sizeof(*e)); + if (!e) return False; + DLIST_ADD(ev->fd_events, e); + e->ref_count = 1; + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + return True; +} + + +/* + recalculate the maxfd +*/ +static void calc_maxfd(struct event_context *ev) +{ + struct fd_event *e; + ev->maxfd = 0; + for (e=ev->fd_events; e; e=e->next) { + if (e->ref_count && + e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + } +} + +/* + remove a fd based event + the event to remove is matched by looking at the handler + function and the file descriptor + return False on failure (event not found) +*/ +BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1) +{ + struct fd_event *e; + for (e=ev->fd_events; e; e=e->next) { + if (e->ref_count && + e->fd == e1->fd && + e->handler == e1->handler) { + e->ref_count--; + /* possibly calculate the new maxfd */ + calc_maxfd(ev); + return True; + } + } + return False; +} + +/* + remove all fd based events that match a specified fd +*/ +void event_remove_fd_all(struct event_context *ev, int fd) +{ + struct fd_event *e; + for (e=ev->fd_events; e; e=e->next) { + if (e->ref_count && e->fd == fd) { + e->ref_count--; + } + } + calc_maxfd(ev); +} + +/* + remove all fd based events that match a specified handler +*/ +void event_remove_fd_all_handler(struct event_context *ev, void *handler) +{ + struct fd_event *e; + for (e=ev->fd_events; e; e=e->next) { + if (e->ref_count && + handler == (void *)e->handler) { + e->ref_count--; + } + } + calc_maxfd(ev); +} + + +/* + add a timed event + return False on failure (memory allocation error) +*/ +BOOL event_add_timed(struct event_context *ev, struct timed_event *e) +{ + e = memdup(e, sizeof(*e)); + if (!e) return False; + e->ref_count = 1; + DLIST_ADD(ev->timed_events, e); + return True; +} + +/* + remove a timed event + the event to remove is matched only on the handler function + return False on failure (event not found) +*/ +BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) +{ + struct timed_event *e; + for (e=ev->timed_events; e; e=e->next) { + if (e->ref_count && + e->handler == e1->handler) { + e->ref_count--; + return True; + } + } + return False; +} + +/* + add a loop event + return False on failure (memory allocation error) +*/ +BOOL event_add_loop(struct event_context *ev, struct loop_event *e) +{ + e = memdup(e, sizeof(*e)); + if (!e) return False; + e->ref_count = 1; + DLIST_ADD(ev->loop_events, e); + return True; +} + +/* + remove a loop event + the event to remove is matched only on the handler function + return False on failure (memory allocation error) +*/ +BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1) +{ + struct loop_event *e; + for (e=ev->loop_events; e; e=e->next) { + if (e->ref_count && + e->handler == e1->handler) { + e->ref_count--; + return True; + } + } + return False; +} + + +/* + tell the event loop to exit with the specified code +*/ +void event_loop_exit(struct event_context *ev, int code) +{ + ev->exit.exit_now = True; + ev->exit.code = code; +} + +/* + go into an event loop using the events defined in ev this function + will return with the specified code if one of the handlers calls + event_loop_exit() + + also return (with code 0) if all fd events are removed +*/ +int event_loop_wait(struct event_context *ev) +{ + time_t t; + + ZERO_STRUCT(ev->exit); + + t = time(NULL); + + while (ev->fd_events && !ev->exit.exit_now) { + fd_set r_fds, w_fds; + struct fd_event *fe; + struct loop_event *le; + struct timed_event *te; + int selrtn; + struct timeval tval; + + /* the loop events are called on each loop. Be careful to allow the + event to remove itself */ + for (le=ev->loop_events;le;) { + struct loop_event *next = le->next; + if (le->ref_count == 0) { + DLIST_REMOVE(ev->loop_events, le); + free(le); + } else { + le->ref_count++; + le->handler(ev, le, t); + le->ref_count--; + } + le = next; + } + + ZERO_STRUCT(tval); + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); + + /* setup any fd events */ + for (fe=ev->fd_events; fe; ) { + struct fd_event *next = fe->next; + if (fe->ref_count == 0) { + DLIST_REMOVE(ev->fd_events, fe); + free(fe); + } else { + if (fe->flags & EVENT_FD_READ) { + FD_SET(fe->fd, &r_fds); + } + if (fe->flags & EVENT_FD_WRITE) { + FD_SET(fe->fd, &w_fds); + } + } + fe = next; + } + + /* start with a reasonable max timeout */ + tval.tv_sec = 600; + + /* work out the right timeout for all timed events */ + for (te=ev->timed_events;te;te=te->next) { + int timeout = te->next_event - t; + if (timeout < 0) { + timeout = 0; + } + if (te->ref_count && + timeout < tval.tv_sec) { + tval.tv_sec = timeout; + } + } + + + selrtn = sys_select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + + t = time(NULL); + + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("EBADF on event_loop_wait - exiting\n")); + return -1; + } + + if (selrtn > 0) { + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16 flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (fe->ref_count && flags) { + fe->ref_count++; + fe->handler(ev, fe, t, flags); + fe->ref_count--; + } + } + } + + /* call any timed events that are now due */ + for (te=ev->timed_events;te;) { + struct timed_event *next = te->next; + if (te->ref_count == 0) { + DLIST_REMOVE(ev->timed_events, te); + free(te); + } else if (te->next_event <= t) { + te->ref_count++; + te->handler(ev, te, t); + te->ref_count--; + if (te->next_event <= t) { + /* the handler didn't set a time for the + next event - remove the event */ + event_remove_timed(ev, te); + } + } + te = next; + } + + } + + return ev->exit.code; +} diff --git a/source4/lib/fault.c b/source4/lib/fault.c new file mode 100644 index 0000000000..5a76ce2c0c --- /dev/null +++ b/source4/lib/fault.c @@ -0,0 +1,107 @@ +/* + Unix SMB/CIFS implementation. + Critical Fault handling + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static void (*cont_fn)(void *); + +/* the registered fault handler */ +static struct { + const char *name; + void (*fault_handler)(int sig); +} fault_handlers; + + +/******************************************************************* +report a fault +********************************************************************/ +static void fault_report(int sig) +{ + static int counter; + + if (counter) _exit(1); + + DEBUG(0,("===============================================================\n")); + DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION)); + DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); + DEBUG(0,("===============================================================\n")); + + smb_panic("internal error"); + + if (cont_fn) { + cont_fn(NULL); +#ifdef SIGSEGV + CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); +#endif + return; /* this should cause a core dump */ + } + exit(1); +} + +/**************************************************************************** +catch serious errors +****************************************************************************/ +static void sig_fault(int sig) +{ + if (fault_handlers.fault_handler) { + /* we have a fault handler, call it. It may not return. */ + fault_handlers.fault_handler(sig); + } + /* If it returns or doean't exist, use regular reporter */ + fault_report(sig); +} + +/******************************************************************* +setup our fault handlers +********************************************************************/ +void fault_setup(void (*fn)(void *)) +{ + cont_fn = fn; + +#ifdef SIGSEGV + CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); +#endif +} + +/* + register a fault handler. + Should only be called once in the execution of smbd. +*/ +BOOL register_fault_handler(const char *name, void (*fault_handler)(int sig)) +{ + if (fault_handlers.name != NULL) { + /* it's already registered! */ + DEBUG(2,("fault handler '%s' already registered - failed '%s'\n", + fault_handlers.name, name)); + return False; + } + + fault_handlers.name = name; + fault_handlers.fault_handler = fault_handler; + + DEBUG(2,("fault handler '%s' registered\n", name)); + return True; +} diff --git a/source4/lib/fsusage.c b/source4/lib/fsusage.c new file mode 100644 index 0000000000..bb7cff0645 --- /dev/null +++ b/source4/lib/fsusage.c @@ -0,0 +1,148 @@ +/* + Unix SMB/CIFS implementation. + functions to calculate the free disk space + Copyright (C) Andrew Tridgell 1998-2000 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/* Return the number of TOSIZE-byte blocks used by + BLOCKS FROMSIZE-byte blocks, rounding away from zero. +*/ +static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SMB_BIG_UINT tosize) +{ + if (fromsize == tosize) /* e.g., from 512 to 512 */ + return blocks; + else if (fromsize > tosize) /* e.g., from 2048 to 512 */ + return blocks * (fromsize / tosize); + else /* e.g., from 256 to 512 */ + return (blocks + 1) / (tosize / fromsize); +} + +/* this does all of the system specific guff to get the free disk space. + It is derived from code in the GNU fileutils package, but has been + considerably mangled for use here + + results are returned in *dfree and *dsize, in 512 byte units +*/ +int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ +#ifdef STAT_STATFS3_OSF1 +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) + struct statfs fsd; + + if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + return -1; +#endif /* STAT_STATFS3_OSF1 */ + +#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)1024, (SMB_BIG_UINT)512) + struct fs_data fsd; + + if (statfs (path, &fsd) != 1) + return -1; + + (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); + (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); +#endif /* STAT_STATFS2_FS_DATA */ + +#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; + +#ifdef STATFS_TRUNCATES_BLOCK_COUNTS + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ +#endif /* STAT_STATFS2_BSIZE */ + + +#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ +#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) + + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#endif /* STAT_STATFS2_FSIZE */ + +#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ +# if _AIX || defined(_CRAY) +# define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) +# ifdef _CRAY +# define f_bavail f_bfree +# endif +# else +# define CONVERT_BLOCKS(B) ((SMB_BIG_UINT)B) +# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ +# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ +# define f_bavail f_bfree +# endif +# endif +# endif + + struct statfs fsd; + + if (statfs (path, &fsd, sizeof fsd, 0) < 0) + return -1; + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ + +#endif /* STAT_STATFS4 */ + +#if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ +# define CONVERT_BLOCKS(B) \ + adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) + +#ifdef STAT_STATVFS64 + struct statvfs64 fsd; + if (statvfs64(path, &fsd) < 0) return -1; +#else + struct statvfs fsd; + if (statvfs(path, &fsd) < 0) return -1; +#endif + + /* f_frsize isn't guaranteed to be supported. */ + +#endif /* STAT_STATVFS */ + +#ifndef CONVERT_BLOCKS + /* we don't have any dfree code! */ + return -1; +#else +#if !defined(STAT_STATFS2_FS_DATA) + /* !Ultrix */ + (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); + (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); +#endif /* not STAT_STATFS2_FS_DATA */ +#endif + + return 0; +} diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c new file mode 100644 index 0000000000..f3740e3e12 --- /dev/null +++ b/source4/lib/gencache.c @@ -0,0 +1,372 @@ +/* + Unix SMB/CIFS implementation. + + Generic, persistent and shared between processes cache mechanism for use + by various parts of the Samba code + + Copyright (C) Rafal Szczesniak 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_TDB + +#define TIMEOUT_LEN 12 +#define CACHE_DATA_FMT "%12u/%s" + +static TDB_CONTEXT *cache; + +/** + * @file gencache.c + * @brief Generic, persistent and shared between processes cache mechanism + * for use by various parts of the Samba code + * + **/ + + +/** + * Cache initialisation function. Opens cache tdb file or creates + * it if does not exist. + * + * @return true on successful initialisation of the cache or + * false on failure + **/ + +BOOL gencache_init(void) +{ + char* cache_fname = NULL; + + /* skip file open if it's already opened */ + if (cache) return True; + + asprintf(&cache_fname, "%s/%s", lp_lockdir(), "gencache.tdb"); + if (cache_fname) + DEBUG(5, ("Opening cache file at %s\n", cache_fname)); + else { + DEBUG(0, ("Filename allocation failed.\n")); + return False; + } + + cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0644); + + SAFE_FREE(cache_fname); + if (!cache) { + DEBUG(5, ("Attempt to open gencache.tdb has failed.\n")); + return False; + } + return True; +} + + +/** + * Cache shutdown function. Closes opened cache tdb file. + * + * @return true on successful closing the cache or + * false on failure during cache shutdown + **/ + +BOOL gencache_shutdown(void) +{ + /* tdb_close routine returns -1 on error */ + if (!cache) return False; + DEBUG(5, ("Closing cache file\n")); + return tdb_close(cache) != -1; +} + + +/** + * 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 + **/ + +BOOL gencache_set(const char *keystr, const char *value, time_t timeout) +{ + int ret; + TDB_DATA keybuf, databuf; + char* valstr = NULL; + + /* fail completely if get null pointers passed */ + SMB_ASSERT(keystr && value); + + if (!gencache_init()) return False; + + asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value); + if (!valstr) + return False; + + keybuf.dptr = strdup(keystr); + keybuf.dsize = strlen(keystr)+1; + databuf.dptr = strdup(valstr); + databuf.dsize = strlen(valstr)+1; + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout \ + = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout), + (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); + + ret = tdb_store(cache, keybuf, databuf, 0); + SAFE_FREE(valstr); + SAFE_FREE(keybuf.dptr); + SAFE_FREE(databuf.dptr); + + return ret == 0; +} + + +/** + * Set existing entry to the cache file. + * + * @param keystr string that represents a key of this entry + * @param valstr text representation value being cached + * @param timeout time when the value is expired + * + * @retval true when entry is successfuly set + * @retval false on failure + **/ + +BOOL gencache_set_only(const char *keystr, const char *valstr, time_t timeout) +{ + int ret = -1; + TDB_DATA keybuf, databuf; + char *old_valstr, *datastr; + time_t old_timeout; + + /* fail completely if get null pointers passed */ + SMB_ASSERT(keystr && valstr); + + if (!gencache_init()) return False; + + /* + * Check whether entry exists in the cache + * Don't verify gencache_get exit code, since the entry may be expired + */ + gencache_get(keystr, &old_valstr, &old_timeout); + + if (!(old_valstr && old_timeout)) return False; + + DEBUG(10, ("Setting cache entry with key = %s; old value = %s and old timeout \ + = %s\n", keystr, old_valstr, ctime(&old_timeout))); + + asprintf(&datastr, CACHE_DATA_FMT, (int)timeout, valstr); + keybuf.dptr = strdup(keystr); + keybuf.dsize = strlen(keystr)+1; + databuf.dptr = strdup(datastr); + databuf.dsize = strlen(datastr)+1; + DEBUGADD(10, ("New value = %s, new timeout = %s (%d seconds %s)", valstr, + ctime(&timeout), (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + + ret = tdb_store(cache, keybuf, databuf, TDB_REPLACE); + + SAFE_FREE(datastr); + SAFE_FREE(old_valstr); + SAFE_FREE(keybuf.dptr); + SAFE_FREE(databuf.dptr); + + return ret == 0; +} + + +/** + * Delete one entry from the cache file. + * + * @param keystr string that represents a key of this entry + * + * @retval true upon successful deletion + * @retval false in case of failure + **/ + +BOOL gencache_del(const char *keystr) +{ + int ret; + TDB_DATA keybuf; + + /* fail completely if get null pointers passed */ + SMB_ASSERT(keystr); + + if (!gencache_init()) return False; + + keybuf.dptr = strdup(keystr); + keybuf.dsize = strlen(keystr)+1; + DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); + ret = tdb_delete(cache, keybuf); + + SAFE_FREE(keybuf.dptr); + return ret == 0; +} + + +/** + * 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 timeout pointer to a time_t that is filled with entry's + * timeout + * + * @retval true when entry is successfuly fetched + * @retval False for failure + **/ + +BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) +{ + TDB_DATA keybuf, databuf; + + /* fail completely if get null pointers passed */ + SMB_ASSERT(keystr); + + if (!gencache_init()) + return False; + + keybuf.dptr = strdup(keystr); + keybuf.dsize = strlen(keystr)+1; + databuf = tdb_fetch(cache, keybuf); + SAFE_FREE(keybuf.dptr); + + if (databuf.dptr && databuf.dsize > TIMEOUT_LEN) { + char* entry_buf = strndup(databuf.dptr, databuf.dsize); + char *v; + time_t t; + + v = (char*)malloc(sizeof(char) * + (databuf.dsize - TIMEOUT_LEN)); + + SAFE_FREE(databuf.dptr); + sscanf(entry_buf, CACHE_DATA_FMT, (int*)&t, v); + SAFE_FREE(entry_buf); + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s\n", t > time(NULL) ? "valid" : + "expired", keystr, v, ctime(&t))); + + if (valstr) + *valstr = v; + else + SAFE_FREE(v); + + if (timeout) + *timeout = t; + + return t > time(NULL); + + } else { + SAFE_FREE(databuf.dptr); + + if (valstr) + *valstr = NULL; + + if (timeout) + timeout = NULL; + + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", + keystr)); + + return False; + } +} + + +/** + * Iterate through all entries which key matches to specified pattern + * + * @param fn pointer to the function that will be supplied with each single + * matching cache entry (key, value and timeout) as an arguments + * @param data void pointer to an arbitrary data that is passed directly to the fn + * function on each call + * @param keystr_pattern pattern the existing entries' keys are matched to + * + **/ + +void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr), + void* data, const char* keystr_pattern) +{ + TDB_LIST_NODE *node, *first_node; + TDB_DATA databuf; + char *keystr = NULL, *valstr = NULL, *entry = NULL; + time_t timeout = 0; + + /* fail completely if get null pointers passed */ + SMB_ASSERT(fn && keystr_pattern); + + if (!gencache_init()) return; + + DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern)); + node = tdb_search_keys(cache, keystr_pattern); + first_node = node; + + while (node) { + /* ensure null termination of the key string */ + keystr = strndup(node->node_key.dptr, node->node_key.dsize); + + /* + * We don't use gencache_get function, because we need to iterate through + * all of the entries. Validity verification is up to fn routine. + */ + databuf = tdb_fetch(cache, node->node_key); + if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) { + SAFE_FREE(databuf.dptr); + SAFE_FREE(keystr); + node = node->next; + continue; + } + entry = strndup(databuf.dptr, databuf.dsize); + SAFE_FREE(databuf.dptr); + valstr = (char*)malloc(sizeof(char) * (databuf.dsize - TIMEOUT_LEN)); + sscanf(entry, CACHE_DATA_FMT, (int*)(&timeout), valstr); + + DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n", + keystr, valstr, ctime(&timeout))); + fn(keystr, valstr, timeout, data); + + SAFE_FREE(valstr); + SAFE_FREE(entry); + SAFE_FREE(keystr); + node = node->next; + } + + tdb_search_list_free(first_node); +} + +/******************************************************************** + lock a key +********************************************************************/ + +int gencache_lock_entry( const char *key ) +{ + return tdb_lock_bystring(cache, key, 0); +} + +/******************************************************************** + unlock a key +********************************************************************/ + +void gencache_unlock_entry( const char *key ) +{ + tdb_unlock_bystring(cache, key); + return; +} + + diff --git a/source4/lib/genparser.c b/source4/lib/genparser.c new file mode 100644 index 0000000000..39c455def4 --- /dev/null +++ b/source4/lib/genparser.c @@ -0,0 +1,786 @@ +/* + Copyright (C) Andrew Tridgell 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + automatic marshalling/unmarshalling system for C structures +*/ + +#include "includes.h" + +/* see if a range of memory is all zero. Used to prevent dumping of zero elements */ +static int all_zero(const char *ptr, unsigned size) +{ + int i; + if (!ptr) return 1; + for (i=0;i>4]; + p[2] = hexdig[c&0xF]; + p += 3; + } + } + + *p = 0; + + return ret; +} + +/* decode an escaped string from encode_bytes() into a buffer */ +static char *decode_bytes(TALLOC_CTX *mem_ctx, const char *s, unsigned *len) +{ + char *ret, *p; + unsigned i; + int slen = strlen(s) + 1; + + ret = talloc(mem_ctx, slen); /* worst case length */ + if (!ret) + return NULL; + memset(ret, 0, slen); + + if (*s == '{') s++; + + for (p=ret,i=0;s[i];i++) { + if (s[i] == '}') { + break; + } else if (s[i] == '\\') { + unsigned v; + if (sscanf(&s[i+1], "%02x", &v) != 1 || v > 255) { + return NULL; + } + *(unsigned char *)p = v; + p++; + i += 2; + } else { + *p++ = s[i]; + } + } + *p = 0; + + (*len) = (unsigned)(p - ret); + + return ret; +} + +/* the add*() functions deal with adding things to a struct + parse_string */ + +/* allocate more space if needed */ +static int addgen_alloc(TALLOC_CTX *mem_ctx, struct parse_string *p, int n) +{ + if (p->length + n <= p->allocated) return 0; + p->allocated = p->length + n + 200; + p->s = talloc_realloc(mem_ctx, p->s, p->allocated); + if (!p->s) { + errno = ENOMEM; + return -1; + } + return 0; +} + +/* add a character to the buffer */ +static int addchar(TALLOC_CTX *mem_ctx, struct parse_string *p, char c) +{ + if (addgen_alloc(mem_ctx, p, 2) != 0) { + return -1; + } + p->s[p->length++] = c; + p->s[p->length] = 0; + return 0; +} + +/* add a string to the buffer */ +int addstr(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *s) +{ + int len = strlen(s); + if (addgen_alloc(mem_ctx, p, len+1) != 0) { + return -1; + } + memcpy(p->s + p->length, s, len+1); + p->length += len; + return 0; +} + +/* add a string to the buffer with a tab prefix */ +static int addtabbed(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *s, unsigned indent) +{ + int len = strlen(s); + if (addgen_alloc(mem_ctx, p, indent+len+1) != 0) { + return -1; + } + while (indent--) { + p->s[p->length++] = '\t'; + } + memcpy(p->s + p->length, s, len+1); + p->length += len; + return 0; +} + +/* note! this can only be used for results up to 60 chars wide! */ +int addshort(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *fmt, ...) +{ + char buf[60]; + int n; + va_list ap; + va_start(ap, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (addgen_alloc(mem_ctx, p, n + 1) != 0) { + return -1; + } + if (n != 0) { + memcpy(p->s + p->length, buf, n); + } + p->length += n; + p->s[p->length] = 0; + return 0; +} + +/* + this is here to make it easier for people to write dump functions + for their own types + */ +int gen_addgen(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *fmt, ...) +{ + char *buf = NULL; + int n; + va_list ap; + va_start(ap, fmt); + n = vasprintf(&buf, fmt, ap); + va_end(ap); + if (addgen_alloc(mem_ctx, p, n + 1) != 0) { + if (buf) free(buf); + return -1; + } + if (n != 0) { + memcpy(p->s + p->length, buf, n); + } + p->length += n; + p->s[p->length] = 0; + if (buf) free(buf); + return 0; +} + +/* dump a enumerated type */ +int gen_dump_enum(TALLOC_CTX *mem_ctx, + const struct enum_struct *einfo, + struct parse_string *p, + const char *ptr, + unsigned indent) +{ + unsigned v = *(const unsigned *)ptr; + int i; + for (i=0;einfo[i].name;i++) { + if (v == einfo[i].value) { + addstr(mem_ctx, p, einfo[i].name); + return 0; + } + } + /* hmm, maybe we should just fail? */ + return gen_dump_unsigned(mem_ctx, p, ptr, indent); +} + +/* dump a single non-array element, hanlding struct and enum */ +static int gen_dump_one(TALLOC_CTX *mem_ctx, + struct parse_string *p, + const struct parse_struct *pinfo, + const char *ptr, + unsigned indent) +{ + if (pinfo->dump_fn == gen_dump_char && pinfo->ptr_count == 1) { + char *s = encode_bytes(mem_ctx, ptr, strlen(ptr)); + if (addchar(mem_ctx, p,'{') || + addstr(mem_ctx, p, s) || + addstr(mem_ctx, p, "}")) { + return -1; + } + return 0; + } + + return pinfo->dump_fn(mem_ctx, p, ptr, indent); +} + +/* handle dumping of an array of arbitrary type */ +static int gen_dump_array(TALLOC_CTX *mem_ctx, + struct parse_string *p, + const struct parse_struct *pinfo, + const char *ptr, + int array_len, + int indent) +{ + int i, count=0; + + /* special handling of fixed length strings */ + if (array_len != 0 && + pinfo->ptr_count == 0 && + pinfo->dump_fn == gen_dump_char) { + char *s = encode_bytes(mem_ctx, ptr, array_len); + if (!s) return -1; + if (addtabbed(mem_ctx, p, pinfo->name, indent) || + addstr(mem_ctx, p, " = {") || + addstr(mem_ctx, p, s) || + addstr(mem_ctx, p, "}\n")) { + return -1; + } + free(s); + return 0; + } + + for (i=0;isize; + + /* generic pointer dereference */ + if (pinfo->ptr_count) { + p2 = *(const char **)ptr; + size = sizeof(void *); + } + + if ((count || pinfo->ptr_count) && + !(pinfo->flags & FLAG_ALWAYS) && + all_zero(ptr, size)) { + ptr += size; + continue; + } + if (count == 0) { + if (addtabbed(mem_ctx, p, pinfo->name, indent) || + addshort(mem_ctx, p, " = %u:", i)) { + return -1; + } + } else { + if (addshort(mem_ctx, p, ", %u:", i) != 0) { + return -1; + } + } + if (gen_dump_one(mem_ctx, p, pinfo, p2, indent) != 0) { + return -1; + } + ptr += size; + count++; + } + if (count) { + return addstr(mem_ctx, p, "\n"); + } + return 0; +} + +/* find a variable by name in a loaded structure and return its value + as an integer. Used to support dynamic arrays */ +static int find_var(const struct parse_struct *pinfo, + const char *data, + const char *var) +{ + int i; + const char *ptr; + + /* this allows for constant lengths */ + if (isdigit(*var)) { + return atoi(var); + } + + for (i=0;pinfo[i].name;i++) { + if (strcmp(pinfo[i].name, var) == 0) break; + } + if (!pinfo[i].name) return -1; + + ptr = data + pinfo[i].offset; + + switch (pinfo[i].size) { + case sizeof(int): + return *(const int *)ptr; + case sizeof(char): + return *(const char *)ptr; + } + + return -1; +} + + +int gen_dump_struct(TALLOC_CTX *mem_ctx, + const struct parse_struct *pinfo, + struct parse_string *p, + const char *ptr, + unsigned indent) +{ + char *s = gen_dump(mem_ctx, pinfo, ptr, indent+1); + if (!s) return -1; + if (addstr(mem_ctx, p, "{\n") || + addstr(mem_ctx, p, s) || + addtabbed(mem_ctx, p, "}", indent)) { + return -1; + } + return 0; +} + +static int gen_dump_string(TALLOC_CTX *mem_ctx, + struct parse_string *p, + const struct parse_struct *pinfo, + const char *data, + unsigned indent) +{ + const char *ptr = *(const char **)data; + char *s = encode_bytes(mem_ctx, ptr, strlen(ptr)); + if (addtabbed(mem_ctx, p, pinfo->name, indent) || + addstr(mem_ctx, p, " = ") || + addchar(mem_ctx, p, '{') || + addstr(mem_ctx, p, s) || + addstr(mem_ctx, p, "}\n")) { + return -1; + } + return 0; +} + +/* + find the length of a nullterm array +*/ +static int len_nullterm(const char *ptr, int size, int array_len) +{ + int len; + + if (size == 1) { + len = strnlen(ptr, array_len); + } else { + for (len=0; len < array_len; len++) { + if (all_zero(ptr+len*size, size)) break; + } + } + + if (len == 0) len = 1; + + return len; +} + + +/* the generic dump routine. Scans the parse information for this structure + and processes it recursively */ +char *gen_dump(TALLOC_CTX *mem_ctx, + const struct parse_struct *pinfo, + const char *data, + unsigned indent) +{ + struct parse_string p; + int i; + + p.length = 0; + p.allocated = 0; + p.s = NULL; + + if (addstr(mem_ctx, &p, "") != 0) { + return NULL; + } + + for (i=0;pinfo[i].name;i++) { + const char *ptr = data + pinfo[i].offset; + unsigned size = pinfo[i].size; + + if (pinfo[i].ptr_count) { + size = sizeof(void *); + } + + /* special handling for array types */ + if (pinfo[i].array_len) { + unsigned len = pinfo[i].array_len; + if (pinfo[i].flags & FLAG_NULLTERM) { + len = len_nullterm(ptr, size, len); + } + if (gen_dump_array(mem_ctx, &p, &pinfo[i], ptr, + len, indent)) { + goto failed; + } + continue; + } + + /* and dynamically sized arrays */ + if (pinfo[i].dynamic_len) { + int len = find_var(pinfo, data, pinfo[i].dynamic_len); + struct parse_struct p2 = pinfo[i]; + if (len < 0) { + goto failed; + } + if (len > 0) { + if (pinfo[i].flags & FLAG_NULLTERM) { + len = len_nullterm(*(const char **)ptr, + pinfo[i].size, len); + } + p2.ptr_count--; + p2.dynamic_len = NULL; + if (gen_dump_array(mem_ctx, &p, &p2, + *(const char **)ptr, + len, indent) != 0) { + goto failed; + } + } + continue; + } + + /* don't dump zero elements */ + if (!(pinfo[i].flags & FLAG_ALWAYS) && all_zero(ptr, size)) continue; + + /* assume char* is a null terminated string */ + if (pinfo[i].size == 1 && pinfo[i].ptr_count == 1 && + pinfo[i].dump_fn == gen_dump_char) { + if (gen_dump_string(mem_ctx, &p, &pinfo[i], ptr, indent) != 0) { + goto failed; + } + continue; + } + + /* generic pointer dereference */ + if (pinfo[i].ptr_count) { + ptr = *(const char **)ptr; + } + + if (addtabbed(mem_ctx, &p, pinfo[i].name, indent) || + addstr(mem_ctx, &p, " = ") || + gen_dump_one(mem_ctx, &p, &pinfo[i], ptr, indent) || + addstr(mem_ctx, &p, "\n")) { + goto failed; + } + } + return p.s; + +failed: + return NULL; +} + +/* search for a character in a string, skipping over sections within + matching braces */ +static char *match_braces(char *s, char c) +{ + int depth = 0; + while (*s) { + switch (*s) { + case '}': + depth--; + break; + case '{': + depth++; + break; + } + if (depth == 0 && *s == c) { + return s; + } + s++; + } + return s; +} + +/* parse routine for enumerated types */ +int gen_parse_enum(TALLOC_CTX *mem_ctx, + const struct enum_struct *einfo, + char *ptr, + const char *str) +{ + unsigned v; + int i; + + if (isdigit(*str)) { + if (sscanf(str, "%u", &v) != 1) { + errno = EINVAL; + return -1; + } + *(unsigned *)ptr = v; + return 0; + } + + for (i=0;einfo[i].name;i++) { + if (strcmp(einfo[i].name, str) == 0) { + *(unsigned *)ptr = einfo[i].value; + return 0; + } + } + + /* unknown enum value?? */ + return -1; +} + + +/* parse all base types */ +static int gen_parse_base(TALLOC_CTX *mem_ctx, + const struct parse_struct *pinfo, + char *ptr, + const char *str) +{ + if (pinfo->parse_fn == gen_parse_char && pinfo->ptr_count==1) { + unsigned len; + char *s = decode_bytes(mem_ctx, str, &len); + if (!s) return -1; + *(char **)ptr = s; + return 0; + } + + if (pinfo->ptr_count) { + unsigned size = pinfo->ptr_count>1?sizeof(void *):pinfo->size; + struct parse_struct p2 = *pinfo; + *(void **)ptr = talloc(mem_ctx, size); + if (! *(void **)ptr) { + return -1; + } + memset(*(void **)ptr, 0, size); + ptr = *(char **)ptr; + p2.ptr_count--; + return gen_parse_base(mem_ctx, &p2, ptr, str); + } + + return pinfo->parse_fn(mem_ctx, ptr, str); +} + +/* parse a generic array */ +static int gen_parse_array(TALLOC_CTX *mem_ctx, + const struct parse_struct *pinfo, + char *ptr, + const char *str, + int array_len) +{ + char *p, *p2; + unsigned size = pinfo->size; + + /* special handling of fixed length strings */ + if (array_len != 0 && + pinfo->ptr_count == 0 && + pinfo->dump_fn == gen_dump_char) { + unsigned len = 0; + char *s = decode_bytes(mem_ctx, str, &len); + if (!s || (len > array_len)) return -1; + memset(ptr, 0, array_len); + memcpy(ptr, s, len); + return 0; + } + + if (pinfo->ptr_count) { + size = sizeof(void *); + } + + while (*str) { + unsigned idx; + int done; + + idx = atoi(str); + p = strchr(str,':'); + if (!p) break; + p++; + p2 = match_braces(p, ','); + done = (*p2 != ','); + *p2 = 0; + + if (*p == '{') { + p++; + p[strlen(p)-1] = 0; + } + + if (gen_parse_base(mem_ctx, pinfo, ptr + idx*size, p) != 0) { + return -1; + } + + if (done) break; + str = p2+1; + } + + return 0; +} + +/* parse one element, hanlding dynamic and static arrays */ +static int gen_parse_one(TALLOC_CTX *mem_ctx, + const struct parse_struct *pinfo, + const char *name, + char *data, + const char *str) +{ + int i; + for (i=0;pinfo[i].name;i++) { + if (strcmp(pinfo[i].name, name) == 0) { + break; + } + } + if (pinfo[i].name == NULL) { + return 0; + } + + if (pinfo[i].array_len) { + return gen_parse_array(mem_ctx, &pinfo[i], + data+pinfo[i].offset, + str, pinfo[i].array_len); + } + + if (pinfo[i].dynamic_len) { + int len = find_var(pinfo, data, pinfo[i].dynamic_len); + if (len < 0) { + errno = EINVAL; + return -1; + } + if (len > 0) { + struct parse_struct p2 = pinfo[i]; + char *ptr; + unsigned size = pinfo[i].ptr_count>1?sizeof(void*):pinfo[i].size; + ptr = talloc(mem_ctx, len*size); + if (!ptr) { + errno = ENOMEM; + return -1; + } + memset(ptr, 0, len*size); + *((char **)(data + pinfo[i].offset)) = ptr; + p2.ptr_count--; + p2.dynamic_len = NULL; + return gen_parse_array(mem_ctx, &p2, ptr, str, len); + } + return 0; + } + + return gen_parse_base(mem_ctx, &pinfo[i], data + pinfo[i].offset, str); +} + +int gen_parse_struct(TALLOC_CTX * mem_ctx, const struct parse_struct *pinfo, char *ptr, const char *str) +{ + return gen_parse(mem_ctx, pinfo, ptr, str); +} + +/* the main parse routine */ +int gen_parse(TALLOC_CTX *mem_ctx, const struct parse_struct *pinfo, char *data, const char *s) +{ + char *str, *s0; + + s0 = strdup(s); + str = s0; + + while (*str) { + char *p; + char *name; + char *value; + + /* skip leading whitespace */ + while (isspace(*str)) str++; + + p = strchr(str, '='); + if (!p) break; + value = p+1; + while (p > str && isspace(*(p-1))) { + p--; + } + + *p = 0; + name = str; + + while (isspace(*value)) value++; + + if (*value == '{') { + str = match_braces(value, '}'); + value++; + } else { + str = match_braces(value, '\n'); + } + + *str++ = 0; + + if (gen_parse_one(mem_ctx, pinfo, name, data, value) != 0) { + free(s0); + return -1; + } + } + + free(s0); + return 0; +} + + + +/* for convenience supply some standard dumpers and parsers here */ + +int gen_parse_char(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(unsigned char *)ptr = atoi(str); + return 0; +} + +int gen_parse_int(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(int *)ptr = atoi(str); + return 0; +} + +int gen_parse_unsigned(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(unsigned *)ptr = strtoul(str, NULL, 10); + return 0; +} + +int gen_parse_time_t(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(time_t *)ptr = strtoul(str, NULL, 10); + return 0; +} + +int gen_parse_double(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(double *)ptr = atof(str); + return 0; +} + +int gen_parse_float(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(float *)ptr = atof(str); + return 0; +} + +int gen_dump_char(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(unsigned char *)(ptr)); +} + +int gen_dump_int(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%d", *(int *)(ptr)); +} + +int gen_dump_unsigned(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(unsigned *)(ptr)); +} + +int gen_dump_time_t(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(time_t *)(ptr)); +} + +int gen_dump_double(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%lg", *(double *)(ptr)); +} + +int gen_dump_float(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%g", *(float *)(ptr)); +} diff --git a/source4/lib/genparser_samba.c b/source4/lib/genparser_samba.c new file mode 100644 index 0000000000..bece587747 --- /dev/null +++ b/source4/lib/genparser_samba.c @@ -0,0 +1,200 @@ +/* + Copyright (C) Andrew Tridgell 2002 + Copyright (C) Simo Sorce 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "genparser_samba.h" + +/* PARSE functions */ + +int gen_parse_uint8(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(uint8 *)ptr = atoi(str); + return 0; +} + +int gen_parse_uint16(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(uint16 *)ptr = atoi(str); + return 0; +} + +int gen_parse_uint32(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + *(uint32 *)ptr = strtoul(str, NULL, 10); + return 0; +} + +int gen_parse_NTTIME(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + if(sscanf(str, "%u,%u", &(((NTTIME *)(ptr))->high), &(((NTTIME *)(ptr))->low)) != 2) { + errno = EINVAL; + return -1; + } + return 0; +} + +int gen_parse_DOM_SID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + if(!string_to_sid((DOM_SID *)ptr, str)) return -1; + return 0; +} + +int gen_parse_SEC_ACCESS(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + ((SEC_ACCESS *)ptr)->mask = strtoul(str, NULL, 10); + return 0; +} + +int gen_parse_GUID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + int info[GUID_SIZE]; + int i; + char *sc; + char *p; + char *m; + + m = strdup(str); + if (!m) return -1; + sc = m; + + memset(info, 0, sizeof(info)); + for (i = 0; i < GUID_SIZE; i++) { + p = strchr(sc, ','); + if (p != NULL) p = '\0'; + info[i] = atoi(sc); + if (p != NULL) sc = p + 1; + } + free(m); + + for (i = 0; i < GUID_SIZE; i++) { + ((GUID *)ptr)->info[i] = info[i]; + } + + return 0; +} + +int gen_parse_SEC_ACE(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + return gen_parse_struct(mem_ctx, pinfo_security_ace_info, ptr, str); +} + +int gen_parse_SEC_ACL(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + return gen_parse_struct(mem_ctx, pinfo_security_acl_info, ptr, str); +} + +int gen_parse_SEC_DESC(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + return gen_parse_struct(mem_ctx, pinfo_security_descriptor_info, ptr, str); +} + +int gen_parse_LUID_ATTR(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + return gen_parse_struct(mem_ctx, pinfo_luid_attr_info, ptr, str); +} + +int gen_parse_LUID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) +{ + if(sscanf(str, "%u,%u", &(((LUID *)(ptr))->high), &(((LUID *)(ptr))->low)) != 2) { + errno = EINVAL; + return -1; + } + return 0; +} + + + +/* DUMP functions */ + +int gen_dump_uint8(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(uint8 *)(ptr)); +} + +int gen_dump_uint16(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(uint16 *)(ptr)); +} + +int gen_dump_uint32(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", *(uint32 *)(ptr)); +} + +int gen_dump_NTTIME(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + uint32 low, high; + + high = ((NTTIME *)(ptr))->high; + low = ((NTTIME *)(ptr))->low; + return addshort(mem_ctx, p, "%u,%u", high, low); +} + +int gen_dump_DOM_SID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + fstring sidstr; + + sid_to_string(sidstr, (DOM_SID *)ptr); + return addstr(mem_ctx, p, sidstr); +} + +int gen_dump_SEC_ACCESS(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return addshort(mem_ctx, p, "%u", ((SEC_ACCESS *)ptr)->mask); +} + +int gen_dump_GUID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + int i, r; + + for (i = 0; i < (GUID_SIZE - 1); i++) { + if (!(r = addshort(mem_ctx, p, "%d,", ((GUID *)ptr)->info[i]))) return r; + } + return addshort(mem_ctx, p, "%d", ((GUID *)ptr)->info[i]); +} + +int gen_dump_SEC_ACE(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return gen_dump_struct(mem_ctx, pinfo_security_ace_info, p, ptr, indent); +} + +int gen_dump_SEC_ACL(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return gen_dump_struct(mem_ctx, pinfo_security_acl_info, p, ptr, indent); +} + +int gen_dump_SEC_DESC(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return gen_dump_struct(mem_ctx, pinfo_security_descriptor_info, p, ptr, indent); +} + +int gen_dump_LUID_ATTR(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + return gen_dump_struct(mem_ctx, pinfo_luid_attr_info, p, ptr, indent); +} + +int gen_dump_LUID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) +{ + uint32 low, high; + + high = ((LUID *)(ptr))->high; + low = ((LUID *)(ptr))->low; + return addshort(mem_ctx, p, "%u,%u", high, low); +} + diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c new file mode 100644 index 0000000000..e2e66f7e58 --- /dev/null +++ b/source4/lib/genrand.c @@ -0,0 +1,267 @@ +/* + Unix SMB/CIFS implementation. + + Functions to create reasonable random numbers for crypto use. + + Copyright (C) Jeremy Allison 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static unsigned char hash[258]; +static uint32 counter; +static unsigned char *reseed_data; +static size_t reseed_data_size; + +/**************************************************************** + Copy any user given reseed data. +*****************************************************************/ + +void set_rand_reseed_data(unsigned char *data, size_t len) +{ + SAFE_FREE(reseed_data); + reseed_data_size = 0; + + reseed_data = (unsigned char *)memdup(data, len); + if (reseed_data) + reseed_data_size = len; +} + +/**************************************************************** + Setup the seed. +*****************************************************************/ + +static void seed_random_stream(unsigned char *seedval, size_t seedlen) +{ + unsigned char j = 0; + size_t ind; + + for (ind = 0; ind < 256; ind++) + hash[ind] = (unsigned char)ind; + + for( ind = 0; ind < 256; ind++) { + unsigned char tc; + + j += (hash[ind] + seedval[ind%seedlen]); + + tc = hash[ind]; + hash[ind] = hash[j]; + hash[j] = tc; + } + + hash[256] = 0; + hash[257] = 0; +} + +/**************************************************************** + Get datasize bytes worth of random data. +*****************************************************************/ + +static void get_random_stream(unsigned char *data, size_t datasize) +{ + unsigned char index_i = hash[256]; + unsigned char index_j = hash[257]; + size_t ind; + + for( ind = 0; ind < datasize; ind++) { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += hash[index_i]; + + tc = hash[index_i]; + hash[index_i] = hash[index_j]; + hash[index_j] = tc; + + t = hash[index_i] + hash[index_j]; + data[ind] = hash[t]; + } + + hash[256] = index_i; + hash[257] = index_j; +} + +/**************************************************************** + Get a 16 byte hash from the contents of a file. + Note that the hash is not initialised. +*****************************************************************/ + +static void do_filehash(const char *fname, unsigned char *the_hash) +{ + unsigned char buf[1011]; /* deliberate weird size */ + unsigned char tmp_md4[16]; + int fd, n; + + fd = sys_open(fname,O_RDONLY,0); + if (fd == -1) + return; + + while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) { + mdfour(tmp_md4, buf, n); + for (n=0;n<16;n++) + the_hash[n] ^= tmp_md4[n]; + } + close(fd); +} + +/************************************************************** + Try and get a good random number seed. Try a number of + different factors. Firstly, try /dev/urandom - use if exists. + + We use /dev/urandom as a read of /dev/random can block if + the entropy pool dries up. This leads clients to timeout + or be very slow on connect. + + If we can't use /dev/urandom then seed the stream random generator + above... +**************************************************************/ + +static int do_reseed(BOOL use_fd, int fd) +{ + unsigned char seed_inbuf[40]; + uint32 v1, v2; struct timeval tval; pid_t mypid; + struct passwd *pw; + + if (use_fd) { + if (fd != -1) + return fd; + + fd = sys_open( "/dev/urandom", O_RDONLY,0); + if(fd >= 0) + return fd; + } + + /* Add in some secret file contents */ + + do_filehash("/etc/shadow", &seed_inbuf[0]); + do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]); + + /* + * Add in the root encrypted password. + * On any system where security is taken + * seriously this will be secret. + */ + + pw = getpwnam_alloc("root"); + if (pw && pw->pw_passwd) { + size_t i; + unsigned char md4_tmp[16]; + mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd)); + for (i=0;i<16;i++) + seed_inbuf[8+i] ^= md4_tmp[i]; + passwd_free(&pw); + } + + /* + * Add the counter, time of day, and pid. + */ + + GetTimeOfDay(&tval); + mypid = getpid(); + v1 = (counter++) + mypid + tval.tv_sec; + v2 = (counter++) * mypid + tval.tv_usec; + + SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32)); + SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36)); + + /* + * Add any user-given reseed data. + */ + + if (reseed_data) { + size_t i; + for (i = 0; i < sizeof(seed_inbuf); i++) + seed_inbuf[i] ^= reseed_data[i % reseed_data_size]; + } + + seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); + + return -1; +} + +/******************************************************************* + Interface to the (hopefully) good crypto random number generator. +********************************************************************/ + +void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) +{ + static BOOL done_reseed = False; + static int urand_fd = -1; + unsigned char md4_buf[64]; + unsigned char tmp_buf[16]; + unsigned char *p; + + if(!done_reseed || do_reseed_now) { + urand_fd = do_reseed(True, urand_fd); + done_reseed = True; + } + + if (urand_fd != -1 && len > 0) { + + if (read(urand_fd, out, len) == len) + return; /* len bytes of random data read from urandom. */ + + /* Read of urand error, drop back to non urand method. */ + close(urand_fd); + urand_fd = -1; + do_reseed(False, -1); + done_reseed = True; + } + + /* + * Generate random numbers in chunks of 64 bytes, + * then md4 them & copy to the output buffer. + * This way the raw state of the stream is never externally + * seen. + */ + + p = out; + while(len > 0) { + int copy_len = len > 16 ? 16 : len; + + get_random_stream(md4_buf, sizeof(md4_buf)); + mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); + memcpy(p, tmp_buf, copy_len); + p += copy_len; + len -= copy_len; + } +} + +/******************************************************************* + Use the random number generator to generate a random string. +********************************************************************/ + +static char c_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; + +char *generate_random_str(size_t len) +{ + static unsigned char retstr[256]; + size_t i; + + memset(retstr, '\0', sizeof(retstr)); + + if (len > sizeof(retstr)-1) + len = sizeof(retstr) -1; + generate_random_buffer( retstr, len, False); + for (i = 0; i < len; i++) + retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ]; + + retstr[i] = '\0'; + + return (char *)retstr; +} diff --git a/source4/lib/getsmbpass.c b/source4/lib/getsmbpass.c new file mode 100644 index 0000000000..b6ae09b318 --- /dev/null +++ b/source4/lib/getsmbpass.c @@ -0,0 +1,156 @@ +/* Copyright (C) 1992-1998 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ + +#include "includes.h" + +#ifdef REPLACE_GETPASS + +#ifdef SYSV_TERMIO + +/* SYSTEM V TERMIO HANDLING */ + +static struct termio t; + +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +#ifndef TCSAFLUSH +#define TCSAFLUSH 1 +#endif + +#ifndef TCSANOW +#define TCSANOW 0 +#endif + +static int tcgetattr(int fd, struct termio *t) +{ + return ioctl(fd, TCGETA, t); +} + +static int tcsetattr(int fd, int flags, struct termio *t) +{ + if(flags & TCSAFLUSH) + ioctl(fd, TCFLSH, TCIOFLUSH); + return ioctl(fd, TCSETS, t); +} + +#elif !defined(TCSAFLUSH) + +/* BSD TERMIO HANDLING */ + +static struct sgttyb t; + +#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) +#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) + +#define TCSAFLUSH 1 +#define TCSANOW 0 + +static int tcgetattr(int fd, struct sgttyb *t) +{ + return ioctl(fd, TIOCGETP, (char *)t); +} + +static int tcsetattr(int fd, int flags, struct sgttyb *t) +{ + return ioctl(fd, TIOCSETP, (char *)t); +} + +#else /* POSIX TERMIO HANDLING */ +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +static struct termios t; +#endif /* SYSV_TERMIO */ + +char *getsmbpass(const char *prompt) +{ + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + if (ECHO_IS_ON(t)) + { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } + else + echo_off = 0; + } + else + echo_off = 0; + + /* Write the prompt. */ + fputs (prompt, out); + fflush (out); + + /* Read the password. */ + buf[0] = 0; + fgets(buf, bufsize, in); + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) + (void) tcsetattr (fileno (in), TCSANOW, &t); + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + return buf; +} + +#else + void getsmbpasswd_dummy(void); + void getsmbpasswd_dummy(void) {;} +#endif diff --git a/source4/lib/hmacmd5.c b/source4/lib/hmacmd5.c new file mode 100644 index 0000000000..f436fd30c0 --- /dev/null +++ b/source4/lib/hmacmd5.c @@ -0,0 +1,134 @@ +/* + Unix SMB/CIFS implementation. + HMAC MD5 code for use in NTLMv2 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Andrew Tridgell 1992-2000 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* taken direct from rfc2104 implementation and modified for suitable use + * for ntlmv2. + */ + +#include "includes.h" + +/*********************************************************************** + the rfc 2104 version of hmac_md5 initialisation. +***********************************************************************/ +void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) +{ + int i; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) + { + uchar tk[16]; + struct MD5Context tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* start out by storing key in pads */ + ZERO_STRUCT(ctx->k_ipad); + ZERO_STRUCT(ctx->k_opad); + memcpy( ctx->k_ipad, key, key_len); + memcpy( ctx->k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) + { + ctx->k_ipad[i] ^= 0x36; + ctx->k_opad[i] ^= 0x5c; + } + + MD5Init(&ctx->ctx); + MD5Update(&ctx->ctx, ctx->k_ipad, 64); +} + +/*********************************************************************** + the microsoft version of hmac_md5 initialisation. +***********************************************************************/ +void hmac_md5_init_limK_to_64(const uchar* key, int key_len, + HMACMD5Context *ctx) +{ + int i; + + /* if key is longer than 64 bytes truncate it */ + if (key_len > 64) + { + key_len = 64; + } + + /* start out by storing key in pads */ + ZERO_STRUCT(ctx->k_ipad); + ZERO_STRUCT(ctx->k_opad); + memcpy( ctx->k_ipad, key, key_len); + memcpy( ctx->k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + ctx->k_ipad[i] ^= 0x36; + ctx->k_opad[i] ^= 0x5c; + } + + MD5Init(&ctx->ctx); + MD5Update(&ctx->ctx, ctx->k_ipad, 64); +} + +/*********************************************************************** + update hmac_md5 "inner" buffer +***********************************************************************/ +void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) +{ + MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ +} + +/*********************************************************************** + finish off hmac_md5 "inner" buffer and generate outer one. +***********************************************************************/ +void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) + +{ + struct MD5Context ctx_o; + + MD5Final(digest, &ctx->ctx); + + MD5Init(&ctx_o); + MD5Update(&ctx_o, ctx->k_opad, 64); + MD5Update(&ctx_o, digest, 16); + MD5Final(digest, &ctx_o); +} + +/*********************************************************** + single function to calculate an HMAC MD5 digest from data. + use the microsoft hmacmd5 init method because the key is 16 bytes. +************************************************************/ +void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest) +{ + HMACMD5Context ctx; + hmac_md5_init_limK_to_64(key, 16, &ctx); + if (data_len != 0) + { + hmac_md5_update(data, data_len, &ctx); + } + hmac_md5_final(digest, &ctx); +} + diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c new file mode 100644 index 0000000000..8f85e29c2e --- /dev/null +++ b/source4/lib/iconv.c @@ -0,0 +1,526 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/** + * @file + * + * @brief Samba wrapper/stub for iconv character set conversion. + * + * iconv is the XPG2 interface for converting between character + * encodings. This file provides a Samba wrapper around it, and also + * a simple reimplementation that is used if the system does not + * implement iconv. + * + * Samba only works with encodings that are supersets of ASCII: ascii + * characters like whitespace can be tested for directly, multibyte + * sequences start with a byte with the high bit set, and strings are + * terminated by a nul byte. + * + * Note that the only function provided by iconv is conversion between + * characters. It doesn't directly support operations like + * uppercasing or comparison. We have to convert to UCS-2 and compare + * there. + * + * @sa Samba Developers Guide + **/ + +static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ascii_push(void *,const char **, size_t *, char **, size_t *); +static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *); +static size_t utf8_push(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *); + +static struct charset_functions builtin_functions[] = { + {"UCS-2LE", iconv_copy, iconv_copy}, + {"UTF8", utf8_pull, utf8_push}, + {"ASCII", ascii_pull, ascii_push}, + {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, + {NULL, NULL, NULL} +}; + +static struct charset_functions *charsets = NULL; + +BOOL smb_register_charset(struct charset_functions *funcs) +{ + struct charset_functions *c = charsets; + + DEBUG(5, ("Attempting to register new charset %s\n", funcs->name)); + /* Check whether we already have this charset... */ + while(c) { + if(!strcasecmp(c->name, funcs->name)){ + DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); + return False; + } + c = c->next; + } + + funcs->next = funcs->prev = NULL; + DEBUG(5, ("Registered charset %s\n", funcs->name)); + DLIST_ADD(charsets, funcs); + return True; +} + +static void lazy_initialize_iconv(void) +{ + static BOOL initialized = False; + int i; + + if (!initialized) { + initialized = True; + for(i = 0; builtin_functions[i].name; i++) + smb_register_charset(&builtin_functions[i]); + } +} + +#ifdef HAVE_NATIVE_ICONV +/* if there was an error then reset the internal state, + this ensures that we don't have a shift state remaining for + character sets like SJIS */ +static size_t sys_iconv(void *cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t ret = iconv((iconv_t)cd, + inbuf, inbytesleft, + outbuf, outbytesleft); + if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); + return ret; +} +#endif + +/** + * This is a simple portable iconv() implementaion. + * + * It only knows about a very small number of character sets - just + * enough that Samba works on systems that don't have iconv. + **/ +size_t smb_iconv(smb_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + char cvtbuf[2048]; + char *bufp = cvtbuf; + size_t bufsize; + + /* in many cases we can go direct */ + if (cd->direct) { + return cd->direct(cd->cd_direct, + inbuf, inbytesleft, outbuf, outbytesleft); + } + + + /* otherwise we have to do it chunks at a time */ + while (*inbytesleft > 0) { + bufp = cvtbuf; + bufsize = sizeof(cvtbuf); + + if (cd->pull(cd->cd_pull, + inbuf, inbytesleft, &bufp, &bufsize) == -1 + && errno != E2BIG) return -1; + + bufp = cvtbuf; + bufsize = sizeof(cvtbuf) - bufsize; + + if (cd->push(cd->cd_push, + &bufp, &bufsize, + outbuf, outbytesleft) == -1) return -1; + } + + return 0; +} + +/* + simple iconv_open() wrapper + */ +smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) +{ + smb_iconv_t ret; + struct charset_functions *from, *to; + + lazy_initialize_iconv(); + from = charsets; + to = charsets; + + ret = (smb_iconv_t)malloc(sizeof(*ret)); + if (!ret) { + errno = ENOMEM; + return (smb_iconv_t)-1; + } + memset(ret, 0, sizeof(*ret)); + + ret->from_name = strdup(fromcode); + ret->to_name = strdup(tocode); + + /* check for the simplest null conversion */ + if (strcmp(fromcode, tocode) == 0) { + ret->direct = iconv_copy; + return ret; + } + + while (from) { + if (strcasecmp(from->name, fromcode) == 0) break; + from = from->next; + } + + while (to) { + if (strcasecmp(to->name, tocode) == 0) break; + to = to->next; + } + +#ifdef HAVE_NATIVE_ICONV + if (!from) { + ret->pull = sys_iconv; + ret->cd_pull = iconv_open("UCS-2LE", fromcode); + if (ret->cd_pull == (iconv_t)-1) goto failed; + } + + if (!to) { + ret->push = sys_iconv; + ret->cd_push = iconv_open(tocode, "UCS-2LE"); + if (ret->cd_push == (iconv_t)-1) goto failed; + } +#else + if (!from || !to) { + goto failed; + } +#endif + + /* check for conversion to/from ucs2 */ + if (strcasecmp(fromcode, "UCS-2LE") == 0 && to) { + ret->direct = to->push; + return ret; + } + if (strcasecmp(tocode, "UCS-2LE") == 0 && from) { + ret->direct = from->pull; + return ret; + } + +#ifdef HAVE_NATIVE_ICONV + if (strcasecmp(fromcode, "UCS-2LE") == 0) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_push; + ret->cd_push = NULL; + return ret; + } + if (strcasecmp(tocode, "UCS-2LE") == 0) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_pull; + ret->cd_pull = NULL; + return ret; + } +#endif + + /* the general case has to go via a buffer */ + if (!ret->pull) ret->pull = from->pull; + if (!ret->push) ret->push = to->push; + return ret; + +failed: + SAFE_FREE(ret); + errno = EINVAL; + return (smb_iconv_t)-1; +} + +/* + simple iconv_close() wrapper +*/ +int smb_iconv_close (smb_iconv_t cd) +{ +#ifdef HAVE_NATIVE_ICONV + if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); + if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull); + if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); +#endif + + SAFE_FREE(cd->from_name); + SAFE_FREE(cd->to_name); + + memset(cd, 0, sizeof(*cd)); + SAFE_FREE(cd); + return 0; +} + + +/********************************************************************** + the following functions implement the builtin character sets in Samba + and also the "test" character sets that are designed to test + multi-byte character set support for english users +***********************************************************************/ +static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + (*outbuf)[0] = (*inbuf)[0] & 0x7F; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + + +static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + unsigned v; + + if ((*inbuf)[0] != '@') { + /* seven bit ascii case */ + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + continue; + } + /* it's a hex character */ + if (*inbytesleft < 5) { + errno = EINVAL; + return -1; + } + + if (sscanf(&(*inbuf)[1], "%04x", &v) != 1) { + errno = EILSEQ; + return -1; + } + + (*outbuf)[0] = v&0xff; + (*outbuf)[1] = v>>8; + (*inbytesleft) -= 5; + (*outbytesleft) -= 2; + (*inbuf) += 5; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + char buf[6]; + + if ((*inbuf)[1] == 0 && + ((*inbuf)[0] & 0x80) == 0 && + (*inbuf)[0] != '@') { + (*outbuf)[0] = (*inbuf)[0]; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + continue; + } + if (*outbytesleft < 5) { + errno = E2BIG; + return -1; + } + snprintf(buf, 6, "@%04x", SVAL(*inbuf, 0)); + memcpy(*outbuf, buf, 5); + (*inbytesleft) -= 2; + (*outbytesleft) -= 5; + (*inbuf) += 2; + (*outbuf) += 5; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return 0; +} + + +static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + memmove(*outbuf, *inbuf, n); + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + const unsigned char *c = (const unsigned char *)*inbuf; + unsigned char *uc = (unsigned char *)*outbuf; + int len = 1; + + if ((c[0] & 0x80) == 0) { + uc[0] = c[0]; + uc[1] = 0; + } else if ((c[0] & 0xf0) == 0xe0) { + if (*inbytesleft < 3) { + DEBUG(0,("short utf8 char\n")); + goto badseq; + } + uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); + uc[0] = (c[1]<<6) | (c[2]&0x3f); + len = 3; + } else if ((c[0] & 0xe0) == 0xc0) { + if (*inbytesleft < 2) { + DEBUG(0,("short utf8 char\n")); + goto badseq; + } + uc[1] = (c[0]>>2) & 0x7; + uc[0] = (c[0]<<6) | (c[1]&0x3f); + len = 2; + } + + (*inbuf) += len; + (*inbytesleft) -= len; + (*outbytesleft) -= 2; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; + +badseq: + errno = EINVAL; + return -1; +} + +static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + unsigned char *c = (unsigned char *)*outbuf; + const unsigned char *uc = (const unsigned char *)*inbuf; + int len=1; + + if (uc[1] & 0xf8) { + if (*outbytesleft < 3) { + DEBUG(0,("short utf8 write\n")); + goto toobig; + } + c[0] = 0xe0 | (uc[1]>>4); + c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6); + c[2] = 0x80 | (uc[0]&0x3f); + len = 3; + } else if (uc[1] | (uc[0] & 0x80)) { + if (*outbytesleft < 2) { + DEBUG(0,("short utf8 write\n")); + goto toobig; + } + c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6); + c[1] = 0x80 | (uc[0]&0x3f); + len = 2; + } else { + c[0] = uc[0]; + } + + + (*inbytesleft) -= 2; + (*outbytesleft) -= len; + (*inbuf) += 2; + (*outbuf) += len; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return 0; + +toobig: + errno = E2BIG; + return -1; +} + diff --git a/source4/lib/interface.c b/source4/lib/interface.c new file mode 100644 index 0000000000..2540c898ff --- /dev/null +++ b/source4/lib/interface.c @@ -0,0 +1,333 @@ +/* + Unix SMB/CIFS implementation. + multiple interface handling + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static struct iface_struct *probed_ifaces; +static int total_probed; + +static struct in_addr allones_ip; +struct in_addr loopback_ip; + +static struct interface *local_interfaces; + +#define ALLONES ((uint32)0xFFFFFFFF) +#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES)) +#define MKNETADDR(_IP, _NM) (_IP & _NM) + +/**************************************************************************** +Try and find an interface that matches an ip. If we cannot, return NULL + **************************************************************************/ +static struct interface *iface_find(struct in_addr ip, BOOL CheckMask) +{ + struct interface *i; + if (is_zero_ip(ip)) return local_interfaces; + + for (i=local_interfaces;i;i=i->next) + if (CheckMask) { + if (same_net(i->ip,ip,i->nmask)) return i; + } else if ((i->ip).s_addr == ip.s_addr) return i; + + return NULL; +} + + +/**************************************************************************** +add an interface to the linked list of interfaces +****************************************************************************/ +static void add_interface(struct in_addr ip, struct in_addr nmask) +{ + struct interface *iface; + if (iface_find(ip, False)) { + DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); + return; + } + + if (ip_equal(nmask, allones_ip)) { + DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); + return; + } + + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + ZERO_STRUCTPN(iface); + + iface->ip = ip; + iface->nmask = nmask; + iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); + + DLIST_ADD(local_interfaces, iface); + + DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip))); + DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); + DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); +} + + + +/**************************************************************************** +interpret a single element from a interfaces= config line + +This handles the following different forms: + +1) wildcard interface name +2) DNS name +3) IP/masklen +4) ip/mask +5) bcast/mask +****************************************************************************/ +static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) +{ + struct in_addr ip, nmask; + char *p; + int i, added=0; + + zero_ip(&ip); + zero_ip(&nmask); + + /* first check if it is an interface name */ + for (i=0;i 2) { + nmask = *interpret_addr2(mem_ctx, p); + } else { + nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); + } + + /* maybe the first component was a broadcast address */ + if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || + ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { + for (i=0;i 0) { + probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); + } + + /* if we don't have a interfaces line then use all broadcast capable + interfaces except loopback */ + if (!ptr || !*ptr || !**ptr) { + if (total_probed <= 0) { + DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); + exit(1); + } + for (i=0;i 0 )&& (n != total_probed || + memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) { + return True; + } + + return False; +} + + +/**************************************************************************** + check if an IP is one of mine + **************************************************************************/ +BOOL ismyip(struct in_addr ip) +{ + struct interface *i; + for (i=local_interfaces;i;i=i->next) + if (ip_equal(i->ip,ip)) return True; + return False; +} + +/**************************************************************************** + check if a packet is from a local (known) net + **************************************************************************/ +BOOL is_local_net(struct in_addr from) +{ + struct interface *i; + for (i=local_interfaces;i;i=i->next) { + if((from.s_addr & i->nmask.s_addr) == + (i->ip.s_addr & i->nmask.s_addr)) + return True; + } + return False; +} + +/**************************************************************************** + how many interfaces do we have + **************************************************************************/ +int iface_count(void) +{ + int ret = 0; + struct interface *i; + + for (i=local_interfaces;i;i=i->next) + ret++; + return ret; +} + +/**************************************************************************** + return IP of the Nth interface + **************************************************************************/ +struct in_addr *iface_n_ip(int n) +{ + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; + + if (i) return &i->ip; + return NULL; +} + +/**************************************************************************** + return bcast of the Nth interface + **************************************************************************/ +struct in_addr *iface_n_bcast(int n) +{ + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; + + if (i) return &i->bcast; + return NULL; +} + + +/* these 3 functions return the ip/bcast/nmask for the interface + most appropriate for the given ip address. If they can't find + an appropriate interface they return the requested field of the + first known interface. */ + +struct in_addr *iface_ip(struct in_addr ip) +{ + struct interface *i = iface_find(ip, True); + return(i ? &i->ip : &local_interfaces->ip); +} + +/* + return True if a IP is directly reachable on one of our interfaces +*/ +BOOL iface_local(struct in_addr ip) +{ + return iface_find(ip, True) ? True : False; +} diff --git a/source4/lib/interfaces.c b/source4/lib/interfaces.c new file mode 100644 index 0000000000..96f4b4cd94 --- /dev/null +++ b/source4/lib/interfaces.c @@ -0,0 +1,407 @@ +/* + Unix SMB/CIFS implementation. + return a list of network interfaces + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* working out the interfaces for a OS is an incredibly non-portable + thing. We have several possible implementations below, and autoconf + tries each of them to see what works + + Note that this file does _not_ include includes.h. That is so this code + can be called directly from the autoconf tests. That also means + this code cannot use any of the normal Samba debug stuff or defines. + This is standalone code. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AUTOCONF_TEST +struct iface_struct { + char name[16]; + struct in_addr ip; + struct in_addr netmask; +}; +#else +#include "config.h" +#include "interfaces.h" +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#if HAVE_IFACE_IFCONF + +/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 + V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. + + It probably also works on any BSD style system. */ + +/**************************************************************************** + get the netmask address for a local interface +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + struct ifconf ifc; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + int total = 0; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + n = ifc.ifc_len / sizeof(struct ifreq); + + /* Loop through interfaces, looking for given IP address */ + for (i=n-1;i>=0 && total < max_interfaces;i--) { + if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) { + continue; + } + + iname = ifr[i].ifr_name; + ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr; + + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) { + continue; + } + + if (!(ifr[i].ifr_flags & IFF_UP)) { + continue; + } + + if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) { + continue; + } + + nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + total++; + } + + close(fd); + + return total; +} + +#elif HAVE_IFACE_IFREQ + +#ifndef I_STR +#include +#endif + +/**************************************************************************** +this should cover most of the streams based systems +Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + struct ifreq ifreq; + struct strioctl strioctl; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + int total = 0; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = buff; + strioctl.ic_len = sizeof(buff); + if (ioctl(fd, I_STR, &strioctl) < 0) { + close(fd); + return -1; + } + + /* we can ignore the possible sizeof(int) here as the resulting + number of interface structures won't change */ + n = strioctl.ic_len / sizeof(struct ifreq); + + /* we will assume that the kernel returns the length as an int + at the start of the buffer if the offered size is a + multiple of the structure size plus an int */ + if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { + ifr = (struct ifreq *)(buff + sizeof(int)); + } else { + ifr = (struct ifreq *)buff; + } + + /* Loop through interfaces */ + + for (i = 0; isin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + + total++; + } + + close(fd); + + return total; +} + +#elif HAVE_IFACE_AIX + +/**************************************************************************** +this one is for AIX (tested on 4.2) +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + char buff[8192]; + int fd, i; + struct ifconf ifc; + struct ifreq *ifr=NULL; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + int total = 0; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + /* Loop through interfaces */ + i = ifc.ifc_len; + + while (i > 0 && total < max_interfaces) { + unsigned inc; + + inc = ifr->ifr_addr.sa_len; + + if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { + goto next; + } + + ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; + iname = ifr->ifr_name; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { + goto next; + } + + if (!(ifr->ifr_flags & IFF_UP)) { + goto next; + } + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + goto next; + } + + nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + + total++; + + next: + /* + * Patch from Archie Cobbs (archie@whistle.com). The + * addresses in the SIOCGIFCONF interface list have a + * minimum size. Usually this doesn't matter, but if + * your machine has tunnel interfaces, etc. that have + * a zero length "link address", this does matter. */ + + if (inc < sizeof(ifr->ifr_addr)) + inc = sizeof(ifr->ifr_addr); + inc += IFNAMSIZ; + + ifr = (struct ifreq*) (((char*) ifr) + inc); + i -= inc; + } + + + close(fd); + return total; +} + +#else /* a dummy version */ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + return -1; +} +#endif + + +static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) +{ + int r; + r = strcmp(i1->name, i2->name); + if (r) return r; + r = ntohl(i1->ip.s_addr) - ntohl(i2->ip.s_addr); + if (r) return r; + r = ntohl(i1->netmask.s_addr) - ntohl(i2->netmask.s_addr); + return r; +} + +/* this wrapper is used to remove duplicates from the interface list generated + above */ +int get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + int total, i, j; + + total = _get_interfaces(ifaces, max_interfaces); + if (total <= 0) return total; + + /* now we need to remove duplicates */ + qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CAST iface_comp); + + for (i=1;i, + Copyright (C) 2003 Andrew Bartlett + + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * Escape a parameter to an LDAP filter string, so they cannot contain + * embeded ( ) * or \ chars which may cause it not to parse correctly. + * + * @param s The input string + * + * @return A string allocated with malloc(), containing the escaped string, + * and to be free()ed by the caller. + **/ + +char *escape_ldap_string_alloc(const char *s) +{ + size_t len = strlen(s)+1; + char *output = malloc(len); + char *output_tmp; + const char *sub; + int i = 0; + char *p = output; + + while (*s) + { + switch (*s) + { + case '*': + sub = "\\2a"; + break; + case '(': + sub = "\\28"; + break; + case ')': + sub = "\\29"; + break; + case '\\': + sub = "\\5c"; + break; + default: + sub = NULL; + break; + } + + if (sub) { + len = len + 3; + output_tmp = realloc(output, len); + if (!output_tmp) { + SAFE_FREE(output); + return NULL; + } + output = output_tmp; + + p = &output[i]; + strncpy (p, sub, 3); + p += 3; + i += 3; + + } else { + *p = *s; + p++; + i++; + } + s++; + } + + *p = '\0'; + return output; +} diff --git a/source4/lib/md4.c b/source4/lib/md4.c new file mode 100644 index 0000000000..417e87bd8e --- /dev/null +++ b/source4/lib/md4.c @@ -0,0 +1,175 @@ +/* + Unix SMB/CIFS implementation. + a implementation of MD4 designed for use in the SMB authentication protocol + Copyright (C) Andrew Tridgell 1997-1998. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* NOTE: This code makes no attempt to be fast! + + It assumes that a int is at least 32 bits long +*/ + +struct mdfour_state { + uint32 A, B, C, D; +}; + +static uint32 F(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | ((~X)&Z); +} + +static uint32 G(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | (X&Z) | (Y&Z); +} + +static uint32 H(uint32 X, uint32 Y, uint32 Z) +{ + return X^Y^Z; +} + +static uint32 lshift(uint32 x, int s) +{ + x &= 0xFFFFFFFF; + return ((x<>(32-s)); +} + +#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64(struct mdfour_state *s, uint32 *M) +{ + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; + + for (j=0;j<16;j++) + X[j] = M[j]; + + AA = s->A; BB = s->B; CC = s->C; DD = s->D; + + ROUND1(s->A,s->B,s->C,s->D, 0, 3); ROUND1(s->D,s->A,s->B,s->C, 1, 7); + ROUND1(s->C,s->D,s->A,s->B, 2, 11); ROUND1(s->B,s->C,s->D,s->A, 3, 19); + ROUND1(s->A,s->B,s->C,s->D, 4, 3); ROUND1(s->D,s->A,s->B,s->C, 5, 7); + ROUND1(s->C,s->D,s->A,s->B, 6, 11); ROUND1(s->B,s->C,s->D,s->A, 7, 19); + ROUND1(s->A,s->B,s->C,s->D, 8, 3); ROUND1(s->D,s->A,s->B,s->C, 9, 7); + ROUND1(s->C,s->D,s->A,s->B, 10, 11); ROUND1(s->B,s->C,s->D,s->A, 11, 19); + ROUND1(s->A,s->B,s->C,s->D, 12, 3); ROUND1(s->D,s->A,s->B,s->C, 13, 7); + ROUND1(s->C,s->D,s->A,s->B, 14, 11); ROUND1(s->B,s->C,s->D,s->A, 15, 19); + + ROUND2(s->A,s->B,s->C,s->D, 0, 3); ROUND2(s->D,s->A,s->B,s->C, 4, 5); + ROUND2(s->C,s->D,s->A,s->B, 8, 9); ROUND2(s->B,s->C,s->D,s->A, 12, 13); + ROUND2(s->A,s->B,s->C,s->D, 1, 3); ROUND2(s->D,s->A,s->B,s->C, 5, 5); + ROUND2(s->C,s->D,s->A,s->B, 9, 9); ROUND2(s->B,s->C,s->D,s->A, 13, 13); + ROUND2(s->A,s->B,s->C,s->D, 2, 3); ROUND2(s->D,s->A,s->B,s->C, 6, 5); + ROUND2(s->C,s->D,s->A,s->B, 10, 9); ROUND2(s->B,s->C,s->D,s->A, 14, 13); + ROUND2(s->A,s->B,s->C,s->D, 3, 3); ROUND2(s->D,s->A,s->B,s->C, 7, 5); + ROUND2(s->C,s->D,s->A,s->B, 11, 9); ROUND2(s->B,s->C,s->D,s->A, 15, 13); + + ROUND3(s->A,s->B,s->C,s->D, 0, 3); ROUND3(s->D,s->A,s->B,s->C, 8, 9); + ROUND3(s->C,s->D,s->A,s->B, 4, 11); ROUND3(s->B,s->C,s->D,s->A, 12, 15); + ROUND3(s->A,s->B,s->C,s->D, 2, 3); ROUND3(s->D,s->A,s->B,s->C, 10, 9); + ROUND3(s->C,s->D,s->A,s->B, 6, 11); ROUND3(s->B,s->C,s->D,s->A, 14, 15); + ROUND3(s->A,s->B,s->C,s->D, 1, 3); ROUND3(s->D,s->A,s->B,s->C, 9, 9); + ROUND3(s->C,s->D,s->A,s->B, 5, 11); ROUND3(s->B,s->C,s->D,s->A, 13, 15); + ROUND3(s->A,s->B,s->C,s->D, 3, 3); ROUND3(s->D,s->A,s->B,s->C, 11, 9); + ROUND3(s->C,s->D,s->A,s->B, 7, 11); ROUND3(s->B,s->C,s->D,s->A, 15, 15); + + s->A += AA; + s->B += BB; + s->C += CC; + s->D += DD; + + s->A &= 0xFFFFFFFF; + s->B &= 0xFFFFFFFF; + s->C &= 0xFFFFFFFF; + s->D &= 0xFFFFFFFF; + + for (j=0;j<16;j++) + X[j] = 0; +} + +static void copy64(uint32 *M, const unsigned char *in) +{ + int i; + + for (i=0;i<16;i++) + M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | + (in[i*4+1]<<8) | (in[i*4+0]<<0); +} + +static void copy4(unsigned char *out, uint32 x) +{ + out[0] = x&0xFF; + out[1] = (x>>8)&0xFF; + out[2] = (x>>16)&0xFF; + out[3] = (x>>24)&0xFF; +} + +/* produce a md4 message digest from data of length n bytes */ +void mdfour(unsigned char *out, const unsigned char *in, int n) +{ + unsigned char buf[128]; + uint32 M[16]; + uint32 b = n * 8; + int i; + struct mdfour_state state; + + state.A = 0x67452301; + state.B = 0xefcdab89; + state.C = 0x98badcfe; + state.D = 0x10325476; + + while (n > 64) { + copy64(M, in); + mdfour64(&state, M); + in += 64; + n -= 64; + } + + for (i=0;i<128;i++) + buf[i] = 0; + memcpy(buf, in, n); + buf[n] = 0x80; + + if (n <= 55) { + copy4(buf+56, b); + copy64(M, buf); + mdfour64(&state, M); + } else { + copy4(buf+120, b); + copy64(M, buf); + mdfour64(&state, M); + copy64(M, buf+64); + mdfour64(&state, M); + } + + for (i=0;i<128;i++) + buf[i] = 0; + copy64(M, buf); + + copy4(out, state.A); + copy4(out+4, state.B); + copy4(out+8, state.C); + copy4(out+12, state.D); +} + + diff --git a/source4/lib/md5.c b/source4/lib/md5.c new file mode 100644 index 0000000000..2121b17047 --- /dev/null +++ b/source4/lib/md5.c @@ -0,0 +1,247 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* This code slightly modified to fit into Samba by + abartlet@samba.org Jun 2001 */ + +#include "includes.h" + +#include "md5.h" + +static void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + register uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memmove(p, buf, len); + return; + } + memmove(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memmove(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memmove(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned int count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memmove(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/source4/lib/messages.c b/source4/lib/messages.c new file mode 100644 index 0000000000..cb26b356bd --- /dev/null +++ b/source4/lib/messages.c @@ -0,0 +1,566 @@ +/* + Unix SMB/CIFS implementation. + Samba internal messaging functions + Copyright (C) Andrew Tridgell 2000 + Copyright (C) 2001 by Martin Pool + Copyright (C) 2002 by Jeremy Allison + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/** + @defgroup messages Internal messaging framework + @{ + @file messages.c + + @brief Module for internal messaging between Samba daemons. + + The idea is that if a part of Samba wants to do communication with + another Samba process then it will do a message_register() of a + dispatch function, and use message_send_pid() to send messages to + that process. + + The dispatch function is given the pid of the sender, and it can + use that to reply by message_send_pid(). See ping_message() for a + simple example. + + @caution Dispatch functions must be able to cope with incoming + messages on an *odd* byte boundary. + + This system doesn't have any inherent size limitations but is not + very efficient for large messages or when messages are sent in very + quick succession. + +*/ + +#include "includes.h" + +/* the locking database handle */ +static TDB_CONTEXT *tdb; +static int received_signal; + +/* change the message version with any incompatible changes in the protocol */ +#define MESSAGE_VERSION 1 + +struct message_rec { + int msg_version; + int msg_type; + pid_t dest; + pid_t src; + size_t len; +}; + +/* we have a linked list of dispatch handlers */ +static struct dispatch_fns { + struct dispatch_fns *next, *prev; + int msg_type; + void (*fn)(int msg_type, pid_t pid, void *buf, size_t len); +} *dispatch_fns; + +/**************************************************************************** + Notifications come in as signals. +****************************************************************************/ + +static void sig_usr1(void) +{ + received_signal = 1; + sys_select_signal(); +} + +/**************************************************************************** + A useful function for testing the message system. +****************************************************************************/ + +static void ping_message(int msg_type, pid_t src, void *buf, size_t len) +{ + const char *msg = buf ? buf : "none"; + DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(unsigned int)src, msg)); + message_send_pid(src, MSG_PONG, buf, len, True); +} + +/**************************************************************************** + Initialise the messaging functions. +****************************************************************************/ + +BOOL message_init(void) +{ + TALLOC_CTX *mem_ctx; + + if (tdb) return True; + + mem_ctx = talloc_init("message_init"); + if (!mem_ctx) { + DEBUG(0,("ERROR: No memory to initialise messages database\n")); + return False; + } + tdb = tdb_open_log(lock_path(mem_ctx, "messages.tdb"), + 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR|O_CREAT,0600); + talloc_destroy(mem_ctx); + + if (!tdb) { + DEBUG(0,("ERROR: Failed to initialise messages database\n")); + return False; + } + + CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1); + + message_register(MSG_PING, ping_message); + + return True; +} + +/******************************************************************* + Form a static tdb key from a pid. +******************************************************************/ + +static TDB_DATA message_key_pid(pid_t pid) +{ + static char key[20]; + TDB_DATA kbuf; + + slprintf(key, sizeof(key)-1, "PID/%d", (int)pid); + + kbuf.dptr = (char *)key; + kbuf.dsize = strlen(key)+1; + return kbuf; +} + +/**************************************************************************** + Notify a process that it has a message. If the process doesn't exist + then delete its record in the database. +****************************************************************************/ + +static BOOL message_notify(pid_t pid) +{ + /* + * Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. + */ + + SMB_ASSERT(pid > 0); + + if (kill(pid, SIGUSR1) == -1) { + if (errno == ESRCH) { + DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); + tdb_delete(tdb, message_key_pid(pid)); + } else { + DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); + } + return False; + } + return True; +} + +/**************************************************************************** + Send a message to a particular pid. +****************************************************************************/ + +static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, size_t len, + BOOL duplicates_allowed, unsigned int timeout) +{ + TDB_DATA kbuf; + TDB_DATA dbuf; + TDB_DATA old_dbuf; + struct message_rec rec; + char *ptr; + struct message_rec prec; + + /* + * Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. + */ + + SMB_ASSERT(pid > 0); + + rec.msg_version = MESSAGE_VERSION; + rec.msg_type = msg_type; + rec.dest = pid; + rec.src = getpid(); + rec.len = len; + + kbuf = message_key_pid(pid); + + dbuf.dptr = (void *)malloc(len + sizeof(rec)); + if (!dbuf.dptr) + return False; + + memcpy(dbuf.dptr, &rec, sizeof(rec)); + if (len > 0) + memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len); + + dbuf.dsize = len + sizeof(rec); + + if (duplicates_allowed) { + + /* If duplicates are allowed we can just append the message and return. */ + + /* lock the record for the destination */ + if (timeout) { + if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); + return False; + } + } else { + if (tdb_chainlock(tdb, kbuf) == -1) { + DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); + return False; + } + } + tdb_append(tdb, kbuf, dbuf); + tdb_chainunlock(tdb, kbuf); + + SAFE_FREE(dbuf.dptr); + errno = 0; /* paranoia */ + return message_notify(pid); + } + + /* lock the record for the destination */ + if (timeout) { + if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); + return False; + } + } else { + if (tdb_chainlock(tdb, kbuf) == -1) { + DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); + return False; + } + } + + old_dbuf = tdb_fetch(tdb, kbuf); + + if (!old_dbuf.dptr) { + /* its a new record */ + + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + tdb_chainunlock(tdb, kbuf); + + SAFE_FREE(dbuf.dptr); + errno = 0; /* paranoia */ + return message_notify(pid); + } + + /* Not a new record. Check for duplicates. */ + + for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) { + /* + * First check if the message header matches, then, if it's a non-zero + * sized message, check if the data matches. If so it's a duplicate and + * we can discard it. JRA. + */ + + if (!memcmp(ptr, &rec, sizeof(rec))) { + if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { + tdb_chainunlock(tdb, kbuf); + DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); + SAFE_FREE(dbuf.dptr); + SAFE_FREE(old_dbuf.dptr); + return True; + } + } + memcpy(&prec, ptr, sizeof(prec)); + ptr += sizeof(rec) + prec.len; + } + + /* we're adding to an existing entry */ + + tdb_append(tdb, kbuf, dbuf); + tdb_chainunlock(tdb, kbuf); + + SAFE_FREE(old_dbuf.dptr); + SAFE_FREE(dbuf.dptr); + + errno = 0; /* paranoia */ + return message_notify(pid); +} + +/**************************************************************************** + Send a message to a particular pid - no timeout. +****************************************************************************/ + +BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed) +{ + return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0); +} + +/**************************************************************************** + Send a message to a particular pid, with timeout in seconds. +****************************************************************************/ + +BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, size_t len, + BOOL duplicates_allowed, unsigned int timeout) +{ + return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout); +} + +/**************************************************************************** + Retrieve all messages for the current process. +****************************************************************************/ + +static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) +{ + TDB_DATA kbuf; + TDB_DATA dbuf; + TDB_DATA null_dbuf; + + ZERO_STRUCT(null_dbuf); + + *msgs_buf = NULL; + *total_len = 0; + + kbuf = message_key_pid(getpid()); + + tdb_chainlock(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + /* + * Replace with an empty record to keep the allocated + * space in the tdb. + */ + tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE); + tdb_chainunlock(tdb, kbuf); + + if (dbuf.dptr == NULL || dbuf.dsize == 0) { + SAFE_FREE(dbuf.dptr); + return False; + } + + *msgs_buf = dbuf.dptr; + *total_len = dbuf.dsize; + + return True; +} + +/**************************************************************************** + Parse out the next message for the current process. +****************************************************************************/ + +static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t *src, char **buf, size_t *len) +{ + struct message_rec rec; + char *ret_buf = *buf; + + *buf = NULL; + *len = 0; + + if (total_len - (ret_buf - msgs_buf) < sizeof(rec)) + return False; + + memcpy(&rec, ret_buf, sizeof(rec)); + ret_buf += sizeof(rec); + + if (rec.msg_version != MESSAGE_VERSION) { + DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION)); + return False; + } + + if (rec.len > 0) { + if (total_len - (ret_buf - msgs_buf) < rec.len) + return False; + } + + *len = rec.len; + *msg_type = rec.msg_type; + *src = rec.src; + *buf = ret_buf; + + return True; +} + +/**************************************************************************** + Receive and dispatch any messages pending for this process. + Notice that all dispatch handlers for a particular msg_type get called, + so you can register multiple handlers for a message. + *NOTE*: Dispatch functions must be able to cope with incoming + messages on an *odd* byte boundary. +****************************************************************************/ + +void message_dispatch(void) +{ + int msg_type; + pid_t src; + char *buf; + char *msgs_buf; + size_t len, total_len; + struct dispatch_fns *dfn; + int n_handled; + + if (!received_signal) + return; + + DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal)); + + received_signal = 0; + + if (!retrieve_all_messages(&msgs_buf, &total_len)) + return; + + for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { + DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n", + msg_type, (unsigned int) src)); + n_handled = 0; + for (dfn = dispatch_fns; dfn; dfn = dfn->next) { + if (dfn->msg_type == msg_type) { + DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type)); + dfn->fn(msg_type, src, len ? (void *)buf : NULL, len); + n_handled++; + } + } + if (!n_handled) { + DEBUG(5,("message_dispatch: warning: no handlers registed for " + "msg_type %d in pid %u\n", + msg_type, (unsigned int)getpid())); + } + } + SAFE_FREE(msgs_buf); +} + +/**************************************************************************** + Register a dispatch function for a particular message type. + *NOTE*: Dispatch functions must be able to cope with incoming + messages on an *odd* byte boundary. +****************************************************************************/ + +void message_register(int msg_type, + void (*fn)(int msg_type, pid_t pid, void *buf, size_t len)) +{ + struct dispatch_fns *dfn; + + dfn = (struct dispatch_fns *)malloc(sizeof(*dfn)); + + if (dfn != NULL) { + + ZERO_STRUCTPN(dfn); + + dfn->msg_type = msg_type; + dfn->fn = fn; + + DLIST_ADD(dispatch_fns, dfn); + } + else { + + DEBUG(0,("message_register: Not enough memory. malloc failed!\n")); + } +} + +/**************************************************************************** + De-register the function for a particular message type. +****************************************************************************/ + +void message_deregister(int msg_type) +{ + struct dispatch_fns *dfn, *next; + + for (dfn = dispatch_fns; dfn; dfn = next) { + next = dfn->next; + if (dfn->msg_type == msg_type) { + DLIST_REMOVE(dispatch_fns, dfn); + SAFE_FREE(dfn); + } + } +} + +struct msg_all { + int msg_type; + uint32 msg_flag; + const void *buf; + size_t len; + BOOL duplicates; + int n_sent; +}; + +/**************************************************************************** + Send one of the messages for the broadcast. +****************************************************************************/ + +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +{ + struct connections_data crec; + struct msg_all *msg_all = (struct msg_all *)state; + + if (dbuf.dsize != sizeof(crec)) + return 0; + + memcpy(&crec, dbuf.dptr, sizeof(crec)); + + if (crec.cnum != -1) + return 0; + + /* Don't send if the receiver hasn't registered an interest. */ + + if(!(crec.bcast_msg_flags & msg_all->msg_flag)) + return 0; + + /* If the msg send fails because the pid was not found (i.e. smbd died), + * the msg has already been deleted from the messages.tdb.*/ + + if (!message_send_pid(crec.pid, msg_all->msg_type, + msg_all->buf, msg_all->len, + msg_all->duplicates)) { + + /* If the pid was not found delete the entry from connections.tdb */ + + if (errno == ESRCH) { + DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", + (unsigned int)crec.pid, crec.cnum, crec.name)); + tdb_delete(the_tdb, kbuf); + } + } + msg_all->n_sent++; + return 0; +} + +/** + * Send a message to all smbd processes. + * + * It isn't very efficient, but should be OK for the sorts of + * applications that use it. When we need efficient broadcast we can add + * it. + * + * @param n_sent Set to the number of messages sent. This should be + * equal to the number of processes, but be careful for races. + * + * @retval True for success. + **/ +BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, + const void *buf, size_t len, + BOOL duplicates_allowed, + int *n_sent) +{ + struct msg_all msg_all; + + msg_all.msg_type = msg_type; + if (msg_type < 1000) + msg_all.msg_flag = FLAG_MSG_GENERAL; + else if (msg_type > 1000 && msg_type < 2000) + msg_all.msg_flag = FLAG_MSG_NMBD; + else if (msg_type > 2000 && msg_type < 3000) + msg_all.msg_flag = FLAG_MSG_PRINTING; + else if (msg_type > 3000 && msg_type < 4000) + msg_all.msg_flag = FLAG_MSG_SMBD; + else + return False; + + msg_all.buf = buf; + msg_all.len = len; + msg_all.duplicates = duplicates_allowed; + msg_all.n_sent = 0; + + tdb_traverse(conn_tdb, traverse_fn, &msg_all); + if (n_sent) + *n_sent = msg_all.n_sent; + return True; +} +/** @} **/ diff --git a/source4/lib/module.c b/source4/lib/module.c new file mode 100644 index 0000000000..152e893100 --- /dev/null +++ b/source4/lib/module.c @@ -0,0 +1,128 @@ +/* + Unix SMB/CIFS implementation. + module loading system + + Copyright (C) Jelmer Vernooij 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifdef HAVE_DLOPEN +int smb_load_module(const char *module_name) +{ + void *handle; + init_module_function *init; + int status; + const char *error; + + /* Always try to use LAZY symbol resolving; if the plugin has + * backwards compatibility, there might be symbols in the + * plugin referencing to old (removed) functions + */ + handle = sys_dlopen(module_name, RTLD_LAZY); + + if(!handle) { + DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); + return False; + } + + init = sys_dlsym(handle, "init_module"); + + /* we must check sys_dlerror() to determine if it worked, because + sys_dlsym() can validly return NULL */ + error = sys_dlerror(); + if (error) { + DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error)); + return False; + } + + status = init(); + + DEBUG(2, ("Module '%s' loaded\n", module_name)); + + return status; +} + +/* Load all modules in list and return number of + * modules that has been successfully loaded */ +int smb_load_modules(const char **modules) +{ + int i; + int success = 0; + + for(i = 0; modules[i]; i++){ + if(smb_load_module(modules[i])) { + success++; + } + } + + DEBUG(2, ("%d modules successfully loaded\n", success)); + + return success; +} + +int smb_probe_module(const char *subsystem, const char *module) +{ + char *full_path; + int rc; + TALLOC_CTX *mem_ctx; + + /* Check for absolute path */ + if(module[0] == '/')return smb_load_module(module); + + mem_ctx = talloc_init("smb_probe_module"); + if (!mem_ctx) { + DEBUG(0,("No memory for loading modules\n")); + return False; + } + full_path = talloc_strdup(mem_ctx, lib_path(mem_ctx, subsystem)); + full_path = talloc_asprintf(mem_ctx, "%s/%s.%s", + full_path, module, shlib_ext()); + + rc = smb_load_module(full_path); + talloc_destroy(mem_ctx); + return rc; +} + +#else /* HAVE_DLOPEN */ + +int smb_load_module(const char *module_name) +{ + DEBUG(0,("This samba executable has not been built with plugin support")); + return False; +} + +int smb_load_modules(const char **modules) +{ + DEBUG(0,("This samba executable has not been built with plugin support")); + return False; +} + +int smb_probe_module(const char *subsystem, const char *module) +{ + DEBUG(0,("This samba executable has not been built with plugin support, not probing")); + return False; +} + +#endif /* HAVE_DLOPEN */ + +void init_modules(void) +{ + if(lp_preload_modules()) + smb_load_modules(lp_preload_modules()); + /* FIXME: load static modules */ +} diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c new file mode 100644 index 0000000000..dd015a0ac8 --- /dev/null +++ b/source4/lib/ms_fnmatch.c @@ -0,0 +1,226 @@ +/* + Unix SMB/CIFS implementation. + filename matching routine + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + This module was originally based on fnmatch.c copyright by the Free + Software Foundation. It bears little resemblence to that code now +*/ + + +#if FNMATCH_TEST +#include +#include +#else +#include "includes.h" +#endif + +/* + bugger. we need a separate wildcard routine for older versions + of the protocol. This is not yet perfect, but its a lot + better than what we had */ +static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, + const smb_ucs2_t *string) +{ + const smb_ucs2_t *p = pattern, *n = string; + smb_ucs2_t c; + + if (strcmp_wa(p, "?")==0 && strcmp_wa(n, ".")) goto match; + + while ((c = *p++)) { + switch (c) { + case UCS2_CHAR('.'): + if (! *n) goto next; + if (*n != UCS2_CHAR('.')) goto nomatch; + n++; + break; + + case UCS2_CHAR('?'): + if (! *n) goto next; + if ((*n == UCS2_CHAR('.') && + n[1] != UCS2_CHAR('.')) || ! *n) + goto next; + n++; + break; + + case UCS2_CHAR('>'): + if (! *n) goto next; + if (n[0] == UCS2_CHAR('.')) { + if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + } + n++; + break; + + case UCS2_CHAR('*'): + if (! *n) goto next; + if (! *p) goto match; + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + } + break; + + case UCS2_CHAR('<'): + for (; *n; n++) { + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == UCS2_CHAR('.') && + !strchr_w(n+1,UCS2_CHAR('.'))) { + n++; + break; + } + } + break; + + case UCS2_CHAR('"'): + if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n != UCS2_CHAR('.')) goto nomatch; + n++; + break; + + default: + if (c != *n) goto nomatch; + n++; + } + } + + if (! *n) goto match; + + nomatch: + /* + if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return -1; + +next: + if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + goto nomatch; + + match: + /* + if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string); + */ + return 0; +} + +static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) +{ + if (!strpbrk_wa(pattern, "?*<>\"")) { + smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; + if (strcmp_wa(string,"..") == 0) string = s; + return strcasecmp_w(pattern, string); + } + + if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { + smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; + smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; + return ms_fnmatch_lanman_core(pattern, dotdot) && + ms_fnmatch_lanman_core(pattern, dot); + } + + return ms_fnmatch_lanman_core(pattern, string); +} + + +/* the following function was derived using the masktest utility - + after years of effort we finally have a perfect MS wildcard + matching routine! + + NOTE: this matches only filenames with no directory component + + Returns 0 on match, -1 on fail. +*/ +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, + enum protocol_types protocol) +{ + const smb_ucs2_t *p = pattern, *n = string; + smb_ucs2_t c; + + if (protocol <= PROTOCOL_LANMAN2) { + return ms_fnmatch_lanman1(pattern, string); + } + + while ((c = *p++)) { + switch (c) { + case UCS2_CHAR('?'): + if (! *n) return -1; + n++; + break; + + case UCS2_CHAR('>'): + if (n[0] == UCS2_CHAR('.')) { + if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + return -1; + } + if (! *n) return ms_fnmatch_w(p, n, protocol); + n++; + break; + + case UCS2_CHAR('*'): + for (; *n; n++) { + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + } + break; + + case UCS2_CHAR('<'): + for (; *n; n++) { + if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { + n++; + break; + } + } + break; + + case UCS2_CHAR('"'): + if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n != UCS2_CHAR('.')) return -1; + n++; + break; + + default: + if (c != *n) return -1; + n++; + } + } + + if (! *n) return 0; + + return -1; +} + + +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) +{ + wpstring p, s; + int ret; + + pstrcpy_wa(p, pattern); + pstrcpy_wa(s, string); + + ret = ms_fnmatch_w(p, s, protocol); +/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ + return ret; +} + +/* a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string) +{ + return ms_fnmatch(pattern, string, PROTOCOL_NT1); +} diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c new file mode 100644 index 0000000000..1be23a52ba --- /dev/null +++ b/source4/lib/mutex.c @@ -0,0 +1,142 @@ +/* + Unix SMB/CIFS implementation. + Samba mutex/lock functions + Copyright (C) Andrew Tridgell 2003 + Copyright (C) James J Myers 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "includes.h" + +static mutex_t mutex_list[MUTEX_MAX]; + +/* the registered mutex handlers */ +static struct { + const char *name; + struct mutex_ops ops; +} mutex_handlers; + +int mutex_lock_by_id(enum mutex_id id, const char *name) +{ + return mutex_lock(&mutex_list[id], name); +} + +int mutex_unlock_by_id(enum mutex_id id, const char *name) +{ + return mutex_unlock(&mutex_list[id], name); +} + +int mutex_init(mutex_t *mutex, const char *name) +{ + if (mutex_handlers.ops.mutex_init) { + return mutex_handlers.ops.mutex_init(mutex, name); + } + return 0; +} + +int mutex_destroy(mutex_t *mutex, const char *name) +{ + if (mutex_handlers.ops.mutex_destroy) { + return mutex_handlers.ops.mutex_destroy(mutex, name); + } + return 0; +} + +int mutex_lock(mutex_t *mutex, const char *name) +{ + if (mutex_handlers.ops.mutex_lock) { + return mutex_handlers.ops.mutex_lock(mutex, name); + } + return 0; +} + +int mutex_unlock(mutex_t *mutex, const char *name) +{ + if (mutex_handlers.ops.mutex_unlock) { + return mutex_handlers.ops.mutex_unlock(mutex, name); + } + return 0; +} + +/* read/write lock routines */ + +int rwlock_init(rwlock_t *rwlock, const char *name) +{ + if (mutex_handlers.ops.rwlock_init) { + return mutex_handlers.ops.rwlock_init(rwlock, name); + } + return 0; +} + +int rwlock_destroy(rwlock_t *rwlock, const char *name) +{ + if (mutex_handlers.ops.rwlock_destroy) { + return mutex_handlers.ops.rwlock_destroy(rwlock, name); + } + return 0; +} + +int rwlock_lock_write(rwlock_t *rwlock, const char *name) +{ + if (mutex_handlers.ops.rwlock_lock_write) { + return mutex_handlers.ops.rwlock_lock_write(rwlock, name); + } + return 0; +} + +int rwlock_lock_read(rwlock_t *rwlock, const char *name) +{ + if (mutex_handlers.ops.rwlock_lock_read) { + return mutex_handlers.ops.rwlock_lock_read(rwlock, name); + } + return 0; +} + +int rwlock_unlock(rwlock_t *rwlock, const char *name) +{ + if (mutex_handlers.ops.rwlock_unlock) { + return mutex_handlers.ops.rwlock_unlock(rwlock, name); + } + return 0; +} + + +/* + register a set of mutex/rwlock handlers. + Should only be called once in the execution of smbd. +*/ +BOOL register_mutex_handlers(const char *name, struct mutex_ops *ops) +{ + if (mutex_handlers.name != NULL) { + /* it's already registered! */ + DEBUG(2,("mutex handler '%s' already registered - failed '%s'\n", + mutex_handlers.name, name)); + return False; + } + + mutex_handlers.name = name; + mutex_handlers.ops = *ops; + + if (mutex_handlers.ops.mutex_init) { + enum mutex_id id; + for (id=0; id < MUTEX_MAX; id++) { + mutex_handlers.ops.mutex_init(&mutex_list[id], "mutex_list"); + } + } + + DEBUG(2,("mutex handler '%s' registered\n", name)); + return True; +} + diff --git a/source4/lib/pam_errors.c b/source4/lib/pam_errors.c new file mode 100644 index 0000000000..925441fb1d --- /dev/null +++ b/source4/lib/pam_errors.c @@ -0,0 +1,126 @@ +/* + * Unix SMB/CIFS implementation. + * PAM error mapping functions + * Copyright (C) Andrew Bartlett 2002 + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#ifdef WITH_PAM +#include + +#if defined(PAM_AUTHTOK_RECOVERY_ERR) && !defined(PAM_AUTHTOK_RECOVER_ERR) +#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR +#endif + +/* PAM -> NT_STATUS map */ +static const struct { + int pam_code; + NTSTATUS ntstatus; +} pam_to_nt_status_map[] = { + {PAM_OPEN_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_SYMBOL_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_SERVICE_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_SYSTEM_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_BUF_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_PERM_DENIED, NT_STATUS_ACCESS_DENIED}, + {PAM_AUTH_ERR, NT_STATUS_WRONG_PASSWORD}, + {PAM_CRED_INSUFFICIENT, NT_STATUS_INSUFFICIENT_LOGON_INFO}, /* FIXME: Is this correct? */ + {PAM_AUTHINFO_UNAVAIL, NT_STATUS_LOGON_FAILURE}, + {PAM_USER_UNKNOWN, NT_STATUS_NO_SUCH_USER}, + {PAM_MAXTRIES, NT_STATUS_REMOTE_SESSION_LIMIT}, /* FIXME: Is this correct? */ + {PAM_NEW_AUTHTOK_REQD, NT_STATUS_PASSWORD_MUST_CHANGE}, + {PAM_ACCT_EXPIRED, NT_STATUS_ACCOUNT_EXPIRED}, + {PAM_SESSION_ERR, NT_STATUS_INSUFFICIENT_RESOURCES}, + {PAM_CRED_UNAVAIL, NT_STATUS_NO_TOKEN}, /* FIXME: Is this correct? */ + {PAM_CRED_EXPIRED, NT_STATUS_PASSWORD_EXPIRED}, /* FIXME: Is this correct? */ + {PAM_CRED_ERR, NT_STATUS_UNSUCCESSFUL}, + {PAM_AUTHTOK_ERR, NT_STATUS_UNSUCCESSFUL}, +#ifdef PAM_AUTHTOK_RECOVER_ERR + {PAM_AUTHTOK_RECOVER_ERR, NT_STATUS_UNSUCCESSFUL}, +#endif + {PAM_AUTHTOK_EXPIRED, NT_STATUS_PASSWORD_EXPIRED}, + {PAM_SUCCESS, NT_STATUS_OK} +}; + +/* NT_STATUS -> PAM map */ +static const struct { + NTSTATUS ntstatus; + int pam_code; +} nt_status_to_pam_map[] = { + {NT_STATUS_UNSUCCESSFUL, PAM_SYSTEM_ERR}, + {NT_STATUS_NO_SUCH_USER, PAM_USER_UNKNOWN}, + {NT_STATUS_WRONG_PASSWORD, PAM_AUTH_ERR}, + {NT_STATUS_LOGON_FAILURE, PAM_AUTH_ERR}, + {NT_STATUS_ACCOUNT_EXPIRED, PAM_ACCT_EXPIRED}, + {NT_STATUS_PASSWORD_EXPIRED, PAM_AUTHTOK_EXPIRED}, + {NT_STATUS_PASSWORD_MUST_CHANGE, PAM_NEW_AUTHTOK_REQD}, + {NT_STATUS_OK, PAM_SUCCESS} +}; + +/***************************************************************************** +convert a PAM error to a NT status32 code + *****************************************************************************/ +NTSTATUS pam_to_nt_status(int pam_error) +{ + int i; + if (pam_error == 0) return NT_STATUS_OK; + + for (i=0; NT_STATUS_V(pam_to_nt_status_map[i].ntstatus); i++) { + if (pam_error == pam_to_nt_status_map[i].pam_code) + return pam_to_nt_status_map[i].ntstatus; + } + return NT_STATUS_UNSUCCESSFUL; +} + +/***************************************************************************** +convert an NT status32 code to a PAM error + *****************************************************************************/ +int nt_status_to_pam(NTSTATUS nt_status) +{ + int i; + if NT_STATUS_IS_OK(nt_status) return PAM_SUCCESS; + + for (i=0; NT_STATUS_V(nt_status_to_pam_map[i].ntstatus); i++) { + if (NT_STATUS_EQUAL(nt_status,nt_status_to_pam_map[i].ntstatus)) + return nt_status_to_pam_map[i].pam_code; + } + return PAM_SYSTEM_ERR; +} + +#else + +/***************************************************************************** +convert a PAM error to a NT status32 code + *****************************************************************************/ +NTSTATUS pam_to_nt_status(int pam_error) +{ + if (pam_error == 0) return NT_STATUS_OK; + return NT_STATUS_UNSUCCESSFUL; +} + +/***************************************************************************** +convert an NT status32 code to a PAM error + *****************************************************************************/ +int nt_status_to_pam(NTSTATUS nt_status) +{ + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OK)) return 0; + return 4; /* PAM_SYSTEM_ERR */ +} + +#endif + diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c new file mode 100644 index 0000000000..3471f27b8e --- /dev/null +++ b/source4/lib/pidfile.c @@ -0,0 +1,109 @@ +/* this code is broken - there is a race condition with the unlink (tridge) */ + +/* + Unix SMB/CIFS implementation. + pidfile handling + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK +#endif + +/* return the pid in a pidfile. return 0 if the process (or pidfile) + does not exist */ +pid_t pidfile_pid(const char *name) +{ + int fd; + char pidstr[20]; + unsigned ret; + pstring pidFile; + + slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); + + fd = sys_open(pidFile, O_NONBLOCK | O_RDONLY, 0644); + if (fd == -1) { + return 0; + } + + ZERO_ARRAY(pidstr); + + if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) { + goto noproc; + } + + ret = atoi(pidstr); + + if (!process_exists((pid_t)ret)) { + goto noproc; + } + + if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_RDLCK)) { + /* we could get the lock - it can't be a Samba process */ + goto noproc; + } + + close(fd); + return (pid_t)ret; + + noproc: + close(fd); + unlink(pidFile); + return 0; +} + +/* create a pid file in the pid directory. open it and leave it locked */ +void pidfile_create(const char *name) +{ + int fd; + char buf[20]; + pstring pidFile; + pid_t pid; + + slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); + + pid = pidfile_pid(name); + if (pid != 0) { + DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n", + name, pidFile, (int)pid)); + exit(1); + } + + fd = sys_open(pidFile, O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL, 0644); + if (fd == -1) { + DEBUG(0,("ERROR: can't open %s: Error was %s\n", pidFile, + strerror(errno))); + exit(1); + } + + if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_WRLCK)==False) { + DEBUG(0,("ERROR: %s : fcntl lock of file %s failed. Error was %s\n", + name, pidFile, strerror(errno))); + exit(1); + } + + memset(buf, 0, sizeof(buf)); + slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) getpid()); + if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) { + DEBUG(0,("ERROR: can't write to file %s: %s\n", + pidFile, strerror(errno))); + exit(1); + } + /* Leave pid file open & locked for the duration... */ +} diff --git a/source4/lib/popt/CHANGES b/source4/lib/popt/CHANGES new file mode 100644 index 0000000000..b6ab2aa308 --- /dev/null +++ b/source4/lib/popt/CHANGES @@ -0,0 +1,43 @@ +1.3 -> + - heavy dose of const's + - poptParseArgvString() now NULL terminates the list + +1.2.3 -> 1.3 + - added support for single - + - misc bug fixes + - portability improvements + +1.2.2 -> 1.2.3 + - fixed memset() in help message generation (Dale Hawkins) + - added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins) + - const'ified poptParseArgvString (Jeff Garzik) + +1.2.1 -> 1.2.2 + - fixed bug in chaind alias happens which seems to have only + affected --triggers in rpm + - added POPT_ARG_VAL + - popt.3 installed by default + +1.2 -> 1.2.1 + - added POPT_ARG_INTL_DOMAIN (Elliot Lee) + - updated Makefile's to be more GNUish (Elliot Lee) + +1.1 -> 1.2 + - added popt.3 man page (Robert Lynch) + - don't use mmap anymore (its lack of portability isn't worth the + trouble) + - added test script + - added support for exec + - removed support for *_POPT_ALIASES env variable -- it was a bad + idea + - reorganized into multiple source files + - added automatic help generation, POPT_AUTOHELP + - added table callbacks + - added table inclusion + - updated man page for new features + - added test scripts + +1.0 -> 1.1 + - moved to autoconf (Fred Fish) + - added STRERROR replacement (Norbert Warmuth) + - added const keywords (Bruce Perens) diff --git a/source4/lib/popt/COPYING b/source4/lib/popt/COPYING new file mode 100644 index 0000000000..b4c7ca876c --- /dev/null +++ b/source4/lib/popt/COPYING @@ -0,0 +1,22 @@ +Copyright (c) 1998 Red Hat Software + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. diff --git a/source4/lib/popt/README b/source4/lib/popt/README new file mode 100644 index 0000000000..7fccc836ff --- /dev/null +++ b/source4/lib/popt/README @@ -0,0 +1,18 @@ +This is the popt command line option parsing library. While it is similiar +to getopt(3), it contains a number of enhancements, including: + + 1) popt is fully reentrant + 2) popt can parse arbitrary argv[] style arrays while + getopt(2) makes this quite difficult + 3) popt allows users to alias command line arguments + 4) popt provides convience functions for parsting strings + into argv[] style arrays + +popt is used by rpm, the Red Hat install program, and many other Red Hat +utilities, all of which provide excellent examples of how to use popt. +Complete documentation on popt is available in popt.ps (included in this +tarball), which is excerpted with permission from the book "Linux +Application Development" by Michael K. Johnson and Erik Troan (availble +from Addison Wesley in May, 1998). + +Comments on popt should be addressed to ewt@redhat.com. diff --git a/source4/lib/popt/dummy.in b/source4/lib/popt/dummy.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/source4/lib/popt/findme.c b/source4/lib/popt/findme.c new file mode 100644 index 0000000000..f2ad05bb3f --- /dev/null +++ b/source4/lib/popt/findme.c @@ -0,0 +1,46 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#include "system.h" +#include "findme.h" + +const char * findProgramPath(const char * argv0) { + char * path = getenv("PATH"); + char * pathbuf; + char * start, * chptr; + char * buf, *local = NULL; + + /* If there is a / in the argv[0], it has to be an absolute + path */ + if (strchr(argv0, '/')) + return xstrdup(argv0); + + if (!path) return NULL; + + local = start = pathbuf = malloc(strlen(path) + 1); + buf = malloc(strlen(path) + strlen(argv0) + 2); + strcpy(pathbuf, path); + + chptr = NULL; + do { + if ((chptr = strchr(start, ':'))) + *chptr = '\0'; + sprintf(buf, "%s/%s", start, argv0); + + if (!access(buf, X_OK)) { + if (local) free(local); + return buf; + } + + if (chptr) + start = chptr + 1; + else + start = NULL; + } while (start && *start); + + free(buf); + if (local) free(local); + + return NULL; +} diff --git a/source4/lib/popt/findme.h b/source4/lib/popt/findme.h new file mode 100644 index 0000000000..5e93963d60 --- /dev/null +++ b/source4/lib/popt/findme.h @@ -0,0 +1,10 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#ifndef H_FINDME +#define H_FINDME + +const char * findProgramPath(const char * argv0); + +#endif diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c new file mode 100644 index 0000000000..9fa8650312 --- /dev/null +++ b/source4/lib/popt/popt.c @@ -0,0 +1,782 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#include "system.h" +#include "findme.h" +#include "poptint.h" + +#ifndef HAVE_STRERROR +static char * strerror(int errno) { + extern int sys_nerr; + extern char * sys_errlist[]; + + if ((0 <= errno) && (errno < sys_nerr)) + return sys_errlist[errno]; + else + return POPT_("unknown errno"); +} +#endif + +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) { + if (con->execPath) xfree(con->execPath); + con->execPath = xstrdup(path); + con->execAbsolute = allowAbsolute; +} + +static void invokeCallbacks(poptContext con, const struct poptOption * table, + int post) { + const struct poptOption * opt = table; + poptCallbackType cb; + + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + invokeCallbacks(con, opt->arg, post); + } else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) && + ((!post && (opt->argInfo & POPT_CBFLAG_PRE)) || + ( post && (opt->argInfo & POPT_CBFLAG_POST)))) { + cb = (poptCallbackType)opt->arg; + cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE, + NULL, NULL, opt->descrip); + } + opt++; + } +} + +poptContext poptGetContext(const char * name, int argc, const char ** argv, + const struct poptOption * options, int flags) { + poptContext con = malloc(sizeof(*con)); + + memset(con, 0, sizeof(*con)); + + con->os = con->optionStack; + con->os->argc = argc; + con->os->argv = argv; + con->os->argb = NULL; + + if (!(flags & POPT_CONTEXT_KEEP_FIRST)) + con->os->next = 1; /* skip argv[0] */ + + con->leftovers = calloc( (argc + 1), sizeof(char *) ); + con->options = options; + con->aliases = NULL; + con->numAliases = 0; + con->flags = flags; + con->execs = NULL; + con->numExecs = 0; + con->finalArgvAlloced = argc * 2; + con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) ); + con->execAbsolute = 1; + con->arg_strip = NULL; + + if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) + con->flags |= POPT_CONTEXT_POSIXMEHARDER; + + if (name) + con->appName = strcpy(malloc(strlen(name) + 1), name); + + invokeCallbacks(con, con->options, 0); + + return con; +} + +static void cleanOSE(struct optionStackEntry *os) +{ + if (os->nextArg) { + xfree(os->nextArg); + os->nextArg = NULL; + } + if (os->argv) { + xfree(os->argv); + os->argv = NULL; + } + if (os->argb) { + PBM_FREE(os->argb); + os->argb = NULL; + } +} + +void poptResetContext(poptContext con) { + int i; + + while (con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (con->os->argb) { + PBM_FREE(con->os->argb); + con->os->argb = NULL; + } + con->os->currAlias = NULL; + con->os->nextCharArg = NULL; + con->os->nextArg = NULL; + con->os->next = 1; /* skip argv[0] */ + + con->numLeftovers = 0; + con->nextLeftover = 0; + con->restLeftover = 0; + con->doExec = NULL; + + for (i = 0; i < con->finalArgvCount; i++) { + if (con->finalArgv[i]) { + xfree(con->finalArgv[i]); + con->finalArgv[i] = NULL; + } + } + + con->finalArgvCount = 0; + + if (con->arg_strip) { + PBM_FREE(con->arg_strip); + con->arg_strip = NULL; + } +} + +/* Only one of longName, shortName may be set at a time */ +static int handleExec(poptContext con, char * longName, char shortName) { + int i; + + i = con->numExecs - 1; + if (longName) { + while (i >= 0 && (!con->execs[i].longName || + strcmp(con->execs[i].longName, longName))) i--; + } else { + while (i >= 0 && + con->execs[i].shortName != shortName) i--; + } + + if (i < 0) return 0; + + if (con->flags & POPT_CONTEXT_NO_EXEC) + return 1; + + if (con->doExec == NULL) { + con->doExec = con->execs + i; + return 1; + } + + /* We already have an exec to do; remember this option for next + time 'round */ + if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + i = con->finalArgvCount++; + { char *s = malloc((longName ? strlen(longName) : 0) + 3); + if (longName) + sprintf(s, "--%s", longName); + else + sprintf(s, "-%c", shortName); + con->finalArgv[i] = s; + } + + return 1; +} + +/* Only one of longName, shortName may be set at a time */ +static int handleAlias(poptContext con, const char * longName, char shortName, + /*@keep@*/ const char * nextCharArg) { + int i; + + if (con->os->currAlias && con->os->currAlias->longName && longName && + !strcmp(con->os->currAlias->longName, longName)) + return 0; + if (con->os->currAlias && shortName && + shortName == con->os->currAlias->shortName) + return 0; + + i = con->numAliases - 1; + if (longName) { + while (i >= 0 && (!con->aliases[i].longName || + strcmp(con->aliases[i].longName, longName))) i--; + } else { + while (i >= 0 && + con->aliases[i].shortName != shortName) i--; + } + + if (i < 0) return 0; + + if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + if (nextCharArg && *nextCharArg) + con->os->nextCharArg = nextCharArg; + + con->os++; + con->os->next = 0; + con->os->stuffed = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = con->aliases + i; + poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, + &con->os->argc, &con->os->argv); + con->os->argb = NULL; + + return 1; +} + +static void execCommand(poptContext con) { + const char ** argv; + int pos = 0; + const char * script = con->doExec->script; + + argv = malloc(sizeof(*argv) * + (6 + con->numLeftovers + con->finalArgvCount)); + + if (!con->execAbsolute && strchr(script, '/')) return; + + if (!strchr(script, '/') && con->execPath) { + char *s = malloc(strlen(con->execPath) + strlen(script) + 2); + sprintf(s, "%s/%s", con->execPath, script); + argv[pos] = s; + } else { + argv[pos] = script; + } + pos++; + + argv[pos] = findProgramPath(con->os->argv[0]); + if (argv[pos]) pos++; + argv[pos++] = ";"; + + memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount); + pos += con->finalArgvCount; + + if (con->numLeftovers) { + argv[pos++] = "--"; + memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers); + pos += con->numLeftovers; + } + + argv[pos++] = NULL; + +#ifdef __hpux + setresuid(getuid(), getuid(),-1); +#else +/* + * XXX " ... on BSD systems setuid() should be preferred over setreuid()" + * XXX sez' Timur Bakeyev + * XXX from Norbert Warmuth + */ +#if defined(HAVE_SETUID) + setuid(getuid()); +#elif defined (HAVE_SETREUID) + setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */ +#else + ; /* Can't drop privileges */ +#endif +#endif + + execvp(argv[0], (char *const *)argv); +} + +/*@observer@*/ static const struct poptOption * +findOption(const struct poptOption * table, const char * longName, + char shortName, + /*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData, + int singleDash) +{ + const struct poptOption * opt = table; + const struct poptOption * opt2; + const struct poptOption * cb = NULL; + + /* This happens when a single - is given */ + if (singleDash && !shortName && !*longName) + shortName = '-'; + + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + opt2 = findOption(opt->arg, longName, shortName, callback, + callbackData, singleDash); + if (opt2) { + if (*callback && !*callbackData) + *callbackData = opt->descrip; + return opt2; + } + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { + cb = opt; + } else if (longName && opt->longName && + (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && + !strcmp(longName, opt->longName)) { + break; + } else if (shortName && shortName == opt->shortName) { + break; + } + opt++; + } + + if (!opt->longName && !opt->shortName) return NULL; + *callbackData = NULL; + *callback = NULL; + if (cb) { + *callback = (poptCallbackType)cb->arg; + if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) + *callbackData = cb->descrip; + } + + return opt; +} + +static const char *findNextArg(poptContext con, unsigned argx, int delete) +{ + struct optionStackEntry * os = con->os; + const char * arg; + + do { + int i; + arg = NULL; + while (os->next == os->argc && os > con->optionStack) os--; + if (os->next == os->argc && os == con->optionStack) break; + for (i = os->next; i < os->argc; i++) { + if (os->argb && PBM_ISSET(i, os->argb)) continue; + if (*os->argv[i] == '-') continue; + if (--argx > 0) continue; + arg = os->argv[i]; + if (delete) { + if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc); + PBM_SET(i, os->argb); + } + break; + } + if (os > con->optionStack) os--; + } while (arg == NULL); + return arg; +} + +static /*@only@*/ const char * expandNextArg(poptContext con, const char * s) +{ + const char *a; + size_t alen; + char *t, *te; + size_t tn = strlen(s) + 1; + char c; + + te = t = malloc(tn);; + while ((c = *s++) != '\0') { + switch (c) { +#if 0 /* XXX can't do this */ + case '\\': /* escape */ + c = *s++; + break; +#endif + case '!': + if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) + break; + if ((a = findNextArg(con, 1, 1)) == NULL) + break; + s += 3; + + alen = strlen(a); + tn += alen; + *te = '\0'; + t = realloc(t, tn); + te = t + strlen(t); + strncpy(te, a, alen); te += alen; + continue; + /*@notreached@*/ break; + default: + break; + } + *te++ = c; + } + *te = '\0'; + t = realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */ + return t; +} + +static void poptStripArg(poptContext con, int which) +{ + if(con->arg_strip == NULL) { + con->arg_strip = PBM_ALLOC(con->optionStack[0].argc); + } + PBM_SET(which, con->arg_strip); +} + +/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ +int poptGetNextOpt(poptContext con) +{ + const struct poptOption * opt = NULL; + int done = 0; + + /* looks a bit tricky to get rid of alloca properly in this fn */ +#if HAVE_ALLOCA_H +#define ALLOCA(x) alloca(x) +#else +#define ALLOCA(x) malloc(x) +#endif + + + while (!done) { + const char * origOptString = NULL; + poptCallbackType cb = NULL; + const void * cbData = NULL; + const char * longArg = NULL; + int canstrip = 0; + + while (!con->os->nextCharArg && con->os->next == con->os->argc + && con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (!con->os->nextCharArg && con->os->next == con->os->argc) { + invokeCallbacks(con, con->options, 1); + if (con->doExec) execCommand(con); + return -1; + } + + /* Process next long option */ + if (!con->os->nextCharArg) { + char * localOptString, * optString; + int thisopt; + + if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { + con->os->next++; + continue; + } + thisopt=con->os->next; + origOptString = con->os->argv[con->os->next++]; + + if (con->restLeftover || *origOptString != '-') { + con->leftovers[con->numLeftovers++] = origOptString; + if (con->flags & POPT_CONTEXT_POSIXMEHARDER) + con->restLeftover = 1; + continue; + } + + /* Make a copy we can hack at */ + localOptString = optString = + strcpy(ALLOCA(strlen(origOptString) + 1), + origOptString); + + if (!optString[0]) + return POPT_ERROR_BADOPT; + + if (optString[1] == '-' && !optString[2]) { + con->restLeftover = 1; + continue; + } else { + char *oe; + int singleDash; + + optString++; + if (*optString == '-') + singleDash = 0, optString++; + else + singleDash = 1; + + /* XXX aliases with arg substitution need "--alias=arg" */ + if (handleAlias(con, optString, '\0', NULL)) + continue; + if (handleExec(con, optString, '\0')) + continue; + + /* Check for "--long=arg" option. */ + for (oe = optString; *oe && *oe != '='; oe++) + ; + if (*oe == '=') { + *oe++ = '\0'; + /* XXX longArg is mapped back to persistent storage. */ + longArg = origOptString + (oe - localOptString); + } + + opt = findOption(con->options, optString, '\0', &cb, &cbData, + singleDash); + if (!opt && !singleDash) + return POPT_ERROR_BADOPT; + } + + if (!opt) { + con->os->nextCharArg = origOptString + 1; + } else { + if(con->os == con->optionStack && + opt->argInfo & POPT_ARGFLAG_STRIP) { + canstrip = 1; + poptStripArg(con, thisopt); + } + } + } + + /* Process next short option */ + if (con->os->nextCharArg) { + origOptString = con->os->nextCharArg; + + con->os->nextCharArg = NULL; + + if (handleAlias(con, NULL, *origOptString, + origOptString + 1)) { + origOptString++; + continue; + } + if (handleExec(con, NULL, *origOptString)) + continue; + + opt = findOption(con->options, NULL, *origOptString, &cb, + &cbData, 0); + if (!opt) + return POPT_ERROR_BADOPT; + + origOptString++; + if (*origOptString) + con->os->nextCharArg = origOptString; + } + + if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) { + *((int *)opt->arg) = 1; + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) { + if (opt->arg) + *((int *) opt->arg) = opt->val; + } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { + if (con->os->nextArg) { + xfree(con->os->nextArg); + con->os->nextArg = NULL; + } + if (longArg) { + con->os->nextArg = expandNextArg(con, longArg); + } else if (con->os->nextCharArg) { + con->os->nextArg = expandNextArg(con, con->os->nextCharArg); + con->os->nextCharArg = NULL; + } else { + while (con->os->next == con->os->argc && + con->os > con->optionStack) { + cleanOSE(con->os--); + } + if (con->os->next == con->os->argc) + return POPT_ERROR_NOARG; + + /* make sure this isn't part of a short arg or the + result of an alias expansion */ + if(con->os == con->optionStack && + opt->argInfo & POPT_ARGFLAG_STRIP && + canstrip) { + poptStripArg(con, con->os->next); + } + + con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]); + } + + if (opt->arg) { + long aLong; + char *end; + + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_STRING: + /* XXX memory leak, hard to plug */ + *((const char **) opt->arg) = xstrdup(con->os->nextArg); + break; + + case POPT_ARG_INT: + case POPT_ARG_LONG: + aLong = strtol(con->os->nextArg, &end, 0); + if (!(end && *end == '\0')) + return POPT_ERROR_BADNUMBER; + + if (aLong == LONG_MIN || aLong == LONG_MAX) + return POPT_ERROR_OVERFLOW; + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { + *((long *) opt->arg) = aLong; + } else { + if (aLong > INT_MAX || aLong < INT_MIN) + return POPT_ERROR_OVERFLOW; + *((int *) opt->arg) = aLong; + } + break; + + default: + fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"), + opt->argInfo & POPT_ARG_MASK); + exit(EXIT_FAILURE); + } + } + } + + if (cb) + cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData); + else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) + done = 1; + + if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { + con->finalArgvAlloced += 10; + con->finalArgv = realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); + if (opt->longName) + sprintf(s, "--%s", opt->longName); + else + sprintf(s, "-%c", opt->shortName); + con->finalArgv[con->finalArgvCount++] = s; + } + + if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE + && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) { + con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg); + } + } + + return opt->val; +} + +const char * poptGetOptArg(poptContext con) { + const char * ret = con->os->nextArg; + con->os->nextArg = NULL; + return ret; +} + +const char * poptGetArg(poptContext con) { + if (con->numLeftovers == con->nextLeftover) return NULL; + return con->leftovers[con->nextLeftover++]; +} + +const char * poptPeekArg(poptContext con) { + if (con->numLeftovers == con->nextLeftover) return NULL; + return con->leftovers[con->nextLeftover]; +} + +const char ** poptGetArgs(poptContext con) { + if (con->numLeftovers == con->nextLeftover) return NULL; + + /* some apps like [like RPM ;-) ] need this NULL terminated */ + con->leftovers[con->numLeftovers] = NULL; + + return (con->leftovers + con->nextLeftover); +} + +void poptFreeContext(poptContext con) { + int i; + + poptResetContext(con); + if (con->os->argb) free(con->os->argb); + + for (i = 0; i < con->numAliases; i++) { + if (con->aliases[i].longName) xfree(con->aliases[i].longName); + free(con->aliases[i].argv); + } + + for (i = 0; i < con->numExecs; i++) { + if (con->execs[i].longName) xfree(con->execs[i].longName); + xfree(con->execs[i].script); + } + if (con->execs) xfree(con->execs); + + free(con->leftovers); + free(con->finalArgv); + if (con->appName) xfree(con->appName); + if (con->aliases) free(con->aliases); + if (con->otherHelp) xfree(con->otherHelp); + if (con->execPath) xfree(con->execPath); + if (con->arg_strip) PBM_FREE(con->arg_strip); + + free(con); +} + +int poptAddAlias(poptContext con, struct poptAlias newAlias, + /*@unused@*/ int flags) +{ + int aliasNum = con->numAliases++; + struct poptAlias * alias; + + /* SunOS won't realloc(NULL, ...) */ + if (!con->aliases) + con->aliases = malloc(sizeof(newAlias) * con->numAliases); + else + con->aliases = realloc(con->aliases, + sizeof(newAlias) * con->numAliases); + alias = con->aliases + aliasNum; + + alias->longName = (newAlias.longName) + ? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName) + : NULL; + alias->shortName = newAlias.shortName; + alias->argc = newAlias.argc; + alias->argv = newAlias.argv; + + return 0; +} + +const char * poptBadOption(poptContext con, int flags) { + struct optionStackEntry * os; + + if (flags & POPT_BADOPTION_NOALIAS) + os = con->optionStack; + else + os = con->os; + + return os->argv[os->next - 1]; +} + +#define POPT_ERROR_NOARG -10 +#define POPT_ERROR_BADOPT -11 +#define POPT_ERROR_OPTSTOODEEP -13 +#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ +#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ + +const char *poptStrerror(const int error) { + switch (error) { + case POPT_ERROR_NOARG: + return POPT_("missing argument"); + case POPT_ERROR_BADOPT: + return POPT_("unknown option"); + case POPT_ERROR_OPTSTOODEEP: + return POPT_("aliases nested too deeply"); + case POPT_ERROR_BADQUOTE: + return POPT_("error in paramter quoting"); + case POPT_ERROR_BADNUMBER: + return POPT_("invalid numeric value"); + case POPT_ERROR_OVERFLOW: + return POPT_("number too large or too small"); + case POPT_ERROR_ERRNO: + return strerror(errno); + default: + return POPT_("unknown error"); + } +} + +int poptStuffArgs(poptContext con, const char ** argv) { + int argc; + + if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) + return POPT_ERROR_OPTSTOODEEP; + + for (argc = 0; argv[argc]; argc++) + ; + + con->os++; + con->os->next = 0; + con->os->nextArg = NULL; + con->os->nextCharArg = NULL; + con->os->currAlias = NULL; + poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); + con->os->argb = NULL; + con->os->stuffed = 1; + + return 0; +} + +const char * poptGetInvocationName(poptContext con) { + return con->os->argv[0]; +} + +int poptStrippedArgv(poptContext con, int argc, char **argv) +{ + int i,j=1, numargs=argc; + + for(i=1; iarg_strip)) { + numargs--; + } + } + + for(i=1; iarg_strip)) { + continue; + } else { + if(j /* for FILE * */ + +#define POPT_OPTION_DEPTH 10 + +#define POPT_ARG_NONE 0 +#define POPT_ARG_STRING 1 +#define POPT_ARG_INT 2 +#define POPT_ARG_LONG 3 +#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */ +#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be + set first in table; arg points + to callback, descrip points to + callback data to pass */ +#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain + for this table and any + included tables; arg points + to the domain string */ +#define POPT_ARG_VAL 7 /* arg should take value val */ +#define POPT_ARG_MASK 0x0000FFFF +#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */ +#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */ +#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */ +#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */ +#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */ +#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line, + not the subtable */ + +#define POPT_ERROR_NOARG -10 +#define POPT_ERROR_BADOPT -11 +#define POPT_ERROR_OPTSTOODEEP -13 +#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ +#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ +#define POPT_ERROR_BADNUMBER -17 +#define POPT_ERROR_OVERFLOW -18 + +/* poptBadOption() flags */ +#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */ + +/* poptGetContext() flags */ +#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */ +#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */ +#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */ + +struct poptOption { + /*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */ + char shortName; /* may be '\0' */ + int argInfo; + /*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */ + int val; /* 0 means don't return, just update flag */ + /*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */ + /*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */ +}; + +struct poptAlias { + /*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */ + char shortName; /* may be '\0' */ + int argc; + /*@owned@*/ const char ** argv; /* must be free()able */ +}; + +extern struct poptOption poptHelpOptions[]; +#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ + 0, "Help options", NULL }, + +typedef struct poptContext_s * poptContext; +#ifndef __cplusplus +typedef struct poptOption * poptOption; +#endif + +enum poptCallbackReason { POPT_CALLBACK_REASON_PRE, + POPT_CALLBACK_REASON_POST, + POPT_CALLBACK_REASON_OPTION }; +typedef void (*poptCallbackType)(poptContext con, + enum poptCallbackReason reason, + const struct poptOption * opt, + const char * arg, const void * data); + +/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name, + int argc, /*@keep@*/ const char ** argv, + /*@keep@*/ const struct poptOption * options, int flags); +void poptResetContext(poptContext con); + +/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ +int poptGetNextOpt(poptContext con); +/* returns NULL if no argument is available */ +/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con); +/* returns NULL if no more options are available */ +/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con); +/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con); +/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con); +/* returns the option which caused the most recent error */ +/*@observer@*/ const char * poptBadOption(poptContext con, int flags); +void poptFreeContext( /*@only@*/ poptContext con); +int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv); +int poptAddAlias(poptContext con, struct poptAlias alias, int flags); +int poptReadConfigFile(poptContext con, const char * fn); +/* like above, but reads /etc/popt and $HOME/.popt along with environment + vars */ +int poptReadDefaultConfig(poptContext con, int useEnv); +/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated + the same as " and both may include \ quotes */ +int poptDupArgv(int argc, const char **argv, + /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); +int poptParseArgvString(const char * s, + /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); +/*@observer@*/ const char *poptStrerror(const int error); +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute); +void poptPrintHelp(poptContext con, FILE * f, int flags); +void poptPrintUsage(poptContext con, FILE * f, int flags); +void poptSetOtherOptionHelp(poptContext con, const char * text); +/*@observer@*/ const char * poptGetInvocationName(poptContext con); +/* shuffles argv pointers to remove stripped args, returns new argc */ +int poptStrippedArgv(poptContext con, int argc, char **argv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source4/lib/popt/poptconfig.c b/source4/lib/popt/poptconfig.c new file mode 100644 index 0000000000..eb76941363 --- /dev/null +++ b/source4/lib/popt/poptconfig.c @@ -0,0 +1,142 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#include "system.h" +#include "poptint.h" + +static void configLine(poptContext con, char * line) { + int nameLength = strlen(con->appName); + char * opt; + struct poptAlias alias; + char * entryType; + char * longName = NULL; + char shortName = '\0'; + + if (strncmp(line, con->appName, nameLength)) return; + line += nameLength; + if (!*line || !isspace(*line)) return; + while (*line && isspace(*line)) line++; + entryType = line; + + while (!*line || !isspace(*line)) line++; + *line++ = '\0'; + while (*line && isspace(*line)) line++; + if (!*line) return; + opt = line; + + while (!*line || !isspace(*line)) line++; + *line++ = '\0'; + while (*line && isspace(*line)) line++; + if (!*line) return; + + if (opt[0] == '-' && opt[1] == '-') + longName = opt + 2; + else if (opt[0] == '-' && !opt[2]) + shortName = opt[1]; + + if (!strcmp(entryType, "alias")) { + if (poptParseArgvString(line, &alias.argc, &alias.argv)) return; + alias.longName = longName, alias.shortName = shortName; + poptAddAlias(con, alias, 0); + } else if (!strcmp(entryType, "exec")) { + con->execs = realloc(con->execs, + sizeof(*con->execs) * (con->numExecs + 1)); + if (longName) + con->execs[con->numExecs].longName = xstrdup(longName); + else + con->execs[con->numExecs].longName = NULL; + + con->execs[con->numExecs].shortName = shortName; + con->execs[con->numExecs].script = xstrdup(line); + + con->numExecs++; + } +} + +int poptReadConfigFile(poptContext con, const char * fn) { + char * file=NULL, * chptr, * end; + char * buf=NULL, * dst; + int fd, rc; + int fileLength; + + fd = open(fn, O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + return 0; + else + return POPT_ERROR_ERRNO; + } + + fileLength = lseek(fd, 0, SEEK_END); + (void) lseek(fd, 0, 0); + + file = malloc(fileLength + 1); + if (read(fd, file, fileLength) != fileLength) { + rc = errno; + close(fd); + errno = rc; + if (file) free(file); + return POPT_ERROR_ERRNO; + } + close(fd); + + dst = buf = malloc(fileLength + 1); + + chptr = file; + end = (file + fileLength); + while (chptr < end) { + switch (*chptr) { + case '\n': + *dst = '\0'; + dst = buf; + while (*dst && isspace(*dst)) dst++; + if (*dst && *dst != '#') { + configLine(con, dst); + } + chptr++; + break; + case '\\': + *dst++ = *chptr++; + if (chptr < end) { + if (*chptr == '\n') + dst--, chptr++; + /* \ at the end of a line does not insert a \n */ + else + *dst++ = *chptr++; + } + break; + default: + *dst++ = *chptr++; + break; + } + } + + free(file); + free(buf); + + return 0; +} + +int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { + char * fn, * home; + int rc; + + if (!con->appName) return 0; + + rc = poptReadConfigFile(con, "/etc/popt"); + if (rc) return rc; + if (getuid() != geteuid()) return 0; + + if ((home = getenv("HOME"))) { + fn = malloc(strlen(home) + 20); + strcpy(fn, home); + strcat(fn, "/.popt"); + rc = poptReadConfigFile(con, fn); + free(fn); + if (rc) return rc; + } + + return 0; +} + diff --git a/source4/lib/popt/popthelp.c b/source4/lib/popt/popthelp.c new file mode 100644 index 0000000000..6b790a63e7 --- /dev/null +++ b/source4/lib/popt/popthelp.c @@ -0,0 +1,301 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#include "system.h" +#include "poptint.h" + +static void displayArgs(poptContext con, + /*@unused@*/ enum poptCallbackReason foo, + struct poptOption * key, + /*@unused@*/ const char * arg, /*@unused@*/ void * data) { + if (key->shortName== '?') + poptPrintHelp(con, stdout, 0); + else + poptPrintUsage(con, stdout, 0); + exit(0); +} + +struct poptOption poptHelpOptions[] = { + { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, + { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, + { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, + { NULL, '\0', 0, NULL, 0, NULL, NULL } +} ; + + +/*@observer@*/ /*@null@*/ static const char * +getTableTranslationDomain(const struct poptOption *table) +{ + const struct poptOption *opt; + + for(opt = table; + opt->longName || opt->shortName || opt->arg; + opt++) { + if(opt->argInfo == POPT_ARG_INTL_DOMAIN) + return opt->arg; + } + + return NULL; +} + +/*@observer@*/ /*@null@*/ static const char * +getArgDescrip(const struct poptOption * opt, const char *translation_domain) +{ + if (!(opt->argInfo & POPT_ARG_MASK)) return NULL; + + if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2)) + if (opt->argDescrip) return POPT_(opt->argDescrip); + + if (opt->argDescrip) return D_(translation_domain, opt->argDescrip); + return POPT_("ARG"); +} + +static void singleOptionHelp(FILE * f, int maxLeftCol, + const struct poptOption * opt, + const char *translation_domain) { + int indentLength = maxLeftCol + 5; + int lineLength = 79 - indentLength; + const char * help = D_(translation_domain, opt->descrip); + int helpLength; + const char * ch; + char format[10]; + char * left; + const char * argDescrip = getArgDescrip(opt, translation_domain); + + left = malloc(maxLeftCol + 1); + *left = '\0'; + + if (opt->longName && opt->shortName) + sprintf(left, "-%c, --%s", opt->shortName, opt->longName); + else if (opt->shortName) + sprintf(left, "-%c", opt->shortName); + else if (opt->longName) + sprintf(left, "--%s", opt->longName); + if (!*left) return ; + if (argDescrip) { + strcat(left, "="); + strcat(left, argDescrip); + } + + if (help) + fprintf(f," %-*s ", maxLeftCol, left); + else { + fprintf(f," %s\n", left); + goto out; + } + + helpLength = strlen(help); + while (helpLength > lineLength) { + ch = help + lineLength - 1; + while (ch > help && !isspace(*ch)) ch--; + if (ch == help) break; /* give up */ + while (ch > (help + 1) && isspace(*ch)) ch--; + ch++; + + sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); + fprintf(f, format, help, " "); + help = ch; + while (isspace(*help) && *help) help++; + helpLength = strlen(help); + } + + if (helpLength) fprintf(f, "%s\n", help); + +out: + free(left); +} + +static int maxArgWidth(const struct poptOption * opt, + const char * translation_domain) { + int max = 0; + int this; + const char * s; + + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + this = maxArgWidth(opt->arg, translation_domain); + if (this > max) max = this; + } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + this = opt->shortName ? 2 : 0; + if (opt->longName) { + if (this) this += 2; + this += strlen(opt->longName) + 2; + } + + s = getArgDescrip(opt, translation_domain); + if (s) + this += strlen(s) + 1; + if (this > max) max = this; + } + + opt++; + } + + return max; +} + +static void singleTableHelp(FILE * f, const struct poptOption * table, + int left, + const char *translation_domain) { + const struct poptOption * opt; + const char *sub_transdom; + + opt = table; + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + singleOptionHelp(f, left, opt, translation_domain); + opt++; + } + + opt = table; + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + sub_transdom = getTableTranslationDomain(opt->arg); + if(!sub_transdom) + sub_transdom = translation_domain; + + if (opt->descrip) + fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip)); + + singleTableHelp(f, opt->arg, left, sub_transdom); + } + opt++; + } +} + +static int showHelpIntro(poptContext con, FILE * f) { + int len = 6; + const char * fn; + + fprintf(f, POPT_("Usage:")); + if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { + fn = con->optionStack->argv[0]; + if (strchr(fn, '/')) fn = strchr(fn, '/') + 1; + fprintf(f, " %s", fn); + len += strlen(fn) + 1; + } + + return len; +} + +void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) { + int leftColWidth; + + showHelpIntro(con, f); + if (con->otherHelp) + fprintf(f, " %s\n", con->otherHelp); + else + fprintf(f, " %s\n", POPT_("[OPTION...]")); + + leftColWidth = maxArgWidth(con->options, NULL); + singleTableHelp(f, con->options, leftColWidth, NULL); +} + +static int singleOptionUsage(FILE * f, int cursor, + const struct poptOption * opt, + const char *translation_domain) { + int len = 3; + char shortStr[2] = { '\0', '\0' }; + const char * item = shortStr; + const char * argDescrip = getArgDescrip(opt, translation_domain); + + if (opt->shortName) { + if (!(opt->argInfo & POPT_ARG_MASK)) + return cursor; /* we did these already */ + len++; + *shortStr = opt->shortName; + shortStr[1] = '\0'; + } else if (opt->longName) { + len += 1 + strlen(opt->longName); + item = opt->longName; + } + + if (len == 3) return cursor; + + if (argDescrip) + len += strlen(argDescrip) + 1; + + if ((cursor + len) > 79) { + fprintf(f, "\n "); + cursor = 7; + } + + fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item, + argDescrip ? (opt->shortName ? " " : "=") : "", + argDescrip ? argDescrip : ""); + + return cursor + len + 1; +} + +static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table, + const char *translation_domain) { + const struct poptOption * opt; + + opt = table; + while (opt->longName || opt->shortName || opt->arg) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) + translation_domain = (const char *)opt->arg; + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) + cursor = singleTableUsage(f, cursor, opt->arg, + translation_domain); + else if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + cursor = singleOptionUsage(f, cursor, opt, translation_domain); + + opt++; + } + + return cursor; +} + +static int showShortOptions(const struct poptOption * opt, FILE * f, + char * str) { + char s[300]; /* this is larger then the ascii set, so + it should do just fine */ + + s[0] = '\0'; + if (str == NULL) { + memset(s, 0, sizeof(s)); + str = s; + } + + while (opt->longName || opt->shortName || opt->arg) { + if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) + str[strlen(str)] = opt->shortName; + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) + showShortOptions(opt->arg, f, str); + + opt++; + } + + if (s != str || !*s) + return 0; + + fprintf(f, " [-%s]", s); + return strlen(s) + 4; +} + +void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) { + int cursor; + + cursor = showHelpIntro(con, f); + cursor += showShortOptions(con->options, f, NULL); + singleTableUsage(f, cursor, con->options, NULL); + + if (con->otherHelp) { + cursor += strlen(con->otherHelp) + 1; + if (cursor > 79) fprintf(f, "\n "); + fprintf(f, " %s", con->otherHelp); + } + + fprintf(f, "\n"); +} + +void poptSetOtherOptionHelp(poptContext con, const char * text) { + if (con->otherHelp) xfree(con->otherHelp); + con->otherHelp = xstrdup(text); +} diff --git a/source4/lib/popt/poptint.h b/source4/lib/popt/poptint.h new file mode 100644 index 0000000000..1847ffafe6 --- /dev/null +++ b/source4/lib/popt/poptint.h @@ -0,0 +1,71 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#ifndef H_POPTINT +#define H_POPTINT + +/* Bit mask macros. */ +typedef unsigned int __pbm_bits; +#define __PBM_NBITS (8 * sizeof (__pbm_bits)) +#define __PBM_IX(d) ((d) / __PBM_NBITS) +#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS)) +typedef struct { + __pbm_bits bits[1]; +} pbm_set; +#define __PBM_BITS(set) ((set)->bits) + +#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) +#define PBM_FREE(s) free(s); +#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) +#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) +#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) + +struct optionStackEntry { + int argc; + /*@only@*/ const char ** argv; + /*@only@*/ pbm_set * argb; + int next; + /*@only@*/ const char * nextArg; + /*@keep@*/ const char * nextCharArg; + /*@dependent@*/ struct poptAlias * currAlias; + int stuffed; +}; + +struct execEntry { + const char * longName; + char shortName; + const char * script; +}; + +struct poptContext_s { + struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; + /*@dependent@*/ struct optionStackEntry * os; + /*@owned@*/ const char ** leftovers; + int numLeftovers; + int nextLeftover; + /*@keep@*/ const struct poptOption * options; + int restLeftover; + /*@only@*/ const char * appName; + /*@only@*/ struct poptAlias * aliases; + int numAliases; + int flags; + struct execEntry * execs; + int numExecs; + /*@only@*/ const char ** finalArgv; + int finalArgvCount; + int finalArgvAlloced; + /*@dependent@*/ struct execEntry * doExec; + /*@only@*/ const char * execPath; + int execAbsolute; + /*@only@*/ const char * otherHelp; + pbm_set * arg_strip; +}; + +#define xfree(_a) free((void *)_a) + +#define POPT_(foo) (foo) +#define D_(dom, str) (str) +#define N_(foo) (foo) + +#endif diff --git a/source4/lib/popt/poptparse.c b/source4/lib/popt/poptparse.c new file mode 100644 index 0000000000..8f00769be9 --- /dev/null +++ b/source4/lib/popt/poptparse.c @@ -0,0 +1,102 @@ +/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING + file accompanying popt source distributions, available from + ftp://ftp.redhat.com/pub/code/popt */ + +#include "system.h" + +#define POPT_ARGV_ARRAY_GROW_DELTA 5 + +int poptDupArgv(int argc, const char **argv, + int * argcPtr, const char *** argvPtr) +{ + size_t nb = (argc + 1) * sizeof(*argv); + const char ** argv2; + char * dst; + int i; + + for (i = 0; i < argc; i++) { + if (argv[i] == NULL) + return POPT_ERROR_NOARG; + nb += strlen(argv[i]) + 1; + } + + dst = malloc(nb); + argv2 = (void *) dst; + dst += (argc + 1) * sizeof(*argv); + + for (i = 0; i < argc; i++) { + argv2[i] = dst; + dst += strlen(strcpy(dst, argv[i])) + 1; + } + argv2[argc] = NULL; + + *argvPtr = argv2; + *argcPtr = argc; + return 0; +} + +int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) +{ + const char * src; + char quote = '\0'; + int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; + const char ** argv = malloc(sizeof(*argv) * argvAlloced); + int argc = 0; + int buflen = strlen(s) + 1; + char *buf0 = calloc(buflen, 1); + char *buf = buf0; + + argv[argc] = buf; + + for (src = s; *src; src++) { + if (quote == *src) { + quote = '\0'; + } else if (quote) { + if (*src == '\\') { + src++; + if (!*src) { + free(argv); + free(buf0); + return POPT_ERROR_BADQUOTE; + } + if (*src != quote) *buf++ = '\\'; + } + *buf++ = *src; + } else if (isspace(*src)) { + if (*argv[argc]) { + buf++, argc++; + if (argc == argvAlloced) { + argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; + argv = realloc(argv, sizeof(*argv) * argvAlloced); + } + argv[argc] = buf; + } + } else switch (*src) { + case '"': + case '\'': + quote = *src; + break; + case '\\': + src++; + if (!*src) { + free(argv); + free(buf0); + return POPT_ERROR_BADQUOTE; + } + /*@fallthrough@*/ + default: + *buf++ = *src; + break; + } + } + + if (strlen(argv[argc])) { + argc++, buf++; + } + + (void) poptDupArgv(argc, argv, argcPtr, argvPtr); + + free(argv); + free(buf0); + return 0; +} diff --git a/source4/lib/popt/system.h b/source4/lib/popt/system.h new file mode 100644 index 0000000000..059c045817 --- /dev/null +++ b/source4/lib/popt/system.h @@ -0,0 +1,53 @@ +#include "config.h" + +#include +#include +#include +#include + +#if HAVE_MCHECK_H +#include +#endif + +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#ifdef __NeXT +/* access macros are not declared in non posix mode in unistd.h - + don't try to use posix on NeXTstep 3.3 ! */ +#include +#endif + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX +#pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +#elif defined(__GNUC__) && defined(__STRICT_ANSI__) +#define alloca __builtin_alloca +#endif + +/*@only@*/ char * xstrdup (const char *str); + +#if HAVE_MCHECK_H && defined(__GNUC__) +#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) +#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) +#else +#define xstrdup(_str) strdup(_str) +#endif /* HAVE_MCHECK_H && defined(__GNUC__) */ + + +#include "popt.h" diff --git a/source4/lib/popt_common.c b/source4/lib/popt_common.c new file mode 100644 index 0000000000..ccdecc91cc --- /dev/null +++ b/source4/lib/popt_common.c @@ -0,0 +1,327 @@ +/* + Unix SMB/CIFS implementation. + Common popt routines + + Copyright (C) Tim Potter 2001,2002 + Copyright (C) Jelmer Vernooij 2002,2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* Handle command line options: + * -d,--debuglevel + * -s,--configfile + * -O,--socket-options + * -V,--version + * -l,--log-base + * -n,--netbios-name + * -W,--workgroup + * -i,--scope + */ + +extern pstring user_socket_options; +extern BOOL AllowDebugChange; + +struct user_auth_info cmdline_auth_info; + +static void popt_common_callback(poptContext con, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) +{ + pstring logfile; + const char *pname; + + /* Find out basename of current program */ + pname = strrchr_m(poptGetInvocationName(con),'/'); + + if (!pname) + pname = poptGetInvocationName(con); + else + pname++; + + if (reason == POPT_CALLBACK_REASON_PRE) { + pstr_sprintf(logfile, "%s/log.%s", dyn_LOGFILEBASE, pname); + lp_set_cmdline("log file", logfile); + return; + } + + switch(opt->val) { + case 'd': + lp_set_cmdline("log level", arg); + break; + + case 'V': + printf( "Version %s\n", SAMBA_VERSION ); + exit(0); + break; + + case 's': + if (arg) { + pstrcpy(dyn_CONFIGFILE, arg); + } + break; + + case 'l': + if (arg) { + pstr_sprintf(logfile, "%s/log.%s", arg, pname); + lp_set_cmdline("log file", logfile); + } + break; + + case 'W': + lp_set_cmdline("workgroup", arg); + break; + + case 'n': + lp_set_cmdline("netbios name", arg); + break; + + case 'i': + lp_set_cmdline("netbios scope", arg); + break; + } +} + +struct poptOption popt_common_connection[] = { + { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", + "SOCKETOPTIONS" }, + { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, + { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, + { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + POPT_TABLEEND +}; + +struct poptOption popt_common_samba[] = { + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, + { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, + { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, + { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, + { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, + POPT_TABLEEND +}; + +struct poptOption popt_common_version[] = { + { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, + { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, + POPT_TABLEEND +}; + + + +/**************************************************************************** + * get a password from a a file or file descriptor + * exit on failure + * ****************************************************************************/ +static void get_password_file(struct user_auth_info *a) +{ + int fd = -1; + char *p; + BOOL close_it = False; + pstring spec; + char pass[128]; + + if ((p = getenv("PASSWD_FD")) != NULL) { + pstrcpy(spec, "descriptor "); + pstrcat(spec, p); + sscanf(p, "%d", &fd); + close_it = False; + } else if ((p = getenv("PASSWD_FILE")) != NULL) { + fd = sys_open(p, O_RDONLY, 0); + pstrcpy(spec, p); + if (fd < 0) { + fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", + spec, strerror(errno)); + exit(1); + } + close_it = True; + } + + for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ + p && p - pass < sizeof(pass);) { + switch (read(fd, p, 1)) { + case 1: + if (*p != '\n' && *p != '\0') { + *++p = '\0'; /* advance p, and null-terminate pass */ + break; + } + case 0: + if (p - pass) { + *p = '\0'; /* null-terminate it, just in case... */ + p = NULL; /* then force the loop condition to become false */ + break; + } else { + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, "empty password\n"); + exit(1); + } + + default: + fprintf(stderr, "Error reading password from file %s: %s\n", + spec, strerror(errno)); + exit(1); + } + } + pstrcpy(a->password, pass); + if (close_it) + close(fd); +} + +static void get_credentials_file(const char *file, struct user_auth_info *info) +{ + XFILE *auth; + fstring buf; + uint16 len = 0; + char *ptr, *val, *param; + + if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) + { + /* fail if we can't open the credentials file */ + d_printf("ERROR: Unable to open credentials file!\n"); + exit(-1); + } + + while (!x_feof(auth)) + { + /* get a line from the file */ + if (!x_fgets(buf, sizeof(buf), auth)) + continue; + len = strlen(buf); + + if ((len) && (buf[len-1]=='\n')) + { + buf[len-1] = '\0'; + len--; + } + if (len == 0) + continue; + + /* break up the line into parameter & value. + * will need to eat a little whitespace possibly */ + param = buf; + if (!(ptr = strchr_m (buf, '='))) + continue; + + val = ptr+1; + *ptr = '\0'; + + /* eat leading white space */ + while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) + val++; + + if (strwicmp("password", param) == 0) + { + pstrcpy(info->password, val); + info->got_pass = True; + } + else if (strwicmp("username", param) == 0) + pstrcpy(info->username, val); + //else if (strwicmp("domain", param) == 0) + // set_global_myworkgroup(val); + memset(buf, 0, sizeof(buf)); + } + x_fclose(auth); +} + +/* Handle command line options: + * -U,--user + * -A,--authentication-file + * -k,--use-kerberos + * -N,--no-pass + */ + + +static void popt_common_credentials_callback(poptContext con, + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) +{ + char *p; + + if (reason == POPT_CALLBACK_REASON_PRE) { + cmdline_auth_info.use_kerberos = False; + cmdline_auth_info.got_pass = False; + pstrcpy(cmdline_auth_info.username, "GUEST"); + + if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); + + if (getenv("USER")) { + pstrcpy(cmdline_auth_info.username,getenv("USER")); + + if ((p = strchr_m(cmdline_auth_info.username,'%'))) { + *p = 0; + pstrcpy(cmdline_auth_info.password,p+1); + cmdline_auth_info.got_pass = True; + memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); + } + } + + if (getenv("PASSWD")) { + pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); + cmdline_auth_info.got_pass = True; + } + + if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { + get_password_file(&cmdline_auth_info); + cmdline_auth_info.got_pass = True; + } + + return; + } + + switch(opt->val) { + case 'U': + { + char *lp; + + pstrcpy(cmdline_auth_info.username,arg); + if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { + *lp = 0; + pstrcpy(cmdline_auth_info.password,lp+1); + cmdline_auth_info.got_pass = True; + memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); + } + } + break; + + case 'A': + get_credentials_file(arg, &cmdline_auth_info); + break; + + case 'k': +#ifndef HAVE_KRB5 + d_printf("No kerberos support compiled in\n"); + exit(1); +#else + cmdline_auth_info.use_kerberos = True; + cmdline_auth_info.got_pass = True; +#endif + break; + } +} + + + +struct poptOption popt_common_credentials[] = { + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, + { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, + { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, + POPT_TABLEEND +}; diff --git a/source4/lib/readline.c b/source4/lib/readline.c new file mode 100644 index 0000000000..c5da88b3e0 --- /dev/null +++ b/source4/lib/readline.c @@ -0,0 +1,159 @@ +/* + Unix SMB/CIFS implementation. + Samba readline wrapper implementation + Copyright (C) Simo Sorce 2001 + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifdef HAVE_LIBREADLINE +# ifdef HAVE_READLINE_READLINE_H +# include +# ifdef HAVE_READLINE_HISTORY_H +# include +# endif +# else +# ifdef HAVE_READLINE_H +# include +# ifdef HAVE_HISTORY_H +# include +# endif +# else +# undef HAVE_LIBREADLINE +# endif +# endif +#endif + +#ifdef HAVE_NEW_LIBREADLINE +# define RL_COMPLETION_CAST (rl_completion_func_t *) +#else +/* This type is missing from libreadline<4.0 (approximately) */ +# define RL_COMPLETION_CAST +#endif /* HAVE_NEW_LIBREADLINE */ + +/**************************************************************************** + Display the prompt and wait for input. Call callback() regularly +****************************************************************************/ + +static char *smb_readline_replacement(const char *prompt, void (*callback)(void), + char **(completion_fn)(const char *text, int start, int end)) +{ + fd_set fds; + static pstring line; + struct timeval timeout; + int fd = x_fileno(x_stdin); + char *ret; + + do_debug("%s", prompt); + + while (1) { + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(fd,&fds); + + if (sys_select_intr(fd+1,&fds,NULL,NULL,&timeout) == 1) { + ret = x_fgets(line, sizeof(line), x_stdin); + return ret; + } + if (callback) + callback(); + } +} + +/**************************************************************************** + Display the prompt and wait for input. Call callback() regularly. +****************************************************************************/ + +char *smb_readline(const char *prompt, void (*callback)(void), + char **(completion_fn)(const char *text, int start, int end)) +{ +#if HAVE_LIBREADLINE + if (isatty(x_fileno(x_stdin))) { + char *ret; + + /* Aargh! Readline does bizzare things with the terminal width + that mucks up expect(1). Set CLI_NO_READLINE in the environment + to force readline not to be used. */ + + if (getenv("CLI_NO_READLINE")) + return smb_readline_replacement(prompt, callback, completion_fn); + + if (completion_fn) { + /* The callback prototype has changed slightly between + different versions of Readline, so the same function + works in all of them to date, but we get compiler + warnings in some. */ + rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; + } + + if (callback) + rl_event_hook = (Function *)callback; + ret = readline(prompt); + if (ret && *ret) + add_history(ret); + return ret; + } else +#endif + return smb_readline_replacement(prompt, callback, completion_fn); +} + +/**************************************************************************** + * return line buffer text + ****************************************************************************/ +const char *smb_readline_get_line_buffer(void) +{ +#if defined(HAVE_LIBREADLINE) + return rl_line_buffer; +#else + return NULL; +#endif +} + +/**************************************************************************** + * set completion append character + ***************************************************************************/ +void smb_readline_ca_char(char c) +{ +#if defined(HAVE_LIBREADLINE) + rl_completion_append_character = c; +#endif +} + + +/**************************************************************************** +history +****************************************************************************/ +int cmd_history(void) +{ +#if defined(HAVE_LIBREADLINE) + HIST_ENTRY **hlist; + int i; + + hlist = history_list(); + + for (i = 0; hlist && hlist[i]; i++) { + DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); + } +#else + DEBUG(0,("no history without readline support\n")); +#endif + + return 0; +} diff --git a/source4/lib/replace.c b/source4/lib/replace.c new file mode 100644 index 0000000000..cda379c63f --- /dev/null +++ b/source4/lib/replace.c @@ -0,0 +1,467 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + void replace_dummy(void); + void replace_dummy(void) {} + +#ifndef HAVE_FTRUNCATE + /******************************************************************* +ftruncate for operating systems that don't have it +********************************************************************/ + int ftruncate(int f,SMB_OFF_T l) +{ + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = l; + fl.l_type = F_WRLCK; + return fcntl(f, F_FREESP, &fl); +} +#endif /* HAVE_FTRUNCATE */ + + +#ifndef HAVE_STRLCPY +/* like strncpy but does not 0 fill the buffer and always null + terminates. bufsize is the size of the destination buffer */ + size_t strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + if (bufsize <= 0) return 0; + if (len >= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ + size_t strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif + +#ifndef HAVE_MKTIME +/******************************************************************* +a mktime() replacement for those who don't have it - contributed by +C.A. Lademann +Corrections by richard.kettlewell@kewill.com +********************************************************************/ + +#define MINUTE 60 +#define HOUR 60*MINUTE +#define DAY 24*HOUR +#define YEAR 365*DAY + time_t mktime(struct tm *t) +{ + struct tm *u; + time_t epoch = 0; + int n; + int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + y, m, i; + + if(t->tm_year < 70) + return((time_t)-1); + + n = t->tm_year + 1900 - 1; + epoch = (t->tm_year - 70) * YEAR + + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; + + y = t->tm_year + 1900; + m = 0; + + for(i = 0; i < t->tm_mon; i++) { + epoch += mon [m] * DAY; + if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) + epoch += DAY; + + if(++m > 11) { + m = 0; + y++; + } + } + + epoch += (t->tm_mday - 1) * DAY; + epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; + + if((u = localtime(&epoch)) != NULL) { + t->tm_sec = u->tm_sec; + t->tm_min = u->tm_min; + t->tm_hour = u->tm_hour; + t->tm_mday = u->tm_mday; + t->tm_mon = u->tm_mon; + t->tm_year = u->tm_year; + t->tm_wday = u->tm_wday; + t->tm_yday = u->tm_yday; + t->tm_isdst = u->tm_isdst; + } + + return(epoch); +} +#endif /* !HAVE_MKTIME */ + + + +#ifndef HAVE_RENAME +/* Rename a file. (from libiberty in GNU binutils) */ + int rename(const char *zfrom, const char *zto) +{ + if (link (zfrom, zto) < 0) + { + if (errno != EEXIST) + return -1; + if (unlink (zto) < 0 + || link (zfrom, zto) < 0) + return -1; + } + return unlink (zfrom); +} +#endif /* HAVE_RENAME */ + + +#ifndef HAVE_INNETGR +#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT) +/* + * Search for a match in a netgroup. This replaces it on broken systems. + */ + int innetgr(const char *group,const char *host,const char *user,const char *dom) +{ + char *hst, *usr, *dm; + + setnetgrent(group); + while (getnetgrent(&hst, &usr, &dm)) { + if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && + ((user == 0) || (usr == 0) || !strcmp(user, usr)) && + ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { + endnetgrent(); + return (1); + } + } + endnetgrent(); + return (0); +} +#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */ +#endif /* HAVE_INNETGR */ + + + +#ifndef HAVE_INITGROUPS +/**************************************************************************** + some systems don't have an initgroups call +****************************************************************************/ + int initgroups(char *name,gid_t id) +{ +#ifndef HAVE_SETGROUPS + static int done; + if (!done) { + DEBUG(1,("WARNING: running without setgroups\n")); + done=1; + } + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ + return(0); +#else /* HAVE_SETGROUPS */ + gid_t *grouplst = NULL; + int max_gr = groups_max(); + int ret; + int i,j; + struct group *g; + char *gr; + + if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) { + DEBUG(0,("initgroups: malloc fail !\n")); + return -1; + } + + grouplst[0] = id; + i = 1; + while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { + if (g->gr_gid == id) + continue; + j = 0; + gr = g->gr_mem[0]; + while (gr && (*gr != (char)NULL)) { + if (strcmp(name,gr) == 0) { + grouplst[i] = g->gr_gid; + i++; + gr = (char *)NULL; + break; + } + gr = g->gr_mem[++j]; + } + } + endgrent(); + ret = sys_setgroups(i,grouplst); + SAFE_FREE(grouplst); + return ret; +#endif /* HAVE_SETGROUPS */ +} +#endif /* HAVE_INITGROUPS */ + + +#if (defined(SecureWare) && defined(SCO)) +/* This is needed due to needing the nap() function but we don't want + to include the Xenix libraries since that will break other things... + BTW: system call # 0x0c28 is the same as calling nap() */ + long nap(long milliseconds) { + return syscall(0x0c28, milliseconds); + } +#endif + + +#ifndef HAVE_MEMMOVE +/******************************************************************* +safely copies memory, ensuring no overlap problems. +this is only used if the machine does not have it's own memmove(). +this is not the fastest algorithm in town, but it will do for our +needs. +********************************************************************/ + void *memmove(void *dest,const void *src,int size) +{ + unsigned long d,s; + int i; + if (dest==src || !size) return(dest); + + d = (unsigned long)dest; + s = (unsigned long)src; + + if ((d >= (s+size)) || (s >= (d+size))) { + /* no overlap */ + memcpy(dest,src,size); + return(dest); + } + + if (d < s) { + /* we can forward copy */ + if (s-d >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=0;i= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + } + } + return(dest); +} +#endif /* HAVE_MEMMOVE */ + +#ifndef HAVE_STRDUP +/**************************************************************************** +duplicate a string +****************************************************************************/ + char *strdup(const char *s) +{ + size_t len; + char *ret; + + if (!s) return(NULL); + + len = strlen(s)+1; + ret = (char *)malloc(len); + if (!ret) return(NULL); + memcpy(ret,s,len); + return(ret); +} +#endif /* HAVE_STRDUP */ +#if 0 /* REWRITE: not thread safe */ +#ifdef REPLACE_INET_NTOA +char *rep_inet_ntoa(struct in_addr ip) +{ + unsigned char *p = (unsigned char *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} +#endif /* REPLACE_INET_NTOA */ +#endif +#ifndef HAVE_STRTOUL +#ifndef ULONG_MAX +#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ +#endif + +/* + * Convert a string to an unsigned long integer. + * Taken from libg++ - libiberty code. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ + unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base); + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} +#endif /* HAVE_STRTOUL */ + +#ifndef HAVE_SETLINEBUF + int setlinebuf(FILE *stream) +{ + return setvbuf(stream, (char *)NULL, _IOLBF, 0); +} +#endif /* HAVE_SETLINEBUF */ + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG + void vsyslog (int facility_priority, char *format, va_list arglist) +{ + char *msg = NULL; + vasprintf(&msg, format, arglist); + if (!msg) + return; + syslog(facility_priority, "%s", msg); + SAFE_FREE(msg); +} +#endif /* HAVE_SYSLOG */ +#endif /* HAVE_VSYSLOG */ + + +#ifndef HAVE_TIMEGM +/* + yes, I know this looks insane, but its really needed. The function in the + Linux timegm() manpage does not work on solaris. +*/ + time_t timegm(struct tm *tm) +{ + struct tm tm2, tm3; + time_t t; + + tm2 = *tm; + + t = mktime(&tm2); + tm3 = *localtime(&t); + tm2 = *tm; + tm2.tm_isdst = tm3.tm_isdst; + t = mktime(&tm2); + t -= TimeDiff(t); + + return t; +} +#endif + +#ifndef HAVE_SETENV + int setenv(const char *name, const char *value, int overwrite) +{ + char *p = NULL; + int ret = -1; + + asprintf(&p, "%s=%s", name, value); + + if (overwrite || getenv(name)) { + if (p) ret = putenv(p); + } else { + ret = 0; + } + + return ret; +} +#endif diff --git a/source4/lib/select.c b/source4/lib/select.c new file mode 100644 index 0000000000..5d7e4a0ad2 --- /dev/null +++ b/source4/lib/select.c @@ -0,0 +1,159 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Samba select/poll implementation + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* This is here because it allows us to avoid a nasty race in signal handling. + We need to guarantee that when we get a signal we get out of a select immediately + but doing that involves a race condition. We can avoid the race by getting the + signal handler to write to a pipe that is in the select/poll list + + This means all Samba signal handlers should call sys_select_signal(). +*/ + +static pid_t initialised; +static int select_pipe[2]; +static VOLATILE unsigned pipe_written, pipe_read; + +/******************************************************************* + Call this from all Samba signal handlers if you want to avoid a + nasty signal race condition. +********************************************************************/ + +void sys_select_signal(void) +{ + char c = 1; + if (!initialised) return; + + if (pipe_written > pipe_read+256) return; + + if (write(select_pipe[1], &c, 1) == 1) pipe_written++; +} + +/******************************************************************* + Like select() but avoids the signal race using a pipe + it also guuarantees that fds on return only ever contains bits set + for file descriptors that were readable. +********************************************************************/ + +int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval) +{ + int ret, saved_errno; + fd_set *readfds2, readfds_buf; + + if (initialised != getpid()) { + pipe(select_pipe); + + /* + * These next two lines seem to fix a bug with the Linux + * 2.0.x kernel (and probably other UNIXes as well) where + * the one byte read below can block even though the + * select returned that there is data in the pipe and + * the pipe_written variable was incremented. Thanks to + * HP for finding this one. JRA. + */ + + if(set_blocking(select_pipe[0],0)==-1) + smb_panic("select_pipe[0]: O_NONBLOCK failed.\n"); + if(set_blocking(select_pipe[1],0)==-1) + smb_panic("select_pipe[1]: O_NONBLOCK failed.\n"); + + initialised = getpid(); + } + + maxfd = MAX(select_pipe[0]+1, maxfd); + + /* If readfds is NULL we need to provide our own set. */ + if (readfds) { + readfds2 = readfds; + } else { + readfds2 = &readfds_buf; + FD_ZERO(readfds2); + } + FD_SET(select_pipe[0], readfds2); + + errno = 0; + ret = select(maxfd,readfds2,writefds,errorfds,tval); + + if (ret <= 0) { + FD_ZERO(readfds2); + if (writefds) + FD_ZERO(writefds); + if (errorfds) + FD_ZERO(errorfds); + } + + if (FD_ISSET(select_pipe[0], readfds2)) { + char c; + saved_errno = errno; + if (read(select_pipe[0], &c, 1) == 1) { + pipe_read++; + } + errno = saved_errno; + FD_CLR(select_pipe[0], readfds2); + ret--; + if (ret == 0) { + ret = -1; + errno = EINTR; + } + } + + return ret; +} + +/******************************************************************* + Similar to sys_select() but catch EINTR and continue. + This is what sys_select() used to do in Samba. +********************************************************************/ + +int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval) +{ + int ret; + fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf; + struct timeval tval2, *ptval; + + readfds2 = (readfds ? &readfds_buf : NULL); + writefds2 = (writefds ? &writefds_buf : NULL); + errorfds2 = (errorfds ? &errorfds_buf : NULL); + ptval = (tval ? &tval2 : NULL); + + do { + if (readfds) + readfds_buf = *readfds; + if (writefds) + writefds_buf = *writefds; + if (errorfds) + errorfds_buf = *errorfds; + if (tval) + tval2 = *tval; + + ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval); + } while (ret == -1 && errno == EINTR); + + if (readfds) + *readfds = readfds_buf; + if (writefds) + *writefds = writefds_buf; + if (errorfds) + *errorfds = errorfds_buf; + + return ret; +} diff --git a/source4/lib/sendfile.c b/source4/lib/sendfile.c new file mode 100644 index 0000000000..bcc8cb08ca --- /dev/null +++ b/source4/lib/sendfile.c @@ -0,0 +1,382 @@ +/* + Unix SMB/Netbios implementation. + Version 2.2.x / 3.0.x + sendfile implementations. + Copyright (C) Jeremy Allison 2002. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * This file handles the OS dependent sendfile implementations. + * The API is such that it returns -1 on error, else returns the + * number of bytes written. + */ + +#include "includes.h" + +#if defined(LINUX_SENDFILE_API) + +#include + +#ifndef MSG_MORE +#define MSG_MORE 0x8000 +#endif + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + ssize_t ret; + size_t hdr_len = 0; + + /* + * Send the header first. + * Use MSG_MORE to cork the TCP output until sendfile is called. + */ + + if (header) { + hdr_len = header->length; + while (total < hdr_len) { + ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); + if (ret == -1) + return -1; + total += ret; + } + } + + total = count; + while (total) { + ssize_t nwritten; + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) + nwritten = sendfile64(tofd, fromfd, &offset, total); +#else + nwritten = sendfile(tofd, fromfd, &offset, total); +#endif + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + total -= nwritten; + } + return count + hdr_len; +} + +#elif defined(LINUX_BROKEN_SENDFILE_API) + +/* + * We must use explicit 32 bit types here. This code path means Linux + * won't do proper 64-bit sendfile. JRA. + */ + +extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count); + + +#ifndef MSG_MORE +#define MSG_MORE 0x8000 +#endif + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + ssize_t ret; + ssize_t hdr_len = 0; + uint32 small_total = 0; + int32 small_offset; + + /* + * Fix for broken Linux 2.4 systems with no working sendfile64(). + * If the offset+count > 2 GB then pretend we don't have the + * system call sendfile at all. The upper layer catches this + * and uses a normal read. JRA. + */ + + if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) { + errno = ENOSYS; + return -1; + } + + /* + * Send the header first. + * Use MSG_MORE to cork the TCP output until sendfile is called. + */ + + if (header) { + hdr_len = header->length; + while (total < hdr_len) { + ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); + if (ret == -1) + return -1; + total += ret; + } + } + + small_total = (uint32)count; + small_offset = (int32)offset; + + while (small_total) { + int32 nwritten; + do { + nwritten = sendfile(tofd, fromfd, &small_offset, small_total); + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + small_total -= nwritten; + } + return count + hdr_len; +} + + +#elif defined(SOLARIS_SENDFILE_API) + +/* + * Solaris sendfile code written by Pierre Belanger . + */ + +#include + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + int sfvcnt; + size_t total, xferred; + struct sendfilevec vec[2]; + ssize_t hdr_len = 0; + + if (header) { + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = header->data; + vec[0].sfv_len = hdr_len = header->length; + + vec[1].sfv_fd = fromfd; + vec[1].sfv_flag = 0; + vec[1].sfv_off = offset; + vec[1].sfv_len = count; + + } else { + sfvcnt = 1; + + vec[0].sfv_fd = fromfd; + vec[0].sfv_flag = 0; + vec[0].sfv_off = offset; + vec[0].sfv_len = count; + } + + total = count + hdr_len; + + while (total) { + ssize_t nwritten; + + /* + * Although not listed in the API error returns, this is almost certainly + * a slow system call and will be interrupted by a signal with EINTR. JRA. + */ + + xferred = 0; + +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64) + nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); +#else + nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); +#endif + if (nwritten == -1 && errno == EINTR) { + if (xferred == 0) + continue; /* Nothing written yet. */ + else + nwritten = xferred; + } + + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than vec[0].sfv_len bytes. + * We move vec[1].* to vec[0].* and set sfvcnt to 1 + */ + + if (sfvcnt == 2 && nwritten >= vec[0].sfv_len) { + vec[1].sfv_off += nwritten - vec[0].sfv_len; + vec[1].sfv_len -= nwritten - vec[0].sfv_len; + + /* Move vec[1].* to vec[0].* and set sfvcnt to 1 */ + vec[0] = vec[1]; + sfvcnt = 1; + } else { + vec[0].sfv_off += nwritten; + vec[0].sfv_len -= nwritten; + } + total -= nwritten; + } + return count + hdr_len; +} + +#elif defined(HPUX_SENDFILE_API) + +#include +#include + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + struct iovec hdtrl[2]; + size_t hdr_len = 0; + + if (header) { + /* Set up the header/trailer iovec. */ + hdtrl[0].iov_base = header->data; + hdtrl[0].iov_len = hdr_len = header->length; + } else { + hdtrl[0].iov_base = NULL; + hdtrl[0].iov_len = hdr_len = 0; + } + hdtrl[1].iov_base = NULL; + hdtrl[1].iov_base = 0; + + total = count; + while (total + hdtrl[0].iov_len) { + ssize_t nwritten; + + /* + * HPUX guarantees that if any data was written before + * a signal interrupt then sendfile returns the number of + * bytes written (which may be less than requested) not -1. + * nwritten includes the header data sent. + */ + + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) + nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0); +#else + nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0); +#endif + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than hdtrl[0].iov_len bytes. + * We change nwritten to be the number of file bytes written. + */ + + if (hdtrl[0].iov_base && hdtrl[0].iov_len) { + if (nwritten >= hdtrl[0].iov_len) { + nwritten -= hdtrl[0].iov_len; + hdtrl[0].iov_base = NULL; + hdtrl[0].iov_len = 0; + } else { + /* iov_base is defined as a void *... */ + hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten; + hdtrl[0].iov_len -= nwritten; + nwritten = 0; + } + } + total -= nwritten; + offset += nwritten; + } + return count + hdr_len; +} + +#elif defined(FREEBSD_SENDFILE_API) + +#include +#include +#include + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + struct sf_hdtr hdr; + struct iovec hdtrl; + size_t hdr_len = 0; + + hdr.headers = &hdtrl; + hdr.hdr_cnt = 1; + hdr.trailers = NULL; + hdr.trl_cnt = 0; + + /* Set up the header iovec. */ + if (header) { + hdtrl.iov_base = header->data; + hdtrl.iov_len = hdr_len = header->length; + } else { + hdtrl.iov_base = NULL; + hdtrl.iov_len = 0; + } + + total = count; + while (total + hdtrl.iov_len) { + SMB_OFF_T nwritten; + int ret; + + /* + * FreeBSD sendfile returns 0 on success, -1 on error. + * Remember, the tofd and fromfd are reversed..... :-). + * nwritten includes the header data sent. + */ + + do { + ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0); + } while (ret == -1 && errno == EINTR); + if (ret == -1) + return -1; + + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than hdtrl.iov_len bytes. + * We change nwritten to be the number of file bytes written. + */ + + if (hdtrl.iov_base && hdtrl.iov_len) { + if (nwritten >= hdtrl.iov_len) { + nwritten -= hdtrl.iov_len; + hdtrl.iov_base = NULL; + hdtrl.iov_len = 0; + } else { + hdtrl.iov_base += nwritten; + hdtrl.iov_len -= nwritten; + nwritten = 0; + } + } + total -= nwritten; + offset += nwritten; + } + return count + hdr_len; +} + +#else /* No sendfile implementation. Return error. */ + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + /* No sendfile syscall. */ + errno = ENOSYS; + return -1; +} +#endif diff --git a/source4/lib/server_mutex.c b/source4/lib/server_mutex.c new file mode 100644 index 0000000000..878e5497d8 --- /dev/null +++ b/source4/lib/server_mutex.c @@ -0,0 +1,58 @@ +/* + Unix SMB/CIFS implementation. + Authenticate against a remote domain + Copyright (C) Andrew Tridgell 1992-2002 + Copyright (C) Andrew Bartlett 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* For reasons known only to MS, many of their NT/Win2k versions + need serialised access only. Two connections at the same time + may (in certain situations) cause connections to be reset, + or access to be denied. + + This locking allows smbd's mutlithread architecture to look + like the single-connection that NT makes. */ + +static char *mutex_server_name; +/* FIXME. ref_count should be allocated per name... JRA. */ +size_t ref_count; + +BOOL grab_server_mutex(const char *name) +{ + mutex_server_name = strdup(name); + if (!mutex_server_name) { + DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name)); + return False; + } + if (!secrets_named_mutex(mutex_server_name, 10, &ref_count)) { + DEBUG(10,("grab_server_mutex: failed for %s\n", name)); + SAFE_FREE(mutex_server_name); + return False; + } + + return True; +} + +void release_server_mutex(void) +{ + if (mutex_server_name) { + secrets_named_mutex_release(mutex_server_name, &ref_count); + SAFE_FREE(mutex_server_name); + } +} diff --git a/source4/lib/signal.c b/source4/lib/signal.c new file mode 100644 index 0000000000..bff4b91c1a --- /dev/null +++ b/source4/lib/signal.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + signal handling functions + + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/**************************************************************************** + Catch child exits and reap the child zombie status. +****************************************************************************/ + +static void sig_cld(int signum) +{ + while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + ; + + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld); +#endif +} + +/**************************************************************************** +catch child exits - leave status; +****************************************************************************/ + +static void sig_cld_leave_status(int signum) +{ + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld_leave_status); +#endif +} + +/******************************************************************* + Block sigs. +********************************************************************/ + +void BlockSignals(BOOL block,int signum) +{ +#ifdef HAVE_SIGPROCMASK + sigset_t set; + sigemptyset(&set); + sigaddset(&set,signum); + sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); +#elif defined(HAVE_SIGBLOCK) + if (block) { + sigblock(sigmask(signum)); + } else { + sigsetmask(siggetmask() & ~sigmask(signum)); + } +#else + /* yikes! This platform can't block signals? */ + static int done; + if (!done) { + DEBUG(0,("WARNING: No signal blocking available\n")); + done=1; + } +#endif +} + +/******************************************************************* + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +********************************************************************/ + +void (*CatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + +/******************************************************************* + Ignore SIGCLD via whatever means is necessary for this OS. +********************************************************************/ + +void CatchChild(void) +{ + CatchSignal(SIGCLD, sig_cld); +} + +/******************************************************************* + Catch SIGCLD but leave the child around so it's status can be reaped. +********************************************************************/ + +void CatchChildLeaveStatus(void) +{ + CatchSignal(SIGCLD, sig_cld_leave_status); +} diff --git a/source4/lib/smbpasswd.c b/source4/lib/smbpasswd.c new file mode 100644 index 0000000000..92ae1ffea2 --- /dev/null +++ b/source4/lib/smbpasswd.c @@ -0,0 +1,200 @@ +/* + Unix SMB/CIFS implementation. + + smbpasswd file format routines + + Copyright (C) Andrew Tridgell 1992-1998 + Modified by Jeremy Allison 1995. + Modified by Gerald (Jerry) Carter 2000-2001 + Copyright (C) Tim Potter 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/*! \file lib/smbpasswd.c + + The smbpasswd file is used to store encrypted passwords in a similar + fashion to the /etc/passwd file. The format is colon separated fields + with one user per line like so: + + ::::: + + The username and uid must correspond to an entry in the /etc/passwd + file. The lanman and nt password hashes are 32 hex digits corresponding + to the 16-byte lanman and nt hashes respectively. + + The password last change time is stored as a string of the format + LCD- where the change time is expressed as an + + 'N' No password + 'D' Disabled + 'H' Homedir required + 'T' Temp account. + 'U' User account (normal) + 'M' MNS logon user account - what is this ? + 'W' Workstation account + 'S' Server account + 'L' Locked account + 'X' No Xpiry on password + 'I' Interdomain trust account + +*/ + +#include "includes.h" + +/*! Convert 32 hex characters into a 16 byte array. */ + +BOOL smbpasswd_gethexpwd(char *p, unsigned char *pwd) +{ + int i; + unsigned char lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + + if (!p) return (False); + + for (i = 0; i < 32; i += 2) + { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); + + p1 = strchr_m(hexchars, hinybble); + p2 = strchr_m(hexchars, lonybble); + + if (!p1 || !p2) + { + return (False); + } + + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + pwd[i / 2] = (hinybble << 4) | lonybble; + } + return (True); +} + +/*! Convert a 16-byte array into 32 hex characters. */ + +void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16 acb_info) +{ + if (pwd != NULL) { + int i; + for (i = 0; i < 16; i++) + slprintf(&p[i*2], 3, "%02X", pwd[i]); + } else { + if (acb_info & ACB_PWNOTREQ) + safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); + else + safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); + } +} + +/*! Decode the account control bits (ACB) info from a string. */ + +uint16 smbpasswd_decode_acb_info(const char *p) +{ + uint16 acb_info = 0; + BOOL finished = False; + + /* + * Check if the account type bits have been encoded after the + * NT password (in the form [NDHTUWSLXI]). + */ + + if (*p != '[') return 0; + + for (p++; *p && !finished; p++) + { + switch (*p) { + case 'N': /* 'N'o password. */ + acb_info |= ACB_PWNOTREQ; + break; + case 'D': /* 'D'isabled. */ + acb_info |= ACB_DISABLED; + break; + case 'H': /* 'H'omedir required. */ + acb_info |= ACB_HOMDIRREQ; + break; + case 'T': /* 'T'emp account. */ + acb_info |= ACB_TEMPDUP; + break; + case 'U': /* 'U'ser account (normal). */ + acb_info |= ACB_NORMAL; + break; + case 'M': /* 'M'NS logon user account. What is this ? */ + acb_info |= ACB_MNS; + break; + case 'W': /* 'W'orkstation account. */ + acb_info |= ACB_WSTRUST; + break; + case 'S': /* 'S'erver account. */ + acb_info |= ACB_SVRTRUST; + break; + case 'L': /* 'L'ocked account. */ + acb_info |= ACB_AUTOLOCK; + break; + case 'X': /* No 'X'piry on password */ + acb_info |= ACB_PWNOEXP; + break; + case 'I': /* 'I'nterdomain trust account. */ + acb_info |= ACB_DOMTRUST; + break; + + case ' ': + break; + case ':': + case '\n': + case '\0': + case ']': + default: + finished = True; + break; + } + } + + return acb_info; +} + +/*! Encode account control bits (ACBs) into a string. */ + +char *smbpasswd_encode_acb_info(uint16 acb_info) +{ + static fstring acct_str; + size_t i = 0; + + acct_str[i++] = '['; + + if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N'; + if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D'; + if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H'; + if (acb_info & ACB_TEMPDUP ) acct_str[i++] = 'T'; + if (acb_info & ACB_NORMAL ) acct_str[i++] = 'U'; + if (acb_info & ACB_MNS ) acct_str[i++] = 'M'; + if (acb_info & ACB_WSTRUST ) acct_str[i++] = 'W'; + if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S'; + if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L'; + if (acb_info & ACB_PWNOEXP ) acct_str[i++] = 'X'; + if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I'; + + for ( ; i < NEW_PW_FORMAT_SPACE_PADDED_LEN - 2 ; i++ ) + acct_str[i] = ' '; + + i = NEW_PW_FORMAT_SPACE_PADDED_LEN - 2; + acct_str[i++] = ']'; + acct_str[i++] = '\0'; + + return acct_str; +} diff --git a/source4/lib/smbrun.c b/source4/lib/smbrun.c new file mode 100644 index 0000000000..acb836ba7a --- /dev/null +++ b/source4/lib/smbrun.c @@ -0,0 +1,171 @@ +/* + Unix SMB/CIFS implementation. + run a command as a specified user + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* need to move this from here!! need some sleep ... */ +struct current_user current_user; + +/**************************************************************************** +This is a utility function of smbrun(). +****************************************************************************/ + +static int setup_out_fd(void) +{ + int fd; + pstring path; + + slprintf(path, sizeof(path)-1, "%s/smb.XXXXXX", tmpdir()); + + /* now create the file */ + fd = smb_mkstemp(path); + + if (fd == -1) { + DEBUG(0,("setup_out_fd: Failed to create file %s. (%s)\n", + path, strerror(errno) )); + return -1; + } + + DEBUG(10,("setup_out_fd: Created tmp file %s\n", path )); + + /* Ensure file only kept around by open fd. */ + unlink(path); + return fd; +} + +/**************************************************************************** +run a command being careful about uid/gid handling and putting the output in +outfd (or discard it if outfd is NULL). +****************************************************************************/ + +int smbrun(char *cmd, int *outfd) +{ + pid_t pid; + uid_t uid = current_user.uid; + gid_t gid = current_user.gid; + + /* + * Lose any kernel oplock capabilities we may have. + */ + oplock_set_capability(False, False); + + /* point our stdout at the file we want output to go into */ + + if (outfd && ((*outfd = setup_out_fd()) == -1)) { + return -1; + } + + /* in this method we will exec /bin/sh with the correct + arguments, after first setting stdout to point at the file */ + + /* + * We need to temporarily stop CatchChild from eating + * SIGCLD signals as it also eats the exit status code. JRA. + */ + + CatchChildLeaveStatus(); + + if ((pid=fork()) < 0) { + DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) )); + CatchChild(); + if (outfd) { + close(*outfd); + *outfd = -1; + } + return errno; + } + + if (pid) { + /* + * Parent. + */ + int status=0; + pid_t wpid; + + + /* the parent just waits for the child to exit */ + while((wpid = sys_waitpid(pid,&status,0)) < 0) { + if(errno == EINTR) { + errno = 0; + continue; + } + break; + } + + CatchChild(); + + if (wpid != pid) { + DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno))); + if (outfd) { + close(*outfd); + *outfd = -1; + } + return -1; + } + + /* Reset the seek pointer. */ + if (outfd) { + sys_lseek(*outfd, 0, SEEK_SET); + } + +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } +#endif + + return status; + } + + CatchChild(); + + /* we are in the child. we exec /bin/sh to do the work for us. we + don't directly exec the command we want because it may be a + pipeline or anything else the config file specifies */ + + /* point our stdout at the file we want output to go into */ + if (outfd) { + close(1); + if (sys_dup2(*outfd,1) != 1) { + DEBUG(2,("Failed to create stdout file descriptor\n")); + close(*outfd); + exit(80); + } + } + + /* now completely lose our privileges. This is a fairly paranoid + way of doing it, but it does work on all systems that I know of */ + + become_user_permanently(uid, gid); + + if (getuid() != uid || geteuid() != uid || + getgid() != gid || getegid() != gid) { + /* we failed to lose our privileges - do not execute + the command */ + exit(81); /* we can't print stuff at this stage, + instead use exit codes for debugging */ + } + + execl("/bin/sh","sh","-c",cmd,NULL); + + /* not reached */ + exit(82); + return 1; +} diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c new file mode 100644 index 0000000000..1eae2f09b9 --- /dev/null +++ b/source4/lib/snprintf.c @@ -0,0 +1,978 @@ +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + **************************************************************/ + +#ifndef NO_CONFIG_H /* for some tests */ +#include "config.h" +#else +#define NULL 0 +#endif + +#ifdef TEST_SNPRINTF /* need math library headers for testing */ +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include + /* make the compiler happy with an empty file */ + void dummy_snprintf(void) {} +#else + +#ifdef HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#endif + +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + +static size_t dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + va_list args; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10*min + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } else { + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, LLONG); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (long)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (!strvalue) strvalue = "(NULL)"; + if (max == -1) { + max = strlen(strvalue); + } + if (min > 0 && max >= 0 && min > max) max = min; + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { + long int *num; + num = va_arg (args, long int *); + *num = (long int)currlen; + } else if (cflags == DP_C_LLONG) { + LLONG *num; + num = va_arg (args, LLONG *); + *num = (LLONG)currlen; + } else { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + + return currlen; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = ""; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + long l; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int index; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 16 digits past the decimal because of our + * conversion method + */ + if (max > 16) + max = 16; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + index = (int) ((temp -intpart +0.05)* 10.0); + /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, index); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + index = (int) ((temp -fracpart +0.05)* 10.0); + /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +/* yes this really must be a ||. Don't muck wiith this (tridge) + * + * The logic for these two is that we need our own definition if the + * OS *either* has no definition of *sprintf, or if it does have one + * that doesn't work properly according to the autoconf test. Perhaps + * these should really be smb_snprintf to avoid conflicts with buggy + * linkers? -- mbp + */ +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF) + int snprintf(char *str,size_t count,const char *fmt,...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#endif + +#ifndef HAVE_VASPRINTF + int vasprintf(char **ptr, const char *format, va_list ap) +{ + int ret; + va_list ap2; + + VA_COPY(ap2, ap); + + ret = vsnprintf(NULL, 0, format, ap2); + if (ret <= 0) return ret; + + (*ptr) = (char *)malloc(ret+1); + if (!*ptr) return -1; + + VA_COPY(ap2, ap); + + ret = vsnprintf(*ptr, ret+1, format, ap2); + + return ret; +} +#endif + + +#ifndef HAVE_ASPRINTF + int asprintf(char **ptr, const char *format, ...) +{ + va_list ap; + int ret; + + *ptr = NULL; + va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + int sprintf(char *str,const char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "-16.16f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 5.030201, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + char *str_fmt[] = { + "10.5s", + "5.10s", + "10.1s", + "0.10s", + "10.0s", + "1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + fp_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + int_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); + int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + sprintf (buf2, str_fmt[x], str_vals[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + str_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); + fail++; + } + num++; + } + } + + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + double p = pow(10, x); + double r = v0*p; + snprintf(buf1, sizeof(buf1), "%1.1f", r); + sprintf(buf2, "%1.1f", r); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* SNPRINTF_TEST */ diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c new file mode 100644 index 0000000000..4e4f0bc040 --- /dev/null +++ b/source4/lib/substitute.c @@ -0,0 +1,188 @@ +/* + Unix SMB/CIFS implementation. + string substitution functions + Copyright (C) Andrew Tridgell 1992-2000 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +/* oh bugger - I realy didn't want to have a top-level context + anywhere, but until we change all lp_*() calls to take a context + argument this is needed */ +static struct substitute_context *sub; + +void sub_set_context(struct substitute_context *subptr) +{ + sub = subptr; +} + +/* + setup a string in the negotiate structure, using alpha_strcpy with SAFE_NETBIOS_CHARS +*/ +static void setup_string(char **dest, const char *str) +{ + char *s; + + s = strdup(str); + if (!s) { + return; + } + + alpha_strcpy(s, str, SAFE_NETBIOS_CHARS, strlen(s)+1); + + trim_string(s," "," "); + strlower(s); + + SAFE_FREE(*dest); + (*dest) = s; +} + +void sub_set_local_machine(const char *local_machine) +{ + if (!sub) return; + setup_string(&sub->local_machine, local_machine); +} + +void sub_set_remote_machine(const char *remote_machine) +{ + if (!sub) return; + setup_string(&sub->remote_machine, remote_machine); +} + +void sub_set_remote_proto(const char *str) +{ + if (!sub) return; + setup_string(&sub->remote_proto, str); +} + +void sub_set_remote_arch(const char *str) +{ + if (!sub) return; + setup_string(&sub->remote_arch, str); +} + +const char *sub_get_remote_machine(void) +{ + if (!sub) return "UNKNOWN"; + return sub->remote_machine; +} + +const char *sub_get_local_machine(void) +{ + if (!sub) return "UNKNOWN"; + return sub->local_machine; +} + + +/* + setup the string used by %U substitution +*/ +void sub_set_user_name(const char *name) +{ + if (!sub) return; + setup_string(&sub->user_name, name); +} + +/**************************************************************************** +FOO +****************************************************************************/ +void standard_sub_basic(char *str,size_t len) +{ +} + +/**************************************************************************** + Do some standard substitutions in a string. + This function will return an allocated string that have to be freed. +****************************************************************************/ +char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str) +{ + return talloc_strdup(mem_ctx, str); +} + +char *alloc_sub_basic(const char *smb_name, const char *str) +{ + return strdup(str); +} + +/**************************************************************************** + Do some specific substitutions in a string. + This function will return an allocated string that have to be freed. +****************************************************************************/ + +char *talloc_sub_specified(TALLOC_CTX *mem_ctx, + const char *input_string, + const char *username, + const char *domain, + uid_t uid, + gid_t gid) +{ + return talloc_strdup(mem_ctx, input_string); +} + +char *alloc_sub_specified(const char *input_string, + const char *username, + const char *domain, + uid_t uid, + gid_t gid) +{ + return strdup(input_string); +} + +char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, + int snum, + const char *user, + const char *connectpath, + gid_t gid, + const char *smb_name, + char *str) +{ + return talloc_strdup(mem_ctx, str); +} + +char *alloc_sub_advanced(int snum, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, char *str) +{ + return strdup(str); +} + +/**************************************************************************** + Do some standard substitutions in a string. +****************************************************************************/ + +void standard_sub_conn(struct tcon_context *conn, char *str, size_t len) +{ +} + +char *talloc_sub_conn(TALLOC_CTX *mem_ctx, struct tcon_context *conn, char *str) +{ + return talloc_strdup(mem_ctx, str); +} + +char *alloc_sub_conn(struct tcon_context *conn, char *str) +{ + return strdup(str); +} + +/**************************************************************************** + Like standard_sub but by snum. +****************************************************************************/ + +void standard_sub_snum(int snum, char *str, size_t len) +{ +} diff --git a/source4/lib/sysacls.c b/source4/lib/sysacls.c new file mode 100644 index 0000000000..fe85b9e72f --- /dev/null +++ b/source4/lib/sysacls.c @@ -0,0 +1,3198 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities for ACL support. + Copyright (C) Jeremy Allison 2000. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This file wraps all differing system ACL interfaces into a consistent + one based on the POSIX interface. It also returns the correct errors + for older UNIX systems that don't support ACLs. + + The interfaces that each ACL implementation must support are as follows : + + int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) + int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) + int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p + void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) + SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) + SMB_ACL_T sys_acl_get_fd(int fd) + int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset); + int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); + char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) + SMB_ACL_T sys_acl_init( int count) + int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) + int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) + int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) + int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) + int sys_acl_valid( SMB_ACL_T theacl ) + int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) + int sys_acl_set_fd( int fd, SMB_ACL_T theacl) + int sys_acl_delete_def_file(const char *path) + + This next one is not POSIX complient - but we *have* to have it ! + More POSIX braindamage. + + int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) + + The generic POSIX free is the following call. We split this into + several different free functions as we may need to add tag info + to structures when emulating the POSIX interface. + + int sys_acl_free( void *obj_p) + + The calls we actually use are : + + int sys_acl_free_text(char *text) - free acl_to_text + int sys_acl_free_acl(SMB_ACL_T posix_acl) + int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype) + +*/ + +#if defined(HAVE_POSIX_ACLS) + +/* Identity mapping - easy. */ + +int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + return acl_get_entry( the_acl, entry_id, entry_p); +} + +int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + return acl_get_tag_type( entry_d, tag_type_p); +} + +int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + return acl_get_permset( entry_d, permset_p); +} + +void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +{ + return acl_get_qualifier( entry_d); +} + +SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +{ + return acl_get_file( path_p, type); +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + return acl_get_fd(fd); +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +{ + return acl_clear_perms(permset); +} + +int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return acl_add_perm(permset, perm); +} + +int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ +#if defined(HAVE_ACL_GET_PERM_NP) + /* + * Required for TrustedBSD-based ACL implementations where + * non-POSIX.1e functions are denoted by a _np (non-portable) + * suffix. + */ + return acl_get_perm_np(permset, perm); +#else + return acl_get_perm(permset, perm); +#endif +} + +char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) +{ + return acl_to_text( the_acl, plen); +} + +SMB_ACL_T sys_acl_init( int count) +{ + return acl_init(count); +} + +int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + return acl_create_entry(pacl, pentry); +} + +int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + return acl_set_tag_type(entry, tagtype); +} + +int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +{ + return acl_set_qualifier(entry, qual); +} + +int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + return acl_set_permset(entry, permset); +} + +int sys_acl_valid( SMB_ACL_T theacl ) +{ + return acl_valid(theacl); +} + +int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + return acl_set_file(name, acltype, theacl); +} + +int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +{ + return acl_set_fd(fd, theacl); +} + +int sys_acl_delete_def_file(const char *name) +{ + return acl_delete_def_file(name); +} + +int sys_acl_free_text(char *text) +{ + return acl_free(text); +} + +int sys_acl_free_acl(SMB_ACL_T the_acl) +{ + return acl_free(the_acl); +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return acl_free(qual); +} + +#elif defined(HAVE_TRU64_ACLS) +/* + * The interface to DEC/Compaq Tru64 UNIX ACLs + * is based on Draft 13 of the POSIX spec which is + * slightly different from the Draft 16 interface. + * + * Also, some of the permset manipulation functions + * such as acl_clear_perm() and acl_add_perm() appear + * to be broken on Tru64 so we have to manipulate + * the permission bits in the permset directly. + */ +int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + SMB_ACL_ENTRY_T entry; + + if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) { + return -1; + } + + errno = 0; + if ((entry = acl_get_entry(the_acl)) != NULL) { + *entry_p = entry; + return 1; + } + + return errno ? -1 : 0; +} + +int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + return acl_get_tag_type( entry_d, tag_type_p); +} + +int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + return acl_get_permset( entry_d, permset_p); +} + +void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +{ + return acl_get_qualifier( entry_d); +} + +SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +{ + return acl_get_file((char *)path_p, type); +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + return acl_get_fd(fd, ACL_TYPE_ACCESS); +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +{ + *permset = 0; /* acl_clear_perm() is broken on Tru64 */ + + return 0; +} + +int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) { + errno = EINVAL; + return -1; + } + + *permset |= perm; /* acl_add_perm() is broken on Tru64 */ + + return 0; +} + +int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return *permset & perm; /* Tru64 doesn't have acl_get_perm() */ +} + +char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) +{ + return acl_to_text( the_acl, plen); +} + +SMB_ACL_T sys_acl_init( int count) +{ + return acl_init(count); +} + +int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + SMB_ACL_ENTRY_T entry; + + if ((entry = acl_create_entry(pacl)) == NULL) { + return -1; + } + + *pentry = entry; + return 0; +} + +int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + return acl_set_tag_type(entry, tagtype); +} + +int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +{ + return acl_set_qualifier(entry, qual); +} + +int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + return acl_set_permset(entry, permset); +} + +int sys_acl_valid( SMB_ACL_T theacl ) +{ + acl_entry_t entry; + + return acl_valid(theacl, &entry); +} + +int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + return acl_set_file((char *)name, acltype, theacl); +} + +int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +{ + return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl); +} + +int sys_acl_delete_def_file(const char *name) +{ + return acl_delete_def_file((char *)name); +} + +int sys_acl_free_text(char *text) +{ + /* + * (void) cast and explicit return 0 are for DEC UNIX + * which just #defines acl_free_text() to be free() + */ + (void) acl_free_text(text); + return 0; +} + +int sys_acl_free_acl(SMB_ACL_T the_acl) +{ + return acl_free(the_acl); +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return acl_free_qualifier(qual, tagtype); +} + +#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) + +/* + * Donated by Michael Davidson for UnixWare / OpenUNIX. + * Modified by Toomas Soome for Solaris. + */ + +/* + * Note that while this code implements sufficient functionality + * to support the sys_acl_* interfaces it does not provide all + * of the semantics of the POSIX ACL interfaces. + * + * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned + * from a call to sys_acl_get_entry() should not be assumed to be + * valid after calling any of the following functions, which may + * reorder the entries in the ACL. + * + * sys_acl_valid() + * sys_acl_set_file() + * sys_acl_set_fd() + */ + +/* + * The only difference between Solaris and UnixWare / OpenUNIX is + * that the #defines for the ACL operations have different names + */ +#if defined(HAVE_UNIXWARE_ACLS) + +#define SETACL ACL_SET +#define GETACL ACL_GET +#define GETACLCNT ACL_CNT + +#endif + + +int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { + errno = EINVAL; + return -1; + } + + if (entry_p == NULL) { + errno = EINVAL; + return -1; + } + + if (entry_id == SMB_ACL_FIRST_ENTRY) { + acl_d->next = 0; + } + + if (acl_d->next < 0) { + errno = EINVAL; + return -1; + } + + if (acl_d->next >= acl_d->count) { + return 0; + } + + *entry_p = &acl_d->acl[acl_d->next++]; + + return 1; +} + +int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) +{ + *type_p = entry_d->a_type; + + return 0; +} + +int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + *permset_p = &entry_d->a_perm; + + return 0; +} + +void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) +{ + if (entry_d->a_type != SMB_ACL_USER + && entry_d->a_type != SMB_ACL_GROUP) { + errno = EINVAL; + return NULL; + } + + return &entry_d->a_id; +} + +/* + * There is no way of knowing what size the ACL returned by + * GETACL will be unless you first call GETACLCNT which means + * making an additional system call. + * + * In the hope of avoiding the cost of the additional system + * call in most cases, we initially allocate enough space for + * an ACL with INITIAL_ACL_SIZE entries. If this turns out to + * be too small then we use GETACLCNT to find out the actual + * size, reallocate the ACL buffer, and then call GETACL again. + */ + +#define INITIAL_ACL_SIZE 16 + +SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) +{ + SMB_ACL_T acl_d; + int count; /* # of ACL entries allocated */ + int naccess; /* # of access ACL entries */ + int ndefault; /* # of default ACL entries */ + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + errno = EINVAL; + return NULL; + } + + count = INITIAL_ACL_SIZE; + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + + /* + * If there isn't enough space for the ACL entries we use + * GETACLCNT to determine the actual number of ACL entries + * reallocate and try again. This is in a loop because it + * is possible that someone else could modify the ACL and + * increase the number of entries between the call to + * GETACLCNT and the call to GETACL. + */ + while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0 + && errno == ENOSPC) { + + sys_acl_free_acl(acl_d); + + if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) { + return NULL; + } + + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + } + + if (count < 0) { + sys_acl_free_acl(acl_d); + return NULL; + } + + /* + * calculate the number of access and default ACL entries + * + * Note: we assume that the acl() system call returned a + * well formed ACL which is sorted so that all of the + * access ACL entries preceed any default ACL entries + */ + for (naccess = 0; naccess < count; naccess++) { + if (acl_d->acl[naccess].a_type & ACL_DEFAULT) + break; + } + ndefault = count - naccess; + + /* + * if the caller wants the default ACL we have to copy + * the entries down to the start of the acl[] buffer + * and mask out the ACL_DEFAULT flag from the type field + */ + if (type == SMB_ACL_TYPE_DEFAULT) { + int i, j; + + for (i = 0, j = naccess; i < ndefault; i++, j++) { + acl_d->acl[i] = acl_d->acl[j]; + acl_d->acl[i].a_type &= ~ACL_DEFAULT; + } + + acl_d->count = ndefault; + } else { + acl_d->count = naccess; + } + + return acl_d; +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + SMB_ACL_T acl_d; + int count; /* # of ACL entries allocated */ + int naccess; /* # of access ACL entries */ + + count = INITIAL_ACL_SIZE; + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + + while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0 + && errno == ENOSPC) { + + sys_acl_free_acl(acl_d); + + if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) { + return NULL; + } + + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + } + + if (count < 0) { + sys_acl_free_acl(acl_d); + return NULL; + } + + /* + * calculate the number of access ACL entries + */ + for (naccess = 0; naccess < count; naccess++) { + if (acl_d->acl[naccess].a_type & ACL_DEFAULT) + break; + } + + acl_d->count = naccess; + + return acl_d; +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) +{ + *permset_d = 0; + + return 0; +} + +int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE + && perm != SMB_ACL_EXECUTE) { + errno = EINVAL; + return -1; + } + + if (permset_d == NULL) { + errno = EINVAL; + return -1; + } + + *permset_d |= perm; + + return 0; +} + +int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + return *permset_d & perm; +} + +char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) +{ + int i; + int len, maxlen; + char *text; + + /* + * use an initial estimate of 20 bytes per ACL entry + * when allocating memory for the text representation + * of the ACL + */ + len = 0; + maxlen = 20 * acl_d->count; + if ((text = malloc(maxlen)) == NULL) { + errno = ENOMEM; + return NULL; + } + + for (i = 0; i < acl_d->count; i++) { + struct acl *ap = &acl_d->acl[i]; + struct passwd *pw; + struct group *gr; + char tagbuf[12]; + char idbuf[12]; + char *tag; + char *id = ""; + char perms[4]; + int nbytes; + + switch (ap->a_type) { + /* + * for debugging purposes it's probably more + * useful to dump unknown tag types rather + * than just returning an error + */ + default: + slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", + ap->a_type); + tag = tagbuf; + slprintf(idbuf, sizeof(idbuf)-1, "%ld", + (long)ap->a_id); + id = idbuf; + break; + + case SMB_ACL_USER: + id = uidtoname(ap->a_id); + case SMB_ACL_USER_OBJ: + tag = "user"; + break; + + case SMB_ACL_GROUP: + if ((gr = getgrgid(ap->a_id)) == NULL) { + slprintf(idbuf, sizeof(idbuf)-1, "%ld", + (long)ap->a_id); + id = idbuf; + } else { + id = gr->gr_name; + } + case SMB_ACL_GROUP_OBJ: + tag = "group"; + break; + + case SMB_ACL_OTHER: + tag = "other"; + break; + + case SMB_ACL_MASK: + tag = "mask"; + break; + + } + + perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; + perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; + perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; + perms[3] = '\0'; + + /* : : rwx \n \0 */ + nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; + + /* + * If this entry would overflow the buffer + * allocate enough additional memory for this + * entry and an estimate of another 20 bytes + * for each entry still to be processed + */ + if ((len + nbytes) > maxlen) { + char *oldtext = text; + + maxlen += nbytes + 20 * (acl_d->count - i); + + if ((text = Realloc(oldtext, maxlen)) == NULL) { + SAFE_FREE(oldtext); + errno = ENOMEM; + return NULL; + } + } + + slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); + len += nbytes - 1; + } + + if (len_p) + *len_p = len; + + return text; +} + +SMB_ACL_T sys_acl_init(int count) +{ + SMB_ACL_T a; + + if (count < 0) { + errno = EINVAL; + return NULL; + } + + /* + * note that since the definition of the structure pointed + * to by the SMB_ACL_T includes the first element of the + * acl[] array, this actually allocates an ACL with room + * for (count+1) entries + */ + if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) { + errno = ENOMEM; + return NULL; + } + + a->size = count + 1; + a->count = 0; + a->next = -1; + + return a; +} + + +int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) +{ + SMB_ACL_T acl_d; + SMB_ACL_ENTRY_T entry_d; + + if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { + errno = EINVAL; + return -1; + } + + if (acl_d->count >= acl_d->size) { + errno = ENOSPC; + return -1; + } + + entry_d = &acl_d->acl[acl_d->count++]; + entry_d->a_type = 0; + entry_d->a_id = -1; + entry_d->a_perm = 0; + *entry_p = entry_d; + + return 0; +} + +int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) +{ + switch (tag_type) { + case SMB_ACL_USER: + case SMB_ACL_USER_OBJ: + case SMB_ACL_GROUP: + case SMB_ACL_GROUP_OBJ: + case SMB_ACL_OTHER: + case SMB_ACL_MASK: + entry_d->a_type = tag_type; + break; + default: + errno = EINVAL; + return -1; + } + + return 0; +} + +int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) +{ + if (entry_d->a_type != SMB_ACL_GROUP + && entry_d->a_type != SMB_ACL_USER) { + errno = EINVAL; + return -1; + } + + entry_d->a_id = *((id_t *)qual_p); + + return 0; +} + +int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) +{ + if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { + return EINVAL; + } + + entry_d->a_perm = *permset_d; + + return 0; +} + +/* + * sort the ACL and check it for validity + * + * if it's a minimal ACL with only 4 entries then we + * need to recalculate the mask permissions to make + * sure that they are the same as the GROUP_OBJ + * permissions as required by the UnixWare acl() system call. + * + * (note: since POSIX allows minimal ACLs which only contain + * 3 entries - ie there is no mask entry - we should, in theory, + * check for this and add a mask entry if necessary - however + * we "know" that the caller of this interface always specifies + * a mask so, in practice "this never happens" (tm) - if it *does* + * happen aclsort() will fail and return an error and someone will + * have to fix it ...) + */ + +static int acl_sort(SMB_ACL_T acl_d) +{ + int fixmask = (acl_d->count <= 4); + + if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) { + errno = EINVAL; + return -1; + } + return 0; +} + +int sys_acl_valid(SMB_ACL_T acl_d) +{ + return acl_sort(acl_d); +} + +int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) +{ + struct stat s; + struct acl *acl_p; + int acl_count; + struct acl *acl_buf = NULL; + int ret; + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + errno = EINVAL; + return -1; + } + + if (acl_sort(acl_d) != 0) { + return -1; + } + + acl_p = &acl_d->acl[0]; + acl_count = acl_d->count; + + /* + * if it's a directory there is extra work to do + * since the acl() system call will replace both + * the access ACLs and the default ACLs (if any) + */ + if (stat(name, &s) != 0) { + return -1; + } + if (S_ISDIR(s.st_mode)) { + SMB_ACL_T acc_acl; + SMB_ACL_T def_acl; + SMB_ACL_T tmp_acl; + int i; + + if (type == SMB_ACL_TYPE_ACCESS) { + acc_acl = acl_d; + def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); + + } else { + def_acl = acl_d; + acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); + } + + if (tmp_acl == NULL) { + return -1; + } + + /* + * allocate a temporary buffer for the complete ACL + */ + acl_count = acc_acl->count + def_acl->count; + acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0])); + + if (acl_buf == NULL) { + sys_acl_free_acl(tmp_acl); + errno = ENOMEM; + return -1; + } + + /* + * copy the access control and default entries into the buffer + */ + memcpy(&acl_buf[0], &acc_acl->acl[0], + acc_acl->count * sizeof(acl_buf[0])); + + memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], + def_acl->count * sizeof(acl_buf[0])); + + /* + * set the ACL_DEFAULT flag on the default entries + */ + for (i = acc_acl->count; i < acl_count; i++) { + acl_buf[i].a_type |= ACL_DEFAULT; + } + + sys_acl_free_acl(tmp_acl); + + } else if (type != SMB_ACL_TYPE_ACCESS) { + errno = EINVAL; + return -1; + } + + ret = acl(name, SETACL, acl_count, acl_p); + + SAFE_FREE(acl_buf); + + return ret; +} + +int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) +{ + if (acl_sort(acl_d) != 0) { + return -1; + } + + return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]); +} + +int sys_acl_delete_def_file(const char *path) +{ + SMB_ACL_T acl_d; + int ret; + + /* + * fetching the access ACL and rewriting it has + * the effect of deleting the default ACL + */ + if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { + return -1; + } + + ret = acl(path, SETACL, acl_d->count, acl_d->acl); + + sys_acl_free_acl(acl_d); + + return ret; +} + +int sys_acl_free_text(char *text) +{ + SAFE_FREE(text); + return 0; +} + +int sys_acl_free_acl(SMB_ACL_T acl_d) +{ + SAFE_FREE(acl_d); + return 0; +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return 0; +} + +#elif defined(HAVE_HPUX_ACLS) +#include + +/* + * Based on the Solaris/SCO code - with modifications. + */ + +/* + * Note that while this code implements sufficient functionality + * to support the sys_acl_* interfaces it does not provide all + * of the semantics of the POSIX ACL interfaces. + * + * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned + * from a call to sys_acl_get_entry() should not be assumed to be + * valid after calling any of the following functions, which may + * reorder the entries in the ACL. + * + * sys_acl_valid() + * sys_acl_set_file() + * sys_acl_set_fd() + */ + +/* This checks if the POSIX ACL system call is defined */ +/* which basically corresponds to whether JFS 3.3 or */ +/* higher is installed. If acl() was called when it */ +/* isn't defined, it causes the process to core dump */ +/* so it is important to check this and avoid acl() */ +/* calls if it isn't there. */ + +static BOOL hpux_acl_call_presence(void) +{ + + shl_t handle = NULL; + void *value; + int ret_val=0; + //static BOOL already_checked=0; + // REWRITE: add this back in?? + //if(already_checked) + // return True; + + + ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); + + if(ret_val != 0) { + DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n", + ret_val, errno, strerror(errno))); + DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); + return False; + } + + DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n")); + + already_checked = True; + return True; +} + +int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { + errno = EINVAL; + return -1; + } + + if (entry_p == NULL) { + errno = EINVAL; + return -1; + } + + if (entry_id == SMB_ACL_FIRST_ENTRY) { + acl_d->next = 0; + } + + if (acl_d->next < 0) { + errno = EINVAL; + return -1; + } + + if (acl_d->next >= acl_d->count) { + return 0; + } + + *entry_p = &acl_d->acl[acl_d->next++]; + + return 1; +} + +int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) +{ + *type_p = entry_d->a_type; + + return 0; +} + +int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + *permset_p = &entry_d->a_perm; + + return 0; +} + +void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) +{ + if (entry_d->a_type != SMB_ACL_USER + && entry_d->a_type != SMB_ACL_GROUP) { + errno = EINVAL; + return NULL; + } + + return &entry_d->a_id; +} + +/* + * There is no way of knowing what size the ACL returned by + * ACL_GET will be unless you first call ACL_CNT which means + * making an additional system call. + * + * In the hope of avoiding the cost of the additional system + * call in most cases, we initially allocate enough space for + * an ACL with INITIAL_ACL_SIZE entries. If this turns out to + * be too small then we use ACL_CNT to find out the actual + * size, reallocate the ACL buffer, and then call ACL_GET again. + */ + +#define INITIAL_ACL_SIZE 16 + +SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) +{ + SMB_ACL_T acl_d; + int count; /* # of ACL entries allocated */ + int naccess; /* # of access ACL entries */ + int ndefault; /* # of default ACL entries */ + + if(hpux_acl_call_presence() == False) { + /* Looks like we don't have the acl() system call on HPUX. + * May be the system doesn't have the latest version of JFS. + */ + return NULL; + } + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + errno = EINVAL; + return NULL; + } + + count = INITIAL_ACL_SIZE; + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + + /* + * If there isn't enough space for the ACL entries we use + * ACL_CNT to determine the actual number of ACL entries + * reallocate and try again. This is in a loop because it + * is possible that someone else could modify the ACL and + * increase the number of entries between the call to + * ACL_CNT and the call to ACL_GET. + */ + while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) { + + sys_acl_free_acl(acl_d); + + if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) { + return NULL; + } + + if ((acl_d = sys_acl_init(count)) == NULL) { + return NULL; + } + } + + if (count < 0) { + sys_acl_free_acl(acl_d); + return NULL; + } + + /* + * calculate the number of access and default ACL entries + * + * Note: we assume that the acl() system call returned a + * well formed ACL which is sorted so that all of the + * access ACL entries preceed any default ACL entries + */ + for (naccess = 0; naccess < count; naccess++) { + if (acl_d->acl[naccess].a_type & ACL_DEFAULT) + break; + } + ndefault = count - naccess; + + /* + * if the caller wants the default ACL we have to copy + * the entries down to the start of the acl[] buffer + * and mask out the ACL_DEFAULT flag from the type field + */ + if (type == SMB_ACL_TYPE_DEFAULT) { + int i, j; + + for (i = 0, j = naccess; i < ndefault; i++, j++) { + acl_d->acl[i] = acl_d->acl[j]; + acl_d->acl[i].a_type &= ~ACL_DEFAULT; + } + + acl_d->count = ndefault; + } else { + acl_d->count = naccess; + } + + return acl_d; +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + /* + * HPUX doesn't have the facl call. Fake it using the path.... JRA. + */ + + files_struct *fsp = file_find_fd(fd); + + if (fsp == NULL) { + errno = EBADF; + return NULL; + } + + /* + * We know we're in the same conn context. So we + * can use the relative path. + */ + + return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) +{ + *permset_d = 0; + + return 0; +} + +int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE + && perm != SMB_ACL_EXECUTE) { + errno = EINVAL; + return -1; + } + + if (permset_d == NULL) { + errno = EINVAL; + return -1; + } + + *permset_d |= perm; + + return 0; +} + +int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + return *permset_d & perm; +} + +char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) +{ + int i; + int len, maxlen; + char *text; + + /* + * use an initial estimate of 20 bytes per ACL entry + * when allocating memory for the text representation + * of the ACL + */ + len = 0; + maxlen = 20 * acl_d->count; + if ((text = malloc(maxlen)) == NULL) { + errno = ENOMEM; + return NULL; + } + + for (i = 0; i < acl_d->count; i++) { + struct acl *ap = &acl_d->acl[i]; + struct passwd *pw; + struct group *gr; + char tagbuf[12]; + char idbuf[12]; + char *tag; + char *id = ""; + char perms[4]; + int nbytes; + + switch (ap->a_type) { + /* + * for debugging purposes it's probably more + * useful to dump unknown tag types rather + * than just returning an error + */ + default: + slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", + ap->a_type); + tag = tagbuf; + slprintf(idbuf, sizeof(idbuf)-1, "%ld", + (long)ap->a_id); + id = idbuf; + break; + + case SMB_ACL_USER: + id = uidtoname(ap->a_id); + case SMB_ACL_USER_OBJ: + tag = "user"; + break; + + case SMB_ACL_GROUP: + if ((gr = getgrgid(ap->a_id)) == NULL) { + slprintf(idbuf, sizeof(idbuf)-1, "%ld", + (long)ap->a_id); + id = idbuf; + } else { + id = gr->gr_name; + } + case SMB_ACL_GROUP_OBJ: + tag = "group"; + break; + + case SMB_ACL_OTHER: + tag = "other"; + break; + + case SMB_ACL_MASK: + tag = "mask"; + break; + + } + + perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; + perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; + perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; + perms[3] = '\0'; + + /* : : rwx \n \0 */ + nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; + + /* + * If this entry would overflow the buffer + * allocate enough additional memory for this + * entry and an estimate of another 20 bytes + * for each entry still to be processed + */ + if ((len + nbytes) > maxlen) { + char *oldtext = text; + + maxlen += nbytes + 20 * (acl_d->count - i); + + if ((text = Realloc(oldtext, maxlen)) == NULL) { + free(oldtext); + errno = ENOMEM; + return NULL; + } + } + + slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); + len += nbytes - 1; + } + + if (len_p) + *len_p = len; + + return text; +} + +SMB_ACL_T sys_acl_init(int count) +{ + SMB_ACL_T a; + + if (count < 0) { + errno = EINVAL; + return NULL; + } + + /* + * note that since the definition of the structure pointed + * to by the SMB_ACL_T includes the first element of the + * acl[] array, this actually allocates an ACL with room + * for (count+1) entries + */ + if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) { + errno = ENOMEM; + return NULL; + } + + a->size = count + 1; + a->count = 0; + a->next = -1; + + return a; +} + + +int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) +{ + SMB_ACL_T acl_d; + SMB_ACL_ENTRY_T entry_d; + + if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { + errno = EINVAL; + return -1; + } + + if (acl_d->count >= acl_d->size) { + errno = ENOSPC; + return -1; + } + + entry_d = &acl_d->acl[acl_d->count++]; + entry_d->a_type = 0; + entry_d->a_id = -1; + entry_d->a_perm = 0; + *entry_p = entry_d; + + return 0; +} + +int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) +{ + switch (tag_type) { + case SMB_ACL_USER: + case SMB_ACL_USER_OBJ: + case SMB_ACL_GROUP: + case SMB_ACL_GROUP_OBJ: + case SMB_ACL_OTHER: + case SMB_ACL_MASK: + entry_d->a_type = tag_type; + break; + default: + errno = EINVAL; + return -1; + } + + return 0; +} + +int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) +{ + if (entry_d->a_type != SMB_ACL_GROUP + && entry_d->a_type != SMB_ACL_USER) { + errno = EINVAL; + return -1; + } + + entry_d->a_id = *((id_t *)qual_p); + + return 0; +} + +int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) +{ + if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { + return EINVAL; + } + + entry_d->a_perm = *permset_d; + + return 0; +} + +/* Structure to capture the count for each type of ACE. */ + +struct hpux_acl_types { + int n_user; + int n_def_user; + int n_user_obj; + int n_def_user_obj; + + int n_group; + int n_def_group; + int n_group_obj; + int n_def_group_obj; + + int n_other; + int n_other_obj; + int n_def_other_obj; + + int n_class_obj; + int n_def_class_obj; + + int n_illegal_obj; +}; + +/* count_obj: + * Counts the different number of objects in a given array of ACL + * structures. + * Inputs: + * + * acl_count - Count of ACLs in the array of ACL strucutres. + * aclp - Array of ACL structures. + * acl_type_count - Pointer to acl_types structure. Should already be + * allocated. + * Output: + * + * acl_type_count - This structure is filled up with counts of various + * acl types. + */ + +static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count) +{ + int i; + + memset(acl_type_count, 0, sizeof(struct hpux_acl_types)); + + for(i=0;in_user++; + break; + case USER_OBJ: + acl_type_count->n_user_obj++; + break; + case DEF_USER_OBJ: + acl_type_count->n_def_user_obj++; + break; + case GROUP: + acl_type_count->n_group++; + break; + case GROUP_OBJ: + acl_type_count->n_group_obj++; + break; + case DEF_GROUP_OBJ: + acl_type_count->n_def_group_obj++; + break; + case OTHER_OBJ: + acl_type_count->n_other_obj++; + break; + case DEF_OTHER_OBJ: + acl_type_count->n_def_other_obj++; + break; + case CLASS_OBJ: + acl_type_count->n_class_obj++; + break; + case DEF_CLASS_OBJ: + acl_type_count->n_def_class_obj++; + break; + case DEF_USER: + acl_type_count->n_def_user++; + break; + case DEF_GROUP: + acl_type_count->n_def_group++; + break; + default: + acl_type_count->n_illegal_obj++; + break; + } + } +} + +/* swap_acl_entries: Swaps two ACL entries. + * + * Inputs: aclp0, aclp1 - ACL entries to be swapped. + */ + +static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1) +{ + struct acl temp_acl; + + temp_acl.a_type = aclp0->a_type; + temp_acl.a_id = aclp0->a_id; + temp_acl.a_perm = aclp0->a_perm; + + aclp0->a_type = aclp1->a_type; + aclp0->a_id = aclp1->a_id; + aclp0->a_perm = aclp1->a_perm; + + aclp1->a_type = temp_acl.a_type; + aclp1->a_id = temp_acl.a_id; + aclp1->a_perm = temp_acl.a_perm; +} + +/* prohibited_duplicate_type + * Identifies if given ACL type can have duplicate entries or + * not. + * + * Inputs: acl_type - ACL Type. + * + * Outputs: + * + * Return.. + * + * True - If the ACL type matches any of the prohibited types. + * False - If the ACL type doesn't match any of the prohibited types. + */ + +static BOOL hpux_prohibited_duplicate_type(int acl_type) +{ + switch(acl_type) { + case USER: + case GROUP: + case DEF_USER: + case DEF_GROUP: + return True; + default: + return False; + } +} + +/* get_needed_class_perm + * Returns the permissions of a ACL structure only if the ACL + * type matches one of the pre-determined types for computing + * CLASS_OBJ permissions. + * + * Inputs: aclp - Pointer to ACL structure. + */ + +static int hpux_get_needed_class_perm(struct acl *aclp) +{ + switch(aclp->a_type) { + case USER: + case GROUP_OBJ: + case GROUP: + case DEF_USER_OBJ: + case DEF_USER: + case DEF_GROUP_OBJ: + case DEF_GROUP: + case DEF_CLASS_OBJ: + case DEF_OTHER_OBJ: + return aclp->a_perm; + default: + return 0; + } +} + +/* acl_sort for HPUX. + * Sorts the array of ACL structures as per the description in + * aclsort man page. Refer to aclsort man page for more details + * + * Inputs: + * + * acl_count - Count of ACLs in the array of ACL structures. + * calclass - If this is not zero, then we compute the CLASS_OBJ + * permissions. + * aclp - Array of ACL structures. + * + * Outputs: + * + * aclp - Sorted array of ACL structures. + * + * Outputs: + * + * Returns 0 for success -1 for failure. Prints a message to the Samba + * debug log in case of failure. + */ + +static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp) +{ +#if !defined(HAVE_HPUX_ACLSORT) + /* + * The aclsort() system call is availabe on the latest HPUX General + * Patch Bundles. So for HPUX, we developed our version of acl_sort + * function. Because, we don't want to update to a new + * HPUX GR bundle just for aclsort() call. + */ + + struct hpux_acl_types acl_obj_count; + int n_class_obj_perm = 0; + int i, j; + + if(!acl_count) { + DEBUG(10,("Zero acl count passed. Returning Success\n")); + return 0; + } + + if(aclp == NULL) { + DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n")); + return -1; + } + + /* Count different types of ACLs in the ACLs array */ + + hpux_count_obj(acl_count, aclp, &acl_obj_count); + + /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, + * CLASS_OBJ and OTHER_OBJ + */ + + if( (acl_obj_count.n_user_obj != 1) || + (acl_obj_count.n_group_obj != 1) || + (acl_obj_count.n_class_obj != 1) || + (acl_obj_count.n_other_obj != 1) + ) { + DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \ +USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n")); + return -1; + } + + /* If any of the default objects are present, there should be only + * one of them each. + */ + + if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) || + (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) { + DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \ +or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n")); + return -1; + } + + /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl + * structures. + * + * Sorting crieteria - First sort by ACL type. If there are multiple entries of + * same ACL type, sort by ACL id. + * + * I am using the trival kind of sorting method here because, performance isn't + * really effected by the ACLs feature. More over there aren't going to be more + * than 17 entries on HPUX. + */ + + for(i=0; i aclp[j].a_type ) { + /* ACL entries out of order, swap them */ + + hpux_swap_acl_entries((aclp+i), (aclp+j)); + + } else if ( aclp[i].a_type == aclp[j].a_type ) { + + /* ACL entries of same type, sort by id */ + + if(aclp[i].a_id > aclp[j].a_id) { + hpux_swap_acl_entries((aclp+i), (aclp+j)); + } else if (aclp[i].a_id == aclp[j].a_id) { + /* We have a duplicate entry. */ + if(hpux_prohibited_duplicate_type(aclp[i].a_type)) { + DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n", + aclp[i].a_type, aclp[i].a_id)); + return -1; + } + } + + } + } + } + + /* set the class obj permissions to the computed one. */ + if(calclass) { + int n_class_obj_index = -1; + + for(i=0;icount <= 4); + + if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) { + errno = EINVAL; + return -1; + } + return 0; +} + +int sys_acl_valid(SMB_ACL_T acl_d) +{ + return acl_sort(acl_d); +} + +int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) +{ + struct stat s; + struct acl *acl_p; + int acl_count; + struct acl *acl_buf = NULL; + int ret; + + if(hpux_acl_call_presence() == False) { + /* Looks like we don't have the acl() system call on HPUX. + * May be the system doesn't have the latest version of JFS. + */ + errno=ENOSYS; + return -1; + } + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + errno = EINVAL; + return -1; + } + + if (acl_sort(acl_d) != 0) { + return -1; + } + + acl_p = &acl_d->acl[0]; + acl_count = acl_d->count; + + /* + * if it's a directory there is extra work to do + * since the acl() system call will replace both + * the access ACLs and the default ACLs (if any) + */ + if (stat(name, &s) != 0) { + return -1; + } + if (S_ISDIR(s.st_mode)) { + SMB_ACL_T acc_acl; + SMB_ACL_T def_acl; + SMB_ACL_T tmp_acl; + int i; + + if (type == SMB_ACL_TYPE_ACCESS) { + acc_acl = acl_d; + def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); + + } else { + def_acl = acl_d; + acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); + } + + if (tmp_acl == NULL) { + return -1; + } + + /* + * allocate a temporary buffer for the complete ACL + */ + acl_count = acc_acl->count + def_acl->count; + acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0])); + + if (acl_buf == NULL) { + sys_acl_free_acl(tmp_acl); + errno = ENOMEM; + return -1; + } + + /* + * copy the access control and default entries into the buffer + */ + memcpy(&acl_buf[0], &acc_acl->acl[0], + acc_acl->count * sizeof(acl_buf[0])); + + memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], + def_acl->count * sizeof(acl_buf[0])); + + /* + * set the ACL_DEFAULT flag on the default entries + */ + for (i = acc_acl->count; i < acl_count; i++) { + acl_buf[i].a_type |= ACL_DEFAULT; + } + + sys_acl_free_acl(tmp_acl); + + } else if (type != SMB_ACL_TYPE_ACCESS) { + errno = EINVAL; + return -1; + } + + ret = acl(name, ACL_SET, acl_count, acl_p); + + if (acl_buf) { + free(acl_buf); + } + + return ret; +} + +int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) +{ + /* + * HPUX doesn't have the facl call. Fake it using the path.... JRA. + */ + + files_struct *fsp = file_find_fd(fd); + + if (fsp == NULL) { + errno = EBADF; + return NULL; + } + + if (acl_sort(acl_d) != 0) { + return -1; + } + + /* + * We know we're in the same conn context. So we + * can use the relative path. + */ + + return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d); +} + +int sys_acl_delete_def_file(const char *path) +{ + SMB_ACL_T acl_d; + int ret; + + /* + * fetching the access ACL and rewriting it has + * the effect of deleting the default ACL + */ + if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { + return -1; + } + + ret = acl(path, ACL_SET, acl_d->count, acl_d->acl); + + sys_acl_free_acl(acl_d); + + return ret; +} + +int sys_acl_free_text(char *text) +{ + free(text); + return 0; +} + +int sys_acl_free_acl(SMB_ACL_T acl_d) +{ + free(acl_d); + return 0; +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return 0; +} + +#elif defined(HAVE_IRIX_ACLS) + +int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { + errno = EINVAL; + return -1; + } + + if (entry_p == NULL) { + errno = EINVAL; + return -1; + } + + if (entry_id == SMB_ACL_FIRST_ENTRY) { + acl_d->next = 0; + } + + if (acl_d->next < 0) { + errno = EINVAL; + return -1; + } + + if (acl_d->next >= acl_d->aclp->acl_cnt) { + return 0; + } + + *entry_p = &acl_d->aclp->acl_entry[acl_d->next++]; + + return 1; +} + +int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) +{ + *type_p = entry_d->ae_tag; + + return 0; +} + +int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + *permset_p = entry_d; + + return 0; +} + +void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) +{ + if (entry_d->ae_tag != SMB_ACL_USER + && entry_d->ae_tag != SMB_ACL_GROUP) { + errno = EINVAL; + return NULL; + } + + return &entry_d->ae_id; +} + +SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) +{ + SMB_ACL_T a; + + if ((a = malloc(sizeof(*a))) == NULL) { + errno = ENOMEM; + return NULL; + } + if ((a->aclp = acl_get_file(path_p, type)) == NULL) { + SAFE_FREE(a); + return NULL; + } + a->next = -1; + a->freeaclp = True; + return a; +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + SMB_ACL_T a; + + if ((a = malloc(sizeof(*a))) == NULL) { + errno = ENOMEM; + return NULL; + } + if ((a->aclp = acl_get_fd(fd)) == NULL) { + SAFE_FREE(a); + return NULL; + } + a->next = -1; + a->freeaclp = True; + return a; +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) +{ + permset_d->ae_perm = 0; + + return 0; +} + +int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE + && perm != SMB_ACL_EXECUTE) { + errno = EINVAL; + return -1; + } + + if (permset_d == NULL) { + errno = EINVAL; + return -1; + } + + permset_d->ae_perm |= perm; + + return 0; +} + +int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) +{ + return permset_d->ae_perm & perm; +} + +char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) +{ + return acl_to_text(acl_d->aclp, len_p); +} + +SMB_ACL_T sys_acl_init(int count) +{ + SMB_ACL_T a; + + if (count < 0) { + errno = EINVAL; + return NULL; + } + + if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) { + errno = ENOMEM; + return NULL; + } + + a->next = -1; + a->freeaclp = False; + a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *)); + a->aclp->acl_cnt = 0; + + return a; +} + + +int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) +{ + SMB_ACL_T acl_d; + SMB_ACL_ENTRY_T entry_d; + + if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { + errno = EINVAL; + return -1; + } + + if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) { + errno = ENOSPC; + return -1; + } + + entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++]; + entry_d->ae_tag = 0; + entry_d->ae_id = 0; + entry_d->ae_perm = 0; + *entry_p = entry_d; + + return 0; +} + +int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) +{ + switch (tag_type) { + case SMB_ACL_USER: + case SMB_ACL_USER_OBJ: + case SMB_ACL_GROUP: + case SMB_ACL_GROUP_OBJ: + case SMB_ACL_OTHER: + case SMB_ACL_MASK: + entry_d->ae_tag = tag_type; + break; + default: + errno = EINVAL; + return -1; + } + + return 0; +} + +int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) +{ + if (entry_d->ae_tag != SMB_ACL_GROUP + && entry_d->ae_tag != SMB_ACL_USER) { + errno = EINVAL; + return -1; + } + + entry_d->ae_id = *((id_t *)qual_p); + + return 0; +} + +int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) +{ + if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { + return EINVAL; + } + + entry_d->ae_perm = permset_d->ae_perm; + + return 0; +} + +int sys_acl_valid(SMB_ACL_T acl_d) +{ + return acl_valid(acl_d->aclp); +} + +int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) +{ + return acl_set_file(name, type, acl_d->aclp); +} + +int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) +{ + return acl_set_fd(fd, acl_d->aclp); +} + +int sys_acl_delete_def_file(const char *name) +{ + return acl_delete_def_file(name); +} + +int sys_acl_free_text(char *text) +{ + return acl_free(text); +} + +int sys_acl_free_acl(SMB_ACL_T acl_d) +{ + if (acl_d->freeaclp) { + acl_free(acl_d->aclp); + } + acl_free(acl_d); + return 0; +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return 0; +} + +#elif defined(HAVE_AIX_ACLS) + +/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ + +int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + struct acl_entry_link *link; + struct new_acl_entry *entry; + int keep_going; + + DEBUG(10,("This is the count: %d\n",theacl->count)); + + /* Check if count was previously set to -1. * + * If it was, that means we reached the end * + * of the acl last time. */ + if(theacl->count == -1) + return(0); + + link = theacl; + /* To get to the next acl, traverse linked list until index * + * of acl matches the count we are keeping. This count is * + * incremented each time we return an acl entry. */ + + for(keep_going = 0; keep_going < theacl->count; keep_going++) + link = link->nextp; + + entry = *entry_p = link->entryp; + + DEBUG(10,("*entry_p is %d\n",entry_p)); + DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access)); + + /* Increment count */ + theacl->count++; + if(link->nextp == NULL) + theacl->count = -1; + + return(1); +} + +int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + /* Initialize tag type */ + + *tag_type_p = -1; + DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type)); + + /* Depending on what type of entry we have, * + * return tag type. */ + switch(entry_d->ace_id->id_type) { + case ACEID_USER: + *tag_type_p = SMB_ACL_USER; + break; + case ACEID_GROUP: + *tag_type_p = SMB_ACL_GROUP; + break; + + case SMB_ACL_USER_OBJ: + case SMB_ACL_GROUP_OBJ: + case SMB_ACL_OTHER: + *tag_type_p = entry_d->ace_id->id_type; + break; + + default: + return(-1); + } + + return(0); +} + +int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + DEBUG(10,("Starting AIX sys_acl_get_permset\n")); + *permset_p = &entry_d->ace_access; + DEBUG(10,("**permset_p is %d\n",**permset_p)); + if(!(**permset_p & S_IXUSR) && + !(**permset_p & S_IWUSR) && + !(**permset_p & S_IRUSR) && + (**permset_p != 0)) + return(-1); + + DEBUG(10,("Ending AIX sys_acl_get_permset\n")); + return(0); +} + +void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +{ + return(entry_d->ace_id->id_data); +} + +SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +{ + struct acl *file_acl = (struct acl *)NULL; + struct acl_entry *acl_entry; + struct new_acl_entry *new_acl_entry; + struct ace_id *idp; + struct acl_entry_link *acl_entry_link; + struct acl_entry_link *acl_entry_link_head; + int i; + int rc = 0; + uid_t user_id; + + /* Get the acl using statacl */ + + DEBUG(10,("Entering sys_acl_get_file\n")); + DEBUG(10,("path_p is %s\n",path_p)); + + file_acl = (struct acl *)malloc(BUFSIZ); + + if(file_acl == NULL) { + errno=ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno)); + return(NULL); + } + + memset(file_acl,0,BUFSIZ); + + rc = statacl((char *)path_p,0,file_acl,BUFSIZ); + if(rc == -1) { + DEBUG(0,("statacl returned %d with errno %d\n",rc,errno)); + SAFE_FREE(file_acl); + return(NULL); + } + + DEBUG(10,("Got facl and returned it\n")); + + /* Point to the first acl entry in the acl */ + acl_entry = file_acl->acl_ext; + + /* Begin setting up the head of the linked list * + * that will be used for the storing the acl * + * in a way that is useful for the posix_acls.c * + * code. */ + + acl_entry_link_head = acl_entry_link = sys_acl_init(0); + if(acl_entry_link_head == NULL) + return(NULL); + + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return(NULL); + } + + DEBUG(10,("acl_entry is %d\n",acl_entry)); + DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); + + /* Check if the extended acl bit is on. * + * If it isn't, do not show the * + * contents of the acl since AIX intends * + * the extended info to remain unused */ + + if(file_acl->acl_mode & S_IXACL){ + /* while we are not pointing to the very end */ + while(acl_entry < acl_last(file_acl)) { + /* before we malloc anything, make sure this is */ + /* a valid acl entry and one that we want to map */ + idp = id_nxt(acl_entry->ace_id); + if((acl_entry->ace_type == ACC_SPECIFY || + (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { + acl_entry = acl_nxt(acl_entry); + continue; + } + + idp = acl_entry->ace_id; + + /* Check if this is the first entry in the linked list. * + * The first entry needs to keep prevp pointing to NULL * + * and already has entryp allocated. */ + + if(acl_entry_link_head->count != 0) { + acl_entry_link->nextp = (struct acl_entry_link *) + malloc(sizeof(struct acl_entry_link)); + + if(acl_entry_link->nextp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return(NULL); + } + + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return(NULL); + } + acl_entry_link->nextp = NULL; + } + + acl_entry_link->entryp->ace_len = acl_entry->ace_len; + + /* Don't really need this since all types are going * + * to be specified but, it's better than leaving it 0 */ + + acl_entry_link->entryp->ace_type = acl_entry->ace_type; + + acl_entry_link->entryp->ace_access = acl_entry->ace_access; + + memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id)); + + /* The access in the acl entries must be left shifted by * + * three bites, because they will ultimately be compared * + * to S_IRUSR, S_IWUSR, and S_IXUSR. */ + + switch(acl_entry->ace_type){ + case ACC_PERMIT: + case ACC_SPECIFY: + acl_entry_link->entryp->ace_access = acl_entry->ace_access; + acl_entry_link->entryp->ace_access <<= 6; + acl_entry_link_head->count++; + break; + case ACC_DENY: + /* Since there is no way to return a DENY acl entry * + * change to PERMIT and then shift. */ + DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); + acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; + DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); + acl_entry_link->entryp->ace_access <<= 6; + acl_entry_link_head->count++; + break; + default: + return(0); + } + + DEBUG(10,("acl_entry = %d\n",acl_entry)); + DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); + + acl_entry = acl_nxt(acl_entry); + } + } /* end of if enabled */ + + /* Since owner, group, other acl entries are not * + * part of the acl entries in an acl, they must * + * be dummied up to become part of the list. */ + + for( i = 1; i < 4; i++) { + DEBUG(10,("i is %d\n",i)); + if(acl_entry_link_head->count != 0) { + acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return(NULL); + } + + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); + return(NULL); + } + } + + acl_entry_link->nextp = NULL; + + new_acl_entry = acl_entry_link->entryp; + idp = new_acl_entry->ace_id; + + new_acl_entry->ace_len = sizeof(struct acl_entry); + new_acl_entry->ace_type = ACC_PERMIT; + idp->id_len = sizeof(struct ace_id); + DEBUG(10,("idp->id_len = %d\n",idp->id_len)); + memset(idp->id_data,0,sizeof(uid_t)); + + switch(i) { + case 2: + new_acl_entry->ace_access = file_acl->g_access << 6; + idp->id_type = SMB_ACL_GROUP_OBJ; + break; + + case 3: + new_acl_entry->ace_access = file_acl->o_access << 6; + idp->id_type = SMB_ACL_OTHER; + break; + + case 1: + new_acl_entry->ace_access = file_acl->u_access << 6; + idp->id_type = SMB_ACL_USER_OBJ; + break; + + default: + return(NULL); + + } + + acl_entry_link_head->count++; + DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); + } + + acl_entry_link_head->count = 0; + SAFE_FREE(file_acl); + + return(acl_entry_link_head); +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + struct acl *file_acl = (struct acl *)NULL; + struct acl_entry *acl_entry; + struct new_acl_entry *new_acl_entry; + struct ace_id *idp; + struct acl_entry_link *acl_entry_link; + struct acl_entry_link *acl_entry_link_head; + int i; + int rc = 0; + uid_t user_id; + + /* Get the acl using fstatacl */ + + DEBUG(10,("Entering sys_acl_get_fd\n")); + DEBUG(10,("fd is %d\n",fd)); + file_acl = (struct acl *)malloc(BUFSIZ); + + if(file_acl == NULL) { + errno=ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + return(NULL); + } + + memset(file_acl,0,BUFSIZ); + + rc = fstatacl(fd,0,file_acl,BUFSIZ); + if(rc == -1) { + DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno)); + SAFE_FREE(file_acl); + return(NULL); + } + + DEBUG(10,("Got facl and returned it\n")); + + /* Point to the first acl entry in the acl */ + + acl_entry = file_acl->acl_ext; + /* Begin setting up the head of the linked list * + * that will be used for the storing the acl * + * in a way that is useful for the posix_acls.c * + * code. */ + + acl_entry_link_head = acl_entry_link = sys_acl_init(0); + if(acl_entry_link_head == NULL){ + SAFE_FREE(file_acl); + return(NULL); + } + + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + + if(acl_entry_link->entryp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + SAFE_FREE(file_acl); + return(NULL); + } + + DEBUG(10,("acl_entry is %d\n",acl_entry)); + DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); + + /* Check if the extended acl bit is on. * + * If it isn't, do not show the * + * contents of the acl since AIX intends * + * the extended info to remain unused */ + + if(file_acl->acl_mode & S_IXACL){ + /* while we are not pointing to the very end */ + while(acl_entry < acl_last(file_acl)) { + /* before we malloc anything, make sure this is */ + /* a valid acl entry and one that we want to map */ + + idp = id_nxt(acl_entry->ace_id); + if((acl_entry->ace_type == ACC_SPECIFY || + (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { + acl_entry = acl_nxt(acl_entry); + continue; + } + + idp = acl_entry->ace_id; + + /* Check if this is the first entry in the linked list. * + * The first entry needs to keep prevp pointing to NULL * + * and already has entryp allocated. */ + + if(acl_entry_link_head->count != 0) { + acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + SAFE_FREE(file_acl); + return(NULL); + } + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(acl_entry_link->entryp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + SAFE_FREE(file_acl); + return(NULL); + } + + acl_entry_link->nextp = NULL; + } + + acl_entry_link->entryp->ace_len = acl_entry->ace_len; + + /* Don't really need this since all types are going * + * to be specified but, it's better than leaving it 0 */ + + acl_entry_link->entryp->ace_type = acl_entry->ace_type; + acl_entry_link->entryp->ace_access = acl_entry->ace_access; + + memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id)); + + /* The access in the acl entries must be left shifted by * + * three bites, because they will ultimately be compared * + * to S_IRUSR, S_IWUSR, and S_IXUSR. */ + + switch(acl_entry->ace_type){ + case ACC_PERMIT: + case ACC_SPECIFY: + acl_entry_link->entryp->ace_access = acl_entry->ace_access; + acl_entry_link->entryp->ace_access <<= 6; + acl_entry_link_head->count++; + break; + case ACC_DENY: + /* Since there is no way to return a DENY acl entry * + * change to PERMIT and then shift. */ + DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); + acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; + DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); + acl_entry_link->entryp->ace_access <<= 6; + acl_entry_link_head->count++; + break; + default: + return(0); + } + + DEBUG(10,("acl_entry = %d\n",acl_entry)); + DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); + + acl_entry = acl_nxt(acl_entry); + } + } /* end of if enabled */ + + /* Since owner, group, other acl entries are not * + * part of the acl entries in an acl, they must * + * be dummied up to become part of the list. */ + + for( i = 1; i < 4; i++) { + DEBUG(10,("i is %d\n",i)); + if(acl_entry_link_head->count != 0){ + acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entry_link->nextp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + SAFE_FREE(file_acl); + return(NULL); + } + + acl_entry_link->nextp->prevp = acl_entry_link; + acl_entry_link = acl_entry_link->nextp; + acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + + if(acl_entry_link->entryp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); + return(NULL); + } + } + + acl_entry_link->nextp = NULL; + + new_acl_entry = acl_entry_link->entryp; + idp = new_acl_entry->ace_id; + + new_acl_entry->ace_len = sizeof(struct acl_entry); + new_acl_entry->ace_type = ACC_PERMIT; + idp->id_len = sizeof(struct ace_id); + DEBUG(10,("idp->id_len = %d\n",idp->id_len)); + memset(idp->id_data,0,sizeof(uid_t)); + + switch(i) { + case 2: + new_acl_entry->ace_access = file_acl->g_access << 6; + idp->id_type = SMB_ACL_GROUP_OBJ; + break; + + case 3: + new_acl_entry->ace_access = file_acl->o_access << 6; + idp->id_type = SMB_ACL_OTHER; + break; + + case 1: + new_acl_entry->ace_access = file_acl->u_access << 6; + idp->id_type = SMB_ACL_USER_OBJ; + break; + + default: + return(NULL); + } + + acl_entry_link_head->count++; + DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); + } + + acl_entry_link_head->count = 0; + SAFE_FREE(file_acl); + + return(acl_entry_link_head); +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +{ + *permset = *permset & ~0777; + return(0); +} + +int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + if((perm != 0) && + (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0) + return(-1); + + *permset |= perm; + DEBUG(10,("This is the permset now: %d\n",*permset)); + return(0); +} + +char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) +{ + return(NULL); +} + +SMB_ACL_T sys_acl_init( int count) +{ + struct acl_entry_link *theacl = NULL; + + DEBUG(10,("Entering sys_acl_init\n")); + + theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(theacl == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_init is %d\n",errno)); + return(NULL); + } + + theacl->count = 0; + theacl->nextp = NULL; + theacl->prevp = NULL; + theacl->entryp = NULL; + DEBUG(10,("Exiting sys_acl_init\n")); + return(theacl); +} + +int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + struct acl_entry_link *theacl; + struct acl_entry_link *acl_entryp; + struct acl_entry_link *temp_entry; + int counting; + + DEBUG(10,("Entering the sys_acl_create_entry\n")); + + theacl = acl_entryp = *pacl; + + /* Get to the end of the acl before adding entry */ + + for(counting=0; counting < theacl->count; counting++){ + DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); + temp_entry = acl_entryp; + acl_entryp = acl_entryp->nextp; + } + + if(theacl->count != 0){ + temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); + if(acl_entryp == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); + return(-1); + } + + DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); + acl_entryp->prevp = temp_entry; + DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp)); + } + + *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); + if(*pentry == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); + return(-1); + } + + memset(*pentry,0,sizeof(struct new_acl_entry)); + acl_entryp->entryp->ace_len = sizeof(struct acl_entry); + acl_entryp->entryp->ace_type = ACC_PERMIT; + acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id); + acl_entryp->nextp = NULL; + theacl->count++; + DEBUG(10,("Exiting sys_acl_create_entry\n")); + return(0); +} + +int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + DEBUG(10,("Starting AIX sys_acl_set_tag_type\n")); + entry->ace_id->id_type = tagtype; + DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type)); + DEBUG(10,("Ending AIX sys_acl_set_tag_type\n")); +} + +int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +{ + DEBUG(10,("Starting AIX sys_acl_set_qualifier\n")); + memcpy(entry->ace_id->id_data,qual,sizeof(uid_t)); + DEBUG(10,("Ending AIX sys_acl_set_qualifier\n")); + return(0); +} + +int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + DEBUG(10,("Starting AIX sys_acl_set_permset\n")); + if(!(*permset & S_IXUSR) && + !(*permset & S_IWUSR) && + !(*permset & S_IRUSR) && + (*permset != 0)) + return(-1); + + entry->ace_access = *permset; + DEBUG(10,("entry->ace_access = %d\n",entry->ace_access)); + DEBUG(10,("Ending AIX sys_acl_set_permset\n")); + return(0); +} + +int sys_acl_valid( SMB_ACL_T theacl ) +{ + int user_obj = 0; + int group_obj = 0; + int other_obj = 0; + struct acl_entry_link *acl_entry; + + for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) { + user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ); + group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ); + other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER); + } + + DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj)); + + if(user_obj != 1 || group_obj != 1 || other_obj != 1) + return(-1); + + return(0); +} + +int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + struct acl_entry_link *acl_entry_link = NULL; + struct acl *file_acl = NULL; + struct acl *file_acl_temp = NULL; + struct acl_entry *acl_entry = NULL; + struct ace_id *ace_id = NULL; + uint id_type; + uint ace_access; + uint user_id; + uint acl_length; + uint rc; + + DEBUG(10,("Entering sys_acl_set_file\n")); + DEBUG(10,("File name is %s\n",name)); + + /* AIX has no default ACL */ + if(acltype == SMB_ACL_TYPE_DEFAULT) + return(0); + + acl_length = BUFSIZ; + file_acl = (struct acl *)malloc(BUFSIZ); + + if(file_acl == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); + return(-1); + } + + memset(file_acl,0,BUFSIZ); + + file_acl->acl_len = ACL_SIZ; + file_acl->acl_mode = S_IXACL; + + for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { + acl_entry_link->entryp->ace_access >>= 6; + id_type = acl_entry_link->entryp->ace_id->id_type; + + switch(id_type) { + case SMB_ACL_USER_OBJ: + file_acl->u_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_GROUP_OBJ: + file_acl->g_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_OTHER: + file_acl->o_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_MASK: + continue; + } + + if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { + acl_length += sizeof(struct acl_entry); + file_acl_temp = (struct acl *)malloc(acl_length); + if(file_acl_temp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); + return(-1); + } + + memcpy(file_acl_temp,file_acl,file_acl->acl_len); + SAFE_FREE(file_acl); + file_acl = file_acl_temp; + } + + acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); + file_acl->acl_len += sizeof(struct acl_entry); + acl_entry->ace_len = acl_entry_link->entryp->ace_len; + acl_entry->ace_access = acl_entry_link->entryp->ace_access; + + /* In order to use this, we'll need to wait until we can get denies */ + /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) + acl_entry->ace_type = ACC_SPECIFY; */ + + acl_entry->ace_type = ACC_SPECIFY; + + ace_id = acl_entry->ace_id; + + ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; + DEBUG(10,("The id type is %d\n",ace_id->id_type)); + ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; + memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); + memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t)); + } + + rc = chacl(name,file_acl,file_acl->acl_len); + DEBUG(10,("errno is %d\n",errno)); + DEBUG(10,("return code is %d\n",rc)); + SAFE_FREE(file_acl); + DEBUG(10,("Exiting the sys_acl_set_file\n")); + return(rc); +} + +int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +{ + struct acl_entry_link *acl_entry_link = NULL; + struct acl *file_acl = NULL; + struct acl *file_acl_temp = NULL; + struct acl_entry *acl_entry = NULL; + struct ace_id *ace_id = NULL; + uint id_type; + uint user_id; + uint acl_length; + uint rc; + + DEBUG(10,("Entering sys_acl_set_fd\n")); + acl_length = BUFSIZ; + file_acl = (struct acl *)malloc(BUFSIZ); + + if(file_acl == NULL) { + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); + return(-1); + } + + memset(file_acl,0,BUFSIZ); + + file_acl->acl_len = ACL_SIZ; + file_acl->acl_mode = S_IXACL; + + for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { + acl_entry_link->entryp->ace_access >>= 6; + id_type = acl_entry_link->entryp->ace_id->id_type; + DEBUG(10,("The id_type is %d\n",id_type)); + + switch(id_type) { + case SMB_ACL_USER_OBJ: + file_acl->u_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_GROUP_OBJ: + file_acl->g_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_OTHER: + file_acl->o_access = acl_entry_link->entryp->ace_access; + continue; + case SMB_ACL_MASK: + continue; + } + + if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { + acl_length += sizeof(struct acl_entry); + file_acl_temp = (struct acl *)malloc(acl_length); + if(file_acl_temp == NULL) { + SAFE_FREE(file_acl); + errno = ENOMEM; + DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); + return(-1); + } + + memcpy(file_acl_temp,file_acl,file_acl->acl_len); + SAFE_FREE(file_acl); + file_acl = file_acl_temp; + } + + acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); + file_acl->acl_len += sizeof(struct acl_entry); + acl_entry->ace_len = acl_entry_link->entryp->ace_len; + acl_entry->ace_access = acl_entry_link->entryp->ace_access; + + /* In order to use this, we'll need to wait until we can get denies */ + /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) + acl_entry->ace_type = ACC_SPECIFY; */ + + acl_entry->ace_type = ACC_SPECIFY; + + ace_id = acl_entry->ace_id; + + ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; + DEBUG(10,("The id type is %d\n",ace_id->id_type)); + ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; + memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); + memcpy(ace_id->id_data, &user_id, sizeof(uid_t)); + } + + rc = fchacl(fd,file_acl,file_acl->acl_len); + DEBUG(10,("errno is %d\n",errno)); + DEBUG(10,("return code is %d\n",rc)); + SAFE_FREE(file_acl); + DEBUG(10,("Exiting sys_acl_set_fd\n")); + return(rc); +} + +int sys_acl_delete_def_file(const char *name) +{ + /* AIX has no default ACL */ + return 0; +} + +int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + return(*permset & perm); +} + +int sys_acl_free_text(char *text) +{ + return(0); +} + +int sys_acl_free_acl(SMB_ACL_T posix_acl) +{ + struct acl_entry_link *acl_entry_link; + + for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) { + SAFE_FREE(acl_entry_link->prevp->entryp); + SAFE_FREE(acl_entry_link->prevp); + } + + SAFE_FREE(acl_entry_link->prevp->entryp); + SAFE_FREE(acl_entry_link->prevp); + SAFE_FREE(acl_entry_link->entryp); + SAFE_FREE(acl_entry_link); + + return(0); +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + return(0); +} + +#else /* No ACLs. */ + +int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +{ + errno = ENOSYS; + return -1; +} + +void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) +{ + errno = ENOSYS; + return NULL; +} + +SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) +{ + errno = ENOSYS; + return (SMB_ACL_T)NULL; +} + +SMB_ACL_T sys_acl_get_fd(int fd) +{ + errno = ENOSYS; + return (SMB_ACL_T)NULL; +} + +int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +{ + errno = ENOSYS; + return (permset & perm) ? 1 : 0; +} + +char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) +{ + errno = ENOSYS; + return NULL; +} + +int sys_acl_free_text(char *text) +{ + errno = ENOSYS; + return -1; +} + +SMB_ACL_T sys_acl_init( int count) +{ + errno = ENOSYS; + return NULL; +} + +int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_valid( SMB_ACL_T theacl ) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_set_fd( int fd, SMB_ACL_T theacl) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_delete_def_file(const char *name) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_free_acl(SMB_ACL_T the_acl) +{ + errno = ENOSYS; + return -1; +} + +int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) +{ + errno = ENOSYS; + return -1; +} + +#endif /* No ACLs. */ diff --git a/source4/lib/system.c b/source4/lib/system.c new file mode 100644 index 0000000000..bafe689a30 --- /dev/null +++ b/source4/lib/system.c @@ -0,0 +1,1114 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + The idea is that this file will eventually have wrappers around all + important system calls in samba. The aims are: + + - to enable easier porting by putting OS dependent stuff in here + + - to allow for hooks into other "pseudo-filesystems" + + - to allow easier integration of things like the japanese extensions + + - to support the philosophy of Samba to expose the features of + the OS within the SMB model. In general whatever file/printer/variable + expansions/etc make sense to the OS should be acceptable to Samba. +*/ + + + +/******************************************************************* + A wrapper for usleep in case we don't have one. +********************************************************************/ + +int sys_usleep(long usecs) +{ +#ifndef HAVE_USLEEP + struct timeval tval; +#endif + + /* + * We need this braindamage as the glibc usleep + * is not SPEC1170 complient... grumble... JRA. + */ + + if(usecs < 0 || usecs > 1000000) { + errno = EINVAL; + return -1; + } + +#if HAVE_USLEEP + usleep(usecs); + return 0; +#else /* HAVE_USLEEP */ + /* + * Fake it with select... + */ + tval.tv_sec = 0; + tval.tv_usec = usecs/1000; + select(0,NULL,NULL,NULL,&tval); + return 0; +#endif /* HAVE_USLEEP */ +} + +/******************************************************************* +A read wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_read(int fd, void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = read(fd, buf, count); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A write wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_write(int fd, const void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = write(fd, buf, count); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A send wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_send(int s, const void *msg, size_t len, int flags) +{ + ssize_t ret; + + do { + ret = send(s, msg, len, flags); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A sendto wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +{ + ssize_t ret; + + do { + ret = sendto(s, msg, len, flags, to, tolen); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A recvfrom wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) +{ + ssize_t ret; + + do { + ret = recvfrom(s, buf, len, flags, from, fromlen); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A fcntl wrapper that will deal with EINTR. +********************************************************************/ + +int sys_fcntl_ptr(int fd, int cmd, void *arg) +{ + int ret; + + do { + ret = fcntl(fd, cmd, arg); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A fcntl wrapper that will deal with EINTR. +********************************************************************/ + +int sys_fcntl_long(int fd, int cmd, long arg) +{ + int ret; + + do { + ret = fcntl(fd, cmd, arg); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* +A stat() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf) +{ + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64) + ret = stat64(fname, sbuf); +#else + ret = stat(fname, sbuf); +#endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; +} + +/******************************************************************* + An fstat() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf) +{ + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64) + ret = fstat64(fd, sbuf); +#else + ret = fstat(fd, sbuf); +#endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; +} + +/******************************************************************* + An lstat() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf) +{ + int ret; +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64) + ret = lstat64(fname, sbuf); +#else + ret = lstat(fname, sbuf); +#endif + /* we always want directories to appear zero size */ + if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + return ret; +} + +/******************************************************************* + An ftruncate() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_ftruncate(int fd, SMB_OFF_T offset) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64) + return ftruncate64(fd, offset); +#else + return ftruncate(fd, offset); +#endif +} + +/******************************************************************* + An lseek() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64) + return lseek64(fd, offset, whence); +#else + return lseek(fd, offset, whence); +#endif +} + +/******************************************************************* + An fseek() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64) + return fseek64(fp, offset, whence); +#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64) + return fseeko64(fp, offset, whence); +#else + return fseek(fp, offset, whence); +#endif +} + +/******************************************************************* + An ftell() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +SMB_OFF_T sys_ftell(FILE *fp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64) + return (SMB_OFF_T)ftell64(fp); +#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64) + return (SMB_OFF_T)ftello64(fp); +#else + return (SMB_OFF_T)ftell(fp); +#endif +} + +/******************************************************************* + A creat() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_creat(const char *path, mode_t mode) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64) + return creat64(path, mode); +#else + /* + * If creat64 isn't defined then ensure we call a potential open64. + * JRA. + */ + return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); +#endif +} + +/******************************************************************* + An open() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_open(const char *path, int oflag, mode_t mode) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64) + return open64(path, oflag, mode); +#else + return open(path, oflag, mode); +#endif +} + +/******************************************************************* + An fopen() wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +FILE *sys_fopen(const char *path, const char *type) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64) + return fopen64(path, type); +#else + return fopen(path, type); +#endif +} + +/******************************************************************* + A readdir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) + return readdir64(dirp); +#else + return readdir(dirp); +#endif +} + +/******************************************************************* +The wait() calls vary between systems +********************************************************************/ + +int sys_waitpid(pid_t pid,int *status,int options) +{ +#ifdef HAVE_WAITPID + return waitpid(pid,status,options); +#else /* HAVE_WAITPID */ + return wait4(pid, status, options, NULL); +#endif /* HAVE_WAITPID */ +} + +/******************************************************************* + System wrapper for getwd +********************************************************************/ + +char *sys_getwd(char *s) +{ + char *wd; +#ifdef HAVE_GETCWD + wd = (char *)getcwd(s, sizeof (pstring)); +#else + wd = (char *)getwd(s); +#endif + return wd; +} + +/******************************************************************* +system wrapper for link +********************************************************************/ + +int sys_link(const char *oldpath, const char *newpath) +{ +#ifndef HAVE_LINK + errno = ENOSYS; + return -1; +#else + return link(oldpath, newpath); +#endif +} + +/******************************************************************* +os/2 also doesn't have chroot +********************************************************************/ +int sys_chroot(const char *dname) +{ +#ifndef HAVE_CHROOT + static int done; + if (!done) { + DEBUG(1,("WARNING: no chroot!\n")); + done=1; + } + errno = ENOSYS; + return -1; +#else + return(chroot(dname)); +#endif +} + +/************************************************************************** +A wrapper for gethostbyname() that tries avoids looking up hostnames +in the root domain, which can cause dial-on-demand links to come up for no +apparent reason. +****************************************************************************/ + +struct hostent *sys_gethostbyname(const char *name) +{ +#ifdef REDUCE_ROOT_DNS_LOOKUPS + char query[256], hostname[256]; + char *domain; + + /* Does this name have any dots in it? If so, make no change */ + + if (strchr_m(name, '.')) + return(gethostbyname(name)); + + /* Get my hostname, which should have domain name + attached. If not, just do the gethostname on the + original string. + */ + + gethostname(hostname, sizeof(hostname) - 1); + hostname[sizeof(hostname) - 1] = 0; + if ((domain = strchr_m(hostname, '.')) == NULL) + return(gethostbyname(name)); + + /* Attach domain name to query and do modified query. + If names too large, just do gethostname on the + original string. + */ + + if((strlen(name) + strlen(domain)) >= sizeof(query)) + return(gethostbyname(name)); + + slprintf(query, sizeof(query)-1, "%s%s", name, domain); + return(gethostbyname(query)); +#else /* REDUCE_ROOT_DNS_LOOKUPS */ + return(gethostbyname(name)); +#endif /* REDUCE_ROOT_DNS_LOOKUPS */ +} + + +#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES) +/************************************************************************** + Try and abstract process capabilities (for systems that have them). +****************************************************************************/ +static BOOL set_process_capability( uint32 cap_flag, BOOL enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return False; + } + + if(enable) + cap->cap_effective |= CAP_NETWORK_MGT; + else + cap->cap_effective &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return False; + } + + cap_free(cap); + + DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return True; +} + +/************************************************************************** + Try and abstract inherited process capabilities (for systems that have them). +****************************************************************************/ + +static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return False; + } + + if(enable) + cap->cap_inheritable |= CAP_NETWORK_MGT; + else + cap->cap_inheritable &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return False; + } + + cap_free(cap); + + DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return True; +} +#endif + +/**************************************************************************** + Gain the oplock capability from the kernel if possible. +****************************************************************************/ + +void oplock_set_capability(BOOL this_process, BOOL inherit) +{ +#if HAVE_KERNEL_OPLOCKS_IRIX + set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit); +#endif +} + +/************************************************************************** + Wrapper for random(). +****************************************************************************/ + +long sys_random(void) +{ +#if defined(HAVE_RANDOM) + return (long)random(); +#elif defined(HAVE_RAND) + return (long)rand(); +#else + DEBUG(0,("Error - no random function available !\n")); + exit(1); +#endif +} + +/************************************************************************** + Wrapper for srandom(). +****************************************************************************/ + +void sys_srandom(unsigned int seed) +{ +#if defined(HAVE_SRANDOM) + srandom(seed); +#elif defined(HAVE_SRAND) + srand(seed); +#else + DEBUG(0,("Error - no srandom function available !\n")); + exit(1); +#endif +} + +/************************************************************************** + Returns equivalent to NGROUPS_MAX - using sysconf if needed. +****************************************************************************/ + +int groups_max(void) +{ +#if defined(SYSCONF_SC_NGROUPS_MAX) + int ret = sysconf(_SC_NGROUPS_MAX); + return (ret == -1) ? NGROUPS_MAX : ret; +#else + return NGROUPS_MAX; +#endif +} + +/************************************************************************** + Wrapper for getgroups. Deals with broken (int) case. +****************************************************************************/ + +int sys_getgroups(int setlen, gid_t *gidset) +{ +#if !defined(HAVE_BROKEN_GETGROUPS) + return getgroups(setlen, gidset); +#else + + GID_T gid; + GID_T *group_list; + int i, ngroups; + + if(setlen == 0) { + return getgroups(setlen, &gid); + } + + /* + * Broken case. We need to allocate a + * GID_T array of size setlen. + */ + + if(setlen < 0) { + errno = EINVAL; + return -1; + } + + if (setlen == 0) + setlen = groups_max(); + + if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { + DEBUG(0,("sys_getgroups: Malloc fail.\n")); + return -1; + } + + if((ngroups = getgroups(setlen, group_list)) < 0) { + int saved_errno = errno; + SAFE_FREE(group_list); + errno = saved_errno; + return -1; + } + + for(i = 0; i < ngroups; i++) + gidset[i] = (gid_t)group_list[i]; + + SAFE_FREE(group_list); + return ngroups; +#endif /* HAVE_BROKEN_GETGROUPS */ +} + +#ifdef HAVE_SETGROUPS + +/************************************************************************** + Wrapper for setgroups. Deals with broken (int) case. Automatically used + if we have broken getgroups. +****************************************************************************/ + +int sys_setgroups(int setlen, gid_t *gidset) +{ +#if !defined(HAVE_BROKEN_GETGROUPS) + return setgroups(setlen, gidset); +#else + + GID_T *group_list; + int i ; + + if (setlen == 0) + return 0 ; + + if (setlen < 0 || setlen > groups_max()) { + errno = EINVAL; + return -1; + } + + /* + * Broken case. We need to allocate a + * GID_T array of size setlen. + */ + + if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { + DEBUG(0,("sys_setgroups: Malloc fail.\n")); + return -1; + } + + for(i = 0; i < setlen; i++) + group_list[i] = (GID_T) gidset[i]; + + if(setgroups(setlen, group_list) != 0) { + int saved_errno = errno; + SAFE_FREE(group_list); + errno = saved_errno; + return -1; + } + + SAFE_FREE(group_list); + return 0 ; +#endif /* HAVE_BROKEN_GETGROUPS */ +} + +#endif /* HAVE_SETGROUPS */ + +struct passwd *sys_getpwent(void) +{ + return getpwent(); +} + +void sys_endpwent(void) +{ + endpwent(); +} + +/************************************************************************** + Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid() +****************************************************************************/ + +struct passwd *sys_getpwnam(const char *name) +{ + return getpwnam(name); +} + +struct passwd *sys_getpwuid(uid_t uid) +{ + return getpwuid(uid); +} + +struct group *sys_getgrnam(const char *name) +{ + return getgrnam(name); +} + +struct group *sys_getgrgid(gid_t gid) +{ + return getgrgid(gid); +} + +#if 0 /* NOT CURRENTLY USED - JRA */ +/************************************************************************** + The following are the UNICODE versions of *all* system interface functions + called within Samba. Ok, ok, the exceptions are the gethostbyXX calls, + which currently are left as ascii as they are not used other than in name + resolution. +****************************************************************************/ + +/************************************************************************** + Wide stat. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf) +{ + pstring fname; + return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf); +} + +/************************************************************************** + Wide lstat. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf) +{ + pstring fname; + return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf); +} + +/************************************************************************** + Wide creat. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_creat(const smb_ucs2_t *wfname, mode_t mode) +{ + pstring fname; + return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode); +} + +/************************************************************************** + Wide open. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode) +{ + pstring fname; + return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode); +} + +/************************************************************************** + Wide fopen. Just narrow and call sys_xxx. +****************************************************************************/ + +FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type) +{ + pstring fname; + return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type); +} + +/************************************************************************** + Wide opendir. Just narrow and call sys_xxx. +****************************************************************************/ + +DIR *wsys_opendir(const smb_ucs2_t *wfname) +{ + pstring fname; + return opendir(unicode_to_unix(fname,wfname,sizeof(fname))); +} + +/************************************************************************** + Wide readdir. Return a structure pointer containing a wide filename. +****************************************************************************/ + +SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp) +{ + static SMB_STRUCT_WDIRENT retval; + SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp); + + if(!dirval) + return NULL; + + /* + * The only POSIX defined member of this struct is d_name. + */ + + unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name)); + + return &retval; +} + +/************************************************************************** + Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring. +****************************************************************************/ + +smb_ucs2_t *wsys_getwd(smb_ucs2_t *s) +{ + pstring fname; + char *p = sys_getwd(fname); + + if(!p) + return NULL; + + return unix_to_unicode(s, p, sizeof(wpstring)); +} + +/************************************************************************** + Wide chown. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid) +{ + pstring fname; + return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid); +} + +/************************************************************************** + Wide chroot. Just narrow and call sys_xxx. +****************************************************************************/ + +int wsys_chroot(const smb_ucs2_t *wfname) +{ + pstring fname; + return chroot(unicode_to_unix(fname,wfname,sizeof(fname))); +} + +/************************************************************************** + Wide getpwnam. Return a structure pointer containing wide names. +****************************************************************************/ + +SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname) +{ + static SMB_STRUCT_WPASSWD retval; + fstring name; + struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name))); + + if(!pwret) + return NULL; + + unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name)); + retval.pw_passwd = pwret->pw_passwd; + retval.pw_uid = pwret->pw_uid; + retval.pw_gid = pwret->pw_gid; + unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); + unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); + unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); + + return &retval; +} + +/************************************************************************** + Wide getpwuid. Return a structure pointer containing wide names. +****************************************************************************/ + +SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid) +{ + static SMB_STRUCT_WPASSWD retval; + struct passwd *pwret = sys_getpwuid(uid); + + if(!pwret) + return NULL; + + unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name)); + retval.pw_passwd = pwret->pw_passwd; + retval.pw_uid = pwret->pw_uid; + retval.pw_gid = pwret->pw_gid; + unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); + unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); + unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); + + return &retval; +} +#endif /* NOT CURRENTLY USED - JRA */ + +/************************************************************************** + Extract a command into an arg list. Uses a static pstring for storage. + Caller frees returned arg list (which contains pointers into the static pstring). +****************************************************************************/ + +static char **extract_args(const char *command) +{ + static pstring trunc_cmd; + char *ptr; + int argcl; + char **argl = NULL; + int i; + + pstrcpy(trunc_cmd, command); + + if(!(ptr = strtok(trunc_cmd, " \t"))) { + errno = EINVAL; + return NULL; + } + + /* + * Count the args. + */ + + for( argcl = 1; ptr; ptr = strtok(NULL, " \t")) + argcl++; + + if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL) + return NULL; + + /* + * Now do the extraction. + */ + + pstrcpy(trunc_cmd, command); + + ptr = strtok(trunc_cmd, " \t"); + i = 0; + argl[i++] = ptr; + + while((ptr = strtok(NULL, " \t")) != NULL) + argl[i++] = ptr; + + argl[i++] = NULL; + return argl; +} + +/************************************************************************** + Wrapper for popen. Safer as it doesn't search a path. + Modified from the glibc sources. + modified by tridge to return a file descriptor. We must kick our FILE* habit +****************************************************************************/ + +typedef struct _popen_list +{ + int fd; + pid_t child_pid; + struct _popen_list *next; +} popen_list; + +static popen_list *popen_chain; + +int sys_popen(const char *command) +{ + int parent_end, child_end; + int pipe_fds[2]; + popen_list *entry = NULL; + char **argl = NULL; + + if (pipe(pipe_fds) < 0) + return -1; + + parent_end = pipe_fds[0]; + child_end = pipe_fds[1]; + + if (!*command) { + errno = EINVAL; + goto err_exit; + } + + if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL) + goto err_exit; + + ZERO_STRUCTP(entry); + + /* + * Extract the command and args into a NULL terminated array. + */ + + if(!(argl = extract_args(command))) + goto err_exit; + + entry->child_pid = fork(); + + if (entry->child_pid == -1) { + goto err_exit; + } + + if (entry->child_pid == 0) { + + /* + * Child ! + */ + + int child_std_end = STDOUT_FILENO; + popen_list *p; + + close(parent_end); + if (child_end != child_std_end) { + dup2 (child_end, child_std_end); + close (child_end); + } + + /* + * POSIX.2: "popen() shall ensure that any streams from previous + * popen() calls that remain open in the parent process are closed + * in the new child process." + */ + + for (p = popen_chain; p; p = p->next) + close(p->fd); + + execv(argl[0], argl); + _exit (127); + } + + /* + * Parent. + */ + + close (child_end); + SAFE_FREE(argl); + + /* Link into popen_chain. */ + entry->next = popen_chain; + popen_chain = entry; + entry->fd = parent_end; + + return entry->fd; + +err_exit: + + SAFE_FREE(entry); + SAFE_FREE(argl); + close(pipe_fds[0]); + close(pipe_fds[1]); + return -1; +} + +/************************************************************************** + Wrapper for pclose. Modified from the glibc sources. +****************************************************************************/ + +int sys_pclose(int fd) +{ + int wstatus; + popen_list **ptr = &popen_chain; + popen_list *entry = NULL; + pid_t wait_pid; + int status = -1; + + /* Unlink from popen_chain. */ + for ( ; *ptr != NULL; ptr = &(*ptr)->next) { + if ((*ptr)->fd == fd) { + entry = *ptr; + *ptr = (*ptr)->next; + status = 0; + break; + } + } + + if (status < 0 || close(entry->fd) < 0) + return -1; + + /* + * As Samba is catching and eating child process + * exits we don't really care about the child exit + * code, a -1 with errno = ECHILD will do fine for us. + */ + + do { + wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0); + } while (wait_pid == -1 && errno == EINTR); + + SAFE_FREE(entry); + + if (wait_pid == -1) + return -1; + return wstatus; +} + +/************************************************************************** + Wrappers for dlopen, dlsym, dlclose. +****************************************************************************/ + +void *sys_dlopen(const char *name, int flags) +{ +#if defined(HAVE_DLOPEN) + return dlopen(name, flags); +#else + return NULL; +#endif +} + +void *sys_dlsym(void *handle, const char *symbol) +{ +#if defined(HAVE_DLSYM) + return dlsym(handle, symbol); +#else + return NULL; +#endif +} + +int sys_dlclose (void *handle) +{ +#if defined(HAVE_DLCLOSE) + return dlclose(handle); +#else + return 0; +#endif +} + +const char *sys_dlerror(void) +{ +#if defined(HAVE_DLERROR) + return dlerror(); +#else + return NULL; +#endif +} + +int sys_dup2(int oldfd, int newfd) +{ +#if defined(HAVE_DUP2) + return dup2(oldfd, newfd); +#else + errno = ENOSYS; + return -1; +#endif +} + diff --git a/source4/lib/system_smbd.c b/source4/lib/system_smbd.c new file mode 100644 index 0000000000..3ae0a6395e --- /dev/null +++ b/source4/lib/system_smbd.c @@ -0,0 +1,119 @@ +/* + Unix SMB/CIFS implementation. + system call wrapper interface. + Copyright (C) Andrew Tridgell 2002 + Copyright (C) Andrew Barteltt 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + This file may assume linkage with smbd - for things like become_root() + etc. +*/ + +#include "includes.h" + +#ifndef HAVE_GETGROUPLIST +/* + This is a *much* faster way of getting the list of groups for a user + without changing the current supplemenrary group list. The old + method used getgrent() which could take 20 minutes on a really big + network with hundeds of thousands of groups and users. The new method + takes a couple of seconds. + + NOTE!! this function only works if it is called as root! + */ +static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt) +{ + gid_t *gids_saved; + int ret, ngrp_saved, num_gids; + + if (non_root_mode()) { + *grpcnt = 0; + return 0; + } + + /* work out how many groups we need to save */ + ngrp_saved = getgroups(0, NULL); + if (ngrp_saved == -1) { + /* this shouldn't happen */ + return -1; + } + + gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1)); + if (!gids_saved) { + errno = ENOMEM; + return -1; + } + + ngrp_saved = getgroups(ngrp_saved, gids_saved); + if (ngrp_saved == -1) { + SAFE_FREE(gids_saved); + /* very strange! */ + return -1; + } + + if (initgroups(user, gid) != 0) { + DEBUG(0, ("getgrouplist_internals: initgroups() failed!\n")); + SAFE_FREE(gids_saved); + return -1; + } + + /* this must be done to cope with systems that put the current egid in the + return from getgroups() */ + save_re_gid(); + set_effective_gid(gid); + setgid(gid); + + num_gids = getgroups(0, NULL); + if (num_gids + 1 > *grpcnt) { + *grpcnt = num_gids + 1; + ret = -1; + } else { + ret = getgroups(*grpcnt - 1, &groups[1]); + if (ret >= 0) { + groups[0] = gid; + *grpcnt = ret + 1; + } + } + + restore_re_gid(); + + if (setgroups(ngrp_saved, gids_saved) != 0) { + /* yikes! */ + DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); + smb_panic("getgrouplist: failed to reset group list!\n"); + free(gids_saved); + return -1; + } + + free(gids_saved); + return ret; +} +#endif + +int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) +{ +#ifdef HAVE_GETGROUPLIST + return getgrouplist(user, gid, groups, grpcnt); +#else + int retval; + become_root(); + retval = getgrouplist_internals(user, gid, groups, grpcnt); + unbecome_root(); + return retval; +#endif +} diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c new file mode 100644 index 0000000000..83a99d8071 --- /dev/null +++ b/source4/lib/talloc.c @@ -0,0 +1,515 @@ +/* + Samba Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + Copyright (C) Andrew Tridgell 2000 + Copyright (C) 2001, 2002 by Martin Pool + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/** + @defgroup talloc Simple memory allocator + @{ + + This is a very simple temporary memory allocator. To use it do the following: + + 1) when you first want to allocate a pool of meomry use + talloc_init() and save the resulting context pointer somewhere + + 2) to allocate memory use talloc() + + 3) when _all_ of the memory allocated using this context is no longer needed + use talloc_destroy() + + talloc does not zero the memory. It guarantees memory of a + TALLOC_ALIGN alignment + + @sa talloc.h +*/ + +/** + * @todo We could allocate both the talloc_chunk structure, and the + * memory it contains all in one allocation, which might be a bit + * faster and perhaps use less memory overhead. + * + * That smells like a premature optimization, though. -- mbp + **/ + +/** + * If you want testing for memory corruption, link with dmalloc or use + * Insure++. It doesn't seem useful to duplicate them here. + **/ + +#include "includes.h" + +struct talloc_chunk { + struct talloc_chunk *next; + size_t size; + void *ptr; +}; + + +struct talloc_ctx { + struct talloc_chunk *list; + off_t total_alloc_size; + + /** The name recorded for this pool, if any. Should describe + * the purpose for which it was allocated. The string is + * allocated within the pool. **/ + char *name; + + /** Pointer to the next allocate talloc pool, so that we can + * summarize all talloc memory usage. **/ + struct talloc_ctx *next, *prev; +}; + + +/** + * Start of linked list of all talloc pools. + * + * @todo We should turn the global list off when using Insure++, + * otherwise all the memory will be seen as still reachable. + **/ +static TALLOC_CTX *list_head; + +/** + * Add to the global list + **/ +static void talloc_enroll(TALLOC_CTX *t) +{ +#if 0 + /* disabled enrole/disenrole until we have __thread support */ + MUTEX_LOCK_BY_ID(MUTEX_TALLOC); + DLIST_ADD(list_head, t); + MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); +#endif +} + + +static void talloc_disenroll(TALLOC_CTX *t) +{ +#if 0 + /* disabled enrole/disenrole until we have __thread support */ + MUTEX_LOCK_BY_ID(MUTEX_TALLOC); + DLIST_REMOVE(list_head, t); + MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); +#endif +} + + +/** Create a new talloc context. **/ +static TALLOC_CTX *talloc_init_internal(void) +{ + TALLOC_CTX *t; + + t = (TALLOC_CTX *)malloc(sizeof(TALLOC_CTX)); + if (t) { + t->list = NULL; + t->total_alloc_size = 0; + t->name = NULL; + talloc_enroll(t); + } + + return t; +} + + + +/** + * Create a new talloc context, with a name specifying its purpose. + **/ + + TALLOC_CTX *talloc_init(char const *fmt, ...) +{ + TALLOC_CTX *t; + va_list ap; + + t = talloc_init_internal(); + if (t && fmt) { + /* + * t->name must not be talloced. + * as destroying the pool would destroy it. JRA. + */ + t->name = NULL; + va_start(ap, fmt); + vasprintf(&t->name, fmt, ap); + va_end(ap); + if (!t->name) { + talloc_destroy(t); + t = NULL; + } + } + + return t; +} + + +/** Allocate a bit of memory from the specified pool **/ +void *talloc(TALLOC_CTX *t, size_t size) +{ + void *p; + struct talloc_chunk *tc; + + if (!t || size == 0) return NULL; + + p = malloc(size); + if (p) { + tc = malloc(sizeof(*tc)); + if (tc) { + tc->ptr = p; + tc->size = size; + tc->next = t->list; + t->list = tc; + t->total_alloc_size += size; + } + else { + SAFE_FREE(p); + } + } + return p; +} + +/** A talloc version of realloc */ +void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size) +{ + struct talloc_chunk *tc; + void *new_ptr; + + /* size zero is equivalent to free() */ + if (!t || size == 0) + return NULL; + + /* realloc(NULL) is equavalent to malloc() */ + if (ptr == NULL) + return talloc(t, size); + + for (tc=t->list; tc; tc=tc->next) { + if (tc->ptr == ptr) { + new_ptr = Realloc(ptr, size); + if (new_ptr) { + t->total_alloc_size += (size - tc->size); + tc->size = size; + tc->ptr = new_ptr; + } + return new_ptr; + } + } + return NULL; +} + +/** Destroy all the memory allocated inside @p t, but not @p t + * itself. */ +void talloc_destroy_pool(TALLOC_CTX *t) +{ + struct talloc_chunk *c; + + if (!t) + return; + + while (t->list) { + c = t->list->next; + SAFE_FREE(t->list->ptr); + SAFE_FREE(t->list); + t->list = c; + } + + t->total_alloc_size = 0; +} + +/** Destroy a whole pool including the context */ +void talloc_destroy(TALLOC_CTX *t) +{ + if (!t) + return; + + talloc_destroy_pool(t); + talloc_disenroll(t); + SAFE_FREE(t->name); + SAFE_FREE(t); +} + +/** Return the current total size of the pool. */ +size_t talloc_pool_size(TALLOC_CTX *t) +{ + return t->total_alloc_size; +} + +const char *talloc_pool_name(TALLOC_CTX const *t) +{ + if (t) return t->name; + + return NULL; +} + + +/** talloc and zero memory. */ +void *talloc_zero(TALLOC_CTX *t, size_t size) +{ + void *p = talloc(t, size); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + + +/** memdup with a talloc. */ +void *talloc_memdup(TALLOC_CTX *t, const void *p, size_t size) +{ + void *newp = talloc(t,size); + + if (newp) { + memcpy(newp, p, size); + } + + return newp; +} + +/** strdup with a talloc */ +char *talloc_strdup(TALLOC_CTX *t, const char *p) +{ + return talloc_memdup(t, p, strlen(p) + 1); +} + +/** strndup with a talloc */ +char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) +{ + size_t len = strnlen(p, n); + char *ret; + + ret = talloc(t, len + 1); + if (!ret) { return NULL; } + memcpy(ret, p, len); + ret[len] = 0; + return ret; +} + +/** strdup_w with a talloc */ +smb_ucs2_t *talloc_strdup_w(TALLOC_CTX *t, const smb_ucs2_t *p) +{ + if (p) + return talloc_memdup(t, p, (strlen_w(p) + 1) * sizeof(smb_ucs2_t)); + return NULL; +} + +/** + * Perform string formatting, and return a pointer to newly allocated + * memory holding the result, inside a memory pool. + **/ + char *talloc_asprintf(TALLOC_CTX *t, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = talloc_vasprintf(t, fmt, ap); + va_end(ap); + return ret; +} + + + char *talloc_vasprintf(TALLOC_CTX *t, const char *fmt, va_list ap) +{ + int len; + char *ret; + va_list ap2; + + VA_COPY(ap2, ap); + + len = vsnprintf(NULL, 0, fmt, ap2); + + ret = talloc(t, len+1); + if (ret) { + VA_COPY(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + } + + return ret; +} + + +/** + * Realloc @p s to append the formatted result of @p fmt and return @p + * s, which may have moved. Good for gradually accumulating output + * into a string buffer. + **/ + char *talloc_asprintf_append(TALLOC_CTX *t, char *s, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append(t, s, fmt, ap); + va_end(ap); + return s; +} + + + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. + **/ + char *talloc_vasprintf_append(TALLOC_CTX *t, char *s, + const char *fmt, va_list ap) +{ + int len, s_len; + va_list ap2; + + VA_COPY(ap2, ap); + + s_len = strlen(s); + len = vsnprintf(NULL, 0, fmt, ap2); + + s = talloc_realloc(t, s, s_len + len+1); + if (!s) return NULL; + + VA_COPY(ap2, ap); + + vsnprintf(s+s_len, len+1, fmt, ap2); + + return s; +} + + +/** + * Return a human-readable description of all talloc memory usage. + * The result is allocated from @p t. + **/ +char *talloc_describe_all(TALLOC_CTX *rt) +{ + int n_pools = 0, total_chunks = 0; + size_t total_bytes = 0; + TALLOC_CTX *it; + char *s; + + if (!rt) return NULL; + + s = talloc_asprintf(rt, "global talloc allocations in pid: %u\n", + (unsigned) getpid()); + s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", + "name", "chunks", "bytes"); + s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", + "----------------------------------------", + "--------", + "--------"); + MUTEX_LOCK_BY_ID(MUTEX_TALLOC); + + for (it = list_head; it; it = it->next) { + size_t bytes; + int n_chunks; + fstring what; + + n_pools++; + + talloc_get_allocation(it, &bytes, &n_chunks); + + if (it->name) + fstrcpy(what, it->name); + else + slprintf(what, sizeof(what), "@%p", it); + + s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", + what, + (unsigned) n_chunks, + (unsigned) bytes); + total_bytes += bytes; + total_chunks += n_chunks; + } + + MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); + + s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", + "----------------------------------------", + "--------", + "--------"); + + s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", + "TOTAL", + (unsigned) total_chunks, (unsigned) total_bytes); + + return s; +} + + + +/** + * Return an estimated memory usage for the specified pool. This does + * not include memory used by the underlying malloc implementation. + **/ +void talloc_get_allocation(TALLOC_CTX *t, + size_t *total_bytes, + int *n_chunks) +{ + struct talloc_chunk *chunk; + + if (t) { + *total_bytes = 0; + *n_chunks = 0; + + for (chunk = t->list; chunk; chunk = chunk->next) { + n_chunks[0]++; + *total_bytes += chunk->size; + } + } +} + + +/* + move a lump of memory from one talloc context to another + return the ptr on success, or NULL if it could not be found + in the old context or could not be transferred +*/ +const void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *tc2; + + if (!ptr || !old_ctx->list) return NULL; + + /* as a special case, see if its the first element in the + list */ + if (old_ctx->list->ptr == ptr) { + tc = old_ctx->list; + old_ctx->list = old_ctx->list->next; + tc->next = new_ctx->list; + new_ctx->list = tc; + old_ctx->total_alloc_size -= tc->size; + new_ctx->total_alloc_size += tc->size; + return ptr; + } + + /* find it in the old context */ + for (tc=old_ctx->list; tc->next; tc=tc->next) { + if (tc->next->ptr == ptr) break; + } + + if (!tc->next) return NULL; + + /* move it to the new context */ + tc2 = tc->next; + tc->next = tc->next->next; + tc2->next = new_ctx->list; + new_ctx->list = tc2; + old_ctx->total_alloc_size -= tc2->size; + new_ctx->total_alloc_size += tc2->size; + + return ptr; +} + + +/** @} */ diff --git a/source4/lib/tallocmsg.c b/source4/lib/tallocmsg.c new file mode 100644 index 0000000000..bbe1ee60a4 --- /dev/null +++ b/source4/lib/tallocmsg.c @@ -0,0 +1,58 @@ +/* + samba -- Unix SMB/CIFS implementation. + Copyright (C) 2001, 2002 by Martin Pool + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * @file tallocmsg.c + * + * Glue code between talloc profiling and the Samba messaging system. + **/ + + +/** + * Respond to a POOL_USAGE message by sending back string form of memory + * usage stats. + **/ +void msg_pool_usage(int msg_type, pid_t src_pid, + void *UNUSED(buf), size_t UNUSED(len)) +{ + char *reply; + TALLOC_CTX *reply_pool = talloc_init("msg_pool_usage"); + + SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); + + DEBUG(2,("Got POOL_USAGE\n")); + + reply = talloc_describe_all(reply_pool); + + message_send_pid(src_pid, MSG_POOL_USAGE, + reply, strlen(reply)+1, True); + + talloc_destroy(reply_pool); +} + +/** + * Register handler for MSG_REQ_POOL_USAGE + **/ +void register_msg_pool_usage(void) +{ + message_register(MSG_REQ_POOL_USAGE, msg_pool_usage); + DEBUG(2, ("Registered MSG_REQ_POOL_USAGE\n")); +} diff --git a/source4/lib/talloctort.c b/source4/lib/talloctort.c new file mode 100644 index 0000000000..ad5de38581 --- /dev/null +++ b/source4/lib/talloctort.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions -- torturer + Copyright (C) 2001 by Martin Pool + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#define NCTX 10 +#define NOBJ 20 + +int main(void) +{ + int i; + TALLOC_CTX *ctx[NCTX]; + + for (i = 0; i < NCTX; i++) { + ctx[i] = talloc_init("torture(%d)", i); + } + + for (i = 0; i < NCTX; i++) { + int j; + for (j = 0; j < NOBJ; j++) { + char *p; + size_t size = 1<<(i/3+j); + + p = talloc(ctx[i], size); + if (!p) { + fprintf(stderr, + "failed to talloc %.0f bytes\n", + (double) size); + exit(1); + } + + memset(p, 'A' + j, size); + } + } + + for (i = 0; i < NCTX; i++) { + printf("talloc@%p %-40s %dkB\n", ctx[i], + talloc_pool_name(ctx[i]), + talloc_pool_size(ctx[i]) >> 10); + } + + printf("%s", talloc_describe_all(ctx[0])); + + for (i = NCTX - 1; i >= 0; i--) + talloc_destroy(ctx[i]); + + return 0; +} diff --git a/source4/lib/tdb/README b/source4/lib/tdb/README new file mode 100644 index 0000000000..fac3eacb4d --- /dev/null +++ b/source4/lib/tdb/README @@ -0,0 +1,167 @@ +tdb - a trivial database system +tridge@linuxcare.com December 1999 +================================== + +This is a simple database API. It was inspired by the realisation that +in Samba we have several ad-hoc bits of code that essentially +implement small databases for sharing structures between parts of +Samba. As I was about to add another I realised that a generic +database module was called for to replace all the ad-hoc bits. + +I based the interface on gdbm. I couldn't use gdbm as we need to be +able to have multiple writers to the databases at one time. + +Compilation +----------- + +add HAVE_MMAP=1 to use mmap instead of read/write +add TDB_DEBUG=1 for verbose debug info +add NOLOCK=1 to disable locking code + +Testing +------- + +Compile tdbtest.c and link with gdbm for testing. tdbtest will perform +identical operations via tdb and gdbm then make sure the result is the +same + +Also included is tdbtool, which allows simple database manipulation +on the commandline. + +tdbtest and tdbtool are not built as part of Samba, but are included +for completeness. + +Interface +--------- + +The interface is very similar to gdbm except for the following: + +- different open interface. The tdb_open call is more similar to a + traditional open() +- no tdbm_reorganise() function +- no tdbm_sync() function. No operations are cached in the library anyway +- added a tdb_traverse() function for traversing the whole database + +A general rule for using tdb is that the caller frees any returned +TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA +return value called p. This is the same as gdbm. + +here is a full list of tdb functions with brief descriptions. + + +---------------------------------------------------------------------- +TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) + + open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the database + file. A flags value of O_WRONLY is invalid + + The hash size is advisory, use zero for a default value. + + return is NULL on error + + possible tdb_flags are: + TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open + TDB_INTERNAL - don't use a file, instaed store the data in + memory. The filename is ignored in this case. + TDB_NOLOCK - don't do any locking + TDB_NOMMAP - don't use mmap + +---------------------------------------------------------------------- +char *tdb_error(TDB_CONTEXT *tdb); + + return a error string for the last tdb error + +---------------------------------------------------------------------- +int tdb_close(TDB_CONTEXT *tdb); + + close a database + +---------------------------------------------------------------------- +int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf); + + update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1 + +---------------------------------------------------------------------- +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); + + fetch an entry in the database given a key + if the return value has a null dptr then a error occurred + + caller must free the resulting data + +---------------------------------------------------------------------- +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); + + check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm + +---------------------------------------------------------------------- +int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, + TDB_DATA key, TDB_DATA dbuf, void *state), void *state); + + traverse the entire database - calling fn(tdb, key, data, state) on each + element. + + return -1 on error or the record count traversed + + if fn is NULL then it is not called + + a non-zero return value from fn() indicates that the traversal should stop + +---------------------------------------------------------------------- +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); + + find the first entry in the database and return its key + + the caller must free the returned data + +---------------------------------------------------------------------- +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); + + find the next entry in the database, returning its key + + the caller must free the returned data + +---------------------------------------------------------------------- +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); + + delete an entry in the database given a key + +---------------------------------------------------------------------- +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); + + store an element in the database, replacing any existing element + with the same key + + If flag==TDB_INSERT then don't overwrite an existing entry + If flag==TDB_MODIFY then don't create a new entry + + return 0 on success, -1 on failure + +---------------------------------------------------------------------- +int tdb_writelock(TDB_CONTEXT *tdb); + + lock the database. If we already have it locked then don't do anything + +---------------------------------------------------------------------- +int tdb_writeunlock(TDB_CONTEXT *tdb); + unlock the database + +---------------------------------------------------------------------- +int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key); + + lock one hash chain. This is meant to be used to reduce locking + contention - it cannot guarantee how many records will be locked + +---------------------------------------------------------------------- +int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key); + + unlock one hash chain diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c new file mode 100644 index 0000000000..2370ce3bdd --- /dev/null +++ b/source4/lib/tdb/spinlock.c @@ -0,0 +1,430 @@ +/* + Unix SMB/CIFS implementation. + Samba database functions + Copyright (C) Anton Blanchard 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if HAVE_CONFIG_H +#include +#endif + +#if STANDALONE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" +#include "spinlock.h" + +#define DEBUG +#else +#include "includes.h" +#endif + +#ifdef USE_SPINLOCKS + +/* + * ARCH SPECIFIC + */ + +#if defined(SPARC_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int result; + + asm volatile("ldstub [%1], %0" + : "=r" (result) + : "r" (lock) + : "memory"); + + return (result == 0) ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#elif defined(POWERPC_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int result; + + __asm__ __volatile__( +"1: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + li %0,0\n\ + bne- 2f\n\ + li %0,1\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r"(result) + : "r"(lock) + : "cr0", "memory"); + + return (result == 1) ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("eieio":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#elif defined(INTEL_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + int oldval; + + asm volatile("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0) + : "memory"); + + return oldval > 0 ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 1; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 1; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 1); +} + +#elif defined(MIPS_SPINLOCKS) + +static inline unsigned int load_linked(unsigned long addr) +{ + unsigned int res; + + __asm__ __volatile__("ll\t%0,(%1)" + : "=r" (res) + : "r" (addr)); + + return res; +} + +static inline unsigned int store_conditional(unsigned long addr, unsigned int value) +{ + unsigned int res; + + __asm__ __volatile__("sc\t%0,(%2)" + : "=r" (res) + : "0" (value), "r" (addr)); + return res; +} + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int mw; + + do { + mw = load_linked(lock); + if (mw) + return EBUSY; + } while (!store_conditional(lock, 1)); + + asm volatile("":::"memory"); + + return 0; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#else +#error Need to implement spinlock code in spinlock.c +#endif + +/* + * OS SPECIFIC + */ + +static void yield_cpu(void) +{ + struct timespec tm; + +#ifdef USE_SCHED_YIELD + sched_yield(); +#else + /* Linux will busy loop for delays < 2ms on real time tasks */ + tm.tv_sec = 0; + tm.tv_nsec = 2000000L + 1; + nanosleep(&tm, NULL); +#endif +} + +static int this_is_smp(void) +{ + return 0; +} + +/* + * GENERIC + */ + +static int smp_machine = 0; + +static inline void __spin_lock(spinlock_t *lock) +{ + int ntries = 0; + + while(__spin_trylock(lock)) { + while(__spin_is_locked(lock)) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __read_lock(tdb_rwlock_t *rwlock) +{ + int ntries = 0; + + while(1) { + __spin_lock(&rwlock->lock); + + if (!(rwlock->count & RWLOCK_BIAS)) { + rwlock->count++; + __spin_unlock(&rwlock->lock); + return; + } + + __spin_unlock(&rwlock->lock); + + while(rwlock->count & RWLOCK_BIAS) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __write_lock(tdb_rwlock_t *rwlock) +{ + int ntries = 0; + + while(1) { + __spin_lock(&rwlock->lock); + + if (rwlock->count == 0) { + rwlock->count |= RWLOCK_BIAS; + __spin_unlock(&rwlock->lock); + return; + } + + __spin_unlock(&rwlock->lock); + + while(rwlock->count != 0) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __write_unlock(tdb_rwlock_t *rwlock) +{ + __spin_lock(&rwlock->lock); + +#ifdef DEBUG + if (!(rwlock->count & RWLOCK_BIAS)) + fprintf(stderr, "bug: write_unlock\n"); +#endif + + rwlock->count &= ~RWLOCK_BIAS; + __spin_unlock(&rwlock->lock); +} + +static void __read_unlock(tdb_rwlock_t *rwlock) +{ + __spin_lock(&rwlock->lock); + +#ifdef DEBUG + if (!rwlock->count) + fprintf(stderr, "bug: read_unlock\n"); + + if (rwlock->count & RWLOCK_BIAS) + fprintf(stderr, "bug: read_unlock\n"); +#endif + + rwlock->count--; + __spin_unlock(&rwlock->lock); +} + +/* TDB SPECIFIC */ + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) +{ + tdb_rwlock_t *rwlocks; + + if (!tdb->map_ptr) return -1; + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + + switch(rw_type) { + case F_RDLCK: + __read_lock(&rwlocks[list+1]); + break; + + case F_WRLCK: + __write_lock(&rwlocks[list+1]); + break; + + default: + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + +/* unlock the database. */ +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) +{ + tdb_rwlock_t *rwlocks; + + if (!tdb->map_ptr) return -1; + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + + switch(rw_type) { + case F_RDLCK: + __read_unlock(&rwlocks[list+1]); + break; + + case F_WRLCK: + __write_unlock(&rwlocks[list+1]); + break; + + default: + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + return 0; +} + +int tdb_create_rwlocks(int fd, unsigned int hash_size) +{ + unsigned size, i; + tdb_rwlock_t *rwlocks; + + size = (hash_size + 1) * sizeof(tdb_rwlock_t); + rwlocks = malloc(size); + if (!rwlocks) + return -1; + + for(i = 0; i < hash_size+1; i++) { + __spin_lock_init(&rwlocks[i].lock); + rwlocks[i].count = 0; + } + + /* Write it out (appending to end) */ + if (write(fd, rwlocks, size) != size) { + free(rwlocks); + return -1; + } + smp_machine = this_is_smp(); + free(rwlocks); + return 0; +} + +int tdb_clear_spinlocks(TDB_CONTEXT *tdb) +{ + tdb_rwlock_t *rwlocks; + unsigned i; + + if (tdb->header.rwlocks == 0) return 0; + if (!tdb->map_ptr) return -1; + + /* We're mmapped here */ + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + for(i = 0; i < tdb->header.hash_size+1; i++) { + __spin_lock_init(&rwlocks[i].lock); + rwlocks[i].count = 0; + } + return 0; +} +#else +int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } + +/* Non-spinlock version: remove spinlock pointer */ +int tdb_clear_spinlocks(TDB_CONTEXT *tdb) +{ + tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks + - (char *)&tdb->header); + + tdb->header.rwlocks = 0; + if (lseek(tdb->fd, off, SEEK_SET) != off + || write(tdb->fd, (void *)&tdb->header.rwlocks, + sizeof(tdb->header.rwlocks)) + != sizeof(tdb->header.rwlocks)) + return -1; + return 0; +} +#endif diff --git a/source4/lib/tdb/spinlock.h b/source4/lib/tdb/spinlock.h new file mode 100644 index 0000000000..d6a2ac6eb8 --- /dev/null +++ b/source4/lib/tdb/spinlock.h @@ -0,0 +1,55 @@ +#ifndef __SPINLOCK_H__ +#define __SPINLOCK_H__ + +#if HAVE_CONFIG_H +#include +#endif + +#include "tdb.h" + +#ifdef USE_SPINLOCKS + +#define RWLOCK_BIAS 0x1000UL + +/* OS SPECIFIC */ +#define MAX_BUSY_LOOPS 1000 +#undef USE_SCHED_YIELD + +/* ARCH SPECIFIC */ +/* We should make sure these are padded to a cache line */ +#if defined(SPARC_SPINLOCKS) +typedef volatile char spinlock_t; +#elif defined(POWERPC_SPINLOCKS) +typedef volatile unsigned long spinlock_t; +#elif defined(INTEL_SPINLOCKS) +typedef volatile int spinlock_t; +#elif defined(MIPS_SPINLOCKS) +typedef volatile unsigned long spinlock_t; +#else +#error Need to implement spinlock code in spinlock.h +#endif + +typedef struct { + spinlock_t lock; + volatile int count; +} tdb_rwlock_t; + +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_create_rwlocks(int fd, unsigned int hash_size); +int tdb_clear_spinlocks(TDB_CONTEXT *tdb); + +#else /* !USE_SPINLOCKS */ +#if 0 +#define tdb_create_rwlocks(fd, hash_size) 0 +#define tdb_spinlock(tdb, list, rw_type) (-1) +#define tdb_spinunlock(tdb, list, rw_type) (-1) +#else +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_create_rwlocks(int fd, unsigned int hash_size); +#endif +int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#endif + +#endif diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c new file mode 100644 index 0000000000..097209ff7a --- /dev/null +++ b/source4/lib/tdb/tdb.c @@ -0,0 +1,2020 @@ + /* + Unix SMB/CIFS implementation. + Samba database functions + Copyright (C) Andrew Tridgell 1999-2000 + Copyright (C) Luke Kenneth Casson Leighton 2000 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#ifdef STANDALONE +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" +#include "spinlock.h" +#else +#include "includes.h" +#endif + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_ALIGNMENT 4 +#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) +#define DEFAULT_HASH_SIZE 131 +#define TDB_PAGE_SIZE 0x2000 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) +TDB_DATA tdb_null; + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static TDB_CONTEXT *tdbs = NULL; + +static int tdb_munmap(TDB_CONTEXT *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +static void tdb_mmap(TDB_CONTEXT *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +static void *convert(void *buf, u32 size) +{ + u32 i, *p = buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) + +/* the body of the database is made of one list_struct for the free space + plus a separate data list for each hash value */ +struct list_struct { + tdb_off next; /* offset of the next record in the list */ + tdb_len rec_len; /* total byte length of record */ + tdb_len key_len; /* byte length of key */ + tdb_len data_len; /* byte length of data */ + u32 full_hash; /* the full 32 bit hash of the key */ + u32 magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + u32 totalsize; (tailer) + } + */ +}; + +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ +static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, + int rw_type, int lck_type, int probe) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) + return 0; + if ((rw_type == F_WRLCK) && (tdb->read_only)) { + errno = EACCES; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = 1; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) + break; + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + if (errno == EINTR && palarm_fired && *palarm_fired) + tdb->ecode = TDB_ERR_LOCK_TIMEOUT; + else + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); + } + /* Was it an alarm timeout ? */ + if (errno == EINTR && palarm_fired && *palarm_fired) + return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); + /* Otherwise - generic lock error. */ + /* errno set by fcntl */ + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + +/* lock a list in the database. list -1 is the alloc list */ +static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) +{ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (tdb->locked[list+1].count == 0) { + if (!tdb->read_only && tdb->header.rwlocks) { + if (tdb_spinlock(tdb, list, ltype)) { + TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n", + list, ltype)); + return -1; + } + } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { + TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", + list, ltype, strerror(errno))); + return -1; + } + tdb->locked[list+1].ltype = ltype; + } + tdb->locked[list+1].count++; + return 0; +} + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) +{ + int ret = -1; + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + if (tdb->locked[list+1].count==0) { + TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); + return ret; + } + + if (tdb->locked[list+1].count == 1) { + /* Down to last nested lock: unlock underneath */ + if (!tdb->read_only && tdb->header.rwlocks) { + ret = tdb_spinunlock(tdb, list, ltype); + } else { + ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + } + } else { + ret = 0; + } + tdb->locked[list+1].count--; + + if (ret) + TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + +/* This is based on the hash algorithm from gdbm */ +static u32 tdb_hash(TDB_DATA *key) +{ + u32 value; /* Used to compute the hash value. */ + u32 i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (fstat(tdb->fd, &st) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + + if (st.st_size < (size_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) +{ + if (tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) + memcpy(off + (char *)tdb->map_ptr, buf, len); +#ifdef HAVE_PWRITE + else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { +#else + else if (lseek(tdb->fd, off, SEEK_SET) != off + || write(tdb->fd, buf, len) != (ssize_t)len) { +#endif + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + return 0; +} + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) +{ + if (tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) + memcpy(buf, off + (char *)tdb->map_ptr, len); +#ifdef HAVE_PREAD + else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { +#else + else if (lseek(tdb->fd, off, SEEK_SET) != off + || read(tdb->fd, buf, len) != (ssize_t)len) { +#endif + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + if (cv) + convert(buf, len); + return 0; +} + +/* read a lump of data, allocating the space for it */ +static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) +{ + char *buf; + + if (!(buf = malloc(len))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_OOM, buf); + } + if (tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* read/write a tdb_off */ +static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) +{ + return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} +static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) +{ + tdb_off off = *d; + return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + +/* read/write a record */ +static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + return tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} +static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + struct list_struct r = *rec; + return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +/* read a freelist record and check for simple errors */ +static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) +{ + if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, 0,"rec_free_read non-free magic at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, + const struct list_struct *rec) +{ + tdb_off totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), + &totalsize); +} + +static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) +{ + struct list_struct rec; + tdb_off tailer_ofs, tailer; + + if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); + if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) +{ + tdb_off rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(TDB_CONTEXT *tdb) +{ + int i; + for (i=0;iheader.hash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(TDB_CONTEXT *tdb) +{ + int ret; + long total_free = 0; + tdb_off offset, rec_ptr; + struct list_struct rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len ); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) +{ + tdb_off last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); +} + +/* Add an element into the freelist. Merge adjacent records if + neccessary. */ +static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + tdb_off right, left; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); + goto fail; + } + + /* Look right first (I'm an Australian, dammit) */ + right = offset + sizeof(*rec) + rec->rec_len; + if (right + sizeof(*rec) <= tdb->map_size) { + struct list_struct r; + + if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + } + } + +left: + /* Look left */ + left = offset - sizeof(tdb_off); + if (left > TDB_HASH_TOP(tdb->header.hash_size-1)) { + struct list_struct l; + tdb_off leftsize; + + /* Read in tailer and jump back to header */ + if (ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + left = offset - leftsize; + + /* Now read in record */ + if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, left, l.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); + goto update; + } else { + offset = left; + rec->rec_len += leftsize; + } + } + } + +update: + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + rec_write(tdb, offset, rec) == -1 || + ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) +{ + char buf[1024]; +#if HAVE_FTRUNCATE_EXTEND + if (ftruncate(tdb->fd, size+addition) != 0) { + TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } +#else + char b = 0; + +#ifdef HAVE_PWRITE + if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { +#else + if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || + write(tdb->fd, &b, 1) != 1) { +#endif + TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } +#endif + + /* now fill the file with something. This ensures that the file isn't sparse, which would be + very bad if we ran out of disk. This must be done with write, not via mmap */ + memset(buf, 0x42, sizeof(buf)); + while (addition) { + int n = addition>sizeof(buf)?sizeof(buf):addition; +#ifdef HAVE_PWRITE + int ret = pwrite(tdb->fd, buf, n, size); +#else + int ret; + if (lseek(tdb->fd, size, SEEK_SET) != size) + return -1; + ret = write(tdb->fd, buf, n); +#endif + if (ret != n) { + TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", + n, strerror(errno))); + return -1; + } + addition -= n; + size += n; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) +{ + struct list_struct rec; + tdb_off offset; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 10 more records, and round + the database up to a multiple of TDB_PAGE_SIZE */ + size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) + tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size); + else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected list_struct within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, + struct list_struct *rec) +{ + tdb_off rec_ptr, last_ptr, newrec_ptr; + struct list_struct newrec; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + /* keep looking until we find a freelist record big enough */ + while (rec_ptr) { + if (rec_free_read(tdb, rec_ptr, rec) == -1) + goto fail; + + if (rec->rec_len >= length) { + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len + - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else + newrec_ptr = 0; + + /* Remove allocated record from the free list */ + if (ofs_write(tdb, last_ptr, &rec->next) == -1) + goto fail; + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (rec_write(tdb, rec_ptr, rec) == -1) + goto fail; + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) + goto fail; + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) + goto fail; + } + + /* all done - return the new record offset */ + tdb_unlock(tdb, -1, F_WRLCK); + return rec_ptr; + } + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + } + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) +{ + struct tdb_header *newdb; + int size, ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); + if (!(newdb = calloc(size, 1))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; +#ifdef USE_SPINLOCKS + newdb->rwlocks = size; +#endif + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + if (write(tdb->fd, newdb, size) != size) + ret = -1; + else + ret = tdb_create_rwlocks(tdb->fd, hash_size); + + fail: + SAFE_FREE(newdb); + return ret; +} + +/* Returns 0 on fail. On success, return offset of record, and fills + in rec */ +static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, + struct list_struct *r) +{ + tdb_off rec_ptr; + + /* read in the hash top */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { + char *k; + /* a very likely hit - read the key */ + k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), + r->key_len); + if (!k) + return 0; + + if (memcmp(key.dptr, k, key.dsize) == 0) { + SAFE_FREE(k); + return rec_ptr; + } + SAFE_FREE(k); + } + rec_ptr = r->next; + } + return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); +} + +/* If they do lockkeys, check that this hash is one they locked */ +static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) +{ + u32 i; + if (!tdb->lockedkeys) + return 1; + for (i = 0; i < tdb->lockedkeys[0]; i++) + if (tdb->lockedkeys[i+1] == hash) + return 1; + return TDB_ERRCODE(TDB_ERR_NOLOCK, 0); +} + +/* As tdb_find, but if you succeed, keep the lock */ +static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype, + struct list_struct *rec) +{ + u32 hash, rec_ptr; + + hash = tdb_hash(&key); + if (!tdb_keylocked(tdb, hash)) + return 0; + if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) + return 0; + if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) + tdb_unlock(tdb, BUCKET(hash), locktype); + return rec_ptr; +} + +enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_NOEXIST, "Record does not exist"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(TDB_CONTEXT *tdb) +{ + u32 i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + +/* update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. +*/ + +static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf) +{ + struct list_struct rec; + tdb_off rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + return -1; + + /* must be long enough key, data and tailer */ + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + dbuf.dptr, dbuf.dsize) == -1) + return -1; + + if (dbuf.dsize != rec.data_len) { + /* update size */ + rec.data_len = dbuf.dsize; + return rec_write(tdb, rec_ptr, &rec); + } + + return 0; +} + +/* find an entry in the database given a key */ +/* If an entry doesn't exist tdb_err will be set to + * TDB_ERR_NOEXIST. If a key has no data attached + * tdb_err will not be set. Both will return a + * zero pptr and zero dsize. + */ + +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) +{ + tdb_off rec_ptr; + struct list_struct rec; + TDB_DATA ret; + + /* find which hash bucket it is in */ + if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec))) + return tdb_null; + + if (rec.data_len) + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); + else + ret.dptr = NULL; + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; +} + +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +{ + struct list_struct rec; + + if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; +} + +/* record lock stops delete underneath */ +static int lock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; +} +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ + +static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ + +static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); +} +/* fcntl locks don't stack: avoid unlocking someone else's */ +static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + struct tdb_traverse_lock *i; + u32 count = 0; + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); +} + +/* actually delete an entry in the database given the offset */ +static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) +{ + tdb_off last_ptr, i; + struct list_struct lastrec; + + if (tdb->read_only) return -1; + + if (write_lock_record(tdb, rec_ptr) == -1) { + /* Someone traversing here: mark it as dead */ + rec->magic = TDB_DEAD_MAGIC; + return rec_write(tdb, rec_ptr, rec); + } + if (write_unlock_record(tdb, rec_ptr) != 0) + return -1; + + /* find previous record in hash chain */ + if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + return -1; + for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) + if (rec_read(tdb, i, &lastrec) == -1) + return -1; + + /* unlink it: next ptr is at start of record. */ + if (last_ptr == 0) + last_ptr = TDB_HASH_TOP(rec->full_hash); + if (ofs_write(tdb, last_ptr, &rec->next) == -1) + return -1; + + /* recover the space */ + if (tdb_free(tdb, rec_ptr, rec) == -1) + return -1; + return 0; +} + +/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ +static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, + struct list_struct *rec) +{ + int want_next = (tlock->off != 0); + + /* No traversal allows if you've called tdb_lockkeys() */ + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) + return -1; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off current; + if (rec_read(tdb, tlock->off, rec) == -1) + goto fail; + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, F_WRLCK); + want_next = 0; + } + /* We finished iteration without finding anything */ + return TDB_ERRCODE(TDB_SUCCESS, 0); + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); + return -1; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state) +{ + TDB_DATA key, dbuf; + struct list_struct rec; + struct tdb_traverse_lock tl = { NULL, 0, 0 }; + int ret, count = 0; + + /* This was in the initializaton, above, but the IRIX compiler + * did not like it. crh + */ + tl.next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = &tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) + goto out; + if (unlock_record(tdb, tl.off) != 0) + TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { + ret = -1; + goto out; + } + if (fn && fn(tdb, key, dbuf, state)) { + /* They want us to terminate traversal */ + ret = count; + if (unlock_record(tdb, tl.off) != 0) { + TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + tdb->travlocks.next = tl.next; + SAFE_FREE(key.dptr); + return count; + } + SAFE_FREE(key.dptr); + } +out: + tdb->travlocks.next = tl.next; + if (ret < 0) + return -1; + else + return count; +} + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) +{ + TDB_DATA key; + struct list_struct rec; + + /* release any old lock */ + if (unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) + return tdb_null; + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) +{ + u32 oldhash; + TDB_DATA key = tdb_null; + struct list_struct rec; + char *k = NULL; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) + return tdb_null; + if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + return tdb_null; + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec); + if (!tdb->travlocks.off) + return tdb_null; + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + return key; +} + +/* delete an entry in the database given a key */ +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +{ + tdb_off rec_ptr; + struct list_struct rec; + int ret; + + if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec))) + return -1; + ret = do_delete(tdb, rec_ptr, &rec); + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); + return ret; +} + +/* store an element in the database, replacing any existing element + with the same key + + return 0 on success, -1 on failure +*/ +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +{ + struct list_struct rec; + u32 hash; + tdb_off rec_ptr; + char *p = NULL; + int ret = 0; + + /* find which hash bucket it is in */ + hash = tdb_hash(&key); + if (!tdb_keylocked(tdb, hash)) + return -1; + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + /* check for it existing, on insert. */ + if (flag == TDB_INSERT) { + if (tdb_exists(tdb, key)) { + tdb->ecode = TDB_ERR_EXISTS; + goto fail; + } + } else { + /* first try in-place update, on modify or replace. */ + if (tdb_update(tdb, key, dbuf) == 0) + goto out; + if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST) + goto fail; + } + /* reset the error code potentially set by the tdb_update() */ + tdb->ecode = TDB_SUCCESS; + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + if (flag != TDB_INSERT) + tdb_delete(tdb, key); + + /* Copy key+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + memcpy(p, key.dptr, key.dsize); + if (dbuf.dsize) + memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); + + /* now we're into insert / modify / replace of a record which + * we know could not be optimised by an in-place store (for + * various reasons). */ + if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec))) + goto fail; + + /* Read hash top into next ptr */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (rec_write(tdb, rec_ptr, &rec) == -1 + || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + out: + SAFE_FREE(p); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; +fail: + ret = -1; + goto out; +} + +/* Attempt to append data to an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. Record must be locked before calling. +*/ +static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +{ + struct list_struct rec; + tdb_off rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + return -1; + + /* Append of 0 is always ok. */ + if (new_dbuf.dsize == 0) + return 0; + + /* must be long enough for key, old data + new data and tailer */ + if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { + /* No room. */ + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, + new_dbuf.dptr, new_dbuf.dsize) == -1) + return -1; + + /* update size */ + rec.data_len += new_dbuf.dsize; + return rec_write(tdb, rec_ptr, &rec); +} + +/* Append to an entry. Create if not exist. */ + +int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +{ + struct list_struct rec; + u32 hash; + tdb_off rec_ptr; + char *p = NULL; + int ret = 0; + size_t new_data_size = 0; + + /* find which hash bucket it is in */ + hash = tdb_hash(&key); + if (!tdb_keylocked(tdb, hash)) + return -1; + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + /* first try in-place. */ + if (tdb_append_inplace(tdb, key, new_dbuf) == 0) + goto out; + + /* reset the error code potentially set by the tdb_append_inplace() */ + tdb->ecode = TDB_SUCCESS; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { + if (tdb->ecode != TDB_ERR_NOEXIST) + goto fail; + + /* Not found - create. */ + + ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); + goto out; + } + + new_data_size = rec.data_len + new_dbuf.dsize; + + /* Copy key+old_value+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + new_data_size))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + /* Copy the key in place. */ + memcpy(p, key.dptr, key.dsize); + + /* Now read the old data into place. */ + if (rec.data_len && + tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) + goto fail; + + /* Finally append the new data. */ + if (new_dbuf.dsize) + memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + + tdb_delete(tdb, key); + + if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) + goto fail; + + /* Read hash top into next ptr */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = new_data_size; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (rec_write(tdb, rec_ptr, &rec) == -1 + || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 + || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + + out: + SAFE_FREE(p); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; + +fail: + ret = -1; + goto out; +} + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + TDB_CONTEXT *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL); +} + + +TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn) +{ + TDB_CONTEXT *tdb; + struct stat st; + int rev = 0, locked; + unsigned char *vp; + u32 vertest; + + if (!(tdb = calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb->fd = -1; + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->lockedkeys = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + tdb->log_fn = log_fn; + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* ensure there is only one process initialising at once */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0)) + && (tdb_flags & TDB_CLEAR_IF_FIRST)) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 + || tdb->header.version != TDB_VERSION + || (tdb->header.hash_size != hash_size + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { + /* its not a valid database - possibly initialise it */ + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } + vp = (unsigned char *)&tdb->header.version; + vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | + (((u32)vp[2]) << 8) | (u32)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, st.st_dev, st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); + if (!tdb->locked) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "failed to allocate lock structure for %s\n", + name)); + errno = ENOMEM; + goto fail; + } + tdb_mmap(tdb); + if (locked) { + if (!tdb->read_only) + if (tdb_clear_spinlocks(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to clear spinlock\n")); + goto fail; + } + if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + } + /* leave this lock in place to indicate it's in use */ + if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) + goto fail; + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(TDB_CONTEXT *tdb) +{ + TDB_CONTEXT **i; + int ret = 0; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + ret = close(tdb->fd); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb->lockedkeys); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* lock/unlock entire database */ +int tdb_lockall(TDB_CONTEXT *tdb) +{ + u32 i; + + /* There are no locks on read-only dbs */ + if (tdb->read_only) + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + for (i = 0; i < tdb->header.hash_size; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < tdb->header.hash_size) { + u32 j; + + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + + return 0; +} +void tdb_unlockall(TDB_CONTEXT *tdb) +{ + u32 i; + for (i=0; i < tdb->header.hash_size; i++) + tdb_unlock(tdb, i, F_WRLCK); +} + +int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) +{ + u32 i, j, hash; + + /* Can't lock more keys if already locked */ + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + if (!(tdb->lockedkeys = malloc(sizeof(u32) * (number+1)))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + /* First number in array is # keys */ + tdb->lockedkeys[0] = number; + + /* Insertion sort by bucket */ + for (i = 0; i < number; i++) { + hash = tdb_hash(&keys[i]); + for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++); + memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j)); + tdb->lockedkeys[j+1] = hash; + } + /* Finally, lock in order */ + for (i = 0; i < number; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < number) { + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + SAFE_FREE(tdb->lockedkeys); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + return 0; +} + +/* Unlock the keys previously locked by tdb_lockkeys() */ +void tdb_unlockkeys(TDB_CONTEXT *tdb) +{ + u32 i; + for (i = 0; i < tdb->lockedkeys[0]; i++) + tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK); + SAFE_FREE(tdb->lockedkeys); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); +} + +int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); +} + +int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + + +/* register a loging function */ +void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) +{ + tdb->log_fn = fn; +} + + +/* reopen a tdb - this is used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(TDB_CONTEXT *tdb) +{ + struct stat st; + + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(void) +{ + TDB_CONTEXT *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + if (tdb_reopen(tdb) != 0) return -1; + } + + return 0; +} diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h new file mode 100644 index 0000000000..6f3b1ff756 --- /dev/null +++ b/source4/lib/tdb/tdb.h @@ -0,0 +1,144 @@ +#ifndef __TDB_H__ +#define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + Samba database functions + Copyright (C) Andrew Tridgell 1999 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* flags to tdb_store() */ +#define TDB_REPLACE 1 +#define TDB_INSERT 2 +#define TDB_MODIFY 3 + +/* flags for tdb_open() */ +#define TDB_DEFAULT 0 /* just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 +#define TDB_INTERNAL 2 /* don't store on disk */ +#define TDB_NOLOCK 4 /* don't do any locking */ +#define TDB_NOMMAP 8 /* don't use mmap */ +#define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ + +#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) + +/* error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT }; + +#ifndef u32 +#define u32 unsigned +#endif + +typedef struct { + char *dptr; + size_t dsize; +} TDB_DATA; + +typedef u32 tdb_len; +typedef u32 tdb_off; + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + u32 version; /* version of the code */ + u32 hash_size; /* number of hash entries */ + tdb_off rwlocks; + tdb_off reserved[31]; +}; + +struct tdb_lock_type { + u32 count; + u32 ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + u32 off; + u32 hash; +}; + +/* this is the context structure that is returned from a db open */ +typedef struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + struct tdb_lock_type *locked; /* array of chain locks */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + u32 flags; /* the flags passed to tdb_open */ + u32 *lockedkeys; /* array of locked keys: first is #keys */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ + int open_flags; /* flags used in the open - needed by reopen */ +} TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); + +TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); +TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn); + +int tdb_reopen(TDB_CONTEXT *tdb); +int tdb_reopen_all(void); +void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); +enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); +const char *tdb_errorstr(TDB_CONTEXT *tdb); +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(TDB_CONTEXT *tdb); +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state); +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); +void tdb_unlockkeys(TDB_CONTEXT *tdb); +int tdb_lockall(TDB_CONTEXT *tdb); +void tdb_unlockall(TDB_CONTEXT *tdb); + +/* Low level locking functions: use with care */ +void tdb_set_lock_alarm(sig_atomic_t *palarm); +int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(TDB_CONTEXT *tdb); +int tdb_printfreelist(TDB_CONTEXT *tdb); + +extern TDB_DATA tdb_null; + +#ifdef __cplusplus +} +#endif + +#endif /* tdb.h */ diff --git a/source4/lib/tdb/tdb.magic b/source4/lib/tdb/tdb.magic new file mode 100644 index 0000000000..f5619e7327 --- /dev/null +++ b/source4/lib/tdb/tdb.magic @@ -0,0 +1,10 @@ +# Magic file(1) information about tdb files. +# +# Install this into /etc/magic or the corresponding location for your +# system, or pass as a -m argument to file(1). + +# You may use and redistribute this file without restriction. + +0 string TDB\ file TDB database +>32 lelong =0x2601196D version 6, little-endian +>>36 lelong x hash size %d bytes diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c new file mode 100644 index 0000000000..0d8f6128cc --- /dev/null +++ b/source4/lib/tdb/tdbutil.c @@ -0,0 +1,687 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = dptr; + ret.dsize = dsize; + return ret; +} + +/**************************************************************************** + Lock a chain with timeout (in seconds). +****************************************************************************/ + +static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +{ + /* Allow tdb_chainlock to be interrupted by an alarm. */ + int ret; + gotalarm = 0; + tdb_set_lock_alarm(&gotalarm); + + if (timeout) { + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + if (rw_type == F_RDLCK) + ret = tdb_chainlock_read(tdb, key); + else + ret = tdb_chainlock(tdb, key); + + if (timeout) { + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) { + DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb->name )); + /* TODO: If we time out waiting for a lock, it might + * be nice to use F_GETLK to get the pid of the + * process currently holding the lock and print that + * as part of the debugging message. -- mbp */ + return -1; + } + } + + return ret; +} + +/**************************************************************************** + Write lock a chain. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +{ + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32 value by a arbitrary blob key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + int32 ret; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(int32)) { + SAFE_FREE(data.dptr); + return -1; + } + + ret = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return ret; +} + +/**************************************************************************** + Fetch a int32 value by string key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); +} + +/**************************************************************************** + Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + int32 v_store; + + SIVAL(&v_store,0,v); + data.dptr = (void *)&v_store; + data.dsize = sizeof(int32); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32 value by string key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) +{ + return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); +} + +/**************************************************************************** + Fetch a uint32 value by a arbitrary blob key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(uint32)) { + SAFE_FREE(data.dptr); + return False; + } + + *value = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return True; +} + +/**************************************************************************** + Fetch a uint32 value by string key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +{ + return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} + +/**************************************************************************** + Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + uint32 v_store; + BOOL ret = True; + + SIVAL(&v_store, 0, value); + data.dptr = (void *)&v_store; + data.dsize = sizeof(uint32); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) + ret = False; + + return ret; +} + +/**************************************************************************** + Store a uint32 value by string key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +{ + return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -1 + on failure. +****************************************************************************/ + +int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_by_string(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) +{ + int32 val; + int32 ret = -1; + + if (tdb_lock_bystring(tdb, keystr,0) == -1) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not becouse it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) == -1) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +{ + uint32 val; + BOOL ret = False; + + if (tdb_lock_bystring(tdb, keystr,0) == -1) + return False; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not becouse it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = True; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint16 w; + uint32 d; + int i; + void *p; + int len; + char *s; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c = *fmt++)) { + case 'w': + len = 2; + w = (uint16)va_arg(ap, int); + if (bufsize >= len) + SSVAL(buf, 0, w); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32); + if (bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'p': + len = 4; + p = va_arg(ap, void *); + d = p?1:0; + if (bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'P': + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize >= len) + memcpy(buf, s, len); + break; + case 'f': + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize >= len) + memcpy(buf, s, len); + break; + case 'B': + i = va_arg(ap, int); + s = va_arg(ap, char *); + len = 4+i; + if (bufsize >= len) { + SIVAL(buf, 0, i); + memcpy(buf+4, s, i); + } + break; + default: + DEBUG(0,("Unknown tdb_pack format %c in %s\n", + c, fmt)); + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + DEBUG(18,("tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint16 *w; + uint32 *d; + int len; + int *i; + void **p; + char *s, **b; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c=*fmt++)) { + case 'w': + len = 2; + w = va_arg(ap, uint16 *); + if (bufsize < len) + goto no_space; + *w = SVAL(buf, 0); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32 *); + if (bufsize < len) + goto no_space; + *d = IVAL(buf, 0); + break; + case 'p': + len = 4; + p = va_arg(ap, void **); + if (bufsize < len) + goto no_space; + *p = (void *)IVAL(buf, 0); + break; + case 'P': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(pstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'f': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(fstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'B': + i = va_arg(ap, int *); + b = va_arg(ap, char **); + len = 4; + if (bufsize < len) + goto no_space; + *i = IVAL(buf, 0); + if (! *i) { + *b = NULL; + break; + } + len += *i; + if (bufsize < len) + goto no_space; + *b = (char *)malloc(*i); + if (! *b) + goto no_space; + memcpy(*b, buf+4, *i); + break; + default: + DEBUG(0,("Unknown tdb_unpack format %c in %s\n", + c, fmt)); + + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + + return PTR_DIFF(buf, buf0); + + no_space: + return -1; +} + +/**************************************************************************** + Log tdb messages via DEBUG(). +****************************************************************************/ + +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + SAFE_FREE(ptr); +} + +/**************************************************************************** + Like tdb_open() but also setup a logging function that redirects to + the samba DEBUG() system. +****************************************************************************/ + +TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + TDB_CONTEXT *tdb; + + if (!lp_use_mmap()) + tdb_flags |= TDB_NOMMAP; + + tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, tdb_log); + if (!tdb) + return NULL; + + return tdb; +} + + +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + +/** + * Search across the whole tdb for keys that match the given pattern + * return the result as a list of keys + * + * @param tdb pointer to opened tdb file context + * @param pattern searching pattern used by fnmatch(3) functions + * + * @return list of keys found by looking up with given pattern + **/ +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) +{ + TDB_DATA key, next; + TDB_LIST_NODE *list = NULL; + TDB_LIST_NODE *rec = NULL; + TDB_LIST_NODE *tmp = NULL; + + for (key = tdb_firstkey(tdb); key.dptr; key = next) { + /* duplicate key string to ensure null-termination */ + char *key_str = (char*) strndup(key.dptr, key.dsize); + if (!key_str) { + DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); + smb_panic("strndup failed!\n"); + } + + DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern)); + + next = tdb_nextkey(tdb, key); + + /* do the pattern checking */ + if (fnmatch(pattern, key_str, 0) == 0) { + rec = (TDB_LIST_NODE*) malloc(sizeof(*rec)); + ZERO_STRUCTP(rec); + + rec->node_key = key; + + DLIST_ADD_END(list, rec, tmp); + + DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern)); + } else { + free(key.dptr); + } + + /* free duplicated key string */ + free(key_str); + } + + return list; + +}; + + +/** + * Free the list returned by tdb_search_keys + * + * @param node list of results found by tdb_search_keys + **/ +void tdb_search_list_free(TDB_LIST_NODE* node) +{ + TDB_LIST_NODE *next_node; + + while (node) { + next_node = node->next; + SAFE_FREE(node); + node = next_node; + }; +}; + + diff --git a/source4/lib/tdb/tdbutil.h b/source4/lib/tdb/tdbutil.h new file mode 100644 index 0000000000..01473446a1 --- /dev/null +++ b/source4/lib/tdb/tdbutil.h @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1999 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDBUTIL_H__ +#define __TDBUTIL_H__ + + +/* single node of a list returned by tdb_search_keys */ +typedef struct keys_node +{ + struct keys_node *prev, *next; + TDB_DATA node_key; +} TDB_LIST_NODE; + + +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); +void tdb_search_list_free(TDB_LIST_NODE*); + + +#endif /* __TDBUTIL_H__ */ diff --git a/source4/lib/time.c b/source4/lib/time.c new file mode 100644 index 0000000000..2844da004d --- /dev/null +++ b/source4/lib/time.c @@ -0,0 +1,754 @@ +/* + Unix SMB/CIFS implementation. + time handling functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Stefan (metze) Metzmacher 2002 + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This stuff was largely rewritten by Paul Eggert + in May 1996 + */ + + +int extra_time_offset = 0; + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifndef TIME_T_MIN +#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ + : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)) +#endif +#ifndef TIME_T_MAX +#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) +#endif + +void get_nttime_max(NTTIME *t) +{ + /* FIXME: This is incorrect */ + unix_to_nt_time(t, get_time_t_max()); +} + +/******************************************************************* + External access to time_t_min and time_t_max. +********************************************************************/ + +time_t get_time_t_max(void) +{ + return TIME_T_MAX; +} + +/******************************************************************* +a gettimeofday wrapper +********************************************************************/ +void GetTimeOfDay(struct timeval *tval) +{ +#ifdef HAVE_GETTIMEOFDAY_TZ + gettimeofday(tval,NULL); +#else + gettimeofday(tval); +#endif +} + +#define TM_YEAR_BASE 1900 + +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (TM_YEAR_BASE - 1); + int by = b->tm_year + (TM_YEAR_BASE - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + +/******************************************************************* + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + ******************************************************************/ +static int TimeZone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); + +} + +static BOOL done_serverzone_init; + +/* Return the smb serverzone value */ + +static int get_serverzone(void) +{ + static int serverzone; + + if (!done_serverzone_init) { + serverzone = TimeZone(time(NULL)); + + if ((serverzone % 60) != 0) { + DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n")); + } + + DEBUG(4,("Serverzone is %d\n",serverzone)); + + done_serverzone_init = True; + } + + return serverzone; +} + +/* Re-read the smb serverzone value */ + +static struct timeval start_time_hires; + +void TimeInit(void) +{ + done_serverzone_init = False; + get_serverzone(); + /* Save the start time of this process. */ + if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) + GetTimeOfDay(&start_time_hires); +} + +/********************************************************************** + Return a timeval struct of the uptime of this process. As TimeInit is + done before a daemon fork then this is the start time from the parent + daemon start. JRA. +***********************************************************************/ + +void get_process_uptime(struct timeval *ret_time) +{ + struct timeval time_now_hires; + + GetTimeOfDay(&time_now_hires); + ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec; + ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; + if (time_now_hires.tv_usec < start_time_hires.tv_usec) { + ret_time->tv_sec -= 1; + ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec); + } else + ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; +} + +/******************************************************************* +return the same value as TimeZone, but it should be more efficient. + +We keep a table of DST offsets to prevent calling localtime() on each +call of this function. This saves a LOT of time on many unixes. + +Updated by Paul Eggert +********************************************************************/ +static int TimeZoneFaster(time_t t) +{ + static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL; + static int table_size = 0; + int i; + int zone = 0; + + if (t == 0) t = time(NULL); + + /* Tunis has a 8 day DST region, we need to be careful ... */ +#define MAX_DST_WIDTH (365*24*60*60) +#define MAX_DST_SKIP (7*24*60*60) + + for (i=0;i= dst_table[i].start && t <= dst_table[i].end) break; + + if (i MAX_DST_SKIP*2) + t = dst_table[i].start - MAX_DST_SKIP; + else + t = low + (dst_table[i].start-low)/2; + if (TimeZone(t) == zone) + dst_table[i].start = t; + else + low = t; + } + + while (high-60*60 > dst_table[i].end) { + if (high - dst_table[i].end > MAX_DST_SKIP*2) + t = dst_table[i].end + MAX_DST_SKIP; + else + t = high - (high-dst_table[i].end)/2; + if (TimeZone(t) == zone) + dst_table[i].end = t; + else + high = t; + } +#if 0 + DEBUG(1,("Added DST entry from %s ", + asctime(localtime(&dst_table[i].start)))); + DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)), + dst_table[i].zone)); +#endif + } + } + return zone; +} + +/**************************************************************************** + return the UTC offset in seconds west of UTC, adjusted for extra time offset + **************************************************************************/ +int TimeDiff(time_t t) +{ + return TimeZoneFaster(t) + 60 * lp_time_offset(); +} + + +/**************************************************************************** + return the UTC offset in seconds west of UTC, adjusted for extra time + offset, for a local time value. If ut = lt + LocTimeDiff(lt), then + lt = ut - TimeDiff(ut), but the converse does not necessarily hold near + daylight savings transitions because some local times are ambiguous. + LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions. + +**************************************************************************/ +static int LocTimeDiff(time_t lte) +{ + time_t lt = lte - 60 * lp_time_offset(); + int d = TimeZoneFaster(lt); + time_t t = lt + d; + + /* if overflow occurred, ignore all the adjustments so far */ + if (((lte < lt) ^ (lp_time_offset() < 0)) | ((t < lt) ^ (d < 0))) + t = lte; + + /* now t should be close enough to the true UTC to yield the right answer */ + return TimeDiff(t); +} + + +/**************************************************************************** +try to optimise the localtime call, it can be quite expensive on some machines +****************************************************************************/ +struct tm *LocalTime(time_t *t) +{ + time_t t2 = *t; + + t2 -= TimeDiff(t2); + + return(gmtime(&t2)); +} + +#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) + +/**************************************************************************** +interpret an 8 byte "filetime" structure to a time_t +It's originally in "100ns units since jan 1st 1601" + +It appears to be kludge-GMT (at least for file listings). This means +its the GMT you get by taking a localtime and adding the +serverzone. This is NOT the same as GMT in some cases. This routine +converts this to real GMT. +****************************************************************************/ +time_t nt_time_to_unix(const NTTIME *nt) +{ + double d; + time_t ret; + /* The next two lines are a fix needed for the + broken SCO compiler. JRA. */ + time_t l_time_min = TIME_T_MIN; + time_t l_time_max = TIME_T_MAX; + + if (nt->high == 0) return(0); + + d = ((double)nt->high)*4.0*(double)(1<<30); + d += (nt->low&0xFFF00000); + d *= 1.0e-7; + + /* now adjust by 369 years to make the secs since 1970 */ + d -= TIME_FIXUP_CONSTANT; + + if (!(l_time_min <= d && d <= l_time_max)) + return(0); + + ret = (time_t)(d+0.5); + + /* this takes us from kludge-GMT to real GMT */ + ret -= get_serverzone(); + ret += LocTimeDiff(ret); + + return(ret); +} + +/**************************************************************************** + Convert a NTTIME structure to a time_t. + It's originally in "100ns units". + + This is an absolute version of the one above. + By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 + if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM +****************************************************************************/ + +time_t nt_time_to_unix_abs(NTTIME *nt) +{ + double d; + time_t ret; + /* The next two lines are a fix needed for the + broken SCO compiler. JRA. */ + time_t l_time_min = TIME_T_MIN; + time_t l_time_max = TIME_T_MAX; + + if (nt->high == 0) + return(0); + + if (nt->high==0x80000000 && nt->low==0) + return -1; + + /* reverse the time */ + /* it's a negative value, turn it to positive */ + nt->high=~nt->high; + nt->low=~nt->low; + + d = ((double)nt->high)*4.0*(double)(1<<30); + d += (nt->low&0xFFF00000); + d *= 1.0e-7; + + if (!(l_time_min <= d && d <= l_time_max)) + return(0); + + ret = (time_t)(d+0.5); + + return(ret); +} + +/**************************************************************************** +put a 8 byte filetime from a time_t +This takes real GMT as input and converts to kludge-GMT +****************************************************************************/ +void unix_to_nt_time(NTTIME *nt, time_t t) +{ + double d; + + if (t==0) { + nt->low = 0; + nt->high = 0; + return; + } + if (t == TIME_T_MAX) { + nt->low = 0xffffffff; + nt->high = 0x7fffffff; + return; + } + if (t == -1) { + nt->low = 0xffffffff; + nt->high = 0xffffffff; + return; + } + + /* this converts GMT to kludge-GMT */ + t -= TimeDiff(t) - get_serverzone(); + + d = (double)(t); + d += TIME_FIXUP_CONSTANT; + d *= 1.0e7; + + nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); + nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); +} + +/**************************************************************************** + Convert a time_t to a NTTIME structure + + This is an absolute version of the one above. + By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 + If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM +****************************************************************************/ + +void unix_to_nt_time_abs(NTTIME *nt, time_t t) +{ + double d; + + if (t==0) { + nt->low = 0; + nt->high = 0; + return; + } + + if (t == TIME_T_MAX) { + nt->low = 0xffffffff; + nt->high = 0x7fffffff; + return; + } + + if (t == -1) { + /* that's what NT uses for infinite */ + nt->low = 0x0; + nt->high = 0x80000000; + return; + } + + d = (double)(t); + d *= 1.0e7; + + nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); + nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); + + /* convert to a negative value */ + nt->high=~nt->high; + nt->low=~nt->low; +} + + +/**************************************************************************** +take an NTTIME structure, containing high / low time. convert to unix time. +lkclXXXX this may need 2 SIVALs not a memcpy. we'll see... +****************************************************************************/ +void put_long_date(char *p,time_t t) +{ + NTTIME nt; + unix_to_nt_time(&nt, t); + SIVAL(p, 0, nt.low); + SIVAL(p, 4, nt.high); +} + +/**************************************************************************** +check if it's a null mtime +****************************************************************************/ +BOOL null_mtime(time_t mtime) +{ + if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1) + return True; + return False; +} + +/******************************************************************* + create a 16 bit dos packed date +********************************************************************/ +static uint16 make_dos_date1(struct tm *t) +{ + uint16 ret=0; + ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); + ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 16 bit dos packed time +********************************************************************/ +static uint16 make_dos_time1(struct tm *t) +{ + uint16 ret=0; + ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); + ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 32 bit dos packed date/time from some parameters + This takes a GMT time and returns a packed localtime structure +********************************************************************/ +static uint32 make_dos_date(time_t unixdate) +{ + struct tm *t; + uint32 ret=0; + + if (unixdate == 0) { + return 0; + } + + t = LocalTime(&unixdate); + if (!t) { + return 0xFFFFFFFF; + } + + ret = make_dos_date1(t); + ret = ((ret&0xFFFF)<<16) | make_dos_time1(t); + + return ret; +} + +/******************************************************************* +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +********************************************************************/ +void put_dos_date(char *buf,int offset,time_t unixdate) +{ + uint32 x = make_dos_date(unixdate); + SIVAL(buf,offset,x); +} + +/******************************************************************* +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +********************************************************************/ +void put_dos_date2(char *buf,int offset,time_t unixdate) +{ + uint32 x; + x = make_dos_date(unixdate); + x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(buf,offset,x); +} + +/******************************************************************* +put a dos 32 bit "unix like" date into a buffer. This routine takes +GMT and converts it to LOCAL time before putting it (most SMBs assume +localtime for this sort of date) +********************************************************************/ +void put_dos_date3(char *buf,int offset,time_t unixdate) +{ + if (!null_mtime(unixdate)) + unixdate -= TimeDiff(unixdate); + SIVAL(buf,offset,unixdate); +} + +/******************************************************************* + interpret a 32 bit dos packed date/time to some parameters +********************************************************************/ +static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) +{ + uint32 p0,p1,p2,p3; + + p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; + p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; + + *second = 2*(p0 & 0x1F); + *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); + *hour = (p1>>3)&0xFF; + *day = (p2&0x1F); + *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; + *year = ((p3>>1)&0xFF) + 80; +} + +/******************************************************************* + create a unix date (int GMT) from a dos date (which is actually in + localtime) +********************************************************************/ +time_t make_unix_date(void *date_ptr) +{ + uint32 dos_date=0; + struct tm t; + time_t ret; + + dos_date = IVAL(date_ptr,0); + + if (dos_date == 0) return (time_t)0; + + interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, + &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); + t.tm_isdst = -1; + + /* mktime() also does the local to GMT time conversion for us */ + ret = mktime(&t); + + return(ret); +} + +/******************************************************************* +like make_unix_date() but the words are reversed +********************************************************************/ +time_t make_unix_date2(void *date_ptr) +{ + uint32 x,x2; + + x = IVAL(date_ptr,0); + x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(&x,0,x2); + + return make_unix_date((void *)&x); +} + +/******************************************************************* + create a unix GMT date from a dos date in 32 bit "unix like" format + these generally arrive as localtimes, with corresponding DST + ******************************************************************/ +time_t make_unix_date3(void *date_ptr) +{ + time_t t = (time_t)IVAL(date_ptr,0); + if (!null_mtime(t)) + t += LocTimeDiff(t); + return t; +} + + +/*************************************************************************** +return a HTTP/1.0 time string + ***************************************************************************/ +char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + char *buf; + fstring tempTime; + struct tm *tm = LocalTime(&t); + + if (!tm) + buf = talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); + else +#ifndef HAVE_STRFTIME + buf = talloc_strdup(mem_ctx, asctime(tm)); + if(buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = 0; +#else /* !HAVE_STRFTIME */ + strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); + buf = talloc_strdup(mem_ctx, tempTime); +#endif /* !HAVE_STRFTIME */ + return buf; +} + + + +/**************************************************************************** + Return the date and time as a string +****************************************************************************/ + +char *timestring(TALLOC_CTX *mem_ctx, BOOL hires) +{ + char *TimeBuf; + fstring tempTime; + struct timeval tp; + time_t t; + struct tm *tm; + + if (hires) { + GetTimeOfDay(&tp); + t = (time_t)tp.tv_sec; + } else { + t = time(NULL); + } + tm = LocalTime(&t); + if (!tm) { + if (hires) { + TimeBuf = talloc_asprintf(mem_ctx, + "%ld.%06ld seconds since the Epoch", + (long)tp.tv_sec, + (long)tp.tv_usec); + } else { + TimeBuf = talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + } else { +#ifdef HAVE_STRFTIME + if (hires) { + strftime(tempTime,sizeof(tempTime)-1,"%Y/%m/%d %H:%M:%S",tm); + TimeBuf = talloc_asprintf(mem_ctx, "%s.%06ld", + tempTime, (long)tp.tv_usec); + } else { + strftime(tempTime,100,"%Y/%m/%d %H:%M:%S",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); + } +#else + if (hires) { + TimeBuf = talloc_asprintf(mem_ctx, + "%s.%06ld", + asctime(tm), + (long)tp.tv_usec); + } else { + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); + } +#endif + } + return(TimeBuf); +} + +/**************************************************************************** + return the best approximation to a 'create time' under UNIX from a stat + structure. +****************************************************************************/ + +time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) +{ + time_t ret, ret1; + + if(S_ISDIR(st->st_mode) && fake_dirs) + return (time_t)315493200L; /* 1/1/1980 */ + + ret = MIN(st->st_ctime, st->st_mtime); + ret1 = MIN(ret, st->st_atime); + + if(ret1 != (time_t)0) + return ret1; + + /* + * One of ctime, mtime or atime was zero (probably atime). + * Just return MIN(ctime, mtime). + */ + return ret; +} + +/**************************************************************************** +initialise an NTTIME to -1, which means "unknown" or "don't expire" +****************************************************************************/ + +void init_nt_time(NTTIME *nt) +{ + nt->high = 0x7FFFFFFF; + nt->low = 0xFFFFFFFF; +} + +/**************************************************************************** +check if NTTIME is 0 +****************************************************************************/ +BOOL nt_time_is_zero(NTTIME *nt) +{ + if(nt->high==0) + return True; + return False; +} + +/* + return a talloced string representing a NTTIME for human consumption +*/ +const char *nt_time_string(TALLOC_CTX *mem_ctx, const NTTIME *nt) +{ + time_t t = nt_time_to_unix(nt); + return talloc_strdup(mem_ctx, http_timestring(mem_ctx, t)); +} + diff --git a/source4/lib/username.c b/source4/lib/username.c new file mode 100644 index 0000000000..c00ac666d4 --- /dev/null +++ b/source4/lib/username.c @@ -0,0 +1,537 @@ +/* + Unix SMB/CIFS implementation. + Username handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1997-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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* internal functions */ +static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N); +static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N); + +/***************************************************************** + Check if a user or group name is local (this is a *local* name for + *local* people, there's nothing for you here...). +*****************************************************************/ + +static BOOL name_is_local(const char *name) +{ + return !(strchr_m(name, *lp_winbind_separator())); +} + +/***************************************************************** + Splits passed user or group name to domain and user/group name parts + Returns True if name was splitted and False otherwise. +*****************************************************************/ + +BOOL split_domain_and_name(const char *name, char *domain, char* username) +{ + char *p = strchr(name,*lp_winbind_separator()); + + + /* Parse a string of the form DOMAIN/user into a domain and a user */ + DEBUG(10,("split_domain_and_name: checking whether name |%s| local or not\n", name)); + + if (p) { + fstrcpy(username, p+1); + fstrcpy(domain, name); + domain[PTR_DIFF(p, name)] = 0; + } else if (lp_winbind_use_default_domain()) { + fstrcpy(username, name); + fstrcpy(domain, lp_workgroup()); + } else { + return False; + } + + DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and name is |%s|\n", domain, username)); + return True; +} + +/**************************************************************************** + Get a users home directory. +****************************************************************************/ + +char *get_user_home_dir(const char *user) +{ + struct passwd *pass; + + /* Ensure the user exists. */ + + pass = Get_Pwnam(user); + + if (!pass) + return(NULL); + /* Return home directory from struct passwd. */ + + return(pass->pw_dir); +} + + +/**************************************************************************** + * A wrapper for sys_getpwnam(). The following variations are tried: + * - as transmitted + * - in all lower case if this differs from transmitted + * - in all upper case if this differs from transmitted + * - using lp_usernamelevel() for permutations. +****************************************************************************/ + +static struct passwd *Get_Pwnam_ret = NULL; + +static struct passwd *Get_Pwnam_internals(const char *user, char *user2) +{ + struct passwd *ret = NULL; + + if (!user2 || !(*user2)) + return(NULL); + + if (!user || !(*user)) + return(NULL); + + /* Try in all lower case first as this is the most + common case on UNIX systems */ + strlower(user2); + DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); + ret = getpwnam_alloc(user2); + if(ret) + goto done; + + /* Try as given, if username wasn't originally lowercase */ + if(strcmp(user, user2) != 0) { + DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n", user)); + ret = getpwnam_alloc(user); + if(ret) + goto done; + } + + /* Try as uppercase, if username wasn't originally uppercase */ + strupper(user2); + if(strcmp(user, user2) != 0) { + DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", user2)); + ret = getpwnam_alloc(user2); + if(ret) + goto done; + } + + /* Try all combinations up to usernamelevel */ + strlower(user2); + DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", lp_usernamelevel(), user2)); + ret = uname_string_combinations(user2, getpwnam_alloc, lp_usernamelevel()); + +done: + DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ? "did":"didn't", user)); + + /* This call used to just return the 'passwd' static buffer. + This could then have accidental reuse implications, so + we now malloc a copy, and free it in the next use. + + This should cause the (ab)user to segfault if it + uses an old struct. + + This is better than useing the wrong data in security + critical operations. + + The real fix is to make the callers free the returned + malloc'ed data. + */ + + if (Get_Pwnam_ret) { + passwd_free(&Get_Pwnam_ret); + } + + Get_Pwnam_ret = ret; + + return ret; +} + +/**************************************************************************** + Get_Pwnam wrapper without modification. + NOTE: This with NOT modify 'user'! +****************************************************************************/ + +struct passwd *Get_Pwnam(const char *user) +{ + fstring user2; + struct passwd *ret; + + fstrcpy(user2, user); + + DEBUG(5,("Finding user %s\n", user)); + + ret = Get_Pwnam_internals(user, user2); + + return ret; +} + +/**************************************************************************** + Check if a user is in a netgroup user list. +****************************************************************************/ + +static BOOL user_in_netgroup_list(const char *user, const char *ngname) +{ +#ifdef HAVE_NETGROUP + //static char *mydomain = NULL; + /* REWRITE: make thread safe if caching */ + char *mydomain = NULL; + //if (mydomain == NULL) + yp_get_default_domain(&mydomain); + + if(mydomain == NULL) { + DEBUG(5,("Unable to get default yp domain\n")); + return False; + } + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + user, mydomain, ngname)); + DEBUG(5,("innetgr is %s\n", innetgr(ngname, NULL, user, mydomain) + ? "TRUE" : "FALSE")); + + if (innetgr(ngname, NULL, user, mydomain)) + return (True); +#endif /* HAVE_NETGROUP */ + return False; +} + +/**************************************************************************** + Check if a user is in a winbind group. +****************************************************************************/ + +static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered) +{ + int num_groups; + int i; + gid_t *groups = NULL; + gid_t gid, gid_low, gid_high; + BOOL ret = False; + + *winbind_answered = False; + + if ((gid = nametogid(gname)) == (gid_t)-1) { + DEBUG(0,("user_in_winbind_group_list: nametogid for group %s failed.\n", + gname )); + goto err; + } + + if (!lp_winbind_gid(&gid_low, &gid_high)) { + DEBUG(4, ("winbind gid range not configured, therefore %s cannot be a winbind group\n", gname)); + goto err; + } + + if (gid < gid_low || gid > gid_high) { + DEBUG(4, ("group %s is not a winbind group\n", gname)); + goto err; + } + + /* + * Get the gid's that this user belongs to. + */ + + if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) + return False; + + if (num_groups == 0) { + *winbind_answered = True; + return False; + } + + if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { + DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); + goto err; + } + + if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { + DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ +failed with error %s\n", strerror(errno) )); + goto err; + } + + /* + * Now we have the gid list for this user - convert the gname + * to a gid_t via either winbind or the local UNIX lookup and do the comparison. + */ + + for (i = 0; i < num_groups; i++) { + if (gid == groups[i]) { + ret = True; + break; + } + } + + *winbind_answered = True; + SAFE_FREE(groups); + return ret; + + err: + + *winbind_answered = False; + SAFE_FREE(groups); + return False; +} + +/**************************************************************************** + Check if a user is in a UNIX group. +****************************************************************************/ +static BOOL user_in_unix_group_list(const char *user,const char *gname) +{ + struct passwd *pass = Get_Pwnam(user); + struct sys_userlist *user_list; + struct sys_userlist *member; + TALLOC_CTX *mem_ctx; + + DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n", user, gname)); + + /* + * We need to check the users primary group as this + * group is implicit and often not listed in the group database. + */ + + mem_ctx = talloc_init("smbgroupedit talloc"); + if (!mem_ctx) return -1; + if (pass) { + if (strequal(gname,gidtoname(mem_ctx, pass->pw_gid))) { + DEBUG(10,("user_in_unix_group_list: group %s is primary group.\n", gname )); + goto exit; + } + } + + user_list = get_users_in_group(gname); + if (user_list == NULL) { + DEBUG(10,("user_in_unix_group_list: no such group %s\n", gname )); + return False; + } + + for (member = user_list; member; member = member->next) { + DEBUG(10,("user_in_unix_group_list: checking user %s against member %s\n", + user, member->unix_name )); + if (strequal(member->unix_name,user)) { + free_userlist(user_list); + goto exit; + } + } + + free_userlist(user_list); + talloc_destroy(mem_ctx); + return False; +exit: + talloc_destroy(mem_ctx); + return True; +} + +/**************************************************************************** + Check if a user is in a group list. Ask winbind first, then use UNIX. +****************************************************************************/ +static BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, size_t n_groups) +{ + BOOL winbind_answered = False; + BOOL ret; + gid_t gid; + unsigned i; + + gid = nametogid(gname); + if (gid == (gid_t)-1) + return False; + + if (groups && n_groups > 0) { + for (i=0; i < n_groups; i++) { + if (groups[i] == gid) { + return True; + } + } + return False; + } + + /* fallback if we don't yet have the group list */ + + ret = user_in_winbind_group_list(user, gname, &winbind_answered); + if (!winbind_answered) + ret = user_in_unix_group_list(user, gname); + + if (ret) + DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n", user, gname)); + return ret; +} + +/**************************************************************************** + Check if a user is in a user list - can check combinations of UNIX + and netgroup lists. +****************************************************************************/ + +BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_groups) +{ + if (!list || !*list) + return False; + + DEBUG(10,("user_in_list: checking user %s in list\n", user)); + + while (*list) { + + DEBUG(10,("user_in_list: checking user |%s| against |%s|\n", user, *list)); + + /* + * Check raw username. + */ + if (strequal(user, *list)) + return(True); + + /* + * Now check to see if any combination + * of UNIX and netgroups has been specified. + */ + + if(**list == '@') { + /* + * Old behaviour. Check netgroup list + * followed by UNIX list. + */ + if(user_in_netgroup_list(user, *list +1)) + return True; + if(user_in_group_list(user, *list +1, groups, n_groups)) + return True; + } else if (**list == '+') { + + if((*(*list +1)) == '&') { + /* + * Search UNIX list followed by netgroup. + */ + if(user_in_group_list(user, *list +2, groups, n_groups)) + return True; + if(user_in_netgroup_list(user, *list +2)) + return True; + + } else { + + /* + * Just search UNIX list. + */ + + if(user_in_group_list(user, *list +1, groups, n_groups)) + return True; + } + + } else if (**list == '&') { + + if(*(*list +1) == '+') { + /* + * Search netgroup list followed by UNIX list. + */ + if(user_in_netgroup_list(user, *list +2)) + return True; + if(user_in_group_list(user, *list +2, groups, n_groups)) + return True; + } else { + /* + * Just search netgroup list. + */ + if(user_in_netgroup_list(user, *list +1)) + return True; + } + } else if (!name_is_local(*list)) { + /* + * If user name did not match and token is not + * a unix group and the token has a winbind separator in the + * name then see if it is a Windows group. + */ + + DOM_SID g_sid; + enum SID_NAME_USE name_type; + BOOL winbind_answered = False; + BOOL ret; + fstring groupname, domain; + + /* Parse a string of the form DOMAIN/user into a domain and a user */ + + char *p = strchr(*list,*lp_winbind_separator()); + + DEBUG(10,("user_in_list: checking if user |%s| is in winbind group |%s|\n", user, *list)); + + if (p) { + fstrcpy(groupname, p+1); + fstrcpy(domain, *list); + domain[PTR_DIFF(p, *list)] = 0; + + /* Check to see if name is a Windows group */ + if (winbind_lookup_name(domain, groupname, &g_sid, &name_type) && name_type == SID_NAME_DOM_GRP) { + + /* Check if user name is in the Windows group */ + ret = user_in_winbind_group_list(user, *list, &winbind_answered); + + if (winbind_answered && ret == True) { + DEBUG(10,("user_in_list: user |%s| is in winbind group |%s|\n", user, *list)); + return ret; + } + } + } + } + + list++; + } + return(False); +} + +/* The functions below have been taken from password.c and slightly modified */ +/**************************************************************************** + Apply a function to upper/lower case combinations + of a string and return true if one of them returns true. + Try all combinations with N uppercase letters. + offset is the first char to try and change (start with 0) + it assumes the string starts lowercased +****************************************************************************/ + +static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(const char *),int N) +{ + ssize_t len = (ssize_t)strlen(s); + int i; + struct passwd *ret; + + if (N <= 0 || offset >= len) + return(fn(s)); + + for (i=offset;i<(len-(N-1));i++) { + char c = s[i]; + if (!islower((int)c)) + continue; + s[i] = toupper(c); + ret = uname_string_combinations2(s,i+1,fn,N-1); + if(ret) + return(ret); + s[i] = c; + } + return(NULL); +} + +/**************************************************************************** + Apply a function to upper/lower case combinations + of a string and return true if one of them returns true. + Try all combinations with up to N uppercase letters. + offset is the first char to try and change (start with 0) + it assumes the string starts lowercased +****************************************************************************/ + +static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(const char *),int N) +{ + int n; + struct passwd *ret; + + for (n=1;n<=N;n++) { + ret = uname_string_combinations2(s,0,fn,n); + if(ret) + return(ret); + } + return(NULL); +} + diff --git a/source4/lib/util.c b/source4/lib/util.c new file mode 100644 index 0000000000..64e3dfe88c --- /dev/null +++ b/source4/lib/util.c @@ -0,0 +1,1000 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Anthony Liguori 2003 + Copyright (C) James J Myers 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) +#ifdef WITH_NISPLUS_HOME +#ifdef BROKEN_NISPLUS_INCLUDE_FILES +/* + * The following lines are needed due to buggy include files + * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and + * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. + * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as + * an enum in /usr/include/rpcsvc/nis.h. + */ + +#if defined(GROUP) +#undef GROUP +#endif + +#if defined(GROUP_OBJ) +#undef GROUP_OBJ +#endif + +#endif /* BROKEN_NISPLUS_INCLUDE_FILES */ + +#include + +#else /* !WITH_NISPLUS_HOME */ + +#include "rpcsvc/ypclnt.h" + +#endif /* WITH_NISPLUS_HOME */ +#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */ + + +/**************************************************************************n + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. +****************************************************************************/ + +const char *tmpdir(void) +{ + char *p; + if ((p = getenv("TMPDIR"))) + return p; + return "/tmp"; +} + +/**************************************************************************** + Determine whether we are in the specified group. +****************************************************************************/ + +BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) +{ + int i; + + if (group == current_gid) + return(True); + + for (i=0;ist_mode)) || (S_ISFIFO(sbuf->st_mode))); +} + +/******************************************************************* + Check a files mod time. +********************************************************************/ + +time_t file_modtime(const char *fname) +{ + SMB_STRUCT_STAT st; + + if (sys_stat(fname,&st) != 0) + return(0); + + return(st.st_mtime); +} + +/******************************************************************* + Check if a directory exists. +********************************************************************/ + +BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st) +{ + SMB_STRUCT_STAT st2; + BOOL ret; + + if (!st) + st = &st2; + + if (sys_stat(dname,st) != 0) + return(False); + + ret = S_ISDIR(st->st_mode); + if(!ret) + errno = ENOTDIR; + return ret; +} + +/******************************************************************* + Returns the size in bytes of the named file. +********************************************************************/ +SMB_OFF_T get_file_size(char *file_name) +{ + SMB_STRUCT_STAT buf; + buf.st_size = 0; + if(sys_stat(file_name,&buf) != 0) + return (SMB_OFF_T)-1; + return(buf.st_size); +} + +/******************************************************************* + Close the low 3 fd's and open dev/null in their place. +********************************************************************/ +void close_low_fds(BOOL stderr_too) +{ +#ifndef VALGRIND + int fd; + int i; + + close(0); + close(1); + + if (stderr_too) + close(2); + + /* try and use up these file descriptors, so silly + library routines writing to stdout etc won't cause havoc */ + for (i=0;i<3;i++) { + if (i == 2 && !stderr_too) + continue; + + fd = sys_open("/dev/null",O_RDWR,0); + if (fd < 0) + fd = sys_open("/dev/null",O_WRONLY,0); + if (fd < 0) { + DEBUG(0,("Can't open /dev/null\n")); + return; + } + if (fd != i) { + DEBUG(0,("Didn't get file descriptor %d\n",i)); + return; + } + } +#endif +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +****************************************************************************/ + +int set_blocking(int fd, BOOL set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return sys_fcntl_long( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + + +/******************************************************************* + Sleep for a specified number of milliseconds. +********************************************************************/ + +void msleep(unsigned int t) +{ + struct timeval tval; + + tval.tv_sec = t/1000; + tval.tv_usec = 1000*(t%1000); + /* this should be the real select - do NOT replace + with sys_select() */ + select(0,NULL,NULL,NULL,&tval); +} + +/**************************************************************************** + Become a daemon, discarding the controlling terminal. +****************************************************************************/ + +void become_daemon(BOOL Fork) +{ + if (Fork) { + if (fork()) { + _exit(0); + } + } + + /* detach from the terminal */ +#ifdef HAVE_SETSID + setsid(); +#elif defined(TIOCNOTTY) + { + int i = sys_open("/dev/tty", O_RDWR, 0); + if (i != -1) { + ioctl(i, (int) TIOCNOTTY, (char *)0); + close(i); + } + } +#endif /* HAVE_SETSID */ + + /* Close fd's 0,1,2. Needed if started by rsh */ + close_low_fds(False); /* Don't close stderr, let the debug system + attach it to the logfile */ +} + + +/**************************************************************************** + Expand a pointer to be a particular size. +****************************************************************************/ + +void *Realloc(void *p,size_t size) +{ + void *ret=NULL; + + if (size == 0) { + SAFE_FREE(p); + DEBUG(5,("Realloc asked for 0 bytes\n")); + return NULL; + } + + if (!p) + ret = (void *)malloc(size); + else + ret = (void *)realloc(p,size); + + if (!ret) + DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size)); + + return(ret); +} + +/**************************************************************************** + Free memory, checks for NULL. + Use directly SAFE_FREE() + Exists only because we need to pass a function pointer somewhere --SSS +****************************************************************************/ + +void safe_free(void *p) +{ + SAFE_FREE(p); +} + + +/* + see if a string matches either our primary or one of our secondary + netbios aliases. do a case insensitive match +*/ +BOOL is_myname(const char *name) +{ + const char **aliases; + int i; + + if (strcasecmp(name, lp_netbios_name()) == 0) { + return True; + } + + aliases = lp_netbios_aliases(); + for (i=0; aliases && aliases[i]; i++) { + if (strcasecmp(name, aliases[i]) == 0) { + return True; + } + } + + return False; +} + + +/**************************************************************************** + Get my own name, return in malloc'ed storage. +****************************************************************************/ + +char* get_myname(void) +{ + char *hostname; + const int host_name_max = 255; + char *p; + + hostname = malloc(host_name_max+1); + *hostname = 0; + + /* get my host name */ + if (gethostname(hostname, host_name_max+1) == -1) { + DEBUG(0,("gethostname failed\n")); + return NULL; + } + + /* Ensure null termination. */ + hostname[host_name_max] = '\0'; + + /* split off any parts after an initial . */ + p = strchr_m(hostname,'.'); + + if (p) + *p = 0; + + return hostname; +} + +/**************************************************************************** + Get my own name, including domain. +****************************************************************************/ + +BOOL get_myfullname(char *my_name) +{ + pstring hostname; + + *hostname = 0; + + /* get my host name */ + if (gethostname(hostname, sizeof(hostname)) == -1) { + DEBUG(0,("gethostname failed\n")); + return False; + } + + /* Ensure null termination. */ + hostname[sizeof(hostname)-1] = '\0'; + + if (my_name) + fstrcpy(my_name, hostname); + return True; +} + +/**************************************************************************** + Get my own domain name. +****************************************************************************/ + +BOOL get_mydomname(fstring my_domname) +{ + pstring hostname; + char *p; + + *hostname = 0; + /* get my host name */ + if (gethostname(hostname, sizeof(hostname)) == -1) { + DEBUG(0,("gethostname failed\n")); + return False; + } + + /* Ensure null termination. */ + hostname[sizeof(hostname)-1] = '\0'; + + p = strchr_m(hostname, '.'); + + if (!p) + return False; + + p++; + + if (my_domname) + fstrcpy(my_domname, p); + + return True; +} + +/**************************************************************************** + Interpret a protocol description string, with a default. +****************************************************************************/ + +int interpret_protocol(char *str,int def) +{ + if (strequal(str,"NT1")) + return(PROTOCOL_NT1); + if (strequal(str,"LANMAN2")) + return(PROTOCOL_LANMAN2); + if (strequal(str,"LANMAN1")) + return(PROTOCOL_LANMAN1); + if (strequal(str,"CORE")) + return(PROTOCOL_CORE); + if (strequal(str,"COREPLUS")) + return(PROTOCOL_COREPLUS); + if (strequal(str,"CORE+")) + return(PROTOCOL_COREPLUS); + + DEBUG(0,("Unrecognised protocol level %s\n",str)); + + return(def); +} + +/**************************************************************************** + Return true if a string could be a pure IP address. +****************************************************************************/ + +BOOL is_ipaddress(const char *str) +{ + BOOL pure_address = True; + int i; + + for (i=0; pure_address && str[i]; i++) + if (!(isdigit((int)str[i]) || str[i] == '.')) + pure_address = False; + + /* Check that a pure number is not misinterpreted as an IP */ + pure_address = pure_address && (strchr_m(str, '.') != NULL); + + return pure_address; +} + +/**************************************************************************** + Interpret an internet address or name into an IP address in 4 byte form. +****************************************************************************/ + +uint32 interpret_addr(const char *str) +{ + struct hostent *hp; + uint32 res; + + if (strcmp(str,"0.0.0.0") == 0) + return(0); + if (strcmp(str,"255.255.255.255") == 0) + return(0xFFFFFFFF); + + /* if it's in the form of an IP address then get the lib to interpret it */ + if (is_ipaddress(str)) { + res = inet_addr(str); + } else { + /* otherwise assume it's a network name of some sort and use + sys_gethostbyname */ + if ((hp = sys_gethostbyname(str)) == 0) { + DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str)); + return 0; + } + + if(hp->h_addr == NULL) { + DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str)); + return 0; + } + putip((char *)&res,(char *)hp->h_addr); + } + + if (res == (uint32)-1) + return(0); + + return(res); +} + +/******************************************************************* + A convenient addition to interpret_addr(). +******************************************************************/ + +struct in_addr *interpret_addr2(TALLOC_CTX *mem_ctx, const char *str) +{ + struct in_addr *ret; + uint32 a = interpret_addr(str); + + ret = talloc(mem_ctx, sizeof(struct in_addr)); + if (!ret) return NULL; + ret->s_addr = a; + return(ret); +} + +/******************************************************************* + Check if an IP is the 0.0.0.0. +******************************************************************/ + +BOOL is_zero_ip(struct in_addr ip) +{ + uint32 a; + putip((char *)&a,(char *)&ip); + return(a == 0); +} + +/******************************************************************* + Set an IP to 0.0.0.0. +******************************************************************/ + +void zero_ip(struct in_addr *ip) +{ + *ip = inet_makeaddr(0,0); + return; +} + + +/******************************************************************* + Are two IPs on the same subnet? +********************************************************************/ + +BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) +{ + uint32 net1,net2,nmask; + + nmask = ntohl(mask.s_addr); + net1 = ntohl(ip1.s_addr); + net2 = ntohl(ip2.s_addr); + + return((net1 & nmask) == (net2 & nmask)); +} + + +/**************************************************************************** + Check if a process exists. Does this work on all unixes? +****************************************************************************/ + +BOOL process_exists(pid_t pid) +{ + /* Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. */ + SMB_ASSERT(pid > 0); + return(kill(pid,0) == 0 || errno != ESRCH); +} + +/******************************************************************* + Convert a gid into a group name. +********************************************************************/ + +char *gidtoname(TALLOC_CTX *mem_ctx, gid_t gid) +{ + char *name; + struct group *grp; + + grp = getgrgid(gid); + if (grp) + return(grp->gr_name); + name = talloc_asprintf(mem_ctx, "%d",(int)gid); + return(name); +} + + +/******************************************************************* + Convert a name to a gid_t if possible. Return -1 if not a group. +********************************************************************/ + +gid_t nametogid(const char *name) +{ + struct group *grp; + char *p; + gid_t g; + + g = (gid_t)strtol(name, &p, 0); + if ((p != name) && (*p == '\0')) + return g; + + grp = sys_getgrnam(name); + if (grp) + return(grp->gr_gid); + return (gid_t)-1; +} + +/******************************************************************* + Something really nasty happened - panic ! +********************************************************************/ + +void smb_panic(const char *why) +{ + char *cmd = lp_panic_action(); + int result; + + if (cmd && *cmd) { + DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd)); + result = system(cmd); + + if (result == -1) + DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", + strerror(errno))); + else + DEBUG(0, ("smb_panic(): action returned status %d\n", + WEXITSTATUS(result))); + } + DEBUG(0,("PANIC: %s\n", why)); + abort(); +} + +/**************************************************************************** + Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping + is dealt with in posix.c +****************************************************************************/ + +BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +{ + SMB_STRUCT_FLOCK lock; + int ret; + + DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type)); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = offset; + lock.l_len = count; + lock.l_pid = 0; + + ret = sys_fcntl_ptr(fd,op,&lock); + + if (ret == -1 && errno != 0) + DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); + + /* a lock query */ + if (op == SMB_F_GETLK) { + if ((ret != -1) && + (lock.l_type != F_UNLCK) && + (lock.l_pid != 0) && + (lock.l_pid != getpid())) { + DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid)); + return(True); + } + + /* it must be not locked or locked by me */ + return(False); + } + + /* a lock set or unset */ + if (ret == -1) { + DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", + (double)offset,(double)count,op,type,strerror(errno))); + return(False); + } + + /* everything went OK */ + DEBUG(8,("fcntl_lock: Lock call successful\n")); + + return(True); +} + +/******************************************************************* + Set the remote_arch string based on an enum. This is used in places +where we desperately need to distinguish client type. +********************************************************************/ +void set_remote_arch(struct server_context *smb, enum remote_arch_types type) +{ + const char *arch; + + smb->negotiate.ra_type = type; + switch (type) { + case RA_WFWG: + arch = "WfWg"; + return; + case RA_OS2: + arch = "OS2"; + return; + case RA_WIN95: + arch = "Win95"; + return; + case RA_WINNT: + arch = "WinNT"; + return; + case RA_WIN2K: + arch = "Win2K"; + return; + case RA_WINXP: + arch = "WinXP"; + return; + case RA_SAMBA: + arch = "Samba"; + return; + default: + smb->negotiate.ra_type = RA_UNKNOWN; + arch = "UNKNOWN"; + break; + } + + sub_set_remote_arch(arch); +} + + +void print_asc(int level, const unsigned char *buf,int len) +{ + int i; + for (i=0;i8) DEBUGADD(level,(" ")); + while (n--) DEBUGADD(level,(" ")); + n = MIN(8,i%16); + print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " )); + n = (i%16) - n; + if (n>0) print_asc(level,&buf[i-n],n); + DEBUGADD(level,("\n")); + } +} + +/***************************************************************** + Possibly replace mkstemp if it is broken. +*****************************************************************/ + +int smb_mkstemp(char *template) +{ +#if HAVE_SECURE_MKSTEMP + return mkstemp(template); +#else + /* have a reasonable go at emulating it. Hope that + the system mktemp() isn't completly hopeless */ + char *p = mktemp(template); + if (!p) + return -1; + return open(p, O_CREAT|O_EXCL|O_RDWR, 0600); +#endif +} + +/***************************************************************** + malloc that aborts with smb_panic on fail or zero size. + *****************************************************************/ + +void *smb_xmalloc(size_t size) +{ + void *p; + if (size == 0) + smb_panic("smb_xmalloc: called with zero size.\n"); + if ((p = malloc(size)) == NULL) + smb_panic("smb_xmalloc: malloc fail.\n"); + return p; +} + +/** + Memdup with smb_panic on fail. +**/ + +void *smb_xmemdup(const void *p, size_t size) +{ + void *p2; + p2 = smb_xmalloc(size); + memcpy(p2, p, size); + return p2; +} + +/** + strdup that aborts on malloc fail. +**/ + +char *smb_xstrdup(const char *s) +{ + char *s1 = strdup(s); + if (!s1) + smb_panic("smb_xstrdup: malloc fail\n"); + return s1; +} + + +/* + vasprintf that aborts on malloc fail +*/ + + int smb_xvasprintf(char **ptr, const char *format, va_list ap) +{ + int n; + va_list ap2; + + VA_COPY(ap2, ap); + + n = vasprintf(ptr, format, ap2); + if (n == -1 || ! *ptr) + smb_panic("smb_xvasprintf: out of memory"); + return n; +} + +/***************************************************************** + Like strdup but for memory. +*****************************************************************/ + +void *memdup(const void *p, size_t size) +{ + void *p2; + if (size == 0) + return NULL; + p2 = malloc(size); + if (!p2) + return NULL; + memcpy(p2, p, size); + return p2; +} + +/***************************************************************** + Get local hostname and cache result. +*****************************************************************/ + +char *myhostname(TALLOC_CTX *mem_ctx) +{ + char *myname, *ret; + myname = get_myname(); + ret = talloc_strdup(mem_ctx, myname); + free(myname); + return ret; + +} + +/***************************************************************** + A useful function for returning a path in the Samba lock directory. +*****************************************************************/ + +char *lock_path(TALLOC_CTX* mem_ctx, const char *name) +{ + char *fname; + + fname = talloc_strdup(mem_ctx, lp_lockdir()); + trim_string(fname,"","/"); + + if (!directory_exist(fname,NULL)) + mkdir(fname,0755); + + fname = talloc_asprintf(mem_ctx, "%s/%s", fname, name); + + return fname; +} + +/** + * @brief Returns an absolute path to a file in the Samba lib directory. + * + * @param name File to find, relative to LIBDIR. + * + * @retval Pointer to a talloc'ed string containing the full path. + **/ + +char *lib_path(TALLOC_CTX* mem_ctx, const char *name) +{ + char *fname; + fname = talloc_asprintf(mem_ctx, "%s/%s", dyn_LIBDIR, name); + return fname; +} + +/** + * @brief Returns the platform specific shared library extension. + * + * @retval Pointer to a static #fstring containing the extension. + **/ + +const char *shlib_ext(void) +{ + return dyn_SHLIBEXT; +} + + +/********************************************************* + Recursive routine that is called by unix_wild_match. +*********************************************************/ + +static BOOL unix_do_match(char *regexp, char *str) +{ + char *p; + + for( p = regexp; *p && *str; ) { + + switch(*p) { + case '?': + str++; + p++; + break; + + case '*': + + /* + * Look for a character matching + * the one after the '*'. + */ + p++; + if(!*p) + return True; /* Automatic match */ + while(*str) { + + while(*str && (*p != *str)) + str++; + + /* + * Patch from weidel@multichart.de. In the case of the regexp + * '*XX*' we want to ensure there are at least 2 'X' characters + * in the string after the '*' for a match to be made. + */ + + { + int matchcount=0; + + /* + * Eat all the characters that match, but count how many there were. + */ + + while(*str && (*p == *str)) { + str++; + matchcount++; + } + + /* + * Now check that if the regexp had n identical characters that + * matchcount had at least that many matches. + */ + + while ( *(p+1) && (*(p+1) == *p)) { + p++; + matchcount--; + } + + if ( matchcount <= 0 ) + return False; + } + + str--; /* We've eaten the match char after the '*' */ + + if(unix_do_match(p, str)) + return True; + + if(!*str) + return False; + else + str++; + } + return False; + + default: + if(*str != *p) + return False; + str++; + p++; + break; + } + } + + if(!*p && !*str) + return True; + + if (!*p && str[0] == '.' && str[1] == 0) + return(True); + + if (!*str && *p == '?') { + while (*p == '?') + p++; + return(!*p); + } + + if(!*str && (*p == '*' && p[1] == '\0')) + return True; + + return False; +} diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c new file mode 100644 index 0000000000..0eb8046227 --- /dev/null +++ b/source4/lib/util_file.c @@ -0,0 +1,531 @@ +/* + * Unix SMB/CIFS implementation. + * SMB parameters and setup + * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. + * + * 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 (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, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +static int gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/*************************************************************** + Lock or unlock a fd for a known lock type. Abandon after waitsecs + seconds. +****************************************************************/ + +BOOL do_file_lock(int fd, int waitsecs, int type) +{ + SMB_STRUCT_FLOCK lock; + int ret; + void (*oldsig_handler)(int); + + gotalarm = 0; + oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + lock.l_pid = 0; + + alarm(waitsecs); + /* Note we must *NOT* use sys_fcntl here ! JRA */ + ret = fcntl(fd, SMB_F_SETLKW, &lock); + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler); + + if (gotalarm) { + DEBUG(0, ("do_file_lock: failed to %s file.\n", + type == F_UNLCK ? "unlock" : "lock")); + return False; + } + + return (ret == 0); +} + + +/*************************************************************** + Lock an fd. Abandon after waitsecs seconds. +****************************************************************/ + +BOOL file_lock(int fd, int type, int secs, int *plock_depth) +{ + if (fd < 0) + return False; + + (*plock_depth)++; + + if ((*plock_depth) == 0) + { + if (!do_file_lock(fd, secs, type)) { + DEBUG(10,("file_lock: locking file failed, error = %s.\n", + strerror(errno))); + return False; + } + } + + return True; +} + +/*************************************************************** + Unlock an fd. Abandon after waitsecs seconds. +****************************************************************/ + +BOOL file_unlock(int fd, int *plock_depth) +{ + BOOL ret=True; + + if(*plock_depth == 1) + ret = do_file_lock(fd, 5, F_UNLCK); + + (*plock_depth)--; + + if(!ret) + DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", + strerror(errno))); + return ret; +} + + +/************************************************************************* + gets a line out of a file. + line is of format "xxxx:xxxxxx:xxxxx:". + lines with "#" at the front are ignored. +*************************************************************************/ +int getfileline(void *vp, char *linebuf, int linebuf_size) +{ + /* Static buffers we will return. */ + FILE *fp = (FILE *)vp; + unsigned char c; + unsigned char *p; + size_t linebuf_len; + + if (fp == NULL) + { + DEBUG(0,("getfileline: Bad file pointer.\n")); + return -1; + } + + /* + * Scan the file, a line at a time. + */ + while (!feof(fp)) + { + linebuf[0] = '\0'; + + fgets(linebuf, linebuf_size, fp); + if (ferror(fp)) + { + return -1; + } + + /* + * Check if the string is terminated with a newline - if not + * then we must keep reading and discard until we get one. + */ + + linebuf_len = strlen(linebuf); + if (linebuf_len == 0) + { + linebuf[0] = '\0'; + return 0; + } + + if (linebuf[linebuf_len - 1] != '\n') + { + c = '\0'; + while (!ferror(fp) && !feof(fp)) + { + c = fgetc(fp); + if (c == '\n') + { + break; + } + } + } + else + { + linebuf[linebuf_len - 1] = '\0'; + } + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("getfileline: got line |%s|\n", linebuf)); +#endif + if ((linebuf[0] == 0) && feof(fp)) + { + DEBUG(4, ("getfileline: end of file reached\n")); + return 0; + } + + if (linebuf[0] == '#' || linebuf[0] == '\0') + { + DEBUG(6, ("getfileline: skipping comment or blank line\n")); + continue; + } + + p = (unsigned char *) strchr_m(linebuf, ':'); + if (p == NULL) + { + DEBUG(0, ("getfileline: malformed line entry (no :)\n")); + continue; + } + return linebuf_len; + } + return -1; +} + + +/**************************************************************************** +read a line from a file with possible \ continuation chars. +Blanks at the start or end of a line are stripped. +The string will be allocated if s2 is NULL +****************************************************************************/ +char *fgets_slash(char *s2,int maxlen,XFILE *f) +{ + char *s=s2; + int len = 0; + int c; + BOOL start_of_line = True; + + if (x_feof(f)) + return(NULL); + + if (maxlen <2) return(NULL); + + if (!s2) + { + maxlen = MIN(maxlen,8); + s = (char *)malloc(maxlen); + } + + if (!s) return(NULL); + + *s = 0; + + while (len < maxlen-1) + { + c = x_getc(f); + switch (c) + { + case '\r': + break; + case '\n': + while (len > 0 && s[len-1] == ' ') + { + s[--len] = 0; + } + if (len > 0 && s[len-1] == '\\') + { + s[--len] = 0; + start_of_line = True; + break; + } + return(s); + case EOF: + if (len <= 0 && !s2) + SAFE_FREE(s); + return(len>0?s:NULL); + case ' ': + if (start_of_line) + break; + default: + start_of_line = False; + s[len++] = c; + s[len] = 0; + } + if (!s2 && len > maxlen-3) + { + char *t; + + maxlen *= 2; + t = (char *)Realloc(s,maxlen); + if (!t) { + DEBUG(0,("fgets_slash: failed to expand buffer!\n")); + SAFE_FREE(s); + return(NULL); + } else s = t; + } + } + return(s); +} + + +/**************************************************************************** +load from a pipe into memory +****************************************************************************/ +char *file_pload(char *syscmd, size_t *size) +{ + int fd, n; + char *p, *tp; + pstring buf; + size_t total; + + fd = sys_popen(syscmd); + if (fd == -1) return NULL; + + p = NULL; + total = 0; + + while ((n = read(fd, buf, sizeof(buf))) > 0) { + tp = Realloc(p, total + n + 1); + if (!tp) { + DEBUG(0,("file_pload: failed to expand buffer!\n")); + close(fd); + SAFE_FREE(p); + return NULL; + } else p = tp; + memcpy(p+total, buf, n); + total += n; + } + if (p) p[total] = 0; + + /* FIXME: Perhaps ought to check that the command completed + * successfully (returned 0); if not the data may be + * truncated. */ + sys_pclose(fd); + + if (size) *size = total; + + return p; +} + +/**************************************************************************** +load a file into memory from a fd. +****************************************************************************/ + +char *fd_load(int fd, size_t *size) +{ + SMB_STRUCT_STAT sbuf; + char *p; + + if (sys_fstat(fd, &sbuf) != 0) return NULL; + + p = (char *)malloc(sbuf.st_size+1); + if (!p) return NULL; + + if (read(fd, p, sbuf.st_size) != sbuf.st_size) { + SAFE_FREE(p); + return NULL; + } + p[sbuf.st_size] = 0; + + if (size) *size = sbuf.st_size; + + return p; +} + +/**************************************************************************** +load a file into memory +****************************************************************************/ +char *file_load(const char *fname, size_t *size) +{ + int fd; + char *p; + + if (!fname || !*fname) return NULL; + + fd = open(fname,O_RDONLY); + if (fd == -1) return NULL; + + p = fd_load(fd, size); + + close(fd); + + return p; +} + + +/******************************************************************* +mmap (if possible) or read a file +********************************************************************/ +void *map_file(char *fname, size_t size) +{ + size_t s2 = 0; + void *p = NULL; +#ifdef HAVE_MMAP + if (lp_use_mmap()) { + int fd; + fd = open(fname, O_RDONLY, 0); + if (fd == -1) { + DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno))); + return NULL; + } + p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + close(fd); + if (p == MAP_FAILED) { + DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno))); + return NULL; + } + } +#endif + if (!p) { + p = file_load(fname, &s2); + if (!p) return NULL; + if (s2 != size) { + DEBUG(1,("incorrect size for %s - got %d expected %d\n", + fname, s2, size)); + if (p) free(p); + return NULL; + } + } + + return p; +} + + +/**************************************************************************** +parse a buffer into lines +****************************************************************************/ +static char **file_lines_parse(char *p, size_t size, int *numlines) +{ + int i; + char *s, **ret; + + if (!p) return NULL; + + for (s = p, i=0; s < p+size; s++) { + if (s[0] == '\n') i++; + } + + ret = (char **)malloc(sizeof(ret[0])*(i+2)); + if (!ret) { + SAFE_FREE(p); + return NULL; + } + memset(ret, 0, sizeof(ret[0])*(i+2)); + if (numlines) *numlines = i; + + ret[0] = p; + for (s = p, i=0; s < p+size; s++) { + if (s[0] == '\n') { + s[0] = 0; + i++; + ret[i] = s+1; + } + if (s[0] == '\r') s[0] = 0; + } + + return ret; +} + + +/**************************************************************************** +load a file into memory and return an array of pointers to lines in the file +must be freed with file_lines_free(). +****************************************************************************/ +char **file_lines_load(const char *fname, int *numlines) +{ + char *p; + size_t size; + + p = file_load(fname, &size); + if (!p) return NULL; + + return file_lines_parse(p, size, numlines); +} + +/**************************************************************************** +load a fd into memory and return an array of pointers to lines in the file +must be freed with file_lines_free(). If convert is true calls unix_to_dos on +the list. +****************************************************************************/ +char **fd_lines_load(int fd, int *numlines) +{ + char *p; + size_t size; + + p = fd_load(fd, &size); + if (!p) return NULL; + + return file_lines_parse(p, size, numlines); +} + + +/**************************************************************************** +load a pipe into memory and return an array of pointers to lines in the data +must be freed with file_lines_free(). +****************************************************************************/ +char **file_lines_pload(char *syscmd, int *numlines) +{ + char *p; + size_t size; + + p = file_pload(syscmd, &size); + if (!p) return NULL; + + return file_lines_parse(p, size, numlines); +} + +/**************************************************************************** +free lines loaded with file_lines_load +****************************************************************************/ +void file_lines_free(char **lines) +{ + if (!lines) return; + SAFE_FREE(lines[0]); + SAFE_FREE(lines); +} + + +/**************************************************************************** +take a lislist of lines and modify them to produce a list where \ continues +a line +****************************************************************************/ +void file_lines_slashcont(char **lines) +{ + int i, j; + + for (i=0; lines[i];) { + int len = strlen(lines[i]); + if (lines[i][len-1] == '\\') { + lines[i][len-1] = ' '; + if (lines[i+1]) { + char *p = &lines[i][len]; + while (p < lines[i+1]) *p++ = ' '; + for (j = i+1; lines[j]; j++) lines[j] = lines[j+1]; + } + } else { + i++; + } + } +} + +/* + save a lump of data into a file. Mostly used for debugging +*/ +BOOL file_save(const char *fname, void *packet, size_t length) +{ + int fd; + fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd == -1) { + return False; + } + if (write(fd, packet, length) != (size_t)length) { + return False; + } + close(fd); + return True; +} diff --git a/source4/lib/util_getent.c b/source4/lib/util_getent.c new file mode 100644 index 0000000000..32641dbf83 --- /dev/null +++ b/source4/lib/util_getent.c @@ -0,0 +1,306 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Simo Sorce 2001 + Copyright (C) Jeremy Allison 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/**************************************************************** + Returns a single linked list of group entries. + Use grent_free() to free it after use. +****************************************************************/ + +struct sys_grent * getgrent_list(void) +{ + struct sys_grent *glist; + struct sys_grent *gent; + struct group *grp; + + gent = (struct sys_grent *) malloc(sizeof(struct sys_grent)); + if (gent == NULL) { + DEBUG (0, ("Out of memory in getgrent_list!\n")); + return NULL; + } + memset(gent, '\0', sizeof(struct sys_grent)); + glist = gent; + + setgrent(); + grp = getgrent(); + if (grp == NULL) { + endgrent(); + SAFE_FREE(glist); + return NULL; + } + + while (grp != NULL) { + int i,num; + + if (grp->gr_name) { + if ((gent->gr_name = strdup(grp->gr_name)) == NULL) + goto err; + } + if (grp->gr_passwd) { + if ((gent->gr_passwd = strdup(grp->gr_passwd)) == NULL) + goto err; + } + gent->gr_gid = grp->gr_gid; + + /* number of strings in gr_mem */ + for (num = 0; grp->gr_mem[num]; num++) + ; + + /* alloc space for gr_mem string pointers */ + if ((gent->gr_mem = (char **) malloc((num+1) * sizeof(char *))) == NULL) + goto err; + + memset(gent->gr_mem, '\0', (num+1) * sizeof(char *)); + + for (i=0; i < num; i++) { + if ((gent->gr_mem[i] = strdup(grp->gr_mem[i])) == NULL) + goto err; + } + gent->gr_mem[num] = NULL; + + grp = getgrent(); + if (grp) { + gent->next = (struct sys_grent *) malloc(sizeof(struct sys_grent)); + if (gent->next == NULL) + goto err; + gent = gent->next; + memset(gent, '\0', sizeof(struct sys_grent)); + } + } + + endgrent(); + return glist; + + err: + + endgrent(); + DEBUG(0, ("Out of memory in getgrent_list!\n")); + grent_free(glist); + return NULL; +} + +/**************************************************************** + Free the single linked list of group entries made by + getgrent_list() +****************************************************************/ + +void grent_free (struct sys_grent *glist) +{ + while (glist) { + struct sys_grent *prev; + + SAFE_FREE(glist->gr_name); + SAFE_FREE(glist->gr_passwd); + if (glist->gr_mem) { + int i; + for (i = 0; glist->gr_mem[i]; i++) + SAFE_FREE(glist->gr_mem[i]); + SAFE_FREE(glist->gr_mem); + } + prev = glist; + glist = glist->next; + SAFE_FREE(prev); + } +} + +/**************************************************************** + Returns a single linked list of passwd entries. + Use pwent_free() to free it after use. +****************************************************************/ + +struct sys_pwent * getpwent_list(void) +{ + struct sys_pwent *plist; + struct sys_pwent *pent; + struct passwd *pwd; + + pent = (struct sys_pwent *) malloc(sizeof(struct sys_pwent)); + if (pent == NULL) { + DEBUG (0, ("Out of memory in getpwent_list!\n")); + return NULL; + } + plist = pent; + + setpwent(); + pwd = getpwent(); + while (pwd != NULL) { + memset(pent, '\0', sizeof(struct sys_pwent)); + if (pwd->pw_name) { + if ((pent->pw_name = strdup(pwd->pw_name)) == NULL) + goto err; + } + if (pwd->pw_passwd) { + if ((pent->pw_passwd = strdup(pwd->pw_passwd)) == NULL) + goto err; + } + pent->pw_uid = pwd->pw_uid; + pent->pw_gid = pwd->pw_gid; + if (pwd->pw_gecos) { + if ((pent->pw_name = strdup(pwd->pw_gecos)) == NULL) + goto err; + } + if (pwd->pw_dir) { + if ((pent->pw_name = strdup(pwd->pw_dir)) == NULL) + goto err; + } + if (pwd->pw_shell) { + if ((pent->pw_name = strdup(pwd->pw_shell)) == NULL) + goto err; + } + + pwd = getpwent(); + if (pwd) { + pent->next = (struct sys_pwent *) malloc(sizeof(struct sys_pwent)); + if (pent->next == NULL) + goto err; + pent = pent->next; + } + } + + endpwent(); + return plist; + + err: + + endpwent(); + DEBUG(0, ("Out of memory in getpwent_list!\n")); + pwent_free(plist); + return NULL; +} + +/**************************************************************** + Free the single linked list of passwd entries made by + getpwent_list() +****************************************************************/ + +void pwent_free (struct sys_pwent *plist) +{ + while (plist) { + struct sys_pwent *prev; + + SAFE_FREE(plist->pw_name); + SAFE_FREE(plist->pw_passwd); + SAFE_FREE(plist->pw_gecos); + SAFE_FREE(plist->pw_dir); + SAFE_FREE(plist->pw_shell); + + prev = plist; + plist = plist->next; + SAFE_FREE(prev); + } +} + +/**************************************************************** + Add the individual group users onto the list. +****************************************************************/ + +static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp) +{ + size_t num_users, i; + + /* Count the number of users. */ + for (num_users = 0; grp->gr_mem[num_users]; num_users++) + ; + + for (i = 0; i < num_users; i++) { + struct sys_userlist *entry = (struct sys_userlist *)malloc(sizeof(*entry)); + if (entry == NULL) { + free_userlist(list_head); + return NULL; + } + entry->unix_name = (char *)strdup(grp->gr_mem[i]); + if (entry->unix_name == NULL) { + SAFE_FREE(entry); + free_userlist(list_head); + return NULL; + } + DLIST_ADD(list_head, entry); + } + return list_head; +} + +/**************************************************************** + Get the list of UNIX users in a group. + We have to enumerate the /etc/group file as some UNIX getgrnam() + calls won't do that for us (notably Tru64 UNIX). +****************************************************************/ + +struct sys_userlist *get_users_in_group(const char *gname) +{ + struct sys_userlist *list_head = NULL; + struct group *gptr; + fstring domain; + fstring groupname; + DOM_SID sid; + enum SID_NAME_USE name_type; + + /* No point using winbind if we can't split it in the + first place */ + if (split_domain_and_name(gname, domain, groupname)) { + + /* + * If we're doing this via winbindd, don't do the + * entire group list enumeration as we know this is + * pointless (and slow). + */ + + if (winbind_lookup_name(domain, groupname, &sid, &name_type) + && name_type == SID_NAME_DOM_GRP) { + if ((gptr = (struct group *)getgrnam(gname)) == NULL) + return NULL; + return add_members_to_userlist(list_head, gptr); + } + } + +#if !defined(BROKEN_GETGRNAM) + if ((gptr = (struct group *)getgrnam(gname)) == NULL) + return NULL; + return add_members_to_userlist(list_head, gptr); +#else + /* BROKEN_GETGRNAM - True64 */ + setgrent(); + while((gptr = getgrent()) != NULL) { + if (strequal(gname, gptr->gr_name)) { + list_head = add_members_to_userlist(list_head, gptr); + if (list_head == NULL) + return NULL; + } + } + endgrent(); + return list_head; +#endif +} + +/**************************************************************** + Free list allocated above. +****************************************************************/ + +void free_userlist(struct sys_userlist *list_head) +{ + while (list_head) { + struct sys_userlist *old_head = list_head; + DLIST_REMOVE(list_head, list_head); + SAFE_FREE(old_head->unix_name); + SAFE_FREE(old_head); + } +} diff --git a/source4/lib/util_pw.c b/source4/lib/util_pw.c new file mode 100644 index 0000000000..9d075a05e8 --- /dev/null +++ b/source4/lib/util_pw.c @@ -0,0 +1,89 @@ +/* + Unix SMB/CIFS implementation. + + Safe versions of getpw* calls + + Copyright (C) Andrew Bartlett 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static struct passwd *alloc_copy_passwd(const struct passwd *from) +{ + struct passwd *ret = smb_xmalloc(sizeof(struct passwd)); + ZERO_STRUCTP(ret); + ret->pw_name = smb_xstrdup(from->pw_name); + ret->pw_passwd = smb_xstrdup(from->pw_passwd); + ret->pw_uid = from->pw_uid; + ret->pw_gid = from->pw_gid; + ret->pw_gecos = smb_xstrdup(from->pw_gecos); + ret->pw_dir = smb_xstrdup(from->pw_dir); + ret->pw_shell = smb_xstrdup(from->pw_shell); + return ret; +} + +void passwd_free (struct passwd **buf) +{ + if (!*buf) { + DEBUG(0, ("attempted double-free of allocated passwd\n")); + return; + } + + SAFE_FREE((*buf)->pw_name); + SAFE_FREE((*buf)->pw_passwd); + SAFE_FREE((*buf)->pw_gecos); + SAFE_FREE((*buf)->pw_dir); + SAFE_FREE((*buf)->pw_shell); + + SAFE_FREE(*buf); +} + +struct passwd *getpwnam_alloc(const char *name) +{ + struct passwd *temp; + + temp = sys_getpwnam(name); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return alloc_copy_passwd(temp); +} + +struct passwd *getpwuid_alloc(uid_t uid) +{ + struct passwd *temp; + + temp = sys_getpwuid(uid); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return alloc_copy_passwd(temp); +} diff --git a/source4/lib/util_seaccess.c b/source4/lib/util_seaccess.c new file mode 100644 index 0000000000..eba8cab7fb --- /dev/null +++ b/source4/lib/util_seaccess.c @@ -0,0 +1,486 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Luke Kenneth Casson Leighton 1996-2000. + Copyright (C) Tim Potter 2000. + Copyright (C) Re-written by Jeremy Allison 2000. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern DOM_SID global_sid_Builtin; + +/********************************************************************************** + Check if this ACE has a SID in common with the token. +**********************************************************************************/ + +static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) +{ + size_t i; + + for (i = 0; i < token->num_sids; i++) { + if (sid_equal(&ace->trustee, &token->user_sids[i])) + return True; + } + + return False; +} + +/********************************************************************************* + Check an ACE against a SID. We return the remaining needed permission + bits not yet granted. Zero means permission allowed (no more needed bits). +**********************************************************************************/ + +static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired, + NTSTATUS *status) +{ + uint32 mask = ace->info.mask; + + /* + * Inherit only is ignored. + */ + + if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + return acc_desired; + } + + /* + * If this ACE has no SID in common with the token, + * ignore it as it cannot be used to make an access + * determination. + */ + + if (!token_sid_in_ace( token, ace)) + return acc_desired; + + switch (ace->type) { + case SEC_ACE_TYPE_ACCESS_ALLOWED: + /* + * This is explicitly allowed. + * Remove the bits from the remaining + * access required. Return the remaining + * bits needed. + */ + acc_desired &= ~mask; + break; + case SEC_ACE_TYPE_ACCESS_DENIED: + /* + * This is explicitly denied. + * If any bits match terminate here, + * we are denied. + */ + if (acc_desired & mask) { + *status = NT_STATUS_ACCESS_DENIED; + return 0xFFFFFFFF; + } + break; + case SEC_ACE_TYPE_SYSTEM_ALARM: + case SEC_ACE_TYPE_SYSTEM_AUDIT: + *status = NT_STATUS_NOT_IMPLEMENTED; + return 0xFFFFFFFF; + default: + *status = NT_STATUS_INVALID_PARAMETER; + return 0xFFFFFFFF; + } + + return acc_desired; +} + +/********************************************************************************* + Maximum access was requested. Calculate the max possible. Fail if it doesn't + include other bits requested. +**********************************************************************************/ + +static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32 *granted, + uint32 desired, + NTSTATUS *status) +{ + uint32 acc_denied = 0; + uint32 acc_granted = 0; + size_t i; + + for ( i = 0 ; i < the_acl->num_aces; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + uint32 mask = ace->info.mask; + + if (!token_sid_in_ace( token, ace)) + continue; + + switch (ace->type) { + case SEC_ACE_TYPE_ACCESS_ALLOWED: + acc_granted |= (mask & ~acc_denied); + break; + case SEC_ACE_TYPE_ACCESS_DENIED: + acc_denied |= (mask & ~acc_granted); + break; + case SEC_ACE_TYPE_SYSTEM_ALARM: + case SEC_ACE_TYPE_SYSTEM_AUDIT: + *status = NT_STATUS_NOT_IMPLEMENTED; + *granted = 0; + return False; + default: + *status = NT_STATUS_INVALID_PARAMETER; + *granted = 0; + return False; + } + } + + /* + * If we were granted no access, or we desired bits that we + * didn't get, then deny. + */ + + if ((acc_granted == 0) || ((acc_granted & desired) != desired)) { + *status = NT_STATUS_ACCESS_DENIED; + *granted = 0; + return False; + } + + /* + * Return the access we did get. + */ + + *granted = acc_granted; + *status = NT_STATUS_OK; + return True; +} + +/* Map generic access rights to object specific rights. This technique is + used to give meaning to assigning read, write, execute and all access to + objects. Each type of object has its own mapping of generic to object + specific access rights. */ + +void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping) +{ + uint32 old_mask = *access_mask; + + if (*access_mask & GENERIC_READ_ACCESS) { + *access_mask &= ~GENERIC_READ_ACCESS; + *access_mask |= mapping->generic_read; + } + + if (*access_mask & GENERIC_WRITE_ACCESS) { + *access_mask &= ~GENERIC_WRITE_ACCESS; + *access_mask |= mapping->generic_write; + } + + if (*access_mask & GENERIC_EXECUTE_ACCESS) { + *access_mask &= ~GENERIC_EXECUTE_ACCESS; + *access_mask |= mapping->generic_execute; + } + + if (*access_mask & GENERIC_ALL_ACCESS) { + *access_mask &= ~GENERIC_ALL_ACCESS; + *access_mask |= mapping->generic_all; + } + + if (old_mask != *access_mask) { + DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n", + old_mask, *access_mask)); + } +} + +/* Map standard access rights to object specific rights. This technique is + used to give meaning to assigning read, write, execute and all access to + objects. Each type of object has its own mapping of standard to object + specific access rights. */ + +void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping) +{ + uint32 old_mask = *access_mask; + + if (*access_mask & READ_CONTROL_ACCESS) { + *access_mask &= ~READ_CONTROL_ACCESS; + *access_mask |= mapping->std_read; + } + + if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS)) { + *access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS); + *access_mask |= mapping->std_all; + } + + if (old_mask != *access_mask) { + DEBUG(10, ("se_map_standard(): mapped mask 0x%08x to 0x%08x\n", + old_mask, *access_mask)); + } +} + +/***************************************************************************** + Check access rights of a user against a security descriptor. Look at + each ACE in the security descriptor until an access denied ACE denies + any of the desired rights to the user or any of the users groups, or one + or more ACEs explicitly grant all requested access rights. See + "Access-Checking" document in MSDN. +*****************************************************************************/ + +BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, + uint32 acc_desired, uint32 *acc_granted, + NTSTATUS *status) +{ + extern NT_USER_TOKEN anonymous_token; + size_t i; + SEC_ACL *the_acl; + fstring sid_str; + uint32 tmp_acc_desired = acc_desired; + + if (!status || !acc_granted) + return False; + + if (!token) + token = &anonymous_token; + + *status = NT_STATUS_OK; + *acc_granted = 0; + + DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n", + (unsigned int)acc_desired, (unsigned int)token->num_sids, + sid_to_string(sid_str, &token->user_sids[0]))); + + /* + * No security descriptor or security descriptor with no DACL + * present allows all access. + */ + + /* ACL must have something in it */ + + if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) { + *status = NT_STATUS_OK; + *acc_granted = acc_desired; + DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n")); + return True; + } + + /* The user sid is the first in the token */ + if (DEBUGLVL(3)) { + DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) )); + + for (i = 1; i < token->num_sids; i++) { + DEBUGADD(3, ("se_access_check: also %s\n", + sid_to_string(sid_str, &token->user_sids[i]))); + } + } + + /* Is the token the owner of the SID ? */ + + if (sd->owner_sid) { + for (i = 0; i < token->num_sids; i++) { + if (sid_equal(&token->user_sids[i], sd->owner_sid)) { + /* + * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL. + */ + if (tmp_acc_desired & WRITE_DAC_ACCESS) + tmp_acc_desired &= ~WRITE_DAC_ACCESS; + if (tmp_acc_desired & READ_CONTROL_ACCESS) + tmp_acc_desired &= ~READ_CONTROL_ACCESS; + } + } + } + + the_acl = sd->dacl; + + if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) { + tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS; + return get_max_access( the_acl, token, acc_granted, tmp_acc_desired, + status); + } + + for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + + DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n", + (unsigned int)i, ace->type, ace->flags, + sid_to_string(sid_str, &ace->trustee), + (unsigned int) ace->info.mask, + (unsigned int)tmp_acc_desired )); + + tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status); + if (NT_STATUS_V(*status)) { + *acc_granted = 0; + DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, nt_errstr(*status))); + return False; + } + } + + /* + * If there are no more desired permissions left then + * access was allowed. + */ + + if (tmp_acc_desired == 0) { + *acc_granted = acc_desired; + *status = NT_STATUS_OK; + DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired )); + return True; + } + + *acc_granted = 0; + *status = NT_STATUS_ACCESS_DENIED; + DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired )); + return False; +} + +/* Create a child security descriptor using another security descriptor as + the parent container. This child object can either be a container or + non-container object. */ + +SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, + BOOL child_container) +{ + SEC_DESC_BUF *sdb; + SEC_DESC *sd; + SEC_ACL *new_dacl, *the_acl; + SEC_ACE *new_ace_list = NULL; + unsigned int new_ace_list_ndx = 0, i; + size_t size; + + /* Currently we only process the dacl when creating the child. The + sacl should also be processed but this is left out as sacls are + not implemented in Samba at the moment.*/ + + the_acl = parent_ctr->dacl; + + if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) + return NULL; + + for (i = 0; the_acl && i < the_acl->num_aces; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; + uint8 new_flags = 0; + BOOL inherit = False; + fstring sid_str; + + /* The OBJECT_INHERIT_ACE flag causes the ACE to be + inherited by non-container children objects. Container + children objects will inherit it as an INHERIT_ONLY + ACE. */ + + if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { + + if (!child_container) { + new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; + } else { + new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } + + inherit = True; + } + + /* The CONAINER_INHERIT_ACE flag means all child container + objects will inherit and use the ACE. */ + + if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { + if (!child_container) { + inherit = False; + } else { + new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; + } + } + + /* The INHERIT_ONLY_ACE is not used by the se_access_check() + function for the parent container, but is inherited by + all child objects as a normal ACE. */ + + if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + /* Move along, nothing to see here */ + } + + /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE + is inherited by child objects but not grandchildren + objects. We clear the object inherit and container + inherit flags in the inherited ACE. */ + + if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + /* Add ACE to ACE list */ + + if (!inherit) + continue; + + init_sec_access(&new_ace->info, ace->info.mask); + init_sec_ace(new_ace, &ace->trustee, ace->type, + new_ace->info, new_flags); + + sid_to_string(sid_str, &ace->trustee); + + DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " + " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, + ace->type, ace->flags, ace->info.mask, + sid_str, new_ace->type, new_ace->flags, + new_ace->info.mask)); + + new_ace_list_ndx++; + } + + /* Create child security descriptor to return */ + + new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); + + /* Use the existing user and group sids. I don't think this is + correct. Perhaps the user and group should be passed in as + parameters by the caller? */ + + sd = make_sec_desc(ctx, SEC_DESC_REVISION, + parent_ctr->owner_sid, + parent_ctr->grp_sid, + parent_ctr->sacl, + new_dacl, &size); + + sdb = make_sec_desc_buf(ctx, size, sd); + + return sdb; +} + +/******************************************************************* + samr_make_sam_obj_sd + ********************************************************************/ + +NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, GENERIC_RIGHTS_SAM_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c new file mode 100644 index 0000000000..9910a9d261 --- /dev/null +++ b/source4/lib/util_sid.c @@ -0,0 +1,631 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 + Copyright (C) Jeremy Allison 1999 + Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Simo Sorce 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + * Some useful sids + */ + +DOM_SID global_sid_World_Domain; /* Everyone domain */ +DOM_SID global_sid_World; /* Everyone */ +DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner domain */ +DOM_SID global_sid_NT_Authority; /* NT Authority */ +DOM_SID global_sid_System; /* System */ +DOM_SID global_sid_NULL; /* NULL sid */ +DOM_SID global_sid_Authenticated_Users; /* All authenticated rids */ +DOM_SID global_sid_Network; /* Network rids */ + +DOM_SID global_sid_Creator_Owner; /* Creator Owner */ +DOM_SID global_sid_Creator_Group; /* Creator Group */ +DOM_SID global_sid_Anonymous; /* Anonymous login */ + +DOM_SID global_sid_Builtin; /* Local well-known domain */ +DOM_SID global_sid_Builtin_Administrators; /* Builtin administrators */ +DOM_SID global_sid_Builtin_Users; /* Builtin users */ +DOM_SID global_sid_Builtin_Guests; /* Builtin guest users */ +DOM_SID global_sid_Builtin_Power_Users; /* Builtin power users */ +DOM_SID global_sid_Builtin_Account_Operators; /* Builtin account operators */ +DOM_SID global_sid_Builtin_Server_Operators; /* Builtin server operators */ +DOM_SID global_sid_Builtin_Print_Operators; /* Builtin print operators */ +DOM_SID global_sid_Builtin_Backup_Operators; /* Builtin backup operators */ +DOM_SID global_sid_Builtin_Replicator; /* Builtin replicator */ + +#define SECURITY_NULL_SID_AUTHORITY 0 +#define SECURITY_WORLD_SID_AUTHORITY 1 +#define SECURITY_LOCAL_SID_AUTHORITY 2 +#define SECURITY_CREATOR_SID_AUTHORITY 3 +#define SECURITY_NT_AUTHORITY 5 + +/* + * An NT compatible anonymous token. + */ + +static DOM_SID anon_sid_array[3]; + +NT_USER_TOKEN anonymous_token = { + 3, + anon_sid_array +}; + +static DOM_SID system_sid_array[4]; +NT_USER_TOKEN system_token = { + 1, + system_sid_array +}; + +/**************************************************************************** + Lookup string names for SID types. +****************************************************************************/ + +static const struct { + enum SID_NAME_USE sid_type; + const char *string; +} sid_name_type[] = { + {SID_NAME_USER, "User"}, + {SID_NAME_DOM_GRP, "Domain Group"}, + {SID_NAME_DOMAIN, "Domain"}, + {SID_NAME_ALIAS, "Local Group"}, + {SID_NAME_WKN_GRP, "Well-known Group"}, + {SID_NAME_DELETED, "Deleted Account"}, + {SID_NAME_INVALID, "Invalid Account"}, + {SID_NAME_UNKNOWN, "UNKNOWN"}, + + {SID_NAME_USE_NONE, NULL} +}; + +const char *sid_type_lookup(uint32 sid_type) +{ + int i = 0; + + /* Look through list */ + while(sid_name_type[i].sid_type != 0) { + if (sid_name_type[i].sid_type == sid_type) + return sid_name_type[i].string; + i++; + } + + /* Default return */ + return "SID *TYPE* is INVALID"; +} + +/**************************************************************************** + Creates some useful well known sids +****************************************************************************/ + +void generate_wellknown_sids(void) +{ + static BOOL initialised = False; + + if (initialised) + return; + + /* SECURITY_NULL_SID_AUTHORITY */ + string_to_sid(&global_sid_NULL, "S-1-0-0"); + + /* SECURITY_WORLD_SID_AUTHORITY */ + string_to_sid(&global_sid_World_Domain, "S-1-1"); + string_to_sid(&global_sid_World, "S-1-1-0"); + + /* SECURITY_CREATOR_SID_AUTHORITY */ + string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); + string_to_sid(&global_sid_Creator_Owner, "S-1-3-0"); + string_to_sid(&global_sid_Creator_Group, "S-1-3-1"); + + /* SECURITY_NT_AUTHORITY */ + string_to_sid(&global_sid_NT_Authority, "S-1-5"); + string_to_sid(&global_sid_Network, "S-1-5-2"); + string_to_sid(&global_sid_Anonymous, "S-1-5-7"); + string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11"); + string_to_sid(&global_sid_System, "S-1-5-18"); + + /* SECURITY_BUILTIN_DOMAIN_RID */ + string_to_sid(&global_sid_Builtin, "S-1-5-32"); + string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544"); + string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545"); + string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546"); + string_to_sid(&global_sid_Builtin_Power_Users, "S-1-5-32-547"); + string_to_sid(&global_sid_Builtin_Account_Operators, "S-1-5-32-548"); + string_to_sid(&global_sid_Builtin_Server_Operators, "S-1-5-32-549"); + string_to_sid(&global_sid_Builtin_Print_Operators, "S-1-5-32-550"); + string_to_sid(&global_sid_Builtin_Backup_Operators, "S-1-5-32-551"); + string_to_sid(&global_sid_Builtin_Replicator, "S-1-5-32-552"); + + /* Create the anon token. */ + sid_copy( &anonymous_token.user_sids[0], &global_sid_World); + sid_copy( &anonymous_token.user_sids[1], &global_sid_Network); + sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous); + + /* Create the system token. */ + sid_copy( &system_token.user_sids[0], &global_sid_System); + + initialised = True; +} + +/************************************************************************** + Create the SYSTEM token. +***************************************************************************/ + +NT_USER_TOKEN *get_system_token(void) +{ + generate_wellknown_sids(); /* The token is initialised here */ + return &system_token; +} + +/************************************************************************** + Splits a name of format \DOMAIN\name or name into its two components. + Sets the DOMAIN name to lp_netbios_name() if it has not been specified. +***************************************************************************/ + +void split_domain_name(const char *fullname, char *domain, char *name) +{ + pstring full_name; + const char *sep; + char *p; + + sep = lp_winbind_separator(); + + *domain = *name = '\0'; + + if (fullname[0] == sep[0] || fullname[0] == '\\') + fullname++; + + pstrcpy(full_name, fullname); + p = strchr_m(full_name+1, '\\'); + if (!p) p = strchr_m(full_name+1, sep[0]); + + if (p != NULL) { + *p = 0; + fstrcpy(domain, full_name); + fstrcpy(name, p+1); + } else { + fstrcpy(domain, lp_netbios_name()); + fstrcpy(name, full_name); + } + + DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n", + fullname, domain, name)); +} + +/**************************************************************************** + Test if a SID is wellknown and resolvable. +****************************************************************************/ + +BOOL resolvable_wellknown_sid(DOM_SID *sid) +{ + uint32 ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + if (sid->sid_rev_num != SEC_DESC_REVISION || sid->num_auths < 1) + return False; + + return (ia == SECURITY_WORLD_SID_AUTHORITY || + ia == SECURITY_CREATOR_SID_AUTHORITY); +} + +/***************************************************************** + Convert a SID to an ascii string. +*****************************************************************/ + +char *sid_to_string(fstring sidstr_out, const DOM_SID *sid) +{ + char subauth[16]; + int i; + uint32 ia; + + if (!sid) { + fstrcpy(sidstr_out, "(NULL SID)"); + return sidstr_out; + } + + /* + * BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 + * in a range of 2^48. + */ + ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia); + + for (i = 0; i < sid->num_auths; i++) { + slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]); + fstrcat(sidstr_out, subauth); + } + + return sidstr_out; +} + +/***************************************************************** + Useful function for debug lines. +*****************************************************************/ + +const char *sid_string_talloc(TALLOC_CTX *mem_ctx, const DOM_SID *sid) +{ + fstring tempSid; + sid_to_string(tempSid, sid); + return talloc_strdup(mem_ctx, tempSid); +} + +/***************************************************************** + Convert a string to a SID. Returns True on success, False on fail. +*****************************************************************/ + +BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) +{ + pstring tok; + char *q; + const char *p; + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ + uint32 ia; + + if (StrnCaseCmp( sidstr, "S-", 2)) { + DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr)); + return False; + } + + memset((char *)sidout, '\0', sizeof(DOM_SID)); + + p = q = strdup(sidstr + 2); + if (p == NULL) { + DEBUG(0, ("string_to_sid: out of memory!\n")); + return False; + } + + if (!next_token(&p, tok, "-", sizeof(tok))) { + DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); + SAFE_FREE(q); + return False; + } + + /* Get the revision number. */ + sidout->sid_rev_num = (uint8)strtoul(tok, NULL, 10); + + if (!next_token(&p, tok, "-", sizeof(tok))) { + DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); + SAFE_FREE(q); + return False; + } + + /* identauth in decimal should be < 2^32 */ + ia = (uint32)strtoul(tok, NULL, 10); + + /* NOTE - the ia value is in big-endian format. */ + sidout->id_auth[0] = 0; + sidout->id_auth[1] = 0; + sidout->id_auth[2] = (ia & 0xff000000) >> 24; + sidout->id_auth[3] = (ia & 0x00ff0000) >> 16; + sidout->id_auth[4] = (ia & 0x0000ff00) >> 8; + sidout->id_auth[5] = (ia & 0x000000ff); + + sidout->num_auths = 0; + + while(next_token(&p, tok, "-", sizeof(tok)) && + sidout->num_auths < MAXSUBAUTHS) { + /* + * NOTE - the subauths are in native machine-endian format. They + * are converted to little-endian when linearized onto the wire. + */ + sid_append_rid(sidout, (uint32)strtoul(tok, NULL, 10)); + } + + SAFE_FREE(q); + return True; +} + +/***************************************************************** + Add a rid to the end of a sid +*****************************************************************/ + +BOOL sid_append_rid(DOM_SID *sid, uint32 rid) +{ + if (sid->num_auths < MAXSUBAUTHS) { + sid->sub_auths[sid->num_auths++] = rid; + return True; + } + return False; +} + +/***************************************************************** + Removes the last rid from the end of a sid +*****************************************************************/ + +BOOL sid_split_rid(DOM_SID *sid, uint32 *rid) +{ + if (sid->num_auths > 0) { + sid->num_auths--; + *rid = sid->sub_auths[sid->num_auths]; + return True; + } + return False; +} + +/***************************************************************** + Return the last rid from the end of a sid +*****************************************************************/ + +BOOL sid_peek_rid(const DOM_SID *sid, uint32 *rid) +{ + if (!sid || !rid) + return False; + + if (sid->num_auths > 0) { + *rid = sid->sub_auths[sid->num_auths - 1]; + return True; + } + return False; +} + +/***************************************************************** + Return the last rid from the end of a sid + and check the sid against the exp_dom_sid +*****************************************************************/ + +BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 *rid) +{ + if (!exp_dom_sid || !sid || !rid) + return False; + + + if (sid_compare_domain(exp_dom_sid, sid)!=0){ + *rid=(-1); + return False; + } + + return sid_peek_rid(sid, rid); +} + +/***************************************************************** + Copies a sid +*****************************************************************/ + +void sid_copy(DOM_SID *dst, const DOM_SID *src) +{ + int i; + + ZERO_STRUCTP(dst); + + dst->sid_rev_num = src->sid_rev_num; + dst->num_auths = src->num_auths; + + memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth)); + + for (i = 0; i < src->num_auths; i++) + dst->sub_auths[i] = src->sub_auths[i]; +} + +/***************************************************************** + Write a sid out into on-the-wire format. +*****************************************************************/ + +BOOL sid_linearize(char *outbuf, size_t len, const DOM_SID *sid) +{ + size_t i; + + if (len < sid_size(sid)) + return False; + + SCVAL(outbuf,0,sid->sid_rev_num); + SCVAL(outbuf,1,sid->num_auths); + memcpy(&outbuf[2], sid->id_auth, 6); + for(i = 0; i < sid->num_auths; i++) + SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]); + + return True; +} + +/***************************************************************** + Parse a on-the-wire SID to a DOM_SID. +*****************************************************************/ + +BOOL sid_parse(const char *inbuf, size_t len, DOM_SID *sid) +{ + int i; + if (len < 8) + return False; + + ZERO_STRUCTP(sid); + + sid->sid_rev_num = CVAL(inbuf, 0); + sid->num_auths = CVAL(inbuf, 1); + memcpy(sid->id_auth, inbuf+2, 6); + if (len < 8 + sid->num_auths*4) + return False; + for (i=0;inum_auths;i++) + sid->sub_auths[i] = IVAL(inbuf, 8+i*4); + return True; +} + +/***************************************************************** + Compare the auth portion of two sids. +*****************************************************************/ + +static int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2) +{ + int i; + + if (sid1 == sid2) + return 0; + if (!sid1) + return -1; + if (!sid2) + return 1; + + if (sid1->sid_rev_num != sid2->sid_rev_num) + return sid1->sid_rev_num - sid2->sid_rev_num; + + for (i = 0; i < 6; i++) + if (sid1->id_auth[i] != sid2->id_auth[i]) + return sid1->id_auth[i] - sid2->id_auth[i]; + + return 0; +} + +/***************************************************************** + Compare two sids. +*****************************************************************/ + +int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2) +{ + int i; + + if (sid1 == sid2) + return 0; + if (!sid1) + return -1; + if (!sid2) + return 1; + + /* Compare most likely different rids, first: i.e start at end */ + if (sid1->num_auths != sid2->num_auths) + return sid1->num_auths - sid2->num_auths; + + for (i = sid1->num_auths-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return sid1->sub_auths[i] - sid2->sub_auths[i]; + + return sid_compare_auth(sid1, sid2); +} + +/***************************************************************** + See if 2 SIDs are in the same domain + this just compares the leading sub-auths +*****************************************************************/ + +int sid_compare_domain(const DOM_SID *sid1, const DOM_SID *sid2) +{ + int n, i; + + n = MIN(sid1->num_auths, sid2->num_auths); + + for (i = n-1; i >= 0; --i) + if (sid1->sub_auths[i] != sid2->sub_auths[i]) + return sid1->sub_auths[i] - sid2->sub_auths[i]; + + return sid_compare_auth(sid1, sid2); +} + +/***************************************************************** + Compare two sids. +*****************************************************************/ + +BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) +{ + return sid_compare(sid1, sid2) == 0; +} + +/***************************************************************** + Check if the SID is the builtin SID (S-1-5-32). +*****************************************************************/ + +BOOL sid_check_is_builtin(const DOM_SID *sid) +{ + return sid_equal(sid, &global_sid_Builtin); +} + +/***************************************************************** + Check if the SID is one of the builtin SIDs (S-1-5-32-a). +*****************************************************************/ + +BOOL sid_check_is_in_builtin(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, &global_sid_Builtin); +} + +/***************************************************************** + Calculates size of a sid. +*****************************************************************/ + +size_t sid_size(const DOM_SID *sid) +{ + if (sid == NULL) + return 0; + + return sid->num_auths * sizeof(uint32) + 8; +} + +/***************************************************************** + Returns true if SID is internal (and non-mappable). +*****************************************************************/ + +BOOL non_mappable_sid(DOM_SID *sid) +{ + DOM_SID dom; + uint32 rid; + + sid_copy(&dom, sid); + sid_split_rid(&dom, &rid); + + if (sid_equal(&dom, &global_sid_Builtin)) + return True; + + if (sid_equal(&dom, &global_sid_NT_Authority)) + return True; + + return False; +} + +/***************************************************************** + Return the binary string representation of a DOM_SID. + Caller must free. +*****************************************************************/ + +char *sid_binstring(const DOM_SID *sid) +{ + char *buf, *s; + int len = sid_size(sid); + buf = malloc(len); + if (!buf) + return NULL; + sid_linearize(buf, len, sid); + s = binary_string(buf, len); + free(buf); + return s; +} + + +/***************************************************************** + Print a GUID structure for debugging. +*****************************************************************/ + +void print_guid(GUID *guid) +{ + int i; + + d_printf("%08x-%04x-%04x", + IVAL(guid->info, 0), SVAL(guid->info, 4), SVAL(guid->info, 6)); + d_printf("-%02x%02x-", guid->info[8], guid->info[9]); + for (i=10;iinfo[i]); + d_printf("\n"); +} diff --git a/source4/lib/util_smbd.c b/source4/lib/util_smbd.c new file mode 100644 index 0000000000..071f20b416 --- /dev/null +++ b/source4/lib/util_smbd.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions, used in smbd only + Copyright (C) Andrew Tridgell 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This function requires sys_getgrouplist - which is only + available in smbd due to it's use of become_root() in a + legacy systems hack. +*/ + +/* + return a full list of groups for a user + + returns the number of groups the user is a member of. The return will include the + users primary group. + + remember to free the resulting gid_t array + + NOTE! uses become_root() to gain correct priviages on systems + that lack a native getgroups() call (uses initgroups and getgroups) +*/ +int getgroups_user(const char *user, gid_t **groups) +{ + struct passwd *pwd; + int ngrp, max_grp; + + pwd = getpwnam_alloc(user); + if (!pwd) return -1; + + max_grp = groups_max(); + (*groups) = (gid_t *)malloc(sizeof(gid_t) * max_grp); + if (! *groups) { + passwd_free(&pwd); + errno = ENOMEM; + return -1; + } + + ngrp = sys_getgrouplist(user, pwd->pw_gid, *groups, &max_grp); + if (ngrp <= 0) { + passwd_free(&pwd); + free(*groups); + return ngrp; + } + + passwd_free(&pwd); + return ngrp; +} diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c new file mode 100644 index 0000000000..42dc04f6c8 --- /dev/null +++ b/source4/lib/util_sock.c @@ -0,0 +1,631 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Tim Potter 2000-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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/**************************************************************************** + Determine if a file descriptor is in fact a socket. +****************************************************************************/ +BOOL is_a_socket(int fd) +{ + int v,l; + l = sizeof(int); + return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0; +} + +enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; + +typedef struct smb_socket_option { + const char *name; + int level; + int option; + int value; + int opttype; +} smb_socket_option; + +static const smb_socket_option socket_options[] = { + {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, + {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, + {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, +#ifdef TCP_NODELAY + {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, +#endif +#ifdef IPTOS_LOWDELAY + {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, +#endif +#ifdef IPTOS_THROUGHPUT + {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, +#endif +#ifdef SO_REUSEPORT + {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL}, +#endif +#ifdef SO_SNDBUF + {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, +#endif +#ifdef SO_RCVBUF + {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, +#endif +#ifdef SO_SNDLOWAT + {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, +#endif +#ifdef SO_RCVLOWAT + {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, +#endif +#ifdef SO_SNDTIMEO + {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, +#endif +#ifdef SO_RCVTIMEO + {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, +#endif + {NULL,0,0,0,0}}; + +/**************************************************************************** + Print socket options. +****************************************************************************/ + +static void print_socket_options(int s) +{ + int value, vlen = 4; + const smb_socket_option *p = &socket_options[0]; + + for (; p->name != NULL; p++) { + if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) { + DEBUG(5,("Could not test socket option %s.\n", p->name)); + } else { + DEBUG(5,("socket option %s = %d\n",p->name,value)); + } + } + } + +/**************************************************************************** + Set user socket options. +****************************************************************************/ + +void set_socket_options(int fd, const char *options) +{ + fstring tok; + + while (next_token(&options,tok," \t,", sizeof(tok))) { + int ret=0,i; + int value = 1; + char *p; + BOOL got_value = False; + + if ((p = strchr_m(tok,'='))) { + *p = 0; + value = atoi(p+1); + got_value = True; + } + + for (i=0;socket_options[i].name;i++) + if (strequal(socket_options[i].name,tok)) + break; + + if (!socket_options[i].name) { + DEBUG(0,("Unknown socket option %s\n",tok)); + continue; + } + + switch (socket_options[i].opttype) { + case OPT_BOOL: + case OPT_INT: + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option,(char *)&value,sizeof(int)); + break; + + case OPT_ON: + if (got_value) + DEBUG(0,("syntax error - %s does not take a value\n",tok)); + + { + int on = socket_options[i].value; + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option,(char *)&on,sizeof(int)); + } + break; + } + + if (ret != 0) + DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); + } + + print_socket_options(fd); +} + +/**************************************************************************** + Read from a socket. +****************************************************************************/ + +ssize_t read_udp_socket(int fd, char *buf, size_t len, + struct in_addr *from_addr, int *from_port) +{ + ssize_t ret; + struct sockaddr_in sock; + socklen_t socklen = sizeof(sock); + + ret = (ssize_t)sys_recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen); + if (ret <= 0) { + DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); + return 0; + } + + if (from_addr) { + *from_addr = sock.sin_addr; + } + if (from_port) { + *from_port = ntohs(sock.sin_port); + } + + return ret; +} + + +/**************************************************************************** + read data from the client, reading exactly N bytes. +****************************************************************************/ +ssize_t read_data(int fd, char *buffer, size_t N) +{ + ssize_t ret; + size_t total=0; + + while (total < N) { + ret = sys_read(fd,buffer + total,N - total); + if (ret == 0) { + return 0; + } + if (ret == -1) { + return -1; + } + total += ret; + } + return (ssize_t)total; +} + + +/**************************************************************************** + Write data to a fd. +****************************************************************************/ +ssize_t write_data(int fd, const char *buffer, size_t N) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + ret = sys_write(fd, buffer + total, N - total); + if (ret == -1) { + return -1; + } + if (ret == 0) + return total; + + total += ret; + } + return (ssize_t)total; +} + + +/**************************************************************************** +send a keepalive packet (rfc1002) +****************************************************************************/ +BOOL send_nbt_keepalive(int sock_fd) +{ + unsigned char buf[4]; + + buf[0] = SMBkeepalive; + buf[1] = buf[2] = buf[3] = 0; + + return write_data(sock_fd,(char *)buf,4) == 4; +} + + +/**************************************************************************** + Open a socket of the specified type, port, and address for incoming data. +****************************************************************************/ +int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL rebind ) +{ + struct sockaddr_in sock; + int res; + + memset( (char *)&sock, '\0', sizeof(sock) ); + +#ifdef HAVE_SOCK_SIN_LEN + sock.sin_len = sizeof(sock); +#endif + sock.sin_port = htons( port ); + sock.sin_family = AF_INET; + sock.sin_addr.s_addr = socket_addr; + + res = socket( AF_INET, type, 0 ); + if( res == -1 ) { + DEBUG(0,("open_socket_in(): socket() call failed: %s\n", strerror(errno))); + return -1; + } + + /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */ + { + int val = rebind ? 1 : 0; + setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); +#ifdef SO_REUSEPORT + setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); +#endif + } + + /* now we've got a socket - we need to bind it */ + if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) { + DEBUG(0,("bind failed on port %d - %s\n", port, strerror(errno))); + close( res ); + return( -1 ); + } + + DEBUG( 10, ( "bind succeeded on port %d\n", port ) ); + + return( res ); + } + + +/**************************************************************************** + create an outgoing socket. timeout is in milliseconds. + **************************************************************************/ +int open_socket_out(int type, struct in_addr *addr, int port, int timeout) +{ + struct sockaddr_in sock_out; + int res,ret; + int connect_loop = 250; /* 250 milliseconds */ + int loops = (timeout) / connect_loop; + + /* create a socket to write to */ + res = socket(PF_INET, type, 0); + if (res == -1) + { DEBUG(0,("socket error\n")); return -1; } + + if (type != SOCK_STREAM) return(res); + + memset((char *)&sock_out,'\0',sizeof(sock_out)); + putip((char *)&sock_out.sin_addr,(char *)addr); + + sock_out.sin_port = htons( port ); + sock_out.sin_family = PF_INET; + + /* set it non-blocking */ + set_blocking(res,False); + + DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); + + /* and connect it to the destination */ +connect_again: + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + /* Some systems return EAGAIN when they mean EINPROGRESS */ + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN) && loops--) { + msleep(connect_loop); + goto connect_again; + } + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN)) { + DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); + close(res); + return -1; + } + +#ifdef EISCONN + if (ret < 0 && errno == EISCONN) { + errno = 0; + ret = 0; + } +#endif + + if (ret < 0) { + DEBUG(2,("error connecting to %s:%d (%s)\n", + inet_ntoa(*addr),port,strerror(errno))); + close(res); + return -1; + } + + /* set it blocking again */ + set_blocking(res,True); + + return res; +} + +/* + open a connected UDP socket to host on port +*/ +int open_udp_socket(const char *host, int port) +{ + int type = SOCK_DGRAM; + struct sockaddr_in sock_out; + int res; + struct in_addr *addr; + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("open_udp_socket"); + if (!mem_ctx) { + return -1; + } + addr = interpret_addr2(mem_ctx, host); + + res = socket(PF_INET, type, 0); + if (res == -1) { + return -1; + } + + memset((char *)&sock_out,'\0',sizeof(sock_out)); + putip((char *)&sock_out.sin_addr,(char *)addr); + sock_out.sin_port = htons(port); + sock_out.sin_family = PF_INET; + + talloc_destroy(mem_ctx); + + if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) { + close(res); + return -1; + } + + return res; +} + + +/******************************************************************* + matchname - determine if host name matches IP address. Used to + confirm a hostname lookup to prevent spoof attacks + ******************************************************************/ +static BOOL matchname(char *remotehost, struct in_addr addr) +{ + struct hostent *hp; + int i; + + if ((hp = sys_gethostbyname(remotehost)) == 0) { + DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n", remotehost)); + return False; + } + + /* + * Make sure that gethostbyname() returns the "correct" host name. + * Unfortunately, gethostbyname("localhost") sometimes yields + * "localhost.domain". Since the latter host name comes from the + * local DNS, we just have to trust it (all bets are off if the local + * DNS is perverted). We always check the address list, though. + */ + + if (strcasecmp(remotehost, hp->h_name) + && strcasecmp(remotehost, "localhost")) { + DEBUG(0,("host name/name mismatch: %s != %s\n", + remotehost, hp->h_name)); + return False; + } + + /* Look up the host address in the address list we just got. */ + for (i = 0; hp->h_addr_list[i]; i++) { + if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0) + return True; + } + + /* + * The host name does not map to the original host address. Perhaps + * someone has compromised a name server. More likely someone botched + * it, but that could be dangerous, too. + */ + + DEBUG(0,("host name/address mismatch: %s != %s\n", + inet_ntoa(addr), hp->h_name)); + return False; +} + + +/******************************************************************* + return the DNS name of the remote end of a socket + ******************************************************************/ +char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) +{ + char *name_buf; + char *addr_buf; + struct hostent *hp; + struct in_addr addr; + char *p; + + /* reverse lookups can be *very* expensive, and in many + situations won't work because many networks don't link dhcp + with dns. To avoid the delay we avoid the lookup if + possible */ + if (!lp_hostname_lookups() && (force_lookup == False)) { + return get_socket_addr(mem_ctx, fd); + } + + p = get_socket_addr(mem_ctx, fd); + + name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); + if (fd == -1) return name_buf; + + addr_buf = talloc_strdup(mem_ctx, p); + + addr = *interpret_addr2(mem_ctx, p); + + /* Look up the remote host name. */ + if ((hp = gethostbyaddr((char *)&addr.s_addr, sizeof(addr.s_addr), AF_INET)) == 0) { + DEBUG(1,("Gethostbyaddr failed for %s\n",p)); + name_buf = talloc_strdup(mem_ctx, p); + } else { + name_buf = talloc_strdup(mem_ctx, (char *)hp->h_name); + if (!matchname(name_buf, addr)) { + DEBUG(0,("Matchname failed on %s %s\n",name_buf,p)); + name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); + } + } + + alpha_strcpy(name_buf, name_buf, "_-.", sizeof(name_buf)); + if (strstr(name_buf,"..")) { + name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); + } + + return name_buf; +} + +/******************************************************************* + return the IP addr of the remote end of a socket as a string + ******************************************************************/ +char *get_socket_addr(TALLOC_CTX *mem_ctx, int fd) +{ + struct sockaddr sa; + struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); + int length = sizeof(sa); + char *addr_buf; + + addr_buf = talloc_strdup(mem_ctx, "0.0.0.0"); + + if (fd == -1) { + return addr_buf; + } + + if (getpeername(fd, &sa, &length) < 0) { + DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) )); + return addr_buf; + } + + addr_buf = talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr)); + + return addr_buf; +} + + + +/******************************************************************* +this is like socketpair but uses tcp. It is used by the Samba +regression test code +The function guarantees that nobody else can attach to the socket, +or if they do that this function fails and the socket gets closed +returns 0 on success, -1 on failure +the resulting file descriptors are symmetrical + ******************************************************************/ +static int socketpair_tcp(int fd[2]) +{ + int listener; + struct sockaddr_in sock; + struct sockaddr_in sock2; + socklen_t socklen = sizeof(sock); + int connect_done = 0; + + fd[0] = fd[1] = listener = -1; + + memset(&sock, 0, sizeof(sock)); + + if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; + + memset(&sock2, 0, sizeof(sock2)); +#ifdef HAVE_SOCK_SIN_LEN + sock2.sin_len = sizeof(sock2); +#endif + sock2.sin_family = PF_INET; + + bind(listener, (struct sockaddr *)&sock2, sizeof(sock2)); + + if (listen(listener, 1) != 0) goto failed; + + if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed; + + if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; + + set_blocking(fd[1], 0); + + sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) { + if (errno != EINPROGRESS) goto failed; + } else { + connect_done = 1; + } + + if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed; + + close(listener); + if (connect_done == 0) { + if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0 + && errno != EISCONN) goto failed; + } + + set_blocking(fd[1], 1); + + /* all OK! */ + return 0; + + failed: + if (fd[0] != -1) close(fd[0]); + if (fd[1] != -1) close(fd[1]); + if (listener != -1) close(listener); + return -1; +} + + +/******************************************************************* +run a program on a local tcp socket, this is used to launch smbd +when regression testing +the return value is a socket which is attached to a subprocess +running "prog". stdin and stdout are attached. stderr is left +attached to the original stderr + ******************************************************************/ +int sock_exec(const char *prog) +{ + int fd[2]; + if (socketpair_tcp(fd) != 0) { + DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno))); + return -1; + } + if (fork() == 0) { + close(fd[0]); + close(0); + close(1); + dup(fd[1]); + dup(fd[1]); + exit(system(prog)); + } + close(fd[1]); + return fd[0]; +} + + +/* + determine if a packet is pending for receive on a socket +*/ +BOOL socket_pending(int fd) +{ + fd_set fds; + int selrtn; + struct timeval timeout; + + FD_ZERO(&fds); + FD_SET(fd,&fds); + + /* immediate timeout */ + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + /* yes, this is supposed to be a normal select not a sys_select() */ + selrtn = select(fd+1,&fds,NULL,NULL,&timeout); + + if (selrtn == 1) { + /* the fd is readable */ + return True; + } + + return False; +} diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c new file mode 100644 index 0000000000..19857cff86 --- /dev/null +++ b/source4/lib/util_str.c @@ -0,0 +1,1619 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * Get the next token from a string, return False if none found. + * Handles double-quotes. + * + * Based on a routine by GJC@VILLAGE.COM. + * Extensively modified by Andrew.Tridgell@anu.edu.au + **/ +BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) +{ + const char *s; + BOOL quoted; + size_t len=1; + + if (!ptr) + return(False); + + s = *ptr; + + /* default to simple separators */ + if (!sep) + sep = " \t\n\r"; + + /* find the first non sep char */ + while (*s && strchr_m(sep,*s)) + s++; + + /* nothing left? */ + if (! *s) + return(False); + + /* copy over the token */ + for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + *buff++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *buff = 0; + + return(True); +} + +/** +This is like next_token but is not re-entrant and "remembers" the first +parameter so you can pass NULL. This is useful for user interface code +but beware the fact that it is not re-entrant! +**/ + +static char *last_ptr=NULL; + +BOOL next_token_nr(const char **ptr, char *buff, const char *sep, size_t bufsize) +{ + BOOL ret; + if (!ptr) + ptr = (const char **)&last_ptr; + + ret = next_token(ptr, buff, sep, bufsize); + last_ptr = *ptr; + return ret; +} + +static uint16 tmpbuf[sizeof(pstring)]; + +void set_first_token(char *ptr) +{ + last_ptr = ptr; +} + +/** + Convert list of tokens to array; dependent on above routine. + Uses last_ptr from above - bit of a hack. +**/ + +char **toktocliplist(int *ctok, const char *sep) +{ + char *s=last_ptr; + int ictok=0; + char **ret, **iret; + + if (!sep) + sep = " \t\n\r"; + + while(*s && strchr_m(sep,*s)) + s++; + + /* nothing left? */ + if (!*s) + return(NULL); + + do { + ictok++; + while(*s && (!strchr_m(sep,*s))) + s++; + while(*s && strchr_m(sep,*s)) + *s++=0; + } while(*s); + + *ctok=ictok; + s=last_ptr; + + if (!(ret=iret=malloc(ictok*sizeof(char *)))) + return NULL; + + while(ictok--) { + *iret++=s; + while(*s++) + ; + while(!*s) + s++; + } + + return ret; +} + +/** + Case insensitive string compararison. +**/ + +int StrCaseCmp(const char *s, const char *t) +{ + pstring buf1, buf2; + unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); + unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2)); + return strcmp(buf1,buf2); +} + +/** + Case insensitive string compararison, length limited. +**/ + +int StrnCaseCmp(const char *s, const char *t, size_t n) +{ + pstring buf1, buf2; + unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); + unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2)); + return strncmp(buf1,buf2,n); +} + +/** + * Compare 2 strings. + * + * @note The comparison is case-insensitive. + **/ +BOOL strequal(const char *s1, const char *s2) +{ + if (s1 == s2) + return(True); + if (!s1 || !s2) + return(False); + + return(StrCaseCmp(s1,s2)==0); +} + +/** + * Compare 2 strings up to and including the nth char. + * + * @note The comparison is case-insensitive. + **/ +BOOL strnequal(const char *s1,const char *s2,size_t n) +{ + if (s1 == s2) + return(True); + if (!s1 || !s2 || !n) + return(False); + + return(StrnCaseCmp(s1,s2,n)==0); +} + +/** + Compare 2 strings (case sensitive). +**/ + +BOOL strcsequal(const char *s1,const char *s2) +{ + if (s1 == s2) + return(True); + if (!s1 || !s2) + return(False); + + return(strcmp(s1,s2)==0); +} + +/** +Do a case-insensitive, whitespace-ignoring string compare. +**/ + +int strwicmp(const char *psz1, const char *psz2) +{ + /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */ + /* appropriate value. */ + if (psz1 == psz2) + return (0); + else if (psz1 == NULL) + return (-1); + else if (psz2 == NULL) + return (1); + + /* sync the strings on first non-whitespace */ + while (1) { + while (isspace((int)*psz1)) + psz1++; + while (isspace((int)*psz2)) + psz2++; + if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' + || *psz2 == '\0') + break; + psz1++; + psz2++; + } + return (*psz1 - *psz2); +} + +/** + Convert a string to upper case, but don't modify it. +**/ + +char *strupper_talloc(TALLOC_CTX *mem_ctx, const char *s) +{ + char *str; + + str = talloc_strdup(mem_ctx, s); + strupper(str); + + return str; +} + + +/** + String replace. + NOTE: oldc and newc must be 7 bit characters +**/ + +void string_replace(char *s,char oldc,char newc) +{ + if (strchr(s, oldc)) { + push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); + pull_ucs2(NULL, s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE); + } +} + +/** + Skip past some strings in a buffer. +**/ + +char *skip_string(char *buf,size_t n) +{ + while (n--) + buf += strlen(buf) + 1; + return(buf); +} + +/** + Count the number of characters in a string. Normally this will + be the same as the number of bytes in a string for single byte strings, + but will be different for multibyte. +**/ + +size_t str_charnum(const char *s) +{ + uint16 tmpbuf2[sizeof(pstring)]; + push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE); + return strlen_w(tmpbuf2); +} + +/** + Count the number of characters in a string. Normally this will + be the same as the number of bytes in a string for single byte strings, + but will be different for multibyte. +**/ + +size_t str_ascii_charnum(const char *s) +{ + pstring tmpbuf2; + push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE); + return strlen(tmpbuf2); +} + +/** + Trim the specified elements off the front and back of a string. +**/ + +BOOL trim_string(char *s,const char *front,const char *back) +{ + BOOL ret = False; + size_t front_len; + size_t back_len; + size_t len; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) + return False; + + front_len = front? strlen(front) : 0; + back_len = back? strlen(back) : 0; + + len = strlen(s); + + if (front_len) { + while (len && strncmp(s, front, front_len)==0) { + memcpy(s, s+front_len, (len-front_len)+1); + len -= front_len; + ret=True; + } + } + + if (back_len) { + while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) { + s[len-back_len]='\0'; + len -= back_len; + ret=True; + } + } + return ret; +} + +/** + Does a string have any uppercase chars in it? +**/ + +BOOL strhasupper(const char *s) +{ + smb_ucs2_t *ptr; + push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + for(ptr=tmpbuf;*ptr;ptr++) + if(isupper_w(*ptr)) + return True; + return(False); +} + +/** + Does a string have any lowercase chars in it? +**/ + +BOOL strhaslower(const char *s) +{ + smb_ucs2_t *ptr; + push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + for(ptr=tmpbuf;*ptr;ptr++) + if(islower_w(*ptr)) + return True; + return(False); +} + +/** + Find the number of 'c' chars in a string +**/ + +size_t count_chars(const char *s,char c) +{ + smb_ucs2_t *ptr; + int count; + push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + for(count=0,ptr=tmpbuf;*ptr;ptr++) + if(*ptr==UCS2_CHAR(c)) + count++; + return(count); +} + +/** +Return True if a string consists only of one particular character. +**/ + +BOOL str_is_all(const char *s,char c) +{ + smb_ucs2_t *ptr; + + if(s == NULL) + return False; + if(!*s) + return False; + + push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + for(ptr=tmpbuf;*ptr;ptr++) + if(*ptr!=UCS2_CHAR(c)) + return False; + + return True; +} + +/** + Safe string copy into a known length string. maxlength does not + include the terminating zero. +**/ + +char *safe_strcpy(char *dest,const char *src, size_t maxlength) +{ + size_t len; + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in safe_strcpy\n")); + return NULL; + } + +#ifdef DEVELOPER + /* We intentionally write out at the extremity of the destination + * string. If the destination is too short (e.g. pstrcpy into mallocd + * or fstring) then this should cause an error under a memory + * checker. */ + dest[maxlength] = '\0'; + if (PTR_DIFF(&len, dest) > 0) { /* check if destination is on the stack, ok if so */ + log_suspicious_usage("safe_strcpy", src); + } +#endif + + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + + if (len > maxlength) { + DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", + (unsigned int)(len-maxlength), len, maxlength, src)); + len = maxlength; + } + + memmove(dest, src, len); + dest[len] = 0; + return dest; +} + +/** + Safe string cat into a string. maxlength does not + include the terminating zero. +**/ + +char *safe_strcat(char *dest, const char *src, size_t maxlength) +{ + size_t src_len, dest_len; + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in safe_strcat\n")); + return NULL; + } + + if (!src) + return dest; + +#ifdef DEVELOPER + if (PTR_DIFF(&src_len, dest) > 0) { /* check if destination is on the stack, ok if so */ + log_suspicious_usage("safe_strcat", src); + } +#endif + src_len = strlen(src); + dest_len = strlen(dest); + + if (src_len + dest_len > maxlength) { + DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", + (int)(src_len + dest_len - maxlength), src)); + if (maxlength > dest_len) { + memcpy(&dest[dest_len], src, maxlength - dest_len); + } + dest[maxlength] = 0; + return NULL; + } + + memcpy(&dest[dest_len], src, src_len); + dest[dest_len + src_len] = 0; + return dest; +} + +/** + Paranoid strcpy into a buffer of given length (includes terminating + zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars + and replaces with '_'. Deliberately does *NOT* check for multibyte + characters. Don't change it ! +**/ + +char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength) +{ + size_t len, i; + + if (maxlength == 0) { + /* can't fit any bytes at all! */ + return NULL; + } + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n")); + return NULL; + } + + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + if (len >= maxlength) + len = maxlength - 1; + + if (!other_safe_chars) + other_safe_chars = ""; + + for(i = 0; i < len; i++) { + int val = (src[i] & 0xff); + if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val)) + dest[i] = src[i]; + else + dest[i] = '_'; + } + + dest[i] = '\0'; + + return dest; +} + +/** + Like strncpy but always null terminates. Make sure there is room! + The variable n should always be one less than the available size. +**/ + +char *StrnCpy(char *dest,const char *src,size_t n) +{ + char *d = dest; + if (!dest) + return(NULL); + if (!src) { + *dest = 0; + return(dest); + } + while (n-- && (*d++ = *src++)) + ; + *d = 0; + return(dest); +} + +/** + Like strncpy but copies up to the character marker. always null terminates. + returns a pointer to the character marker in the source string (src). +**/ + +char *strncpyn(char *dest, const char *src, size_t n, char c) +{ + char *p; + size_t str_len; + + p = strchr_m(src, c); + if (p == NULL) { + DEBUG(5, ("strncpyn: separator character (%c) not found\n", c)); + return NULL; + } + + str_len = PTR_DIFF(p, src); + strncpy(dest, src, MIN(n, str_len)); + dest[str_len] = '\0'; + + return p; +} + +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + +**/ + +size_t strhex_to_str(char *p, size_t len, const char *strhex) +{ + size_t i; + size_t num_chars = 0; + unsigned char lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1 = NULL, *p2 = NULL; + + for (i = 0; i < len && strhex[i] != 0; i++) { + if (strnequal(hexchars, "0x", 2)) { + i++; /* skip two chars */ + continue; + } + + if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + i++; /* next hex digit */ + + if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + /* get the two nybbles */ + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + p[num_chars] = (hinybble << 4) | lonybble; + num_chars++; + + p1 = NULL; + p2 = NULL; + } + return num_chars; +} + +/** + Check if a string is part of a list. +**/ + +BOOL in_list(const char *s, const char *list, BOOL casesensitive) +{ + pstring tok; + const char *p=list; + + if (!list) + return(False); + + while (next_token(&p,tok,LIST_SEP,sizeof(tok))) { + if (casesensitive) { + if (strcmp(tok,s) == 0) + return(True); + } else { + if (StrCaseCmp(tok,s) == 0) + return(True); + } + } + return(False); +} + +/** + Set a string value, allocing the space for the string +**/ +static BOOL string_init(char **dest,const char *src) +{ + size_t l; + if (!src) src = ""; + + l = strlen(src); + + (*dest) = strdup(src); + if ((*dest) == NULL) { + DEBUG(0,("Out of memory in string_init\n")); + return False; + } + return True; +} + +/** + Free a string value. +**/ +void string_free(char **s) +{ + if (s) SAFE_FREE(*s); +} + +/** + Set a string value, deallocating any existing space, and allocing the space + for the string +**/ +BOOL string_set(char **dest, const char *src) +{ + string_free(dest); + return string_init(dest,src); +} + +/** + Substitute a string for a pattern in another string. Make sure there is + enough room! + + This routine looks for pattern in s and replaces it with + insert. It may do multiple replacements. + + Any of " ; ' $ or ` in the insert string are replaced with _ + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ + +void string_sub(char *s,const char *pattern, const char *insert, size_t len) +{ + char *p; + ssize_t ls,lp,li, i; + + if (!insert || !pattern || !*pattern || !s) + return; + + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); + + if (len == 0) + len = ls + 1; /* len is number of *bytes* */ + + while (lp <= ls && (p = strstr(s,pattern))) { + if (ls + (li-lp) >= len) { + DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + for (i=0;i 0) { + char *t = Realloc(string, ls + ld + 1); + if (!t) { + DEBUG(0, ("realloc_string_sub: out of memory!\n")); + SAFE_FREE(in); + return NULL; + } + string = t; + p = t + (p - s); + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + memcpy(p, in, li); + s = p + li; + ls += ld; + } + SAFE_FREE(in); + return string; +} + +/** + Similar to string_sub() but allows for any character to be substituted. + Use with caution! + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ + +void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) +{ + char *p; + ssize_t ls,lp,li; + + if (!insert || !pattern || !s) + return; + + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); + + if (!*pattern) + return; + + if (len == 0) + len = ls + 1; /* len is number of *bytes* */ + + while (lp <= ls && (p = strstr(s,pattern))) { + if (ls + (li-lp) >= len) { + DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + memcpy(p, insert, li); + s = p + li; + ls += (li-lp); + } +} + +/** + Similar to all_string_sub but for unicode strings. + Return a new allocated unicode string. + similar to string_sub() but allows for any character to be substituted. + Use with caution! +**/ + +smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern, + const smb_ucs2_t *insert) +{ + smb_ucs2_t *r, *rp; + const smb_ucs2_t *sp; + size_t lr, lp, li, lt; + + if (!insert || !pattern || !*pattern || !s) + return NULL; + + lt = (size_t)strlen_w(s); + lp = (size_t)strlen_w(pattern); + li = (size_t)strlen_w(insert); + + if (li > lp) { + const smb_ucs2_t *st = s; + int ld = li - lp; + while ((sp = strstr_w(st, pattern))) { + st = sp + lp; + lt += ld; + } + } + + r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t))); + if (!r) { + DEBUG(0, ("all_string_sub_w: out of memory!\n")); + return NULL; + } + + while ((sp = strstr_w(s, pattern))) { + memcpy(rp, s, (sp - s)); + rp += ((sp - s) / sizeof(smb_ucs2_t)); + memcpy(rp, insert, (li * sizeof(smb_ucs2_t))); + s = sp + lp; + rp += li; + } + lr = ((rp - r) / sizeof(smb_ucs2_t)); + if (lr < lt) { + memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t))); + rp += (lt - lr); + } + *rp = 0; + + return r; +} + +smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern, + const char *insert) +{ + wpstring p, i; + + if (!insert || !pattern || !s) + return NULL; + push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE); + push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE); + return all_string_sub_w(s, p, i); +} + +/** + Splits out the front and back at a separator. +**/ + +void split_at_last_component(char *path, char *front, char sep, char *back) +{ + char *p = strrchr_m(path, sep); + + if (p != NULL) + *p = 0; + + if (front != NULL) + pstrcpy(front, path); + + if (p != NULL) { + if (back != NULL) + pstrcpy(back, p+1); + *p = '\\'; + } else { + if (back != NULL) + back[0] = 0; + } +} + +/** + Write an octal as a string. +**/ + +const char *octal_string(int i) +{ + static char ret[64]; + if (i == -1) + return "-1"; + slprintf(ret, sizeof(ret)-1, "0%o", i); + return ret; +} + + +/** + Truncate a string at a specified length. +**/ + +char *string_truncate(char *s, int length) +{ + if (s && strlen(s) > length) + s[length] = 0; + return s; +} + +/** + Strchr and strrchr_m are very hard to do on general multi-byte strings. + We convert via ucs2 for now. +**/ + +char *strchr_m(const char *s, char c) +{ + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strchr_w(ws, UCS2_CHAR(c)); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); +} + +char *strrchr_m(const char *s, char c) +{ + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strrchr_w(ws, UCS2_CHAR(c)); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); +} + +/** + Convert a string to lower case. +**/ + +void strlower_m(char *s) +{ + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (*s && !(((unsigned char)s[0]) & 0x7F)) { + *s = tolower((unsigned char)*s); + s++; + } + + if (!*s) + return; + + /* I assume that lowercased string takes the same number of bytes + * as source string even in UTF-8 encoding. (VIV) */ + unix_strlower(s,strlen(s)+1,s,strlen(s)+1); +} + +/** + Duplicate convert a string to lower case. +**/ + +char *strdup_lower(const char *s) +{ + char *t = strdup(s); + if (t == NULL) { + DEBUG(0, ("strdup_lower: Out of memory!\n")); + return NULL; + } + strlower_m(t); + return t; +} + +/** + Convert a string to upper case. +**/ + +void strupper_m(char *s) +{ + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (*s && !(((unsigned char)s[0]) & 0x7F)) { + *s = toupper((unsigned char)*s); + s++; + } + + if (!*s) + return; + + /* I assume that lowercased string takes the same number of bytes + * as source string even in multibyte encoding. (VIV) */ + unix_strupper(s,strlen(s)+1,s,strlen(s)+1); +} + +/** + Convert a string to upper case. +**/ + +char *strdup_upper(const char *s) +{ + char *t = strdup(s); + if (t == NULL) { + DEBUG(0, ("strdup_upper: Out of memory!\n")); + return NULL; + } + strupper_m(t); + return t; +} + +/** + Return a RFC2254 binary string representation of a buffer. + Used in LDAP filters. + Caller must free. +**/ + +char *binary_string(char *buf, int len) +{ + char *s; + int i, j; + const char *hex = "0123456789ABCDEF"; + s = malloc(len * 3 + 1); + if (!s) + return NULL; + for (j=i=0;i> 4]; + s[j+2] = hex[((unsigned char)buf[i]) & 0xF]; + j += 3; + } + s[j] = 0; + return s; +} + +/** + Just a typesafety wrapper for snprintf into a pstring. +**/ + + int pstr_sprintf(pstring s, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsnprintf(s, PSTRING_LEN, fmt, ap); + va_end(ap); + return ret; +} + +/** + Just a typesafety wrapper for snprintf into a fstring. +**/ + + int fstr_sprintf(fstring s, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsnprintf(s, FSTRING_LEN, fmt, ap); + va_end(ap); + return ret; +} + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ + + char *strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + + size_t strnlen(const char *s, size_t n) +{ + int i; + for (i=0; s[i] && i= '0' && c1 <= '9') + c1 = c1 - '0'; + else if (c1 >= 'A' && c1 <= 'F') + c1 = 10 + c1 - 'A'; + else if (c1 >= 'a' && c1 <= 'f') + c1 = 10 + c1 - 'a'; + else {p++; continue;} + + if (c2 >= '0' && c2 <= '9') + c2 = c2 - '0'; + else if (c2 >= 'A' && c2 <= 'F') + c2 = 10 + c2 - 'A'; + else if (c2 >= 'a' && c2 <= 'f') + c2 = 10 + c2 - 'a'; + else {p++; continue;} + + *p = (c1<<4) | c2; + + memmove(p+1, p+3, strlen(p+3)+1); + p++; + } +} + +static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * Decode a base64 string into a DATA_BLOB - simple and slow algorithm + **/ +DATA_BLOB base64_decode_data_blob(const char *s) +{ + int bit_offset, byte_offset, idx, i, n; + DATA_BLOB decoded = data_blob(s, strlen(s)+1); + unsigned char *d = decoded.data; + char *p; + + n=i=0; + + while (*s && (p=strchr_m(b64,*s))) { + idx = (int)(p - b64); + byte_offset = (i*6)/8; + bit_offset = (i*6)%8; + d[byte_offset] &= ~((1<<(8-bit_offset))-1); + if (bit_offset < 3) { + d[byte_offset] |= (idx << (2-bit_offset)); + n = byte_offset+1; + } else { + d[byte_offset] |= (idx >> (bit_offset-2)); + d[byte_offset+1] = 0; + d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; + n = byte_offset+2; + } + s++; i++; + } + + /* fix up length */ + decoded.length = n; + return decoded; +} + +/** + * Decode a base64 string in-place - wrapper for the above + **/ +void base64_decode_inplace(char *s) +{ + DATA_BLOB decoded = base64_decode_data_blob(s); + memcpy(s, decoded.data, decoded.length); + data_blob_free(&decoded); + + /* null terminate */ + s[decoded.length] = '\0'; +} + +/** + * Encode a base64 string into a malloc()ed string caller to free. + * + *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments + **/ +char * base64_encode_data_blob(DATA_BLOB data) +{ + int bits = 0; + int char_count = 0; + size_t out_cnt = 0; + size_t len = data.length; + size_t output_len = data.length * 2; + char *result = malloc(output_len); /* get us plenty of space */ + + while (len-- && out_cnt < (data.length * 2) - 5) { + int c = (unsigned char) *(data.data++); + bits += c; + char_count++; + if (char_count == 3) { + result[out_cnt++] = b64[bits >> 18]; + result[out_cnt++] = b64[(bits >> 12) & 0x3f]; + result[out_cnt++] = b64[(bits >> 6) & 0x3f]; + result[out_cnt++] = b64[bits & 0x3f]; + bits = 0; + char_count = 0; + } else { + bits <<= 8; + } + } + if (char_count != 0) { + bits <<= 16 - (8 * char_count); + result[out_cnt++] = b64[bits >> 18]; + result[out_cnt++] = b64[(bits >> 12) & 0x3f]; + if (char_count == 1) { + result[out_cnt++] = '='; + result[out_cnt++] = '='; + } else { + result[out_cnt++] = b64[(bits >> 6) & 0x3f]; + result[out_cnt++] = '='; + } + } + result[out_cnt] = '\0'; /* terminate */ + return result; +} + +#ifdef VALGRIND +size_t valgrind_strlen(const char *s) +{ + size_t count; + for(count = 0; *s++; count++) + ; + return count; +} +#endif diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c new file mode 100644 index 0000000000..e5d2b8c3db --- /dev/null +++ b/source4/lib/util_unistr.c @@ -0,0 +1,838 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifndef MAXUNI +#define MAXUNI 1024 +#endif + +/* these 3 tables define the unicode case handling. They are loaded + at startup either via mmap() or read() from the lib directory */ +static smb_ucs2_t *upcase_table; +static smb_ucs2_t *lowcase_table; +static uint8 *valid_table; + + +/******************************************************************* +load the case handling tables +********************************************************************/ +void load_case_tables(void) +{ + static int initialised; + int i; + TALLOC_CTX *mem_ctx; + + if (initialised) return; + initialised = 1; + + mem_ctx = talloc_init("load_case_tables"); + if (!mem_ctx) { + smb_panic("No memory for case_tables"); + } + upcase_table = map_file(lib_path(mem_ctx, "upcase.dat"), 0x20000); + lowcase_table = map_file(lib_path(mem_ctx, "lowcase.dat"), 0x20000); + talloc_destroy(mem_ctx); + + /* we would like Samba to limp along even if these tables are + not available */ + if (!upcase_table) { + DEBUG(1,("creating lame upcase table\n")); + upcase_table = malloc(0x20000); + if (!upcase_table) { + smb_panic("No memory for upcase tables"); + } + for (i=0;i<0x10000;i++) { + smb_ucs2_t v; + SSVAL(&v, 0, i); + upcase_table[v] = i; + } + for (i=0;i<256;i++) { + smb_ucs2_t v; + SSVAL(&v, 0, UCS2_CHAR(i)); + upcase_table[v] = UCS2_CHAR(islower(i)?toupper(i):i); + } + } + + if (!lowcase_table) { + DEBUG(1,("creating lame lowcase table\n")); + lowcase_table = malloc(0x20000); + if (!lowcase_table) { + smb_panic("No memory for lowcase tables"); + } + for (i=0;i<0x10000;i++) { + smb_ucs2_t v; + SSVAL(&v, 0, i); + lowcase_table[v] = i; + } + for (i=0;i<256;i++) { + smb_ucs2_t v; + SSVAL(&v, 0, UCS2_CHAR(i)); + lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i); + } + } +} + +/* + see if a ucs2 character can be mapped correctly to a dos character + and mapped back to the same character in ucs2 +*/ +static int check_dos_char(smb_ucs2_t c) +{ + char buf[10]; + smb_ucs2_t c2 = 0; + int len1, len2; + len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf)); + if (len1 == 0) return 0; + len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2); + if (len2 != 2) return 0; + return (c == c2); +} + +/** + * Load the valid character map table from valid.dat or + * create from the configured codepage. + * + * This function is called whenever the configuration is reloaded. + * However, the valid character table is not changed if it's loaded + * from a file, because we can't unmap files. + **/ +void init_valid_table(void) +{ + static int mapped_file; + int i; + const char *allowed = ".!#$%&'()_-@^`~"; + uint8 *valid_file; + TALLOC_CTX *mem_ctx; + + if (mapped_file) { + /* Can't unmap files, so stick with what we have */ + return; + } + + mem_ctx = talloc_init("init_valid_table"); + if (!mem_ctx) { + smb_panic("No memory for valid_table"); + } + valid_file = map_file(lib_path(mem_ctx, "valid.dat"), 0x10000); + talloc_destroy(mem_ctx); + if (valid_file) { + valid_table = valid_file; + mapped_file = 1; + return; + } + + /* Otherwise, we're using a dynamically created valid_table. + * It might need to be regenerated if the code page changed. + * We know that we're not using a mapped file, so we can + * free() the old one. */ + if (valid_table) free(valid_table); + + DEBUG(2,("creating default valid table\n")); + valid_table = malloc(0x10000); + if (!valid_table) { + smb_panic("No memory for valid_table"); + } + for (i=0;i<128;i++) + valid_table[i] = isalnum(i) || strchr(allowed,i); + + for (;i<0x10000;i++) { + smb_ucs2_t c; + SSVAL(&c, 0, i); + valid_table[i] = check_dos_char(c); + } +} + + + +/******************************************************************* + Write a string in (little-endian) unicode format. src is in + the current DOS codepage. len is the length in bytes of the + string pointed to by dst. + + if null_terminate is True then null terminate the packet (adds 2 bytes) + + the return value is the length in bytes consumed by the string, including the + null termination if applied +********************************************************************/ + +size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate) +{ + return push_ucs2(NULL, dst, src, len, + STR_UNICODE|STR_NOALIGN | (null_terminate?STR_TERMINATE:0)); +} + + +/******************************************************************* + Skip past a unicode string, but not more than len. Always move + past a terminating zero if found. +********************************************************************/ + +char *skip_unibuf(char *src, size_t len) +{ + char *srcend = src + len; + + while (src < srcend && SVAL(src,0)) + src += 2; + + if(!SVAL(src,0)) + src += 2; + + return src; +} + +/* Copy a string from little-endian or big-endian unicode source (depending + * on flags) to internal samba format destination + */ +int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags) +{ + if (!src) return 0; + if(dest_len==-1) dest_len=MAXUNI-3; + return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN); +} + +/* Copy a string from a unistr2 source to internal samba format + destination. Use this instead of direct calls to rpcstr_pull() to avoid + having to determine whether the source string is null terminated. */ + +int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src) +{ + return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring), + src->uni_str_len * 2, 0); +} + +/* Converts a string from internal samba format to unicode + */ +int rpcstr_push(void* dest, const char *src, int dest_len, int flags) +{ + return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN); +} + +/******************************************************************* + Convert a (little-endian) UNISTR2 structure to an ASCII string +********************************************************************/ +void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) +{ + if (str == NULL) { + *dest='\0'; + return; + } + pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN); +} + +/******************************************************************* +give a static string for displaying a UNISTR2 +********************************************************************/ +const char *unistr2_static(TALLOC_CTX *mem_ctx, const UNISTR2 *str) +{ + pstring ret; + unistr2_to_ascii(ret, str, sizeof(ret)); + return talloc_strdup(mem_ctx, ret); +} + + +/******************************************************************* + duplicate a UNISTR2 string into a null terminated char* + using a talloc context +********************************************************************/ +char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str) +{ + char *s; + int maxlen = (str->uni_str_len+1)*4; + if (!str->buffer) return NULL; + s = (char *)talloc(ctx, maxlen); /* convervative */ + if (!s) return NULL; + pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, + STR_NOALIGN); + return s; +} + + +/******************************************************************* +Return a number stored in a buffer +********************************************************************/ + +uint32 buffer2_to_uint32(BUFFER2 *str) +{ + if (str->buf_len == 4) + return IVAL(str->buffer, 0); + else + return 0; +} + +/******************************************************************* + Convert a wchar to upper case. +********************************************************************/ + +smb_ucs2_t toupper_w(smb_ucs2_t val) +{ + return upcase_table[SVAL(&val,0)]; +} + +/******************************************************************* + Convert a wchar to lower case. +********************************************************************/ + +smb_ucs2_t tolower_w( smb_ucs2_t val ) +{ + return lowcase_table[SVAL(&val,0)]; + +} + +/******************************************************************* +determine if a character is lowercase +********************************************************************/ +BOOL islower_w(smb_ucs2_t c) +{ + return upcase_table[SVAL(&c,0)] != c; +} + +/******************************************************************* +determine if a character is uppercase +********************************************************************/ +BOOL isupper_w(smb_ucs2_t c) +{ + return lowcase_table[SVAL(&c,0)] != c; +} + + +/******************************************************************* +determine if a character is valid in a 8.3 name +********************************************************************/ +BOOL isvalid83_w(smb_ucs2_t c) +{ + return valid_table[SVAL(&c,0)] != 0; +} + +/******************************************************************* + Count the number of characters in a smb_ucs2_t string. +********************************************************************/ +size_t strlen_w(const smb_ucs2_t *src) +{ + size_t len; + + for (len = 0; SVAL(src,0); len++, src++) ; + + return len; +} + +/******************************************************************* + Count up to max number of characters in a smb_ucs2_t string. +********************************************************************/ +size_t strnlen_w(const smb_ucs2_t *src, size_t max) +{ + size_t len; + + for (len = 0; (len < max) && SVAL(src, 0); len++, src++) ; + + return len; +} + +/******************************************************************* +wide strchr() +********************************************************************/ +const smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +{ + while (*s != 0) { + if (c == *s) return s; + s++; + } + if (c == *s) return s; + + return NULL; +} + +const smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) +{ + return strchr_w(s, UCS2_CHAR(c)); +} + +const smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +{ + const smb_ucs2_t *p = s; + int len = strlen_w(s); + if (len == 0) return NULL; + p += (len - 1); + do { + if (c == *p) return p; + } while (p-- != s); + return NULL; +} + +/******************************************************************* +wide strstr() +********************************************************************/ +const smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) +{ + const smb_ucs2_t *r; + size_t slen, inslen; + + if (!s || !*s || !ins || !*ins) return NULL; + slen = strlen_w(s); + inslen = strlen_w(ins); + r = s; + while ((r = strchr_w(r, *ins))) { + if (strncmp_w(r, ins, inslen) == 0) return r; + r++; + } + return NULL; +} + +/******************************************************************* + Convert a string to lower case. + return True if any char is converted +********************************************************************/ +BOOL strlower_w(smb_ucs2_t *s) +{ + BOOL ret = False; + while (*s) { + smb_ucs2_t v = tolower_w(*s); + if (v != *s) { + *s = v; + ret = True; + } + s++; + } + return ret; +} + +/******************************************************************* + Convert a string to upper case. + return True if any char is converted +********************************************************************/ +BOOL strupper_w(smb_ucs2_t *s) +{ + BOOL ret = False; + while (*s) { + smb_ucs2_t v = toupper_w(*s); + if (v != *s) { + *s = v; + ret = True; + } + s++; + } + return ret; +} + +int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) +{ + while (*b && *a == *b) { a++; b++; } + return (*a - *b); + /* warning: if *a != *b and both are not 0 we retrun a random + greater or lesser than 0 number not realted to which + string is longer */ +} + +int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) +{ + size_t n = 0; + while ((n < len) && *b && *a == *b) { a++; b++; n++;} + return (len - n)?(*a - *b):0; +} + +/******************************************************************* +case insensitive string comparison +********************************************************************/ +int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) +{ + while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; } + return (tolower_w(*a) - tolower_w(*b)); +} + +/******************************************************************* +case insensitive string comparison, lenght limited +********************************************************************/ +int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) +{ + size_t n = 0; + while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; } + return (len - n)?(tolower_w(*a) - tolower_w(*b)):0; +} + +/******************************************************************* + compare 2 strings +********************************************************************/ +BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2) +{ + if (s1 == s2) return(True); + if (!s1 || !s2) return(False); + + return(strcasecmp_w(s1,s2)==0); +} + +/******************************************************************* + compare 2 strings up to and including the nth char. + ******************************************************************/ +BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n) +{ + if (s1 == s2) return(True); + if (!s1 || !s2 || !n) return(False); + + return(strncasecmp_w(s1,s2,n)==0); +} + +/******************************************************************* +duplicate string +********************************************************************/ +smb_ucs2_t *strdup_w(const smb_ucs2_t *src) +{ + return strndup_w(src, 0); +} + +/* if len == 0 then duplicate the whole string */ +smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len) +{ + smb_ucs2_t *dest; + + if (!len) len = strlen_w(src); + dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t)); + if (!dest) { + DEBUG(0,("strdup_w: out of memory!\n")); + return NULL; + } + + memcpy(dest, src, len * sizeof(smb_ucs2_t)); + dest[len] = 0; + + return dest; +} + +/******************************************************************* +copy a string with max len +********************************************************************/ + +smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) +{ + size_t len; + + if (!dest || !src) return NULL; + + for (len = 0; (src[len] != 0) && (len < max); len++) + dest[len] = src[len]; + while (len < max) + dest[len++] = 0; + + return dest; +} + + +/******************************************************************* +append a string of len bytes and add a terminator +********************************************************************/ + +smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) +{ + size_t start; + size_t len; + + if (!dest || !src) return NULL; + + start = strlen_w(dest); + len = strnlen_w(src, max); + + memcpy(&dest[start], src, len*sizeof(smb_ucs2_t)); + dest[start+len] = 0; + + return dest; +} + +smb_ucs2_t *strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src) +{ + size_t start; + size_t len; + + if (!dest || !src) return NULL; + + start = strlen_w(dest); + len = strlen_w(src); + + memcpy(&dest[start], src, len*sizeof(smb_ucs2_t)); + dest[start+len] = 0; + + return dest; +} + + +/******************************************************************* +replace any occurence of oldc with newc in unicode string +********************************************************************/ + +void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc) +{ + for(;*s;s++) { + if(*s==oldc) *s=newc; + } +} + +/******************************************************************* +trim unicode string +********************************************************************/ + +BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front, + const smb_ucs2_t *back) +{ + BOOL ret = False; + size_t len, front_len, back_len; + + if (!s || !*s) return False; + + len = strlen_w(s); + + if (front && *front) { + front_len = strlen_w(front); + while (len && strncmp_w(s, front, front_len) == 0) { + memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t)); + len -= front_len; + ret = True; + } + } + + if (back && *back) { + back_len = strlen_w(back); + while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) { + s[len - back_len] = 0; + len -= back_len; + ret = True; + } + } + + return ret; +} + +/* + The *_wa() functions take a combination of 7 bit ascii + and wide characters They are used so that you can use string + functions combining C string constants with ucs2 strings + + The char* arguments must NOT be multibyte - to be completely sure + of this only pass string constants */ + + +void pstrcpy_wa(smb_ucs2_t *dest, const char *src) +{ + int i; + for (i=0;ibuffer) { + dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1)); + if (!dst->buffer) return NULL; + } + + /* set UNISTR2 parameters */ + dst->uni_max_len = len + 1; + dst->undoc = 0; + dst->uni_str_len = len; + + /* copy the actual unicode string */ + strncpy_w(dst->buffer, src, dst->uni_max_len); + + return dst; +}; + diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c new file mode 100644 index 0000000000..76eb93a9b8 --- /dev/null +++ b/source4/lib/util_uuid.c @@ -0,0 +1,104 @@ +/* + * Unix SMB/CIFS implementation. + * UUID server routines + * Copyright (C) Theodore Ts'o 1996, 1997, + * Copyright (C) Jim McDonough 2002. + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/* + * Offset between 15-Oct-1582 and 1-Jan-70 + */ +#define TIME_OFFSET_HIGH 0x01B21DD2 +#define TIME_OFFSET_LOW 0x13814000 + +struct uuid { + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq[2]; + uint8 node[6]; +}; + + +static void uuid_pack(const struct uuid *uu, GUID *ptr) +{ + uint8 *out = ptr->info; + + SIVAL(out, 0, uu->time_low); + SSVAL(out, 4, uu->time_mid); + SSVAL(out, 6, uu->time_hi_and_version); + memcpy(out+8, uu->clock_seq, 2); + memcpy(out+10, uu->node, 6); +} + +static void uuid_unpack(const GUID in, struct uuid *uu) +{ + const uint8 *ptr = in.info; + + uu->time_low = IVAL(ptr, 0); + uu->time_mid = SVAL(ptr, 4); + uu->time_hi_and_version = SVAL(ptr, 6); + memcpy(uu->clock_seq, ptr+8, 2); + memcpy(uu->node, ptr+10, 6); +} + +void uuid_generate_random(GUID *out) +{ + GUID tmp; + struct uuid uu; + + generate_random_buffer(tmp.info, sizeof(tmp.info), True); + uuid_unpack(tmp, &uu); + + uu.clock_seq[0] = (uu.clock_seq[0] & 0x3F) | 0x80; + uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; + uuid_pack(&uu, out); +} + +char *guid_to_string(const GUID in) +{ + struct uuid uu; + char *out; + + uuid_unpack(in, &uu); + + asprintf(&out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uu.time_low, uu.time_mid, uu.time_hi_and_version, + uu.clock_seq[0], uu.clock_seq[1], + uu.node[0], uu.node[1], uu.node[2], + uu.node[3], uu.node[4], uu.node[5]); + + return out; +} + +const char *uuid_string(TALLOC_CTX *mem_ctx, const GUID in) +{ + struct uuid uu; + char *out; + + uuid_unpack(in, &uu); + if (!out) return NULL; + out = talloc_asprintf(mem_ctx, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uu.time_low, uu.time_mid, uu.time_hi_and_version, + uu.clock_seq[0], uu.clock_seq[1], + uu.node[0], uu.node[1], uu.node[2], + uu.node[3], uu.node[4], uu.node[5]); + return out; +} diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c new file mode 100644 index 0000000000..30e81b08ab --- /dev/null +++ b/source4/lib/wins_srv.c @@ -0,0 +1,361 @@ +/* + Unix SMB/CIFS implementation. + Samba wins server helper functions + Copyright (C) Andrew Tridgell 1992-2002 + Copyright (C) Christopher R. Hertel 2000 + Copyright (C) Tim Potter 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This is pretty much a complete rewrite of the earlier code. The main + aim of the rewrite is to add support for having multiple wins server + lists, so Samba can register with multiple groups of wins servers + and each group has a failover list of wins servers. + + Central to the way it all works is the idea of a wins server + 'tag'. A wins tag is a label for a group of wins servers. For + example if you use + + wins server = fred:192.168.2.10 mary:192.168.3.199 fred:192.168.2.61 + + then you would have two groups of wins servers, one tagged with the + name 'fred' and the other with the name 'mary'. I would usually + recommend using interface names instead of 'fred' and 'mary' but + they can be any alpha string. + + Now, how does it all work. Well, nmbd needs to register each of its + IPs with each of its names once with each group of wins servers. So + it tries registering with the first one mentioned in the list, then + if that fails it marks that WINS server dead and moves onto the next + one. + + In the client code things are a bit different. As each of the groups + of wins servers is a separate name space we need to try each of the + groups until we either succeed or we run out of wins servers to + try. If we get a negative response from a wins server then that + means the name doesn't exist in that group, so we give up on that + group and move to the next group. If we don't get a response at all + then maybe the wins server is down, in which case we need to + failover to the next one for that group. + + confused yet? (tridge) +*/ + +/* how long a server is marked dead for */ +#define DEATH_TIME 600 + +/* The list of dead wins servers is stored in gencache.tdb. Each server is + marked dead from the point of view of a given source address. We keep a + separate dead list for each src address to cope with multiple interfaces + that are not routable to each other. + */ + +#define WINS_SRV_FMT "WINS_SRV_DEAD/%s,%s" /* wins_ip,src_ip */ + +static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip) +{ + char *keystr; + + if (asprintf(&keystr, WINS_SRV_FMT, inet_ntoa(wins_ip), + inet_ntoa(src_ip)) == -1) { + DEBUG(0, ("wins_srv_is_dead: malloc error\n")); + return NULL; + } + + return keystr; +} + +/* + see if an ip is on the dead list +*/ + +BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip) +{ + char *keystr = wins_srv_keystr(wins_ip, src_ip); + BOOL result; + + /* If the key exists then the WINS server has been marked as dead */ + + result = gencache_get(keystr, NULL, NULL); + SAFE_FREE(keystr); + + DEBUG(4, ("wins_srv_is_dead: %s is %s\n", inet_ntoa(wins_ip), + result ? "dead" : "alive")); + + return result; +} + + +/* + mark a wins server as being alive (for the moment) +*/ +void wins_srv_alive(struct in_addr wins_ip, struct in_addr src_ip) +{ + char *keystr = wins_srv_keystr(wins_ip, src_ip); + + gencache_del(keystr); + SAFE_FREE(keystr); + + DEBUG(4, ("wins_srv_alive: marking wins server %s alive\n", + inet_ntoa(wins_ip))); +} + +/* + mark a wins server as temporarily dead +*/ +void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip) +{ + char *keystr; + + if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip)) + return; + + keystr = wins_srv_keystr(wins_ip, src_ip); + + gencache_set(keystr, "DOWN", time(NULL) + DEATH_TIME); + + SAFE_FREE(keystr); + + DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n", + inet_ntoa(wins_ip), DEATH_TIME, inet_ntoa(src_ip))); +} + +/* + return the total number of wins servers, dead or not +*/ +unsigned wins_srv_count(void) +{ + const char **list; + int count = 0; + + if (lp_wins_support()) { + /* simple - just talk to ourselves */ + return 1; + } + + list = lp_wins_server_list(); + for (count=0; list && list[count]; count++) + /* nop */ ; + + return count; +} + +/* an internal convenience structure for an IP with a short string tag + attached */ +struct tagged_ip { + fstring tag; + struct in_addr ip; +}; + +/* + parse an IP string that might be in tagged format + the result is a tagged_ip structure containing the tag + and the ip in in_addr format. If there is no tag then + use the tag '*' +*/ +static void parse_ip(TALLOC_CTX *mem_ctx, struct tagged_ip *ip, const char *str) +{ + char *s = strchr(str, ':'); + if (!s) { + fstrcpy(ip->tag, "*"); + ip->ip = *interpret_addr2(mem_ctx, str); + return; + } + + ip->ip = *interpret_addr2(mem_ctx, s+1); + fstrcpy(ip->tag, str); + s = strchr(ip->tag, ':'); + if (s) *s = 0; +} + + + +/* + return the list of wins server tags. A 'tag' is used to distinguish + wins server as either belonging to the same name space or a separate + name space. Usually you would setup your 'wins server' option to + list one or more wins server per interface and use the interface + name as your tag, but you are free to use any tag you like. +*/ +char **wins_srv_tags(void) +{ + char **ret = NULL; + int count=0, i, j; + const char **list; + TALLOC_CTX *mem_ctx; + + if (lp_wins_support()) { + /* give the caller something to chew on. This makes + the rest of the logic simpler (ie. less special cases) */ + ret = (char **)malloc(sizeof(char *)*2); + if (!ret) return NULL; + ret[0] = strdup("*"); + ret[1] = NULL; + return ret; + } + + list = lp_wins_server_list(); + if (!list) + return NULL; + + mem_ctx = talloc_init("wins_ssrv_tags"); + if (!mem_ctx) { + return NULL; + } + /* yes, this is O(n^2) but n is very small */ + for (i=0;list[i];i++) { + struct tagged_ip t_ip; + + parse_ip(mem_ctx, &t_ip, list[i]); + + /* see if we already have it */ + for (j=0;jbufused) return -1; + + /* on files being read full buffering is the only option */ + if ((f->open_flags & O_ACCMODE) == O_RDONLY) { + mode = X_IOFBF; + } + + /* destroy any earlier buffer */ + SAFE_FREE(f->buf); + f->buf = 0; + f->bufsize = 0; + f->next = NULL; + f->bufused = 0; + f->buftype = mode; + + if (f->buftype == X_IONBF) return 0; + + /* if buffering then we need some size */ + if (size == 0) size = XBUFSIZE; + + f->bufsize = size; + f->bufused = 0; + + return 0; +} + +/* allocate the buffer */ +static int x_allocate_buffer(XFILE *f) +{ + if (f->buf) return 1; + if (f->bufsize == 0) return 0; + f->buf = malloc(f->bufsize); + if (!f->buf) return 0; + f->next = f->buf; + return 1; +} + + +/* this looks more like open() than fopen(), but that is quite deliberate. + I want programmers to *think* about O_EXCL, O_CREAT etc not just + get them magically added +*/ +XFILE *x_fopen(const char *fname, int flags, mode_t mode) +{ + XFILE *ret; + + ret = (XFILE *)malloc(sizeof(XFILE)); + if (!ret) return NULL; + + memset(ret, 0, sizeof(XFILE)); + + if ((flags & O_ACCMODE) == O_RDWR) { + /* we don't support RDWR in XFILE - use file + descriptors instead */ + errno = EINVAL; + return NULL; + } + + ret->open_flags = flags; + + ret->fd = sys_open(fname, flags, mode); + if (ret->fd == -1) { + SAFE_FREE(ret); + return NULL; + } + + x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE); + + return ret; +} + +/* simulate fclose() */ +int x_fclose(XFILE *f) +{ + int ret; + + /* make sure we flush any buffered data */ + x_fflush(f); + + ret = close(f->fd); + f->fd = -1; + if (f->buf) { + /* make sure data can't leak into a later malloc */ + memset(f->buf, 0, f->bufsize); + SAFE_FREE(f->buf); + } + SAFE_FREE(f); + return ret; +} + +/* simulate fwrite() */ +size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) +{ + ssize_t ret; + size_t total=0; + + /* we might be writing unbuffered */ + if (f->buftype == X_IONBF || + (!f->buf && !x_allocate_buffer(f))) { + ret = write(f->fd, p, size*nmemb); + if (ret == -1) return -1; + return ret/size; + } + + + while (total < size*nmemb) { + size_t n = f->bufsize - f->bufused; + n = MIN(n, (size*nmemb)-total); + + if (n == 0) { + /* it's full, flush it */ + x_fflush(f); + continue; + } + + memcpy(f->buf + f->bufused, total+(const char *)p, n); + f->bufused += n; + total += n; + } + + /* when line buffered we need to flush at the last linefeed. This can + flush a bit more than necessary, but that is harmless */ + if (f->buftype == X_IOLBF && f->bufused) { + int i; + for (i=(size*nmemb)-1; i>=0; i--) { + if (*(i+(const char *)p) == '\n') { + x_fflush(f); + break; + } + } + } + + return total/size; +} + +/* thank goodness for asprintf() */ + int x_vfprintf(XFILE *f, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + VA_COPY(ap2, ap); + + len = vasprintf(&p, format, ap2); + if (len <= 0) return len; + ret = x_fwrite(p, 1, len, f); + SAFE_FREE(p); + return ret; +} + + int x_fprintf(XFILE *f, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = x_vfprintf(f, format, ap); + va_end(ap); + return ret; +} + +/* at least fileno() is simple! */ +int x_fileno(XFILE *f) +{ + return f->fd; +} + +/* simulate fflush() */ +int x_fflush(XFILE *f) +{ + int ret; + + if (f->flags & X_FLAG_ERROR) return -1; + + if ((f->open_flags & O_ACCMODE) != O_WRONLY) { + errno = EINVAL; + return -1; + } + + if (f->bufused == 0) return 0; + + ret = write(f->fd, f->buf, f->bufused); + if (ret == -1) return -1; + + f->bufused -= ret; + if (f->bufused > 0) { + f->flags |= X_FLAG_ERROR; + memmove(f->buf, ret + (char *)f->buf, f->bufused); + return -1; + } + + return 0; +} + +/* simulate setbuffer() */ +void x_setbuffer(XFILE *f, char *buf, size_t size) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size); +} + +/* simulate setbuf() */ +void x_setbuf(XFILE *f, char *buf) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE); +} + +/* simulate setlinebuf() */ +void x_setlinebuf(XFILE *f) +{ + x_setvbuf(f, NULL, X_IOLBF, 0); +} + + +/* simulate feof() */ +int x_feof(XFILE *f) +{ + if (f->flags & X_FLAG_EOF) return 1; + return 0; +} + +/* simulate ferror() */ +int x_ferror(XFILE *f) +{ + if (f->flags & X_FLAG_ERROR) return 1; + return 0; +} + +/* fill the read buffer */ +static void x_fillbuf(XFILE *f) +{ + int n; + + if (f->bufused) return; + + if (!f->buf && !x_allocate_buffer(f)) return; + + n = read(f->fd, f->buf, f->bufsize); + if (n <= 0) return; + f->bufused = n; + f->next = f->buf; +} + +/* simulate fgetc() */ +int x_fgetc(XFILE *f) +{ + int ret; + + if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF; + + if (f->bufused == 0) x_fillbuf(f); + + if (f->bufused == 0) { + f->flags |= X_FLAG_EOF; + return EOF; + } + + ret = *(unsigned char *)(f->next); + f->next++; + f->bufused--; + return ret; +} + +/* simulate fread */ +size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) +{ + size_t total = 0; + while (total < size*nmemb) { + int c = x_fgetc(f); + if (c == EOF) break; + (total+(char *)p)[0] = (char)c; + total++; + } + return total/size; +} + +/* simulate fgets() */ +char *x_fgets(char *s, int size, XFILE *stream) +{ + char *s0 = s; + int l = size; + while (l>1) { + int c = x_fgetc(stream); + if (c == EOF) break; + *s++ = (char)c; + l--; + if (c == '\n') break; + } + if (l==size || x_ferror(stream)) { + return 0; + } + *s = 0; + return s0; +} + +/* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is + * set then an error is returned */ +off_t x_tseek(XFILE *f, off_t offset, int whence) +{ + if (f->flags & X_FLAG_ERROR) + return -1; + + /* only SEEK_SET and SEEK_END are supported */ + /* SEEK_CUR needs internal offset counter */ + if (whence != SEEK_SET && whence != SEEK_END) { + f->flags |= X_FLAG_EINVAL; + errno = EINVAL; + return -1; + } + + /* empty the buffer */ + switch (f->open_flags & O_ACCMODE) { + case O_RDONLY: + f->bufused = 0; + break; + case O_WRONLY: + if (x_fflush(f) != 0) + return -1; + break; + default: + errno = EINVAL; + return -1; + } + + f->flags &= ~X_FLAG_EOF; + return (off_t)sys_lseek(f->fd, offset, whence); +} -- cgit From 2efe201fa4082f0aad7360b9f6f21c7683a29e96 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Thu, 14 Aug 2003 21:56:26 +0000 Subject: client/client.c - cannot initialize struct with non-const values include/byteorder.h - fix for IRIX compiler - cannot cast an LVALUE include/smb_interfaces.h - remove empty structure source/lib/debug.c - void functions cannot return value libcli/clifile.c - cannot assign *struct to struct (This used to be commit 9a724762012f55d21d44ea87add7daf21f7414d1) --- source4/lib/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/debug.c b/source4/lib/debug.c index 37f93b9ae5..792cf14c5a 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -129,13 +129,13 @@ const char *do_debug_tab(uint_t n) void log_suspicious_usage(const char *from, const char *info) { if (debug_handlers.ops.log_suspicious_usage) { - return debug_handlers.ops.log_suspicious_usage(from, info); + debug_handlers.ops.log_suspicious_usage(from, info); } } void print_suspicious_usage(const char* from, const char* info) { if (debug_handlers.ops.print_suspicious_usage) { - return debug_handlers.ops.print_suspicious_usage(from, info); + debug_handlers.ops.print_suspicious_usage(from, info); } } -- cgit From fe3195367803e90958ca6a159308c055dffbb1e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Aug 2003 15:16:34 +0000 Subject: a few build fixes to try to get irix building (This used to be commit 4059fbcf028e105c9377ec5a302623ae282e33f1) --- source4/lib/system_smbd.c | 119 ---------------------------------------------- 1 file changed, 119 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/system_smbd.c b/source4/lib/system_smbd.c index 3ae0a6395e..e69de29bb2 100644 --- a/source4/lib/system_smbd.c +++ b/source4/lib/system_smbd.c @@ -1,119 +0,0 @@ -/* - Unix SMB/CIFS implementation. - system call wrapper interface. - Copyright (C) Andrew Tridgell 2002 - Copyright (C) Andrew Barteltt 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This file may assume linkage with smbd - for things like become_root() - etc. -*/ - -#include "includes.h" - -#ifndef HAVE_GETGROUPLIST -/* - This is a *much* faster way of getting the list of groups for a user - without changing the current supplemenrary group list. The old - method used getgrent() which could take 20 minutes on a really big - network with hundeds of thousands of groups and users. The new method - takes a couple of seconds. - - NOTE!! this function only works if it is called as root! - */ -static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt) -{ - gid_t *gids_saved; - int ret, ngrp_saved, num_gids; - - if (non_root_mode()) { - *grpcnt = 0; - return 0; - } - - /* work out how many groups we need to save */ - ngrp_saved = getgroups(0, NULL); - if (ngrp_saved == -1) { - /* this shouldn't happen */ - return -1; - } - - gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1)); - if (!gids_saved) { - errno = ENOMEM; - return -1; - } - - ngrp_saved = getgroups(ngrp_saved, gids_saved); - if (ngrp_saved == -1) { - SAFE_FREE(gids_saved); - /* very strange! */ - return -1; - } - - if (initgroups(user, gid) != 0) { - DEBUG(0, ("getgrouplist_internals: initgroups() failed!\n")); - SAFE_FREE(gids_saved); - return -1; - } - - /* this must be done to cope with systems that put the current egid in the - return from getgroups() */ - save_re_gid(); - set_effective_gid(gid); - setgid(gid); - - num_gids = getgroups(0, NULL); - if (num_gids + 1 > *grpcnt) { - *grpcnt = num_gids + 1; - ret = -1; - } else { - ret = getgroups(*grpcnt - 1, &groups[1]); - if (ret >= 0) { - groups[0] = gid; - *grpcnt = ret + 1; - } - } - - restore_re_gid(); - - if (setgroups(ngrp_saved, gids_saved) != 0) { - /* yikes! */ - DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); - smb_panic("getgrouplist: failed to reset group list!\n"); - free(gids_saved); - return -1; - } - - free(gids_saved); - return ret; -} -#endif - -int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) -{ -#ifdef HAVE_GETGROUPLIST - return getgrouplist(user, gid, groups, grpcnt); -#else - int retval; - become_root(); - retval = getgrouplist_internals(user, gid, groups, grpcnt); - unbecome_root(); - return retval; -#endif -} -- cgit From cc38992e3f6c6ca04ae7170cb03028d3d1c06ae3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Aug 2003 16:19:48 +0000 Subject: fixed some places where we don't brace (flags & STR_UNICODE) this fixes the samba4 server with ascii clients (This used to be commit c770603ac6c3331a4ac79a650cbbbeb21c778137) --- source4/lib/charcnv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 90ddbb4d53..622de26ab8 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -769,7 +769,7 @@ ssize_t pull_utf8_allocate(void **dest, const char *src) ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) { if (!(flags & STR_ASCII) && \ - ((flags & STR_UNICODE || \ + (((flags & STR_UNICODE) || \ (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { return push_ucs2(base_ptr, dest, src, dest_len, flags); } @@ -794,7 +794,7 @@ ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t de ssize_t pull_string(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) { if (!(flags & STR_ASCII) && \ - ((flags & STR_UNICODE || \ + (((flags & STR_UNICODE) || \ (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags); } -- cgit From f24c298f43a86d117314007246e1175af74a7d96 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 15 Aug 2003 17:13:41 +0000 Subject: rename mutex_t to smb_mutex_t to prevent name collision (This used to be commit d32f14959277a5b7d1302638b65ff1fc568f08a9) --- source4/lib/mutex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c index 1be23a52ba..18b7e08b5a 100644 --- a/source4/lib/mutex.c +++ b/source4/lib/mutex.c @@ -20,7 +20,7 @@ */ #include "includes.h" -static mutex_t mutex_list[MUTEX_MAX]; +static smb_mutex_t mutex_list[MUTEX_MAX]; /* the registered mutex handlers */ static struct { @@ -38,7 +38,7 @@ int mutex_unlock_by_id(enum mutex_id id, const char *name) return mutex_unlock(&mutex_list[id], name); } -int mutex_init(mutex_t *mutex, const char *name) +int mutex_init(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_init) { return mutex_handlers.ops.mutex_init(mutex, name); @@ -46,7 +46,7 @@ int mutex_init(mutex_t *mutex, const char *name) return 0; } -int mutex_destroy(mutex_t *mutex, const char *name) +int mutex_destroy(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_destroy) { return mutex_handlers.ops.mutex_destroy(mutex, name); @@ -54,7 +54,7 @@ int mutex_destroy(mutex_t *mutex, const char *name) return 0; } -int mutex_lock(mutex_t *mutex, const char *name) +int mutex_lock(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_lock) { return mutex_handlers.ops.mutex_lock(mutex, name); @@ -62,7 +62,7 @@ int mutex_lock(mutex_t *mutex, const char *name) return 0; } -int mutex_unlock(mutex_t *mutex, const char *name) +int mutex_unlock(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_unlock) { return mutex_handlers.ops.mutex_unlock(mutex, name); -- cgit From de10237719db8101cd9487b257761d4721f857ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Aug 2003 18:54:44 +0000 Subject: more fixes from the IRIX compiler (thanks herb!) (This used to be commit 02d068ba7d81d6db25122144981c63f74ad44025) --- source4/lib/charcnv.c | 2 +- source4/lib/tdb/tdb.c | 4 ++-- source4/lib/tdb/tdb.h | 2 +- source4/lib/util_sock.c | 5 +---- source4/lib/util_str.c | 3 --- source4/lib/util_unistr.c | 6 ++---- source4/lib/util_uuid.c | 1 - 7 files changed, 7 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 622de26ab8..72277b4f2e 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -151,7 +151,7 @@ ssize_t convert_string(charset_t from, charset_t to, o_len=destlen; retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); if(retval==(size_t)-1) { - const char *reason="unknown error"; + const char *reason; switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 097209ff7a..513fbce519 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -166,9 +166,9 @@ struct list_struct { a blocking lock on SIGALRM. ***************************************************************/ -static sig_atomic_t *palarm_fired; +static SIG_ATOMIC_T *palarm_fired; -void tdb_set_lock_alarm(sig_atomic_t *palarm) +void tdb_set_lock_alarm(SIG_ATOMIC_T *palarm) { palarm_fired = palarm; } diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index 6f3b1ff756..720066f1b3 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -127,7 +127,7 @@ int tdb_lockall(TDB_CONTEXT *tdb); void tdb_unlockall(TDB_CONTEXT *tdb); /* Low level locking functions: use with care */ -void tdb_set_lock_alarm(sig_atomic_t *palarm); +void tdb_set_lock_alarm(SIG_ATOMIC_T *palarm); int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 42dc04f6c8..8362290804 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -439,7 +439,6 @@ static BOOL matchname(char *remotehost, struct in_addr addr) char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) { char *name_buf; - char *addr_buf; struct hostent *hp; struct in_addr addr; char *p; @@ -457,8 +456,6 @@ char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); if (fd == -1) return name_buf; - addr_buf = talloc_strdup(mem_ctx, p); - addr = *interpret_addr2(mem_ctx, p); /* Look up the remote host name. */ @@ -473,7 +470,7 @@ char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) } } - alpha_strcpy(name_buf, name_buf, "_-.", sizeof(name_buf)); + alpha_strcpy(name_buf, name_buf, "_-.", strlen(name_buf)+1); if (strstr(name_buf,"..")) { name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 19857cff86..f689ae4355 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -651,11 +651,8 @@ BOOL in_list(const char *s, const char *list, BOOL casesensitive) **/ static BOOL string_init(char **dest,const char *src) { - size_t l; if (!src) src = ""; - l = strlen(src); - (*dest) = strdup(src); if ((*dest) == NULL) { DEBUG(0,("Out of memory in string_init\n")); diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index e5d2b8c3db..71a67eb159 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -383,10 +383,9 @@ wide strstr() const smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) { const smb_ucs2_t *r; - size_t slen, inslen; + size_t inslen; if (!s || !*s || !ins || !*ins) return NULL; - slen = strlen_w(s); inslen = strlen_w(ins); r = s; while ((r = strchr_w(r, *ins))) { @@ -663,10 +662,9 @@ const smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) const smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) { const smb_ucs2_t *r; - size_t slen, inslen; + size_t inslen; if (!s || !*s || !ins || !*ins) return NULL; - slen = strlen_w(s); inslen = strlen(ins); r = s; while ((r = strchr_w(r, UCS2_CHAR(*ins)))) { diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 76eb93a9b8..25b51af6ba 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -93,7 +93,6 @@ const char *uuid_string(TALLOC_CTX *mem_ctx, const GUID in) char *out; uuid_unpack(in, &uu); - if (!out) return NULL; out = talloc_asprintf(mem_ctx, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uu.time_low, uu.time_mid, uu.time_hi_and_version, -- cgit From 039e9dc5e609f32b959b6120976e2c59534c659f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Aug 2003 20:19:30 +0000 Subject: - patch to fix a memory leak from metze - fix a couple of unicode string errors for ascii clients found by RAW- tests (This used to be commit 81c941ba8ae33567d79b4bb0bb5928f5f6077b76) --- source4/lib/util_sock.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 8362290804..95e0c5fe0c 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -486,22 +486,12 @@ char *get_socket_addr(TALLOC_CTX *mem_ctx, int fd) struct sockaddr sa; struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); int length = sizeof(sa); - char *addr_buf; - addr_buf = talloc_strdup(mem_ctx, "0.0.0.0"); - - if (fd == -1) { - return addr_buf; - } - - if (getpeername(fd, &sa, &length) < 0) { - DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) )); - return addr_buf; + if (fd == -1 || getpeername(fd, &sa, &length) == -1) { + return talloc_strdup(mem_ctx, "0.0.0.0"); } - addr_buf = talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr)); - - return addr_buf; + return talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr)); } -- cgit From 4e73a3c0feb47c761fdcded9e6c2ac6d32534d9b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Oct 2003 05:40:32 +0000 Subject: fixed snprintf.c for systems that have only some of the *printf() family of functions cope with servers that return bogus (too large) values in max_xmit cope with a couple more error conditions in RAW-SFILEINFO better startup time heuristics in NBENCH (This used to be commit 89f7261ba589e5760b3cf9c3594eab9d7198dd7e) --- source4/lib/snprintf.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c index 1eae2f09b9..fd31870162 100644 --- a/source4/lib/snprintf.c +++ b/source4/lib/snprintf.c @@ -81,6 +81,15 @@ #include #endif +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + + #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) /* only include stdio.h if we are not re-defining snprintf or vsnprintf */ #include @@ -105,14 +114,6 @@ #define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) #endif -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) __va_copy(dest, src) -#else -#define VA_COPY(dest, src) (dest) = (src) -#endif -#endif - static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, -- cgit From 062670f00c4f536e28eae9a3414239581d618774 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 13 Nov 2003 10:15:48 +0000 Subject: removed a bunch of the old rpc code in preparation for replacing it all with auto-generated code (This used to be commit 874bf4689d2816474b33eb1ac21530186319ed62) --- source4/lib/util_sid.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 9910a9d261..6436035f8e 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -629,3 +629,18 @@ void print_guid(GUID *guid) d_printf("%02x", guid->info[i]); d_printf("\n"); } + + +/******************************************************************* + Check if ACE has OBJECT type. +********************************************************************/ +BOOL sec_ace_object(uint8 type) +{ + if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { + return True; + } + return False; +} -- cgit From bcfbaa312a8493aa2b6ef76a7ebeee55625e5a9c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Nov 2003 07:51:19 +0000 Subject: run LookupDomain on each domain returned from EnumDomains in samr (This used to be commit 947b9f8ced486d34ee6710a921fb985ea14e2bb1) --- source4/lib/util_str.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index f689ae4355..b220820104 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1066,6 +1066,26 @@ void strupper_m(char *s) unix_strupper(s,strlen(s)+1,s,strlen(s)+1); } + +/** + work out the number of multibyte chars in a string +**/ +size_t strlen_m(const char *s) +{ + size_t count = 0; + + while (*s && !(((unsigned char)s[0]) & 0x7F)) { + s++; + count++; + } + + if (!*s) + return; + + push_ucs2(NULL,tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + return count + strlen_w(tmpbuf); +} + /** Convert a string to upper case. **/ -- cgit From d4dfcda78eeca4206965667a45f4f00f4e10457a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Nov 2003 10:29:54 +0000 Subject: * fixed level2 of QueryUserInfo * added per-field testing of SetUserInfo * fixed strlen_m() (This used to be commit 26238b0f8a5752bb0f611c4aa492b964e419209a) --- source4/lib/util_str.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index b220820104..285b0cc02e 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1074,13 +1074,18 @@ size_t strlen_m(const char *s) { size_t count = 0; + if (!s) { + return 0; + } + while (*s && !(((unsigned char)s[0]) & 0x7F)) { s++; count++; } - if (!*s) - return; + if (!*s) { + return count; + } push_ucs2(NULL,tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); return count + strlen_w(tmpbuf); -- cgit From d47d14f2ffc7a6d2cc306530b777f364767998b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Nov 2003 01:53:54 +0000 Subject: reduced the number of magic types we need in mkproto.pl In general I prefer "struct foo" to just "foo" for most structures. There are exceptions. (This used to be commit 04eb12b56c653f98801ab29411f47564ab32fa58) --- source4/lib/system.c | 2 +- source4/lib/util_unistr.c | 39 --------------------------------------- 2 files changed, 1 insertion(+), 40 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/system.c b/source4/lib/system.c index bafe689a30..f79386eed1 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -324,7 +324,7 @@ FILE *sys_fopen(const char *path, const char *type) A readdir wrapper that will deal with 64 bit filesizes. ********************************************************************/ -SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp) +struct smb_dirent *sys_readdir(DIR *dirp) { #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) return readdir64(dirp); diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 71a67eb159..3ab04eda1f 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -794,43 +794,4 @@ int unistrcpy(uint16 *dst, uint16 *src) return num_wchars; } -/** - * Samba ucs2 type to UNISTR2 conversion - * - * @param ctx Talloc context to create the dst strcture (if null) and the - * contents of the unicode string. - * @param dst UNISTR2 destination. If equals null, then it's allocated. - * @param src smb_ucs2_t source. - * @param max_len maximum number of unicode characters to copy. If equals - * null, then null-termination of src is taken - * - * @return copied UNISTR2 destination - **/ -UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) -{ - size_t len; - - if (!src) return NULL; - len = strlen_w(src); - - /* allocate UNISTR2 destination if not given */ - if (!dst) { - dst = (UNISTR2*) talloc(ctx, sizeof(UNISTR2)); - if (!dst) return NULL; - } - if (!dst->buffer) { - dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1)); - if (!dst->buffer) return NULL; - } - - /* set UNISTR2 parameters */ - dst->uni_max_len = len + 1; - dst->undoc = 0; - dst->uni_str_len = len; - - /* copy the actual unicode string */ - strncpy_w(dst->buffer, src, dst->uni_max_len); - - return dst; -}; -- cgit From c071301a77b1987526f42c8877336a1f6a1bfa7e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 23 Nov 2003 10:50:52 +0000 Subject: Add a strlen_m_term() function for returning the length of a string including the termination. Using value(strlen_m((r->name)+1)*2) gives the wrong answer for the NULL string. (This used to be commit 7ae329e6630a07d29f83b6dd4572d26ab8a18c71) --- source4/lib/util_str.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 285b0cc02e..6005a3e49a 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1091,6 +1091,21 @@ size_t strlen_m(const char *s) return count + strlen_w(tmpbuf); } +/** + Work out the number of multibyte chars in a string, including the NULL + terminator. +**/ +size_t strlen_m_term(const char *s) +{ + size_t count = 0; + + if (!s) { + return 0; + } + + return strlen_m(s) + 1; +} + /** Convert a string to upper case. **/ -- cgit From c32a03ad124c76000a8cd6821f731a845310e7a4 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 23 Nov 2003 11:05:31 +0000 Subject: Removed unused variable. (This used to be commit 40ccaeefed1a3baea356254795c698794cb81384) --- source4/lib/util_str.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 6005a3e49a..ace2e19be3 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1097,8 +1097,6 @@ size_t strlen_m(const char *s) **/ size_t strlen_m_term(const char *s) { - size_t count = 0; - if (!s) { return 0; } -- cgit From f4e485117a0dea627addfb8518e6517c7104fd9e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 24 Nov 2003 13:19:00 +0000 Subject: * fixed byte order in epmapper parsing * allow rpc transport to be specified on command line in smbtorture (This used to be commit 8a82050fd6f45bcdb31c2c365eaed5fc12599e4f) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 64e3dfe88c..c9c38ddd33 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -467,7 +467,7 @@ uint32 interpret_addr(const char *str) if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF); - /* if it's in the form of an IP address then get the lib to interpret it */ + /* if it's in the form of an IP address then get the lib to interpret it */ if (is_ipaddress(str)) { res = inet_addr(str); } else { -- cgit From a846e592058726b670e40505493a4668bd856186 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 25 Nov 2003 03:15:26 +0000 Subject: CVS: ---------------------------------------------------------------------- CVS: Enter Log. Lines beginning with `CVS:' are removed automatically CVS: CVS: Committing in . CVS: CVS: Modified Files: CVS: Makefile.in configure.in include/includes.h include/ntvfs.h CVS: include/smb.h lib/iconv.c lib/module.c ntvfs/ntvfs_base.c CVS: ntvfs/cifs/vfs_cifs.c ntvfs/ipc/vfs_ipc.c CVS: ntvfs/posix/vfs_posix.c ntvfs/print/vfs_print.c CVS: ntvfs/reference/vfs_ref.c ntvfs/simple/vfs_simple.c CVS: passdb/pdb_interface.c CVS: Added Files: CVS: include/module.h CVS: ---------------------------------------------------------------------- Update to the modules system. Fixed: - get rid of smb_probe_module - merge older updates from 3.0 - introduced register_subsystem() and register_backend() functions - adapt ntvfs and charset to use new register functions - made smb_load_modules() work recursively (e.g. 'preload modules = /usr/lib/samba') - got rid of some old remains Things that still need work: - Did I break tankFS? I don't think so, but I can't test it here :-( - Add 'postload modules = ' (for modules that need to be loaded after fork() in smbd, if applicable) - Convert RPC, auth, passdb, etc to use new register_{subsystem,backend}() functions - Accept wildcards in 'preload modules' option, instead of loading recursively (This used to be commit 7512b9ab1a8b3103f7a6c13f736353c46a26b668) --- source4/lib/iconv.c | 11 ++++-- source4/lib/module.c | 110 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 74 insertions(+), 47 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 8f85e29c2e..2a0b013257 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -63,8 +63,9 @@ static struct charset_functions builtin_functions[] = { static struct charset_functions *charsets = NULL; -BOOL smb_register_charset(struct charset_functions *funcs) +static NTSTATUS charset_register_backend(void *_funcs) { + struct charset_functions *funcs = (struct charset_functions *)_funcs; struct charset_functions *c = charsets; DEBUG(5, ("Attempting to register new charset %s\n", funcs->name)); @@ -72,7 +73,7 @@ BOOL smb_register_charset(struct charset_functions *funcs) while(c) { if(!strcasecmp(c->name, funcs->name)){ DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); - return False; + return NT_STATUS_OBJECT_NAME_COLLISION; } c = c->next; } @@ -80,7 +81,7 @@ BOOL smb_register_charset(struct charset_functions *funcs) funcs->next = funcs->prev = NULL; DEBUG(5, ("Registered charset %s\n", funcs->name)); DLIST_ADD(charsets, funcs); - return True; + return NT_STATUS_OK; } static void lazy_initialize_iconv(void) @@ -90,8 +91,10 @@ static void lazy_initialize_iconv(void) if (!initialized) { initialized = True; + register_subsystem("charset", charset_register_backend); + for(i = 0; builtin_functions[i].name; i++) - smb_register_charset(&builtin_functions[i]); + register_backend("charset", &builtin_functions[i]); } } diff --git a/source4/lib/module.c b/source4/lib/module.c index 152e893100..d45f99473e 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. module loading system - Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Jelmer Vernooij 2002-2003 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 @@ -22,12 +22,32 @@ #include "includes.h" #ifdef HAVE_DLOPEN -int smb_load_module(const char *module_name) + +/* Load module (or directory with modules) recursively. + * Includes running the init_module() function */ +NTSTATUS smb_load_module(const char *module_name) { void *handle; - init_module_function *init; - int status; + init_module_function init; + NTSTATUS status; const char *error; + struct stat st; + DIR *dir; + struct dirent *dirent; + + stat(module_name, &st); + + /* If the argument is a directory, recursively load all files / + * directories in it */ + + /* How about symlinks pointing to themselves - wouldn't we rather + * want to use wildcards here? */ + if(S_ISDIR(st.st_mode)) { + dir = opendir(module_name); + while(dirent = readdir(dir)) { + smb_load_module(dirent->d_name); + } + } /* Always try to use LAZY symbol resolving; if the plugin has * backwards compatibility, there might be symbols in the @@ -37,17 +57,17 @@ int smb_load_module(const char *module_name) if(!handle) { DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); - return False; + return NT_STATUS_UNSUCCESSFUL; } - init = sys_dlsym(handle, "init_module"); + init = (init_module_function)sys_dlsym(handle, "init_module"); /* we must check sys_dlerror() to determine if it worked, because sys_dlsym() can validly return NULL */ error = sys_dlerror(); if (error) { DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error)); - return False; + return NT_STATUS_UNSUCCESSFUL; } status = init(); @@ -65,7 +85,7 @@ int smb_load_modules(const char **modules) int success = 0; for(i = 0; modules[i]; i++){ - if(smb_load_module(modules[i])) { + if(NT_STATUS_IS_OK(smb_load_module(modules[i]))) { success++; } } @@ -75,47 +95,18 @@ int smb_load_modules(const char **modules) return success; } -int smb_probe_module(const char *subsystem, const char *module) -{ - char *full_path; - int rc; - TALLOC_CTX *mem_ctx; - - /* Check for absolute path */ - if(module[0] == '/')return smb_load_module(module); - - mem_ctx = talloc_init("smb_probe_module"); - if (!mem_ctx) { - DEBUG(0,("No memory for loading modules\n")); - return False; - } - full_path = talloc_strdup(mem_ctx, lib_path(mem_ctx, subsystem)); - full_path = talloc_asprintf(mem_ctx, "%s/%s.%s", - full_path, module, shlib_ext()); - - rc = smb_load_module(full_path); - talloc_destroy(mem_ctx); - return rc; -} - #else /* HAVE_DLOPEN */ -int smb_load_module(const char *module_name) +NTSTATUS smb_load_module(const char *module_name) { - DEBUG(0,("This samba executable has not been built with plugin support")); - return False; + DEBUG(0,("This samba executable has not been built with plugin support\n")); + return NT_STATUS_NOT_SUPPORTED; } int smb_load_modules(const char **modules) { - DEBUG(0,("This samba executable has not been built with plugin support")); - return False; -} - -int smb_probe_module(const char *subsystem, const char *module) -{ - DEBUG(0,("This samba executable has not been built with plugin support, not probing")); - return False; + DEBUG(0,("This samba executable has not been built with plugin support\n")); + return -1; } #endif /* HAVE_DLOPEN */ @@ -124,5 +115,38 @@ void init_modules(void) { if(lp_preload_modules()) smb_load_modules(lp_preload_modules()); - /* FIXME: load static modules */ +} + +struct subsystem { + char *name; + register_backend_function callback; + struct subsystem *prev, *next; +}; + +struct subsystem *subsystems = NULL; + +void register_subsystem(const char *name, register_backend_function callback) +{ + struct subsystem *s; + + s = smb_xmalloc(sizeof(struct subsystem)); + + s->name = smb_xstrdup(name); + s->callback = callback; + s->prev = s->next = NULL; + + DLIST_ADD(subsystems, s); +} + +NTSTATUS register_backend(const char *subsystem, void *args) +{ + /* Find the specified subsystem */ + struct subsystem *s = subsystems; + + while(s) { + if(!strcmp(subsystem, s->name)) return s->callback(args); + s = s->next; + } + + return NT_STATUS_NOT_IMPLEMENTED; } -- cgit From e0ac659917066dbf7f8fdbcc7684ce2b49dd04d9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 26 Nov 2003 01:16:41 +0000 Subject: signed DCERPC over TCP now works ! * moved ntlmssp code into libcli/auth/, and updated to latest ntlmssp code from samba3 (thanks Andrew! the new interface is great) * added signing/ntlmssp support in the dcerpc code * added a dcerpc_auth.c module for the various dcerpc auth mechanisms (This used to be commit c18c9b5585a3e5f7868562820c14f7cb529cdbcd) --- source4/lib/crc32.c | 122 ++++++++++++++++++++++----------------------- source4/lib/crypto/crc32.c | 122 ++++++++++++++++++++++----------------------- source4/lib/data_blob.c | 2 + source4/lib/replace.c | 5 ++ source4/lib/util.c | 11 ++++ 5 files changed, 136 insertions(+), 126 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crc32.c b/source4/lib/crc32.c index 86b0bb6fd9..da3aeaa901 100644 --- a/source4/lib/crc32.c +++ b/source4/lib/crc32.c @@ -1,71 +1,67 @@ /* - Unix SMB/CIFS implementation. - crc32 implementation - Copyright (C) Andrew Tridgell 2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ + * Copyright Francesco Ferrara, 1998 + * + * Used by kind permission, 14th October 1998. http://www.aerre.it/francesco + * + * + */ #include "includes.h" -/* table generated using algorithm from Mark Adler */ -static const uint32 crc_table[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +static const unsigned long CRCTable[256] = +{ + 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F, + 0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988, + 0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2, + 0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, + 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9, + 0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172, + 0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C, + 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, + 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423, + 0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924, + 0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106, + 0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, + 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D, + 0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E, + 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950, + 0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, + 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7, + 0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0, + 0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA, + 0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, + 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81, + 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A, + 0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84, + 0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, + 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB, + 0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC, + 0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E, + 0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, + 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55, + 0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236, + 0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28, + 0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, + 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F, + 0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38, + 0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242, + 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, + 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69, + 0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2, + 0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC, + 0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, + 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693, + 0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94, + 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; - -/* - see PNG specification or ISO-3309 for details -*/ -uint32 crc32_buffer(const uint8 *buf, int n) +uint32 crc32_calc_buffer( const char *buffer, uint32 count) { - int i; - uint32 ret; - for (ret=~0, i=0;i> 8); - } - return ~ret; + uint32 crc=0xffffffff, i; + for(i=0;i>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff]; + crc^=0xffffffff; + DEBUG(10,("crc32_calc_buffer: %x\n", crc)); + dump_data(100, buffer, count); + return crc; } diff --git a/source4/lib/crypto/crc32.c b/source4/lib/crypto/crc32.c index 86b0bb6fd9..da3aeaa901 100644 --- a/source4/lib/crypto/crc32.c +++ b/source4/lib/crypto/crc32.c @@ -1,71 +1,67 @@ /* - Unix SMB/CIFS implementation. - crc32 implementation - Copyright (C) Andrew Tridgell 2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ + * Copyright Francesco Ferrara, 1998 + * + * Used by kind permission, 14th October 1998. http://www.aerre.it/francesco + * + * + */ #include "includes.h" -/* table generated using algorithm from Mark Adler */ -static const uint32 crc_table[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +static const unsigned long CRCTable[256] = +{ + 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F, + 0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988, + 0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2, + 0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, + 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9, + 0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172, + 0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C, + 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, + 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423, + 0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924, + 0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106, + 0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, + 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D, + 0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E, + 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950, + 0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, + 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7, + 0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0, + 0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA, + 0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, + 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81, + 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A, + 0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84, + 0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, + 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB, + 0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC, + 0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E, + 0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, + 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55, + 0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236, + 0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28, + 0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, + 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F, + 0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38, + 0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242, + 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, + 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69, + 0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2, + 0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC, + 0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, + 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693, + 0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94, + 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; - -/* - see PNG specification or ISO-3309 for details -*/ -uint32 crc32_buffer(const uint8 *buf, int n) +uint32 crc32_calc_buffer( const char *buffer, uint32 count) { - int i; - uint32 ret; - for (ret=~0, i=0;i> 8); - } - return ~ret; + uint32 crc=0xffffffff, i; + for(i=0;i>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff]; + crc^=0xffffffff; + DEBUG(10,("crc32_calc_buffer: %x\n", crc)); + dump_data(100, buffer, count); + return crc; } diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 8e7df52bef..d51cffbca4 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -91,6 +91,8 @@ free a data blob *******************************************************************/ void data_blob_free(DATA_BLOB *d) { + return; + if (d) { if (d->free) { (d->free)(d); diff --git a/source4/lib/replace.c b/source4/lib/replace.c index cda379c63f..63e6a71149 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -465,3 +465,8 @@ char *rep_inet_ntoa(struct in_addr ip) return ret; } #endif + +const char *global_myname(void) +{ + return lp_netbios_name(); +} diff --git a/source4/lib/util.c b/source4/lib/util.c index c9c38ddd33..9b6cef8bfe 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -998,3 +998,14 @@ static BOOL unix_do_match(char *regexp, char *str) return False; } + +void dump_data_pw(const char *msg, const uchar * data, size_t len) +{ +#ifdef DEBUG_PASSWORD + DEBUG(11, ("%s", msg)); + if (data != NULL && len > 0) + { + dump_data(11, data, len); + } +#endif +} -- cgit From c123c8454142d17d2884ae9dd951b7f2a0b1a343 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 26 Nov 2003 02:08:41 +0000 Subject: fixed some memory leaks in the dcerpc use of ntlmssp signing (This used to be commit abbc9993b8f7eb9f57e079db1d0b170d0b9aa443) --- source4/lib/data_blob.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index d51cffbca4..933617e9ee 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -73,6 +73,7 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) } ret.length = length; memset(ret.data, 0, ret.length); + ret.free = NULL; return ret; } @@ -91,8 +92,6 @@ free a data blob *******************************************************************/ void data_blob_free(DATA_BLOB *d) { - return; - if (d) { if (d->free) { (d->free)(d); @@ -124,7 +123,7 @@ void data_blob_clear_free(DATA_BLOB *d) /******************************************************************* check if two data blobs are equal *******************************************************************/ -BOOL data_blob_equal(DATA_BLOB *d1, DATA_BLOB *d2) +BOOL data_blob_equal(const DATA_BLOB *d1, const DATA_BLOB *d2) { if (d1->length != d2->length) { return False; -- cgit From 0b1b3850a084be52fcb2abc5985cf6b06e7a54fa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 27 Nov 2003 04:00:21 +0000 Subject: added -m for 'max protocol' as a standard option (This used to be commit 8fe4058711c12b8116982357723c36e862aa0bef) --- source4/lib/cmdline/popt_common.c | 5 +++++ source4/lib/popt_common.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index ccdecc91cc..8a6cce7e5b 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -94,6 +94,10 @@ static void popt_common_callback(poptContext con, case 'i': lp_set_cmdline("netbios scope", arg); break; + + case 'm': + lp_set_cmdline("max protocol", arg); + break; } } @@ -104,6 +108,7 @@ struct poptOption popt_common_connection[] = { { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + { "maxprotocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set max protocol level", "MAXPROTOCOL" }, POPT_TABLEEND }; diff --git a/source4/lib/popt_common.c b/source4/lib/popt_common.c index ccdecc91cc..8a6cce7e5b 100644 --- a/source4/lib/popt_common.c +++ b/source4/lib/popt_common.c @@ -94,6 +94,10 @@ static void popt_common_callback(poptContext con, case 'i': lp_set_cmdline("netbios scope", arg); break; + + case 'm': + lp_set_cmdline("max protocol", arg); + break; } } @@ -104,6 +108,7 @@ struct poptOption popt_common_connection[] = { { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + { "maxprotocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set max protocol level", "MAXPROTOCOL" }, POPT_TABLEEND }; -- cgit From f83f0cb0605368387358782179460ca4d75a9541 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Nov 2003 09:05:44 +0000 Subject: fixed some warnings (This used to be commit 1c2b8a93c50e3d5485732a2f06847166e883f939) --- source4/lib/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index d45f99473e..c6c4ef6979 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -44,7 +44,7 @@ NTSTATUS smb_load_module(const char *module_name) * want to use wildcards here? */ if(S_ISDIR(st.st_mode)) { dir = opendir(module_name); - while(dirent = readdir(dir)) { + while ((dirent = readdir(dir))) { smb_load_module(dirent->d_name); } } -- cgit From fa062af11ada2cf1c58465447ea711ec4b9b3a12 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Nov 2003 23:40:04 +0000 Subject: * removed a bunch of unused code * made some functions static (This used to be commit 829b87f30d5f4cc7174b716f3354982d84af4818) --- source4/lib/system.c | 171 -------------------- source4/lib/util_unistr.c | 390 ++-------------------------------------------- source4/lib/util_uuid.c | 31 ---- 3 files changed, 11 insertions(+), 581 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/system.c b/source4/lib/system.c index f79386eed1..98d975aa50 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -699,177 +699,6 @@ struct group *sys_getgrgid(gid_t gid) return getgrgid(gid); } -#if 0 /* NOT CURRENTLY USED - JRA */ -/************************************************************************** - The following are the UNICODE versions of *all* system interface functions - called within Samba. Ok, ok, the exceptions are the gethostbyXX calls, - which currently are left as ascii as they are not used other than in name - resolution. -****************************************************************************/ - -/************************************************************************** - Wide stat. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf) -{ - pstring fname; - return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf); -} - -/************************************************************************** - Wide lstat. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf) -{ - pstring fname; - return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf); -} - -/************************************************************************** - Wide creat. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_creat(const smb_ucs2_t *wfname, mode_t mode) -{ - pstring fname; - return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode); -} - -/************************************************************************** - Wide open. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode) -{ - pstring fname; - return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode); -} - -/************************************************************************** - Wide fopen. Just narrow and call sys_xxx. -****************************************************************************/ - -FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type) -{ - pstring fname; - return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type); -} - -/************************************************************************** - Wide opendir. Just narrow and call sys_xxx. -****************************************************************************/ - -DIR *wsys_opendir(const smb_ucs2_t *wfname) -{ - pstring fname; - return opendir(unicode_to_unix(fname,wfname,sizeof(fname))); -} - -/************************************************************************** - Wide readdir. Return a structure pointer containing a wide filename. -****************************************************************************/ - -SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp) -{ - static SMB_STRUCT_WDIRENT retval; - SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp); - - if(!dirval) - return NULL; - - /* - * The only POSIX defined member of this struct is d_name. - */ - - unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name)); - - return &retval; -} - -/************************************************************************** - Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring. -****************************************************************************/ - -smb_ucs2_t *wsys_getwd(smb_ucs2_t *s) -{ - pstring fname; - char *p = sys_getwd(fname); - - if(!p) - return NULL; - - return unix_to_unicode(s, p, sizeof(wpstring)); -} - -/************************************************************************** - Wide chown. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid) -{ - pstring fname; - return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid); -} - -/************************************************************************** - Wide chroot. Just narrow and call sys_xxx. -****************************************************************************/ - -int wsys_chroot(const smb_ucs2_t *wfname) -{ - pstring fname; - return chroot(unicode_to_unix(fname,wfname,sizeof(fname))); -} - -/************************************************************************** - Wide getpwnam. Return a structure pointer containing wide names. -****************************************************************************/ - -SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname) -{ - static SMB_STRUCT_WPASSWD retval; - fstring name; - struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name))); - - if(!pwret) - return NULL; - - unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name)); - retval.pw_passwd = pwret->pw_passwd; - retval.pw_uid = pwret->pw_uid; - retval.pw_gid = pwret->pw_gid; - unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); - unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); - unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); - - return &retval; -} - -/************************************************************************** - Wide getpwuid. Return a structure pointer containing wide names. -****************************************************************************/ - -SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid) -{ - static SMB_STRUCT_WPASSWD retval; - struct passwd *pwret = sys_getpwuid(uid); - - if(!pwret) - return NULL; - - unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name)); - retval.pw_passwd = pwret->pw_passwd; - retval.pw_uid = pwret->pw_uid; - retval.pw_gid = pwret->pw_gid; - unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); - unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); - unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); - - return &retval; -} -#endif /* NOT CURRENTLY USED - JRA */ /************************************************************************** Extract a command into an arg list. Uses a static pstring for storage. diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 3ab04eda1f..3e3430d147 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -21,10 +21,6 @@ #include "includes.h" -#ifndef MAXUNI -#define MAXUNI 1024 -#endif - /* these 3 tables define the unicode case handling. They are loaded at startup either via mmap() or read() from the lib directory */ static smb_ucs2_t *upcase_table; @@ -162,74 +158,10 @@ void init_valid_table(void) } - -/******************************************************************* - Write a string in (little-endian) unicode format. src is in - the current DOS codepage. len is the length in bytes of the - string pointed to by dst. - - if null_terminate is True then null terminate the packet (adds 2 bytes) - - the return value is the length in bytes consumed by the string, including the - null termination if applied -********************************************************************/ - -size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate) -{ - return push_ucs2(NULL, dst, src, len, - STR_UNICODE|STR_NOALIGN | (null_terminate?STR_TERMINATE:0)); -} - - -/******************************************************************* - Skip past a unicode string, but not more than len. Always move - past a terminating zero if found. -********************************************************************/ - -char *skip_unibuf(char *src, size_t len) -{ - char *srcend = src + len; - - while (src < srcend && SVAL(src,0)) - src += 2; - - if(!SVAL(src,0)) - src += 2; - - return src; -} - -/* Copy a string from little-endian or big-endian unicode source (depending - * on flags) to internal samba format destination - */ -int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags) -{ - if (!src) return 0; - if(dest_len==-1) dest_len=MAXUNI-3; - return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN); -} - -/* Copy a string from a unistr2 source to internal samba format - destination. Use this instead of direct calls to rpcstr_pull() to avoid - having to determine whether the source string is null terminated. */ - -int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src) -{ - return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring), - src->uni_str_len * 2, 0); -} - -/* Converts a string from internal samba format to unicode - */ -int rpcstr_push(void* dest, const char *src, int dest_len, int flags) -{ - return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN); -} - /******************************************************************* Convert a (little-endian) UNISTR2 structure to an ASCII string ********************************************************************/ -void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) +static void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) { if (str == NULL) { *dest='\0'; @@ -266,23 +198,11 @@ char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str) } -/******************************************************************* -Return a number stored in a buffer -********************************************************************/ - -uint32 buffer2_to_uint32(BUFFER2 *str) -{ - if (str->buf_len == 4) - return IVAL(str->buffer, 0); - else - return 0; -} - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ -smb_ucs2_t toupper_w(smb_ucs2_t val) +static smb_ucs2_t toupper_w(smb_ucs2_t val) { return upcase_table[SVAL(&val,0)]; } @@ -291,7 +211,7 @@ smb_ucs2_t toupper_w(smb_ucs2_t val) Convert a wchar to lower case. ********************************************************************/ -smb_ucs2_t tolower_w( smb_ucs2_t val ) +static smb_ucs2_t tolower_w( smb_ucs2_t val ) { return lowcase_table[SVAL(&val,0)]; @@ -314,14 +234,6 @@ BOOL isupper_w(smb_ucs2_t c) } -/******************************************************************* -determine if a character is valid in a 8.3 name -********************************************************************/ -BOOL isvalid83_w(smb_ucs2_t c) -{ - return valid_table[SVAL(&c,0)] != 0; -} - /******************************************************************* Count the number of characters in a smb_ucs2_t string. ********************************************************************/ @@ -377,6 +289,14 @@ const smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) return NULL; } +static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) +{ + size_t n = 0; + while ((n < len) && *b && *a == *b) { a++; b++; n++;} + return (len - n)?(*a - *b):0; +} + + /******************************************************************* wide strstr() ********************************************************************/ @@ -431,22 +351,6 @@ BOOL strupper_w(smb_ucs2_t *s) return ret; } -int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) -{ - while (*b && *a == *b) { a++; b++; } - return (*a - *b); - /* warning: if *a != *b and both are not 0 we retrun a random - greater or lesser than 0 number not realted to which - string is longer */ -} - -int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) -{ - size_t n = 0; - while ((n < len) && *b && *a == *b) { a++; b++; n++;} - return (len - n)?(*a - *b):0; -} - /******************************************************************* case insensitive string comparison ********************************************************************/ @@ -456,64 +360,6 @@ int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) return (tolower_w(*a) - tolower_w(*b)); } -/******************************************************************* -case insensitive string comparison, lenght limited -********************************************************************/ -int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) -{ - size_t n = 0; - while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; } - return (len - n)?(tolower_w(*a) - tolower_w(*b)):0; -} - -/******************************************************************* - compare 2 strings -********************************************************************/ -BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2) -{ - if (s1 == s2) return(True); - if (!s1 || !s2) return(False); - - return(strcasecmp_w(s1,s2)==0); -} - -/******************************************************************* - compare 2 strings up to and including the nth char. - ******************************************************************/ -BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n) -{ - if (s1 == s2) return(True); - if (!s1 || !s2 || !n) return(False); - - return(strncasecmp_w(s1,s2,n)==0); -} - -/******************************************************************* -duplicate string -********************************************************************/ -smb_ucs2_t *strdup_w(const smb_ucs2_t *src) -{ - return strndup_w(src, 0); -} - -/* if len == 0 then duplicate the whole string */ -smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len) -{ - smb_ucs2_t *dest; - - if (!len) len = strlen_w(src); - dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t)); - if (!dest) { - DEBUG(0,("strdup_w: out of memory!\n")); - return NULL; - } - - memcpy(dest, src, len * sizeof(smb_ucs2_t)); - dest[len] = 0; - - return dest; -} - /******************************************************************* copy a string with max len ********************************************************************/ @@ -533,43 +379,6 @@ smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) } -/******************************************************************* -append a string of len bytes and add a terminator -********************************************************************/ - -smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) -{ - size_t start; - size_t len; - - if (!dest || !src) return NULL; - - start = strlen_w(dest); - len = strnlen_w(src, max); - - memcpy(&dest[start], src, len*sizeof(smb_ucs2_t)); - dest[start+len] = 0; - - return dest; -} - -smb_ucs2_t *strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src) -{ - size_t start; - size_t len; - - if (!dest || !src) return NULL; - - start = strlen_w(dest); - len = strlen_w(src); - - memcpy(&dest[start], src, len*sizeof(smb_ucs2_t)); - dest[start+len] = 0; - - return dest; -} - - /******************************************************************* replace any occurence of oldc with newc in unicode string ********************************************************************/ @@ -581,40 +390,6 @@ void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc) } } -/******************************************************************* -trim unicode string -********************************************************************/ - -BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front, - const smb_ucs2_t *back) -{ - BOOL ret = False; - size_t len, front_len, back_len; - - if (!s || !*s) return False; - - len = strlen_w(s); - - if (front && *front) { - front_len = strlen_w(front); - while (len && strncmp_w(s, front, front_len) == 0) { - memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t)); - len -= front_len; - ret = True; - } - } - - if (back && *back) { - back_len = strlen_w(back); - while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) { - s[len - back_len] = 0; - len -= back_len; - ret = True; - } - } - - return ret; -} /* The *_wa() functions take a combination of 7 bit ascii @@ -640,13 +415,6 @@ int strcmp_wa(const smb_ucs2_t *a, const char *b) return (*a - UCS2_CHAR(*b)); } -int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len) -{ - size_t n = 0; - while ((n < len) && *b && *a == UCS2_CHAR(*b)) { a++; b++; n++;} - return (len - n)?(*a - UCS2_CHAR(*b)):0; -} - const smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) { while (*s != 0) { @@ -659,139 +427,3 @@ const smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) return NULL; } -const smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) -{ - const smb_ucs2_t *r; - size_t inslen; - - if (!s || !*s || !ins || !*ins) return NULL; - inslen = strlen(ins); - r = s; - while ((r = strchr_w(r, UCS2_CHAR(*ins)))) { - if (strncmp_wa(r, ins, inslen) == 0) return r; - r++; - } - return NULL; -} - -/******************************************************************* -copy a string with max len -********************************************************************/ - -smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncpy_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -/******************************************************************* -convert and duplicate an ascii string -********************************************************************/ -smb_ucs2_t *strdup_wa(const char *src) -{ - return strndup_wa(src, 0); -} - -/* if len == 0 then duplicate the whole string */ -smb_ucs2_t *strndup_wa(const char *src, size_t len) -{ - smb_ucs2_t *dest, *s; - - s = acnv_dosu2(src); - if (!len) len = strlen_w(s); - dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t)); - if (!dest) { - DEBUG(0,("strdup_w: out of memory!\n")); - SAFE_FREE(s); - return NULL; - } - - memcpy(dest, src, len * sizeof(smb_ucs2_t)); - dest[len] = 0; - - SAFE_FREE(s); - return dest; -} - -/******************************************************************* -append a string of len bytes and add a terminator -********************************************************************/ - -smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncat_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -smb_ucs2_t *strcat_wa(smb_ucs2_t *dest, const char *src) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strcat_w(dest, ucs2_src); - SAFE_FREE(ucs2_src); - return dest; -} - -BOOL trim_string_wa(smb_ucs2_t *s, const char *front, - const char *back) -{ - wpstring f, b; - - if (front) push_ucs2(NULL, f, front, sizeof(wpstring) - 1, STR_TERMINATE); - else *f = 0; - if (back) push_ucs2(NULL, b, back, sizeof(wpstring) - 1, STR_TERMINATE); - else *b = 0; - return trim_string_w(s, f, b); -} - -/******************************************************************* - returns the length in number of wide characters - ******************************************************************/ -int unistrlen(uint16 *s) -{ - int len; - - if (!s) - return -1; - - for (len=0; *s; s++,len++); - - return len; -} - -/******************************************************************* - Strcpy for unicode strings. returns length (in num of wide chars) -********************************************************************/ - -int unistrcpy(uint16 *dst, uint16 *src) -{ - int num_wchars = 0; - - while (*src) { - *dst++ = *src++; - num_wchars++; - } - *dst = 0; - - return num_wchars; -} - - diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 25b51af6ba..1b8c7572c7 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -70,34 +70,3 @@ void uuid_generate_random(GUID *out) uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; uuid_pack(&uu, out); } - -char *guid_to_string(const GUID in) -{ - struct uuid uu; - char *out; - - uuid_unpack(in, &uu); - - asprintf(&out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uu.time_low, uu.time_mid, uu.time_hi_and_version, - uu.clock_seq[0], uu.clock_seq[1], - uu.node[0], uu.node[1], uu.node[2], - uu.node[3], uu.node[4], uu.node[5]); - - return out; -} - -const char *uuid_string(TALLOC_CTX *mem_ctx, const GUID in) -{ - struct uuid uu; - char *out; - - uuid_unpack(in, &uu); - out = talloc_asprintf(mem_ctx, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uu.time_low, uu.time_mid, uu.time_hi_and_version, - uu.clock_seq[0], uu.clock_seq[1], - uu.node[0], uu.node[1], uu.node[2], - uu.node[3], uu.node[4], uu.node[5]); - return out; -} -- cgit From 7602aa50fd591e63393def79d55302a22e77c387 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Dec 2003 00:17:30 +0000 Subject: * got rid of UNISTR2 and everything that depends on it * removed a bunch of code that needs to be rewritten using the new interfaces (This used to be commit 9b02b486ef5906516f8cad79dbff5e3dd54cde66) --- source4/lib/util_unistr.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 3e3430d147..5e48d716b9 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -158,46 +158,6 @@ void init_valid_table(void) } -/******************************************************************* - Convert a (little-endian) UNISTR2 structure to an ASCII string -********************************************************************/ -static void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen) -{ - if (str == NULL) { - *dest='\0'; - return; - } - pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN); -} - -/******************************************************************* -give a static string for displaying a UNISTR2 -********************************************************************/ -const char *unistr2_static(TALLOC_CTX *mem_ctx, const UNISTR2 *str) -{ - pstring ret; - unistr2_to_ascii(ret, str, sizeof(ret)); - return talloc_strdup(mem_ctx, ret); -} - - -/******************************************************************* - duplicate a UNISTR2 string into a null terminated char* - using a talloc context -********************************************************************/ -char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str) -{ - char *s; - int maxlen = (str->uni_str_len+1)*4; - if (!str->buffer) return NULL; - s = (char *)talloc(ctx, maxlen); /* convervative */ - if (!s) return NULL; - pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, - STR_NOALIGN); - return s; -} - - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ -- cgit From 47702c85524afceba520cc3c2d2bc0d9a4e02e40 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 2 Dec 2003 11:10:56 +0000 Subject: Initial step at cleaning and splitting up configure.in. (This used to be commit 369a9c1ac1ff94a1d3f51eac20a39577f9cf2155) --- source4/lib/popt/config.m4 | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 source4/lib/popt/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 new file mode 100644 index 0000000000..7532c5826e --- /dev/null +++ b/source4/lib/popt/config.m4 @@ -0,0 +1,31 @@ +################################################# +# Check to see if we should use the included popt + +AC_ARG_WITH(included-popt, +[ --with-included-popt use bundled popt library, not from system], +[ + case "$withval" in + yes) + INCLUDED_POPT=yes + ;; + no) + INCLUDED_POPT=no + ;; + esac ], +) +if test x"$INCLUDED_POPT" != x"yes"; then + AC_CHECK_LIB(popt, poptGetContext, + INCLUDED_POPT=no, INCLUDED_POPT=yes) +fi + +AC_MSG_CHECKING(whether to use included popt) +if test x"$INCLUDED_POPT" = x"yes"; then + AC_MSG_RESULT(yes) + BUILD_POPT='$(POPT_OBJS)' + FLAGS1="-I$srcdir/popt" +else + AC_MSG_RESULT(no) + LIBS="$LIBS -lpopt" +fi +AC_SUBST(BUILD_POPT) +AC_SUBST(FLAGS1) -- cgit From 0e958fbe47582c0c460f4cccff6d101761ca3d26 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Dec 2003 01:18:34 +0000 Subject: don't use c++ style comments (This used to be commit b11a19cc767e20189710d7d9428168ed74c59d1c) --- source4/lib/username.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/username.c b/source4/lib/username.c index c00ac666d4..084d7e0bdb 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -185,10 +185,10 @@ struct passwd *Get_Pwnam(const char *user) static BOOL user_in_netgroup_list(const char *user, const char *ngname) { #ifdef HAVE_NETGROUP - //static char *mydomain = NULL; + /* static char *mydomain = NULL; */ /* REWRITE: make thread safe if caching */ char *mydomain = NULL; - //if (mydomain == NULL) + /*if (mydomain == NULL) */ yp_get_default_domain(&mydomain); if(mydomain == NULL) { -- cgit From b8cbd9181efabbc360ef335e214a696011839b41 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Dec 2003 01:59:24 +0000 Subject: don't use c++ comments (This used to be commit 3d48fa8f37a510959c8958b5c025c7f19f632c54) --- source4/lib/cmdline/popt_common.c | 6 ++++-- source4/lib/popt_common.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 8a6cce7e5b..3c9a5eb231 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -236,8 +236,10 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) } else if (strwicmp("username", param) == 0) pstrcpy(info->username, val); - //else if (strwicmp("domain", param) == 0) - // set_global_myworkgroup(val); +#if 0 + else if (strwicmp("domain", param) == 0) + set_global_myworkgroup(val); +#endif memset(buf, 0, sizeof(buf)); } x_fclose(auth); diff --git a/source4/lib/popt_common.c b/source4/lib/popt_common.c index 8a6cce7e5b..3c9a5eb231 100644 --- a/source4/lib/popt_common.c +++ b/source4/lib/popt_common.c @@ -236,8 +236,10 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) } else if (strwicmp("username", param) == 0) pstrcpy(info->username, val); - //else if (strwicmp("domain", param) == 0) - // set_global_myworkgroup(val); +#if 0 + else if (strwicmp("domain", param) == 0) + set_global_myworkgroup(val); +#endif memset(buf, 0, sizeof(buf)); } x_fclose(auth); -- cgit From 2e5ae6f0650962db86fcdb1290f9a7c8b07b1410 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Dec 2003 09:52:14 +0000 Subject: * added a debug thread id hook from jim myers * change to select() from sys_select() in events.c, as sys_select() is not thread safe. We need a new unified signal handling scheme for Samba4, but for now just use select() (This used to be commit 126fcd4a76ac029ee4f662ed41b84c791406c324) --- source4/lib/debug.c | 8 ++++++++ source4/lib/events.c | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/debug.c b/source4/lib/debug.c index 792cf14c5a..dbd3946c81 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -57,6 +57,8 @@ void do_debug(const char *format, ...) vasprintf(&s, format, ap); va_end(ap); + log_task_id(); + write(state.fd, s, strlen(s)); free(s); } @@ -147,6 +149,12 @@ uint32 get_task_id(void) return getpid(); } +void log_task_id(void) +{ + if (debug_handlers.ops.log_task_id) { + debug_handlers.ops.log_task_id(state.fd); + } +} /* register a set of debug handlers. */ diff --git a/source4/lib/events.c b/source4/lib/events.c index f95028b731..00d32043f7 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -317,7 +317,13 @@ int event_loop_wait(struct event_context *ev) } - selrtn = sys_select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + /* TODO: + + we don't use sys_select() as it isn't thread + safe. We need to replace the magic pipe handling in + sys_select() with something in the events + structure - for now just use select() */ + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); t = time(NULL); -- cgit From 3c76426f2e343df2194825ae2e0ef84f4ad4c6ac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 Dec 2003 03:02:12 +0000 Subject: * removed some unused code * updated tdb to latest version from Samba3 * removed some extraneous ';' in tdbutil.c (Thanks to Erlend Aasland for pointing this out) (This used to be commit f3eaf270e57d8d2e2157a6a36e260860c7f71c19) --- source4/lib/tdb/spinlock.c | 2 +- source4/lib/tdb/spinlock.h | 6 ++- source4/lib/tdb/tdb.c | 91 ++++++++++++++++++++++++--------- source4/lib/tdb/tdbutil.c | 124 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 174 insertions(+), 49 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c index 2370ce3bdd..3fddeafb2c 100644 --- a/source4/lib/tdb/spinlock.c +++ b/source4/lib/tdb/spinlock.c @@ -372,7 +372,7 @@ int tdb_create_rwlocks(int fd, unsigned int hash_size) unsigned size, i; tdb_rwlock_t *rwlocks; - size = (hash_size + 1) * sizeof(tdb_rwlock_t); + size = TDB_SPINLOCK_SIZE(hash_size); rwlocks = malloc(size); if (!rwlocks) return -1; diff --git a/source4/lib/tdb/spinlock.h b/source4/lib/tdb/spinlock.h index d6a2ac6eb8..967fe37457 100644 --- a/source4/lib/tdb/spinlock.h +++ b/source4/lib/tdb/spinlock.h @@ -1,7 +1,7 @@ #ifndef __SPINLOCK_H__ #define __SPINLOCK_H__ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H #include #endif @@ -39,6 +39,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_create_rwlocks(int fd, unsigned int hash_size); int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) + #else /* !USE_SPINLOCKS */ #if 0 #define tdb_create_rwlocks(fd, hash_size) 0 @@ -50,6 +52,8 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_create_rwlocks(int fd, unsigned int hash_size); #endif int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#define TDB_SPINLOCK_SIZE(hash_size) 0 + #endif #endif diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 513fbce519..fc210f42d4 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -20,6 +20,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +/* NOTE: If you use tdbs under valgrind, and in particular if you run + * tdbtorture, you may get spurious "uninitialized value" warnings. I + * think this is because valgrind doesn't understand that the mmap'd + * area may be written to by other processes. Memory can, from the + * point of view of the grinded process, spontaneously become + * initialized. + * + * I can think of a few solutions. [mbp 20030311] + * + * 1 - Write suppressions for Valgrind so that it doesn't complain + * about this. Probably the most reasonable but people need to + * remember to use them. + * + * 2 - Use IO not mmap when running under valgrind. Not so nice. + * + * 3 - Use the special valgrind macros to mark memory as valid at the + * right time. Probably too hard -- the process just doesn't know. + */ + #ifdef STANDALONE #if HAVE_CONFIG_H #include @@ -56,6 +77,8 @@ #define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) #define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) #define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) +#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) + /* NB assumes there is a local variable called "tdb" that is the * current context, also takes doubly-parenthesized print-style @@ -214,10 +237,15 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, tdb->fd, offset, rw_type, lck_type)); } /* Was it an alarm timeout ? */ - if (errno == EINTR && palarm_fired && *palarm_fired) + if (errno == EINTR && palarm_fired && *palarm_fired) { + TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); + } /* Otherwise - generic lock error. */ /* errno set by fcntl */ + TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", + tdb->fd, offset, rw_type, lck_type, strerror(errno))); return TDB_ERRCODE(TDB_ERR_LOCK, -1); } return 0; @@ -642,10 +670,10 @@ static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) left: /* Look left */ left = offset - sizeof(tdb_off); - if (left > TDB_HASH_TOP(tdb->header.hash_size-1)) { + if (left > TDB_DATA_START(tdb->header.hash_size)) { struct list_struct l; tdb_off leftsize; - + /* Read in tailer and jump back to header */ if (ofs_read(tdb, left, &leftsize) == -1) { TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); @@ -994,12 +1022,11 @@ static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) } /* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype, +static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, struct list_struct *rec) { - u32 hash, rec_ptr; + u32 rec_ptr; - hash = tdb_hash(&key); if (!tdb_keylocked(tdb, hash)) return 0; if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) @@ -1040,13 +1067,13 @@ const char *tdb_errorstr(TDB_CONTEXT *tdb) on failure return -1. */ -static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf) +static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) { struct list_struct rec; tdb_off rec_ptr; /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* must be long enough key, data and tailer */ @@ -1080,9 +1107,11 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) tdb_off rec_ptr; struct list_struct rec; TDB_DATA ret; + u32 hash; /* find which hash bucket it is in */ - if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec))) + hash = tdb_hash(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; if (rec.data_len) @@ -1101,16 +1130,22 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) this doesn't match the conventions in the rest of this module, but is compatible with gdbm */ -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) { struct list_struct rec; - if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0) + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) return 0; tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); return 1; } +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_exists_hash(tdb, key, hash); +} + /* record lock stops delete underneath */ static int lock_record(TDB_CONTEXT *tdb, tdb_off off) { @@ -1236,7 +1271,8 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, /* Try to clean dead ones from old traverses */ current = tlock->off; tlock->off = rec->next; - if (do_delete(tdb, current, rec) != 0) + if (!tdb->read_only && + do_delete(tdb, current, rec) != 0) goto fail; } tdb_unlock(tdb, tlock->hash, F_WRLCK); @@ -1366,7 +1402,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) if (!tdb->travlocks.off) { /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec); + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec); if (!tdb->travlocks.off) return tdb_null; tdb->travlocks.hash = BUCKET(rec.full_hash); @@ -1394,13 +1430,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) } /* delete an entry in the database given a key */ -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) { tdb_off rec_ptr; struct list_struct rec; int ret; - if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec))) + if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) return -1; ret = do_delete(tdb, rec_ptr, &rec); if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) @@ -1408,6 +1444,12 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) return ret; } +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_delete_hash(tdb, key, hash); +} + /* store an element in the database, replacing any existing element with the same key @@ -1430,13 +1472,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* check for it existing, on insert. */ if (flag == TDB_INSERT) { - if (tdb_exists(tdb, key)) { + if (tdb_exists_hash(tdb, key, hash)) { tdb->ecode = TDB_ERR_EXISTS; goto fail; } } else { /* first try in-place update, on modify or replace. */ - if (tdb_update(tdb, key, dbuf) == 0) + if (tdb_update_hash(tdb, key, hash, dbuf) == 0) goto out; if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST) goto fail; @@ -1448,7 +1490,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) care. Doing this first reduces fragmentation, and avoids coalescing with `allocated' block before it's updated. */ if (flag != TDB_INSERT) - tdb_delete(tdb, key); + tdb_delete_hash(tdb, key, hash); /* Copy key+value *before* allocating free space in case malloc fails and we are left with a dead spot in the tdb. */ @@ -1497,13 +1539,13 @@ fail: is <= the old data size and the key exists. on failure return -1. Record must be locked before calling. */ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) { struct list_struct rec; tdb_off rec_ptr; /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* Append of 0 is always ok. */ @@ -1545,7 +1587,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) return -1; /* first try in-place. */ - if (tdb_append_inplace(tdb, key, new_dbuf) == 0) + if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) goto out; /* reset the error code potentially set by the tdb_append_inplace() */ @@ -1588,7 +1630,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) care. Doing this first reduces fragmentation, and avoids coalescing with `allocated' block before it's updated. */ - tdb_delete(tdb, key); + tdb_delete_hash(tdb, key, hash); if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) goto fail; @@ -1728,8 +1770,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 - || tdb->header.version != TDB_VERSION - || (tdb->header.hash_size != hash_size + || (tdb->header.version != TDB_VERSION && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { /* its not a valid database - possibly initialise it */ if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { @@ -1934,6 +1975,8 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) void tdb_unlockkeys(TDB_CONTEXT *tdb) { u32 i; + if (!tdb->lockedkeys) + return; for (i = 0; i < tdb->lockedkeys[0]; i++) tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK); SAFE_FREE(tdb->lockedkeys); diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index 0d8f6128cc..ce5188300c 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -266,7 +266,7 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) on failure. ****************************************************************************/ -int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -278,7 +278,7 @@ int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int free() on the result dptr. ****************************************************************************/ -TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr) +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -289,7 +289,7 @@ TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr) Delete an entry using a null terminated string key. ****************************************************************************/ -int tdb_delete_by_string(TDB_CONTEXT *tdb, const char *keystr) +int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -311,7 +311,7 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { /* The lookup failed */ if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* but not becouse it didn't exist */ + /* but not because it didn't exist */ goto err_out; } @@ -352,7 +352,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv if (!tdb_fetch_uint32(tdb, keystr, &val)) { /* It failed */ if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* and not becouse it didn't exist */ + /* and not because it didn't exist */ goto err_out; } @@ -387,6 +387,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) { va_list ap; + uint8 bt; uint16 w; uint32 d; int i; @@ -402,44 +403,50 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) while (*fmt) { switch ((c = *fmt++)) { - case 'w': + case 'b': /* unsigned 8-bit integer */ + len = 1; + bt = (uint8)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, bt); + break; + case 'w': /* unsigned 16-bit integer */ len = 2; w = (uint16)va_arg(ap, int); - if (bufsize >= len) + if (bufsize && bufsize >= len) SSVAL(buf, 0, w); break; - case 'd': + case 'd': /* signed 32-bit integer (standard int in most systems) */ len = 4; d = va_arg(ap, uint32); - if (bufsize >= len) + if (bufsize && bufsize >= len) SIVAL(buf, 0, d); break; - case 'p': + case 'p': /* pointer */ len = 4; p = va_arg(ap, void *); d = p?1:0; - if (bufsize >= len) + if (bufsize && bufsize >= len) SIVAL(buf, 0, d); break; - case 'P': + case 'P': /* null-terminated string */ s = va_arg(ap,char *); w = strlen(s); len = w + 1; - if (bufsize >= len) + if (bufsize && bufsize >= len) memcpy(buf, s, len); break; - case 'f': + case 'f': /* null-terminated string */ s = va_arg(ap,char *); w = strlen(s); len = w + 1; - if (bufsize >= len) + if (bufsize && bufsize >= len) memcpy(buf, s, len); break; - case 'B': + case 'B': /* fixed-length string */ i = va_arg(ap, int); s = va_arg(ap, char *); len = 4+i; - if (bufsize >= len) { + if (bufsize && bufsize >= len) { SIVAL(buf, 0, i); memcpy(buf+4, s, i); } @@ -452,7 +459,10 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) } buf += len; - bufsize -= len; + if (bufsize) + bufsize -= len; + if (bufsize < 0) + bufsize = 0; } va_end(ap); @@ -471,6 +481,7 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) { va_list ap; + uint8 *bt; uint16 *w; uint32 *d; int len; @@ -486,6 +497,13 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) while (*fmt) { switch ((c=*fmt++)) { + case 'b': + len = 1; + bt = va_arg(ap, uint8 *); + if (bufsize < len) + goto no_space; + *bt = SVAL(buf, 0); + break; case 'w': len = 2; w = va_arg(ap, uint16 *); @@ -563,6 +581,67 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) return -1; } + +/** + * Pack SID passed by pointer + * + * @param pack_buf pointer to buffer which is to be filled with packed data + * @param bufsize size of packing buffer + * @param sid pointer to sid to be packed + * + * @return length of the packed representation of the whole structure + **/ +size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) +{ + int idx; + size_t len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, + sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); + } + + for (idx = 0; idx < MAXSUBAUTHS; idx++) { + len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); + } + + return len; +} + + +/** + * Unpack SID into a pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param sid pointer to sid structure to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid) +{ + int idx, len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_unpack(pack_buf + len, bufsize - len, "bb", + &sid->sid_rev_num, &sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); + } + + for (idx = 0; idx < MAXSUBAUTHS; idx++) { + len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); + } + + return len; +} + /**************************************************************************** Log tdb messages via DEBUG(). ****************************************************************************/ @@ -665,7 +744,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) return list; -}; +} /** @@ -679,9 +758,8 @@ void tdb_search_list_free(TDB_LIST_NODE* node) while (node) { next_node = node->next; + SAFE_FREE(node->node_key.dptr); SAFE_FREE(node); node = next_node; - }; -}; - - + } +} -- cgit From 16309de71d6c8de96e869aeaab0b879185991d87 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Dec 2003 03:59:09 +0000 Subject: * the RPC-ECHO pipe now works in smbd, as long as the data sizes don't cause fragmented pdus (I'll add fragments shortly) * change data_blob_talloc() to not zero memory when the 2nd argument is NULL. The zeroing just masks bugs, and can't even allow a DOS attack * modified pidl to ensure that [ref] arguments to the out side of functions are allocated when parsing the in side. This allows rpc backends to assume that [ref] variables are all setup. Doesn't work correctly for [ref] arrays yet * changed DLIST_ADD_END() to take the type instead of a tmp variable. This means you don't need to declare a silly tmp variable in the caller (This used to be commit 46e0a358198eeb9af1907ee2a29025d3ab23b6d1) --- source4/lib/data_blob.c | 2 +- source4/lib/tdb/tdbutil.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 933617e9ee..457ad382a2 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -67,12 +67,12 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) } if (p == NULL) { + /* note that we do NOT zero memory in this case */ ret.data = talloc(mem_ctx, length); if (ret.data == NULL) { smb_panic("data_blob_talloc: talloc_memdup failed.\n"); } ret.length = length; - memset(ret.data, 0, ret.length); ret.free = NULL; return ret; } diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index ce5188300c..3c22333b4d 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -710,7 +710,6 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) TDB_DATA key, next; TDB_LIST_NODE *list = NULL; TDB_LIST_NODE *rec = NULL; - TDB_LIST_NODE *tmp = NULL; for (key = tdb_firstkey(tdb); key.dptr; key = next) { /* duplicate key string to ensure null-termination */ @@ -731,7 +730,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) rec->node_key = key; - DLIST_ADD_END(list, rec, tmp); + DLIST_ADD_END(list, rec, TDB_LIST_NODE *); DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern)); } else { -- cgit From 340d9b71f9e75d634389104da5949ba59669ede2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 13 Dec 2003 02:20:40 +0000 Subject: added a basic dcerpc endpoint mapper to Samba4. Currently only implements the epm_Lookup() call, I'll add the other important calls soon. I was rather pleased to find that epm_Lookup() worked first time, which is particularly surprising given its complexity. This required quite a bit of new infrastructure: * a generic way of handling dcerpc policy handles in the rpc server * added type checked varients of talloc. These are much less error prone. I'd like to move to using these for nearly all uses of talloc. * added more dcerpc fault handling code, and translation from NTSTATUS to a dcerpc fault code * added data_blob_talloc_zero() for allocating an initially zero blob * added a endpoint enumeration hook in the dcerpc endpoint server operations (This used to be commit 3f85f9b782dc17417baf1ca557fcae22f5b6a83a) --- source4/lib/data_blob.c | 12 +++++++++++ source4/lib/genparser.c | 11 ---------- source4/lib/talloc.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++--- source4/lib/util.c | 14 ++++++++++++ 4 files changed, 80 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 457ad382a2..b5d1b4076e 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -87,6 +87,18 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) return ret; } +/******************************************************************* + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +*******************************************************************/ +DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length); + data_blob_clear(&blob); + return blob; +} + /******************************************************************* free a data blob *******************************************************************/ diff --git a/source4/lib/genparser.c b/source4/lib/genparser.c index 39c455def4..0f5d26620b 100644 --- a/source4/lib/genparser.c +++ b/source4/lib/genparser.c @@ -22,17 +22,6 @@ #include "includes.h" -/* see if a range of memory is all zero. Used to prevent dumping of zero elements */ -static int all_zero(const char *ptr, unsigned size) -{ - int i; - if (!ptr) return 1; - for (i=0;ilist) return; + + /* as a special case, see if its the first element in the + list */ + if (ctx->list->ptr == ptr) { + ctx->total_alloc_size -= ctx->list->size; + ctx->list = ctx->list->next; + free(ptr); + return; + } + + /* find it in the context */ + for (tc=ctx->list; tc->next; tc=tc->next) { + if (tc->next->ptr == ptr) break; + } + + if (tc->next) { + ctx->total_alloc_size -= tc->next->size; + tc->next = tc->next->next; + } else { + DEBUG(0,("Attempt to free non-allocated chunk in context '%s'\n", + ctx->name)); + } +} + + /* move a lump of memory from one talloc context to another return the ptr on success, or NULL if it could not be found @@ -511,5 +551,16 @@ const void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, const void *p return ptr; } +/* + realloc an array, checking for integer overflow in the array size +*/ +void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned count) +{ + if (count == 0 || + count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return talloc_realloc(ctx, ptr, el_size * count); +} /** @} */ diff --git a/source4/lib/util.c b/source4/lib/util.c index 9b6cef8bfe..233609263d 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -1009,3 +1009,17 @@ void dump_data_pw(const char *msg, const uchar * data, size_t len) } #endif } + + +/* see if a range of memory is all zero. A NULL pointer is considered + to be all zero */ +BOOL all_zero(const char *ptr, unsigned size) +{ + int i; + if (!ptr) return True; + for (i=0;i Date: Sun, 14 Dec 2003 03:51:48 +0000 Subject: fixed some memory leaks in the rpc server code (This used to be commit 20458556017f426ab57ca9a9d098cacecefbdcff) --- source4/lib/talloc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 25871feac1..59d4eac500 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -490,7 +490,9 @@ void talloc_free(TALLOC_CTX *ctx, void *ptr) list */ if (ctx->list->ptr == ptr) { ctx->total_alloc_size -= ctx->list->size; + tc = ctx->list; ctx->list = ctx->list->next; + free(tc); free(ptr); return; } @@ -501,8 +503,11 @@ void talloc_free(TALLOC_CTX *ctx, void *ptr) } if (tc->next) { + struct talloc_chunk *tc2 = tc->next; ctx->total_alloc_size -= tc->next->size; tc->next = tc->next->next; + free(tc2); + free(ptr); } else { DEBUG(0,("Attempt to free non-allocated chunk in context '%s'\n", ctx->name)); -- cgit From ff6478bb4a894228a8959ede750da9d079c13c7b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 03:27:36 +0000 Subject: use smb_rwlock_t instead of rwlock_t to avoid conflicts with system types on some platforms (eg. solaris) (This used to be commit ac8a23af8c67d2e39bb6cfd409c50f1f429cf271) --- source4/lib/mutex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c index 18b7e08b5a..c1a0986040 100644 --- a/source4/lib/mutex.c +++ b/source4/lib/mutex.c @@ -72,7 +72,7 @@ int mutex_unlock(smb_mutex_t *mutex, const char *name) /* read/write lock routines */ -int rwlock_init(rwlock_t *rwlock, const char *name) +int rwlock_init(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_init) { return mutex_handlers.ops.rwlock_init(rwlock, name); @@ -80,7 +80,7 @@ int rwlock_init(rwlock_t *rwlock, const char *name) return 0; } -int rwlock_destroy(rwlock_t *rwlock, const char *name) +int rwlock_destroy(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_destroy) { return mutex_handlers.ops.rwlock_destroy(rwlock, name); @@ -88,7 +88,7 @@ int rwlock_destroy(rwlock_t *rwlock, const char *name) return 0; } -int rwlock_lock_write(rwlock_t *rwlock, const char *name) +int rwlock_lock_write(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_lock_write) { return mutex_handlers.ops.rwlock_lock_write(rwlock, name); @@ -96,7 +96,7 @@ int rwlock_lock_write(rwlock_t *rwlock, const char *name) return 0; } -int rwlock_lock_read(rwlock_t *rwlock, const char *name) +int rwlock_lock_read(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_lock_read) { return mutex_handlers.ops.rwlock_lock_read(rwlock, name); @@ -104,7 +104,7 @@ int rwlock_lock_read(rwlock_t *rwlock, const char *name) return 0; } -int rwlock_unlock(rwlock_t *rwlock, const char *name) +int rwlock_unlock(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_unlock) { return mutex_handlers.ops.rwlock_unlock(rwlock, name); -- cgit From 2c6b585f2de11d4facfe06b8e8db789d22955716 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 03:34:23 +0000 Subject: more portability fixes. We now almost compile on solaris (This used to be commit f4abd20b8437703211676fb12ea23af8f0e4642a) --- source4/lib/mutex.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c index c1a0986040..8d1eee7828 100644 --- a/source4/lib/mutex.c +++ b/source4/lib/mutex.c @@ -28,17 +28,17 @@ static struct { struct mutex_ops ops; } mutex_handlers; -int mutex_lock_by_id(enum mutex_id id, const char *name) +int smb_mutex_lock_by_id(enum mutex_id id, const char *name) { - return mutex_lock(&mutex_list[id], name); + return smb_mutex_lock(&mutex_list[id], name); } -int mutex_unlock_by_id(enum mutex_id id, const char *name) +int smb_mutex_unlock_by_id(enum mutex_id id, const char *name) { - return mutex_unlock(&mutex_list[id], name); + return smb_mutex_unlock(&mutex_list[id], name); } -int mutex_init(smb_mutex_t *mutex, const char *name) +int smb_mutex_init(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_init) { return mutex_handlers.ops.mutex_init(mutex, name); @@ -46,7 +46,7 @@ int mutex_init(smb_mutex_t *mutex, const char *name) return 0; } -int mutex_destroy(smb_mutex_t *mutex, const char *name) +int smb_mutex_destroy(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_destroy) { return mutex_handlers.ops.mutex_destroy(mutex, name); @@ -54,7 +54,7 @@ int mutex_destroy(smb_mutex_t *mutex, const char *name) return 0; } -int mutex_lock(smb_mutex_t *mutex, const char *name) +int smb_mutex_lock(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_lock) { return mutex_handlers.ops.mutex_lock(mutex, name); @@ -62,7 +62,7 @@ int mutex_lock(smb_mutex_t *mutex, const char *name) return 0; } -int mutex_unlock(smb_mutex_t *mutex, const char *name) +int smb_mutex_unlock(smb_mutex_t *mutex, const char *name) { if (mutex_handlers.ops.mutex_unlock) { return mutex_handlers.ops.mutex_unlock(mutex, name); -- cgit From 1abd0be41e7dde4e2edda7fe4c77f231a1583fda Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 03:45:04 +0000 Subject: more mutex portability. (This used to be commit 42dd8d888a1d4c09aebb199e8636f49df6d2e36a) --- source4/lib/mutex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c index 8d1eee7828..25ea3c55ee 100644 --- a/source4/lib/mutex.c +++ b/source4/lib/mutex.c @@ -72,7 +72,7 @@ int smb_mutex_unlock(smb_mutex_t *mutex, const char *name) /* read/write lock routines */ -int rwlock_init(smb_rwlock_t *rwlock, const char *name) +int smb_rwlock_init(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_init) { return mutex_handlers.ops.rwlock_init(rwlock, name); @@ -80,7 +80,7 @@ int rwlock_init(smb_rwlock_t *rwlock, const char *name) return 0; } -int rwlock_destroy(smb_rwlock_t *rwlock, const char *name) +int smb_rwlock_destroy(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_destroy) { return mutex_handlers.ops.rwlock_destroy(rwlock, name); @@ -88,7 +88,7 @@ int rwlock_destroy(smb_rwlock_t *rwlock, const char *name) return 0; } -int rwlock_lock_write(smb_rwlock_t *rwlock, const char *name) +int smb_rwlock_lock_write(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_lock_write) { return mutex_handlers.ops.rwlock_lock_write(rwlock, name); @@ -96,7 +96,7 @@ int rwlock_lock_write(smb_rwlock_t *rwlock, const char *name) return 0; } -int rwlock_lock_read(smb_rwlock_t *rwlock, const char *name) +int smb_rwlock_lock_read(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_lock_read) { return mutex_handlers.ops.rwlock_lock_read(rwlock, name); @@ -104,7 +104,7 @@ int rwlock_lock_read(smb_rwlock_t *rwlock, const char *name) return 0; } -int rwlock_unlock(smb_rwlock_t *rwlock, const char *name) +int smb_rwlock_unlock(smb_rwlock_t *rwlock, const char *name) { if (mutex_handlers.ops.rwlock_unlock) { return mutex_handlers.ops.rwlock_unlock(rwlock, name); -- cgit From b2b9ea54298077cba7df8a7cd849184c40e02e4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 04:10:47 +0000 Subject: enable rep_inet_ntoa() for non-pthread builds (This used to be commit f50d4b602af73045e5b15d62fd24224eba849fd1) --- source4/lib/replace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 63e6a71149..a4f3da1a66 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -322,7 +322,9 @@ duplicate a string return(ret); } #endif /* HAVE_STRDUP */ -#if 0 /* REWRITE: not thread safe */ + +#ifndef WITH_PTHREADS +/* REWRITE: not thread safe */ #ifdef REPLACE_INET_NTOA char *rep_inet_ntoa(struct in_addr ip) { @@ -334,6 +336,7 @@ char *rep_inet_ntoa(struct in_addr ip) } #endif /* REPLACE_INET_NTOA */ #endif + #ifndef HAVE_STRTOUL #ifndef ULONG_MAX #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ -- cgit From 24c22aef90d8534ee2d016b37b2b302f1367d106 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 09:02:58 +0000 Subject: a fairly large commit! This adds support for bigendian rpc in the client. I have installed SUN pcnetlink locally and am using it to test the samba4 rpc code. This allows us to easily find places where we have stuffed up the types (such as 2 uint16 versus a uint32), as testing both big-endian and little-endian easily shows which is correct. I have now used this to fix several bugs like that in the samba4 IDL. In order to make this work I also had to redefine a GUID as a true structure, not a blob. From the pcnetlink wire it is clear that it is indeed defined as a structure (the byte order changes). This required changing lots of Samba code to use a GUID as a structure. I also had to fix the if_version code in dcerpc syntax IDs, as it turns out they are a single uint32 not two uint16s. The big-endian support is a bit ugly at the moment, and breaks the layering in some places. More work is needed, especially on the server side. (This used to be commit bb1af644a5a7b188290ce36232f255da0e5d66d2) --- source4/lib/util_sid.c | 18 ----------------- source4/lib/util_uuid.c | 52 +++++-------------------------------------------- 2 files changed, 5 insertions(+), 65 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 6436035f8e..44bb4cebb1 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -613,24 +613,6 @@ char *sid_binstring(const DOM_SID *sid) return s; } - -/***************************************************************** - Print a GUID structure for debugging. -*****************************************************************/ - -void print_guid(GUID *guid) -{ - int i; - - d_printf("%08x-%04x-%04x", - IVAL(guid->info, 0), SVAL(guid->info, 4), SVAL(guid->info, 6)); - d_printf("-%02x%02x-", guid->info[8], guid->info[9]); - for (i=10;iinfo[i]); - d_printf("\n"); -} - - /******************************************************************* Check if ACE has OBJECT type. ********************************************************************/ diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 1b8c7572c7..0c607fb823 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -3,6 +3,7 @@ * UUID server routines * Copyright (C) Theodore Ts'o 1996, 1997, * Copyright (C) Jim McDonough 2002. + * Copyright (C) Andrew Tridgell 2003. * * 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 @@ -21,52 +22,9 @@ #include "includes.h" -/* - * Offset between 15-Oct-1582 and 1-Jan-70 - */ -#define TIME_OFFSET_HIGH 0x01B21DD2 -#define TIME_OFFSET_LOW 0x13814000 - -struct uuid { - uint32 time_low; - uint16 time_mid; - uint16 time_hi_and_version; - uint8 clock_seq[2]; - uint8 node[6]; -}; - - -static void uuid_pack(const struct uuid *uu, GUID *ptr) -{ - uint8 *out = ptr->info; - - SIVAL(out, 0, uu->time_low); - SSVAL(out, 4, uu->time_mid); - SSVAL(out, 6, uu->time_hi_and_version); - memcpy(out+8, uu->clock_seq, 2); - memcpy(out+10, uu->node, 6); -} - -static void uuid_unpack(const GUID in, struct uuid *uu) +void uuid_generate_random(struct GUID *out) { - const uint8 *ptr = in.info; - - uu->time_low = IVAL(ptr, 0); - uu->time_mid = SVAL(ptr, 4); - uu->time_hi_and_version = SVAL(ptr, 6); - memcpy(uu->clock_seq, ptr+8, 2); - memcpy(uu->node, ptr+10, 6); -} - -void uuid_generate_random(GUID *out) -{ - GUID tmp; - struct uuid uu; - - generate_random_buffer(tmp.info, sizeof(tmp.info), True); - uuid_unpack(tmp, &uu); - - uu.clock_seq[0] = (uu.clock_seq[0] & 0x3F) | 0x80; - uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; - uuid_pack(&uu, out); + generate_random_buffer(out, sizeof(struct GUID), False); + out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; + out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; } -- cgit From 7779b1e00022599f9b77dab7f5f983d930514f15 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 09:20:34 +0000 Subject: added support for big-endian ucs2 strings (as used by big-endian msrpc). this was easier than I expected! (This used to be commit a0a51af6b746b1f82faaa49d33c17fea9d708fb0) --- source4/lib/charcnv.c | 1 + source4/lib/iconv.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 72277b4f2e..11b0e64dce 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -52,6 +52,7 @@ static const char *charset_name(charset_t ch) else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); else if (ch == CH_UTF8) ret = "UTF8"; + else if (ch == CH_UCS2BE) ret = "UCS-2BE"; if (!ret || !*ret) ret = "ASCII"; return ret; diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 2a0b013257..3f37583e39 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -45,16 +45,18 @@ * @sa Samba Developers Guide **/ -static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *); -static size_t ascii_push(void *,const char **, size_t *, char **, size_t *); -static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *); -static size_t utf8_push(void *,const char **, size_t *, char **, size_t *); +static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); +static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); +static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); +static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); -static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); +static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); static struct charset_functions builtin_functions[] = { {"UCS-2LE", iconv_copy, iconv_copy}, + {"UCS-2BE", iconv_swab, iconv_swab}, {"UTF8", utf8_pull, utf8_push}, {"ASCII", ascii_pull, ascii_push}, {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, @@ -404,6 +406,31 @@ static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, return 0; } +static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + swab(*inbuf, *outbuf, (n&~1)); + if (n&1) { + (*outbuf)[n-1] = 0; + } + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) -- cgit From 6f12e4ace1609fbf00d42226134b1dbb259f38bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 09:50:49 +0000 Subject: it turns out that a wire policy handle isn't a blob either, its a uint32 followed by a GUID. I needed to fix this to support running in mixed-mode rpc (where smbtorture is bigendian and w2k3 is little-endian). Otherwise when you send back a policy handle the server doesn't recognise it. (This used to be commit 9b1c76a8e9e953e051072441f8938ee17a674d35) --- source4/lib/util_uuid.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 0c607fb823..c7858aae72 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -28,3 +28,29 @@ void uuid_generate_random(struct GUID *out) out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; } + +BOOL uuid_all_zero(const struct GUID *u) +{ + if (u->time_low != 0 || + u->time_mid != 0 || + u->time_hi_and_version != 0 || + u->clock_seq[0] != 0 || + u->clock_seq[1] != 0 || + !all_zero(u->node, 6)) { + return False; + } + return True; +} + +BOOL uuid_equal(const struct GUID *u1, const struct GUID *u2) +{ + if (u1->time_low != u2->time_low || + u1->time_mid != u2->time_mid || + u1->time_hi_and_version != u2->time_hi_and_version || + u1->clock_seq[0] != u2->clock_seq[0] || + u1->clock_seq[1] != u2->clock_seq[1] || + memcmp(u1->node, u2->node, 6) != 0) { + return False; + } + return True; +} -- cgit From 938eef5bebed15cca6259c760d0afc00f5c088e6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2003 12:59:20 +0000 Subject: removed some unused functions (This used to be commit 09d17d705a6e378a7c1a40b29d2e091200b6d757) --- source4/lib/util_str.c | 87 -------------------------------------------------- 1 file changed, 87 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index ace2e19be3..07fdf334fd 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -737,11 +737,6 @@ void string_sub(char *s,const char *pattern, const char *insert, size_t len) } } -void fstring_sub(char *s,const char *pattern,const char *insert) -{ - string_sub(s, pattern, insert, sizeof(fstring)); -} - void pstring_sub(char *s,const char *pattern,const char *insert) { string_sub(s, pattern, insert, sizeof(pstring)); @@ -854,71 +849,6 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) } } -/** - Similar to all_string_sub but for unicode strings. - Return a new allocated unicode string. - similar to string_sub() but allows for any character to be substituted. - Use with caution! -**/ - -smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern, - const smb_ucs2_t *insert) -{ - smb_ucs2_t *r, *rp; - const smb_ucs2_t *sp; - size_t lr, lp, li, lt; - - if (!insert || !pattern || !*pattern || !s) - return NULL; - - lt = (size_t)strlen_w(s); - lp = (size_t)strlen_w(pattern); - li = (size_t)strlen_w(insert); - - if (li > lp) { - const smb_ucs2_t *st = s; - int ld = li - lp; - while ((sp = strstr_w(st, pattern))) { - st = sp + lp; - lt += ld; - } - } - - r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t))); - if (!r) { - DEBUG(0, ("all_string_sub_w: out of memory!\n")); - return NULL; - } - - while ((sp = strstr_w(s, pattern))) { - memcpy(rp, s, (sp - s)); - rp += ((sp - s) / sizeof(smb_ucs2_t)); - memcpy(rp, insert, (li * sizeof(smb_ucs2_t))); - s = sp + lp; - rp += li; - } - lr = ((rp - r) / sizeof(smb_ucs2_t)); - if (lr < lt) { - memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t))); - rp += (lt - lr); - } - *rp = 0; - - return r; -} - -smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern, - const char *insert) -{ - wpstring p, i; - - if (!insert || !pattern || !s) - return NULL; - push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE); - push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE); - return all_string_sub_w(s, p, i); -} - /** Splits out the front and back at a separator. **/ @@ -1158,26 +1088,10 @@ char *binary_string(char *buf, int len) return ret; } -/** - Just a typesafety wrapper for snprintf into a fstring. -**/ - - int fstr_sprintf(fstring s, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vsnprintf(s, FSTRING_LEN, fmt, ap); - va_end(ap); - return ret; -} - #ifndef HAVE_STRNDUP /** Some platforms don't have strndup. **/ - char *strndup(const char *s, size_t n) { char *ret; @@ -1197,7 +1111,6 @@ char *binary_string(char *buf, int len) /** Some platforms don't have strnlen **/ - size_t strnlen(const char *s, size_t n) { int i; -- cgit From db22c0c5f94ecc12339efbd3950fe1c5648fde76 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 19 Dec 2003 03:59:27 +0000 Subject: added a bunch of alias functions in samr.idl based on work by Kai. (This used to be commit f740b02ac36780740700909da2bcdf672cb146cb) --- source4/lib/util_uuid.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index c7858aae72..6a705a4f30 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -54,3 +54,9 @@ BOOL uuid_equal(const struct GUID *u1, const struct GUID *u2) } return True; } + +BOOL policy_handle_empty(struct policy_handle *h) +{ + return (h->handle_type == 0 && uuid_all_zero(&h->uuid)); +} + -- cgit From f4307200ac338202bc4680cd25fcbac83620ae95 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Dec 2003 22:55:12 +0000 Subject: "subsystems" should be static (This used to be commit 64cf9b3fd3ad971973f6f1d73b924af225252837) --- source4/lib/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index c6c4ef6979..ffd6a38c77 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -123,7 +123,7 @@ struct subsystem { struct subsystem *prev, *next; }; -struct subsystem *subsystems = NULL; +static struct subsystem *subsystems = NULL; void register_subsystem(const char *name, register_backend_function callback) { -- cgit From 7e6cf43756b7643e2f0ee7ada5076f36f3a24bb7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 8 Jan 2004 22:55:27 +0000 Subject: This patch adds a better dcerpc server infastructure. 1.) We now register endpoint servers add startup via register_backend() and later use the smb.conf 'dcerpc endpoint servers' parameter to setup the dcesrv_context 2.) each endpoint server can register at context creation time as much interfaces as it wants (multiple interfaces on one endpoint are supported!) (NOTE: there's a difference between 'endpoint server' and 'endpoint'! for details look at rpc_server/dcesrv_server.h) 3.) one endpoint can have a security descriptor registered to it self this will be checked in the future when a client wants to connect to an smb pipe endpoint. 4.) we now have a 'remote' endpoint server, which works like the ntvfs_cifs module it takes this options in the [globals] section: dcerpc remote:interfaces = srvsvc, winreg, w32time, epmapper dcerpc remote:binding = ... dcerpc remote:user = ... dcerpc remote:password = ... 5.) we currently have tree endpoint servers: epmapper, rpcecho and remote the default for the 'dcerpc endpiont servers = epmapper, rpcecho' for testing you can also do dcerpc endpoint servers = rpcecho, remote, epmapper dcerpc remote:interfaces = srvsvc, samr, netlogon 6,) please notice the the epmapper now only returns NO_ENTRIES (but I think we'll find a solution for this too:-) 7.) also there're some other stuff left, but step by step :-) This patch also includes updates for the register_subsystem() , ntvfs_init(), and some other funtions to check for duplicate subsystem registration metze (hmmm, my first large commit...I hope it works as supposed :-) (This used to be commit 917e45dafd5be4c2cd90ff425b8d6f8403122349) --- source4/lib/module.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index ffd6a38c77..15f92db59e 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -125,9 +125,19 @@ struct subsystem { static struct subsystem *subsystems = NULL; -void register_subsystem(const char *name, register_backend_function callback) +NTSTATUS register_subsystem(const char *name, register_backend_function callback) { struct subsystem *s; + struct subsystem *t = subsystems; + + while(t) { + if(!strcmp(name, t->name)) { + /* its already registered! */ + DEBUG(0,("SUBSYSTEM '%s' for type already registered\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + t = t->next; + } s = smb_xmalloc(sizeof(struct subsystem)); @@ -136,6 +146,8 @@ void register_subsystem(const char *name, register_backend_function callback) s->prev = s->next = NULL; DLIST_ADD(subsystems, s); + + return NT_STATUS_OK; } NTSTATUS register_backend(const char *subsystem, void *args) -- cgit From aafd0efc582ae4b857d19cc50a73bad1a67f0f28 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 21 Jan 2004 23:19:59 +0000 Subject: let the event_add_XXX() function return a pointer of the allocated event structure and NULL on allacation error. metze (This used to be commit fffc6cfb6b9946155d209dd14faa79c5b9d43d1d) --- source4/lib/events.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 00d32043f7..4c30f2cacb 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -88,18 +88,18 @@ struct event_context *event_context_init(void) /* add a fd based event - return False on failure (memory allocation error) + return NULL on failure (memory allocation error) */ -BOOL event_add_fd(struct event_context *ev, struct fd_event *e) +struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) { e = memdup(e, sizeof(*e)); - if (!e) return False; + if (!e) return NULL; DLIST_ADD(ev->fd_events, e); e->ref_count = 1; if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } - return True; + return e; } @@ -172,15 +172,15 @@ void event_remove_fd_all_handler(struct event_context *ev, void *handler) /* add a timed event - return False on failure (memory allocation error) + return NULL on failure (memory allocation error) */ -BOOL event_add_timed(struct event_context *ev, struct timed_event *e) +struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) { e = memdup(e, sizeof(*e)); - if (!e) return False; + if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->timed_events, e); - return True; + return e; } /* @@ -203,15 +203,15 @@ BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) /* add a loop event - return False on failure (memory allocation error) + return NULL on failure (memory allocation error) */ -BOOL event_add_loop(struct event_context *ev, struct loop_event *e) +struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e) { e = memdup(e, sizeof(*e)); - if (!e) return False; + if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->loop_events, e); - return True; + return e; } /* -- cgit From d8ee9d7a0e8826915900f2bf514886ca3f067fd8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Jan 2004 01:35:51 +0000 Subject: - make the recalculation of ev->maxfd a bit more efficient. - fix the case when we have no fd_events left on the event_context we now exit after doing the timed events and not block in select() waiting for no fd's to become ready... metze (This used to be commit 857e76ef6b891c199534db6ce229410340286461) --- source4/lib/events.c | 85 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 35 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 4c30f2cacb..022674460f 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -118,6 +118,11 @@ static void calc_maxfd(struct event_context *ev) } } +/* to mark the ev->maxfd invalid + * this means we need to recalculate it + */ +#define EVENT_INVALID_MAXFD (-1) + /* remove a fd based event the event to remove is matched by looking at the handler @@ -132,8 +137,6 @@ BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1) e->fd == e1->fd && e->handler == e1->handler) { e->ref_count--; - /* possibly calculate the new maxfd */ - calc_maxfd(ev); return True; } } @@ -151,7 +154,6 @@ void event_remove_fd_all(struct event_context *ev, int fd) e->ref_count--; } } - calc_maxfd(ev); } /* @@ -166,7 +168,6 @@ void event_remove_fd_all_handler(struct event_context *ev, void *handler) e->ref_count--; } } - calc_maxfd(ev); } @@ -289,6 +290,9 @@ int event_loop_wait(struct event_context *ev) struct fd_event *next = fe->next; if (fe->ref_count == 0) { DLIST_REMOVE(ev->fd_events, fe); + if (ev->maxfd == fe->fd) { + ev->maxfd = EVENT_INVALID_MAXFD; + } free(fe); } else { if (fe->flags & EVENT_FD_READ) { @@ -316,39 +320,50 @@ int event_loop_wait(struct event_context *ev) } } + /* only do a select() if there're fd_events + * otherwise we would block for a the time in tval, + * and if there're no fd_events present anymore we want to + * leave the event loop directly + */ + if (ev->fd_events) { + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } - /* TODO: - - we don't use sys_select() as it isn't thread - safe. We need to replace the magic pipe handling in - sys_select() with something in the events - structure - for now just use select() */ - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); - - t = time(NULL); - - if (selrtn == -1 && errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - DEBUG(0,("EBADF on event_loop_wait - exiting\n")); - return -1; - } + /* TODO: + * we don't use sys_select() as it isn't thread + * safe. We need to replace the magic pipe handling in + * sys_select() with something in the events + * structure - for now just use select() + */ + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + + t = time(NULL); + + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("EBADF on event_loop_wait - exiting\n")); + return -1; + } - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { - uint16 flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (fe->ref_count && flags) { - fe->ref_count++; - fe->handler(ev, fe, t, flags); - fe->ref_count--; + if (selrtn > 0) { + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16 flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (fe->ref_count && flags) { + fe->ref_count++; + fe->handler(ev, fe, t, flags); + fe->ref_count--; + } } } } -- cgit From 55dfa23e4149b8daa9fe007fd1b7fac744bcdf12 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 22 Jan 2004 01:56:31 +0000 Subject: initilize ev->maxfd = EVENT_INVALID_MAXFD; before the while() loop. metze (This used to be commit 61ec710518469876ccc48d57b5fee5d6ead3d482) --- source4/lib/events.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 022674460f..85a2cee70f 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -255,6 +255,7 @@ int event_loop_wait(struct event_context *ev) time_t t; ZERO_STRUCT(ev->exit); + ev->maxfd = EVENT_INVALID_MAXFD; t = time(NULL); -- cgit From e06687eb174d5ca785a6c67fa63a99ea019182c4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 28 Jan 2004 12:47:52 +0000 Subject: merge the version.h autogeneration stuff from 3.0 metze (This used to be commit 24dc237e109f6dce69814b22e0fb7878a7f6bfa8) --- source4/lib/cmdline/popt_common.c | 2 +- source4/lib/fault.c | 2 +- source4/lib/popt_common.c | 2 +- source4/lib/version.c | 42 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 source4/lib/version.c (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 3c9a5eb231..1b8e3bd93e 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -66,7 +66,7 @@ static void popt_common_callback(poptContext con, break; case 'V': - printf( "Version %s\n", SAMBA_VERSION ); + printf( "Version %s\n", SAMBA_VERSION_STRING ); exit(0); break; diff --git a/source4/lib/fault.c b/source4/lib/fault.c index 5a76ce2c0c..47a43bca84 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -39,7 +39,7 @@ static void fault_report(int sig) if (counter) _exit(1); DEBUG(0,("===============================================================\n")); - DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION)); + DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING)); DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); DEBUG(0,("===============================================================\n")); diff --git a/source4/lib/popt_common.c b/source4/lib/popt_common.c index 3c9a5eb231..1b8e3bd93e 100644 --- a/source4/lib/popt_common.c +++ b/source4/lib/popt_common.c @@ -66,7 +66,7 @@ static void popt_common_callback(poptContext con, break; case 'V': - printf( "Version %s\n", SAMBA_VERSION ); + printf( "Version %s\n", SAMBA_VERSION_STRING ); exit(0); break; diff --git a/source4/lib/version.c b/source4/lib/version.c new file mode 100644 index 0000000000..99f836c2d5 --- /dev/null +++ b/source4/lib/version.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + Samba Version functions + + Copyright (C) Stefan Metzmacher 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +const char *samba_version_string(void) +{ +#ifndef SAMBA_VERSION_VENDOR_SUFFIX + return SAMBA_VERSION_OFFICIAL_STRING; +#else + static fstring samba_version; + static BOOL init_samba_version; + + if (init_samba_version) + return samba_version; + + snprintf(samba_version,sizeof(samba_version),"%s-%s", + SAMBA_VERSION_OFFICIAL_STRING, + SAMBA_VERSION_VENDOR_SUFFIX); + + init_samba_version = True; + return samba_version; +#endif +} -- cgit From a5ece462abeaa1326cb7fd7073dfc9fd0c7cb9f2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 28 Jan 2004 18:54:36 +0000 Subject: remove a lot of unused stuff from the header files and exclude some files from Makefile.in metze (This used to be commit f77990cf2496f72d02566f09477349436be3dfcd) --- source4/lib/smbrun.c | 12 +++++++++--- source4/lib/talloctort.c | 4 ++++ source4/lib/util_seaccess.c | 4 ++++ 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/smbrun.c b/source4/lib/smbrun.c index acb836ba7a..78f3d22ea0 100644 --- a/source4/lib/smbrun.c +++ b/source4/lib/smbrun.c @@ -20,13 +20,18 @@ #include "includes.h" -/* need to move this from here!! need some sleep ... */ -struct current_user current_user; +#if 1 +int smbrun(char *cmd, int *outfd) +{ + #warning smbrun() needs a rewrite: struct current_user is gone! + DEBUG(0,("smbrun() needs a rewrite: struct current_user is gone!\n")); + return -1; +} +#else /**************************************************************************** This is a utility function of smbrun(). ****************************************************************************/ - static int setup_out_fd(void) { int fd; @@ -169,3 +174,4 @@ int smbrun(char *cmd, int *outfd) exit(82); return 1; } +#endif diff --git a/source4/lib/talloctort.c b/source4/lib/talloctort.c index ad5de38581..9c10f4eed8 100644 --- a/source4/lib/talloctort.c +++ b/source4/lib/talloctort.c @@ -18,6 +18,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#error SAMBA4 clean up +#error this file should be (re)moved +#error and all unused stuff should go + #include "includes.h" #define NCTX 10 diff --git a/source4/lib/util_seaccess.c b/source4/lib/util_seaccess.c index eba8cab7fb..9d56a0d850 100644 --- a/source4/lib/util_seaccess.c +++ b/source4/lib/util_seaccess.c @@ -19,6 +19,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#error SAMBA4 clean up +#error this file should be (re)moved +#error and all unused stuff should go + #include "includes.h" extern DOM_SID global_sid_Builtin; -- cgit From ac7d38c3f99d91e5d9168aebc0ec2ad93f7f962d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Feb 2004 07:23:29 +0000 Subject: remove unused files we maybe need the util_smbd.c code later but this should not be in the lib/ dir metze (This used to be commit 2149d414079cefc956bc9a50e30b7bb423f4aca6) --- source4/lib/system_smbd.c | 0 source4/lib/util_smbd.c | 65 ----------------------------------------------- 2 files changed, 65 deletions(-) delete mode 100644 source4/lib/system_smbd.c delete mode 100644 source4/lib/util_smbd.c (limited to 'source4/lib') diff --git a/source4/lib/system_smbd.c b/source4/lib/system_smbd.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/source4/lib/util_smbd.c b/source4/lib/util_smbd.c deleted file mode 100644 index 071f20b416..0000000000 --- a/source4/lib/util_smbd.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions, used in smbd only - Copyright (C) Andrew Tridgell 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* - This function requires sys_getgrouplist - which is only - available in smbd due to it's use of become_root() in a - legacy systems hack. -*/ - -/* - return a full list of groups for a user - - returns the number of groups the user is a member of. The return will include the - users primary group. - - remember to free the resulting gid_t array - - NOTE! uses become_root() to gain correct priviages on systems - that lack a native getgroups() call (uses initgroups and getgroups) -*/ -int getgroups_user(const char *user, gid_t **groups) -{ - struct passwd *pwd; - int ngrp, max_grp; - - pwd = getpwnam_alloc(user); - if (!pwd) return -1; - - max_grp = groups_max(); - (*groups) = (gid_t *)malloc(sizeof(gid_t) * max_grp); - if (! *groups) { - passwd_free(&pwd); - errno = ENOMEM; - return -1; - } - - ngrp = sys_getgrouplist(user, pwd->pw_gid, *groups, &max_grp); - if (ngrp <= 0) { - passwd_free(&pwd); - free(*groups); - return ngrp; - } - - passwd_free(&pwd); - return ngrp; -} -- cgit From ada1de721ab17e83cfedf9d68adec750de626317 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Feb 2004 12:15:25 +0000 Subject: some compilers don't like the #warning preprocessing directive so just do a DEBUG(0,("...")); metze (This used to be commit c087ff38b0c67a2246214c1303b045e6a7c2aa4a) --- source4/lib/smbrun.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/smbrun.c b/source4/lib/smbrun.c index 78f3d22ea0..ab36ec6e40 100644 --- a/source4/lib/smbrun.c +++ b/source4/lib/smbrun.c @@ -24,7 +24,6 @@ #if 1 int smbrun(char *cmd, int *outfd) { - #warning smbrun() needs a rewrite: struct current_user is gone! DEBUG(0,("smbrun() needs a rewrite: struct current_user is gone!\n")); return -1; } -- cgit From c61089219b82ff94f83e1fb428e8b47ad778c868 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Feb 2004 13:43:03 +0000 Subject: - we now specify the object files in the subsystems config.m4 file I plan to convert all objectfile group to use SMB_SUBSYSTEM later I'll add a SMB_BINARY() and SMB_LIBRARY(), then there will be no more need to touch Makefile.in, because all make rules will be autogenerated by configure - convert the PROCESS_MODEL subsystem to this new scheme and move the pthread test to smbd/process_model.m4 - convert the CHARSET subsystem to this new scheme and move the iconv test to lib/iconv.m4 (This used to be commit 2e57ee884ebea194ee79ac20e84e385481b56aa2) --- source4/lib/iconv.m4 | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 source4/lib/iconv.m4 (limited to 'source4/lib') diff --git a/source4/lib/iconv.m4 b/source4/lib/iconv.m4 new file mode 100644 index 0000000000..26512ff326 --- /dev/null +++ b/source4/lib/iconv.m4 @@ -0,0 +1,66 @@ +dnl # ICONV/CHARSET subsystem + +ICONV_LOCATION=standard +LOOK_DIRS="/usr /usr/local /sw" +AC_ARG_WITH(libiconv, +[ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], +[ + if test "$withval" = "no" ; then + AC_MSG_ERROR(I won't take no for an answer) + else + if test "$withval" != "yes" ; then + LOOK_DIRS="$withval $LOOK_DIRS" + fi + fi +]) + +ICONV_FOUND="no" +for i in $LOOK_DIRS ; do + save_LIBS=$LIBS + save_LDFLAGS=$LDFLAGS + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="-I$i/include" + LDFLAGS="-L$i/lib" + LIBS= + export LDFLAGS LIBS CPPFLAGS +dnl Try to find iconv(3) + jm_ICONV($i) + + CPPFLAGS=$save_CPPFLAGS + if test -n "$ICONV_FOUND" ; then + LDFLAGS=$save_LDFLAGS + LIB_ADD_DIR(LDFLAGS, "$i/lib") + CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") + LIBS="$save_LIBS $LIBS" + ICONV_LOCATION=$i + export LDFLAGS LIBS CPPFLAGS + break + else + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + export LDFLAGS LIBS CPPFLAGS + fi +done + +############ +# check for iconv in libc +AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ +AC_TRY_RUN([ +#include +main() { + iconv_t cd = iconv_open("ASCII", "UCS-2LE"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} +], +samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) +if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then + AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) +fi + +if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then + AC_MSG_WARN([Sufficient support for iconv function was not found. + Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) +fi + +SMB_SUBSYSTEM(CHARSET,lib/iconv.o,lib/charcnv.o) -- cgit From 078cced5ec1026432f5df275a7023db70a62693e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Feb 2004 10:22:12 +0000 Subject: - modified the dcerpc client security code to be generic, so ntlmssp and schannel are both instances of possible security modules - added schannel sign and sign/seal support to the dcerpc client code. You select it with binding options of "schannel,sign" or "schannel,seal". (This used to be commit 05db0b9d942cad8f1dd574dc35b759e5e79d4195) --- source4/lib/crypto/hmacmd5.c | 2 +- source4/lib/hmacmd5.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index f436fd30c0..8ca7dba841 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -121,7 +121,7 @@ void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ -void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest) +void hmac_md5(const uchar key[16], const uchar *data, int data_len, uchar* digest) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(key, 16, &ctx); diff --git a/source4/lib/hmacmd5.c b/source4/lib/hmacmd5.c index f436fd30c0..8ca7dba841 100644 --- a/source4/lib/hmacmd5.c +++ b/source4/lib/hmacmd5.c @@ -121,7 +121,7 @@ void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ -void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest) +void hmac_md5(const uchar key[16], const uchar *data, int data_len, uchar* digest) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(key, 16, &ctx); -- cgit From 45e446248d36087dd53c341051424beb058bd99d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Feb 2004 06:02:32 +0000 Subject: move more code to the config.m4 scheme LIBBASIC, LIBSMB are the new global subsystems metze (This used to be commit a25c167b3f13031ba992b2d3f74387bdfffbf5b0) --- source4/lib/basic.m4 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 source4/lib/basic.m4 (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 new file mode 100644 index 0000000000..e9ea611dbf --- /dev/null +++ b/source4/lib/basic.m4 @@ -0,0 +1,24 @@ +dnl # LIB BASIC subsystem + +SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], + [lib/debug.o lib/fault.o \ + lib/getsmbpass.o lib/interface.o lib/md4.o \ + lib/interfaces.o lib/pidfile.o lib/replace.o \ + lib/signal.o lib/system.o lib/sendfile.o lib/time.o \ + lib/genrand.o lib/username.o \ + lib/util_getent.o lib/util_pw.o lib/smbrun.o \ + lib/bitmap.o lib/crc32.o lib/snprintf.o lib/dprintf.o \ + lib/xfile.o lib/wins_srv.o \ + lib/util_str.o lib/util_sid.o lib/util_uuid.o \ + lib/util_unistr.o lib/util_file.o lib/data_blob.o \ + lib/util.o lib/util_sock.o \ + lib/talloc.o lib/substitute.o lib/fsusage.o \ + lib/ms_fnmatch.o lib/select.o lib/messages.o \ + lib/tallocmsg.o lib/dmallocmsg.o \ + lib/md5.o lib/hmacmd5.o lib/smbpasswd.o \ + nsswitch/wb_client.o nsswitch/wb_common.o \ + lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ + lib/gencache.o lib/module.o lib/mutex.o \ + lib/ldap_escape.o lib/events.o \ + tdb/tdb.o tdb/spinlock.o tdb/tdbutil.o \$(CHARSET_OBJS)], + lib/libbasic_public_proto.h) -- cgit From e46d297083c6e656774d94bb8153334836a27937 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Feb 2004 08:07:46 +0000 Subject: move the -lpopt replacement to a LIBPOPT subsystem metze (This used to be commit 9eb593a7c065326dafbba896ed723d0ea5cb00ed) --- source4/lib/popt/config.m4 | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index 7532c5826e..0be7d308c7 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -1,31 +1,40 @@ ################################################# -# Check to see if we should use the included popt +# Check to see if we should use the included popt +INCLUDED_POPT=auto AC_ARG_WITH(included-popt, [ --with-included-popt use bundled popt library, not from system], [ - case "$withval" in +case "$withval" in yes) INCLUDED_POPT=yes ;; no) - INCLUDED_POPT=no - ;; - esac ], + INCLUDED_POPT=no + ;; +esac ], ) if test x"$INCLUDED_POPT" != x"yes"; then - AC_CHECK_LIB(popt, poptGetContext, - INCLUDED_POPT=no, INCLUDED_POPT=yes) + AC_CHECK_HEADERS(popt.h) + AC_CHECK_LIB_EXT(popt, TMP_LIBPOPT_LIBS, poptGetContext, [], [], INCLUDED_POPT=no) + if test x"$ac_cv_header_popt_h" = x"no"; then + INCLUDED_POPT=yes + TMP_LIBPOPT_LIBS="" + fi fi AC_MSG_CHECKING(whether to use included popt) -if test x"$INCLUDED_POPT" = x"yes"; then - AC_MSG_RESULT(yes) - BUILD_POPT='$(POPT_OBJS)' - FLAGS1="-I$srcdir/popt" +if test x"$INCLUDED_POPT" != x"no"; then + TMP_LIBPOPT_OBJS="popt/findme.o popt/popt.o popt/poptconfig.o \ + popt/popthelp.o popt/poptparse.o" + CPPFLAGS="$CPPFLAGS -I$srcdir/popt" + AC_MSG_RESULT(yes) else - AC_MSG_RESULT(no) - LIBS="$LIBS -lpopt" + AC_MSG_RESULT(no) fi -AC_SUBST(BUILD_POPT) -AC_SUBST(FLAGS1) + +SMB_SUBSYSTEM(LIBPOPT,[], + [${TMP_LIBPOPT_OBJS}], + [], + [], + [${TMP_LIBPOPT_LIBS}]) -- cgit From 6647ff74306dd6985c32c75b177707b5c60b23b3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Feb 2004 14:21:44 +0000 Subject: move -lpopt replacement code from source/popt/* to source/lib/popt/* metze (This used to be commit 9d1018557fdc51cada1ad082d85c0dc48e1b3072) --- source4/lib/popt/config.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index 0be7d308c7..6ac5d91079 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -25,9 +25,9 @@ fi AC_MSG_CHECKING(whether to use included popt) if test x"$INCLUDED_POPT" != x"no"; then - TMP_LIBPOPT_OBJS="popt/findme.o popt/popt.o popt/poptconfig.o \ - popt/popthelp.o popt/poptparse.o" - CPPFLAGS="$CPPFLAGS -I$srcdir/popt" + TMP_LIBPOPT_OBJS="lib/popt/findme.o lib/popt/popt.o lib/popt/poptconfig.o \ + lib/popt/popthelp.o lib/popt/poptparse.o" + CPPFLAGS="$CPPFLAGS -I$srcdir/lib/popt" AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) -- cgit From 9a8cd1aa27204096d64b99c4dbed73f498e3ccfe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Feb 2004 15:59:16 +0000 Subject: move the tdb lib code to lib/tdb/* metze (This used to be commit 5ebd6fb761370cbe2835a2a2631e24e35bcaffb4) --- source4/lib/basic.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index e9ea611dbf..d185a33c33 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -20,5 +20,5 @@ SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ lib/gencache.o lib/module.o lib/mutex.o \ lib/ldap_escape.o lib/events.o \ - tdb/tdb.o tdb/spinlock.o tdb/tdbutil.o \$(CHARSET_OBJS)], + lib/tdb/tdb.o lib/tdb/spinlock.o lib/tdb/tdbutil.o \$(CHARSET_OBJS)], lib/libbasic_public_proto.h) -- cgit From 0af9994327e249420e7e9b1943a12fcea6c8693f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Feb 2004 12:20:17 +0000 Subject: move some cryto stuff to lib/crypto/* metze (This used to be commit afe4dbfea658d3d3de847651ea2b3d5517e81f41) --- source4/lib/basic.m4 | 8 +- source4/lib/crc32.c | 67 -------------- source4/lib/hmacmd5.c | 134 --------------------------- source4/lib/md4.c | 175 ----------------------------------- source4/lib/md5.c | 247 -------------------------------------------------- 5 files changed, 5 insertions(+), 626 deletions(-) delete mode 100644 source4/lib/crc32.c delete mode 100644 source4/lib/hmacmd5.c delete mode 100644 source4/lib/md4.c delete mode 100644 source4/lib/md5.c (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index d185a33c33..712a4826b7 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -2,12 +2,12 @@ dnl # LIB BASIC subsystem SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], [lib/debug.o lib/fault.o \ - lib/getsmbpass.o lib/interface.o lib/md4.o \ + lib/getsmbpass.o lib/interface.o \ lib/interfaces.o lib/pidfile.o lib/replace.o \ lib/signal.o lib/system.o lib/sendfile.o lib/time.o \ lib/genrand.o lib/username.o \ lib/util_getent.o lib/util_pw.o lib/smbrun.o \ - lib/bitmap.o lib/crc32.o lib/snprintf.o lib/dprintf.o \ + lib/bitmap.o lib/snprintf.o lib/dprintf.o \ lib/xfile.o lib/wins_srv.o \ lib/util_str.o lib/util_sid.o lib/util_uuid.o \ lib/util_unistr.o lib/util_file.o lib/data_blob.o \ @@ -15,10 +15,12 @@ SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], lib/talloc.o lib/substitute.o lib/fsusage.o \ lib/ms_fnmatch.o lib/select.o lib/messages.o \ lib/tallocmsg.o lib/dmallocmsg.o \ - lib/md5.o lib/hmacmd5.o lib/smbpasswd.o \ + lib/smbpasswd.o \ nsswitch/wb_client.o nsswitch/wb_common.o \ lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ lib/gencache.o lib/module.o lib/mutex.o \ lib/ldap_escape.o lib/events.o \ + lib/crypto/crc32.o lib/crypto/md5.o \ + lib/crypto/hmacmd5.o lib/crypto/md4.o \ lib/tdb/tdb.o lib/tdb/spinlock.o lib/tdb/tdbutil.o \$(CHARSET_OBJS)], lib/libbasic_public_proto.h) diff --git a/source4/lib/crc32.c b/source4/lib/crc32.c deleted file mode 100644 index da3aeaa901..0000000000 --- a/source4/lib/crc32.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Francesco Ferrara, 1998 - * - * Used by kind permission, 14th October 1998. http://www.aerre.it/francesco - * - * - */ - -#include "includes.h" - -static const unsigned long CRCTable[256] = -{ - 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F, - 0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988, - 0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2, - 0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, - 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9, - 0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172, - 0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C, - 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, - 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423, - 0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924, - 0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106, - 0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, - 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D, - 0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E, - 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950, - 0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, - 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7, - 0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0, - 0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA, - 0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, - 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81, - 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A, - 0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84, - 0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, - 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB, - 0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC, - 0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E, - 0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, - 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55, - 0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236, - 0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28, - 0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, - 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F, - 0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38, - 0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242, - 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, - 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69, - 0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2, - 0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC, - 0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, - 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693, - 0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94, - 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D -}; - -uint32 crc32_calc_buffer( const char *buffer, uint32 count) -{ - uint32 crc=0xffffffff, i; - for(i=0;i>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff]; - crc^=0xffffffff; - DEBUG(10,("crc32_calc_buffer: %x\n", crc)); - dump_data(100, buffer, count); - return crc; -} diff --git a/source4/lib/hmacmd5.c b/source4/lib/hmacmd5.c deleted file mode 100644 index 8ca7dba841..0000000000 --- a/source4/lib/hmacmd5.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - Unix SMB/CIFS implementation. - HMAC MD5 code for use in NTLMv2 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Tridgell 1992-2000 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* taken direct from rfc2104 implementation and modified for suitable use - * for ntlmv2. - */ - -#include "includes.h" - -/*********************************************************************** - the rfc 2104 version of hmac_md5 initialisation. -***********************************************************************/ -void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) -{ - int i; - - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) - { - uchar tk[16]; - struct MD5Context tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* start out by storing key in pads */ - ZERO_STRUCT(ctx->k_ipad); - ZERO_STRUCT(ctx->k_opad); - memcpy( ctx->k_ipad, key, key_len); - memcpy( ctx->k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) - { - ctx->k_ipad[i] ^= 0x36; - ctx->k_opad[i] ^= 0x5c; - } - - MD5Init(&ctx->ctx); - MD5Update(&ctx->ctx, ctx->k_ipad, 64); -} - -/*********************************************************************** - the microsoft version of hmac_md5 initialisation. -***********************************************************************/ -void hmac_md5_init_limK_to_64(const uchar* key, int key_len, - HMACMD5Context *ctx) -{ - int i; - - /* if key is longer than 64 bytes truncate it */ - if (key_len > 64) - { - key_len = 64; - } - - /* start out by storing key in pads */ - ZERO_STRUCT(ctx->k_ipad); - ZERO_STRUCT(ctx->k_opad); - memcpy( ctx->k_ipad, key, key_len); - memcpy( ctx->k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - ctx->k_ipad[i] ^= 0x36; - ctx->k_opad[i] ^= 0x5c; - } - - MD5Init(&ctx->ctx); - MD5Update(&ctx->ctx, ctx->k_ipad, 64); -} - -/*********************************************************************** - update hmac_md5 "inner" buffer -***********************************************************************/ -void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) -{ - MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ -} - -/*********************************************************************** - finish off hmac_md5 "inner" buffer and generate outer one. -***********************************************************************/ -void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) - -{ - struct MD5Context ctx_o; - - MD5Final(digest, &ctx->ctx); - - MD5Init(&ctx_o); - MD5Update(&ctx_o, ctx->k_opad, 64); - MD5Update(&ctx_o, digest, 16); - MD5Final(digest, &ctx_o); -} - -/*********************************************************** - single function to calculate an HMAC MD5 digest from data. - use the microsoft hmacmd5 init method because the key is 16 bytes. -************************************************************/ -void hmac_md5(const uchar key[16], const uchar *data, int data_len, uchar* digest) -{ - HMACMD5Context ctx; - hmac_md5_init_limK_to_64(key, 16, &ctx); - if (data_len != 0) - { - hmac_md5_update(data, data_len, &ctx); - } - hmac_md5_final(digest, &ctx); -} - diff --git a/source4/lib/md4.c b/source4/lib/md4.c deleted file mode 100644 index 417e87bd8e..0000000000 --- a/source4/lib/md4.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - Unix SMB/CIFS implementation. - a implementation of MD4 designed for use in the SMB authentication protocol - Copyright (C) Andrew Tridgell 1997-1998. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* NOTE: This code makes no attempt to be fast! - - It assumes that a int is at least 32 bits long -*/ - -struct mdfour_state { - uint32 A, B, C, D; -}; - -static uint32 F(uint32 X, uint32 Y, uint32 Z) -{ - return (X&Y) | ((~X)&Z); -} - -static uint32 G(uint32 X, uint32 Y, uint32 Z) -{ - return (X&Y) | (X&Z) | (Y&Z); -} - -static uint32 H(uint32 X, uint32 Y, uint32 Z) -{ - return X^Y^Z; -} - -static uint32 lshift(uint32 x, int s) -{ - x &= 0xFFFFFFFF; - return ((x<>(32-s)); -} - -#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) -#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) -#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) - -/* this applies md4 to 64 byte chunks */ -static void mdfour64(struct mdfour_state *s, uint32 *M) -{ - int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; - - for (j=0;j<16;j++) - X[j] = M[j]; - - AA = s->A; BB = s->B; CC = s->C; DD = s->D; - - ROUND1(s->A,s->B,s->C,s->D, 0, 3); ROUND1(s->D,s->A,s->B,s->C, 1, 7); - ROUND1(s->C,s->D,s->A,s->B, 2, 11); ROUND1(s->B,s->C,s->D,s->A, 3, 19); - ROUND1(s->A,s->B,s->C,s->D, 4, 3); ROUND1(s->D,s->A,s->B,s->C, 5, 7); - ROUND1(s->C,s->D,s->A,s->B, 6, 11); ROUND1(s->B,s->C,s->D,s->A, 7, 19); - ROUND1(s->A,s->B,s->C,s->D, 8, 3); ROUND1(s->D,s->A,s->B,s->C, 9, 7); - ROUND1(s->C,s->D,s->A,s->B, 10, 11); ROUND1(s->B,s->C,s->D,s->A, 11, 19); - ROUND1(s->A,s->B,s->C,s->D, 12, 3); ROUND1(s->D,s->A,s->B,s->C, 13, 7); - ROUND1(s->C,s->D,s->A,s->B, 14, 11); ROUND1(s->B,s->C,s->D,s->A, 15, 19); - - ROUND2(s->A,s->B,s->C,s->D, 0, 3); ROUND2(s->D,s->A,s->B,s->C, 4, 5); - ROUND2(s->C,s->D,s->A,s->B, 8, 9); ROUND2(s->B,s->C,s->D,s->A, 12, 13); - ROUND2(s->A,s->B,s->C,s->D, 1, 3); ROUND2(s->D,s->A,s->B,s->C, 5, 5); - ROUND2(s->C,s->D,s->A,s->B, 9, 9); ROUND2(s->B,s->C,s->D,s->A, 13, 13); - ROUND2(s->A,s->B,s->C,s->D, 2, 3); ROUND2(s->D,s->A,s->B,s->C, 6, 5); - ROUND2(s->C,s->D,s->A,s->B, 10, 9); ROUND2(s->B,s->C,s->D,s->A, 14, 13); - ROUND2(s->A,s->B,s->C,s->D, 3, 3); ROUND2(s->D,s->A,s->B,s->C, 7, 5); - ROUND2(s->C,s->D,s->A,s->B, 11, 9); ROUND2(s->B,s->C,s->D,s->A, 15, 13); - - ROUND3(s->A,s->B,s->C,s->D, 0, 3); ROUND3(s->D,s->A,s->B,s->C, 8, 9); - ROUND3(s->C,s->D,s->A,s->B, 4, 11); ROUND3(s->B,s->C,s->D,s->A, 12, 15); - ROUND3(s->A,s->B,s->C,s->D, 2, 3); ROUND3(s->D,s->A,s->B,s->C, 10, 9); - ROUND3(s->C,s->D,s->A,s->B, 6, 11); ROUND3(s->B,s->C,s->D,s->A, 14, 15); - ROUND3(s->A,s->B,s->C,s->D, 1, 3); ROUND3(s->D,s->A,s->B,s->C, 9, 9); - ROUND3(s->C,s->D,s->A,s->B, 5, 11); ROUND3(s->B,s->C,s->D,s->A, 13, 15); - ROUND3(s->A,s->B,s->C,s->D, 3, 3); ROUND3(s->D,s->A,s->B,s->C, 11, 9); - ROUND3(s->C,s->D,s->A,s->B, 7, 11); ROUND3(s->B,s->C,s->D,s->A, 15, 15); - - s->A += AA; - s->B += BB; - s->C += CC; - s->D += DD; - - s->A &= 0xFFFFFFFF; - s->B &= 0xFFFFFFFF; - s->C &= 0xFFFFFFFF; - s->D &= 0xFFFFFFFF; - - for (j=0;j<16;j++) - X[j] = 0; -} - -static void copy64(uint32 *M, const unsigned char *in) -{ - int i; - - for (i=0;i<16;i++) - M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | - (in[i*4+1]<<8) | (in[i*4+0]<<0); -} - -static void copy4(unsigned char *out, uint32 x) -{ - out[0] = x&0xFF; - out[1] = (x>>8)&0xFF; - out[2] = (x>>16)&0xFF; - out[3] = (x>>24)&0xFF; -} - -/* produce a md4 message digest from data of length n bytes */ -void mdfour(unsigned char *out, const unsigned char *in, int n) -{ - unsigned char buf[128]; - uint32 M[16]; - uint32 b = n * 8; - int i; - struct mdfour_state state; - - state.A = 0x67452301; - state.B = 0xefcdab89; - state.C = 0x98badcfe; - state.D = 0x10325476; - - while (n > 64) { - copy64(M, in); - mdfour64(&state, M); - in += 64; - n -= 64; - } - - for (i=0;i<128;i++) - buf[i] = 0; - memcpy(buf, in, n); - buf[n] = 0x80; - - if (n <= 55) { - copy4(buf+56, b); - copy64(M, buf); - mdfour64(&state, M); - } else { - copy4(buf+120, b); - copy64(M, buf); - mdfour64(&state, M); - copy64(M, buf+64); - mdfour64(&state, M); - } - - for (i=0;i<128;i++) - buf[i] = 0; - copy64(M, buf); - - copy4(out, state.A); - copy4(out+4, state.B); - copy4(out+8, state.C); - copy4(out+12, state.D); -} - - diff --git a/source4/lib/md5.c b/source4/lib/md5.c deleted file mode 100644 index 2121b17047..0000000000 --- a/source4/lib/md5.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* This code slightly modified to fit into Samba by - abartlet@samba.org Jun 2001 */ - -#include "includes.h" - -#include "md5.h" - -static void MD5Transform(uint32 buf[4], uint32 const in[16]); - -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - uint32 t; - do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; - buf += 4; - } while (--longs); -} - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - register uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memmove(p, buf, len); - return; - } - memmove(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memmove(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memmove(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned int count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (uint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memmove(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(uint32 buf[4], uint32 const in[16]) -{ - register uint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} -- cgit From 932026724ff7e8050cfa0412c45168c25ee47e1a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Feb 2004 13:55:15 +0000 Subject: remove unused NISPLUS/AUTOMOUNT stuff metze (This used to be commit cbfa29549e5b302f947c7f2ca14fbea257e46c33) --- source4/lib/util.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 233609263d..0cb5258a64 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -24,37 +24,6 @@ #include "includes.h" -#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) -#ifdef WITH_NISPLUS_HOME -#ifdef BROKEN_NISPLUS_INCLUDE_FILES -/* - * The following lines are needed due to buggy include files - * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and - * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. - * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as - * an enum in /usr/include/rpcsvc/nis.h. - */ - -#if defined(GROUP) -#undef GROUP -#endif - -#if defined(GROUP_OBJ) -#undef GROUP_OBJ -#endif - -#endif /* BROKEN_NISPLUS_INCLUDE_FILES */ - -#include - -#else /* !WITH_NISPLUS_HOME */ - -#include "rpcsvc/ypclnt.h" - -#endif /* WITH_NISPLUS_HOME */ -#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */ - - /**************************************************************************n Find a suitable temporary directory. The result should be copied immediately as it may be overwritten by a subsequent call. -- cgit From 64cdbddbc1e0f63302aee4f02213d7a771feb315 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Feb 2004 15:31:25 +0000 Subject: don't inlcude rpc/rpc.h and rpcsvc/*.h anymore and remove NET_GROUP stuff, this needs to be implemented in a better way if we ever readd this metze (This used to be commit da5f22976fb40ec96160439c7a926a15805fc7f0) --- source4/lib/username.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/username.c b/source4/lib/username.c index 084d7e0bdb..2d6cd651c5 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -178,35 +178,6 @@ struct passwd *Get_Pwnam(const char *user) return ret; } -/**************************************************************************** - Check if a user is in a netgroup user list. -****************************************************************************/ - -static BOOL user_in_netgroup_list(const char *user, const char *ngname) -{ -#ifdef HAVE_NETGROUP - /* static char *mydomain = NULL; */ - /* REWRITE: make thread safe if caching */ - char *mydomain = NULL; - /*if (mydomain == NULL) */ - yp_get_default_domain(&mydomain); - - if(mydomain == NULL) { - DEBUG(5,("Unable to get default yp domain\n")); - return False; - } - - DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", - user, mydomain, ngname)); - DEBUG(5,("innetgr is %s\n", innetgr(ngname, NULL, user, mydomain) - ? "TRUE" : "FALSE")); - - if (innetgr(ngname, NULL, user, mydomain)) - return (True); -#endif /* HAVE_NETGROUP */ - return False; -} - /**************************************************************************** Check if a user is in a winbind group. ****************************************************************************/ @@ -398,8 +369,6 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr * Old behaviour. Check netgroup list * followed by UNIX list. */ - if(user_in_netgroup_list(user, *list +1)) - return True; if(user_in_group_list(user, *list +1, groups, n_groups)) return True; } else if (**list == '+') { @@ -410,9 +379,6 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr */ if(user_in_group_list(user, *list +2, groups, n_groups)) return True; - if(user_in_netgroup_list(user, *list +2)) - return True; - } else { /* @@ -429,16 +395,8 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr /* * Search netgroup list followed by UNIX list. */ - if(user_in_netgroup_list(user, *list +2)) - return True; if(user_in_group_list(user, *list +2, groups, n_groups)) return True; - } else { - /* - * Just search netgroup list. - */ - if(user_in_netgroup_list(user, *list +1)) - return True; } } else if (!name_is_local(*list)) { /* -- cgit From 42887e406a8751f9f852292d175682c5743d03ae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 22 Feb 2004 13:09:51 +0000 Subject: - creat the LIBCMDLINE subsystem including readline and popt - creat the CONFIG subsystem including param/* dynconfig.* and passdb/secrets.* metze (This used to be commit bfd7fd21c8e38c0065fc41dde10e863a169878c2) --- source4/lib/cmdline/config.m4 | 79 ++++++++++ source4/lib/popt_common.c | 334 ------------------------------------------ source4/lib/readline.c | 159 -------------------- 3 files changed, 79 insertions(+), 493 deletions(-) create mode 100644 source4/lib/cmdline/config.m4 delete mode 100644 source4/lib/popt_common.c delete mode 100644 source4/lib/readline.c (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 new file mode 100644 index 0000000000..6e9a8f4508 --- /dev/null +++ b/source4/lib/cmdline/config.m4 @@ -0,0 +1,79 @@ +################################################# + +############################################### +# Readline included by default unless explicitly asked not to +test "${with_readline+set}" != "set" && with_readline=yes + +# test for where we get readline() from +AC_MSG_CHECKING(whether to use readline) +AC_ARG_WITH(readline, +[ --with-readline[=DIR] Look for readline include/libs in DIR (default=auto) ], +[ case "$with_readline" in + yes) + AC_MSG_RESULT(yes) + + AC_CHECK_HEADERS(readline.h history.h readline/readline.h) + AC_CHECK_HEADERS(readline/history.h) + + AC_CHECK_HEADERS(readline.h readline/readline.h,[ + for termlib in ncurses curses termcap terminfo termlib tinfo; do + AC_CHECK_LIB(${termlib}, tgetent, [TERMLIBS="-l${termlib}"; break]) + done + AC_CHECK_LIB(readline, rl_callback_handler_install, + [TERMLIBS="-lreadline $TERMLIBS" + AC_DEFINE(HAVE_LIBREADLINE,1,[Whether the system has readline]) + break], [TERMLIBS=], $TERMLIBS)]) + ;; + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + + # Needed for AC_CHECK_HEADERS and AC_CHECK_LIB to look at + # alternate readline path + _ldflags=${LDFLAGS} + _cppflags=${CPPFLAGS} + + # Add additional search path + LDFLAGS="-L$with_readline/lib $LDFLAGS" + CPPFLAGS="-I$with_readline/include $CPPFLAGS" + + AC_CHECK_HEADERS(readline.h history.h readline/readline.h) + AC_CHECK_HEADERS(readline/history.h) + + AC_CHECK_HEADERS(readline.h readline/readline.h,[ + for termlib in ncurses curses termcap terminfo termlib; do + AC_CHECK_LIB(${termlib}, tgetent, [TERMLIBS="-l${termlib}"; break]) + done + AC_CHECK_LIB(readline, rl_callback_handler_install, + [TERMLDFLAGS="-L$with_readline/lib" + TERMCPPFLAGS="-I$with_readline/include" + LDFLAGS="-L$with_readline/lib $LDFLAGS" + CPPFLAGS="-I$with_readline/include $CPPFLAGS" + TERMLIBS="-lreadline $TERMLIBS" + AC_DEFINE(HAVE_LIBREADLINE,1,[Whether the system has readline]) + break], [TERMLIBS= CPPFLAGS=$_cppflags], $TERMLIBS)]) + + ;; + esac], + AC_MSG_RESULT(no) +) + +# The readline API changed slightly from readline3 to readline4, so +# code will generate warnings on one of them unless we have a few +# special cases. +AC_CHECK_LIB(readline, rl_completion_matches, + [AC_DEFINE(HAVE_NEW_LIBREADLINE, 1, + [Do we have rl_completion_matches?])], + [], + [$TERMLIBS]) + +TMP_LIBCMDLINE_OBJS="lib/cmdline/readline.o lib/cmdline/popt_common.o" +TMP_LIBCMDLINE_LIBS="$TERMLIBS" + +SMB_SUBSYSTEM(LIBCMDLINE,[], + [${TMP_LIBCMDLINE_OBJS}], + [], + [], + [${TMP_LIBCMDLINE_LIBS}]) diff --git a/source4/lib/popt_common.c b/source4/lib/popt_common.c deleted file mode 100644 index 1b8e3bd93e..0000000000 --- a/source4/lib/popt_common.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Common popt routines - - Copyright (C) Tim Potter 2001,2002 - Copyright (C) Jelmer Vernooij 2002,2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* Handle command line options: - * -d,--debuglevel - * -s,--configfile - * -O,--socket-options - * -V,--version - * -l,--log-base - * -n,--netbios-name - * -W,--workgroup - * -i,--scope - */ - -extern pstring user_socket_options; -extern BOOL AllowDebugChange; - -struct user_auth_info cmdline_auth_info; - -static void popt_common_callback(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, const void *data) -{ - pstring logfile; - const char *pname; - - /* Find out basename of current program */ - pname = strrchr_m(poptGetInvocationName(con),'/'); - - if (!pname) - pname = poptGetInvocationName(con); - else - pname++; - - if (reason == POPT_CALLBACK_REASON_PRE) { - pstr_sprintf(logfile, "%s/log.%s", dyn_LOGFILEBASE, pname); - lp_set_cmdline("log file", logfile); - return; - } - - switch(opt->val) { - case 'd': - lp_set_cmdline("log level", arg); - break; - - case 'V': - printf( "Version %s\n", SAMBA_VERSION_STRING ); - exit(0); - break; - - case 's': - if (arg) { - pstrcpy(dyn_CONFIGFILE, arg); - } - break; - - case 'l': - if (arg) { - pstr_sprintf(logfile, "%s/log.%s", arg, pname); - lp_set_cmdline("log file", logfile); - } - break; - - case 'W': - lp_set_cmdline("workgroup", arg); - break; - - case 'n': - lp_set_cmdline("netbios name", arg); - break; - - case 'i': - lp_set_cmdline("netbios scope", arg); - break; - - case 'm': - lp_set_cmdline("max protocol", arg); - break; - } -} - -struct poptOption popt_common_connection[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, - { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", - "SOCKETOPTIONS" }, - { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, - { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, - { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, - { "maxprotocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set max protocol level", "MAXPROTOCOL" }, - POPT_TABLEEND -}; - -struct poptOption popt_common_samba[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, - { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, - { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, - { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, - { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, - POPT_TABLEEND -}; - -struct poptOption popt_common_version[] = { - { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, - { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, - POPT_TABLEEND -}; - - - -/**************************************************************************** - * get a password from a a file or file descriptor - * exit on failure - * ****************************************************************************/ -static void get_password_file(struct user_auth_info *a) -{ - int fd = -1; - char *p; - BOOL close_it = False; - pstring spec; - char pass[128]; - - if ((p = getenv("PASSWD_FD")) != NULL) { - pstrcpy(spec, "descriptor "); - pstrcat(spec, p); - sscanf(p, "%d", &fd); - close_it = False; - } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = sys_open(p, O_RDONLY, 0); - pstrcpy(spec, p); - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - spec, strerror(errno)); - exit(1); - } - close_it = True; - } - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, "empty password\n"); - exit(1); - } - - default: - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, strerror(errno)); - exit(1); - } - } - pstrcpy(a->password, pass); - if (close_it) - close(fd); -} - -static void get_credentials_file(const char *file, struct user_auth_info *info) -{ - XFILE *auth; - fstring buf; - uint16 len = 0; - char *ptr, *val, *param; - - if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) - { - /* fail if we can't open the credentials file */ - d_printf("ERROR: Unable to open credentials file!\n"); - exit(-1); - } - - while (!x_feof(auth)) - { - /* get a line from the file */ - if (!x_fgets(buf, sizeof(buf), auth)) - continue; - len = strlen(buf); - - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } - if (len == 0) - continue; - - /* break up the line into parameter & value. - * will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr_m (buf, '='))) - continue; - - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) - { - pstrcpy(info->password, val); - info->got_pass = True; - } - else if (strwicmp("username", param) == 0) - pstrcpy(info->username, val); -#if 0 - else if (strwicmp("domain", param) == 0) - set_global_myworkgroup(val); -#endif - memset(buf, 0, sizeof(buf)); - } - x_fclose(auth); -} - -/* Handle command line options: - * -U,--user - * -A,--authentication-file - * -k,--use-kerberos - * -N,--no-pass - */ - - -static void popt_common_credentials_callback(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, const void *data) -{ - char *p; - - if (reason == POPT_CALLBACK_REASON_PRE) { - cmdline_auth_info.use_kerberos = False; - cmdline_auth_info.got_pass = False; - pstrcpy(cmdline_auth_info.username, "GUEST"); - - if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); - - if (getenv("USER")) { - pstrcpy(cmdline_auth_info.username,getenv("USER")); - - if ((p = strchr_m(cmdline_auth_info.username,'%'))) { - *p = 0; - pstrcpy(cmdline_auth_info.password,p+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); - } - } - - if (getenv("PASSWD")) { - pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); - cmdline_auth_info.got_pass = True; - } - - if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { - get_password_file(&cmdline_auth_info); - cmdline_auth_info.got_pass = True; - } - - return; - } - - switch(opt->val) { - case 'U': - { - char *lp; - - pstrcpy(cmdline_auth_info.username,arg); - if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { - *lp = 0; - pstrcpy(cmdline_auth_info.password,lp+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); - } - } - break; - - case 'A': - get_credentials_file(arg, &cmdline_auth_info); - break; - - case 'k': -#ifndef HAVE_KRB5 - d_printf("No kerberos support compiled in\n"); - exit(1); -#else - cmdline_auth_info.use_kerberos = True; - cmdline_auth_info.got_pass = True; -#endif - break; - } -} - - - -struct poptOption popt_common_credentials[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, - { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, - { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, - POPT_TABLEEND -}; diff --git a/source4/lib/readline.c b/source4/lib/readline.c deleted file mode 100644 index c5da88b3e0..0000000000 --- a/source4/lib/readline.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba readline wrapper implementation - Copyright (C) Simo Sorce 2001 - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#ifdef HAVE_LIBREADLINE -# ifdef HAVE_READLINE_READLINE_H -# include -# ifdef HAVE_READLINE_HISTORY_H -# include -# endif -# else -# ifdef HAVE_READLINE_H -# include -# ifdef HAVE_HISTORY_H -# include -# endif -# else -# undef HAVE_LIBREADLINE -# endif -# endif -#endif - -#ifdef HAVE_NEW_LIBREADLINE -# define RL_COMPLETION_CAST (rl_completion_func_t *) -#else -/* This type is missing from libreadline<4.0 (approximately) */ -# define RL_COMPLETION_CAST -#endif /* HAVE_NEW_LIBREADLINE */ - -/**************************************************************************** - Display the prompt and wait for input. Call callback() regularly -****************************************************************************/ - -static char *smb_readline_replacement(const char *prompt, void (*callback)(void), - char **(completion_fn)(const char *text, int start, int end)) -{ - fd_set fds; - static pstring line; - struct timeval timeout; - int fd = x_fileno(x_stdin); - char *ret; - - do_debug("%s", prompt); - - while (1) { - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - - if (sys_select_intr(fd+1,&fds,NULL,NULL,&timeout) == 1) { - ret = x_fgets(line, sizeof(line), x_stdin); - return ret; - } - if (callback) - callback(); - } -} - -/**************************************************************************** - Display the prompt and wait for input. Call callback() regularly. -****************************************************************************/ - -char *smb_readline(const char *prompt, void (*callback)(void), - char **(completion_fn)(const char *text, int start, int end)) -{ -#if HAVE_LIBREADLINE - if (isatty(x_fileno(x_stdin))) { - char *ret; - - /* Aargh! Readline does bizzare things with the terminal width - that mucks up expect(1). Set CLI_NO_READLINE in the environment - to force readline not to be used. */ - - if (getenv("CLI_NO_READLINE")) - return smb_readline_replacement(prompt, callback, completion_fn); - - if (completion_fn) { - /* The callback prototype has changed slightly between - different versions of Readline, so the same function - works in all of them to date, but we get compiler - warnings in some. */ - rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; - } - - if (callback) - rl_event_hook = (Function *)callback; - ret = readline(prompt); - if (ret && *ret) - add_history(ret); - return ret; - } else -#endif - return smb_readline_replacement(prompt, callback, completion_fn); -} - -/**************************************************************************** - * return line buffer text - ****************************************************************************/ -const char *smb_readline_get_line_buffer(void) -{ -#if defined(HAVE_LIBREADLINE) - return rl_line_buffer; -#else - return NULL; -#endif -} - -/**************************************************************************** - * set completion append character - ***************************************************************************/ -void smb_readline_ca_char(char c) -{ -#if defined(HAVE_LIBREADLINE) - rl_completion_append_character = c; -#endif -} - - -/**************************************************************************** -history -****************************************************************************/ -int cmd_history(void) -{ -#if defined(HAVE_LIBREADLINE) - HIST_ENTRY **hlist; - int i; - - hlist = history_list(); - - for (i = 0; hlist && hlist[i]; i++) { - DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); - } -#else - DEBUG(0,("no history without readline support\n")); -#endif - - return 0; -} -- cgit From 2027b1922b01d3b6af17d24ae51d33cc7048d27d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Feb 2004 06:49:59 +0000 Subject: let the popt replacement stuff survive a make proto metze (This used to be commit 0f1c6dd631c7a1d4be333b8e3e4ce9850752d5c2) --- source4/lib/popt/findme.c | 3 ++- source4/lib/popt/popt.c | 54 ++++++++++++++++++++++++++++--------------- source4/lib/popt/poptconfig.c | 10 ++++---- source4/lib/popt/popthelp.c | 33 +++++++++++++++++--------- source4/lib/popt/poptparse.c | 4 ++-- 5 files changed, 67 insertions(+), 37 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/findme.c b/source4/lib/popt/findme.c index f2ad05bb3f..67a535ac65 100644 --- a/source4/lib/popt/findme.c +++ b/source4/lib/popt/findme.c @@ -5,7 +5,8 @@ #include "system.h" #include "findme.h" -const char * findProgramPath(const char * argv0) { + const char * findProgramPath(const char * argv0) +{ char * path = getenv("PATH"); char * pathbuf; char * start, * chptr; diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c index 9fa8650312..2aa80a7b7c 100644 --- a/source4/lib/popt/popt.c +++ b/source4/lib/popt/popt.c @@ -18,14 +18,16 @@ static char * strerror(int errno) { } #endif -void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) { + void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) +{ if (con->execPath) xfree(con->execPath); con->execPath = xstrdup(path); con->execAbsolute = allowAbsolute; } static void invokeCallbacks(poptContext con, const struct poptOption * table, - int post) { + int post) +{ const struct poptOption * opt = table; poptCallbackType cb; @@ -43,8 +45,9 @@ static void invokeCallbacks(poptContext con, const struct poptOption * table, } } -poptContext poptGetContext(const char * name, int argc, const char ** argv, - const struct poptOption * options, int flags) { + poptContext poptGetContext(const char * name, int argc, const char ** argv, + const struct poptOption * options, int flags) +{ poptContext con = malloc(sizeof(*con)); memset(con, 0, sizeof(*con)); @@ -96,7 +99,8 @@ static void cleanOSE(struct optionStackEntry *os) } } -void poptResetContext(poptContext con) { +void poptResetContext(poptContext con) +{ int i; while (con->os > con->optionStack) { @@ -132,7 +136,8 @@ void poptResetContext(poptContext con) { } /* Only one of longName, shortName may be set at a time */ -static int handleExec(poptContext con, char * longName, char shortName) { +static int handleExec(poptContext con, char * longName, char shortName) +{ int i; i = con->numExecs - 1; @@ -176,7 +181,8 @@ static int handleExec(poptContext con, char * longName, char shortName) { /* Only one of longName, shortName may be set at a time */ static int handleAlias(poptContext con, const char * longName, char shortName, - /*@keep@*/ const char * nextCharArg) { + /*@keep@*/ const char * nextCharArg) +{ int i; if (con->os->currAlias && con->os->currAlias->longName && longName && @@ -216,7 +222,8 @@ static int handleAlias(poptContext con, const char * longName, char shortName, return 1; } -static void execCommand(poptContext con) { +static void execCommand(poptContext con) +{ const char ** argv; int pos = 0; const char * script = con->doExec->script; @@ -616,23 +623,27 @@ int poptGetNextOpt(poptContext con) return opt->val; } -const char * poptGetOptArg(poptContext con) { + const char * poptGetOptArg(poptContext con) +{ const char * ret = con->os->nextArg; con->os->nextArg = NULL; return ret; } -const char * poptGetArg(poptContext con) { + const char * poptGetArg(poptContext con) +{ if (con->numLeftovers == con->nextLeftover) return NULL; return con->leftovers[con->nextLeftover++]; } -const char * poptPeekArg(poptContext con) { + const char * poptPeekArg(poptContext con) +{ if (con->numLeftovers == con->nextLeftover) return NULL; return con->leftovers[con->nextLeftover]; } -const char ** poptGetArgs(poptContext con) { + const char ** poptGetArgs(poptContext con) +{ if (con->numLeftovers == con->nextLeftover) return NULL; /* some apps like [like RPM ;-) ] need this NULL terminated */ @@ -641,7 +652,8 @@ const char ** poptGetArgs(poptContext con) { return (con->leftovers + con->nextLeftover); } -void poptFreeContext(poptContext con) { + void poptFreeContext(poptContext con) +{ int i; poptResetContext(con); @@ -669,7 +681,7 @@ void poptFreeContext(poptContext con) { free(con); } -int poptAddAlias(poptContext con, struct poptAlias newAlias, + int poptAddAlias(poptContext con, struct poptAlias newAlias, /*@unused@*/ int flags) { int aliasNum = con->numAliases++; @@ -693,7 +705,8 @@ int poptAddAlias(poptContext con, struct poptAlias newAlias, return 0; } -const char * poptBadOption(poptContext con, int flags) { + const char * poptBadOption(poptContext con, int flags) +{ struct optionStackEntry * os; if (flags & POPT_BADOPTION_NOALIAS) @@ -710,7 +723,8 @@ const char * poptBadOption(poptContext con, int flags) { #define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ #define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ -const char *poptStrerror(const int error) { + const char *poptStrerror(const int error) +{ switch (error) { case POPT_ERROR_NOARG: return POPT_("missing argument"); @@ -731,7 +745,8 @@ const char *poptStrerror(const int error) { } } -int poptStuffArgs(poptContext con, const char ** argv) { + int poptStuffArgs(poptContext con, const char ** argv) +{ int argc; if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) @@ -752,11 +767,12 @@ int poptStuffArgs(poptContext con, const char ** argv) { return 0; } -const char * poptGetInvocationName(poptContext con) { + const char * poptGetInvocationName(poptContext con) +{ return con->os->argv[0]; } -int poptStrippedArgv(poptContext con, int argc, char **argv) + int poptStrippedArgv(poptContext con, int argc, char **argv) { int i,j=1, numargs=argc; diff --git a/source4/lib/popt/poptconfig.c b/source4/lib/popt/poptconfig.c index eb76941363..113270a569 100644 --- a/source4/lib/popt/poptconfig.c +++ b/source4/lib/popt/poptconfig.c @@ -5,7 +5,8 @@ #include "system.h" #include "poptint.h" -static void configLine(poptContext con, char * line) { +static void configLine(poptContext con, char * line) +{ int nameLength = strlen(con->appName); char * opt; struct poptAlias alias; @@ -54,7 +55,8 @@ static void configLine(poptContext con, char * line) { } } -int poptReadConfigFile(poptContext con, const char * fn) { + int poptReadConfigFile(poptContext con, const char * fn) +{ char * file=NULL, * chptr, * end; char * buf=NULL, * dst; int fd, rc; @@ -118,7 +120,8 @@ int poptReadConfigFile(poptContext con, const char * fn) { return 0; } -int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { + int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) +{ char * fn, * home; int rc; @@ -139,4 +142,3 @@ int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { return 0; } - diff --git a/source4/lib/popt/popthelp.c b/source4/lib/popt/popthelp.c index 6b790a63e7..562995c011 100644 --- a/source4/lib/popt/popthelp.c +++ b/source4/lib/popt/popthelp.c @@ -10,7 +10,8 @@ static void displayArgs(poptContext con, /*@unused@*/ enum poptCallbackReason foo, struct poptOption * key, - /*@unused@*/ const char * arg, /*@unused@*/ void * data) { + /*@unused@*/ const char * arg, /*@unused@*/ void * data) +{ if (key->shortName== '?') poptPrintHelp(con, stdout, 0); else @@ -55,7 +56,8 @@ getArgDescrip(const struct poptOption * opt, const char *translation_domain) static void singleOptionHelp(FILE * f, int maxLeftCol, const struct poptOption * opt, - const char *translation_domain) { + const char *translation_domain) +{ int indentLength = maxLeftCol + 5; int lineLength = 79 - indentLength; const char * help = D_(translation_domain, opt->descrip); @@ -109,7 +111,8 @@ out: } static int maxArgWidth(const struct poptOption * opt, - const char * translation_domain) { + const char * translation_domain) +{ int max = 0; int this; const char * s; @@ -139,7 +142,8 @@ static int maxArgWidth(const struct poptOption * opt, static void singleTableHelp(FILE * f, const struct poptOption * table, int left, - const char *translation_domain) { + const char *translation_domain) +{ const struct poptOption * opt; const char *sub_transdom; @@ -167,7 +171,8 @@ static void singleTableHelp(FILE * f, const struct poptOption * table, } } -static int showHelpIntro(poptContext con, FILE * f) { +static int showHelpIntro(poptContext con, FILE * f) +{ int len = 6; const char * fn; @@ -182,7 +187,8 @@ static int showHelpIntro(poptContext con, FILE * f) { return len; } -void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) { + void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) +{ int leftColWidth; showHelpIntro(con, f); @@ -197,7 +203,8 @@ void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) { static int singleOptionUsage(FILE * f, int cursor, const struct poptOption * opt, - const char *translation_domain) { + const char *translation_domain) +{ int len = 3; char shortStr[2] = { '\0', '\0' }; const char * item = shortStr; @@ -232,7 +239,8 @@ static int singleOptionUsage(FILE * f, int cursor, } static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table, - const char *translation_domain) { + const char *translation_domain) +{ const struct poptOption * opt; opt = table; @@ -253,7 +261,8 @@ static int singleTableUsage(FILE * f, int cursor, const struct poptOption * tabl } static int showShortOptions(const struct poptOption * opt, FILE * f, - char * str) { + char * str) +{ char s[300]; /* this is larger then the ascii set, so it should do just fine */ @@ -279,7 +288,8 @@ static int showShortOptions(const struct poptOption * opt, FILE * f, return strlen(s) + 4; } -void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) { + void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) +{ int cursor; cursor = showHelpIntro(con, f); @@ -295,7 +305,8 @@ void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) { fprintf(f, "\n"); } -void poptSetOtherOptionHelp(poptContext con, const char * text) { + void poptSetOtherOptionHelp(poptContext con, const char * text) +{ if (con->otherHelp) xfree(con->otherHelp); con->otherHelp = xstrdup(text); } diff --git a/source4/lib/popt/poptparse.c b/source4/lib/popt/poptparse.c index 8f00769be9..93bf7acfb8 100644 --- a/source4/lib/popt/poptparse.c +++ b/source4/lib/popt/poptparse.c @@ -6,7 +6,7 @@ #define POPT_ARGV_ARRAY_GROW_DELTA 5 -int poptDupArgv(int argc, const char **argv, + int poptDupArgv(int argc, const char **argv, int * argcPtr, const char *** argvPtr) { size_t nb = (argc + 1) * sizeof(*argv); @@ -35,7 +35,7 @@ int poptDupArgv(int argc, const char **argv, return 0; } -int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) + int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * src; char quote = '\0'; -- cgit From 2622eaeca67edd0ff23ff34fc65b8db1f1d2fe83 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Feb 2004 06:53:53 +0000 Subject: make proto should not catch any function of the lib/popt/*.c stuff metze (This used to be commit ec96914c66573ae54f4fa0a706001f5b91c61075) --- source4/lib/popt/popt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c index 2aa80a7b7c..a607f19f2f 100644 --- a/source4/lib/popt/popt.c +++ b/source4/lib/popt/popt.c @@ -99,7 +99,7 @@ static void cleanOSE(struct optionStackEntry *os) } } -void poptResetContext(poptContext con) + void poptResetContext(poptContext con) { int i; @@ -400,7 +400,7 @@ static void poptStripArg(poptContext con, int which) } /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ -int poptGetNextOpt(poptContext con) + int poptGetNextOpt(poptContext con) { const struct poptOption * opt = NULL; int done = 0; -- cgit From 4217c609a8c932967aa2641c5e24dde413efb575 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 01:30:54 +0000 Subject: removed the state parameter to tdb_traverse and the TDB_MODIFY flag (This used to be commit 6505efc7e9bfcdae3e370d8557328470608b87ca) --- source4/lib/tdb/tdb.c | 11 +++-------- source4/lib/tdb/tdb.h | 8 ++++---- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index fc210f42d4..1fef5d54fa 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -2,7 +2,6 @@ Unix SMB/CIFS implementation. Samba database functions Copyright (C) Andrew Tridgell 1999-2000 - Copyright (C) Luke Kenneth Casson Leighton 2000 Copyright (C) Paul `Rusty' Russell 2000 Copyright (C) Jeremy Allison 2000-2003 @@ -1293,7 +1292,7 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, if fn is NULL then it is not called a non-zero return value from fn() indicates that the traversal should stop */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state) +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn) { TDB_DATA key, dbuf; struct list_struct rec; @@ -1331,7 +1330,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state) ret = -1; goto out; } - if (fn && fn(tdb, key, dbuf, state)) { + if (fn && fn(tdb, key, dbuf)) { /* They want us to terminate traversal */ ret = count; if (unlock_record(tdb, tl.off) != 0) { @@ -1480,8 +1479,6 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* first try in-place update, on modify or replace. */ if (tdb_update_hash(tdb, key, hash, dbuf) == 0) goto out; - if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST) - goto fail; } /* reset the error code potentially set by the tdb_update() */ tdb->ecode = TDB_SUCCESS; @@ -1504,9 +1501,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) if (dbuf.dsize) memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); - /* now we're into insert / modify / replace of a record which - * we know could not be optimised by an in-place store (for - * various reasons). */ + /* we have to allocate some space */ if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec))) goto fail; diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index 720066f1b3..d20f4cd677 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -29,7 +29,6 @@ extern "C" { /* flags to tdb_store() */ #define TDB_REPLACE 1 #define TDB_INSERT 2 -#define TDB_MODIFY 3 /* flags for tdb_open() */ #define TDB_DEFAULT 0 /* just a readability place holder */ @@ -44,7 +43,8 @@ extern "C" { /* error codes */ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, - TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT }; + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST}; #ifndef u32 #define u32 unsigned @@ -98,7 +98,7 @@ typedef struct tdb_context { int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; -typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); +typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA); typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, @@ -119,7 +119,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); int tdb_close(TDB_CONTEXT *tdb); TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state); +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn); int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); void tdb_unlockkeys(TDB_CONTEXT *tdb); -- cgit From 2fe43ec90f6c76ced5e697f4a26630bd72accdc5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 01:33:32 +0000 Subject: added a private pointer to tdb_traverse() to allow callers to supply data to their traverse function (This used to be commit 76bf816485bf869c293791659da5dff2425d2d32) --- source4/lib/tdb/tdb.c | 4 ++-- source4/lib/tdb/tdb.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 1fef5d54fa..8fbf128914 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -1292,7 +1292,7 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, if fn is NULL then it is not called a non-zero return value from fn() indicates that the traversal should stop */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn) +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private) { TDB_DATA key, dbuf; struct list_struct rec; @@ -1330,7 +1330,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn) ret = -1; goto out; } - if (fn && fn(tdb, key, dbuf)) { + if (fn && fn(tdb, key, dbuf, private)) { /* They want us to terminate traversal */ ret = count; if (unlock_record(tdb, tl.off) != 0) { diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index d20f4cd677..b3a28b7440 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -98,7 +98,7 @@ typedef struct tdb_context { int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; -typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA); +typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, @@ -119,7 +119,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); int tdb_close(TDB_CONTEXT *tdb); TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn); +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); void tdb_unlockkeys(TDB_CONTEXT *tdb); -- cgit From ad15f42b6d50eff9199aef7497d24b2c9167fea1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 01:38:42 +0000 Subject: added a TDB_MODIFY flag to tdb_store() that says "if the record doesn't exist then fail the store" (This used to be commit 6aec1457f8772cf81b88a0a00cc2ad7c16cd0d87) --- source4/lib/tdb/tdb.c | 6 ++++++ source4/lib/tdb/tdb.h | 1 + 2 files changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 8fbf128914..5f57f05778 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -1479,6 +1479,12 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* first try in-place update, on modify or replace. */ if (tdb_update_hash(tdb, key, hash, dbuf) == 0) goto out; + if (tdb->ecode == TDB_ERR_NOEXIST && + flag == TDB_MODIFY) { + /* if the record doesn't exist and we are in TDB_MODIFY mode then + we should fail the store */ + goto fail; + } } /* reset the error code potentially set by the tdb_update() */ tdb->ecode = TDB_SUCCESS; diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index b3a28b7440..b7c51b5519 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -29,6 +29,7 @@ extern "C" { /* flags to tdb_store() */ #define TDB_REPLACE 1 #define TDB_INSERT 2 +#define TDB_MODIFY 3 /* flags for tdb_open() */ #define TDB_DEFAULT 0 /* just a readability place holder */ -- cgit From 3744324dbd29ca3c732a3d82fab1c0ee94598eaf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 01:43:06 +0000 Subject: after discussion with the copyright holders tdb is now under the LGPL (This used to be commit 51409e2a417fb0673f59e5c823d7fe54b21e6f76) --- source4/lib/tdb/spinlock.c | 30 ++++++++++++++++++------------ source4/lib/tdb/tdb.c | 32 +++++++++++++++++++------------- source4/lib/tdb/tdb.h | 32 +++++++++++++++++++------------- 3 files changed, 56 insertions(+), 38 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c index 3fddeafb2c..dc7fa3b784 100644 --- a/source4/lib/tdb/spinlock.c +++ b/source4/lib/tdb/spinlock.c @@ -1,21 +1,27 @@ /* Unix SMB/CIFS implementation. - Samba database functions + + trivial database library + Copyright (C) Anton Blanchard 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 - (at your option) any later version. + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if HAVE_CONFIG_H #include diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 5f57f05778..0bcf4d5cb8 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -1,23 +1,29 @@ /* Unix SMB/CIFS implementation. - Samba database functions - Copyright (C) Andrew Tridgell 1999-2000 + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 Copyright (C) Paul `Rusty' Russell 2000 Copyright (C) Jeremy Allison 2000-2003 - 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 - (at your option) any later version. + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index b7c51b5519..c9faa0464f 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -3,22 +3,28 @@ /* Unix SMB/CIFS implementation. - Samba database functions - Copyright (C) Andrew Tridgell 1999 + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 - 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 - (at your option) any later version. + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __cplusplus -- cgit From 9403f3dc7e977d53efe1439ec20461bbc4935fe5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 01:57:28 +0000 Subject: switch from SIG_ATOMIC_T to sig_atomic_t (This used to be commit b881b72cb9cb5a4a8ad27b621e8cbe9dcfa7ba7f) --- source4/lib/tdb/tdb.c | 4 ++-- source4/lib/tdb/tdb.h | 2 +- source4/lib/tdb/tdbutil.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 0bcf4d5cb8..5367842cbb 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -194,9 +194,9 @@ struct list_struct { a blocking lock on SIGALRM. ***************************************************************/ -static SIG_ATOMIC_T *palarm_fired; +static sig_atomic_t *palarm_fired; -void tdb_set_lock_alarm(SIG_ATOMIC_T *palarm) +void tdb_set_lock_alarm(sig_atomic_t *palarm) { palarm_fired = palarm; } diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index c9faa0464f..169de5f87d 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -134,7 +134,7 @@ int tdb_lockall(TDB_CONTEXT *tdb); void tdb_unlockall(TDB_CONTEXT *tdb); /* Low level locking functions: use with care */ -void tdb_set_lock_alarm(SIG_ATOMIC_T *palarm); +void tdb_set_lock_alarm(sig_atomic_t *palarm); int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index 3c22333b4d..4a4423d2ce 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -24,7 +24,7 @@ /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ -static SIG_ATOMIC_T gotalarm; +static sig_atomic_t gotalarm; /*************************************************************** Signal function to tell us we timed out. -- cgit From 4aa785b1b23d0add18d5fec6fb6c5b37a6feecac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Mar 2004 02:18:38 +0000 Subject: merge some recent tdb changed from samba3 (This used to be commit 0e845ecd49841c620f7f9c5ba6c5bfbb0c572032) --- source4/lib/tdb/spinlock.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ source4/lib/tdb/tdb.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c index dc7fa3b784..1b789d4daa 100644 --- a/source4/lib/tdb/spinlock.c +++ b/source4/lib/tdb/spinlock.c @@ -149,6 +149,47 @@ static inline int __spin_is_locked(spinlock_t *lock) return (*lock != 1); } +#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730) + +/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See + * sync(3) for the details of the intrinsic operations. + * + * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. + */ + +#if defined(STANDALONE) + +/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ +#define inline __inline + +#endif /* STANDALONE */ + +/* Returns 0 if the lock is acquired, EBUSY otherwise. */ +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int val; + val = __lock_test_and_set(lock, 1); + return val == 0 ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + __lock_release(lock); +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + __lock_release(lock); +} + +/* Returns 1 if the lock is held, 0 otherwise. */ +static inline int __spin_is_locked(spinlock_t *lock) +{ + unsigned int val; + val = __add_and_fetch(lock, 0); + return val; +} + #elif defined(MIPS_SPINLOCKS) static inline unsigned int load_linked(unsigned long addr) @@ -227,7 +268,11 @@ static void yield_cpu(void) static int this_is_smp(void) { +#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN) + return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0; +#else return 0; +#endif } /* diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 5367842cbb..47ba2cb52c 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -247,10 +247,14 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, tdb->fd, offset, rw_type, lck_type)); return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); } - /* Otherwise - generic lock error. */ - /* errno set by fcntl */ + /* Otherwise - generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (errno != EAGAIN) { TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, strerror(errno))); + tdb->fd, offset, rw_type, lck_type, + strerror(errno))); + } return TDB_ERRCODE(TDB_ERR_LOCK, -1); } return 0; @@ -858,6 +862,8 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, tdb_off rec_ptr, last_ptr, newrec_ptr; struct list_struct newrec; + memset(&newrec, '\0', sizeof(newrec)); + if (tdb_lock(tdb, -1, F_WRLCK) == -1) return 0; @@ -1706,7 +1712,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, { TDB_CONTEXT *tdb; struct stat st; - int rev = 0, locked; + int rev = 0, locked = 0; unsigned char *vp; u32 vertest; @@ -1764,8 +1770,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } /* we need to zero database if we are the only one with it open */ - if ((locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0)) - && (tdb_flags & TDB_CLEAR_IF_FIRST)) { + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { open_flags |= O_CREAT; if (ftruncate(tdb->fd, 0) == -1) { TDB_LOG((tdb, 0, "tdb_open_ex: " @@ -1838,10 +1844,19 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, name, strerror(errno))); goto fail; } + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { /* leave this lock in place to indicate it's in use */ if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) goto fail; + } + internal: /* Internal (memory-only) databases skip all the code above to @@ -2019,12 +2034,14 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons } -/* reopen a tdb - this is used after a fork to ensure that we have an independent +/* reopen a tdb - this can be used after a fork to ensure that we have an independent seek pointer from our parent and to re-establish locks */ int tdb_reopen(TDB_CONTEXT *tdb) { struct stat st; + if (tdb->flags & TDB_INTERNAL) + return 0; /* Nothing to do. */ if (tdb_munmap(tdb) != 0) { TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); goto fail; @@ -2045,7 +2062,7 @@ int tdb_reopen(TDB_CONTEXT *tdb) goto fail; } tdb_mmap(tdb); - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { + if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); goto fail; } @@ -2063,7 +2080,10 @@ int tdb_reopen_all(void) TDB_CONTEXT *tdb; for (tdb=tdbs; tdb; tdb = tdb->next) { - if (tdb_reopen(tdb) != 0) return -1; + /* Ensure no clear-if-first. */ + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_reopen(tdb) != 0) + return -1; } return 0; -- cgit From 58d50a614f1b4a3fc6b60ad5f777d987263fe54f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 31 Mar 2004 06:45:39 +0000 Subject: make a more recent snapshot of ldb available to interested people. Note that I decided to make it LGPL. ldb is not finished yet, but enough of it is there for people to get an idea of what it does, and quite a few simple tests work (This used to be commit dc6f41f9e777d37f883303ddef0d96840d80f78e) --- source4/lib/ldb/Makefile.ldb | 43 +++ source4/lib/ldb/common/ldb.c | 129 +++++++ source4/lib/ldb/common/ldb_ldif.c | 476 +++++++++++++++++++++++++ source4/lib/ldb/common/ldb_parse.c | 460 ++++++++++++++++++++++++ source4/lib/ldb/common/util.c | 102 ++++++ source4/lib/ldb/docs/design.txt | 41 +++ source4/lib/ldb/include/includes.h | 22 ++ source4/lib/ldb/include/ldb.h | 204 +++++++++++ source4/lib/ldb/include/ldb_parse.h | 53 +++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 524 +++++++++++++++++++++++++++ source4/lib/ldb/ldb_ldap/ldb_ldap.h | 8 + source4/lib/ldb/ldb_tdb/.cvsignore | 7 + source4/lib/ldb/ldb_tdb/ldb_index.c | 641 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_ldif.c | 366 +++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_match.c | 176 ++++++++++ source4/lib/ldb/ldb_tdb/ldb_pack.c | 174 +++++++++ source4/lib/ldb/ldb_tdb/ldb_parse.c | 448 ++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_parse.h | 40 +++ source4/lib/ldb/ldb_tdb/ldb_search.c | 482 +++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 303 ++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 11 + source4/lib/ldb/ldb_tdb/ldbadd.c | 55 +++ source4/lib/ldb/ldb_tdb/ldbdel.c | 50 +++ source4/lib/ldb/ldb_tdb/ldbsearch.c | 73 ++++ source4/lib/ldb/tests/init.ldif | 15 + source4/lib/ldb/tests/init_slapd.sh | 11 + source4/lib/ldb/tests/ldapi_url.sh | 11 + source4/lib/ldb/tests/slapd.conf | 25 ++ source4/lib/ldb/tests/start_slapd.sh | 8 + source4/lib/ldb/tests/test-index.ldif | 4 + source4/lib/ldb/tests/test.ldif | 416 ++++++++++++++++++++++ source4/lib/ldb/tests/testdata.txt | 8 + source4/lib/ldb/tests/testsearch.txt | 5 + source4/lib/ldb/tools/ldbadd.c | 74 ++++ source4/lib/ldb/tools/ldbdel.c | 69 ++++ source4/lib/ldb/tools/ldbsearch.c | 122 +++++++ 36 files changed, 5656 insertions(+) create mode 100644 source4/lib/ldb/Makefile.ldb create mode 100644 source4/lib/ldb/common/ldb.c create mode 100644 source4/lib/ldb/common/ldb_ldif.c create mode 100644 source4/lib/ldb/common/ldb_parse.c create mode 100644 source4/lib/ldb/common/util.c create mode 100644 source4/lib/ldb/docs/design.txt create mode 100644 source4/lib/ldb/include/includes.h create mode 100644 source4/lib/ldb/include/ldb.h create mode 100644 source4/lib/ldb/include/ldb_parse.h create mode 100644 source4/lib/ldb/ldb_ldap/ldb_ldap.c create mode 100644 source4/lib/ldb/ldb_ldap/ldb_ldap.h create mode 100644 source4/lib/ldb/ldb_tdb/.cvsignore create mode 100644 source4/lib/ldb/ldb_tdb/ldb_index.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_ldif.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_match.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_pack.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_parse.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_parse.h create mode 100644 source4/lib/ldb/ldb_tdb/ldb_search.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_tdb.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_tdb.h create mode 100644 source4/lib/ldb/ldb_tdb/ldbadd.c create mode 100644 source4/lib/ldb/ldb_tdb/ldbdel.c create mode 100644 source4/lib/ldb/ldb_tdb/ldbsearch.c create mode 100644 source4/lib/ldb/tests/init.ldif create mode 100755 source4/lib/ldb/tests/init_slapd.sh create mode 100755 source4/lib/ldb/tests/ldapi_url.sh create mode 100644 source4/lib/ldb/tests/slapd.conf create mode 100755 source4/lib/ldb/tests/start_slapd.sh create mode 100644 source4/lib/ldb/tests/test-index.ldif create mode 100644 source4/lib/ldb/tests/test.ldif create mode 100644 source4/lib/ldb/tests/testdata.txt create mode 100644 source4/lib/ldb/tests/testsearch.txt create mode 100644 source4/lib/ldb/tools/ldbadd.c create mode 100644 source4/lib/ldb/tools/ldbdel.c create mode 100644 source4/lib/ldb/tools/ldbsearch.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb new file mode 100644 index 0000000000..346c041666 --- /dev/null +++ b/source4/lib/ldb/Makefile.ldb @@ -0,0 +1,43 @@ +CFLAGS=-Wall -g -Iinclude -I. -DSTANDALONE=1 -DUSE_MMAP=1 +OPENLDAP=/home/tridge/samba/openldap/prefix + +LIB_FLAGS=-Llib -lldb -L$(OPENLDAP)/lib -lldap + +TDB_OBJ=tdb/tdb.o tdb/spinlock.o + +LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ + ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o + +LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o + +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/ldb_parse.o + +OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) + +LDB_LIB = lib/libldb.a + +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel + +LIBS = $(LDB_LIB)($(OBJS)) + +all: $(BINS) $(LIBS) + +lib/libldb.a: $(OBJS) + +bin/ldbadd: tools/ldbadd.o $(LIBS) + $(CC) -o bin/ldbadd tools/ldbadd.o $(LIB_FLAGS) + +bin/ldbsearch: tools/ldbsearch.o $(LIBS) + $(CC) -o bin/ldbsearch tools/ldbsearch.o $(LIB_FLAGS) + +bin/ldbdel: tools/ldbdel.o $(LIBS) + $(CC) -o bin/ldbdel tools/ldbdel.o $(LIB_FLAGS) + +clean: + rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) + +proto: + mkproto.pl */*.c > include/proto.h + +etags: + etags */*.[ch] diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c new file mode 100644 index 0000000000..90b77e1e7f --- /dev/null +++ b/source4/lib/ldb/common/ldb.c @@ -0,0 +1,129 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb core API + * + * Description: core API routines interfacing to ldb backends + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +/* + connect to a database. The URL can either be one of the following forms + ldb://path + ldapi://path + + flags is made up of LDB_FLG_* + + the options are passed uninterpreted to the backend, and are + backend specific +*/ +struct ldb_context *ldb_connect(const char *url, unsigned int flags, + const char *options[]) +{ + + if (strncmp(url, "tdb:", 4) == 0) { + return ltdb_connect(url, flags, options); + } + + if (strncmp(url, "ldap", 4) == 0) { + return lldb_connect(url, flags, options); + } + + errno = EINVAL; + return NULL; +} + +/* + close the connection to the database +*/ +int ldb_close(struct ldb_context *ldb) +{ + return ldb->ops->close(ldb); +} + + +/* + search the database given a LDAP-like search expression + + return the number of records found, or -1 on error +*/ +int ldb_search(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + const char *expression, + const char *attrs[], struct ldb_message ***res) +{ + return ldb->ops->search(ldb, base, scope, expression, attrs, res); +} + +/* + free a set of messages returned by ldb_search +*/ +int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) +{ + return ldb->ops->search_free(ldb, msgs); +} + + +/* + add a record to the database. Will fail if a record with the given class and key + already exists +*/ +int ldb_add(struct ldb_context *ldb, + const struct ldb_message *message) +{ + return ldb->ops->add(ldb, message); +} + +/* + modify the specified attributes of a record +*/ +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message) +{ + return ldb->ops->modify(ldb, message); +} + + +/* + delete a record from the database +*/ +int ldb_delete(struct ldb_context *ldb, const char *dn) +{ + return ldb->ops->delete(ldb, dn); +} + +/* + return extended error information +*/ +const char *ldb_errstring(struct ldb_context *ldb) +{ + return ldb->ops->errstring(ldb); +} diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c new file mode 100644 index 0000000000..198c984823 --- /dev/null +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -0,0 +1,476 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldif routines + * + * Description: ldif pack/unpack routines + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + this base64 decoder was taken from jitterbug (written by tridge). + we might need to replace it with a new version +*/ +static int base64_decode(char *s) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i, n; + unsigned char *d = (unsigned char *)s; + char *p; + + n=i=0; + + while (*s && (p=strchr(b64,*s))) { + idx = (int)(p - b64); + byte_offset = (i*6)/8; + bit_offset = (i*6)%8; + d[byte_offset] &= ~((1<<(8-bit_offset))-1); + if (bit_offset < 3) { + d[byte_offset] |= (idx << (2-bit_offset)); + n = byte_offset+1; + } else { + d[byte_offset] |= (idx >> (bit_offset-2)); + d[byte_offset+1] = 0; + d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; + n = byte_offset+2; + } + s++; i++; + } + + if (*s && !p) { + /* the only termination allowed */ + if (*s != '=') { + return -1; + } + } + + /* null terminate */ + d[n] = 0; + return n; +} + + +/* + encode as base64 + caller frees +*/ +char *ldb_base64_encode(const char *buf, int len) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i; + unsigned char *d = (unsigned char *)buf; + int bytes = (len*8 + 5)/6; + char *out; + + out = malloc(bytes+2); + if (!out) return NULL; + + for (i=0;i> (2-bit_offset)) & 0x3F; + } else { + idx = (d[byte_offset] << (bit_offset-2)) & 0x3F; + if (byte_offset+1 < len) { + idx |= (d[byte_offset+1] >> (8-(bit_offset-2))); + } + } + out[i] = b64[idx]; + } + + out[i++] = '='; + out[i] = 0; + + return out; +} + +/* + see if a buffer should be base64 encoded +*/ +int ldb_should_b64_encode(const struct ldb_val *val) +{ + int i; + unsigned char *p = val->data; + + if (val->length == 0 || p[0] == ' ' || p[0] == ':') { + return 1; + } + + for (i=0; ilength; i++) { + if (!isprint(p[i]) || p[i] == '\n') { + return 1; + } + } + return 0; +} + +/* this macro is used to handle the return checking on fprintf_fn() */ +#define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0) + +/* + write a line folded string onto a file +*/ +static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private, + const char *buf, size_t length, int start_pos) +{ + int i; + int total=0, ret; + + for (i=0;idn); + CHECK_RET; + + for (i=0;inum_elements;i++) { + if (ldb_should_b64_encode(&msg->elements[i].value)) { + ret = fprintf_fn(private, "%s:: ", msg->elements[i].name); + CHECK_RET; + ret = base64_encode_f(fprintf_fn, private, + msg->elements[i].value.data, + msg->elements[i].value.length, + strlen(msg->elements[i].name)+3); + CHECK_RET; + ret = fprintf_fn(private, "\n"); + CHECK_RET; + } else { + ret = fprintf_fn(private, "%s: ", msg->elements[i].name); + CHECK_RET; + ret = fold_string(fprintf_fn, private, + msg->elements[i].value.data, + msg->elements[i].value.length, + strlen(msg->elements[i].name)+2); + CHECK_RET; + ret = fprintf_fn(private, "\n"); + CHECK_RET; + } + } + ret = fprintf_fn(private,"\n"); + CHECK_RET; + + return total; +} + +#undef CHECK_RET + + +/* + pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF + this routine removes any RFC2849 continuations and comments + + caller frees +*/ +static char *next_chunk(int (*fgetc_fn)(void *), void *private) +{ + size_t alloc_size=0, chunk_size = 0; + char *chunk = NULL; + int c; + int in_comment = 0; + + while ((c = fgetc_fn(private)) != EOF) { + if (chunk_size == alloc_size) { + char *c2; + alloc_size += 1024; + c2 = realloc_p(chunk, char, alloc_size); + if (!c2) { + free(chunk); + errno = ENOMEM; + return NULL; + } + chunk = c2; + } + + if (in_comment) { + if (c == '\n') { + in_comment = 0; + } + continue; + } + + /* handle continuation lines - see RFC2849 */ + if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') { + chunk_size--; + continue; + } + + /* chunks are terminated by a double line-feed */ + if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') { + chunk[chunk_size-1] = 0; + return chunk; + } + + if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) { + in_comment = 1; + continue; + } + + /* ignore leading blank lines */ + if (chunk_size == 0 && c == '\n') { + continue; + } + + chunk[chunk_size++] = c; + } + + return chunk; +} + + +/* simple ldif attribute parser */ +static int next_attr(char **s, char **attr, struct ldb_val *value) +{ + char *p; + int base64_encoded = 0; + + p = strchr(*s, ':'); + if (!p) { + return -1; + } + + *p++ = 0; + + if (*p == ':') { + base64_encoded = 1; + p++; + } + + *attr = *s; + + while (isspace(*p)) { + p++; + } + + value->data = p; + + p = strchr(p, '\n'); + + if (!p) { + value->length = strlen((char *)value->data); + *s = ((char *)value->data) + value->length; + } else { + value->length = p - (char *)value->data; + *s = p+1; + *p = 0; + } + + if (base64_encoded) { + int len = base64_decode(value->data); + if (len == -1) { + /* it wasn't valid base64 data */ + return -1; + } + value->length = len; + } + + return 0; +} + + +/* + free a message from a ldif_read +*/ +void ldif_read_free(struct ldb_message *msg) +{ + if (msg->elements) free(msg->elements); + if (msg->private) free(msg->private); + free(msg); +} + +/* + read from a LDIF source, creating a ldb_message +*/ +struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private) +{ + struct ldb_message *msg; + char *attr=NULL, *chunk=NULL, *s; + struct ldb_val value; + + value.data = NULL; + + msg = malloc_p(struct ldb_message); + if (!msg) return NULL; + + msg->dn = NULL; + msg->elements = NULL; + msg->num_elements = 0; + msg->private = NULL; + + chunk = next_chunk(fgetc_fn, private); + if (!chunk) { + goto failed; + } + + msg->private = chunk; + s = chunk; + + if (next_attr(&s, &attr, &value) != 0) { + goto failed; + } + + /* first line must be a dn */ + if (strcmp(attr, "dn") != 0) { + fprintf(stderr, "First line must be a dn not '%s'\n", attr); + goto failed; + } + + msg->dn = value.data; + + while (next_attr(&s, &attr, &value) == 0) { + msg->elements = realloc_p(msg->elements, + struct ldb_message_element, + msg->num_elements+1); + if (!msg->elements) { + goto failed; + } + msg->elements[msg->num_elements].flags = 0; + msg->elements[msg->num_elements].name = attr; + msg->elements[msg->num_elements].value = value; + msg->num_elements++; + } + + return msg; + +failed: + if (msg) ldif_read_free(msg); + return NULL; +} + + + +/* + a wrapper around ldif_read() for reading from FILE* +*/ +struct ldif_read_file_state { + FILE *f; +}; + +static int fgetc_file(void *private) +{ + struct ldif_read_file_state *state = private; + return fgetc(state->f); +} + +struct ldb_message *ldif_read_file(FILE *f) +{ + struct ldif_read_file_state state; + state.f = f; + return ldif_read(fgetc_file, &state); +} + + +/* + a wrapper around ldif_read() for reading from const char* +*/ +struct ldif_read_string_state { + const char *s; +}; + +static int fgetc_string(void *private) +{ + struct ldif_read_string_state *state = private; + if (state->s[0] != 0) { + return *state->s++; + } + return EOF; +} + +struct ldb_message *ldif_read_string(const char *s) +{ + struct ldif_read_string_state state; + state.s = s; + return ldif_read(fgetc_string, &state); +} + + +/* + wrapper around ldif_write() for a file +*/ +struct ldif_write_file_state { + FILE *f; +}; + +static int fprintf_file(void *private, const char *fmt, ...) +{ + struct ldif_write_file_state *state = private; + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(state->f, fmt, ap); + va_end(ap); + return ret; +} + +int ldif_write_file(FILE *f, const struct ldb_message *msg) +{ + struct ldif_write_file_state state; + state.f = f; + return ldif_write(fprintf_file, &state, msg); +} diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c new file mode 100644 index 0000000000..4f8d469e6c --- /dev/null +++ b/source4/lib/ldb/common/ldb_parse.c @@ -0,0 +1,460 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb expression parsing + * + * Description: parse LDAP-like search expressions + * + * Author: Andrew Tridgell + */ + +/* + TODO: + - add RFC2254 binary string handling + - possibly add ~=, <= and >= handling + - expand the test suite + - add better parse error handling + +*/ + +#include "includes.h" + + +/* +a filter is defined by: + ::= '(' ')' + ::= | | | + ::= '&' + ::= '|' + ::= '!' + ::= | + ::= + ::= '=' | '~=' | '<=' | '>=' +*/ + +/* + return next token element. Caller frees +*/ +static char *ldb_parse_lex(const char **s) +{ + const char *p = *s; + char *ret; + + while (isspace(*p)) { + p++; + } + *s = p; + + if (*p == 0) { + return NULL; + } + + if (strchr("()&|=!", *p)) { + (*s) = p+1; + ret = strndup(p, 1); + if (!ret) { + errno = ENOMEM; + } + return ret; + } + + while (*p && (isalnum(*p) || !strchr("()&|=!", *p))) { + p++; + } + + if (p == *s) { + return NULL; + } + + ret = strndup(*s, p - *s); + if (!ret) { + errno = ENOMEM; + } + + *s = p; + + return ret; +} + +/* + find a matching close brace in a string +*/ +static const char *match_brace(const char *s) +{ + unsigned int count = 0; + while (*s && (count != 0 || *s != ')')) { + if (*s == '(') { + count++; + } + if (*s == ')') { + count--; + } + s++; + } + if (! *s) { + return NULL; + } + return s; +} + + +static struct ldb_parse_tree *ldb_parse_filter(const char **s); + +/* + ::= +*/ +static struct ldb_parse_tree *ldb_parse_simple(const char *s) +{ + char *eq, *val, *l; + struct ldb_parse_tree *ret; + + l = ldb_parse_lex(&s); + if (!l) { + fprintf(stderr, "Unexpected end of expression\n"); + return NULL; + } + + if (strchr("()&|=", *l)) { + fprintf(stderr, "Unexpected token '%s'\n", l); + free(l); + return NULL; + } + + eq = ldb_parse_lex(&s); + if (!eq || strcmp(eq, "=") != 0) { + fprintf(stderr, "Expected '='\n"); + free(l); + if (eq) free(eq); + return NULL; + } + free(eq); + + val = ldb_parse_lex(&s); + if (val && strchr("()&|=", *val)) { + fprintf(stderr, "Unexpected token '%s'\n", val); + free(l); + if (val) free(val); + return NULL; + } + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = LDB_OP_SIMPLE; + ret->u.simple.attr = l; + ret->u.simple.value.data = val; + ret->u.simple.value.length = val?strlen(val):0; + + return ret; +} + + +/* + parse a filterlist + ::= '&' + ::= '|' + ::= | +*/ +static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const char *s) +{ + struct ldb_parse_tree *ret, *next; + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = op; + ret->u.list.num_elements = 1; + ret->u.list.elements = malloc_p(struct ldb_parse_tree *); + if (!ret->u.list.elements) { + errno = ENOMEM; + free(ret); + return NULL; + } + + ret->u.list.elements[0] = ldb_parse_filter(&s); + if (!ret->u.list.elements[0]) { + free(ret->u.list.elements); + free(ret); + return NULL; + } + + while (isspace(*s)) s++; + + while (*s && (next = ldb_parse_filter(&s))) { + struct ldb_parse_tree **e; + e = realloc_p(ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements+1); + if (!e) { + errno = ENOMEM; + ldb_parse_tree_free(next); + ldb_parse_tree_free(ret); + return NULL; + } + ret->u.list.elements = e; + ret->u.list.elements[ret->u.list.num_elements] = next; + ret->u.list.num_elements++; + while (isspace(*s)) s++; + } + + return ret; +} + + +/* + ::= '!' +*/ +static struct ldb_parse_tree *ldb_parse_not(const char *s) +{ + struct ldb_parse_tree *ret; + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = LDB_OP_NOT; + ret->u.not.child = ldb_parse_filter(&s); + if (!ret->u.not.child) { + free(ret); + return NULL; + } + + return ret; +} + +/* + parse a filtercomp + ::= | | | +*/ +static struct ldb_parse_tree *ldb_parse_filtercomp(const char *s) +{ + while (isspace(*s)) s++; + + switch (*s) { + case '&': + return ldb_parse_filterlist(LDB_OP_AND, s+1); + + case '|': + return ldb_parse_filterlist(LDB_OP_OR, s+1); + + case '!': + return ldb_parse_not(s+1); + + case '(': + case ')': + fprintf(stderr, "Unexpected token '%c'\n", *s); + return NULL; + } + + return ldb_parse_simple(s); +} + + +/* + ::= '(' ')' +*/ +static struct ldb_parse_tree *ldb_parse_filter(const char **s) +{ + char *l, *s2; + const char *p, *p2; + struct ldb_parse_tree *ret; + + l = ldb_parse_lex(s); + if (!l) { + fprintf(stderr, "Unexpected end of expression\n"); + return NULL; + } + + if (strcmp(l, "(") != 0) { + free(l); + fprintf(stderr, "Expected '('\n"); + return NULL; + } + free(l); + + p = match_brace(*s); + if (!p) { + fprintf(stderr, "Parse error - mismatched braces\n"); + return NULL; + } + p2 = p + 1; + + s2 = strndup(*s, p - *s); + if (!s2) { + errno = ENOMEM; + return NULL; + } + + ret = ldb_parse_filtercomp(s2); + free(s2); + + *s = p2; + + return ret; +} + + +/* + main parser entry point. Takes a search string and returns a parse tree + + expression ::= | +*/ +struct ldb_parse_tree *ldb_parse_tree(const char *s) +{ + while (isspace(*s)) s++; + + if (*s == '(') { + return ldb_parse_filter(&s); + } + + return ldb_parse_simple(s); +} + +/* + free a parse tree returned from ldb_parse_tree() +*/ +void ldb_parse_tree_free(struct ldb_parse_tree *tree) +{ + int i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + free(tree->u.simple.attr); + if (tree->u.simple.value.data) free(tree->u.simple.value.data); + break; + + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ldb_parse_tree_free(tree->u.list.elements[i]); + } + if (tree->u.list.elements) free(tree->u.list.elements); + break; + + case LDB_OP_NOT: + ldb_parse_tree_free(tree->u.not.child); + break; + } + + free(tree); +} + +#if TEST_PROGRAM +/* + return a string representation of a parse tree + used for debugging +*/ +static char *tree_string(struct ldb_parse_tree *tree) +{ + char *s = NULL; + char *s1, *s2; + int i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + asprintf(&s, "( %s = \"%s\" )", tree->u.simple.attr, + (char *)tree->u.simple.value.data); + break; + + case LDB_OP_AND: + case LDB_OP_OR: + asprintf(&s, "( %c", tree->operation==LDB_OP_AND?'&':'|'); + if (!s) return NULL; + + for (i=0;iu.list.num_elements;i++) { + s1 = tree_string(tree->u.list.elements[i]); + if (!s1) { + free(s); + return NULL; + } + asprintf(&s2, "%s %s", s, s1); + free(s); + free(s1); + s = s2; + } + if (!s) { + return NULL; + } + asprintf(&s2, "%s )", s); + free(s); + s = s2; + break; + + case LDB_OP_NOT: + s1 = tree_string(tree->u.not.child); + asprintf(&s, "( ! %s )", s1); + free(s1); + break; + } + return s; +} + + +/* + print a tree + */ +static void print_tree(struct ldb_parse_tree *tree) +{ + char *s = tree_string(tree); + printf("%s\n", s); + free(s); +} + + + int main(void) +{ + char line[1000]; + int ret = 0; + + while (fgets(line, sizeof(line)-1, stdin)) { + struct ldb_parse_tree *tree; + + if (line[strlen(line)-1] == '\n') { + line[strlen(line)-1] = 0; + } + tree = ldb_parse_tree(line); + if (!tree) { + fprintf(stderr, "Failed to parse\n"); + ret = 1; + continue; + } + print_tree(tree); + ldb_parse_tree_free(tree); + } + + return ret; +} +#endif /* TEST_PROGRAM */ + diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c new file mode 100644 index 0000000000..d198a1ad92 --- /dev/null +++ b/source4/lib/ldb/common/util.c @@ -0,0 +1,102 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb utility functions + * + * Description: miscellanous utility functions for ldb + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +#define MAX_MALLOC_SIZE 0x7fffffff + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *realloc_array(void *ptr, size_t el_size, unsigned count) +{ + if (count == 0 || + count >= MAX_MALLOC_SIZE/el_size) { + return NULL; + } + if (!ptr) { + return malloc(el_size * count); + } + return realloc(ptr, el_size * count); +} + + +/* + find an element in a list, using the given comparison function and + assuming that the list is already sorted using comp_fn + + return -1 if not found, or the index of the first occurance of needle if found +*/ +int list_find(const void *needle, + const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn) +{ + const char *base_p = base; + size_t min_i, max_i, test_i; + + if (nmemb == 0) { + return -1; + } + + min_i = 0; + max_i = nmemb-1; + + while (min_i < max_i) { + size_t test_t; + int r; + + test_i = (min_i + max_i) / 2; + r = comp_fn(needle, *(void **)(base_p + (size * test_i))); + if (r == 0) { + /* scan back for first element */ + while (test_t > 0 && + comp_fn(needle, *(void **)(base_p + (size * (test_i-1)))) == 0) { + test_i--; + } + return test_i; + } + if (r == -1) { + max_i = test_i - 1; + } + if (r == 1) { + min_i = test_i + 1; + } + } + + if (comp_fn(needle, *(void **)(base_p + (size * min_i))) == 0) { + return min_i; + } + + return -1; +} diff --git a/source4/lib/ldb/docs/design.txt b/source4/lib/ldb/docs/design.txt new file mode 100644 index 0000000000..0bb278b5b4 --- /dev/null +++ b/source4/lib/ldb/docs/design.txt @@ -0,0 +1,41 @@ +The list of indexed fields +-------------------------- + +dn=@INDEXLIST + list of field names that are indexed + + contains fields of type @IDXATTR which contain attriute names + of indexed fields + + +Data records +------------ + +for each user record in the db there is: + main record + key: DN=dn + data: packed attribute/value list + + a index record for each indexed field in the record + + +Index Records +------------- + +The index records contain the list of dn's that contain records +matching the index key + +All index records are of the form: + dn=@INDEX:field:value + +and contain fields of type @IDX which are the dns of the records +that have that value for some attribute + + +Search Expressions +------------------ + +Very similar to LDAP search expressions, but does not allow ~=, <= or >= + + attrib0 := (field=value) + attrib := attrib0 | (attrib&&attrib) | (attrib||attrib) | !attrib diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h new file mode 100644 index 0000000000..ea8540d330 --- /dev/null +++ b/source4/lib/ldb/include/includes.h @@ -0,0 +1,22 @@ +/* + a temporary includes file until I work on the ldb build system +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldb.h" +#include "ldb_parse.h" + +#define malloc_p(type) (type *)malloc(sizeof(type)) +#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) +#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) + +#include "tdb/tdb.h" +#include "proto.h" diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h new file mode 100644 index 0000000000..35474d23c5 --- /dev/null +++ b/source4/lib/ldb/include/ldb.h @@ -0,0 +1,204 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb header + * + * Description: defines for base ldb API + * + * Author: Andrew Tridgell + */ + +/* + major restrictions as compared to normal LDAP: + + - no async calls. + - each record must have a unique key field + - the key must be representable as a NULL terminated C string and may not + contain a comma or braces + + major restrictions as compared to tdb: + + - no explicit locking calls + +*/ + + +/* + an individual lump of data in a result comes in this format. The + pointer will usually be to a UTF-8 string if the application is + sensible, but it can be to anything you like, including binary data + blobs of arbitrary size. +*/ +struct ldb_val { + unsigned int length; + void *data; +}; + +/* these flags are used in ldd_message_element.flags fields. The + LDA_FLAGS_MOD_* flags are used in ldap_modify() calls to specify + whether attributes are being added, deleted or modified */ +#define LDB_FLAG_MOD_MASK 0x3 +#define LDB_FLAG_MOD_ADD 1 +#define LDB_FLAG_MOD_REPLACE 2 +#define LDB_FLAG_MOD_DELETE 3 + + +/* + results are given back as arrays of ldb_message_element +*/ +struct ldb_message_element { + unsigned int flags; + char *name; + struct ldb_val value; +}; + + +/* + a ldb_message represents all or part of a record. It can contain an arbitrary + number of elements. +*/ +struct ldb_message { + char *dn; + unsigned int num_elements; + struct ldb_message_element *elements; + void *private; /* private to the backend */ +}; + + +enum ldb_scope {LDB_SCOPE_DEFAULT=-1, + LDB_SCOPE_BASE=0, + LDB_SCOPE_ONELEVEL=1, + LDB_SCOPE_SUBTREE=2}; + +struct ldb_context; + +/* + the fuction type for the callback used in traversing the database +*/ +typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *); + + +/* + these function pointers define the operations that a ldb backend must perform + they correspond exactly to the ldb_*() interface +*/ +struct ldb_backend_ops { + int (*close)(struct ldb_context *); + int (*search)(struct ldb_context *, const char *, enum ldb_scope, + const char *, const char *[], struct ldb_message ***); + int (*search_free)(struct ldb_context *, struct ldb_message **); + int (*add)(struct ldb_context *, const struct ldb_message *); + int (*modify)(struct ldb_context *, const struct ldb_message *); + int (*delete)(struct ldb_context *, const char *); + const char * (*errstring)(struct ldb_context *); +}; + +/* + every ldb connection is started by establishing a ldb_context +*/ +struct ldb_context { + /* a private pointer for the backend to use */ + void *private; + + /* the operations provided by the backend */ + const struct ldb_backend_ops *ops; +}; + + +#define LDB_FLG_RDONLY 1 + +/* + connect to a database. The URL can either be one of the following forms + ldb://path + ldapi://path + + flags is made up of LDB_FLG_* + + the options are passed uninterpreted to the backend, and are + backend specific +*/ +struct ldb_context *ldb_connect(const char *url, unsigned int flags, + const char *options[]); + +/* + close the connection to the database +*/ +int ldb_close(struct ldb_context *ldb); + + +/* + search the database given a LDAP-like search expression + + return the number of records found, or -1 on error +*/ +int ldb_search(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + const char *expression, + const char *attrs[], struct ldb_message ***res); + +/* + free a set of messages returned by ldb_search +*/ +int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); + + +/* + add a record to the database. Will fail if a record with the given class and key + already exists +*/ +int ldb_add(struct ldb_context *ldb, + const struct ldb_message *message); + +/* + modify the specified attributes of a record +*/ +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message); + +/* + delete a record from the database +*/ +int ldb_delete(struct ldb_context *ldb, const char *dn); + + +/* + return extended error information from the last call +*/ +const char *ldb_errstring(struct ldb_context *ldb); + +/* + ldif manipulation functions +*/ +int ldif_write(int (*fprintf_fn)(void *, const char *, ...), + void *private, + const struct ldb_message *msg); +void ldif_read_free(struct ldb_message *msg); +struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private); +struct ldb_message *ldif_read_file(FILE *f); +struct ldb_message *ldif_read_string(const char *s); +int ldif_write_file(FILE *f, const struct ldb_message *msg); diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h new file mode 100644 index 0000000000..c0d5806cc9 --- /dev/null +++ b/source4/lib/ldb/include/ldb_parse.h @@ -0,0 +1,53 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb expression parse header + * + * Description: structure for expression parsing + * + * Author: Andrew Tridgell + */ + + +enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT}; + +struct ldb_parse_tree { + enum ldb_parse_op operation; + union { + struct { + char *attr; + struct ldb_val value; + } simple; + struct { + unsigned int num_elements; + struct ldb_parse_tree **elements; + } list; + struct { + struct ldb_parse_tree *child; + } not; + } u; +}; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c new file mode 100644 index 0000000000..b2f7688497 --- /dev/null +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -0,0 +1,524 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb ldap backend + * + * Description: core files for LDAP backend + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb_ldap/ldb_ldap.h" + +#if 0 +/* + we don't need this right now, but will once we add more backend + options +*/ + +/* + find an option in an option list (a null terminated list of strings) + + this assumes the list is short. If it ever gets long then we really + should do this in some smarter way + */ +static const char *lldb_option_find(const struct lldb_private *lldb, const char *name) +{ + int i; + size_t len = strlen(name); + + if (!lldb->options) return NULL; + + for (i=0;lldb->options[i];i++) { + if (strncmp(lldb->options[i], name, len) == 0 && + lldb->options[i][len] == '=') { + return &lldb->options[i][len+1]; + } + } + + return NULL; +} +#endif + +/* + close/free the connection +*/ +static int lldb_close(struct ldb_context *ldb) +{ + int i, ret = 0; + struct lldb_private *lldb = ldb->private; + + if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) { + ret = -1; + } + + if (lldb->options) { + for (i=0;lldb->options[i];i++) { + free(lldb->options[i]); + } + free(lldb->options); + } + free(lldb); + free(ldb); + + return ret; +} + +/* + delete a record +*/ +static int lldb_delete(struct ldb_context *ldb, const char *dn) +{ + struct lldb_private *lldb = ldb->private; + int ret = 0; + + lldb->last_rc = ldap_delete_s(lldb->ldap, dn); + if (lldb->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + return ret; +} + +/* + free a search message +*/ +static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) +{ + int i; + free(msg->dn); + for (i=0;inum_elements;i++) { + free(msg->elements[i].name); + if (msg->elements[i].value.data) { + free(msg->elements[i].value.data); + } + } + if (msg->elements) free(msg->elements); + free(msg); + return 0; +} + +/* + free a search result +*/ +static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res) +{ + int i; + for (i=0;res[i];i++) { + if (lldb_msg_free(ldb, res[i]) != 0) { + return -1; + } + } + free(res); + return 0; +} + + +/* + add a single set of ldap message values to a ldb_message +*/ +static int lldb_add_msg_attr(struct ldb_message *msg, + const char *attr, struct berval **bval) +{ + int count, i; + struct ldb_message_element *el; + + count = ldap_count_values_len(bval); + + if (count <= 0) { + return -1; + } + + el = realloc_p(msg->elements, struct ldb_message_element, + msg->num_elements + count); + if (!el) { + errno = ENOMEM; + return -1; + } + + msg->elements = el; + + for (i=0;ielements[msg->num_elements].name = strdup(attr); + if (!msg->elements[msg->num_elements].name) { + return -1; + } + msg->elements[msg->num_elements].value.data = malloc(bval[i]->bv_len); + if (!msg->elements[msg->num_elements].value.data) { + free(msg->elements[msg->num_elements].name); + return -1; + } + memcpy(msg->elements[msg->num_elements].value.data, + bval[i]->bv_val, bval[i]->bv_len); + msg->elements[msg->num_elements].value.length = bval[i]->bv_len; + msg->num_elements++; + } + + return 0; +} + +/* + search for matching records +*/ +static int lldb_search(struct ldb_context *ldb, const char *base, + enum ldb_scope scope, const char *expression, + const char **attrs, struct ldb_message ***res) +{ + struct lldb_private *lldb = ldb->private; + int count, msg_count; + LDAPMessage *ldapres, *msg; + + lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, + expression, attrs, 0, &ldapres); + if (lldb->last_rc != LDAP_SUCCESS) { + return -1; + } + + count = ldap_count_entries(lldb->ldap, ldapres); + if (count == -1 || count == 0) { + ldap_msgfree(ldapres); + return count; + } + + (*res) = malloc_array_p(struct ldb_message *, count+1); + if (! *res) { + ldap_msgfree(ldapres); + errno = ENOMEM; + return -1; + } + + (*res)[0] = NULL; + + msg_count = 0; + + /* loop over all messages */ + for (msg=ldap_first_entry(lldb->ldap, ldapres); + msg; + msg=ldap_next_entry(lldb->ldap, msg)) { + BerElement *berptr = NULL; + char *attr, *dn; + + if (msg_count == count) { + /* hmm, got too many? */ + fprintf(stderr,"Too many messages?!\n"); + break; + } + + (*res)[msg_count] = malloc_p(struct ldb_message); + if (!(*res)[msg_count]) { + goto failed; + } + (*res)[msg_count+1] = NULL; + + dn = ldap_get_dn(lldb->ldap, msg); + if (!dn) { + goto failed; + } + + (*res)[msg_count]->dn = strdup(dn); + ldap_memfree(dn); + if (!(*res)[msg_count]->dn) { + goto failed; + } + + + (*res)[msg_count]->num_elements = 0; + (*res)[msg_count]->elements = NULL; + (*res)[msg_count]->private = NULL; + + /* loop over all attributes */ + for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr); + attr; + attr=ldap_next_attribute(lldb->ldap, msg, berptr)) { + struct berval **bval; + bval = ldap_get_values_len(lldb->ldap, msg, attr); + + if (bval) { + lldb_add_msg_attr((*res)[msg_count], attr, bval); + ldap_value_free_len(bval); + } + + ldap_memfree(attr); + } + if (berptr) ber_free(berptr, 0); + + msg_count++; + } + + ldap_msgfree(ldapres); + + return msg_count; + +failed: + if (*res) lldb_search_free(ldb, *res); + return -1; +} + + +/* + free a set of mods from lldb_msg_to_mods() +*/ +static void lldb_mods_free(LDAPMod **mods) +{ + int i, j; + + if (!mods) return; + + for (i=0;mods[i];i++) { + if (mods[i]->mod_vals.modv_bvals) { + for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) { + free(mods[i]->mod_vals.modv_bvals[j]); + } + free(mods[i]->mod_vals.modv_bvals); + } + free(mods[i]); + } + free(mods); +} + + +/* + convert a ldb_message structure to a list of LDAPMod structures + ready for ldap_add() or ldap_modify() +*/ +static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) +{ + LDAPMod **mods; + int i, num_vals, num_mods = 0; + + /* allocate maximum number of elements needed */ + mods = malloc_array_p(LDAPMod *, msg->num_elements+1); + if (!mods) { + errno = ENOMEM; + return NULL; + } + mods[0] = NULL; + + for (i=0;inum_elements;i++) { + + if (i > 0 && + (!use_flags || + (msg->elements[i].flags == msg->elements[i-1].flags)) && + strcmp(msg->elements[i].name, msg->elements[i-1].name) == 0) { + struct berval **b; + /* when attributes are repeated we need to extend the + existing bvals array */ + b = realloc_p(mods[num_mods-1]->mod_vals.modv_bvals, + struct berval *, num_vals+2); + if (!b) { + goto failed; + } + mods[num_mods-1]->mod_vals.modv_bvals = b; + b[num_vals+1] = NULL; + b[num_vals] = malloc_p(struct berval); + if (!b[num_vals]) goto failed; + b[num_vals]->bv_val = msg->elements[i].value.data; + b[num_vals]->bv_len = msg->elements[i].value.length; + num_vals++; + continue; + } + + num_vals = 1; + + mods[num_mods] = malloc_p(LDAPMod); + if (!mods[num_mods]) { + goto failed; + } + mods[num_mods+1] = NULL; + mods[num_mods]->mod_op = LDAP_MOD_BVALUES; + if (use_flags) { + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + mods[num_mods]->mod_op |= LDAP_MOD_ADD; + break; + case LDB_FLAG_MOD_DELETE: + mods[num_mods]->mod_op |= LDAP_MOD_DELETE; + break; + case LDB_FLAG_MOD_REPLACE: + mods[num_mods]->mod_op |= LDAP_MOD_REPLACE; + break; + } + } + mods[num_mods]->mod_type = msg->elements[i].name; + mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *, 2); + if (!mods[num_mods]->mod_vals.modv_bvals) { + goto failed; + } + mods[num_mods]->mod_vals.modv_bvals[0] = malloc_p(struct berval); + if (!mods[num_mods]->mod_vals.modv_bvals[0]) { + goto failed; + } + mods[num_mods]->mod_vals.modv_bvals[0]->bv_val = msg->elements[i].value.data; + mods[num_mods]->mod_vals.modv_bvals[0]->bv_len = msg->elements[i].value.length; + mods[num_mods]->mod_vals.modv_bvals[1] = NULL; + num_mods++; + } + + return mods; + +failed: + lldb_mods_free(mods); + return NULL; +} + + +/* + add a record +*/ +static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) +{ + struct lldb_private *lldb = ldb->private; + LDAPMod **mods; + int ret = 0; + + mods = lldb_msg_to_mods(msg, 0); + + lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods); + if (lldb->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + lldb_mods_free(mods); + + return ret; +} + + +/* + modify a record +*/ +static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +{ + struct lldb_private *lldb = ldb->private; + LDAPMod **mods; + int ret = 0; + + mods = lldb_msg_to_mods(msg, 1); + + lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods); + if (lldb->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + lldb_mods_free(mods); + + return ret; +} + + +/* + return extended error information +*/ +static const char *lldb_errstring(struct ldb_context *ldb) +{ + struct lldb_private *lldb = ldb->private; + return ldap_err2string(lldb->last_rc); +} + + +static const struct ldb_backend_ops lldb_ops = { + lldb_close, + lldb_search, + lldb_search_free, + lldb_add, + lldb_modify, + lldb_delete, + lldb_errstring +}; + + +/* + connect to the database +*/ +struct ldb_context *lldb_connect(const char *url, + unsigned int flags, + const char *options[]) +{ + struct ldb_context *ldb = NULL; + struct lldb_private *lldb = NULL; + int i; + + ldb = malloc_p(struct ldb_context); + if (!ldb) { + errno = ENOMEM; + goto failed; + } + + lldb = malloc_p(struct lldb_private); + if (!lldb) { + free(ldb); + errno = ENOMEM; + goto failed; + } + + lldb->ldap = NULL; + lldb->options = NULL; + + lldb->last_rc = ldap_initialize(&lldb->ldap, url); + if (lldb->last_rc != LDAP_SUCCESS) { + goto failed; + } + + ldb->ops = &lldb_ops; + ldb->private = lldb; + + if (options) { + /* take a copy of the options array, so we don't have to rely + on the caller keeping it around (it might be dynamic) */ + for (i=0;options[i];i++) ; + + lldb->options = malloc_array_p(char *, i+1); + if (!lldb->options) { + goto failed; + } + + for (i=0;options[i];i++) { + lldb->options[i+1] = NULL; + lldb->options[i] = strdup(options[i]); + if (!lldb->options[i]) { + goto failed; + } + } + } + + return ldb; + +failed: + if (lldb && lldb->options) { + for (i=0;lldb->options[i];i++) { + free(lldb->options[i]); + } + free(lldb->options); + } + if (lldb && lldb->ldap) { + ldap_unbind(lldb->ldap); + } + if (lldb) free(lldb); + if (ldb) free(ldb); + return NULL; +} diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.h b/source4/lib/ldb/ldb_ldap/ldb_ldap.h new file mode 100644 index 0000000000..ba68283abd --- /dev/null +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.h @@ -0,0 +1,8 @@ +#include + +struct lldb_private { + char **options; + const char *basedn; + LDAP *ldap; + int last_rc; +}; diff --git a/source4/lib/ldb/ldb_tdb/.cvsignore b/source4/lib/ldb/ldb_tdb/.cvsignore new file mode 100644 index 0000000000..8f968d06f4 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/.cvsignore @@ -0,0 +1,7 @@ +ldbadd +ldbsearch +ldbdel +test.ldb +TAGS +.*~ +*.o diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c new file mode 100644 index 0000000000..dda80a6b2a --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -0,0 +1,641 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb tdb backend - indexing + * + * Description: indexing routines for ldb tdb backend + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +struct dn_list { + unsigned int count; + char **dn; +}; + +/* + free a struct dn_list +*/ +static void dn_list_free(struct dn_list *list) +{ + int i; + for (i=0;icount;i++) { + free(list->dn[i]); + } + if (list->dn) free(list->dn); +} + +/* + return the dn key to be used for an index + caller frees +*/ +static char *ldb_dn_key(const char *attr, const struct ldb_val *value) +{ + char *ret = NULL; + + if (ldb_should_b64_encode(value)) { + char *vstr = ldb_base64_encode(value->data, value->length); + if (!vstr) return NULL; + asprintf(&ret, "@INDEX:%s::%s", attr, vstr); + free(vstr); + return ret; + } + + asprintf(&ret, "@INDEX:%s:%s", attr, (char *)value->data); + return ret; +} + +/* + see if a attribute value is in the list of indexed attributes +*/ +static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr) +{ + int i; + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, "@IDXATTR") == 0 && + strcmp((char *)msg->elements[i].value.data, attr) == 0) { + return i; + } + } + return -1; +} + +/* + return a list of dn's that might match a simple indexed search or + */ +static int ltdb_index_dn_simple(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + char *dn = NULL; + int ret, i; + struct ldb_message msg; + + list->count = 0; + list->dn = NULL; + + /* + if the value is a wildcard then we can't do a match via indexing + */ + if (ltdb_has_wildcard(&tree->u.simple.value)) { + return -1; + } + + /* if the attribute isn't in the list of indexed attributes then + this node needs a full search */ + if (ldb_msg_find_idx(index_list, tree->u.simple.attr) == -1) { + return -1; + } + + /* the attribute is indexed. Pull the list of DNs that match the + search criterion */ + dn = ldb_dn_key(tree->u.simple.attr, &tree->u.simple.value); + if (!dn) return -1; + + ret = ltdb_search_dn1(ldb, dn, &msg); + free(dn); + if (ret == 0 || ret == -1) { + return ret; + } + + list->dn = malloc_array_p(char *, msg.num_elements); + if (!list->dn) { + ltdb_search_dn1_free(ldb, &msg); + } + + for (i=0;idn[list->count] = + strdup((char *)msg.elements[i].value.data); + if (!list->dn[list->count]) { + dn_list_free(list); + ltdb_search_dn1_free(ldb, &msg); + return -1; + } + list->count++; + } + + ltdb_search_dn1_free(ldb, &msg); + + qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) strcmp); + + return 1; +} + +/* + list intersection + list = list & list2 + relies on the lists being sorted +*/ +static int list_intersect(struct dn_list *list, const struct dn_list *list2) +{ + struct dn_list list3; + int i; + + if (list->count == 0 || list2->count == 0) { + /* 0 & X == 0 */ + dn_list_free(list); + return 0; + } + + list3.dn = malloc_array_p(char *, list->count); + if (!list3.dn) { + dn_list_free(list); + return -1; + } + list3.count = 0; + + for (i=0;icount;i++) { + if (list_find(list->dn[i], list2->dn, list2->count, + sizeof(char *), (comparison_fn_t)strcmp) != -1) { + list3.dn[list3.count] = list->dn[i]; + list3.count++; + } else { + free(list->dn[i]); + } + } + + free(list->dn); + list->dn = list3.dn; + list->count = list3.count; + + return 0; +} + + +/* + list union + list = list | list2 + relies on the lists being sorted +*/ +static int list_union(struct dn_list *list, const struct dn_list *list2) +{ + int i; + char **d; + unsigned int count = list->count; + + if (list->count == 0 && list2->count == 0) { + /* 0 | 0 == 0 */ + dn_list_free(list); + return 0; + } + + d = realloc_p(list->dn, char *, list->count + list2->count); + if (!d) { + dn_list_free(list); + return -1; + } + list->dn = d; + + for (i=0;icount;i++) { + if (list_find(list2->dn[i], list->dn, count, + sizeof(char *), (comparison_fn_t)strcmp) == -1) { + list->dn[list->count] = strdup(list2->dn[i]); + if (!list->dn[list->count]) { + dn_list_free(list); + return -1; + } + list->count++; + } + } + + if (list->count != count) { + qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)strcmp); + } + + return 0; +} + +static int ltdb_index_dn(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list); + + +/* + OR two index results + */ +static int ltdb_index_dn_or(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + int ret, i; + + ret = -1; + list->dn = NULL; + list->count = 0; + + for (i=0;iu.list.num_elements;i++) { + struct dn_list list2; + int v; + v = ltdb_index_dn(ldb, tree->u.list.elements[i], index_list, &list2); + + if (v == 0) { + /* 0 || X == X */ + if (ret == -1) { + ret = 0; + } + continue; + } + + if (v == -1) { + /* 1 || X == 1 */ + dn_list_free(list); + return -1; + } + + if (ret == -1) { + ret = 1; + *list = list2; + } else { + if (list_union(list, &list2) == -1) { + dn_list_free(&list2); + return -1; + } + dn_list_free(&list2); + } + } + + if (list->count == 0) { + dn_list_free(list); + return 0; + } + + return ret; +} + + +/* + NOT an index results + */ +static int ltdb_index_dn_not(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + /* the only way to do an indexed not would be if we could + negate the not via another not or if we knew the total + number of database elements so we could know that the + existing expression covered the whole database. + + instead, we just give up, and rely on a full index scan + (unless an outer & manages to reduce the list) + */ + return -1; +} + +/* + AND two index results + */ +static int ltdb_index_dn_and(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + int ret, i; + + ret = -1; + list->dn = NULL; + list->count = 0; + + for (i=0;iu.list.num_elements;i++) { + struct dn_list list2; + int v; + v = ltdb_index_dn(ldb, tree->u.list.elements[i], index_list, &list2); + + if (v == 0) { + /* 0 && X == 0 */ + dn_list_free(list); + return 0; + } + + if (v == -1) { + continue; + } + + if (ret == -1) { + ret = 1; + *list = list2; + } else { + if (list_intersect(list, &list2) == -1) { + dn_list_free(&list2); + return -1; + } + dn_list_free(&list2); + } + + if (list->count == 0) { + if (list->dn) free(list->dn); + return 0; + } + } + + return ret; +} + +/* + return a list of dn's that might match a indexed search or + -1 if an error. return 0 for no matches, or 1 for matches + */ +static int ltdb_index_dn(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + int ret; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + ret = ltdb_index_dn_simple(ldb, tree, index_list, list); + break; + + case LDB_OP_AND: + ret = ltdb_index_dn_and(ldb, tree, index_list, list); + break; + + case LDB_OP_OR: + ret = ltdb_index_dn_or(ldb, tree, index_list, list); + break; + + case LDB_OP_NOT: + ret = ltdb_index_dn_not(ldb, tree, index_list, list); + break; + } + + return ret; +} + +/* + filter a candidate dn_list from an indexed search into a set of results + extracting just the given attributes +*/ +static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope, + const struct dn_list *dn_list, + const char *attrs[], struct ldb_message ***res) +{ + int i; + unsigned int count = 0; + + for (i=0;icount;i++) { + struct ldb_message msg; + int ret; + ret = ltdb_search_dn1(ldb, dn_list->dn[i], &msg); + if (ret == 0) { + /* the record has disappeared? yes, this can happen */ + continue; + } + + if (ret == -1) { + /* an internal error */ + return -1; + } + + if (ldb_message_match(ldb, &msg, tree, base, scope) == 1) { + ret = ltdb_add_attr_results(ldb, &msg, attrs, &count, res); + } + ltdb_search_dn1_free(ldb, &msg); + if (ret != 0) { + return -1; + } + } + + return count; +} + +/* + search the database with a LDAP-like expression using indexes + returns -1 if an indexed search is not possible, in which + case the caller should call ltdb_search_full() +*/ +int ltdb_search_indexed(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char *attrs[], struct ldb_message ***res) +{ + struct ldb_message index_list; + struct dn_list dn_list; + int ret; + + /* find the list of indexed fields */ + ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); + if (ret != 1) { + /* no index list? must do full search */ + return -1; + } + + ret = ltdb_index_dn(ldb, tree, &index_list, &dn_list); + ltdb_search_dn1_free(ldb, &index_list); + + if (ret == 1) { + /* we've got a candidate list - now filter by the full tree + and extract the needed attributes */ + ret = ldb_index_filter(ldb, tree, base, scope, &dn_list, + attrs, res); + dn_list_free(&dn_list); + } + + return ret; +} + +/* + add an index entry for one message element +*/ +static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, + struct ldb_message_element *el) +{ + struct ldb_message msg; + char *dn_key; + int ret; + struct ldb_message_element *el2; + + dn_key = ldb_dn_key(el->name, &el->value); + if (!dn_key) { + return -1; + } + + ret = ltdb_search_dn1(ldb, dn_key, &msg); + if (ret == -1) { + free(dn_key); + return -1; + } + + if (ret == 0) { + msg.dn = dn_key; + msg.num_elements = 0; + msg.elements = NULL; + msg.private = NULL; + } + + /* add another entry */ + el2 = realloc_p(msg.elements, struct ldb_message_element, msg.num_elements+1); + if (!el2) { + if (ret == 1) { + ltdb_search_dn1_free(ldb, &msg); + } + free(dn_key); + return -1; + } + + msg.elements = el2; + msg.elements[msg.num_elements].name = "@IDX"; + msg.elements[msg.num_elements].value.length = strlen(dn); + msg.elements[msg.num_elements].value.data = dn; + msg.num_elements++; + + ret = ltdb_store(ldb, &msg, TDB_REPLACE); + + if (msg.num_elements == 1) { + free(msg.elements); + } else { + ltdb_search_dn1_free(ldb, &msg); + } + + return ret; +} + +/* + add the index entries for a new record + return -1 on failure +*/ +int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) +{ + int ret, i; + struct ldb_message index_list; + + /* find the list of indexed fields */ + ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); + if (ret != 1) { + /* no indexed fields or an error */ + return ret; + } + + for (i=0;inum_elements;i++) { + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + if (ret == -1) { + continue; + } + ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i]); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } + } + + return 0; +} + + +/* + delete an index entry for one message element +*/ +static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, + struct ldb_message_element *el) +{ + struct ldb_message msg; + char *dn_key; + int ret, i; + + dn_key = ldb_dn_key(el->name, &el->value); + if (!dn_key) { + return -1; + } + + ret = ltdb_search_dn1(ldb, dn_key, &msg); + if (ret == -1) { + free(dn_key); + return -1; + } + + if (ret == 0) { + /* it wasn't indexed. Did we have an earlier error? If we did then + its gone now */ + ltdb_search_dn1_free(ldb, &msg); + return 0; + } + + i = ldb_msg_find_idx(&msg, dn); + if (i == -1) { + /* it ain't there. hmmm */ + ltdb_search_dn1_free(ldb, &msg); + return 0; + } + + if (i != msg.num_elements - 1) { + memmove(&msg.elements[i], &msg.elements[i+1], sizeof(msg.elements[i])); + } + msg.num_elements--; + + if (msg.num_elements == 0) { + ret = ltdb_delete_noindex(ldb, dn_key); + } else { + ret = ltdb_store(ldb, &msg, TDB_REPLACE); + } + + ltdb_search_dn1_free(ldb, &msg); + + return ret; +} + +/* + delete the index entries for a record + return -1 on failure +*/ +int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) +{ + int ret, i; + struct ldb_message index_list; + + /* find the list of indexed fields */ + ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); + if (ret != 1) { + /* no indexed fields or an error */ + return ret; + } + + for (i=0;inum_elements;i++) { + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + if (ret == -1) { + continue; + } + ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i]); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } + } + + return 0; +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_ldif.c b/source4/lib/ldb/ldb_tdb/ldb_ldif.c new file mode 100644 index 0000000000..170685cc03 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_ldif.c @@ -0,0 +1,366 @@ + /* + Unix SMB/CIFS implementation. + + ldif utilities for ldb + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + +/* + this base64 decoder was taken from jitterbug (written by tridge). + we might need to replace it with a new version +*/ +static int base64_decode(char *s) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i, n; + unsigned char *d = (unsigned char *)s; + char *p; + + n=i=0; + + while (*s && (p=strchr(b64,*s))) { + idx = (int)(p - b64); + byte_offset = (i*6)/8; + bit_offset = (i*6)%8; + d[byte_offset] &= ~((1<<(8-bit_offset))-1); + if (bit_offset < 3) { + d[byte_offset] |= (idx << (2-bit_offset)); + n = byte_offset+1; + } else { + d[byte_offset] |= (idx >> (bit_offset-2)); + d[byte_offset+1] = 0; + d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; + n = byte_offset+2; + } + s++; i++; + } + + if (*s && !p) { + /* the only termination allowed */ + if (*s != '=') { + return -1; + } + } + + /* null terminate */ + d[n] = 0; + return n; +} + + +/* + encode as base64 + caller frees +*/ +char *ldb_base64_encode(const char *buf, int len) +{ + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i; + unsigned char *d = (unsigned char *)buf; + int bytes = (len*8 + 5)/6; + char *out; + + out = malloc(bytes+2); + if (!out) return NULL; + + for (i=0;i> (2-bit_offset)) & 0x3F; + } else { + idx = (d[byte_offset] << (bit_offset-2)) & 0x3F; + if (byte_offset+1 < len) { + idx |= (d[byte_offset+1] >> (8-(bit_offset-2))); + } + } + out[i] = b64[idx]; + } + + out[i++] = '='; + out[i] = 0; + + return out; +} + +/* + see if a buffer should be base64 encoded +*/ +int ldb_should_b64_encode(const struct ldb_val *val) +{ + int i; + unsigned char *p = val->data; + + if (val->length == 0 || p[0] == ' ' || p[0] == ':') { + return 1; + } + + for (i=0; ilength; i++) { + if (!isprint(p[i]) || p[i] == '\n') { + return 1; + } + } + return 0; +} + + +/* + encode as base64 to a file +*/ +static int base64_encode_f(FILE *f, const char *buf, int len, int start_pos) +{ + int i; + char *b = ldb_base64_encode(buf, len); + + if (!b) { + return -1; + } + + for (i=0;b[i];i++) { + fputc(b[i], f); + if (b[i+1] && (i + start_pos) % 77 == 0) { + fputc('\n', f); + fputc(' ', f); + } + } + free(b); + return 0; +} + +/* + write a line folded string onto a file +*/ +static void fold_string(FILE *f, const char *buf, size_t length, int start_pos) +{ + int i; + + for (i=0;i 1 && chunk[chunk_size-1] == '\n') { + chunk_size--; + continue; + } + + /* chunks are terminated by a double line-feed */ + if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') { + chunk[chunk_size-1] = 0; + return chunk; + } + + if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) { + in_comment = 1; + continue; + } + + chunk[chunk_size++] = c; + } + + return chunk; +} + + +/* simple ldif attribute parser */ +static int next_attr(char **s, char **attr, struct ldb_val *value) +{ + char *p; + int base64_encoded = 0; + + p = strchr(*s, ':'); + if (!p) { + return -1; + } + + *p++ = 0; + + if (*p == ':') { + base64_encoded = 1; + p++; + } + + *attr = *s; + + while (isspace(*p)) { + p++; + } + + value->data = p; + + p = strchr(p, '\n'); + + if (!p) { + value->length = strlen((char *)value->data); + *s = ((char *)value->data) + value->length; + } else { + value->length = p - (char *)value->data; + *s = p+1; + *p = 0; + } + + if (base64_encoded) { + int len = base64_decode(value->data); + if (len == -1) { + /* it wasn't valid base64 data */ + return -1; + } + value->length = len; + } + + return 0; +} + + +/* + free a message from a ldif_read +*/ +void ldif_read_free(struct ldb_message *msg) +{ + if (msg->elements) free(msg->elements); + if (msg->private) free(msg->private); + free(msg); +} + +/* + read from a LDIF file, creating a ldb_message +*/ +struct ldb_message *ldif_read(FILE *f) +{ + struct ldb_message *msg; + char *attr=NULL, *chunk=NULL, *s; + struct ldb_val value; + + value.data = NULL; + + msg = malloc_p(struct ldb_message); + if (!msg) return NULL; + + msg->dn = NULL; + msg->elements = NULL; + msg->num_elements = 0; + msg->private = NULL; + + chunk = next_chunk(f); + if (!chunk) { + goto failed; + } + + msg->private = chunk; + s = chunk; + + if (next_attr(&s, &attr, &value) != 0) { + goto failed; + } + + /* first line must be a dn */ + if (strcmp(attr, "dn") != 0) { + fprintf(stderr, "First line must be a dn not '%s'\n", attr); + goto failed; + } + + msg->dn = value.data; + + while (next_attr(&s, &attr, &value) == 0) { + msg->elements = realloc_p(msg->elements, + struct ldb_message_element, + msg->num_elements+1); + if (!msg->elements) { + goto failed; + } + msg->elements[msg->num_elements].flags = 0; + msg->elements[msg->num_elements].name = attr; + msg->elements[msg->num_elements].value = value; + msg->num_elements++; + } + + return msg; + +failed: + if (msg) ldif_read_free(msg); + return NULL; +} + + +/* + write to a ldif file +*/ +void ldif_write(FILE *f, const struct ldb_message *msg) +{ + int i; + fprintf(f, "dn: %s\n", msg->dn); + for (i=0;inum_elements;i++) { + if (ldb_should_b64_encode(&msg->elements[i].value)) { + fprintf(f, "%s:: ", msg->elements[i].name); + base64_encode_f(f, + msg->elements[i].value.data, + msg->elements[i].value.length, + strlen(msg->elements[i].name)+3); + fprintf(f, "\n"); + } else { + fprintf(f, "%s: ", msg->elements[i].name); + fold_string(f, msg->elements[i].value.data, + msg->elements[i].value.length, + strlen(msg->elements[i].name)+2); + fprintf(f, "\n"); + } + } + fprintf(f,"\n"); +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c new file mode 100644 index 0000000000..89d204f56a --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -0,0 +1,176 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb expression matching + * + * Description: ldb expression matching for tdb backend + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + see if two ldb_val structures contain the same data + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal(struct ldb_val *v1, struct ldb_val *v2) +{ + if (v1->length != v2->length) return 0; + + if (v1->length == 0) return 1; + + if (memcmp(v1->data, v2->data, v1->length) == 0) { + return 1; + } + + return 0; +} + +/* + check if the scope matches in a search result +*/ +static int scope_match(const char *dn, const char *base, enum ldb_scope scope) +{ + size_t dn_len, base_len; + + if (base == NULL) { + return 1; + } + + base_len = strlen(base); + dn_len = strlen(dn); + + if (strcmp(dn, base) == 0) { + return 1; + } + + if (base_len+1 >= dn_len) { + return 0; + } + + switch (scope) { + case LDB_SCOPE_BASE: + break; + + case LDB_SCOPE_ONELEVEL: + if (strcmp(dn + (dn_len - base_len), base) == 0 && + dn[dn_len - base_len - 1] == ',' && + strchr(dn, ',') == &dn[dn_len - base_len - 1]) { + return 1; + } + break; + + case LDB_SCOPE_SUBTREE: + default: + if (strcmp(dn + (dn_len - base_len), base) == 0 && + dn[dn_len - base_len - 1] == ',') { + return 1; + } + break; + } + + return 0; +} + + +/* + match a leaf node +*/ +static int match_leaf(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + int i; + + if (!scope_match(msg->dn, base, scope)) { + return 0; + } + + if (strcmp(tree->u.simple.attr, "dn") == 0) { + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + return strcmp(msg->dn, tree->u.simple.value.data) == 0; + } + + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, tree->u.simple.attr) == 0 && + (strcmp(tree->u.simple.value.data, "*") == 0 || + ldb_val_equal(&msg->elements[i].value, &tree->u.simple.value))) { + return 1; + } + } + + return 0; +} + +/* + return 0 if the given parse tree matches the given message. Assumes + the message is in sorted order + + return 1 if it matches, and 0 if it doesn't match + + this is a recursive function, and does short-circuit evaluation + */ +int ldb_message_match(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + int v, i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + break; + + case LDB_OP_NOT: + return ! ldb_message_match(ldb, msg, tree->u.not.child, base, scope); + + case LDB_OP_AND: + for (i=0;iu.list.num_elements;i++) { + v = ldb_message_match(ldb, msg, tree->u.list.elements[i], + base, scope); + if (!v) return 0; + } + return 1; + + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + v = ldb_message_match(ldb, msg, tree->u.list.elements[i], + base, scope); + if (v) return 1; + } + return 0; + } + + return match_leaf(ldb, msg, tree, base, scope); +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c new file mode 100644 index 0000000000..b0c825e8e2 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -0,0 +1,174 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb pack/unpack + * + * Description: pack/unpack routines for ldb messages as key/value blobs + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb_tdb/ldb_tdb.h" + +/* change this if the data format ever changes */ +#define LTDB_PACKING_FORMAT 0x26011966 + +/* + pack a ldb message into a linear buffer in a TDB_DATA + + caller frees the data buffer after use +*/ +int ltdb_pack_data(struct ldb_context *ctx, + const struct ldb_message *message, + struct TDB_DATA *data) +{ + int i; + size_t size; + char *p; + + /* work out how big it needs to be */ + size = 8; + + for (i=0;inum_elements;i++) { + size += 1 + strlen(message->elements[i].name); + size += 4 + message->elements[i].value.length + 1; + } + + /* allocate it */ + data->dptr = malloc(size); + if (!data->dptr) { + errno = ENOMEM; + return -1; + } + data->dsize = size; + + p = data->dptr; + SIVAL(p, 0, LTDB_PACKING_FORMAT); + SIVAL(p, 4, message->num_elements); + p += 8; + + for (i=0;inum_elements;i++) { + size_t len = strlen(message->elements[i].name); + memcpy(p, message->elements[i].name, len+1); + p += len + 1; + SIVAL(p, 0, message->elements[i].value.length); + memcpy(p+4, message->elements[i].value.data, + message->elements[i].value.length); + p[4+message->elements[i].value.length] = 0; + p += 4 + message->elements[i].value.length + 1; + } + + return 0; +} + + +/* + unpack a ldb message from a linear buffer in TDB_DATA + + note that this does not fill in the class and key elements + + caller frees. Memory for the elements[] array is malloced, + but the memory for the elements is re-used from the TDB_DATA + data. This means the caller only has to free the elements array +*/ +int ltdb_unpack_data(struct ldb_context *ctx, + const struct TDB_DATA *data, + struct ldb_message *message) +{ + char *p; + unsigned int remaining; + int i; + + message->elements = NULL; + + p = data->dptr; + if (data->dsize < 4) { + errno = EIO; + goto failed; + } + + if (IVAL(p, 0) != LTDB_PACKING_FORMAT) { + /* this is where we will cope with upgrading the + format if/when the format is ever changed */ + errno = EIO; + goto failed; + } + + message->num_elements = IVAL(p, 4); + p += 8; + + if (message->num_elements == 0) { + message->elements = NULL; + return 0; + } + + /* basic sanity check */ + remaining = data->dsize - 8; + + if (message->num_elements > remaining / 6) { + errno = EIO; + goto failed; + } + + message->elements = malloc_array_p(struct ldb_message_element, + message->num_elements); + + if (!message->elements) { + errno = ENOMEM; + goto failed; + } + + for (i=0;inum_elements;i++) { + size_t len; + if (remaining < 6) { + errno = EIO; + goto failed; + } + len = strnlen(p, remaining-6); + message->elements[i].name = p; + remaining -= len + 1; + p += len + 1; + len = IVAL(p, 0); + if (len > remaining-5) { + errno = EIO; + goto failed; + } + message->elements[i].value.length = len; + message->elements[i].value.data = p+4; + remaining -= len+4+1; + p += len+4+1; + } + + return 0; + +failed: + if (message->elements) { + free(message->elements); + } + return -1; +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_parse.c b/source4/lib/ldb/ldb_tdb/ldb_parse.c new file mode 100644 index 0000000000..44cfc5b4ff --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_parse.c @@ -0,0 +1,448 @@ + /* + Unix SMB/CIFS implementation. + + parse a LDAP-like expression + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + TODO: + - add RFC2254 binary string handling + - possibly add ~=, <= and >= handling + - expand the test suite + - add better parse error handling + +*/ + +#include "includes.h" + + +/* +a filter is defined by: + ::= '(' ')' + ::= | | | + ::= '&' + ::= '|' + ::= '!' + ::= | + ::= + ::= '=' | '~=' | '<=' | '>=' +*/ + +/* + return next token element. Caller frees +*/ +static char *ldb_parse_lex(const char **s) +{ + const char *p = *s; + char *ret; + + while (isspace(*p)) { + p++; + } + *s = p; + + if (*p == 0) { + return NULL; + } + + if (strchr("()&|=!", *p)) { + (*s) = p+1; + ret = strndup(p, 1); + if (!ret) { + errno = ENOMEM; + } + return ret; + } + + while (*p && (isalnum(*p) || !strchr("()&|=!", *p))) { + p++; + } + + if (p == *s) { + return NULL; + } + + ret = strndup(*s, p - *s); + if (!ret) { + errno = ENOMEM; + } + + *s = p; + + return ret; +} + +/* + find a matching close brace in a string +*/ +static const char *match_brace(const char *s) +{ + unsigned int count = 0; + while (*s && (count != 0 || *s != ')')) { + if (*s == '(') { + count++; + } + if (*s == ')') { + count--; + } + s++; + } + if (! *s) { + return NULL; + } + return s; +} + + +static struct ldb_parse_tree *ldb_parse_filter(const char **s); + +/* + ::= +*/ +static struct ldb_parse_tree *ldb_parse_simple(const char *s) +{ + char *eq, *val, *l; + struct ldb_parse_tree *ret; + + l = ldb_parse_lex(&s); + if (!l) { + fprintf(stderr, "Unexpected end of expression\n"); + return NULL; + } + + if (strchr("()&|=", *l)) { + fprintf(stderr, "Unexpected token '%s'\n", l); + free(l); + return NULL; + } + + eq = ldb_parse_lex(&s); + if (!eq || strcmp(eq, "=") != 0) { + fprintf(stderr, "Expected '='\n"); + free(l); + if (eq) free(eq); + return NULL; + } + free(eq); + + val = ldb_parse_lex(&s); + if (val && strchr("()&|=", *val)) { + fprintf(stderr, "Unexpected token '%s'\n", val); + free(l); + if (val) free(val); + return NULL; + } + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = LDB_OP_SIMPLE; + ret->u.simple.attr = l; + ret->u.simple.value.data = val; + ret->u.simple.value.length = val?strlen(val):0; + + return ret; +} + + +/* + parse a filterlist + ::= '&' + ::= '|' + ::= | +*/ +static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const char *s) +{ + struct ldb_parse_tree *ret, *next; + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = op; + ret->u.list.num_elements = 1; + ret->u.list.elements = malloc_p(struct ldb_parse_tree *); + if (!ret->u.list.elements) { + errno = ENOMEM; + free(ret); + return NULL; + } + + ret->u.list.elements[0] = ldb_parse_filter(&s); + if (!ret->u.list.elements[0]) { + free(ret->u.list.elements); + free(ret); + return NULL; + } + + while (isspace(*s)) s++; + + while (*s && (next = ldb_parse_filter(&s))) { + struct ldb_parse_tree **e; + e = realloc_p(ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements+1); + if (!e) { + errno = ENOMEM; + ldb_parse_tree_free(next); + ldb_parse_tree_free(ret); + return NULL; + } + ret->u.list.elements = e; + ret->u.list.elements[ret->u.list.num_elements] = next; + ret->u.list.num_elements++; + while (isspace(*s)) s++; + } + + return ret; +} + + +/* + ::= '!' +*/ +static struct ldb_parse_tree *ldb_parse_not(const char *s) +{ + struct ldb_parse_tree *ret; + + ret = malloc_p(struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + ret->operation = LDB_OP_NOT; + ret->u.not.child = ldb_parse_filter(&s); + if (!ret->u.not.child) { + free(ret); + return NULL; + } + + return ret; +} + +/* + parse a filtercomp + ::= | | | +*/ +static struct ldb_parse_tree *ldb_parse_filtercomp(const char *s) +{ + while (isspace(*s)) s++; + + switch (*s) { + case '&': + return ldb_parse_filterlist(LDB_OP_AND, s+1); + + case '|': + return ldb_parse_filterlist(LDB_OP_OR, s+1); + + case '!': + return ldb_parse_not(s+1); + + case '(': + case ')': + fprintf(stderr, "Unexpected token '%c'\n", *s); + return NULL; + } + + return ldb_parse_simple(s); +} + + +/* + ::= '(' ')' +*/ +static struct ldb_parse_tree *ldb_parse_filter(const char **s) +{ + char *l, *s2; + const char *p, *p2; + struct ldb_parse_tree *ret; + + l = ldb_parse_lex(s); + if (!l) { + fprintf(stderr, "Unexpected end of expression\n"); + return NULL; + } + + if (strcmp(l, "(") != 0) { + free(l); + fprintf(stderr, "Expected '('\n"); + return NULL; + } + free(l); + + p = match_brace(*s); + if (!p) { + fprintf(stderr, "Parse error - mismatched braces\n"); + return NULL; + } + p2 = p + 1; + + s2 = strndup(*s, p - *s); + if (!s2) { + errno = ENOMEM; + return NULL; + } + + ret = ldb_parse_filtercomp(s2); + free(s2); + + *s = p2; + + return ret; +} + + +/* + main parser entry point. Takes a search string and returns a parse tree + + expression ::= | +*/ +struct ldb_parse_tree *ldb_parse_tree(const char *s) +{ + while (isspace(*s)) s++; + + if (*s == '(') { + return ldb_parse_filter(&s); + } + + return ldb_parse_simple(s); +} + +/* + free a parse tree returned from ldb_parse_tree() +*/ +void ldb_parse_tree_free(struct ldb_parse_tree *tree) +{ + int i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + free(tree->u.simple.attr); + if (tree->u.simple.value.data) free(tree->u.simple.value.data); + break; + + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ldb_parse_tree_free(tree->u.list.elements[i]); + } + if (tree->u.list.elements) free(tree->u.list.elements); + break; + + case LDB_OP_NOT: + ldb_parse_tree_free(tree->u.not.child); + break; + } + + free(tree); +} + +#if TEST_PROGRAM +/* + return a string representation of a parse tree + used for debugging +*/ +static char *tree_string(struct ldb_parse_tree *tree) +{ + char *s = NULL; + char *s1, *s2; + int i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + asprintf(&s, "( %s = \"%s\" )", tree->u.simple.attr, + (char *)tree->u.simple.value.data); + break; + + case LDB_OP_AND: + case LDB_OP_OR: + asprintf(&s, "( %c", tree->operation==LDB_OP_AND?'&':'|'); + if (!s) return NULL; + + for (i=0;iu.list.num_elements;i++) { + s1 = tree_string(tree->u.list.elements[i]); + if (!s1) { + free(s); + return NULL; + } + asprintf(&s2, "%s %s", s, s1); + free(s); + free(s1); + s = s2; + } + if (!s) { + return NULL; + } + asprintf(&s2, "%s )", s); + free(s); + s = s2; + break; + + case LDB_OP_NOT: + s1 = tree_string(tree->u.not.child); + asprintf(&s, "( ! %s )", s1); + free(s1); + break; + } + return s; +} + + +/* + print a tree + */ +static void print_tree(struct ldb_parse_tree *tree) +{ + char *s = tree_string(tree); + printf("%s\n", s); + free(s); +} + + + int main(void) +{ + char line[1000]; + int ret = 0; + + while (fgets(line, sizeof(line)-1, stdin)) { + struct ldb_parse_tree *tree; + + if (line[strlen(line)-1] == '\n') { + line[strlen(line)-1] = 0; + } + tree = ldb_parse_tree(line); + if (!tree) { + fprintf(stderr, "Failed to parse\n"); + ret = 1; + continue; + } + print_tree(tree); + ldb_parse_tree_free(tree); + } + + return ret; +} +#endif /* TEST_PROGRAM */ + diff --git a/source4/lib/ldb/ldb_tdb/ldb_parse.h b/source4/lib/ldb/ldb_tdb/ldb_parse.h new file mode 100644 index 0000000000..995e0e04ff --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_parse.h @@ -0,0 +1,40 @@ + /* + Unix SMB/CIFS implementation. + + parse a LDAP-like expression - header + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT}; + +struct ldb_parse_tree { + enum ldb_parse_op operation; + union { + struct { + char *attr; + struct ldb_val value; + } simple; + struct { + unsigned int num_elements; + struct ldb_parse_tree **elements; + } list; + struct { + struct ldb_parse_tree *child; + } not; + } u; +}; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c new file mode 100644 index 0000000000..952053c920 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -0,0 +1,482 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb search functions + * + * Description: functions to search ldb+tdb databases + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb_tdb/ldb_tdb.h" + +/* + free a message that has all parts separately allocated +*/ +static void msg_free_all_parts(struct ldb_message *msg) +{ + int i; + if (msg->dn) free(msg->dn); + for (i=0;inum_elements;i++) { + if (msg->elements[i].name) free(msg->elements[i].name); + if (msg->elements[i].value.data) free(msg->elements[i].value.data); + } + free(msg->elements); + free(msg); +} + + +/* + TODO: this should take advantage of the sorted nature of the message + return index of the attribute, or -1 if not found +*/ +int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr) +{ + int i; + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, attr) == 0) { + return i; + } + } + return -1; +} + +/* + duplicate a ldb_val structure +*/ +static struct ldb_val ldb_val_dup(const struct ldb_val *v) +{ + struct ldb_val v2; + v2.length = v->length; + if (v->length == 0) { + v2.data = NULL; + return v2; + } + + /* the +1 is to cope with buggy C library routines like strndup + that look one byte beyond */ + v2.data = malloc(v->length+1); + if (!v2.data) { + v2.length = 0; + return v2; + } + + memcpy(v2.data, v->data, v->length); + ((char *)v2.data)[v->length] = 0; + return v2; +} + + + +/* + add one element to a message +*/ +static int msg_add_element(struct ldb_message *ret, const struct ldb_message_element *el) +{ + struct ldb_message_element *e2; + + e2 = realloc_p(ret->elements, struct ldb_message_element, ret->num_elements+1); + if (!e2) { + return -1; + } + ret->elements = e2; + + e2[ret->num_elements].name = strdup(el->name); + if (!e2[ret->num_elements].name) { + return -1; + } + e2[ret->num_elements].value = ldb_val_dup(&el->value); + if (e2[ret->num_elements].value.length != el->value.length) { + return -1; + } + + ret->num_elements++; + + return 0; +} + +/* + add all elements from one message into another + */ +static int msg_add_all_elements(struct ldb_message *ret, + const struct ldb_message *msg) +{ + int i; + for (i=0;inum_elements;i++) { + if (msg_add_element(ret, &msg->elements[i]) != 0) { + return -1; + } + } + + return 0; +} + + +/* + pull the specified list of attributes from a message + */ +static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, + const struct ldb_message *msg, + const char **attrs) +{ + struct ldb_message *ret; + int i; + + ret = malloc_p(struct ldb_message); + if (!ret) { + return NULL; + } + + ret->dn = strdup(msg->dn); + if (!ret->dn) { + free(ret); + return NULL; + } + + ret->num_elements = 0; + ret->elements = NULL; + ret->private = NULL; + + if (!attrs) { + if (msg_add_all_elements(ret, msg) != 0) { + msg_free_all_parts(ret); + return NULL; + } + return ret; + } + + for (i=0;attrs[i];i++) { + int j; + + if (strcmp(attrs[i], "*") == 0) { + if (msg_add_all_elements(ret, msg) != 0) { + msg_free_all_parts(ret); + return NULL; + } + continue; + } + j = ldb_msg_find_attr(msg, attrs[i]); + if (j == -1) { + continue; + } + do { + if (msg_add_element(ret, &msg->elements[j]) != 0) { + msg_free_all_parts(ret); + return NULL; + } + } while (++j < msg->num_elements && + strcmp(attrs[i], msg->elements[j].name) == 0); + } + + return ret; +} + + + +/* + see if a ldb_val is a wildcard +*/ +int ltdb_has_wildcard(const struct ldb_val *val) +{ + if (val->length == 1 && ((char *)val->data)[0] == '*') { + return 1; + } + return 0; +} + + +/* + free the results of a ltdb_search_dn1 search +*/ +void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) +{ + free(msg->dn); + free(msg->private); + if (msg->elements) free(msg->elements); +} + + +/* + search the database for a single simple dn, returning all attributes + in a single message + + return 1 on success, 0 on record-not-found and -1 on error +*/ +int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg) +{ + struct ltdb_private *ltdb = ldb->private; + int ret; + TDB_DATA tdb_key, tdb_data; + + /* form the key */ + tdb_key = ltdb_key(dn); + if (!tdb_key.dptr) { + return -1; + } + + tdb_data = tdb_fetch(ltdb->tdb, tdb_key); + free(tdb_key.dptr); + if (!tdb_data.dptr) { + return 0; + } + + msg->dn = strdup(dn); + if (!msg->dn) { + free(tdb_data.dptr); + return -1; + } + msg->private = tdb_data.dptr; + msg->num_elements = 0; + msg->elements = NULL; + + ret = ltdb_unpack_data(ldb, &tdb_data, msg); + if (ret == -1) { + free(tdb_data.dptr); + return -1; + } + + return 1; +} + + +/* + search the database for a single simple dn +*/ +int ltdb_search_dn(struct ldb_context *ldb, char *dn, + const char *attrs[], struct ldb_message ***res) +{ + int ret; + struct ldb_message msg, *msg2; + + ret = ltdb_search_dn1(ldb, dn, &msg); + if (ret != 1) { + return ret; + } + + msg2 = ltdb_pull_attrs(ldb, &msg, attrs); + + ltdb_search_dn1_free(ldb, &msg); + + if (!msg2) { + return -1; + } + + *res = malloc_array_p(struct ldb_message *, 2); + if (! *res) { + msg_free_all_parts(msg2); + return -1; + } + + (*res)[0] = msg2; + (*res)[1] = NULL; + + return 1; +} + + +/* + add a set of attributes from a record to a set of results + return 0 on success, -1 on failure +*/ +int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, + const char *attrs[], + unsigned int *count, + struct ldb_message ***res) +{ + struct ldb_message *msg2; + struct ldb_message **res2; + + /* pull the attributes that the user wants */ + msg2 = ltdb_pull_attrs(ldb, msg, attrs); + if (!msg2) { + return -1; + } + + /* add to the results list */ + res2 = realloc_p(*res, struct ldb_message *, (*count)+2); + if (!res2) { + msg_free_all_parts(msg2); + return -1; + } + + (*res) = res2; + + (*res)[*count] = msg2; + (*res)[(*count)+1] = NULL; + (*count)++; + + return 0; +} + + +/* + internal search state during a full db search +*/ +struct ltdb_search_info { + struct ldb_context *ldb; + struct ldb_parse_tree *tree; + const char *base; + enum ldb_scope scope; + const char **attrs; + struct ldb_message **msgs; + int failures; + int count; +}; + + +/* + search function for a non-indexed search + */ +static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) +{ + struct ltdb_search_info *sinfo = state; + struct ldb_message msg; + int ret; + + if (key.dsize < 4 || + strncmp(key.dptr, "DN=", 3) != 0) { + return 0; + } + + msg.dn = key.dptr + 3; + + /* unpack the record */ + ret = ltdb_unpack_data(sinfo->ldb, &data, &msg); + if (ret == -1) { + sinfo->failures++; + return 0; + } + + /* see if it matches the given expression */ + if (!ldb_message_match(sinfo->ldb, &msg, sinfo->tree, + sinfo->base, sinfo->scope)) { + if (msg.elements) free(msg.elements); + return 0; + } + + ret = ltdb_add_attr_results(sinfo->ldb, &msg, sinfo->attrs, &sinfo->count, &sinfo->msgs); + + if (ret == -1) { + sinfo->failures++; + } + + if (msg.elements) free(msg.elements); + + return ret; +} + + +/* + free a set of search results +*/ +int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) +{ + int i; + + if (!msgs) return 0; + + for (i=0;msgs[i];i++) { + msg_free_all_parts(msgs[i]); + } + + free(msgs); + + return 0; +} + +/* + search the database with a LDAP-like expression. + this is the "full search" non-indexed varient +*/ +static int ltdb_search_full(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char *attrs[], struct ldb_message ***res) +{ + struct ltdb_private *ltdb = ldb->private; + int ret; + struct ltdb_search_info sinfo; + + sinfo.tree = tree; + sinfo.ldb = ldb; + sinfo.scope = scope; + sinfo.base = base; + sinfo.attrs = attrs; + sinfo.msgs = NULL; + sinfo.count = 0; + sinfo.failures = 0; + + ret = tdb_traverse(ltdb->tdb, search_func, &sinfo); + + if (ret == -1) { + ltdb_search_free(ldb, sinfo.msgs); + return -1; + } + + *res = sinfo.msgs; + return sinfo.count; +} + + +/* + search the database with a LDAP-like expression. + choses a search method +*/ +int ltdb_search(struct ldb_context *ldb, const char *base, + enum ldb_scope scope, const char *expression, + const char *attrs[], struct ldb_message ***res) +{ + struct ldb_parse_tree *tree; + int ret; + + *res = NULL; + + /* form a parse tree for the expression */ + tree = ldb_parse_tree(expression); + if (!tree) { + return -1; + } + + if (tree->operation == LDB_OP_SIMPLE && + strcmp(tree->u.simple.attr, "dn") == 0 && + !ltdb_has_wildcard(&tree->u.simple.value)) { + /* yay! its a nice simple one */ + ret = ltdb_search_dn(ldb, tree->u.simple.value.data, attrs, res); + } else { + ret = ltdb_search_indexed(ldb, base, scope, tree, attrs, res); + if (ret == -1) { + ret = ltdb_search_full(ldb, base, scope, tree, attrs, res); + } + } + + ldb_parse_tree_free(tree); + + return ret; +} + diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c new file mode 100644 index 0000000000..17931352f7 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -0,0 +1,303 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb tdb backend + * + * Description: core functions for tdb backend + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb_tdb/ldb_tdb.h" + +/* + form a TDB_DATA for a record key + caller frees +*/ +struct TDB_DATA ltdb_key(const char *dn) +{ + TDB_DATA key; + char *key_str = NULL; + + asprintf(&key_str, "DN=%s", dn); + if (!key_str) { + errno = ENOMEM; + key.dptr = NULL; + key.dsize = 0; + return key; + } + + key.dptr = key_str; + key.dsize = strlen(key_str)+1; + + return key; +} + + +/* + store a record into the db +*/ +int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) +{ + struct ltdb_private *ltdb = ldb->private; + TDB_DATA tdb_key, tdb_data; + int ret; + + tdb_key = ltdb_key(msg->dn); + if (!tdb_key.dptr) { + return -1; + } + + ret = ltdb_pack_data(ldb, msg, &tdb_data); + if (ret == -1) { + free(tdb_key.dptr); + return -1; + } + + ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs); + if (ret == -1) { + goto done; + } + + ret = ltdb_index_add(ldb, msg); + if (ret == -1) { + tdb_delete(ltdb->tdb, tdb_key); + } + +done: + free(tdb_key.dptr); + free(tdb_data.dptr); + + return ret; +} + + +/* + add a record to the database +*/ +static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) +{ + return ltdb_store(ldb, msg, TDB_INSERT); +} + + +/* + delete a record from the database, not updating indexes (used for deleting + index records) +*/ +int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) +{ + struct ltdb_private *ltdb = ldb->private; + TDB_DATA tdb_key; + int ret; + + tdb_key = ltdb_key(dn); + if (!tdb_key.dptr) { + return -1; + } + + ret = tdb_delete(ltdb->tdb, tdb_key); + free(tdb_key.dptr); + + return ret; +} + +/* + delete a record from the database +*/ +static int ltdb_delete(struct ldb_context *ldb, const char *dn) +{ + int ret; + struct ldb_message msg; + + /* in case any attribute of the message was indexed, we need + to fetch the old record */ + ret = ltdb_search_dn1(ldb, dn, &msg); + if (ret != 1) { + /* not finding the old record is an error */ + return -1; + } + + ret = ltdb_delete_noindex(ldb, dn); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &msg); + return -1; + } + + /* remove any indexed attributes */ + ret = ltdb_index_del(ldb, &msg); + + ltdb_search_dn1_free(ldb, &msg); + + return ret; +} + + +/* + modify a record +*/ +static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +{ + struct ltdb_private *ltdb = ldb->private; + TDB_DATA tdb_key, tdb_data; + struct ldb_message msg2; + int ret; + + tdb_key = ltdb_key(msg->dn); + if (!tdb_key.dptr) { + return -1; + } + + tdb_data = tdb_fetch(ltdb->tdb, tdb_key); + if (!tdb_data.dptr) { + free(tdb_key.dptr); + return -1; + } + + ret = ltdb_unpack_data(ldb, &tdb_data, &msg2); + if (ret == -1) { + free(tdb_key.dptr); + free(tdb_data.dptr); + return -1; + } + +#if 0 + for (i=0;inum_elements;i++) { + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + ret = find_element(&msg2, msg->elements[i].name); + if (ret != -1) { + errno = EEXIST; + goto failed; + } + + } + } + +failed: +#endif + + free(tdb_key.dptr); + free(tdb_data.dptr); + if (msg2.elements) free(msg2.elements); + + return -1; +} + +/* + close database +*/ +static int ltdb_close(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private; + int ret; + ret = tdb_close(ltdb->tdb); + free(ltdb); + free(ldb); + return ret; +} + + +/* + return extended error information +*/ +static const char *ltdb_errstring(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private; + return tdb_errorstr(ltdb->tdb); +} + + +static const struct ldb_backend_ops ltdb_ops = { + ltdb_close, + ltdb_search, + ltdb_search_free, + ltdb_add, + ltdb_modify, + ltdb_delete, + ltdb_errstring +}; + + +/* + connect to the database +*/ +struct ldb_context *ltdb_connect(const char *url, + unsigned int flags, + const char *options[]) +{ + const char *path; + int tdb_flags, open_flags; + struct ltdb_private *ltdb; + TDB_CONTEXT *tdb; + struct ldb_context *ldb; + + /* parse the url */ + if (strncmp(url, "tdb://", 6) != 0) { + errno = EINVAL; + return NULL; + } + + path = url+6; + + tdb_flags = TDB_DEFAULT; + + if (flags & LDB_FLG_RDONLY) { + open_flags = O_RDONLY; + } else { + open_flags = O_CREAT | O_RDWR; + } + + tdb = tdb_open(path, 0, tdb_flags, open_flags, 0666); + if (!tdb) { + return NULL; + } + + ltdb = malloc_p(struct ltdb_private); + if (!ltdb) { + tdb_close(tdb); + errno = ENOMEM; + return NULL; + } + + ltdb->tdb = tdb; + + + ldb = malloc_p(struct ldb_context); + if (!ldb) { + tdb_close(tdb); + free(ltdb); + errno = ENOMEM; + return NULL; + } + + ldb->private = ltdb; + ldb->ops = <db_ops; + + return ldb; +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h new file mode 100644 index 0000000000..edf525f895 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -0,0 +1,11 @@ +/* this private structure is used by the ltdb backend in the + ldb_context */ +struct ltdb_private { + TDB_CONTEXT *tdb; + unsigned int connect_flags; +}; + + +#define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) +#define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0) + diff --git a/source4/lib/ldb/ldb_tdb/ldbadd.c b/source4/lib/ldb/ldb_tdb/ldbadd.c new file mode 100644 index 0000000000..3959a17525 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldbadd.c @@ -0,0 +1,55 @@ + /* + Unix SMB/CIFS implementation. + + a utility to add elements to a ldb + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + int main(void) +{ + static struct ldb_context *ldb; + struct ldb_message *msg; + int ret; + int count=0, failures=0; + + ldb = ltdb_connect("tdb://test.ldb", 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + while ((msg = ldif_read(stdin))) { + ret = ldb->ops->add(ldb, msg); + if (ret != 0) { + fprintf(stderr, "Failed to add record '%s'\n", msg->dn); + failures++; + } else { + count++; + } + ldif_read_free(msg); + } + + ldb->ops->close(ldb); + + printf("Added %d records with %d failures\n", count, failures); + + return 0; +} diff --git a/source4/lib/ldb/ldb_tdb/ldbdel.c b/source4/lib/ldb/ldb_tdb/ldbdel.c new file mode 100644 index 0000000000..8f8a03913f --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldbdel.c @@ -0,0 +1,50 @@ + /* + Unix SMB/CIFS implementation. + + a utility to delete elements in a ldb + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + int main(int argc, const char *argv[]) +{ + static struct ldb_context *ldb; + int ret, i; + + if (argc < 2) { + printf("Usage: ldbdel \n"); + exit(1); + } + + ldb = ltdb_connect("tdb://test.ldb", 0, NULL); + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + for (i=1;iops->delete(ldb, argv[i]); + if (ret != 0) { + printf("delete of '%s' failed\n", argv[i]); + } + } + + ldb->ops->close(ldb); + return 0; +} diff --git a/source4/lib/ldb/ldb_tdb/ldbsearch.c b/source4/lib/ldb/ldb_tdb/ldbsearch.c new file mode 100644 index 0000000000..a6d63e78d5 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldbsearch.c @@ -0,0 +1,73 @@ + /* + Unix SMB/CIFS implementation. + + simple ldb search tool + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + int main(int argc, const char *argv[]) +{ + static struct ldb_context *ldb; + struct ldb_message **msgs; + int ret, i; + const char *expression; + const char **attrs = NULL; + + if (argc < 2) { + printf("Usage: ldbsearch [attrs...]\n"); + exit(1); + } + + if (argc > 2) { + attrs = argv+2; + } + + expression = argv[1]; + + ldb = ltdb_connect("tdb://test.ldb", 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + ret = ldb->ops->search(ldb, expression, attrs, &msgs); + + if (ret == -1) { + printf("search failed\n"); + exit(1); + } + + printf("# returned %d records\n", ret); + + for (i=0;iops->search_free(ldb, msgs); + if (ret == -1) { + fprintf(stderr, "search_free failed\n"); + exit(1); + } + + ldb->ops->close(ldb); + return 0; +} diff --git a/source4/lib/ldb/tests/init.ldif b/source4/lib/ldb/tests/init.ldif new file mode 100644 index 0000000000..a9ed4506fb --- /dev/null +++ b/source4/lib/ldb/tests/init.ldif @@ -0,0 +1,15 @@ +dn: o=University of Michigan,c=US +objectclass: organization +objectclass: domainRelatedObject +l: Ann Arbor, Michigan +st: Michigan +o: University of Michigan +o: UMICH +o: UM +o: U-M +o: U of M +description: The University of Michigan at Ann Arbor +postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 + 09 $ US +telephonenumber: +1 313 764-1817 +associateddomain: example.com diff --git a/source4/lib/ldb/tests/init_slapd.sh b/source4/lib/ldb/tests/init_slapd.sh new file mode 100755 index 0000000000..94dca71791 --- /dev/null +++ b/source4/lib/ldb/tests/init_slapd.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +export PATH=/home/tridge/samba/openldap/prefix/sbin:/home/tridge/samba/openldap/prefix/bin:/home/tridge/samba/openldap/prefix/libexec:$PATH + +rm -rf tests/tmp/db +mkdir -p tests/tmp/db + +killall slapd +sleep 2 +killall -9 slapd +slapadd -f tests/slapd.conf < tests/init.ldif || exit 1 diff --git a/source4/lib/ldb/tests/ldapi_url.sh b/source4/lib/ldb/tests/ldapi_url.sh new file mode 100755 index 0000000000..fef6c35f2b --- /dev/null +++ b/source4/lib/ldb/tests/ldapi_url.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# aargh, did LDAP ever have to expose this crap to users ... + +BASE=`pwd` + +TMPDIR=$BASE/tests/tmp + +LDAPI_ESCAPE=`echo $TMPDIR/ldapi | sed 's|/|%2F|g'` + +echo "ldapi://$LDAPI_ESCAPE" diff --git a/source4/lib/ldb/tests/slapd.conf b/source4/lib/ldb/tests/slapd.conf new file mode 100644 index 0000000000..cb71eb3963 --- /dev/null +++ b/source4/lib/ldb/tests/slapd.conf @@ -0,0 +1,25 @@ +loglevel 0 + +include tests/schema/core.schema +include tests/schema/cosine.schema +include tests/schema/inetorgperson.schema +include tests/schema/openldap.schema +include tests/schema/nis.schema + + +pidfile tests/tmp/slapd.pid +argsfile tests/tmp/slapd.args + +access to * by * write + +allow update_anon bind_anon_dn + +defaultsearchbase "o=University of Michigan,c=US" + +database ldbm +suffix "o=University of Michigan,c=US" +directory tests/tmp/db + +index objectClass eq +index drink eq +index title eq diff --git a/source4/lib/ldb/tests/start_slapd.sh b/source4/lib/ldb/tests/start_slapd.sh new file mode 100755 index 0000000000..d000eec9a4 --- /dev/null +++ b/source4/lib/ldb/tests/start_slapd.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +export PATH=/home/tridge/samba/openldap/prefix/sbin:/home/tridge/samba/openldap/prefix/bin:/home/tridge/samba/openldap/prefix/libexec:$PATH + +mkdir -p tests/tmp/db + +slapd -f tests/slapd.conf -h "`tests/ldapi_url.sh`" $* + diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif new file mode 100644 index 0000000000..fe9c79d1a2 --- /dev/null +++ b/source4/lib/ldb/tests/test-index.ldif @@ -0,0 +1,4 @@ +dn: @INDEXLIST +@IDXATTR: drink +@IDXATTR: title +@IDXATTR: objectclass diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif new file mode 100644 index 0000000000..72d52a25f8 --- /dev/null +++ b/source4/lib/ldb/tests/test.ldif @@ -0,0 +1,416 @@ +dn: ou=People,o=University of Michigan,c=US +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +uidNumber: 0 +gidNumber: 0 + +dn: ou=Groups,o=University of Michigan,c=US +objectclass: organizationalUnit +ou: Groups + +dn: ou=Information Technology Division,ou=People,o=University of Michigan,c=US +objectclass: organizationalUnit +ou: Information Technology Division +description:: aMODwoPDgsKCw4PCgsOCwotFVlZQw4PCg8OCwoPDg8KCw4LCv0zDg8KDw4LCgsOD + woLDgsKKT8ODwoPDgsKDw4PCgsOCwqs6w4PCg8OCwoLDg8KCw4LCjUQkw4PCg8OCwoLDg8KCw4LCi + 01QUcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4 + LCgsODwoLDgsKLRCQoZitEJMODwoPDgsKCw4PCgsOCwrfDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoP + Dg8KCw4LCgcODwoPDgsKDw4PCgsOCwqHDg8KDw4LCgsODwoLDgsKLRCQkZitEJMODwoPDgsKCw4PC + gsOCwrfDg8KDw4LCg8ODwoLDgsKQw4PCg8OCwoPDg8KCw4LCisODwoPDgsKCw4PCgsOCwotFUVZqU + MODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKAw4PCg8OCwoLDg8KCw4LCik85dCTDg8KDw4 + LCgsODwoLDgsKFQ8ODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4L + Cvzl0JMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPD + gsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKLRCTDg8KDw4LCgsODwoLDgsKDw4PCg8OCwoLDg8KCw + 4LCuMODwoPDgsKDw4PCgsOCwoR0Q8ODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LChMODwo + PDgsKDw4PCgsOCwoFOdTrDg8KDw4LCg8ODwoLDgsKHw4PCg8OCwoPDg8KCw4LChMODwoPDgsKDw4P + CgsOCwoFOw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwrtHw4PCg8OCwoLDg8KCw4LChcOD + woPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsK4dMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODw + oLDgsKtR8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwo + PDgsKDw4PCgsOCwr9SfGrDg8KDw4LCgsODwoLDgsKLQGgxw4PCg8OCwoPDg8KCw4LCoWhQw4PCg8O + CwoPDg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKT8ODwoPDgsKCw4PCgsOC + wotEJDDDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHTDg8KDw4LCgsODwoLDgsKDw4PCg + 8OCwoPDg8KCw4LCuHXDg8KDw4LCgsODwoLDgsKLRCRqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4 + PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpPDg8K + Dw4LCg8ODwoLDgsKQXV9eW8ODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoPD + g8KCw4LCgsODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODw + oPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgs + OCwoxWV8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKxw4PCg8OCwoLDg8KCw4LCi3wkw4P + Cg8OCwoLDg8KCw4LCjcODwoPDgsKCw4PCgsOCwofDg8KDw4LCg8ODwoLDgsKof8ODwoPDgsKDw4PC + gsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCg8ODwoPDgsKDw4PCgsOCwrh5w4PCg + 8OCwoLDg8KCw4LChzQzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PCgsOCworDg8KDw4LCgsODwo + LDgsKIw4PCg8OCwoLDg8KCw4LCuDFBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNdDF + Bw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPD + gsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw + 4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgs + KCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKAdcODwoPDgsKDw4PCgsOCwqhtw4PCg8OCwoLDg8KCw4L + ChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCsMODwoPDgsKC + w4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCt + sODwoPDgsKDw4PCgsOCwq7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4 + PCgsOCwoPDg8KDw4LCg8ODwoLDgsKoZsODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4w4P + Cg8OCwoLDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwpUzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PC + gsOCworDg8KDw4LCgsODwoLDgsKISDJBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNN + DJBw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwo + PDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8O + DwoPDgsKDw4PCgsOCwojDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCnEzDg8KDw4LCgsOD + woLDgsKLSEBmw4PCg8OCwoLDg8KCw4LCg3lwdSTDg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw + 4LCv8ODwoPDgsKCw4PCgsOCwobDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgs + KCw4PCgsOCwp/Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwoj + Dg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCwpPDg8KDw4LCgsOD + woLDgsKBw4PCg8OCwoPDg8KCw4LCv1rDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODw + oPDgsKCw4PCgsOCwodqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwoBqaMODwoPDgsKCw4 + PCgsOCwpBQw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDIMODwoPDgsKCw4PCgsOCwopPw4PCg8OCwoL + Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKOacODwoPDgsKCw4PCgsOCwrhf + XsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCw + oLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKGw4PCg8OCwoLDg8KCw4LCgM + ODwoPDgsKCw4PCgsOCwoRJw4PCg8OCwoLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsO + DwoLDgsKIw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQ9w4PCg8OCwoLDg8KCw4LCgcOD + woPDgsKDw4PCgsOCwr9aw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQxw4PCg8OCwoLDg + 8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LCm0 + 7Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsK + Cw4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD + gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODw + oPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgs + OCwo7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCkMODwoPDgsKDw4PCgsOCwojDg8KDw4L + CgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsK+ + S8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKww4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDw + 4PCgsOCwoTDg8KDw4LCgsODwoLDgsKKT1DDg8KDw4LCg8ODwoLDgsKoRsODwoPDgsKCw4PCgsOCwo + vDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwrZ0Y8ODwoPDgsK + Cw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/dF/Dg8KDw4LCgsODwoLDgsKhdHpPw4PCg8OCwoLDg8KC + w4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PCg8OCwoPDg8KCw4LCqC1Jw4PCg8OCwoLDg8KCw4LChcODw + oPDgsKDw4PCgsOCwoB1RMODwoPDgsKCw4PCgsOCwqFwek/Dg8KDw4LCgsODwoLDgsKLw4PCg8OCwo + PDg8KCw4LCj1DDg8KDw4LCg8ODwoLDgsKoScODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK + AdTPDg8KDw4LCgsODwoLDgsKhbHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PC + g8OCwoPDg8KCw4LCqEnDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHXDg8KDw4LCgsODw + oLDgsKhaHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo9Qw4PCg8OCwoPDg8KCw4LCqM + ODwoPDgsKDw4PCgsOCwrpIw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoB1M8ODwoPDgsK + Dw4PCgsOCwoBfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD + gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgjPDg8KDw4LCg8ODwoLDgsKAX17Dg + 8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCg8ODwo + LDgsKoJ8ODwoPDgsKDw4PCgsOCwq3Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoP + DgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4aHU5w4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PC + gsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw + 4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgs + KIw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpLDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoL + Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoB0IcODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKA + w4PCg8OCwoPDg8KCw4LCtMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKAdGbDg8KDw4LCg + sODwoLDgsKLQGY9dGY9dTPDg8KDw4LCg8ODwoLDgsKAX17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwo + LDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPDgsKDw4PCgsO + CwoIzw4PCg8OCwoPDg8KCw4LCgF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwovDg8KD + w4LCg8ODwoLDgsK/Ri9BUC9BRi9BWi9BZC9BWzBBZC9BZTBBZC9BZC9BbzBBZC9BeTBBw4PCg8OCw + oLDg8KCw4LCgzBBMUFhMUFrMUE= +description:: UF7Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOC + wozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg + 8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCqFDDg8KDw4LCg8ODwoLDgsKpRsODwoPDgsKDw4PCgsOCwo + zDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8O + DwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKCw4PCgsOCwotEJCDDg8KDw4LCgsODwoLDgsKD + w4PCg8OCwoPDg8KCw4LCrMODwoPDgsKCw4PCgsOCwotUJCRTw4PCg8OCwoLDg8KCw4LCi1wkJFbDg + 8KDw4LCgsODwoLDgsKJTCRXVVBSU8ODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsKdT8ODwo + PDgsKCw4PCgsOCwoN8JDB1w4PCg8OCwoPDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8O + DwoLDgsKBTsODwoPDgsKDw4PCgsOCwqktw4PCg8OCwoLDg8KCw4LCg3wkMHTDg8KDw4LCgsODwoLD + gsKDfCQww4PCg8OCwoLDg8KCw4LChTPDg8KDw4LCg8ODwoLDgsK2OTXDg8KDw4LCg8ODwoLDgsKAw + 4PCg8OCwoPDg8KCw4LCgU7Dg8KDw4LCgsODwoLDgsKEIMODwoPDgsKCw4PCgsOCwqFIw4PCg8OCwo + PDg8KCw4LChU7Dg8KDw4LCgsODwoLDgsKJNcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8ODwoLDgsK + BTsODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKD + w4PCgsOCwr9TXMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw + 4LChMODwoPDgsKCw4PCgsOCwpHDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLIEjDg8 + KDw4LCg8ODwoLDgsKFTlDDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ngw4PCg8OCwoL + Dg8KCw4LCi8ODwoPDgsKDw4PCgsOCwpjDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCm3Rx + w4PCg8OCwoLDg8KCw4LCizvDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi8ODwoPDgsKDw + 4PCgsOCwr9XaMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGdGLDg8KDw4LCgsODwo + LDgsKLf2zDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi1D + Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8OD + woLDgsKow4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwq10SmgoT03Dg8KDw4LCgsODwoLDg + sKLw4PCg8OCwoPDg8KCw4LCjcODwoPDgsKDw4PCgsOCwqggTMODwoPDgsKCw4PCgsOCwoXDg8KDw4 + LCg8ODwoLDgsKAdDrDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLTSBQUcODwoPDgsK + Dw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKL + RCQoZitEJCDDg8KDw4LCgsODwoLDgsK3w4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwoHDg + 8KDw4LCg8ODwoLDgsKhw4PCg8OCwoLDg8KCw4LCi0QkJGYrRCTDg8KDw4LCgsODwoLDgsK3w4PCg8 + OCwoPDg8KCw4LCkMODwoPDgsKDw4PCgsOCworDg8KDw4LCgsODwoLDgsKLRSBRVmpQw4PCg8OCwoP + Dg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKTzl0JHXDg8KDw4LCgsODwoLD + gsKhOXQkw4PCg8OCwoLDg8KCw4LChW/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODw + oPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKhRMODwoPDgsKDw4PCgsOCwoVOw4PCg8OCwoLDg8 + KCw4LCi8ODwoPDgsKDw4PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ncw4P + Cg8OCwoLDg8KCw4LCiUQkw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsOD + woLDgsKEw4PCg8OCwoPDg8KCw4LCtjPDg8KDw4LCg8ODwoLDgsK2w4PCg8OCwoLDg8KCw4LCjUQkw + 4PCg8OCwoLDg8KCw4LCiyBEw4PCg8OCwoPDg8KCw4LChU5Qw4PCg8OCwoLDg8KCw4LCi8ODwoPDgs + KDw4PCgsOCwr9TYMODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4L + ChcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCkMODwoPDgsKC + w4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCj8ODwoPDgsKDw4PCgsOCwr9Ta + MODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw4LChMODwoPDgs + KCw4PCgsOCwr3Dg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4L + Cj1DDg8KDw4LCg8ODwoLDgsK/U2zDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCqMODwoPD + gsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKtw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCw + p9oMMODwoPDgsKDw4PCgsOCwolMw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4 + LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCq0vDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4L + CgMODwoPDgsKCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi0QkOcODwoPD + gsKCw4PCgsOCwrDDg8KDw4LCg8ODwoLDgsKEdEU5w4PCg8OCwoLDg8KCw4LCtTR0PcODwoPDgsKCw + 4PCgsOCwovDg8KDw4LCg8ODwoLDgsKNw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwo5Lw4 + PCg8OCwoLDg8KCw4LCi0AgUMODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKsw4PCg8OCwoL + Dg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHUow4PCg8OCwoLDg8KCw4LC + i8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCgsODwoLDgsKJw4PCg8OCwoLDg8KCw4LCtTTDg8KDw4LCg + 8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKDw4PCgsOCwrtWw4PCg8OCwoLDg8KCw4LCi8 + ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCnw== + +#LEAD COMMENT + +# another comment +dn: CN=All Staff,ou=Groups,o=University of Michigan,c=US +#EMBEDDED COMMENT +member: cn=Manager,o=University of Michigan,c=US +member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Unive + rsity of Michigan,c=US +member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c + =US +member: cn=John Doe,ou=Information Technology Division,ou=People,o=University + of Michigan,c=US +member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Univ + ersity of Michigan,c=US +member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich + igan,c=US +member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Univers + ity of Michigan,c=US +owner: cn=Manager,o=University of Michigan,c=US +cn: All Staff +description: Everyone in the sample data +objectclass: groupofnames + +dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US +member: cn=Manager,o=University of Michigan,c=US +member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c + =US +member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich + igan,c=US +member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic + higan,c=US +owner: cn=Manager,o=University of Michigan,c=US +description: All Alumni Assoc Staff +cn: Alumni Assoc Staff +objectclass: groupofnames + +dn: ou=Alumni Association,ou=People,o=University of Michigan,c=US +objectclass: organizationalUnit +ou: Alumni Association + +dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Universit + y of Michigan,c=US +objectclass: OpenLDAPperson +cn: Barbara Jensen +cn: Babs Jensen +sn:: IEplbnNlbiA= +uid: bjensen +title: Mythical Manager, Research Systems +postaladdress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann + Arbor, MI 48103-4943 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +userpassword:: YmplbnNlbg== +mail: bjensen@mailgw.example.com +homepostaladdress: 123 Wesley $ Ann Arbor, MI 48103 +description: Mythical manager of the rsdd unix project +drink: water +homephone: +1 313 555 2333 +pager: +1 313 555 3233 +facsimiletelephonenumber: +1 313 555 2274 +telephonenumber: +1 313 555 9022 + +dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=University + of Michigan,c=US +objectclass: OpenLDAPperson +cn: Bjorn Jensen +cn: Biiff Jensen +sn: Jensen +uid: bjorn +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +userpassword:: Ympvcm4= +homepostaladdress: 19923 Seven Mile Rd. $ South Lyon, MI 49999 +drink: Iced Tea +description: Hiker, biker +title: Director, Embedded Systems +postaladdress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103 +mail: bjorn@mailgw.example.com +homephone: +1 313 555 5444 +pager: +1 313 555 4474 +facsimiletelephonenumber: +1 313 555 2177 +telephonenumber: +1 313 555 0355 + +dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +objectclass: OpenLDAPperson +cn: Dorothy Stevens +cn: Dot Stevens +sn: Stevens +uid: dots +title: Secretary, UM Alumni Association +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +drink: Lemonade +homepostaladdress: 377 White St. Apt. 3 $ Ann Arbor, MI 48104 +description: Very tall +facsimiletelephonenumber: +1 313 555 3223 +telephonenumber: +1 313 555 3664 +mail: dots@mail.alumni.example.com +homephone: +1 313 555 0454 + +dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US +owner: cn=Manager,o=University of Michigan,c=US +description: All ITD Staff +cn: ITD Staff +objectclass: groupofuniquenames +uniquemember: cn=Manager,o=University of Michigan,c=US +uniquemember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=U + niversity of Michigan,c=US +uniquemember: cn=James A Jones 2,ou=Information Technology Division,ou=People, + o=University of Michigan,c=US +uniquemember: cn=John Doe,ou=Information Technology Division,ou=People,o=Unive + rsity of Michigan,c=US + +dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +objectclass: OpenLDAPperson +cn: James A Jones 1 +cn: James Jones +cn: Jim Jones +sn: Jones +uid: jaj +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +userpassword:: amFq +homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105 +homephone: +1 313 555 4772 +description: Outstanding +title: Mad Cow Researcher, UM Alumni Association +pager: +1 313 555 3923 +mail: jaj@mail.alumni.example.com +facsimiletelephonenumber: +1 313 555 4332 +telephonenumber: +1 313 555 0895 + +dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Universi + ty of Michigan,c=US +objectclass: OpenLDAPperson +cn: James A Jones 2 +cn: James Jones +cn: Jim Jones +sn: Doe +uid: jjones +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +homepostaladdress: 933 Brooks $ Ann Arbor, MI 48104 +homephone: +1 313 555 8838 +title: Senior Manager, Information Technology Division +description: Not around very much +mail: jjones@mailgw.example.com +postaladdress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103 +pager: +1 313 555 2833 +facsimiletelephonenumber: +1 313 555 8688 +telephonenumber: +1 313 555 7334 + +dn: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c=US +objectclass: OpenLDAPperson +cn: Jane Doe +cn: Jane Alverson +sn: Doe +uid: jdoe +title: Programmer Analyst, UM Alumni Association +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104 +drink: diet coke +description: Enthusiastic +mail: jdoe@woof.net +homephone: +1 313 555 5445 +pager: +1 313 555 1220 +facsimiletelephonenumber: +1 313 555 2311 +telephonenumber: +1 313 555 4774 + +dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Michigan + ,c=US +objectclass: OpenLDAPperson +cn: Jennifer Smith +cn: Jen Smith +sn: Smith +uid: jen +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +drink: Sam Adams +homepostaladdress: 1000 Maple #44 $ Ann Arbor, MI 48103 +title: Telemarketer, UM Alumni Association +mail: jen@mail.alumni.example.com +homephone: +1 313 555 2333 +pager: +1 313 555 6442 +facsimiletelephonenumber: +1 313 555 2756 +telephonenumber: +1 313 555 8232 + +dn: cn=John Doe,ou=Information Technology Division,ou=People,o=University of M + ichigan,c=US +objectclass: OpenLDAPperson +cn: John Doe +cn: Jonathon Doe +sn: Doe +uid: johnd +postaladdress: ITD $ 535 W. William $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +homepostaladdress: 912 East Bllvd $ Ann Arbor, MI 48104 +title: System Administrator, Information Technology Division +description: overworked! +mail: johnd@mailgw.example.com +homephone: +1 313 555 3774 +pager: +1 313 555 6573 +facsimiletelephonenumber: +1 313 555 4544 +telephonenumber: +1 313 555 9394 + +dn: cn=Manager,o=University of Michigan,c=US +objectclass: person +cn: Manager +cn: Directory Manager +cn: Dir Man +sn: Manager +description: Manager of the directory +userpassword:: c2VjcmV0 + +dn: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michigan,c= + US +objectclass: OpenLDAPperson +cn: Mark Elliot +cn: Mark A Elliot +sn: Elliot +uid: melliot +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +homepostaladdress: 199 Outer Drive $ Ypsilanti, MI 48198 +homephone: +1 313 555 0388 +drink: Gasoline +title: Director, UM Alumni Association +mail: melliot@mail.alumni.example.com +pager: +1 313 555 7671 +facsimiletelephonenumber: +1 313 555 7762 +telephonenumber: +1 313 555 4177 + +dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +objectclass: OpenLDAPperson +cn: Ursula Hampster +sn: Hampster +uid: uham +title: Secretary, UM Alumni Association +postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 +seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US +homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104 +mail: uham@mail.alumni.example.com +homephone: +1 313 555 8421 +pager: +1 313 555 2844 +facsimiletelephonenumber: +1 313 555 9700 +telephonenumber: +1 313 555 5331 + diff --git a/source4/lib/ldb/tests/testdata.txt b/source4/lib/ldb/tests/testdata.txt new file mode 100644 index 0000000000..dadb9f0f98 --- /dev/null +++ b/source4/lib/ldb/tests/testdata.txt @@ -0,0 +1,8 @@ +foo=bar5 +(&(|(a=b)(c=d))(e=f)) +(&(|(a=b)(c=d)(g=h))(e=f)) +name=firstname lastname +(&(sid=S-1-2-3)(name = fred bloggs)) +(&(|(a=b)(c=d))(g=f)) +(&(sid=S-1-2-3)(!(name = fred bloggs))) +(&(!(|(a=b)(c=d))(g=f))) diff --git a/source4/lib/ldb/tests/testsearch.txt b/source4/lib/ldb/tests/testsearch.txt new file mode 100644 index 0000000000..c5738639b7 --- /dev/null +++ b/source4/lib/ldb/tests/testsearch.txt @@ -0,0 +1,5 @@ +(blah=foo) +(objectclass=person) +(dn=*) +(&(objectclass=person)(objectclass=person)) +(&(objectclass=person)(objectclass=personx)) diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c new file mode 100644 index 0000000000..3eb7cb8de2 --- /dev/null +++ b/source4/lib/ldb/tools/ldbadd.c @@ -0,0 +1,74 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbadd + * + * Description: utility to add records - modelled on ldapadd + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + int main(void) +{ + static struct ldb_context *ldb; + struct ldb_message *msg; + int ret; + int count=0, failures=0; + const char *ldb_url; + + ldb_url = getenv("LDB_URL"); + if (!ldb_url) { + ldb_url = "tdb://test.ldb"; + } + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + while ((msg = ldif_read_file(stdin))) { + ret = ldb_add(ldb, msg); + if (ret != 0) { + fprintf(stderr, "ERR: \"%s\" on DN %s\n", + ldb_errstring(ldb), msg->dn); + failures++; + } else { + count++; + } + ldif_read_free(msg); + } + + ldb_close(ldb); + + printf("Added %d records with %d failures\n", count, failures); + + return 0; +} diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c new file mode 100644 index 0000000000..177279d47a --- /dev/null +++ b/source4/lib/ldb/tools/ldbdel.c @@ -0,0 +1,69 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbdel + * + * Description: utility to delete records - modelled on ldapdelete + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + int main(int argc, const char *argv[]) +{ + static struct ldb_context *ldb; + int ret, i; + const char *ldb_url; + + ldb_url = getenv("LDB_URL"); + if (!ldb_url) { + ldb_url = "tdb://test.ldb"; + } + + + if (argc < 2) { + printf("Usage: ldbdel \n"); + exit(1); + } + + ldb = ldb_connect(ldb_url, 0, NULL); + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + for (i=1;i + + int main(int argc, char * const argv[]) +{ + static struct ldb_context *ldb; + struct ldb_message **msgs; + int ret, i; + const char *expression; + const char * const *attrs = NULL; + const char *ldb_url; + const char *basedn = NULL; + int opt; + enum ldb_scope scope = LDB_SCOPE_DEFAULT; + + ldb_url = getenv("LDB_URL"); + if (!ldb_url) { + ldb_url = "tdb://test.ldb"; + } + + while ((opt = getopt(argc, argv, "b:H:s:")) != EOF) { + switch (opt) { + case 'b': + basedn = optarg; + break; + + case 'H': + ldb_url = optarg; + break; + + case 's': + if (strcmp(optarg, "base") == 0) { + scope = LDB_SCOPE_BASE; + } else if (strcmp(optarg, "sub") == 0) { + scope = LDB_SCOPE_SUBTREE; + } else if (strcmp(optarg, "one") == 0) { + scope = LDB_SCOPE_ONELEVEL; + } + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + printf("Usage: ldbsearch [attrs...]\n"); + exit(1); + } + + if (argc > 1) { + attrs = argv+1; + } + + expression = argv[0]; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); + + if (ret == -1) { + printf("search failed\n"); + exit(1); + } + + printf("# returned %d records\n", ret); + + for (i=0;i 0) { + ret = ldb_search_free(ldb, msgs); + if (ret == -1) { + fprintf(stderr, "search_free failed\n"); + exit(1); + } + } + + ldb_close(ldb); + return 0; +} -- cgit From 4258c7f27ff628b93e296fd0fc0f7a5a5bf2efeb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 31 Mar 2004 06:51:44 +0000 Subject: building with Makefile.ldb now works (This used to be commit 12538cd2c650bacabd37f4d2ecd3ff3ffce87a00) --- source4/lib/ldb/Makefile.ldb | 16 +- source4/lib/ldb/include/proto.h | 126 ++++++++++ source4/lib/ldb/ldb_tdb/ldb_ldif.c | 366 ----------------------------- source4/lib/ldb/ldb_tdb/ldb_parse.c | 448 ------------------------------------ source4/lib/ldb/ldb_tdb/ldb_parse.h | 40 ---- 5 files changed, 139 insertions(+), 857 deletions(-) create mode 100644 source4/lib/ldb/include/proto.h delete mode 100644 source4/lib/ldb/ldb_tdb/ldb_ldif.c delete mode 100644 source4/lib/ldb/ldb_tdb/ldb_parse.c delete mode 100644 source4/lib/ldb/ldb_tdb/ldb_parse.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 346c041666..b983ca2c49 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -1,9 +1,11 @@ -CFLAGS=-Wall -g -Iinclude -I. -DSTANDALONE=1 -DUSE_MMAP=1 OPENLDAP=/home/tridge/samba/openldap/prefix +TDBDIR=../tdb + +CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 LIB_FLAGS=-Llib -lldb -L$(OPENLDAP)/lib -lldap -TDB_OBJ=tdb/tdb.o tdb/spinlock.o +TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o @@ -20,7 +22,15 @@ BINS = bin/ldbadd bin/ldbsearch bin/ldbdel LIBS = $(LDB_LIB)($(OBJS)) -all: $(BINS) $(LIBS) +DIRS = lib bin + +all: $(DIRS) $(BINS) $(LIBS) + +lib: + mkdir -p lib + +bin: + mkdir -p bin lib/libldb.a: $(OBJS) diff --git a/source4/lib/ldb/include/proto.h b/source4/lib/ldb/include/proto.h new file mode 100644 index 0000000000..8690d96fee --- /dev/null +++ b/source4/lib/ldb/include/proto.h @@ -0,0 +1,126 @@ +#ifndef _PROTO_H_ +#define _PROTO_H_ + +/* This file is automatically generated with "make proto". DO NOT EDIT */ + + +/* The following definitions come from common/ldb.c */ + +struct ldb_context *ldb_connect(const char *url, unsigned int flags, + const char *options[]); +int ldb_close(struct ldb_context *ldb); +int ldb_search(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + const char *expression, + const char *attrs[], struct ldb_message ***res); +int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); +int ldb_add(struct ldb_context *ldb, + const struct ldb_message *message); +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message); +int ldb_delete(struct ldb_context *ldb, const char *dn); +const char *ldb_errstring(struct ldb_context *ldb); + +/* The following definitions come from common/ldb_ldif.c */ + +char *ldb_base64_encode(const char *buf, int len); +int ldb_should_b64_encode(const struct ldb_val *val); +int ldif_write(int (*fprintf_fn)(void *, const char *, ...), + void *private, + const struct ldb_message *msg); +void ldif_read_free(struct ldb_message *msg); +struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private); +struct ldb_message *ldif_read_file(FILE *f); +struct ldb_message *ldif_read_string(const char *s); +int ldif_write_file(FILE *f, const struct ldb_message *msg); + +/* The following definitions come from common/ldb_parse.c */ + +struct ldb_parse_tree *ldb_parse_tree(const char *s); +void ldb_parse_tree_free(struct ldb_parse_tree *tree); + +/* The following definitions come from common/util.c */ + +void *realloc_array(void *ptr, size_t el_size, unsigned count); +int list_find(const void *needle, + const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn); + +/* The following definitions come from ldb_ldap/ldb_ldap.c */ + +struct ldb_context *lldb_connect(const char *url, + unsigned int flags, + const char *options[]); + +/* The following definitions come from ldb_tdb/ldb_index.c */ + +int ltdb_search_indexed(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char *attrs[], struct ldb_message ***res); +int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg); +int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg); + +/* The following definitions come from ldb_tdb/ldb_match.c */ + +int ldb_message_match(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope); + +/* The following definitions come from ldb_tdb/ldb_pack.c */ + +int ltdb_pack_data(struct ldb_context *ctx, + const struct ldb_message *message, + struct TDB_DATA *data); +int ltdb_unpack_data(struct ldb_context *ctx, + const struct TDB_DATA *data, + struct ldb_message *message); + +/* The following definitions come from ldb_tdb/ldb_search.c */ + +int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr); +int ltdb_has_wildcard(const struct ldb_val *val); +void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg); +int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg); +int ltdb_search_dn(struct ldb_context *ldb, char *dn, + const char *attrs[], struct ldb_message ***res); +int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, + const char *attrs[], + unsigned int *count, + struct ldb_message ***res); +int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); +int ltdb_search(struct ldb_context *ldb, const char *base, + enum ldb_scope scope, const char *expression, + const char *attrs[], struct ldb_message ***res); + +/* The following definitions come from ldb_tdb/ldb_tdb.c */ + +struct TDB_DATA ltdb_key(const char *dn); +int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs); +int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn); +struct ldb_context *ltdb_connect(const char *url, + unsigned int flags, + const char *options[]); + +/* The following definitions come from ldb_tdb/ldbadd.c */ + + +/* The following definitions come from ldb_tdb/ldbdel.c */ + + +/* The following definitions come from ldb_tdb/ldbsearch.c */ + + +/* The following definitions come from tools/ldbadd.c */ + + +/* The following definitions come from tools/ldbdel.c */ + + +/* The following definitions come from tools/ldbsearch.c */ + + +#endif /* _PROTO_H_ */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_ldif.c b/source4/lib/ldb/ldb_tdb/ldb_ldif.c deleted file mode 100644 index 170685cc03..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldb_ldif.c +++ /dev/null @@ -1,366 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - ldif utilities for ldb - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - -/* - this base64 decoder was taken from jitterbug (written by tridge). - we might need to replace it with a new version -*/ -static int base64_decode(char *s) -{ - const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int bit_offset, byte_offset, idx, i, n; - unsigned char *d = (unsigned char *)s; - char *p; - - n=i=0; - - while (*s && (p=strchr(b64,*s))) { - idx = (int)(p - b64); - byte_offset = (i*6)/8; - bit_offset = (i*6)%8; - d[byte_offset] &= ~((1<<(8-bit_offset))-1); - if (bit_offset < 3) { - d[byte_offset] |= (idx << (2-bit_offset)); - n = byte_offset+1; - } else { - d[byte_offset] |= (idx >> (bit_offset-2)); - d[byte_offset+1] = 0; - d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; - n = byte_offset+2; - } - s++; i++; - } - - if (*s && !p) { - /* the only termination allowed */ - if (*s != '=') { - return -1; - } - } - - /* null terminate */ - d[n] = 0; - return n; -} - - -/* - encode as base64 - caller frees -*/ -char *ldb_base64_encode(const char *buf, int len) -{ - const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int bit_offset, byte_offset, idx, i; - unsigned char *d = (unsigned char *)buf; - int bytes = (len*8 + 5)/6; - char *out; - - out = malloc(bytes+2); - if (!out) return NULL; - - for (i=0;i> (2-bit_offset)) & 0x3F; - } else { - idx = (d[byte_offset] << (bit_offset-2)) & 0x3F; - if (byte_offset+1 < len) { - idx |= (d[byte_offset+1] >> (8-(bit_offset-2))); - } - } - out[i] = b64[idx]; - } - - out[i++] = '='; - out[i] = 0; - - return out; -} - -/* - see if a buffer should be base64 encoded -*/ -int ldb_should_b64_encode(const struct ldb_val *val) -{ - int i; - unsigned char *p = val->data; - - if (val->length == 0 || p[0] == ' ' || p[0] == ':') { - return 1; - } - - for (i=0; ilength; i++) { - if (!isprint(p[i]) || p[i] == '\n') { - return 1; - } - } - return 0; -} - - -/* - encode as base64 to a file -*/ -static int base64_encode_f(FILE *f, const char *buf, int len, int start_pos) -{ - int i; - char *b = ldb_base64_encode(buf, len); - - if (!b) { - return -1; - } - - for (i=0;b[i];i++) { - fputc(b[i], f); - if (b[i+1] && (i + start_pos) % 77 == 0) { - fputc('\n', f); - fputc(' ', f); - } - } - free(b); - return 0; -} - -/* - write a line folded string onto a file -*/ -static void fold_string(FILE *f, const char *buf, size_t length, int start_pos) -{ - int i; - - for (i=0;i 1 && chunk[chunk_size-1] == '\n') { - chunk_size--; - continue; - } - - /* chunks are terminated by a double line-feed */ - if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') { - chunk[chunk_size-1] = 0; - return chunk; - } - - if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) { - in_comment = 1; - continue; - } - - chunk[chunk_size++] = c; - } - - return chunk; -} - - -/* simple ldif attribute parser */ -static int next_attr(char **s, char **attr, struct ldb_val *value) -{ - char *p; - int base64_encoded = 0; - - p = strchr(*s, ':'); - if (!p) { - return -1; - } - - *p++ = 0; - - if (*p == ':') { - base64_encoded = 1; - p++; - } - - *attr = *s; - - while (isspace(*p)) { - p++; - } - - value->data = p; - - p = strchr(p, '\n'); - - if (!p) { - value->length = strlen((char *)value->data); - *s = ((char *)value->data) + value->length; - } else { - value->length = p - (char *)value->data; - *s = p+1; - *p = 0; - } - - if (base64_encoded) { - int len = base64_decode(value->data); - if (len == -1) { - /* it wasn't valid base64 data */ - return -1; - } - value->length = len; - } - - return 0; -} - - -/* - free a message from a ldif_read -*/ -void ldif_read_free(struct ldb_message *msg) -{ - if (msg->elements) free(msg->elements); - if (msg->private) free(msg->private); - free(msg); -} - -/* - read from a LDIF file, creating a ldb_message -*/ -struct ldb_message *ldif_read(FILE *f) -{ - struct ldb_message *msg; - char *attr=NULL, *chunk=NULL, *s; - struct ldb_val value; - - value.data = NULL; - - msg = malloc_p(struct ldb_message); - if (!msg) return NULL; - - msg->dn = NULL; - msg->elements = NULL; - msg->num_elements = 0; - msg->private = NULL; - - chunk = next_chunk(f); - if (!chunk) { - goto failed; - } - - msg->private = chunk; - s = chunk; - - if (next_attr(&s, &attr, &value) != 0) { - goto failed; - } - - /* first line must be a dn */ - if (strcmp(attr, "dn") != 0) { - fprintf(stderr, "First line must be a dn not '%s'\n", attr); - goto failed; - } - - msg->dn = value.data; - - while (next_attr(&s, &attr, &value) == 0) { - msg->elements = realloc_p(msg->elements, - struct ldb_message_element, - msg->num_elements+1); - if (!msg->elements) { - goto failed; - } - msg->elements[msg->num_elements].flags = 0; - msg->elements[msg->num_elements].name = attr; - msg->elements[msg->num_elements].value = value; - msg->num_elements++; - } - - return msg; - -failed: - if (msg) ldif_read_free(msg); - return NULL; -} - - -/* - write to a ldif file -*/ -void ldif_write(FILE *f, const struct ldb_message *msg) -{ - int i; - fprintf(f, "dn: %s\n", msg->dn); - for (i=0;inum_elements;i++) { - if (ldb_should_b64_encode(&msg->elements[i].value)) { - fprintf(f, "%s:: ", msg->elements[i].name); - base64_encode_f(f, - msg->elements[i].value.data, - msg->elements[i].value.length, - strlen(msg->elements[i].name)+3); - fprintf(f, "\n"); - } else { - fprintf(f, "%s: ", msg->elements[i].name); - fold_string(f, msg->elements[i].value.data, - msg->elements[i].value.length, - strlen(msg->elements[i].name)+2); - fprintf(f, "\n"); - } - } - fprintf(f,"\n"); -} diff --git a/source4/lib/ldb/ldb_tdb/ldb_parse.c b/source4/lib/ldb/ldb_tdb/ldb_parse.c deleted file mode 100644 index 44cfc5b4ff..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldb_parse.c +++ /dev/null @@ -1,448 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - parse a LDAP-like expression - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - TODO: - - add RFC2254 binary string handling - - possibly add ~=, <= and >= handling - - expand the test suite - - add better parse error handling - -*/ - -#include "includes.h" - - -/* -a filter is defined by: - ::= '(' ')' - ::= | | | - ::= '&' - ::= '|' - ::= '!' - ::= | - ::= - ::= '=' | '~=' | '<=' | '>=' -*/ - -/* - return next token element. Caller frees -*/ -static char *ldb_parse_lex(const char **s) -{ - const char *p = *s; - char *ret; - - while (isspace(*p)) { - p++; - } - *s = p; - - if (*p == 0) { - return NULL; - } - - if (strchr("()&|=!", *p)) { - (*s) = p+1; - ret = strndup(p, 1); - if (!ret) { - errno = ENOMEM; - } - return ret; - } - - while (*p && (isalnum(*p) || !strchr("()&|=!", *p))) { - p++; - } - - if (p == *s) { - return NULL; - } - - ret = strndup(*s, p - *s); - if (!ret) { - errno = ENOMEM; - } - - *s = p; - - return ret; -} - -/* - find a matching close brace in a string -*/ -static const char *match_brace(const char *s) -{ - unsigned int count = 0; - while (*s && (count != 0 || *s != ')')) { - if (*s == '(') { - count++; - } - if (*s == ')') { - count--; - } - s++; - } - if (! *s) { - return NULL; - } - return s; -} - - -static struct ldb_parse_tree *ldb_parse_filter(const char **s); - -/* - ::= -*/ -static struct ldb_parse_tree *ldb_parse_simple(const char *s) -{ - char *eq, *val, *l; - struct ldb_parse_tree *ret; - - l = ldb_parse_lex(&s); - if (!l) { - fprintf(stderr, "Unexpected end of expression\n"); - return NULL; - } - - if (strchr("()&|=", *l)) { - fprintf(stderr, "Unexpected token '%s'\n", l); - free(l); - return NULL; - } - - eq = ldb_parse_lex(&s); - if (!eq || strcmp(eq, "=") != 0) { - fprintf(stderr, "Expected '='\n"); - free(l); - if (eq) free(eq); - return NULL; - } - free(eq); - - val = ldb_parse_lex(&s); - if (val && strchr("()&|=", *val)) { - fprintf(stderr, "Unexpected token '%s'\n", val); - free(l); - if (val) free(val); - return NULL; - } - - ret = malloc_p(struct ldb_parse_tree); - if (!ret) { - errno = ENOMEM; - return NULL; - } - - ret->operation = LDB_OP_SIMPLE; - ret->u.simple.attr = l; - ret->u.simple.value.data = val; - ret->u.simple.value.length = val?strlen(val):0; - - return ret; -} - - -/* - parse a filterlist - ::= '&' - ::= '|' - ::= | -*/ -static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const char *s) -{ - struct ldb_parse_tree *ret, *next; - - ret = malloc_p(struct ldb_parse_tree); - if (!ret) { - errno = ENOMEM; - return NULL; - } - - ret->operation = op; - ret->u.list.num_elements = 1; - ret->u.list.elements = malloc_p(struct ldb_parse_tree *); - if (!ret->u.list.elements) { - errno = ENOMEM; - free(ret); - return NULL; - } - - ret->u.list.elements[0] = ldb_parse_filter(&s); - if (!ret->u.list.elements[0]) { - free(ret->u.list.elements); - free(ret); - return NULL; - } - - while (isspace(*s)) s++; - - while (*s && (next = ldb_parse_filter(&s))) { - struct ldb_parse_tree **e; - e = realloc_p(ret->u.list.elements, - struct ldb_parse_tree *, - ret->u.list.num_elements+1); - if (!e) { - errno = ENOMEM; - ldb_parse_tree_free(next); - ldb_parse_tree_free(ret); - return NULL; - } - ret->u.list.elements = e; - ret->u.list.elements[ret->u.list.num_elements] = next; - ret->u.list.num_elements++; - while (isspace(*s)) s++; - } - - return ret; -} - - -/* - ::= '!' -*/ -static struct ldb_parse_tree *ldb_parse_not(const char *s) -{ - struct ldb_parse_tree *ret; - - ret = malloc_p(struct ldb_parse_tree); - if (!ret) { - errno = ENOMEM; - return NULL; - } - - ret->operation = LDB_OP_NOT; - ret->u.not.child = ldb_parse_filter(&s); - if (!ret->u.not.child) { - free(ret); - return NULL; - } - - return ret; -} - -/* - parse a filtercomp - ::= | | | -*/ -static struct ldb_parse_tree *ldb_parse_filtercomp(const char *s) -{ - while (isspace(*s)) s++; - - switch (*s) { - case '&': - return ldb_parse_filterlist(LDB_OP_AND, s+1); - - case '|': - return ldb_parse_filterlist(LDB_OP_OR, s+1); - - case '!': - return ldb_parse_not(s+1); - - case '(': - case ')': - fprintf(stderr, "Unexpected token '%c'\n", *s); - return NULL; - } - - return ldb_parse_simple(s); -} - - -/* - ::= '(' ')' -*/ -static struct ldb_parse_tree *ldb_parse_filter(const char **s) -{ - char *l, *s2; - const char *p, *p2; - struct ldb_parse_tree *ret; - - l = ldb_parse_lex(s); - if (!l) { - fprintf(stderr, "Unexpected end of expression\n"); - return NULL; - } - - if (strcmp(l, "(") != 0) { - free(l); - fprintf(stderr, "Expected '('\n"); - return NULL; - } - free(l); - - p = match_brace(*s); - if (!p) { - fprintf(stderr, "Parse error - mismatched braces\n"); - return NULL; - } - p2 = p + 1; - - s2 = strndup(*s, p - *s); - if (!s2) { - errno = ENOMEM; - return NULL; - } - - ret = ldb_parse_filtercomp(s2); - free(s2); - - *s = p2; - - return ret; -} - - -/* - main parser entry point. Takes a search string and returns a parse tree - - expression ::= | -*/ -struct ldb_parse_tree *ldb_parse_tree(const char *s) -{ - while (isspace(*s)) s++; - - if (*s == '(') { - return ldb_parse_filter(&s); - } - - return ldb_parse_simple(s); -} - -/* - free a parse tree returned from ldb_parse_tree() -*/ -void ldb_parse_tree_free(struct ldb_parse_tree *tree) -{ - int i; - - switch (tree->operation) { - case LDB_OP_SIMPLE: - free(tree->u.simple.attr); - if (tree->u.simple.value.data) free(tree->u.simple.value.data); - break; - - case LDB_OP_AND: - case LDB_OP_OR: - for (i=0;iu.list.num_elements;i++) { - ldb_parse_tree_free(tree->u.list.elements[i]); - } - if (tree->u.list.elements) free(tree->u.list.elements); - break; - - case LDB_OP_NOT: - ldb_parse_tree_free(tree->u.not.child); - break; - } - - free(tree); -} - -#if TEST_PROGRAM -/* - return a string representation of a parse tree - used for debugging -*/ -static char *tree_string(struct ldb_parse_tree *tree) -{ - char *s = NULL; - char *s1, *s2; - int i; - - switch (tree->operation) { - case LDB_OP_SIMPLE: - asprintf(&s, "( %s = \"%s\" )", tree->u.simple.attr, - (char *)tree->u.simple.value.data); - break; - - case LDB_OP_AND: - case LDB_OP_OR: - asprintf(&s, "( %c", tree->operation==LDB_OP_AND?'&':'|'); - if (!s) return NULL; - - for (i=0;iu.list.num_elements;i++) { - s1 = tree_string(tree->u.list.elements[i]); - if (!s1) { - free(s); - return NULL; - } - asprintf(&s2, "%s %s", s, s1); - free(s); - free(s1); - s = s2; - } - if (!s) { - return NULL; - } - asprintf(&s2, "%s )", s); - free(s); - s = s2; - break; - - case LDB_OP_NOT: - s1 = tree_string(tree->u.not.child); - asprintf(&s, "( ! %s )", s1); - free(s1); - break; - } - return s; -} - - -/* - print a tree - */ -static void print_tree(struct ldb_parse_tree *tree) -{ - char *s = tree_string(tree); - printf("%s\n", s); - free(s); -} - - - int main(void) -{ - char line[1000]; - int ret = 0; - - while (fgets(line, sizeof(line)-1, stdin)) { - struct ldb_parse_tree *tree; - - if (line[strlen(line)-1] == '\n') { - line[strlen(line)-1] = 0; - } - tree = ldb_parse_tree(line); - if (!tree) { - fprintf(stderr, "Failed to parse\n"); - ret = 1; - continue; - } - print_tree(tree); - ldb_parse_tree_free(tree); - } - - return ret; -} -#endif /* TEST_PROGRAM */ - diff --git a/source4/lib/ldb/ldb_tdb/ldb_parse.h b/source4/lib/ldb/ldb_tdb/ldb_parse.h deleted file mode 100644 index 995e0e04ff..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldb_parse.h +++ /dev/null @@ -1,40 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - parse a LDAP-like expression - header - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT}; - -struct ldb_parse_tree { - enum ldb_parse_op operation; - union { - struct { - char *attr; - struct ldb_val value; - } simple; - struct { - unsigned int num_elements; - struct ldb_parse_tree **elements; - } list; - struct { - struct ldb_parse_tree *child; - } not; - } u; -}; -- cgit From 05d10eba1f6142219638bf9b859d07b5bb175f72 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Apr 2004 07:39:04 +0000 Subject: allow "struct TDB_DATA" as well as just "TDB_DATA" in general I prefer the struct form for Samba4 structures. I think its clearer. (This used to be commit 63b26557744ce4cbf5c9419f752fbd63ed8bfec6) --- source4/lib/tdb/tdb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index 169de5f87d..281925068c 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -57,7 +57,7 @@ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, #define u32 unsigned #endif -typedef struct { +typedef struct TDB_DATA { char *dptr; size_t dsize; } TDB_DATA; -- cgit From ee44733f94864fb0a1ae15d48e3335c0705a82ae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Apr 2004 12:29:21 +0000 Subject: added the rest of the ldb_modify() code, which required a fairly large change in the ldb API. The API is now much closer to LDAP. (This used to be commit e9e85c464411c561c5073d262a2e3533fec175ca) --- source4/lib/ldb/Makefile.ldb | 5 +- source4/lib/ldb/common/ldb_ldif.c | 233 +++++++++++++++++++++++------ source4/lib/ldb/include/ldb.h | 29 +++- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 96 ++++++------ source4/lib/ldb/ldb_tdb/ldb_index.c | 208 ++++++++++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_match.c | 18 ++- source4/lib/ldb/ldb_tdb/ldb_pack.c | 94 ++++++++---- source4/lib/ldb/ldb_tdb/ldb_search.c | 52 +++++-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 263 +++++++++++++++++++++++++++++++-- source4/lib/ldb/ldb_tdb/ldbadd.c | 55 ------- source4/lib/ldb/ldb_tdb/ldbdel.c | 50 ------- source4/lib/ldb/ldb_tdb/ldbsearch.c | 73 --------- source4/lib/ldb/tests/test-generic.sh | 8 + source4/lib/ldb/tests/test-ldap.sh | 8 + source4/lib/ldb/tests/test-modify.ldif | 14 ++ source4/lib/ldb/tests/test-tdb.sh | 8 + source4/lib/ldb/tools/ldbadd.c | 17 ++- source4/lib/ldb/tools/ldbmodify.c | 85 +++++++++++ source4/lib/ldb/tools/ldbsearch.c | 11 +- 19 files changed, 922 insertions(+), 405 deletions(-) delete mode 100644 source4/lib/ldb/ldb_tdb/ldbadd.c delete mode 100644 source4/lib/ldb/ldb_tdb/ldbdel.c delete mode 100644 source4/lib/ldb/ldb_tdb/ldbsearch.c create mode 100644 source4/lib/ldb/tests/test-generic.sh create mode 100755 source4/lib/ldb/tests/test-ldap.sh create mode 100644 source4/lib/ldb/tests/test-modify.ldif create mode 100755 source4/lib/ldb/tests/test-tdb.sh create mode 100644 source4/lib/ldb/tools/ldbmodify.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index b983ca2c49..0610ccf19b 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -18,7 +18,7 @@ OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify LIBS = $(LDB_LIB)($(OBJS)) @@ -43,6 +43,9 @@ bin/ldbsearch: tools/ldbsearch.o $(LIBS) bin/ldbdel: tools/ldbdel.o $(LIBS) $(CC) -o bin/ldbdel tools/ldbdel.o $(LIB_FLAGS) +bin/ldbmodify: tools/ldbmodify.o $(LIBS) + $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) + clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 198c984823..b4c27c3369 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -32,6 +32,10 @@ * Author: Andrew Tridgell */ +/* + see RFC2849 for the LDIF format definition +*/ + #include "includes.h" @@ -176,40 +180,71 @@ static int base64_encode_f(int (*fprintf_fn)(void *, const char *, ...), void *p return ret; } + +static const struct { + const char *name; + enum ldb_changetype changetype; +} ldb_changetypes[] = { + {"add", LDB_CHANGETYPE_ADD}, + {"delete", LDB_CHANGETYPE_DELETE}, + {"modify", LDB_CHANGETYPE_MODIFY}, + {NULL, 0} +}; + /* write to ldif, using a caller supplied write method */ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), void *private, - const struct ldb_message *msg) + const struct ldb_ldif *ldif) { - int i; + int i, j; int total=0, ret; + const struct ldb_message *msg; + + msg = &ldif->msg; ret = fprintf_fn(private, "dn: %s\n", msg->dn); CHECK_RET; + if (ldif->changetype != LDB_CHANGETYPE_NONE) { + for (i=0;ldb_changetypes[i].name;i++) { + if (ldb_changetypes[i].changetype == ldif->changetype) { + break; + } + } + if (!ldb_changetypes[i].name) { + fprintf(stderr,"Invalid changetype\n"); + return -1; + } + ret = fprintf_fn(private, "changetype: %s\n", ldb_changetypes[i].name); + CHECK_RET; + } + for (i=0;inum_elements;i++) { - if (ldb_should_b64_encode(&msg->elements[i].value)) { - ret = fprintf_fn(private, "%s:: ", msg->elements[i].name); - CHECK_RET; - ret = base64_encode_f(fprintf_fn, private, - msg->elements[i].value.data, - msg->elements[i].value.length, - strlen(msg->elements[i].name)+3); - CHECK_RET; - ret = fprintf_fn(private, "\n"); - CHECK_RET; - } else { - ret = fprintf_fn(private, "%s: ", msg->elements[i].name); - CHECK_RET; - ret = fold_string(fprintf_fn, private, - msg->elements[i].value.data, - msg->elements[i].value.length, - strlen(msg->elements[i].name)+2); - CHECK_RET; - ret = fprintf_fn(private, "\n"); - CHECK_RET; + for (j=0;jelements[i].num_values;j++) { + if (ldb_should_b64_encode(&msg->elements[i].values[j])) { + ret = fprintf_fn(private, "%s:: ", + msg->elements[i].name); + CHECK_RET; + ret = base64_encode_f(fprintf_fn, private, + msg->elements[i].values[j].data, + msg->elements[i].values[j].length, + strlen(msg->elements[i].name)+3); + CHECK_RET; + ret = fprintf_fn(private, "\n"); + CHECK_RET; + } else { + ret = fprintf_fn(private, "%s: ", msg->elements[i].name); + CHECK_RET; + ret = fold_string(fprintf_fn, private, + msg->elements[i].values[j].data, + msg->elements[i].values[j].length, + strlen(msg->elements[i].name)+2); + CHECK_RET; + ret = fprintf_fn(private, "\n"); + CHECK_RET; + } } } ret = fprintf_fn(private,"\n"); @@ -235,7 +270,7 @@ static char *next_chunk(int (*fgetc_fn)(void *), void *private) int in_comment = 0; while ((c = fgetc_fn(private)) != EOF) { - if (chunk_size == alloc_size) { + if (chunk_size+1 >= alloc_size) { char *c2; alloc_size += 1024; c2 = realloc_p(chunk, char, alloc_size); @@ -279,6 +314,10 @@ static char *next_chunk(int (*fgetc_fn)(void *), void *private) chunk[chunk_size++] = c; } + if (chunk) { + chunk[chunk_size] = 0; + } + return chunk; } @@ -289,6 +328,13 @@ static int next_attr(char **s, char **attr, struct ldb_val *value) char *p; int base64_encoded = 0; + if (strncmp(*s, "-\n", 2) == 0) { + value->length = 0; + *attr = "-"; + *s += 2; + return 0; + } + p = strchr(*s, ':'); if (!p) { return -1; @@ -336,26 +382,63 @@ static int next_attr(char **s, char **attr, struct ldb_val *value) /* free a message from a ldif_read */ -void ldif_read_free(struct ldb_message *msg) +void ldif_read_free(struct ldb_ldif *ldif) { + struct ldb_message *msg = &ldif->msg; + int i; + for (i=0;inum_elements;i++) { + if (msg->elements[i].values) free(msg->elements[i].values); + } if (msg->elements) free(msg->elements); if (msg->private) free(msg->private); - free(msg); + free(ldif); +} + +/* + add an empty element +*/ +static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned flags) +{ + struct ldb_message_element *el2, *el; + + el2 = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + if (!el2) { + errno = ENOMEM; + return -1; + } + + msg->elements = el2; + + el = &msg->elements[msg->num_elements]; + + el->name = name; + el->num_values = 0; + el->values = NULL; + el->flags = flags; + + msg->num_elements++; + + return 0; } /* read from a LDIF source, creating a ldb_message */ -struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private) +struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private) { + struct ldb_ldif *ldif; struct ldb_message *msg; char *attr=NULL, *chunk=NULL, *s; struct ldb_val value; + unsigned flags = 0; value.data = NULL; - msg = malloc_p(struct ldb_message); - if (!msg) return NULL; + ldif = malloc_p(struct ldb_ldif); + if (!ldif) return NULL; + + ldif->changetype = LDB_CHANGETYPE_NONE; + msg = &ldif->msg; msg->dn = NULL; msg->elements = NULL; @@ -383,22 +466,86 @@ struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private) msg->dn = value.data; while (next_attr(&s, &attr, &value) == 0) { - msg->elements = realloc_p(msg->elements, - struct ldb_message_element, - msg->num_elements+1); - if (!msg->elements) { - goto failed; + struct ldb_message_element *el; + int empty = 0; + + if (strcmp(attr, "changetype") == 0) { + int i; + for (i=0;ldb_changetypes[i].name;i++) { + if (strcmp((char *)value.data, ldb_changetypes[i].name) == 0) { + ldif->changetype = ldb_changetypes[i].changetype; + break; + } + } + if (!ldb_changetypes[i].name) { + fprintf(stderr,"Bad changetype '%s'\n", + (char *)value.data); + } + flags = 0; + continue; + } + + if (strcmp(attr, "add") == 0) { + flags = LDB_FLAG_MOD_ADD; + empty = 1; + } + if (strcmp(attr, "delete") == 0) { + flags = LDB_FLAG_MOD_DELETE; + empty = 1; + } + if (strcmp(attr, "replace") == 0) { + flags = LDB_FLAG_MOD_REPLACE; + empty = 1; + } + if (strcmp(attr, "-") == 0) { + flags = 0; + continue; + } + + if (empty) { + if (msg_add_empty(msg, (char *)value.data, flags) != 0) { + goto failed; + } + continue; + } + + el = &msg->elements[msg->num_elements-1]; + + if (msg->num_elements > 0 && strcmp(attr, el->name) == 0 && + flags == el->flags) { + /* its a continuation */ + el->values = + realloc_p(el->values, struct ldb_val, el->num_values+1); + if (!el->values) { + goto failed; + } + el->values[el->num_values] = value; + el->num_values++; + } else { + /* its a new attribute */ + msg->elements = realloc_p(msg->elements, + struct ldb_message_element, + msg->num_elements+1); + if (!msg->elements) { + goto failed; + } + msg->elements[msg->num_elements].flags = flags; + msg->elements[msg->num_elements].name = attr; + el = &msg->elements[msg->num_elements]; + el->values = malloc_p(struct ldb_val); + if (!el->values) { + goto failed; + } + el->num_values = 1; + el->values[0] = value; + msg->num_elements++; } - msg->elements[msg->num_elements].flags = 0; - msg->elements[msg->num_elements].name = attr; - msg->elements[msg->num_elements].value = value; - msg->num_elements++; } - return msg; + return ldif; failed: - if (msg) ldif_read_free(msg); + if (ldif) ldif_read_free(ldif); return NULL; } @@ -417,7 +564,7 @@ static int fgetc_file(void *private) return fgetc(state->f); } -struct ldb_message *ldif_read_file(FILE *f) +struct ldb_ldif *ldif_read_file(FILE *f) { struct ldif_read_file_state state; state.f = f; @@ -441,7 +588,7 @@ static int fgetc_string(void *private) return EOF; } -struct ldb_message *ldif_read_string(const char *s) +struct ldb_ldif *ldif_read_string(const char *s) { struct ldif_read_string_state state; state.s = s; @@ -468,9 +615,9 @@ static int fprintf_file(void *private, const char *fmt, ...) return ret; } -int ldif_write_file(FILE *f, const struct ldb_message *msg) +int ldif_write_file(FILE *f, const struct ldb_ldif *ldif) { struct ldif_write_file_state state; state.f = f; - return ldif_write(fprintf_file, &state, msg); + return ldif_write(fprintf_file, &state, ldif); } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 35474d23c5..12064bbf75 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -73,7 +73,8 @@ struct ldb_val { struct ldb_message_element { unsigned int flags; char *name; - struct ldb_val value; + unsigned int num_values; + struct ldb_val *values; }; @@ -88,6 +89,20 @@ struct ldb_message { void *private; /* private to the backend */ }; +enum ldb_changetype { + LDB_CHANGETYPE_NONE=0, + LDB_CHANGETYPE_ADD, + LDB_CHANGETYPE_DELETE, + LDB_CHANGETYPE_MODIFY +}; + +/* + a ldif record - from ldif_read +*/ +struct ldb_ldif { + enum ldb_changetype changetype; + struct ldb_message msg; +}; enum ldb_scope {LDB_SCOPE_DEFAULT=-1, LDB_SCOPE_BASE=0, @@ -196,9 +211,9 @@ const char *ldb_errstring(struct ldb_context *ldb); */ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), void *private, - const struct ldb_message *msg); -void ldif_read_free(struct ldb_message *msg); -struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private); -struct ldb_message *ldif_read_file(FILE *f); -struct ldb_message *ldif_read_string(const char *s); -int ldif_write_file(FILE *f, const struct ldb_message *msg); + const struct ldb_ldif *ldif); +void ldif_read_free(struct ldb_ldif *); +struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private); +struct ldb_ldif *ldif_read_file(FILE *f); +struct ldb_ldif *ldif_read_string(const char *s); +int ldif_write_file(FILE *f, const struct ldb_ldif *msg); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index b2f7688497..e6cbb52cad 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -37,7 +37,7 @@ #if 0 /* - we don't need this right now, but will once we add more backend + we don't need this right now, but will once we add some backend options */ @@ -110,13 +110,16 @@ static int lldb_delete(struct ldb_context *ldb, const char *dn) */ static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) { - int i; + int i, j; free(msg->dn); for (i=0;inum_elements;i++) { free(msg->elements[i].name); - if (msg->elements[i].value.data) { - free(msg->elements[i].value.data); + for (j=0;jelements[i].num_values;j++) { + if (msg->elements[i].values[j].data) { + free(msg->elements[i].values[j].data); + } } + free(msg->elements[i].values); } if (msg->elements) free(msg->elements); free(msg); @@ -155,7 +158,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg, } el = realloc_p(msg->elements, struct ldb_message_element, - msg->num_elements + count); + msg->num_elements + 1); if (!el) { errno = ENOMEM; return -1; @@ -163,22 +166,34 @@ static int lldb_add_msg_attr(struct ldb_message *msg, msg->elements = el; + el = &msg->elements[msg->num_elements]; + + el->name = strdup(attr); + if (!el->name) { + errno = ENOMEM; + return -1; + } + el->flags = 0; + + el->num_values = 0; + el->values = malloc_array_p(struct ldb_val, count); + if (!el->values) { + errno = ENOMEM; + return -1; + } + for (i=0;ielements[msg->num_elements].name = strdup(attr); - if (!msg->elements[msg->num_elements].name) { + el->values[i].data = malloc(bval[i]->bv_len); + if (!el->values[i].data) { return -1; } - msg->elements[msg->num_elements].value.data = malloc(bval[i]->bv_len); - if (!msg->elements[msg->num_elements].value.data) { - free(msg->elements[msg->num_elements].name); - return -1; - } - memcpy(msg->elements[msg->num_elements].value.data, - bval[i]->bv_val, bval[i]->bv_len); - msg->elements[msg->num_elements].value.length = bval[i]->bv_len; - msg->num_elements++; + memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len); + el->values[i].length = bval[i]->bv_len; + el->num_values++; } + msg->num_elements++; + return 0; } @@ -309,7 +324,7 @@ static void lldb_mods_free(LDAPMod **mods) static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) { LDAPMod **mods; - int i, num_vals, num_mods = 0; + int i, j, num_mods = 0; /* allocate maximum number of elements needed */ mods = malloc_array_p(LDAPMod *, msg->num_elements+1); @@ -320,30 +335,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) mods[0] = NULL; for (i=0;inum_elements;i++) { - - if (i > 0 && - (!use_flags || - (msg->elements[i].flags == msg->elements[i-1].flags)) && - strcmp(msg->elements[i].name, msg->elements[i-1].name) == 0) { - struct berval **b; - /* when attributes are repeated we need to extend the - existing bvals array */ - b = realloc_p(mods[num_mods-1]->mod_vals.modv_bvals, - struct berval *, num_vals+2); - if (!b) { - goto failed; - } - mods[num_mods-1]->mod_vals.modv_bvals = b; - b[num_vals+1] = NULL; - b[num_vals] = malloc_p(struct berval); - if (!b[num_vals]) goto failed; - b[num_vals]->bv_val = msg->elements[i].value.data; - b[num_vals]->bv_len = msg->elements[i].value.length; - num_vals++; - continue; - } - - num_vals = 1; + const struct ldb_message_element *el = &msg->elements[i]; mods[num_mods] = malloc_p(LDAPMod); if (!mods[num_mods]) { @@ -352,7 +344,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) mods[num_mods+1] = NULL; mods[num_mods]->mod_op = LDAP_MOD_BVALUES; if (use_flags) { - switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + switch (el->flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_ADD: mods[num_mods]->mod_op |= LDAP_MOD_ADD; break; @@ -364,18 +356,22 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) break; } } - mods[num_mods]->mod_type = msg->elements[i].name; - mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *, 2); + mods[num_mods]->mod_type = el->name; + mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *, + 1+el->num_values); if (!mods[num_mods]->mod_vals.modv_bvals) { goto failed; } - mods[num_mods]->mod_vals.modv_bvals[0] = malloc_p(struct berval); - if (!mods[num_mods]->mod_vals.modv_bvals[0]) { - goto failed; + + for (j=0;jnum_values;j++) { + mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval); + if (!mods[num_mods]->mod_vals.modv_bvals[j]) { + goto failed; + } + mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data; + mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length; } - mods[num_mods]->mod_vals.modv_bvals[0]->bv_val = msg->elements[i].value.data; - mods[num_mods]->mod_vals.modv_bvals[0]->bv_len = msg->elements[i].value.length; - mods[num_mods]->mod_vals.modv_bvals[1] = NULL; + mods[num_mods]->mod_vals.modv_bvals[j] = NULL; num_mods++; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index dda80a6b2a..8cda8abff8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -74,13 +74,22 @@ static char *ldb_dn_key(const char *attr, const struct ldb_val *value) /* see if a attribute value is in the list of indexed attributes */ -static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr) +static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, + int *v_idx) { - int i; + int i, j; for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, "@IDXATTR") == 0 && - strcmp((char *)msg->elements[i].value.data, attr) == 0) { - return i; + if (strcmp(msg->elements[i].name, "@IDXATTR") == 0) { + const struct ldb_message_element *el = + &msg->elements[i]; + for (j=0;jnum_values;j++) { + if (strcmp((char *)el->values[j].data, attr) == 0) { + if (v_idx) { + *v_idx = j; + } + return i; + } + } } } return -1; @@ -95,7 +104,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, struct dn_list *list) { char *dn = NULL; - int ret, i; + int ret, i, j; struct ldb_message msg; list->count = 0; @@ -110,7 +119,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* if the attribute isn't in the list of indexed attributes then this node needs a full search */ - if (ldb_msg_find_idx(index_list, tree->u.simple.attr) == -1) { + if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL) == -1) { return -1; } @@ -125,23 +134,30 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, return ret; } - list->dn = malloc_array_p(char *, msg.num_elements); - if (!list->dn) { - ltdb_search_dn1_free(ldb, &msg); - } - for (i=0;idn[list->count] = - strdup((char *)msg.elements[i].value.data); - if (!list->dn[list->count]) { - dn_list_free(list); - ltdb_search_dn1_free(ldb, &msg); - return -1; + + el = &msg.elements[i]; + + list->dn = malloc_array_p(char *, el->num_values); + if (!list->dn) { + break; + } + + for (j=0;jnum_values;j++) { + list->dn[list->count] = + strdup((char *)el->values[j].data); + if (!list->dn[list->count]) { + dn_list_free(list); + ltdb_search_dn1_free(ldb, &msg); + return -1; + } + list->count++; } - list->count++; } ltdb_search_dn1_free(ldb, &msg); @@ -470,18 +486,76 @@ int ltdb_search_indexed(struct ldb_context *ldb, return ret; } +/* + add a index element where this is the first indexed DN for this value +*/ +static int ltdb_index_add1_new(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_message_element *el, + const char *dn) +{ + struct ldb_message_element *el2; + + /* add another entry */ + el2 = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + if (!el2) { + return -1; + } + + msg->elements = el2; + msg->elements[msg->num_elements].name = "@IDX"; + msg->elements[msg->num_elements].num_values = 0; + msg->elements[msg->num_elements].values = malloc_p(struct ldb_val); + if (!msg->elements[msg->num_elements].values) { + return -1; + } + msg->elements[msg->num_elements].values[0].length = strlen(dn); + msg->elements[msg->num_elements].values[0].data = dn; + msg->elements[msg->num_elements].num_values = 1; + msg->num_elements++; + + return 0; +} + + +/* + add a index element where this is not the first indexed DN for this + value +*/ +static int ltdb_index_add1_add(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_message_element *el, + int idx, + const char *dn) +{ + struct ldb_val *v2; + + v2 = realloc_p(msg->elements[idx].values, + struct ldb_val, + msg->elements[idx].num_values+1); + if (!v2) { + return -1; + } + msg->elements[idx].values = v2; + + msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn); + msg->elements[idx].values[msg->elements[idx].num_values].data = dn; + msg->elements[idx].num_values++; + + return 0; +} + /* add an index entry for one message element */ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, - struct ldb_message_element *el) + struct ldb_message_element *el, int v_idx) { struct ldb_message msg; char *dn_key; - int ret; - struct ldb_message_element *el2; + int ret, i; - dn_key = ldb_dn_key(el->name, &el->value); + dn_key = ldb_dn_key(el->name, &el->values[v_idx]); if (!dn_key) { return -1; } @@ -493,36 +567,37 @@ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, } if (ret == 0) { - msg.dn = dn_key; + msg.dn = strdup(dn_key); + if (!msg.dn) { + free(dn_key); + errno = ENOMEM; + return -1; + } msg.num_elements = 0; msg.elements = NULL; msg.private = NULL; } - /* add another entry */ - el2 = realloc_p(msg.elements, struct ldb_message_element, msg.num_elements+1); - if (!el2) { - if (ret == 1) { - ltdb_search_dn1_free(ldb, &msg); + free(dn_key); + + for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); if (ret == -1) { continue; } - ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i]); - if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); - return -1; + for (j=0;jelements[i].num_values;j++) { + ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i], j); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } } } + ltdb_search_dn1_free(ldb, &index_list); + return 0; } @@ -562,13 +641,13 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) delete an index entry for one message element */ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, - struct ldb_message_element *el) + struct ldb_message_element *el, int v_idx) { struct ldb_message msg; char *dn_key; - int ret, i; + int ret, i, j; - dn_key = ldb_dn_key(el->name, &el->value); + dn_key = ldb_dn_key(el->name, &el->values[v_idx]); if (!dn_key) { return -1; } @@ -586,19 +665,22 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, return 0; } - i = ldb_msg_find_idx(&msg, dn); + i = ldb_msg_find_idx(&msg, dn, &j); if (i == -1) { /* it ain't there. hmmm */ ltdb_search_dn1_free(ldb, &msg); return 0; } - if (i != msg.num_elements - 1) { - memmove(&msg.elements[i], &msg.elements[i+1], sizeof(msg.elements[i])); + if (j != msg.elements[i].num_values - 1) { + memmove(&msg.elements[i].values[j], + &msg.elements[i].values[j+1], + (msg.elements[i].num_values-1) * + sizeof(msg.elements[i].values[0])); } - msg.num_elements--; + msg.elements[i].num_values--; - if (msg.num_elements == 0) { + if (msg.elements[i].num_values == 0) { ret = ltdb_delete_noindex(ldb, dn_key); } else { ret = ltdb_store(ldb, &msg, TDB_REPLACE); @@ -615,7 +697,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, */ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) { - int ret, i; + int ret, i, j; struct ldb_message index_list; /* find the list of indexed fields */ @@ -626,14 +708,16 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); if (ret == -1) { continue; } - ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i]); - if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); - return -1; + for (j=0;jelements[i].num_values;j++) { + ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i], j); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 89d204f56a..6f29726ee7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -39,7 +39,7 @@ see if two ldb_val structures contain the same data return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal(struct ldb_val *v1, struct ldb_val *v2) +int ldb_val_equal(const struct ldb_val *v1, const struct ldb_val *v2) { if (v1->length != v2->length) return 0; @@ -108,7 +108,7 @@ static int match_leaf(struct ldb_context *ldb, const char *base, enum ldb_scope scope) { - int i; + int i, j; if (!scope_match(msg->dn, base, scope)) { return 0; @@ -122,10 +122,16 @@ static int match_leaf(struct ldb_context *ldb, } for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, tree->u.simple.attr) == 0 && - (strcmp(tree->u.simple.value.data, "*") == 0 || - ldb_val_equal(&msg->elements[i].value, &tree->u.simple.value))) { - return 1; + if (strcmp(msg->elements[i].name, tree->u.simple.attr) == 0) { + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + for (j=0;jelements[i].num_values;j++) { + if (ldb_val_equal(&msg->elements[i].values[j], + &tree->u.simple.value)) { + return 1; + } + } } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index b0c825e8e2..1b0c8a1857 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -41,13 +41,16 @@ /* pack a ldb message into a linear buffer in a TDB_DATA + note that this routine avoids saving elements with zero values, + as these are equivalent to having no element + caller frees the data buffer after use */ int ltdb_pack_data(struct ldb_context *ctx, const struct ldb_message *message, struct TDB_DATA *data) { - int i; + int i, j; size_t size; char *p; @@ -55,8 +58,13 @@ int ltdb_pack_data(struct ldb_context *ctx, size = 8; for (i=0;inum_elements;i++) { - size += 1 + strlen(message->elements[i].name); - size += 4 + message->elements[i].value.length + 1; + if (message->elements[i].num_values == 0) { + continue; + } + size += 1 + strlen(message->elements[i].name) + 4; + for (j=0;jelements[i].num_values;j++) { + size += 4 + message->elements[i].values[j].length + 1; + } } /* allocate it */ @@ -73,28 +81,50 @@ int ltdb_pack_data(struct ldb_context *ctx, p += 8; for (i=0;inum_elements;i++) { - size_t len = strlen(message->elements[i].name); + size_t len; + if (message->elements[i].num_values == 0) { + continue; + } + len = strlen(message->elements[i].name); memcpy(p, message->elements[i].name, len+1); p += len + 1; - SIVAL(p, 0, message->elements[i].value.length); - memcpy(p+4, message->elements[i].value.data, - message->elements[i].value.length); - p[4+message->elements[i].value.length] = 0; - p += 4 + message->elements[i].value.length + 1; + SIVAL(p, 0, message->elements[i].num_values); + p += 4; + for (j=0;jelements[i].num_values;j++) { + SIVAL(p, 0, message->elements[i].values[j].length); + memcpy(p+4, message->elements[i].values[j].data, + message->elements[i].values[j].length); + p[4+message->elements[i].values[j].length] = 0; + p += 4 + message->elements[i].values[j].length + 1; + } } return 0; } +/* + free the memory allocated from a ltdb_unpack_data() +*/ +void ltdb_unpack_data_free(struct ldb_message *message) +{ + int i; + + for (i=0;inum_elements;i++) { + if (message->elements[i].values) free(message->elements[i].values); + } + if (message->elements) free(message->elements); +} + /* unpack a ldb message from a linear buffer in TDB_DATA note that this does not fill in the class and key elements - caller frees. Memory for the elements[] array is malloced, - but the memory for the elements is re-used from the TDB_DATA - data. This means the caller only has to free the elements array + caller frees. Memory for the elements[] and values[] arrays are + malloced, but the memory for the elements is re-used from the + TDB_DATA data. This means the caller only has to free the elements + and values arrays. This can be done with ltdb_unpack_data_free() */ int ltdb_unpack_data(struct ldb_context *ctx, const struct TDB_DATA *data, @@ -102,7 +132,7 @@ int ltdb_unpack_data(struct ldb_context *ctx, { char *p; unsigned int remaining; - int i; + int i, j; message->elements = NULL; @@ -145,30 +175,44 @@ int ltdb_unpack_data(struct ldb_context *ctx, for (i=0;inum_elements;i++) { size_t len; - if (remaining < 6) { + if (remaining < 10) { errno = EIO; goto failed; } len = strnlen(p, remaining-6); + message->elements[i].flags = 0; message->elements[i].name = p; remaining -= len + 1; p += len + 1; - len = IVAL(p, 0); - if (len > remaining-5) { - errno = EIO; - goto failed; + message->elements[i].num_values = IVAL(p, 0); + message->elements[i].values = NULL; + if (message->elements[i].num_values != 0) { + message->elements[i].values = malloc_array_p(struct ldb_val, + message->elements[i].num_values); + if (!message->elements[i].values) { + errno = ENOMEM; + goto failed; + } + } + p += 4; + for (j=0;jelements[i].num_values;j++) { + len = IVAL(p, 0); + if (len > remaining-5) { + errno = EIO; + goto failed; + } + + message->elements[i].values[j].length = len; + message->elements[i].values[j].data = p+4; + remaining -= len+4+1; + p += len+4+1; } - message->elements[i].value.length = len; - message->elements[i].value.data = p+4; - remaining -= len+4+1; - p += len+4+1; } return 0; failed: - if (message->elements) { - free(message->elements); - } + ltdb_unpack_data_free(message); + return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 952053c920..d7a7b7ffbd 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -40,11 +40,15 @@ */ static void msg_free_all_parts(struct ldb_message *msg) { - int i; + int i, j; if (msg->dn) free(msg->dn); for (i=0;inum_elements;i++) { if (msg->elements[i].name) free(msg->elements[i].name); - if (msg->elements[i].value.data) free(msg->elements[i].value.data); + for (j=0;jelements[i].num_values;j++) { + if (msg->elements[i].values[j].data) + free(msg->elements[i].values[j].data); + } + if (msg->elements[i].values) free(msg->elements[i].values); } free(msg->elements); free(msg); @@ -53,6 +57,7 @@ static void msg_free_all_parts(struct ldb_message *msg) /* TODO: this should take advantage of the sorted nature of the message + return index of the attribute, or -1 if not found */ int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr) @@ -69,7 +74,7 @@ int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr) /* duplicate a ldb_val structure */ -static struct ldb_val ldb_val_dup(const struct ldb_val *v) +struct ldb_val ldb_val_dup(const struct ldb_val *v) { struct ldb_val v2; v2.length = v->length; @@ -98,7 +103,8 @@ static struct ldb_val ldb_val_dup(const struct ldb_val *v) */ static int msg_add_element(struct ldb_message *ret, const struct ldb_message_element *el) { - struct ldb_message_element *e2; + int i; + struct ldb_message_element *e2, *elnew; e2 = realloc_p(ret->elements, struct ldb_message_element, ret->num_elements+1); if (!e2) { @@ -106,15 +112,31 @@ static int msg_add_element(struct ldb_message *ret, const struct ldb_message_ele } ret->elements = e2; - e2[ret->num_elements].name = strdup(el->name); - if (!e2[ret->num_elements].name) { + elnew = &e2[ret->num_elements]; + + elnew->name = strdup(el->name); + if (!elnew->name) { return -1; } - e2[ret->num_elements].value = ldb_val_dup(&el->value); - if (e2[ret->num_elements].value.length != el->value.length) { - return -1; + + if (el->num_values) { + elnew->values = malloc_array_p(struct ldb_val, el->num_values); + if (!elnew->values) { + return -1; + } + } else { + elnew->values = NULL; } + for (i=0;inum_values;i++) { + elnew->values[i] = ldb_val_dup(&el->values[i]); + if (elnew->values[i].length != el->values[i].length) { + return -1; + } + } + + elnew->num_values = el->num_values; + ret->num_elements++; return 0; @@ -215,8 +237,12 @@ int ltdb_has_wildcard(const struct ldb_val *val) */ void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { - free(msg->dn); - free(msg->private); + int i; + if (msg->dn) free(msg->dn); + if (msg->private) free(msg->private); + for (i=0;inum_elements;i++) { + if (msg->elements[i].values) free(msg->elements[i].values); + } if (msg->elements) free(msg->elements); } @@ -375,7 +401,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi /* see if it matches the given expression */ if (!ldb_message_match(sinfo->ldb, &msg, sinfo->tree, sinfo->base, sinfo->scope)) { - if (msg.elements) free(msg.elements); + ltdb_unpack_data_free(&msg); return 0; } @@ -385,7 +411,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi sinfo->failures++; } - if (msg.elements) free(msg.elements); + ltdb_unpack_data_free(&msg); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 17931352f7..95dce498f1 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -58,6 +58,44 @@ struct TDB_DATA ltdb_key(const char *dn) return key; } +/* + lock the database for write - currently a single lock is used +*/ +static int ltdb_lock(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private; + TDB_DATA key; + int ret; + + key = ltdb_key("LDBLOCK"); + if (!key.dptr) { + return -1; + } + + ret = tdb_chainlock(ltdb->tdb, key); + + free(key.dptr); + + return ret; +} + +/* + unlock the database after a ltdb_lock() +*/ +static void ltdb_unlock(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private; + TDB_DATA key; + + key = ltdb_key("LDBLOCK"); + if (!key.dptr) { + return; + } + + tdb_chainunlock(ltdb->tdb, key); + + free(key.dptr); +} /* store a record into the db @@ -102,7 +140,17 @@ done: */ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) { - return ltdb_store(ldb, msg, TDB_INSERT); + int ret; + + if (ltdb_lock(ldb) != 0) { + return -1; + } + + ret = ltdb_store(ldb, msg, TDB_INSERT); + + ltdb_unlock(ldb); + + return ret; } @@ -135,18 +183,22 @@ static int ltdb_delete(struct ldb_context *ldb, const char *dn) int ret; struct ldb_message msg; + if (ltdb_lock(ldb) != 0) { + return -1; + } + /* in case any attribute of the message was indexed, we need to fetch the old record */ ret = ltdb_search_dn1(ldb, dn, &msg); if (ret != 1) { /* not finding the old record is an error */ - return -1; + goto failed; } ret = ltdb_delete_noindex(ldb, dn); if (ret == -1) { ltdb_search_dn1_free(ldb, &msg); - return -1; + goto failed; } /* remove any indexed attributes */ @@ -154,57 +206,244 @@ static int ltdb_delete(struct ldb_context *ldb, const char *dn) ltdb_search_dn1_free(ldb, &msg); + ltdb_unlock(ldb); return ret; + +failed: + ltdb_unlock(ldb); + return -1; +} + + +/* + find an element by attribute name. At the moment this does a linear search, it should + be re-coded to use a binary search once all places that modify records guarantee + sorted order + + return the index of the first matching element if found, otherwise -1 +*/ +static int find_element(const struct ldb_message *msg, const char *name) +{ + int i; + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, name) == 0) { + return i; + } + } + return -1; +} + + +/* + add an element to an existing record. Assumes a elements array that we + can call re-alloc on, and assumed that we can re-use the data pointers from the + passed in additional values. Use with care! + + returns 0 on success, -1 on failure (and sets errno) +*/ +static int msg_add_element(struct ldb_message *msg, struct ldb_message_element *el) +{ + struct ldb_message_element *e2; + int i; + + e2 = realloc_p(msg->elements, struct ldb_message_element, + msg->num_elements+1); + if (!e2) { + errno = ENOMEM; + return -1; + } + + msg->elements = e2; + + e2 = &msg->elements[msg->num_elements]; + + e2->name = el->name; + e2->flags = el->flags; + e2->values = NULL; + if (el->num_values != 0) { + e2->values = malloc_array_p(struct ldb_val, el->num_values); + if (!e2->values) { + free(e2->name); + errno = ENOMEM; + return -1; + } + } + for (i=0;inum_values;i++) { + e2->values[i] = el->values[i]; + } + e2->num_values = el->num_values; + + msg->num_elements++; + + return 0; +} + +/* + delete all elements having a specified attribute name +*/ +static int msg_delete_attribute(struct ldb_message *msg, const char *name) +{ + int i, count=0; + struct ldb_message_element *el2; + + el2 = malloc_array_p(struct ldb_message_element, msg->num_elements); + if (!el2) { + errno = ENOMEM; + return -1; + } + + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, name) != 0) { + el2[count++] = msg->elements[i]; + } else { + if (msg->elements[i].values) free(msg->elements[i].values); + } + } + + msg->num_elements = count; + if (msg->elements) free(msg->elements); + msg->elements = el2; + + return 0; } +/* + delete all elements matching an attribute name/value + + return 0 on success, -1 on failure +*/ +static int msg_delete_element(struct ldb_message *msg, + const char *name, + const struct ldb_val *val) +{ + int i; + struct ldb_message_element *el; + + i = find_element(msg, name); + if (i == -1) { + return -1; + } + + el = &msg->elements[i]; + + for (i=0;inum_values;i++) { + if (ldb_val_equal(&el->values[i], val)) { + if (inum_values-1) { + memmove(&el->values[i], &el->values[i+1], + sizeof(el->values[i])*el->num_values-(i+1)); + } + el->num_values--; + return 0; + } + } + + return -1; +} /* modify a record + + yuck - this is O(n^2). Luckily n is usually small so we probably + get away with it, but if we ever have really large attribute lists + then we'll need to look at this again */ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) { struct ltdb_private *ltdb = ldb->private; TDB_DATA tdb_key, tdb_data; struct ldb_message msg2; - int ret; + int ret, i, j; + + if (ltdb_lock(ldb) != 0) { + return -1; + } tdb_key = ltdb_key(msg->dn); if (!tdb_key.dptr) { - return -1; + goto unlock_fail; } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); if (!tdb_data.dptr) { free(tdb_key.dptr); - return -1; + goto unlock_fail; } ret = ltdb_unpack_data(ldb, &tdb_data, &msg2); if (ret == -1) { free(tdb_key.dptr); free(tdb_data.dptr); - return -1; + goto unlock_fail; } -#if 0 + msg2.dn = msg->dn; + for (i=0;inum_elements;i++) { switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + /* add this element to the message. fail if it + already exists */ ret = find_element(&msg2, msg->elements[i].name); if (ret != -1) { errno = EEXIST; goto failed; } - + if (msg_add_element(&msg2, &msg->elements[i]) != 0) { + goto failed; + } + break; + + case LDB_FLAG_MOD_REPLACE: + /* replace all elements of this attribute name with the elements + listed */ + if (msg_delete_attribute(&msg2, msg->elements[i].name) != 0) { + goto failed; + } + /* add the replacement element */ + if (msg_add_element(&msg2, &msg->elements[i]) != 0) { + goto failed; + } + break; + + case LDB_FLAG_MOD_DELETE: + /* we could be being asked to delete all + values or just some values */ + if (msg->elements[i].num_values == 0) { + if (msg_delete_attribute(&msg2, + msg->elements[i].name) != 0) { + goto failed; + } + break; + } + for (j=0;jelements[i].num_values;j++) { + if (msg_delete_element(&msg2, + msg->elements[i].name, + &msg->elements[i].values[j]) != 0) { + goto failed; + } + } + break; } } -failed: -#endif + /* we've made all the mods - save the modified record back into the database */ + ret = ltdb_store(ldb, &msg2, TDB_MODIFY); + + free(tdb_key.dptr); + free(tdb_data.dptr); + ltdb_unpack_data_free(&msg2); + ltdb_unlock(ldb); + return ret; + +failed: free(tdb_key.dptr); free(tdb_data.dptr); - if (msg2.elements) free(msg2.elements); + ltdb_unpack_data_free(&msg2); + +unlock_fail: + ltdb_unlock(ldb); return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldbadd.c b/source4/lib/ldb/ldb_tdb/ldbadd.c deleted file mode 100644 index 3959a17525..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldbadd.c +++ /dev/null @@ -1,55 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - a utility to add elements to a ldb - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - int main(void) -{ - static struct ldb_context *ldb; - struct ldb_message *msg; - int ret; - int count=0, failures=0; - - ldb = ltdb_connect("tdb://test.ldb", 0, NULL); - - if (!ldb) { - perror("ldb_connect"); - exit(1); - } - - while ((msg = ldif_read(stdin))) { - ret = ldb->ops->add(ldb, msg); - if (ret != 0) { - fprintf(stderr, "Failed to add record '%s'\n", msg->dn); - failures++; - } else { - count++; - } - ldif_read_free(msg); - } - - ldb->ops->close(ldb); - - printf("Added %d records with %d failures\n", count, failures); - - return 0; -} diff --git a/source4/lib/ldb/ldb_tdb/ldbdel.c b/source4/lib/ldb/ldb_tdb/ldbdel.c deleted file mode 100644 index 8f8a03913f..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldbdel.c +++ /dev/null @@ -1,50 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - a utility to delete elements in a ldb - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - int main(int argc, const char *argv[]) -{ - static struct ldb_context *ldb; - int ret, i; - - if (argc < 2) { - printf("Usage: ldbdel \n"); - exit(1); - } - - ldb = ltdb_connect("tdb://test.ldb", 0, NULL); - if (!ldb) { - perror("ldb_connect"); - exit(1); - } - - for (i=1;iops->delete(ldb, argv[i]); - if (ret != 0) { - printf("delete of '%s' failed\n", argv[i]); - } - } - - ldb->ops->close(ldb); - return 0; -} diff --git a/source4/lib/ldb/ldb_tdb/ldbsearch.c b/source4/lib/ldb/ldb_tdb/ldbsearch.c deleted file mode 100644 index a6d63e78d5..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldbsearch.c +++ /dev/null @@ -1,73 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - simple ldb search tool - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - int main(int argc, const char *argv[]) -{ - static struct ldb_context *ldb; - struct ldb_message **msgs; - int ret, i; - const char *expression; - const char **attrs = NULL; - - if (argc < 2) { - printf("Usage: ldbsearch [attrs...]\n"); - exit(1); - } - - if (argc > 2) { - attrs = argv+2; - } - - expression = argv[1]; - - ldb = ltdb_connect("tdb://test.ldb", 0, NULL); - - if (!ldb) { - perror("ldb_connect"); - exit(1); - } - - ret = ldb->ops->search(ldb, expression, attrs, &msgs); - - if (ret == -1) { - printf("search failed\n"); - exit(1); - } - - printf("# returned %d records\n", ret); - - for (i=0;iops->search_free(ldb, msgs); - if (ret == -1) { - fprintf(stderr, "search_free failed\n"); - exit(1); - } - - ldb->ops->close(ldb); - return 0; -} diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh new file mode 100644 index 0000000000..41f5707e9c --- /dev/null +++ b/source4/lib/ldb/tests/test-generic.sh @@ -0,0 +1,8 @@ +echo "Adding base elements" +bin/ldbadd < tests/test.ldif + +echo "Modifying elements" +bin/ldbmodify < tests/test-modify.ldif + +echo "Showing modified record" +bin/ldbsearch '(uid=uham)' diff --git a/source4/lib/ldb/tests/test-ldap.sh b/source4/lib/ldb/tests/test-ldap.sh new file mode 100755 index 0000000000..29b40ff455 --- /dev/null +++ b/source4/lib/ldb/tests/test-ldap.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +tests/init_slapd.sh +tests/start_slapd.sh + +export LDB_URL=`tests/ldapi_url.sh` + +. tests/test-generic.sh diff --git a/source4/lib/ldb/tests/test-modify.ldif b/source4/lib/ldb/tests/test-modify.ldif new file mode 100644 index 0000000000..521c6d8b56 --- /dev/null +++ b/source4/lib/ldb/tests/test-modify.ldif @@ -0,0 +1,14 @@ +dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michiga + n,c=US +changetype: modify +add: drink +drink: mango lassi +- +delete: pager +- +replace: telephonenumber +telephonenumber: +61 2 6260 6012 +telephonenumber: +61 412 666 929 +- +delete: telephonenumber +telephonenumber: +61 2 6260 6012 diff --git a/source4/lib/ldb/tests/test-tdb.sh b/source4/lib/ldb/tests/test-tdb.sh new file mode 100755 index 0000000000..1e21accac5 --- /dev/null +++ b/source4/lib/ldb/tests/test-tdb.sh @@ -0,0 +1,8 @@ +#!/bin/sh + + +export LDB_URL="tdb://test.ldb" + +rm -f test.ldb + +. tests/test-generic.sh diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 3eb7cb8de2..92ed29e6b8 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -37,7 +37,7 @@ int main(void) { static struct ldb_context *ldb; - struct ldb_message *msg; + struct ldb_ldif *ldif; int ret; int count=0, failures=0; const char *ldb_url; @@ -54,16 +54,23 @@ exit(1); } - while ((msg = ldif_read_file(stdin))) { - ret = ldb_add(ldb, msg); + while ((ldif = ldif_read_file(stdin))) { + + if (ldif->changetype != LDB_CHANGETYPE_ADD && + ldif->changetype != LDB_CHANGETYPE_NONE) { + fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); + break; + } + + ret = ldb_add(ldb, &ldif->msg); if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", - ldb_errstring(ldb), msg->dn); + ldb_errstring(ldb), ldif->msg.dn); failures++; } else { count++; } - ldif_read_free(msg); + ldif_read_free(ldif); } ldb_close(ldb); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c new file mode 100644 index 0000000000..e1cff655db --- /dev/null +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -0,0 +1,85 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbmodify + * + * Description: utility to modify records - modelled on ldapmodify + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + int main(void) +{ + static struct ldb_context *ldb; + struct ldb_ldif *ldif; + int ret; + int count=0, failures=0; + const char *ldb_url; + + ldb_url = getenv("LDB_URL"); + if (!ldb_url) { + ldb_url = "tdb://test.ldb"; + } + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + while ((ldif = ldif_read_file(stdin))) { + switch (ldif->changetype) { + case LDB_CHANGETYPE_NONE: + case LDB_CHANGETYPE_ADD: + ret = ldb_add(ldb, &ldif->msg); + break; + case LDB_CHANGETYPE_DELETE: + ret = ldb_delete(ldb, ldif->msg.dn); + break; + case LDB_CHANGETYPE_MODIFY: + ret = ldb_modify(ldb, &ldif->msg); + break; + } + if (ret != 0) { + fprintf(stderr, "ERR: \"%s\" on DN %s\n", + ldb_errstring(ldb), ldif->msg.dn); + failures++; + } else { + count++; + } + ldif_read_free(ldif); + } + + ldb_close(ldb); + + printf("Modified %d records with %d failures\n", count, failures); + + return 0; +} diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index d7d3c83162..f4eb8f00db 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -45,7 +45,7 @@ const char *ldb_url; const char *basedn = NULL; int opt; - enum ldb_scope scope = LDB_SCOPE_DEFAULT; + enum ldb_scope scope = LDB_SCOPE_SUBTREE; ldb_url = getenv("LDB_URL"); if (!ldb_url) { @@ -98,15 +98,20 @@ ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); if (ret == -1) { - printf("search failed\n"); + printf("search failed - %s\n", ldb_errstring(ldb)); exit(1); } printf("# returned %d records\n", ret); for (i=0;i 0) { -- cgit From 3855ee0164d1c8ff3c3c4ba8a5556d8cfb6546b3 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 12:39:20 -0500 Subject: [GLUE] Sync tree with SVN r17. (This used to be commit 6e50109b664ff5fcc3d27f676d101c2b36574a63) --- source4/lib/popt/dummy.in | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 source4/lib/popt/dummy.in (limited to 'source4/lib') diff --git a/source4/lib/popt/dummy.in b/source4/lib/popt/dummy.in deleted file mode 100644 index e69de29bb2..0000000000 -- cgit From c424c2b857fe08587eb81a5c5e3625545119d1c2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Apr 2004 16:24:08 +0000 Subject: r20: Add the registry library. Still needs a lot of work, see source/lib/registry/TODO for details. (This used to be commit 7cab3a00d7b4b1d95a3bfa6b28f318b4aaa5d493) --- source4/lib/registry/TODO | 27 + source4/lib/registry/common/reg_display.c | 60 + source4/lib/registry/common/reg_interface.c | 423 +++++ source4/lib/registry/common/reg_objects.c | 202 +++ source4/lib/registry/common/reg_util.c | 164 ++ source4/lib/registry/common/registry.h | 121 ++ source4/lib/registry/config.m4 | 16 + .../lib/registry/reg_backend_dir/reg_backend_dir.c | 154 ++ .../registry/reg_backend_gconf/reg_backend_gconf.c | 189 +++ .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 61 + .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 1745 ++++++++++++++++++++ .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 311 ++++ .../registry/reg_backend_wine/reg_backend_wine.c | 32 + source4/lib/registry/tools/regdiff.c | 148 ++ source4/lib/registry/tools/regpatch.c | 808 +++++++++ source4/lib/registry/tools/regshell.c | 243 +++ source4/lib/registry/tools/regtree.c | 91 + source4/lib/registry/winregistry.pc.in | 10 + 18 files changed, 4805 insertions(+) create mode 100644 source4/lib/registry/TODO create mode 100644 source4/lib/registry/common/reg_display.c create mode 100644 source4/lib/registry/common/reg_interface.c create mode 100644 source4/lib/registry/common/reg_objects.c create mode 100644 source4/lib/registry/common/reg_util.c create mode 100644 source4/lib/registry/common/registry.h create mode 100644 source4/lib/registry/config.m4 create mode 100644 source4/lib/registry/reg_backend_dir/reg_backend_dir.c create mode 100644 source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c create mode 100644 source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c create mode 100644 source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c create mode 100644 source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c create mode 100644 source4/lib/registry/reg_backend_wine/reg_backend_wine.c create mode 100644 source4/lib/registry/tools/regdiff.c create mode 100644 source4/lib/registry/tools/regpatch.c create mode 100644 source4/lib/registry/tools/regshell.c create mode 100644 source4/lib/registry/tools/regtree.c create mode 100644 source4/lib/registry/winregistry.pc.in (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO new file mode 100644 index 0000000000..26fb8d217d --- /dev/null +++ b/source4/lib/registry/TODO @@ -0,0 +1,27 @@ +- support subtrees +- ../../, /bla/blie support in regshell +- use memory pools? +- get rid of all the nasty memory leaks.. +- security stuff +- finish 'regpatch' +- clean up code +- rpc_server + +reg_backend_dir: + - value support + +reg_backend_nt4: + - write support + +reg_backend_rpc: + - value enum support + - write support + +reg_backend_ldb: + - implement + +reg_backend_wine.c: + - implement + +regpatch.c: + - test/finish diff --git a/source4/lib/registry/common/reg_display.c b/source4/lib/registry/common/reg_display.c new file mode 100644 index 0000000000..e12f4ba20e --- /dev/null +++ b/source4/lib/registry/common/reg_display.c @@ -0,0 +1,60 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Gerald Carter 2001 + Copyright (C) Tim Potter 2000 + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +void display_reg_value(REG_VAL *value) +{ + pstring text; + + switch(reg_val_type(value)) { + case REG_DWORD: + printf("%s: REG_DWORD: 0x%08x\n", reg_val_name(value), + *((uint32 *) reg_val_data_blk(value))); + break; + case REG_SZ: + rpcstr_pull(text, reg_val_data_blk(value), sizeof(text), reg_val_size(value), + STR_TERMINATE); + printf("%s: REG_SZ: %s\n", reg_val_name(value), text); + break; + case REG_BINARY: + printf("%s: REG_BINARY: unknown length value not displayed\n", + reg_val_name(value)); + break; + case REG_MULTI_SZ: { + uint16 *curstr = (uint16 *) reg_val_data_blk(value); + uint8 *start = reg_val_data_blk(value); + printf("%s: REG_MULTI_SZ:\n", reg_val_name(value)); + while ((*curstr != 0) && + ((uint8 *) curstr < start + reg_val_size(value))) { + rpcstr_pull(text, curstr, sizeof(text), -1, + STR_TERMINATE); + printf(" %s\n", text); + curstr += strlen(text) + 1; + } + } + break; + default: + printf("%s: unknown type %d\n", reg_val_name(value), reg_val_type(value)); + } + +} diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c new file mode 100644 index 0000000000..dc49dab4c1 --- /dev/null +++ b/source4/lib/registry/common/reg_interface.c @@ -0,0 +1,423 @@ +/* + Unix SMB/CIFS implementation. + Transparent registry backend handling + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +/* List of available backends */ +static struct reg_init_function_entry *backends = NULL; + +static struct reg_init_function_entry *reg_find_backend_entry(const char *name); + +/* Register new backend */ +NTSTATUS registry_register(void *_function) +{ + REG_OPS *functions = _function; + struct reg_init_function_entry *entry = backends; + + if (!functions || !functions->name) { + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(5,("Attempting to register registry backend %s\n", functions->name)); + + /* Check for duplicates */ + if (reg_find_backend_entry(functions->name)) { + DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = malloc(sizeof(struct reg_init_function_entry)); + entry->functions = functions; + + DLIST_ADD(backends, entry); + DEBUG(5,("Successfully added registry backend '%s'\n", functions->name)); + return NT_STATUS_OK; +} + + +/* Find a backend in the list of available backends */ +static struct reg_init_function_entry *reg_find_backend_entry(const char *name) +{ + struct reg_init_function_entry *entry = backends; + + while(entry) { + if (strcmp(entry->functions->name, name)==0) return entry; + entry = entry->next; + } + + return NULL; +} + +/* Open a registry file/host/etc */ +REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_load) +{ + struct reg_init_function_entry *entry; + static BOOL reg_first_init = True; + REG_HANDLE *ret; + + if(reg_first_init) { + if (!NT_STATUS_IS_OK(register_subsystem("registry", registry_register))) { + return False; + } + + static_init_reg; + reg_first_init = False; + } + + entry = reg_find_backend_entry(backend); + + if (!entry) { + DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); + return NULL; + } + + ret = malloc(sizeof(REG_HANDLE)); + ZERO_STRUCTP(ret); + ret->location = location?strdup(location):NULL; + ret->functions = entry->functions; + ret->backend_data = NULL; + + if(!entry->functions->open_registry) { + return ret; + } + + if(entry->functions->open_registry(ret, location, try_full_load)) + return ret; + + SAFE_FREE(ret); + return NULL; +} + +/* Open a key */ +REG_KEY *reg_open_key(REG_KEY *parent, const char *name) +{ + char *fullname; + REG_KEY *ret = NULL; + + if(!parent) { + DEBUG(0, ("Invalid parent key specified")); + return NULL; + } + + if(!parent->handle->functions->open_key && + (parent->handle->functions->get_subkey_by_name || + parent->handle->functions->get_subkey_by_index)) { + char *orig = strdup(name), + *curbegin = orig, + *curend = strchr(orig, '\\'); + REG_KEY *curkey = parent; + + while(curbegin && *curbegin) { + if(curend)*curend = '\0'; + curkey = reg_key_get_subkey_by_name(curkey, curbegin); + if(!curkey) return NULL; + if(!curend) break; + curbegin = curend + 1; + curend = strchr(curbegin, '\\'); + } + + return curkey; + } + + asprintf(&fullname, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); + + if(!parent->handle->functions->open_key) { + DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); + return NULL; + } + + ret = parent->handle->functions->open_key(parent->handle, fullname); + + if(ret) { + ret->handle = parent->handle; + ret->path = fullname; + } else + SAFE_FREE(fullname); + + return ret; +} + +REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx) +{ + REG_VAL *ret; + + if(!key) return NULL; + + if(!key->handle->functions->get_value_by_index) { + if(!key->cache_values) + key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); + + if(idx < key->cache_values_count && idx >= 0) { + ret = reg_val_dup(key->cache_values[idx]); + } else { + return NULL; + } + } else { + ret = key->handle->functions->get_value_by_index(key, idx); + } + + if(ret) { + ret->parent = key; + ret->handle = key->handle; + } + + return ret; +} + +int reg_key_num_subkeys(REG_KEY *key) +{ + if(!key->handle->functions->num_subkeys) { + if(!key->cache_subkeys) + key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + + return key->cache_subkeys_count; + } + + return key->handle->functions->num_subkeys(key); +} + +int reg_key_num_values(REG_KEY *key) +{ + + if(!key) return 0; + + if(!key->handle->functions->num_values) { + if(!key->handle->functions->fetch_values) { + DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); + return 0; + } + + if(!key->cache_values) + key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); + + return key->cache_values_count; + } + + + return key->handle->functions->num_values(key); +} + +REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx) +{ + REG_KEY *ret = NULL; + + if(!key) return NULL; + + if(!key->handle->functions->get_subkey_by_index) { + if(!key->cache_subkeys) + key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + + if(idx < key->cache_subkeys_count) { + ret = reg_key_dup(key->cache_subkeys[idx]); + } else { + /* No such key ! */ + return NULL; + } + } else { + ret = key->handle->functions->get_subkey_by_index(key, idx); + } + + if(ret && !ret->path) { + asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->handle = key->handle; + } + + return ret; +} + +REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name) +{ + int i, max; + REG_KEY *ret = NULL; + + if(!key) return NULL; + + if(key->handle->functions->get_subkey_by_name) { + ret = key->handle->functions->get_subkey_by_name(key,name); + } else { + max = reg_key_num_subkeys(key); + for(i = 0; i < max; i++) { + REG_KEY *v = reg_key_get_subkey_by_index(key, i); + if(v && !strcmp(v->name, name)) { + ret = v; + break; + } + reg_key_free(v); + } + } + + if(ret && !ret->path) { + asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->handle = key->handle; + } + + return ret; +} + +REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name) +{ + int i, max; + REG_VAL *ret = NULL; + + if(!key) return NULL; + + if(key->handle->functions->get_value_by_name) { + ret = key->handle->functions->get_value_by_name(key,name); + } else { + max = reg_key_num_values(key); + for(i = 0; i < max; i++) { + REG_VAL *v = reg_key_get_value_by_index(key, i); + if(v && StrCaseCmp(v->name, name)) { + ret = v; + break; + } + reg_val_free(v); + } + } + + if(ret) { + ret->parent = key; + ret->handle = key->handle; + } + + return ret; +} + +BOOL reg_key_del(REG_KEY *key) +{ + if(key->handle->functions->del_key) + return key->handle->functions->del_key(key); + + return False; +} + +BOOL reg_sync(REG_HANDLE *h, const char *location) +{ + if(!h->functions->sync) + return True; + + return h->functions->sync(h, location); +} + +BOOL reg_key_del_recursive(REG_KEY *key) +{ + BOOL succeed = True; + int i; + + /* Delete all values for specified key */ + for(i = 0; i < reg_key_num_values(key); i++) { + if(!reg_val_del(reg_key_get_value_by_index(key, i))) + succeed = False; + } + + /* Delete all keys below this one */ + for(i = 0; i < reg_key_num_subkeys(key); i++) { + if(!reg_key_del_recursive(reg_key_get_subkey_by_index(key, i))) + succeed = False; + } + + if(succeed)reg_key_del(key); + + return succeed; +} + +BOOL reg_val_del(REG_VAL *val) +{ + if (!val->handle->functions->del_value) { + DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); + return False; + } + + return val->handle->functions->del_value(val); +} + +BOOL reg_key_add_name(REG_KEY *parent, const char *name) +{ + if (!parent->handle->functions->add_key) { + DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); + return False; + } + + return parent->handle->functions->add_key(parent, name); +} + +BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) +{ + /* A 'real' update function has preference */ + if (val->handle->functions->update_value) + return val->handle->functions->update_value(val, type, data, len); + + /* Otherwise, just remove and add again */ + if (val->handle->functions->add_value && + val->handle->functions->del_value) { + REG_VAL *new; + if(!val->handle->functions->del_value(val)) + return False; + + new = val->handle->functions->add_value(val->parent, val->name, type, data, len); + memcpy(val, new, sizeof(REG_VAL)); + return True; + } + + DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); + return False; +} + +void reg_free(REG_HANDLE *h) +{ + if(!h->functions->close_registry) return; + + h->functions->close_registry(h); +} + +REG_KEY *reg_get_root(REG_HANDLE *h) +{ + REG_KEY *ret = NULL; + if(h->functions->open_root_key) { + ret = h->functions->open_root_key(h); + } else if(h->functions->open_key) { + ret = h->functions->open_key(h, "\\"); + } else { + DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name)); + } + + if(ret) { + ret->handle = h; + ret->path = strdup("\\"); + } + + return ret; +} + +REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +{ + REG_VAL *ret; + if(!key->handle->functions->add_value) + return NULL; + + ret = key->handle->functions->add_value(key, name, type, value, vallen); + ret->parent = key; + ret->handle = key->handle; + return ret; +} diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c new file mode 100644 index 0000000000..911dc15c8e --- /dev/null +++ b/source4/lib/registry/common/reg_objects.c @@ -0,0 +1,202 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2002. + * Copyright (C) Jelmer Vernooij 2003-2004. + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of registry frontend view functions. */ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/*********************************************************************** + allocate memory for and duplicate a REG_VAL. + This is malloc'd memory so the caller should free it when done + **********************************************************************/ + +REG_VAL* reg_val_dup( REG_VAL *val ) +{ + REG_VAL *copy = NULL; + + if ( !val ) + return NULL; + + if ( !(copy = malloc( sizeof(REG_VAL) )) ) { + DEBUG(0,("dup_registry_value: malloc() failed!\n")); + return NULL; + } + + /* copy all the non-pointer initial data */ + + memcpy( copy, val, sizeof(REG_VAL) ); + if ( val->data_blk ) + { + if ( !(copy->data_blk = memdup( val->data_blk, val->data_len )) ) { + DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n", + val->data_len)); + SAFE_FREE( copy ); + } + } + + return copy; +} + +/********************************************************************** + free the memory allocated to a REG_VAL + *********************************************************************/ + +void reg_val_free( REG_VAL *val ) +{ + if ( !val ) + return; + + if(val->handle->functions->free_val_backend_data) + val->handle->functions->free_val_backend_data(val); + + SAFE_FREE( val->data_blk ); + SAFE_FREE( val ); + + return; +} + +/********************************************************************** + *********************************************************************/ + +uint8* reg_val_data_blk( REG_VAL *val ) +{ + return val->data_blk; +} + +/********************************************************************** + *********************************************************************/ + +int reg_val_size( REG_VAL *val ) +{ + return val->data_len; +} + +/********************************************************************** + *********************************************************************/ + +char *reg_val_name( REG_VAL *val ) +{ + return val->name; +} + +/********************************************************************** + *********************************************************************/ + +uint32 reg_val_type( REG_VAL *val ) +{ + return val->data_type; +} + +/********************************************************************** + *********************************************************************/ + +char *reg_key_name( REG_KEY *key ) +{ + return key->name; +} + +REG_KEY *reg_key_dup(REG_KEY *key) +{ + key->ref++; + return key; +} + +void reg_key_free(REG_KEY *key) +{ + if(!key) + return; + + key->ref--; + if(key->ref) return; + + if(key->handle->functions->free_key_backend_data) + key->handle->functions->free_key_backend_data(key); + + if(key->cache_values) { + int i; + for(i = 0; i < key->cache_values_count; i++) { + reg_val_free(key->cache_values[i]); + } + SAFE_FREE(key->cache_values); + } + + if(key->cache_subkeys) { + int i; + for(i = 0; i < key->cache_subkeys_count; i++) { + reg_key_free(key->cache_subkeys[i]); + } + SAFE_FREE(key->cache_subkeys); + } + + SAFE_FREE(key->path); + SAFE_FREE(key->name); + SAFE_FREE(key); +} + +char *reg_val_get_path(REG_VAL *v) +{ + /* FIXME */ + return NULL; +} + +char *reg_key_get_path(REG_KEY *k) +{ + SMB_REG_ASSERT(k); + return k->path; +} + +/* For use by the backends _ONLY_ */ +REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) +{ + REG_KEY *r = malloc(sizeof(REG_KEY)); + ZERO_STRUCTP(r); + r->handle = h; + r->path = strdup(path); + r->name = strdup(strrchr(path, '\\')?strrchr(path,'\\')+1:path); + r->backend_data = data; + r->ref = 1; + return r; +} + +REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) +{ + REG_KEY *r = malloc(sizeof(REG_KEY)); + ZERO_STRUCTP(r); + r->handle = k->handle; + r->name = strdup(name); + r->backend_data = data; + r->ref = 1; + return r; +} + +REG_VAL *reg_val_new(REG_KEY *parent, void *data) +{ + REG_VAL *r = malloc(sizeof(REG_VAL)); + ZERO_STRUCTP(r); + r->handle = parent->handle; + r->backend_data = data; + r->ref = 1; + return r; +} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c new file mode 100644 index 0000000000..2941c38cf4 --- /dev/null +++ b/source4/lib/registry/common/reg_util.c @@ -0,0 +1,164 @@ +/* + Unix SMB/CIFS implementation. + Transparent registry backend handling + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +/* Return string description of registry value type */ +const char *str_regtype(int type) +{ + switch(type) { + case REG_SZ: return "STRING"; + case REG_DWORD: return "DWORD"; + case REG_BINARY: return "BINARY"; + } + return "Unknown"; +} + +char *reg_val_data_string(REG_VAL *v) +{ + char *asciip; + char *ret = NULL; + int i; + + if(reg_val_size(v) == 0) return strdup(""); + + switch (reg_val_type(v)) { + case REG_SZ: + /* FIXME: Convert to ascii */ + return strdup(reg_val_data_blk(v)); + + case REG_EXPAND_SZ: + return strdup(reg_val_data_blk(v)); + + case REG_BINARY: + ret = malloc(reg_val_size(v) * 3 + 2); + asciip = ret; + for (i=0; i 0) + *asciip = ' '; asciip++; + } + *asciip = '\0'; + return ret; + break; + + case REG_DWORD: + if (*(int *)reg_val_data_blk(v) == 0) + ret = strdup("0"); + else + asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v)); + break; + + case REG_MULTI_SZ: + /* FIXME */ + break; + + default: + return 0; + break; + } + + return ret; +} + +const char *reg_val_description(REG_VAL *val) +{ + char *ret, *ds = reg_val_data_string(val); + asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"", str_regtype(reg_val_type(val)), ds); + free(ds); + return ret; +} + +BOOL reg_val_set_string(REG_VAL *val, char *str) +{ + /* FIXME */ + return False; +} + +REG_VAL *reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname) +{ + REG_KEY *k = reg_key_get_subkey_by_name(key, subname); + if(!k) return NULL; + + return reg_key_get_value_by_name(k, valname); +} + +BOOL reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len) +{ + REG_KEY *k = reg_key_get_subkey_by_name(key, subname); + REG_VAL *v; + if(!k) return False; + + v = reg_key_get_value_by_name(k, valname); + if(!v) return False; + + return reg_val_update(v, type, data, real_len); +} + +/*********************************************************************** + Utility function for splitting the base path of a registry path off + by setting base and new_path to the apprapriate offsets withing the + path. + + WARNING!! Does modify the original string! + ***********************************************************************/ + +BOOL reg_split_path( char *path, char **base, char **new_path ) +{ + char *p; + + *new_path = *base = NULL; + + if ( !path) + return False; + + *base = path; + + p = strchr( path, '\\' ); + + if ( p ) { + *p = '\0'; + *new_path = p+1; + } + + return True; +} + +char *reg_path_win2unix(char *path) +{ + int i; + for(i = 0; path[i]; i++) { + if(path[i] == '\\') path[i] = '/'; + } + return path; +} + +char *reg_path_unix2win(char *path) +{ + int i; + for(i = 0; path[i]; i++) { + if(path[i] == '/') path[i] = '\\'; + } + return path; +} diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h new file mode 100644 index 0000000000..4b29006217 --- /dev/null +++ b/source4/lib/registry/common/registry.h @@ -0,0 +1,121 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + This file contains the _internal_ structs for the registry + subsystem. Backends and the subsystem itself are the only + files that need to include this file. + Copyright (C) Gerald Carter 2002. + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */ +#define _REGISTRY_REGISTRY_H + +#define REGISTRY_INTERFACE_VERSION 1 + +/* structure to store the registry handles */ +struct reg_key_s { + char *name; /* Name of the key */ + char *path; /* Full path to the key */ + smb_ucs2_t *class_name; /* Name of key class */ + NTTIME last_mod; /* Time last modified */ + SEC_DESC *security; + REG_HANDLE *handle; + void *backend_data; + REG_VAL **cache_values; + int cache_values_count; + REG_KEY **cache_subkeys; + int cache_subkeys_count; + int ref; +}; + +struct reg_val_s { + char *name; + int has_name; + int data_type; + int data_len; + void *data_blk; /* Might want a separate block */ + REG_HANDLE *handle; + REG_KEY *parent; + void *backend_data; + int ref; +}; + +/* + * Container for function pointers to enumeration routines + * for virtual registry view + */ + +struct reg_ops_s { + const char *name; + BOOL (*open_registry) (REG_HANDLE *, const char *location, BOOL try_complete_load); + BOOL (*sync)(REG_HANDLE *, const char *location); + BOOL (*close_registry) (REG_HANDLE *); + + /* Either implement these */ + REG_KEY *(*open_root_key) (REG_HANDLE *); + int (*num_subkeys) (REG_KEY *); + int (*num_values) (REG_KEY *); + REG_KEY *(*get_subkey_by_index) (REG_KEY *, int idx); + REG_KEY *(*get_subkey_by_name) (REG_KEY *, const char *name); + REG_VAL *(*get_value_by_index) (REG_KEY *, int idx); + REG_VAL *(*get_value_by_name) (REG_KEY *, const char *name); + + /* Or these */ + REG_KEY *(*open_key) (REG_HANDLE *, const char *name); + BOOL (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); + BOOL (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); + + /* Key management */ + BOOL (*add_key)(REG_KEY *, const char *name); + BOOL (*del_key)(REG_KEY *); + + /* Value management */ + REG_VAL *(*add_value)(REG_KEY *, const char *name, int type, void *data, int len); + BOOL (*del_value)(REG_VAL *); + + /* If update is not available, value will first be deleted and then added + * again */ + BOOL (*update_value)(REG_VAL *, int type, void *data, int len); + + void (*free_key_backend_data) (REG_KEY *); + void (*free_val_backend_data) (REG_VAL *); +}; + +typedef struct reg_sub_tree_s { + char *path; + REG_HANDLE *handle; + struct reg_sub_tree_s *prev, *next; +} REG_SUBTREE; + +struct reg_handle_s { + REG_OPS *functions; + REG_SUBTREE *subtrees; + char *location; + void *backend_data; +}; + +struct reg_init_function_entry { + /* Function to create a member of the pdb_methods list */ + REG_OPS *functions; + struct reg_init_function_entry *prev, *next; +}; + +/* Used internally */ +#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} + +#endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 new file mode 100644 index 0000000000..277fd30dd1 --- /dev/null +++ b/source4/lib/registry/config.m4 @@ -0,0 +1,16 @@ +# Registry backends + +if test t$BLDSHARED = ttrue; then + LIBWINREG_SHARED=bin/libwinregistry.$SHLIBEXT +fi +LIBWINREG=libwinregistry + +PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC) + CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building reg_gconf])]) + +SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) +SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) +SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) +SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) +SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[]) +AC_OUTPUT(lib/registry/winregistry.pc) diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c new file mode 100644 index 0000000000..baed39b4eb --- /dev/null +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -0,0 +1,154 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +static DIR *reg_dir_dir(REG_HANDLE *h, const char *base, const char *name) +{ + char *path = NULL; + DIR *d; + asprintf(&path, "%s/%s/%s", h->location, base, name); + path = reg_path_win2unix(path); + + d = opendir(path); + if(!d) { + printf("Unable to open '%s'\n", path); + return NULL; + } + SAFE_FREE(path); + return d; +} + +static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) +{ + char *path; + int ret; + asprintf(&path, "%s/%s/%s", parent->handle->location, reg_key_get_path(parent), name); + path = reg_path_win2unix(path); + ret = mkdir(path, 0700); + free(path); + return (ret == 0); +} + +static BOOL reg_dir_del_key(REG_KEY *k) +{ + char *path; + int ret; + asprintf(&path, "%s/%s", k->handle->location, reg_key_get_path(k)); + path = reg_path_win2unix(path); + ret = rmdir(path); + free(path); + return (ret == 0); +} + +static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) +{ + DIR *d; + char *fullpath; + if(!name) { + DEBUG(0, ("NULL pointer passed as directory name!")); + return NULL; + } + fullpath = reg_path_win2unix(strdup(name)); + d = reg_dir_dir(h, "", fullpath); + free(fullpath); + + if(d) return reg_key_new_abs(name, h, d); + return NULL; +} + +static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) +{ + DIR *d = (DIR *)k->backend_data; + struct dirent *e; + int max = 200; + REG_KEY **ar; + if(!d) return False; + rewinddir(d); + (*count) = 0; + ar = malloc(sizeof(REG_KEY *) * max); + + while((e = readdir(d))) { + if(e->d_type == DT_DIR && + strcmp(e->d_name, ".") && + strcmp(e->d_name, "..")) { + char *fullpath = reg_path_win2unix(strdup(k->path)); + ar[(*count)] = reg_key_new_rel(e->d_name, k, reg_dir_dir(k->handle, fullpath, e->d_name)); + free(fullpath); + if(ar[(*count)])(*count)++; + + if((*count) == max) { + max+=200; + ar = realloc(ar, sizeof(REG_KEY *) * max); + } + } + } + + *r = ar; + return True; +} + +static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) { + if(!loc) return False; + return True; +} + +static void dir_free(REG_KEY *k) +{ + closedir((DIR *)k->backend_data); +} + +static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) +{ + REG_VAL *ret = reg_val_new(p, NULL); + char *fullpath; + FILE *fd; + ret->name = name?strdup(name):NULL; + fullpath = reg_path_win2unix(strdup(reg_val_get_path(ret))); + + fd = fopen(fullpath, "w+"); + + /* FIXME */ + return NULL; +} + +static BOOL reg_dir_del_value(REG_VAL *v) +{ + char *fullpath = reg_path_win2unix(strdup(reg_val_get_path(v))); + return False; +} + +static REG_OPS reg_backend_dir = { + .name = "dir", + .open_registry = reg_dir_open, + .open_key = reg_dir_open_key, + .fetch_subkeys = reg_dir_fetch_subkeys, + .add_key = reg_dir_add_key, + .del_key = reg_dir_del_key, + .add_value = reg_dir_add_value, + .del_value = reg_dir_del_value, + .free_key_backend_data = dir_free +}; + +NTSTATUS reg_dir_init(void) +{ + return register_backend("registry", ®_backend_dir); +} diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c new file mode 100644 index 0000000000..14da2f54e9 --- /dev/null +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -0,0 +1,189 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" +#include + +static BOOL reg_open_gconf(REG_HANDLE *h, const char *location, BOOL try_complete_load) +{ + h->backend_data = (void *)gconf_client_get_default(); + return True; +} + +static BOOL reg_close_gconf(REG_HANDLE *h) +{ + return True; +} + +static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name) +{ + char *fullpath = reg_path_win2unix(strdup(name)); + + /* Check if key exists */ + if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { + free(fullpath); + return NULL; + } + free(fullpath); + + return reg_key_new_abs(name, h, NULL); +} + +static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) +{ + GSList *entries; + GSList *cur; + REG_VAL **ar = malloc(sizeof(REG_VAL *)); + char *fullpath = strdup(reg_key_get_path(p)); + fullpath = reg_path_win2unix(fullpath); + cur = entries = gconf_client_all_entries((GConfClient*)p->handle->backend_data, fullpath, NULL); + free(fullpath); + + (*count) = 0; + while(cur) { + GConfEntry *entry = cur->data; + GConfValue *value = gconf_entry_get_value(entry); + REG_VAL *newval = reg_val_new(p, NULL); + newval->name = strdup(strrchr(gconf_entry_get_key(entry), '/')+1); + if(value) { + switch(value->type) { + case GCONF_VALUE_INVALID: + newval->data_type = REG_NONE; + break; + + case GCONF_VALUE_STRING: + newval->data_type = REG_SZ; + newval->data_blk = strdup(gconf_value_get_string(value)); + newval->data_len = strlen(newval->data_blk); + break; + + case GCONF_VALUE_INT: + newval->data_type = REG_DWORD; + newval->data_blk = malloc(sizeof(long)); + *((long *)newval->data_blk) = gconf_value_get_int(value); + newval->data_len = sizeof(long); + break; + + case GCONF_VALUE_FLOAT: + newval->data_blk = malloc(sizeof(double)); + newval->data_type = REG_BINARY; + *((double *)newval->data_blk) = gconf_value_get_float(value); + newval->data_len = sizeof(double); + break; + + case GCONF_VALUE_BOOL: + newval->data_blk = malloc(sizeof(BOOL)); + newval->data_type = REG_BINARY; + *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); + newval->data_len = sizeof(BOOL); + break; + + default: + newval->data_type = REG_NONE; + DEBUG(0, ("Not implemented..\n")); + break; + } + } else newval->data_type = REG_NONE; + + ar[(*count)] = newval; + ar = realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); + (*count)++; + g_free(cur->data); + cur = cur->next; + } + + g_slist_free(entries); + *vals = ar; + return True; +} + +static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) +{ + GSList *dirs; + GSList *cur; + REG_KEY **ar = malloc(sizeof(REG_KEY *)); + char *fullpath = strdup(reg_key_get_path(p)); + fullpath = reg_path_win2unix(fullpath); + cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); + free(fullpath); + + (*count) = 0; + while(cur) { + ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle, NULL); + ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+2)); + (*count)++; + g_free(cur->data); + cur = cur->next; + } + + g_slist_free(dirs); + *subs = ar; + return True; +} + +static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len) +{ + GError *error = NULL; + char *keypath = reg_path_win2unix(strdup(reg_key_get_path(val->parent))); + char *valpath; + if(val->name)asprintf(&valpath, "%s/%s", keypath, val->name); + else valpath = strdup(keypath); + free(keypath); + + switch(type) { + case REG_SZ: + case REG_EXPAND_SZ: + gconf_client_set_string((GConfClient *)val->handle->backend_data, valpath, data, &error); + free(valpath); + return (error == NULL); + + case REG_DWORD: + gconf_client_set_int((GConfClient *)val->handle->backend_data, valpath, + *((int *)data), &error); + free(valpath); + return (error == NULL); + default: + DEBUG(0, ("Unsupported type: %d\n", type)); + free(valpath); + return False; + } + return False; +} + +static REG_OPS reg_backend_gconf = { + .name = "gconf", + .open_registry = reg_open_gconf, + .close_registry = reg_close_gconf, + .open_key = gconf_open_key, + .fetch_subkeys = gconf_fetch_subkeys, + .fetch_values = gconf_fetch_values, + .update_value = gconf_update_value, + + /* Note: + * since GConf uses schemas for what keys and values are allowed, there + * is no way of 'emulating' add_key and del_key here. + */ +}; + +NTSTATUS reg_gconf_init(void) +{ + return register_backend("registry", ®_backend_gconf); +} diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c new file mode 100644 index 0000000000..75d5a95187 --- /dev/null +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +/* + * Saves the dn as private_data for every key/val + */ + +static BOOL ldb_open_registry(REG_HANDLE *handle, const char *location, BOOL try_full_load) +{ + struct ldb_context *c; + c = ldb_connect(location, 0, NULL); + + if(!c) return False; + + handle->backend_data = c; + + return True; +} + +static BOOL ldb_close_registry(REG_HANDLE *h) +{ + ldb_close(h); + return True; +} + +static REG_KEY *ldb_open_key(REG_HANDLE *h, const char *name) +{ + /* FIXME */ +} + +static REG_OPS reg_backend_ldb = { + .name = "ldb", + .open_registry = ldb_open_registry, + .close_registry = ldb_close_registry, + .open_key = ldb_open_key, +}; + +NTSTATUS reg_ldb_init(void) +{ + return register_backend("registry", ®_backend_ldb); +} diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c new file mode 100644 index 0000000000..ef2565bda8 --- /dev/null +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -0,0 +1,1745 @@ +/* + Samba Unix/Linux SMB client utility libeditreg.c + Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com + Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/************************************************************************* + + A utility to edit a Windows NT/2K etc registry file. + + Many of the ideas in here come from other people and software. + I first looked in Wine in misc/registry.c and was also influenced by + http://www.wednesday.demon.co.uk/dosreg.html + + Which seems to contain comments from someone else. I reproduce them here + incase the site above disappears. It actually comes from + http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. + + The goal here is to read the registry into memory, manipulate it, and then + write it out if it was changed by any actions of the user. + +The windows NT registry has 2 different blocks, where one can occur many +times... + +the "regf"-Block +================ + +"regf" is obviously the abbreviation for "Registry file". "regf" is the +signature of the header-block which is always 4kb in size, although only +the first 64 bytes seem to be used and a checksum is calculated over +the first 0x200 bytes only! + +Offset Size Contents +0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 +0x00000004 D-Word ???? //see struct REG_HANDLE +0x00000008 D-Word ???? Always the same value as at 0x00000004 +0x0000000C Q-Word last modify date in WinNT date-format +0x00000014 D-Word 1 +0x00000018 D-Word 3 +0x0000001C D-Word 0 +0x00000020 D-Word 1 +0x00000024 D-Word Offset of 1st key record +0x00000028 D-Word Size of the data-blocks (Filesize-4kb) +0x0000002C D-Word 1 +0x000001FC D-Word Sum of all D-Words from 0x00000000 to +0x000001FB //XOR of all words. Nigel + +I have analyzed more registry files (from multiple machines running +NT 4.0 german version) and could not find an explanation for the values +marked with ???? the rest of the first 4kb page is not important... + +the "hbin"-Block +================ +I don't know what "hbin" stands for, but this block is always a multiple +of 4kb in size. + +Inside these hbin-blocks the different records are placed. The memory- +management looks like a C-compiler heap management to me... + +hbin-Header +=========== +Offset Size Contents +0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 +0x0004 D-Word Offset from the 1st hbin-Block +0x0008 D-Word Offset to the next hbin-Block +0x001C D-Word Block-size + +The values in 0x0008 and 0x001C should be the same, so I don't know +if they are correct or swapped... + +From offset 0x0020 inside a hbin-block data is stored with the following +format: + +Offset Size Contents +0x0000 D-Word Data-block size //this size must be a +multiple of 8. Nigel +0x0004 ???? Data + +If the size field is negative (bit 31 set), the corresponding block +is free and has a size of -blocksize! + +That does not seem to be true. All block lengths seem to be negative! +(Richard Sharpe) + +The data is stored as one record per block. Block size is a multiple +of 4 and the last block reaches the next hbin-block, leaving no room. + +(That also seems incorrect, in that the block size if a multiple of 8. +That is, the block, including the 4 byte header, is always a multiple of +8 bytes. Richard Sharpe.) + +Records in the hbin-blocks +========================== + +nk-Record + + The nk-record can be treated as a combination of tree-record and + key-record of the win 95 registry. + +lf-Record + + The lf-record is the counterpart to the RGKN-record (the + hash-function) + +vk-Record + + The vk-record consists information to a single value (value key). + +sk-Record + + sk (? Security Key ?) is the ACL of the registry. + +Value-Lists + + The value-lists contain information about which values are inside a + sub-key and don't have a header. + +Datas + + The datas of the registry are (like the value-list) stored without a + header. + +All offset-values are relative to the first hbin-block and point to the +block-size field of the record-entry. to get the file offset, you have to add +the header size (4kb) and the size field (4 bytes)... + +the nk-Record +============= +Offset Size Contents +0x0000 Word ID: ASCII-"nk" = 0x6B6E +0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel +0x0004 Q-Word write-date/time in windows nt notation +0x0010 D-Word Offset of Owner/Parent key +0x0014 D-Word number of sub-Keys +0x001C D-Word Offset of the sub-key lf-Records +0x0024 D-Word number of values +0x0028 D-Word Offset of the Value-List +0x002C D-Word Offset of the sk-Record + +0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel +0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel +0x0048 Word name-length +0x004A Word class-name length +0x004C ???? key-name + +the Value-List +============== +Offset Size Contents +0x0000 D-Word Offset 1st Value +0x0004 D-Word Offset 2nd Value +0x???? D-Word Offset nth Value + +To determine the number of values, you have to look at the owner-nk-record! + +Der vk-Record +============= +Offset Size Contents +0x0000 Word ID: ASCII-"vk" = 0x6B76 +0x0002 Word name length +0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel +0x0008 D-Word Offset of Data +0x000C D-Word Type of value +0x0010 Word Flag +0x0012 Word Unused (data-trash) +0x0014 ???? Name + +If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) + +If the data-size is lower 5, the data-offset value is used to store the data itself! + +The data-types +============== +Wert Beteutung +0x0001 RegSZ: character string (in UNICODE!) +0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) +0x0003 RegBin: raw-binary value +0x0004 RegDWord: Dword +0x0007 RegMultiSZ: multiple strings, seperated with 0 + (UNICODE!) + +The "lf"-record +=============== +Offset Size Contents +0x0000 Word ID: ASCII-"lf" = 0x666C +0x0002 Word number of keys +0x0004 ???? Hash-Records + +Hash-Record +=========== +Offset Size Contents +0x0000 D-Word Offset of corresponding "nk"-Record +0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! + +Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the +key-name you have to change the hash-value too! + +//These hashrecords must be sorted low to high within the lf record. Nigel. + +The "sk"-block +============== +(due to the complexity of the SAM-info, not clear jet) +(This is just a self-relative security descriptor in the data. R Sharpe.) + + +Offset Size Contents +0x0000 Word ID: ASCII-"sk" = 0x6B73 +0x0002 Word Unused +0x0004 D-Word Offset of previous "sk"-Record +0x0008 D-Word Offset of next "sk"-Record +0x000C D-Word usage-counter +0x0010 D-Word Size of "sk"-record in bytes +???? //standard self +relative security desciptor. Nigel +???? ???? Security and auditing settings... +???? + +The usage counter counts the number of references to this +"sk"-record. You can use one "sk"-record for the entire registry! + +Windows nt date/time format +=========================== +The time-format is a 64-bit integer which is incremented every +0,0000001 seconds by 1 (I don't know how accurate it realy is!) +It starts with 0 at the 1st of january 1601 0:00! All values are +stored in GMT time! The time-zone is important to get the real +time! + +Common values for win95 and win-nt +================================== +Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). +If a value has no name (length=0, flag(bit 0)=0), it is treated as the +"Default" entry... +If a value has no data (length=0), it is displayed as empty. + +simplyfied win-3.?? registry: +============================= + ++-----------+ +| next rec. |---+ +----->+------------+ +| first sub | | | | Usage cnt. | +| name | | +-->+------------+ | | length | +| value | | | | next rec. | | | text |------->+-------+ ++-----------+ | | | name rec. |--+ +------------+ | xxxxx | + +------------+ | | value rec. |-------->+------------+ +-------+ + v | +------------+ | Usage cnt. | ++-----------+ | | length | +| next rec. | | | text |------->+-------+ +| first sub |------+ +------------+ | xxxxx | +| name | +-------+ +| value | ++-----------+ + +Greatly simplyfied structure of the nt-registry: +================================================ + ++---------------------------------------------------------------+ +| | +v | ++---------+ +---------->+-----------+ +----->+---------+ | +| "nk" | | | lf-rec. | | | nk-rec. | | +| ID | | | # of keys | | | parent |---+ +| Date | | | 1st key |--+ | .... | +| parent | | +-----------+ +---------+ +| suk-keys|-----+ +| values |--------------------->+----------+ +| SK-rec. |---------------+ | 1. value |--> +----------+ +| class |--+ | +----------+ | vk-rec. | ++---------+ | | | .... | + v | | data |--> +-------+ + +------------+ | +----------+ | xxxxx | + | Class name | | +-------+ + +------------+ | + v + +---------+ +---------+ + +----->| next sk |--->| Next sk |--+ + | +---| prev sk |<---| prev sk | | + | | | .... | | ... | | + | | +---------+ +---------+ | + | | ^ | + | | | | + | +--------------------+ | + +----------------------------------+ + +--------------------------------------------------------------------------- + +Hope this helps.... (Although it was "fun" for me to uncover this things, + it took me several sleepless nights ;) + + B.D. + +*************************************************************************/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +#define REG_KEY_LIST_SIZE 10 +/*FIXME*/ + +/* + * Structures for dealing with the on-disk format of the registry + */ + +const char *def_owner_sid_str = NULL; + +/* + * These definitions are for the in-memory registry structure. + * It is a tree structure that mimics what you see with tools like regedit + */ + + +/* + * Definition of a Key. It has a name, classname, date/time last modified, + * sub-keys, values, and a security descriptor + */ + +#define REG_ROOT_KEY 1 +#define REG_SUB_KEY 2 +#define REG_SYM_LINK 3 + +/* + * All of the structures below actually have a four-byte length before them + * which always seems to be negative. The following macro retrieves that + * size as an integer + */ + +#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) + +typedef unsigned int DWORD; +typedef unsigned short WORD; + +typedef struct sk_struct SK_HDR; +/* + * This structure keeps track of the output format of the registry + */ +#define REG_OUTBLK_HDR 1 +#define REG_OUTBLK_HBIN 2 + +typedef struct regf_block { + DWORD REGF_ID; /* regf */ + DWORD uk1; + DWORD uk2; + DWORD tim1, tim2; + DWORD uk3; /* 1 */ + DWORD uk4; /* 3 */ + DWORD uk5; /* 0 */ + DWORD uk6; /* 1 */ + DWORD first_key; /* offset */ + unsigned int dblk_size; + DWORD uk7[116]; /* 1 */ + DWORD chksum; +} REGF_HDR; + +typedef struct hbin_sub_struct { + DWORD dblocksize; + char data[1]; +} HBIN_SUB_HDR; + +typedef struct hbin_struct { + DWORD HBIN_ID; /* hbin */ + DWORD off_from_first; + DWORD off_to_next; + DWORD uk1; + DWORD uk2; + DWORD uk3; + DWORD uk4; + DWORD blk_size; + HBIN_SUB_HDR hbin_sub_hdr; +} HBIN_HDR; + +typedef struct nk_struct { + WORD NK_ID; + WORD type; + DWORD t1, t2; + DWORD uk1; + DWORD own_off; + DWORD subk_num; + DWORD uk2; + DWORD lf_off; + DWORD uk3; + DWORD val_cnt; + DWORD val_off; + DWORD sk_off; + DWORD clsnam_off; + DWORD unk4[4]; + DWORD unk5; + WORD nam_len; + WORD clsnam_len; + char key_nam[1]; /* Actual length determined by nam_len */ +} NK_HDR; + +struct sk_struct { + WORD SK_ID; + WORD uk1; + DWORD prev_off; + DWORD next_off; + DWORD ref_cnt; + DWORD rec_size; + char sec_desc[1]; +}; + +typedef struct key_sec_desc_s { + struct key_sec_desc_s *prev, *next; + int ref_cnt; + int state; + int offset; + SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ + SEC_DESC *sec_desc; +} KEY_SEC_DESC; + +/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ +typedef struct sk_map_s { + int sk_off; + KEY_SEC_DESC *key_sec_desc; +} SK_MAP; + +typedef struct vk_struct { + WORD VK_ID; + WORD nam_len; + DWORD dat_len; /* If top-bit set, offset contains the data */ + DWORD dat_off; + DWORD dat_type; + WORD flag; /* =1, has name, else no name (=Default). */ + WORD unk1; + char dat_name[1]; /* Name starts here ... */ +} VK_HDR; + +typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */ + +typedef struct hash_struct { + DWORD nk_off; + char hash[4]; +} HASH_REC; + + +typedef struct lf_struct { + WORD LF_ID; + WORD key_count; + struct hash_struct hr[1]; /* Array of hash records, depending on key_count */} LF_HDR; + + + +/* + * This structure keeps track of the output format of the registry + */ +#define REG_OUTBLK_HDR 1 +#define REG_OUTBLK_HBIN 2 + +typedef struct hbin_blk_s { + int type, size; + struct hbin_blk_s *next; + char *data; /* The data block */ + unsigned int file_offset; /* Offset in file */ + unsigned int free_space; /* Amount of free space in block */ + unsigned int fsp_off; /* Start of free space in block */ + int complete, stored; +} HBIN_BLK; + +typedef struct regf_struct_s { + int reg_type; + int fd; + struct stat sbuf; + char *base; + int modified; + NTTIME last_mod_time; + NK_HDR *first_key; + int sk_count, sk_map_size; + SK_MAP *sk_map; + const char *owner_sid_str; + SEC_DESC *def_sec_desc; + /* + * These next pointers point to the blocks used to contain the + * keys when we are preparing to write them to a file + */ + HBIN_BLK *blk_head, *blk_tail, *free_space; + TALLOC_CTX *mem_ctx; +} REGF; + +DWORD str_to_dword(const char *a) { + int i; + unsigned long ret = 0; + for(i = strlen(a)-1; i >= 0; i--) { + ret = ret * 0x100 + a[i]; + } + return ret; +} + +#if 0 + +/* + * Create an ACE + */ +static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32 perms, const char *sid) +{ + DOM_SID s; + SEC_ACCESS access; + access.mask = perms; + if(!string_to_sid(&s, sid))return False; + init_sec_ace(ace, &s, type, access, flags); + return True; +} + +/* + * Create a default ACL + */ +static SEC_ACL *nt_create_default_acl(REG_HANDLE *regf) +{ + SEC_ACE aces[8]; + + if(!nt_create_ace(&aces[0], 0x00, 0x0, 0xF003F, regf->owner_sid_str)) return NULL; + if(!nt_create_ace(&aces[1], 0x00, 0x0, 0xF003F, "S-1-5-18")) return NULL; + if(!nt_create_ace(&aces[2], 0x00, 0x0, 0xF003F, "S-1-5-32-544")) return NULL; + if(!nt_create_ace(&aces[3], 0x00, 0x0, 0x20019, "S-1-5-12")) return NULL; + if(!nt_create_ace(&aces[4], 0x00, 0x0B, GENERIC_RIGHT_ALL_ACCESS, regf->owner_sid_str)) return NULL; + if(!nt_create_ace(&aces[5], 0x00, 0x0B, 0x10000000, "S-1-5-18")) return NULL; + if(!nt_create_ace(&aces[6], 0x00, 0x0B, 0x10000000, "S-1-5-32-544")) return NULL; + if(!nt_create_ace(&aces[7], 0x00, 0x0B, 0x80000000, "S-1-5-12")) return NULL; + + return make_sec_acl(regf->mem_ctx, 2, 8, aces); +} + +/* + * Create a default security descriptor. We pull in things from env + * if need be + */ +static SEC_DESC *nt_create_def_sec_desc(REG_HANDLE *regf) +{ + SEC_DESC *tmp; + + tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC)); + + tmp->revision = 1; + tmp->type = SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT; + if (!string_to_sid(tmp->owner_sid, "S-1-5-32-544")) goto error; + if (!string_to_sid(tmp->grp_sid, "S-1-5-18")) goto error; + tmp->sacl = NULL; + tmp->dacl = nt_create_default_acl(regf); + + return tmp; + + error: + if (tmp) nt_delete_sec_desc(tmp); + return NULL; +} + +/* + * We will implement inheritence that is based on what the parent's SEC_DESC + * says, but the Owner and Group SIDs can be overwridden from the command line + * and additional ACEs can be applied from the command line etc. + */ +static KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) +{ + + if (!key) return NULL; + return key->security; +} + +/* + * Create an initial security descriptor and init other structures, if needed + * We assume that the initial security stuff is empty ... + */ +static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) +{ + REGF *regf = h->backend_data; + KEY_SEC_DESC *tsec = NULL; + + tsec = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + + tsec->ref_cnt = 1; + tsec->state = SEC_DESC_NBK; + tsec->offset = 0; + + tsec->sec_desc = regf->def_sec_desc; + + return tsec; +} +#endif + +/* + * Get the starting record for NT Registry file + */ + +/* + * Where we keep all the regf stuff for one registry. + * This is the structure that we use to tie the in memory tree etc + * together. By keeping separate structs, we can operate on different + * registries at the same time. + * Currently, the SK_MAP is an array of mapping structure. + * Since we only need this on input and output, we fill in the structure + * as we go on input. On output, we know how many SK items we have, so + * we can allocate the structure as we need to. + * If you add stuff here that is dynamically allocated, add the + * appropriate free statements below. + */ + +#define REG_HANDLE_REGTYPE_NONE 0 +#define REG_HANDLE_REGTYPE_NT 1 +#define REG_HANDLE_REGTYPE_W9X 2 + +#define TTTONTTIME(r, t1, t2) (r)->last_mod_time.low = (t1); \ + (r)->last_mod_time.high = (t2); + +#define REGF_HDR_BLKSIZ 0x1000 + +#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) +#define LOCN(base, f) ((base) + OFF(f)) + +/* Get the header of the registry. Return a pointer to the structure + * If the mmap'd area has not been allocated, then mmap the input file + */ +static REGF_HDR *nt_get_regf_hdr(REG_HANDLE *h) +{ + REGF *regf = h->backend_data; + SMB_REG_ASSERT(regf); + + if (!regf->base) { /* Try to mmap etc the file */ + + if ((regf->fd = open(h->location, O_RDONLY, 0000)) <0) { + return NULL; /* What about errors? */ + } + + if (fstat(regf->fd, ®f->sbuf) < 0) { + return NULL; + } + + regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0); + + if ((int)regf->base == 1) { + DEBUG(0,("Could not mmap file: %s, %s\n", h->location, + strerror(errno))); + return NULL; + } + } + + /* + * At this point, regf->base != NULL, and we should be able to read the + * header + */ + + SMB_REG_ASSERT(regf->base != NULL); + + return (REGF_HDR *)regf->base; +} + +/* + * Validate a regf header + * For now, do nothing, but we should check the checksum + */ +static int valid_regf_hdr(REGF_HDR *regf_hdr) +{ + if (!regf_hdr) return 0; + + return 1; +} + +#if 0 + +/* + * Process an SK header ... + * Every time we see a new one, add it to the map. Otherwise, just look it up. + * We will do a simple linear search for the moment, since many KEYs have the + * same security descriptor. + * We allocate the map in increments of 10 entries. + */ + +/* + * Create a new entry in the map, and increase the size of the map if needed + */ +static SK_MAP *alloc_sk_map_entry(REG_HANDLE *h, KEY_SEC_DESC *tmp, int sk_off) +{ + REGF *regf = h->backend_data; + if (!regf->sk_map) { /* Allocate a block of 10 */ + regf->sk_map = (SK_MAP *)malloc(sizeof(SK_MAP) * 10); + regf->sk_map_size = 10; + regf->sk_count = 1; + (regf->sk_map)[0].sk_off = sk_off; + (regf->sk_map)[0].key_sec_desc = tmp; + } + else { /* Simply allocate a new slot, unless we have to expand the list */ + int ndx = regf->sk_count; + if (regf->sk_count >= regf->sk_map_size) { + regf->sk_map = (SK_MAP *)realloc(regf->sk_map, + (regf->sk_map_size + 10)*sizeof(SK_MAP)); + if (!regf->sk_map) { + free(tmp); + return NULL; + } + /* + * ndx already points at the first entry of the new block + */ + regf->sk_map_size += 10; + } + (regf->sk_map)[ndx].sk_off = sk_off; + (regf->sk_map)[ndx].key_sec_desc = tmp; + regf->sk_count++; + } + return regf->sk_map; +} + +/* + * Search for a KEY_SEC_DESC in the sk_map, but don't create one if not + * found + */ +KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) +{ + int i; + + if (!sk_map) return NULL; + + for (i = 0; i < count; i++) { + + if (sk_map[i].sk_off == sk_off) + return sk_map[i].key_sec_desc; + + } + + return NULL; + +} + +/* + * Allocate a KEY_SEC_DESC if we can't find one in the map + */ +static KEY_SEC_DESC *lookup_create_sec_key(REG_HANDLE *h, SK_MAP *sk_map, int sk_off) +{ + REGF *regf = h->backend_data; + KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); + + if (tmp) { + return tmp; + } + else { /* Allocate a new one */ + tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ + tmp->state = SEC_DESC_RES; + if (!alloc_sk_map_entry(h, tmp, sk_off)) { + return NULL; + } + return tmp; + } +} + +static SEC_DESC *process_sec_desc(REG_HANDLE *regf, SEC_DESC *sec_desc) +{ + SEC_DESC *tmp = NULL; + + tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC)); + + tmp->revision = SVAL(&sec_desc->revision,0); + tmp->type = SVAL(&sec_desc->type,0); + DEBUG(2, ("SEC_DESC Rev: %0X, Type: %0X\n", tmp->revision, tmp->type)); + DEBUGADD(2, ("SEC_DESC Owner Off: %0X\n", IVAL(&sec_desc->off_owner_sid,0))); + DEBUGADD(2, ("SEC_DESC Group Off: %0X\n", IVAL(&sec_desc->off_grp_sid,0))); + DEBUGADD(2, ("SEC_DESC DACL Off: %0X\n", IVAL(&sec_desc->off_dacl,0))); + tmp->owner_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_owner_sid,0))); + if (!tmp->owner_sid) { + free(tmp); + return NULL; + } + tmp->grp_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_grp_sid,0))); + if (!tmp->grp_sid) { + free(tmp); + return NULL; + } + + /* Now pick up the SACL and DACL */ + + DEBUG(0, ("%d, %d\n", IVAL(&sec_desc->off_sacl,0), IVAL(&sec_desc->off_dacl,0))); + + if (sec_desc->off_sacl) + tmp->sacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_sacl,0))); + else + tmp->sacl = NULL; + + if (sec_desc->off_dacl) + tmp->dacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_dacl,0))); + else + tmp->dacl = NULL; + + return tmp; +} + +static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, int size) +{ + KEY_SEC_DESC *tmp = NULL; + int sk_next_off, sk_prev_off, sk_size; + SEC_DESC *sec_desc; + + if (!sk_hdr) return NULL; + + if (SVAL(&sk_hdr->SK_ID,0) != str_to_dword("sk")) { + DEBUG(0, ("Unrecognized SK Header ID: %08X, %s\n", (int)sk_hdr, + regf->regfile_name)); + return NULL; + } + + if (-size < (sk_size = IVAL(&sk_hdr->rec_size,0))) { + DEBUG(0, ("Incorrect SK record size: %d vs %d. %s\n", + -size, sk_size, regf->regfile_name)); + return NULL; + } + + /* + * Now, we need to look up the SK Record in the map, and return it + * Since the map contains the SK_OFF mapped to KEY_SEC_DESC, we can + * use that + */ + + if (regf->sk_map && + ((tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off)) != NULL) + && (tmp->state == SEC_DESC_OCU)) { + tmp->ref_cnt++; + return tmp; + } + + /* Here, we have an item in the map that has been reserved, or tmp==NULL. */ + + SMB_REG_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); + + /* + * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the + * new KEY_SEC_DESC to the mapping structure, since the offset supplied is + * the actual offset of structure. The same offset will be used by + * all future references to this structure + * We could put all this unpleasantness in a function. + */ + + if (!tmp) { + tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + memset(tmp, 0, sizeof(KEY_SEC_DESC)); + + /* + * Allocate an entry in the SK_MAP ... + * We don't need to free tmp, because that is done for us if the + * sm_map entry can't be expanded when we need more space in the map. + */ + + if (!alloc_sk_map_entry(regf, tmp, sk_off)) { + return NULL; + } + } + + tmp->ref_cnt++; + tmp->state = SEC_DESC_OCU; + + /* + * Now, process the actual sec desc and plug the values in + */ + + sec_desc = (SEC_DESC *)&sk_hdr->sec_desc[0]; + tmp->sec_desc = process_sec_desc(regf, sec_desc); + + /* + * Now forward and back links. Here we allocate an entry in the sk_map + * if it does not exist, and mark it reserved + */ + + sk_prev_off = IVAL(&sk_hdr->prev_off,0); + tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off); + SMB_REG_ASSERT(tmp->prev != NULL); + sk_next_off = IVAL(&sk_hdr->next_off,0); + tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off); + SMB_REG_ASSERT(tmp->next != NULL); + + return tmp; +} +#endif + +/* + * Process a VK header and return a value + */ +static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size) +{ + char val_name[1024]; + REGF *regf = parent->handle->backend_data; + int nam_len, dat_len, flag, dat_type, dat_off, vk_id; + const char *val_type; + REG_VAL *tmp = NULL; + + if (!vk_hdr) return NULL; + + if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { + DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", + vk_id, (int)vk_hdr, parent->handle->location)); + return NULL; + } + + nam_len = SVAL(&vk_hdr->nam_len,0); + val_name[nam_len] = '\0'; + flag = SVAL(&vk_hdr->flag,0); + dat_type = IVAL(&vk_hdr->dat_type,0); + dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ + dat_off = IVAL(&vk_hdr->dat_off,0); + + tmp = reg_val_new(parent, NULL); + tmp->has_name = flag; + tmp->data_type = dat_type; + + if (flag & 0x01) { + strncpy(val_name, vk_hdr->dat_name, nam_len); + tmp->name = strdup(val_name); + } + else + strncpy(val_name, "", 10); + + /* + * Allocate space and copy the data as a BLOB + */ + + if (dat_len&0x7FFFFFFF) { + + char *dtmp = (char *)malloc(dat_len&0x7FFFFFFF); + + tmp->data_blk = dtmp; + + if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ + char *dat_ptr = LOCN(regf->base, dat_off); + memcpy(dtmp, dat_ptr, dat_len); + } + else { /* The data is in the offset or type */ + /* + * FIXME. + * Some registry files seem to have weird fields. If top bit is set, + * but len is 0, the type seems to be the value ... + * Not sure how to handle this last type for the moment ... + */ + dat_len = dat_len & 0x7FFFFFFF; + memcpy(dtmp, &dat_off, dat_len); + } + + tmp->data_len = dat_len; + } + + return tmp; +} + +static BOOL vl_verify(VL_TYPE vl, int count, int size) +{ + if(!vl) return False; + if (-size < (count+1)*sizeof(int)){ + DEBUG(0, ("Error in VL header format. Size less than space required. %d\n", -size)); + return False; + } + return True; +} + +static BOOL lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +{ + int lf_id; + if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { + DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n", + lf_id, (int)lf_hdr, h->location)); + return False; + } + return True; +} + +static int lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +{ + int count; + + if(!lf_verify(h, lf_hdr, size)) return 0; + + SMB_REG_ASSERT(size < 0); + + count = SVAL(&lf_hdr->key_count,0); + DEBUG(2, ("Key Count: %u\n", count)); + if (count <= 0) return 0; + + return count; +} + + +static REG_KEY *nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent); + + + +/* + * Process an LF Header and return a list of sub-keys + */ +static REG_KEY *lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n) +{ + REGF *regf = parent->handle->backend_data; + int count, nk_off; + NK_HDR *nk_hdr; + + if (!lf_hdr) return NULL; + + if(!lf_verify(parent->handle, lf_hdr, size)) return NULL; + + SMB_REG_ASSERT(size < 0); + + count = SVAL(&lf_hdr->key_count,0); + DEBUG(2, ("Key Count: %u\n", count)); + if (count <= 0 || n > count) return NULL; + + nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); + DEBUG(2, ("NK Offset: %0X\n", nk_off)); + nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); + return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent); +} + +static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent) +{ + REGF *regf = h->backend_data; + REG_KEY *tmp = NULL, *own; + int name_len, clsname_len, sk_off, own_off; + unsigned int nk_id; + SK_HDR *sk_hdr; + int type; + char key_name[1024], cls_name[1024]; + + if (!nk_hdr) return NULL; + + if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { + DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", + nk_id, (int)nk_hdr, parent->handle->location)); + return NULL; + } + + SMB_REG_ASSERT(size < 0); + + name_len = SVAL(&nk_hdr->nam_len,0); + clsname_len = SVAL(&nk_hdr->clsnam_len,0); + + /* + * The value of -size should be ge + * (sizeof(NK_HDR) - 1 + name_len) + * The -1 accounts for the fact that we included the first byte of + * the name in the structure. clsname_len is the length of the thing + * pointed to by clsnam_off + */ + + if (-size < (sizeof(NK_HDR) - 1 + name_len)) { + DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); + DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", + sizeof(NK_HDR), name_len, clsname_len)); + /*return NULL;*/ + } + + DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", name_len, clsname_len)); + + /* Fish out the key name and process the LF list */ + + SMB_REG_ASSERT(name_len < sizeof(key_name)); + + strncpy(key_name, nk_hdr->key_nam, name_len); + key_name[name_len] = '\0'; + + type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); + if(type == REG_ROOT_KEY && parent) { + DEBUG(0,("Root key encountered below root level!\n")); + return NULL; + } + + if(type == REG_ROOT_KEY) tmp = reg_key_new_abs(key_name, h, nk_hdr); + else tmp = reg_key_new_rel(key_name, parent, nk_hdr); + + DEBUG(2, ("Key name: %s\n", key_name)); + + /* + * Fish out the class name, it is in UNICODE, while the key name is + * ASCII :-) + */ + + if (clsname_len) { /* Just print in Ascii for now */ + smb_ucs2_t *clsnamep; + int clsnam_off; + + clsnam_off = IVAL(&nk_hdr->clsnam_off,0); + clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); + DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); + + tmp->class_name = talloc_strdup_w(regf->mem_ctx, clsnamep); + + DEBUGADD(2,(" Class Name: %s\n", cls_name)); + + } + + /* + * Process the owner offset ... + */ + + own_off = IVAL(&nk_hdr->own_off,0); + own = (REG_KEY *)LOCN(regf->base, own_off); + DEBUG(2, ("Owner Offset: %0X\n", own_off)); + + DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", + (unsigned int)own, (unsigned int)nk_hdr)); + + /* + * We should verify that the owner field is correct ... + * for now, we don't worry ... + */ + + /* + * Also handle the SK header ... + */ + + sk_off = IVAL(&nk_hdr->sk_off,0); + sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); + DEBUG(2, ("SK Offset: %0X\n", sk_off)); + + if (sk_off != -1) { + +#if 0 + tmp->security = process_sk(regf, sk_hdr, sk_off, BLK_SIZE(sk_hdr)); +#endif + + } + + return tmp; +} + +/* + * Allocate a new hbin block, set up the header for the block etc + */ +static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) +{ + REGF *regf = h->backend_data; + HBIN_BLK *tmp; + HBIN_HDR *hdr; + + if (!regf || !size) return NULL; + + /* Round size up to multiple of REGF_HDR_BLKSIZ */ + + size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); + + tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); + memset(tmp, 0, sizeof(HBIN_BLK)); + + tmp->data = malloc(size); + + memset(tmp->data, 0, size); /* Make it pristine */ + + tmp->size = size; + /*FIXMEtmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size;*/ + + tmp->free_space = size - (sizeof(HBIN_HDR) - sizeof(HBIN_SUB_HDR)); + tmp->fsp_off = size - tmp->free_space; + + /* + * Now, build the header in the data block + */ + hdr = (HBIN_HDR *)tmp->data; + hdr->HBIN_ID = str_to_dword("hbin"); + hdr->off_from_first = tmp->file_offset - REGF_HDR_BLKSIZ; + hdr->off_to_next = tmp->size; + hdr->blk_size = tmp->size; + + /* + * Now link it in + */ + + regf->blk_tail->next = tmp; + regf->blk_tail = tmp; + if (!regf->free_space) regf->free_space = tmp; + + return tmp; +} + +/* + * Allocate a unit of space ... and return a pointer as function param + * and the block's offset as a side effect + */ +static void *nt_alloc_regf_space(REG_HANDLE *h, int size, unsigned int *off) +{ + REGF *regf = h->backend_data; + int tmp = 0; + void *ret = NULL; + HBIN_BLK *blk; + + if (!regf || !size || !off) return NULL; + + SMB_REG_ASSERT(regf->blk_head != NULL); + + /* + * round up size to include header and then to 8-byte boundary + */ + size = (size + 4 + 7) & ~7; + + /* + * Check if there is space, if none, grab a block + */ + if (!regf->free_space) { + if (!nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) + return NULL; + } + + /* + * Now, chain down the list of blocks looking for free space + */ + + for (blk = regf->free_space; blk != NULL; blk = blk->next) { + if (blk->free_space <= size) { + tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; + ret = blk->data + blk->fsp_off; + blk->free_space -= size; + blk->fsp_off += size; + + /* Insert the header */ + ((HBIN_SUB_HDR *)ret)->dblocksize = -size; + + /* + * Fix up the free space ptr + * If it is NULL, we fix it up next time + */ + + if (!blk->free_space) + regf->free_space = blk->next; + + *off = tmp; + return (((char *)ret)+4);/* The pointer needs to be to the data struct */ + } + } + + /* + * If we got here, we need to add another block, which might be + * larger than one block -- deal with that later + */ + if (nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) { + blk = regf->free_space; + tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; + ret = blk->data + blk->fsp_off; + blk->free_space -= size; + blk->fsp_off += size; + + /* Insert the header */ + ((HBIN_SUB_HDR *)ret)->dblocksize = -size; + + /* + * Fix up the free space ptr + * If it is NULL, we fix it up next time + */ + + if (!blk->free_space) + regf->free_space = blk->next; + + *off = tmp; + return (((char *)ret) + 4);/* The pointer needs to be to the data struct */ + } + + return NULL; +} + +/* + * Store a SID at the location provided + */ +static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, unsigned char *locn) +{ + int i; + unsigned char *p = locn; + + if (!regf || !sid || !locn) return 0; + + *p = sid->sid_rev_num; p++; + *p = sid->num_auths; p++; + + for (i=0; i < 6; i++) { + *p = sid->id_auth[i]; p++; + } + + for (i=0; i < sid->num_auths; i++) { + SIVAL(p, 0, sid->sub_auths[i]); p+=4; + } + + return p - locn; + +} + +static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, unsigned char *locn) +{ + int size = 0; + SEC_ACE *reg_ace = (SEC_ACE *)locn; + unsigned char *p; + + if (!regf || !ace || !locn) return 0; + + reg_ace->type = ace->type; + reg_ace->flags = ace->flags; + + /* Deal with the length when we have stored the SID */ + + p = (unsigned char *)®_ace->info.mask; + + SIVAL(p, 0, ace->info.mask); p += 4; + + size = nt_store_SID(regf, &ace->trustee, p); + + size += 8; /* Size of the fixed header */ + + p = (unsigned char *)®_ace->size; + + SSVAL(p, 0, size); + + return size; +} + +/* + * Store an ACL at the location provided + */ +static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, unsigned char *locn) { + int size = 0, i; + unsigned char *p = locn, *s; + + if (!regf || !acl || !locn) return 0; + + /* + * Now store the header and then the ACEs ... + */ + + SSVAL(p, 0, acl->revision); + + p += 2; s = p; /* Save this for the size field */ + + p += 2; + + SIVAL(p, 0, acl->num_aces); + + p += 4; + + for (i = 0; i < acl->num_aces; i++) { + size = nt_store_ace(regf, &acl->ace[i], p); + p += size; + } + + size = s - locn; + SSVAL(s, 0, size); + return size; +} + +/* + * Flatten and store the Sec Desc + * Windows lays out the DACL first, but since there is no SACL, it might be + * that first, then the owner, then the group SID. So, we do it that way + * too. + */ +static unsigned int nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) +{ + SEC_DESC *rsd = (SEC_DESC *)locn; + unsigned int size = 0, off = 0; + + if (!regf || !sd || !locn) return 0; + + /* + * Now, fill in the first two fields, then lay out the various fields + * as needed + */ + + rsd->revision = SEC_DESC_REVISION; + rsd->type = SEC_DESC_DACL_PRESENT | SEC_DESC_SELF_RELATIVE; + + off = 4 * sizeof(DWORD) + 4; + + if (sd->sacl){ + size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); + rsd->off_sacl = off; + } + else + rsd->off_sacl = 0; + + off += size; + + if (sd->dacl) { + rsd->off_dacl = off; + size = nt_store_acl(regf, sd->dacl, (char *)(locn + off)); + } + else { + rsd->off_dacl = 0; + } + + off += size; + + /* Now the owner and group SIDs */ + + if (sd->owner_sid) { + rsd->off_owner_sid = off; + size = nt_store_SID(regf, sd->owner_sid, (char *)(locn + off)); + } + else { + rsd->off_owner_sid = 0; + } + + off += size; + + if (sd->grp_sid) { + rsd->off_grp_sid = off; + size = nt_store_SID(regf, sd->grp_sid, (char *)(locn + off)); + } + else { + rsd->off_grp_sid = 0; + } + + off += size; + + return size; +} + +/* + * Store the security information + * + * If it has already been stored, just get its offset from record + * otherwise, store it and record its offset + */ +static unsigned int nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) +{ + int size = 0; + unsigned int sk_off; + SK_HDR *sk_hdr; + + if (sec->offset) return sec->offset; + + /* + * OK, we don't have this one in the file yet. We must compute the + * size taken by the security descriptor as a self-relative SD, which + * means making one pass over each structure and figuring it out + */ + +//FIXME size = sec_desc_size(sec->sec_desc); + + /* Allocate that much space */ + + sk_hdr = nt_alloc_regf_space(regf, size, &sk_off); + sec->sk_hdr = sk_hdr; + + if (!sk_hdr) return 0; + + /* Now, lay out the sec_desc in the space provided */ + + sk_hdr->SK_ID = str_to_dword("sk"); + + /* + * We can't deal with the next and prev offset in the SK_HDRs until the + * whole tree has been stored, then we can go and deal with them + */ + + sk_hdr->ref_cnt = sec->ref_cnt; + sk_hdr->rec_size = size; /* Is this correct */ + + /* Now, lay out the sec_desc */ + + if (!nt_store_sec_desc(regf, sec->sec_desc, (char *)&sk_hdr->sec_desc)) + return 0; + + return sk_off; + +} + +#if 0 + +/* + * Store a KEY in the file ... + * + * We store this depth first, and defer storing the lf struct until + * all the sub-keys have been stored. + * + * We store the NK hdr, any SK header, class name, and VK structure, then + * recurse down the LF structures ... + * + * We return the offset of the NK struct + * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... + */ +static int nt_store_reg_key(REG_HANDLE *regf, REG_KEY *key) +{ + NK_HDR *nk_hdr; + unsigned int nk_off, sk_off, size; + + if (!regf || !key) return 0; + + size = sizeof(NK_HDR) + strlen(key->name) - 1; + nk_hdr = nt_alloc_regf_space(regf, size, &nk_off); + if (!nk_hdr) goto error; + + key->offset = nk_off; /* We will need this later */ + + /* + * Now fill in each field etc ... + */ + + nk_hdr->NK_ID = str_to_dword("nk"); + if (key->type == REG_ROOT_KEY) + nk_hdr->type = 0x2C; + else + nk_hdr->type = 0x20; + + /* FIXME: Fill in the time of last update */ + + if (key->type != REG_ROOT_KEY) + nk_hdr->own_off = key->owner->offset; + + if (key->sub_keys) + nk_hdr->subk_num = key->sub_keys->key_count; + + /* + * Now, process the Sec Desc and then store its offset + */ + + sk_off = nt_store_security(regf, key->security); + nk_hdr->sk_off = sk_off; + + /* + * Then, store the val list and store its offset + */ + if (key->values) { + nk_hdr->val_cnt = key->values->val_count; + nk_hdr->val_off = nt_store_val_list(regf, key->values); + } + else { + nk_hdr->val_off = -1; + nk_hdr->val_cnt = 0; + } + + /* + * Finally, store the subkeys, and their offsets + */ + +error: + return 0; +} +#endif + +/* + * Store the registry header ... + * We actually create the registry header block and link it to the chain + * of output blocks. + */ +static REGF_HDR *nt_get_reg_header(REG_HANDLE *h) { + REGF *regf = h->backend_data; + HBIN_BLK *tmp = NULL; + + tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); + + memset(tmp, 0, sizeof(HBIN_BLK)); + tmp->type = REG_OUTBLK_HDR; + tmp->size = REGF_HDR_BLKSIZ; + tmp->data = malloc(REGF_HDR_BLKSIZ); + if (!tmp->data) goto error; + + memset(tmp->data, 0, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ + regf->blk_head = regf->blk_tail = tmp; + + return (REGF_HDR *)tmp->data; + +error: + if (tmp) free(tmp); + return NULL; +} + +static BOOL nt_close_registry (REG_HANDLE *h) +{ + REGF *regf = h->backend_data; + if (regf->base) munmap(regf->base, regf->sbuf.st_size); + regf->base = NULL; + close(regf->fd); /* Ignore the error :-) */ + + free(regf->sk_map); + regf->sk_count = regf->sk_map_size = 0; + + free(regf); + return False; +} + +static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load) +{ + REGF *regf = (REGF *)malloc(sizeof(REGF)); + REGF_HDR *regf_hdr; + unsigned int regf_id, hbin_id; + HBIN_HDR *hbin_hdr; + + memset(regf, 0, sizeof(REGF)); + regf->mem_ctx = talloc_init("regf"); + regf->owner_sid_str = def_owner_sid_str; + h->backend_data = regf; + + DEBUG(5, ("Attempting to load registry file\n")); + + /* Get the header */ + + if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) { + DEBUG(0, ("Unable to get header\n")); + return False; + } + + /* Now process that header and start to read the rest in */ + + if ((regf_id = IVAL(®f_hdr->REGF_ID,0)) != str_to_dword("regf")) { + DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n", + regf_id, h->location)); + return False; + } + + /* + * Validate the header ... + */ + if (!valid_regf_hdr(regf_hdr)) { + DEBUG(0, ("Registry file header does not validate: %s\n", + h->location)); + return False; + } + + /* Update the last mod date, and then go get the first NK record and on */ + + TTTONTTIME(regf, IVAL(®f_hdr->tim1,0), IVAL(®f_hdr->tim2,0)); + + /* + * The hbin hdr seems to be just uninteresting garbage. Check that + * it is there, but that is all. + */ + + hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ); + + if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) { + DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", + hbin_id, h->location)); + return False; + } + + /* + * Get a pointer to the first key from the hreg_hdr + */ + + DEBUG(2, ("First Key: %0X\n", + IVAL(®f_hdr->first_key, 0))); + + regf->first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key,0)); + DEBUGADD(2, ("First Key Offset: %0X\n", + IVAL(®f_hdr->first_key, 0))); + + DEBUGADD(2, ("Data Block Size: %d\n", + IVAL(®f_hdr->dblk_size, 0))); + + DEBUGADD(2, ("Offset to next hbin block: %0X\n", + IVAL(&hbin_hdr->off_to_next, 0))); + + DEBUGADD(2, ("HBIN block size: %0X\n", + IVAL(&hbin_hdr->blk_size, 0))); + + /* + * Unmap the registry file, as we might want to read in another + * tree etc. + */ + + h->backend_data = regf; + + return True; +} + +static REG_KEY *nt_get_root_key(REG_HANDLE *h) +{ + return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL); +} + +static int nt_num_subkeys(REG_KEY *k) +{ + REGF *regf = k->handle->backend_data; + LF_HDR *lf_hdr; + int lf_off; + NK_HDR *nk_hdr = k->backend_data; + lf_off = IVAL(&nk_hdr->lf_off,0); + DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); + if(lf_off == -1) return 0; + lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); + + return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr)); +} + +static int nt_num_values(REG_KEY *k) +{ + NK_HDR *nk_hdr = k->backend_data; + return IVAL(&nk_hdr->val_cnt,0); +} + +static REG_VAL *nt_value_by_index(REG_KEY *k, int n) +{ + VL_TYPE *vl; + int val_off, vk_off; + VK_HDR *vk_hdr; + REGF *regf = k->handle->backend_data; + NK_HDR *nk_hdr = k->backend_data; + val_off = IVAL(&nk_hdr->val_off,0); + vl = (VL_TYPE *)LOCN(regf->base, val_off); + DEBUG(2, ("Val List Offset: %0X\n", val_off)); + + vk_off = IVAL(&vl[n],0); + vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); + return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr)); +} + +static REG_KEY *nt_key_by_index(REG_KEY *k, int n) +{ + REGF *regf = k->handle->backend_data; + int lf_off; + NK_HDR *nk_hdr = k->backend_data; + LF_HDR *lf_hdr; + lf_off = IVAL(&nk_hdr->lf_off,0); + DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); + + /* + * No more subkeys if lf_off == -1 + */ + + if (lf_off != -1) { + lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); + return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n); + } + + return NULL; +} + +static REG_OPS reg_backend_nt4 = { + .name = "nt4", + .open_registry = nt_open_registry, + .close_registry = nt_close_registry, + .open_root_key = nt_get_root_key, + .num_subkeys = nt_num_subkeys, + .num_values = nt_num_values, + .get_subkey_by_index = nt_key_by_index, + .get_value_by_index = nt_value_by_index, + + /* TODO: + .add_key + .add_value + .del_key + .del_value + .update_value + */ +}; + +NTSTATUS reg_nt4_init(void) +{ + return register_backend("registry", ®_backend_nt4); +} diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c new file mode 100644 index 0000000000..7e8ad9bf48 --- /dev/null +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -0,0 +1,311 @@ +/* + Samba Unix/Linux SMB implementation + RPC backend for the registry library + Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +static void init_winreg_String(struct winreg_String *name, const char *s) +{ + name->name = s; + if (s) { + name->name_len = 2 * (strlen_m(s) + 1); + name->name_size = name->name_len; + } else { + name->name_len = 0; + name->name_size = 0; + } +} + + +#define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \ +{ \ + NTSTATUS status; \ + struct winreg_Open ## u r; \ + struct winreg_OpenUnknown unknown; \ + struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \ + TALLOC_CTX *mem_ctx = talloc_init("openhive"); \ + \ + unknown.unknown0 = 0x84e0; \ + unknown.unknown1 = 0x0000; \ + r.in.unknown = &unknown; \ + r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ + r.out.handle = hnd;\ + \ + if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, mem_ctx, &r))) {\ + printf("Error executing open\n");\ + return NULL;\ + }\ +\ + talloc_destroy(mem_ctx);\ +\ + return hnd;\ +} + +openhive(HKLM) +openhive(HKCU) +openhive(HKPD) +openhive(HKU) +openhive(HKCR) + +struct rpc_data { + struct dcerpc_pipe *pipe; + struct policy_handle *hives[10]; +}; + +struct { + char *name; + struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h); +} known_hives[] = { +{ "HKEY_LOCAL_MACHINE", open_HKLM }, +{ "HKEY_CURRENT_USER", open_HKCU }, +{ "HKEY_CLASSES_ROOT", open_HKCR }, +{ "HKEY_PERFORMANCE_DATA", open_HKPD }, +{ "HKEY_USERS", open_HKU }, +{ NULL, NULL } +}; + +static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full) +{ + BOOL res = True; + struct rpc_data *mydata = malloc(sizeof(struct rpc_data)); + char *binding = strdup(location); + NTSTATUS status; + + ZERO_STRUCTP(mydata); + + status = dcerpc_pipe_connect(&mydata->pipe, binding, + DCERPC_WINREG_UUID, + DCERPC_WINREG_VERSION, + lp_workgroup(), + "jelwin", "dds"); + + if(!NT_STATUS_IS_OK(status)) return False; + + h->backend_data = mydata; + + return True; +} + +static REG_KEY *rpc_open_root(REG_HANDLE *h) +{ + /* There's not really a 'root' key here */ + return reg_key_new_abs("\\", h, h->backend_data); +} + +static BOOL rpc_close_registry(REG_HANDLE *h) +{ + dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe); + free(h->backend_data); + return True; +} + +static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path) +{ + char *hivename; + int i = 0; + struct rpc_data *mydata = h->backend_data; + struct policy_handle *hive = NULL; + char *end = strchr(path+1, '\\'); + NTSTATUS status; + struct winreg_OpenKey r; + struct policy_handle *key_handle = malloc(sizeof(struct policy_handle)); + TALLOC_CTX *mem_ctx; + + if(end) hivename = strndup(path+1, end-path-1); + else hivename = strdup(path+1); + + for(i = 0; known_hives[i].name; i++) { + if(!strcmp(hivename, known_hives[i].name)) { + if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, h); + hive = mydata->hives[i]; + } + } + + if(!hive) { + DEBUG(0, ("No such hive: %s\n", hivename)); + return NULL; + } + + DEBUG(2, ("Opening %s, hive: %s\n", path, hivename)); + + if(!end || !(*end) || !(*(end+1))) return hive; + + memset(&r, 0, sizeof(struct winreg_OpenKey)); + r.in.handle = hive; + init_winreg_String(&r.in.keyname, end+1); + r.in.unknown = 0x00000000; + r.in.access_mask = 0x02000000; + r.out.handle = key_handle; + + mem_ctx = talloc_init("openkey"); + status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r); + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) { + return NULL; + } + + return key_handle; +} + +static REG_KEY *rpc_open_key(REG_HANDLE *h, const char *name) +{ + return reg_key_new_abs(name, h, rpc_get_key_handle(h, name)); +} + +static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) +{ + struct winreg_EnumKey r; + struct winreg_EnumKeyNameRequest keyname; + struct winreg_String classname; + struct winreg_Time tm; + struct rpc_data *mydata = parent->handle->backend_data; + int i; + REG_KEY **ar = malloc(sizeof(REG_KEY *)); + NTSTATUS status = NT_STATUS_OK; + TALLOC_CTX *mem_ctx; + + /* List the hives */ + if(parent->backend_data == parent->handle->backend_data) { + REG_KEY **ar = malloc(sizeof(REG_KEY *)); + for(i = 0; known_hives[i].name; i++) { + ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL); + (*count)++; + ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+1)); + } + + *subkeys = ar; + + return True; + } + + if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); + + if(!parent->backend_data) return False; + + mem_ctx = talloc_init("enumkey"); + (*count) = 0; + r.in.handle = parent->backend_data; + keyname.unknown = 0x0000020a; + init_winreg_String(&keyname.key_name, NULL); + init_winreg_String(&classname, NULL); + r.in.in_name = &keyname; + r.in.class = &classname; + tm.low = tm.high = 0x7fffffff; + r.in.last_changed_time = &tm; + r.out.result.v = 0; + + for(i = 0; NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result); i++) { + r.in.enum_index = i; + r.in.unknown = r.out.unknown = 0x0414; + r.in.key_name_len = r.out.key_name_len = 0; + status = dcerpc_winreg_EnumKey(mydata->pipe, mem_ctx, &r); + if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL); + (*count)++; + ar = realloc(ar, ((*count)+1) * sizeof(REG_KEY *)); + } + } + + *subkeys = ar; + return True; +} + +static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) +{ + struct winreg_EnumValue r; + struct winreg_EnumValueName name; + struct winreg_Uint8buf value; + struct winreg_Uint16buf buf; + struct rpc_data *mydata = parent->handle->backend_data; + TALLOC_CTX *mem_ctx; + uint32 type, requested_len, returned_len; + NTSTATUS status = NT_STATUS_OK; + REG_VAL **ar = malloc(sizeof(REG_VAL *)); + + (*count) = 0; + + if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); + + if(!parent->backend_data) return False; + + r.in.handle = parent->backend_data; + r.in.enum_index = 0; + + buf.max_len = 0x7fff; + buf.offset = 0; + buf.len = 0; + buf.buffer = NULL; + + name.len = 0; + name.max_len = buf.max_len *2; + name.buf = &buf; + + r.in.name = r.out.name = &name; + + type = 0; + r.in.type = r.out.type = &type; + value.max_len = 0x7fff; + value.offset = 0; + value.len = 0; + value.buffer = NULL; + + r.in.value = r.out.value = &value; + + requested_len = value.max_len; + r.in.requested_len = &requested_len; + returned_len = 0; + r.in.returned_len = &returned_len; + r.out.result.v = 0; + + mem_ctx = talloc_init("fetchvalues"); + while(1) { + status = dcerpc_winreg_EnumValue(mydata->pipe, mem_ctx, &r); + if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + r.in.enum_index++; + ar[(*count)] = reg_val_new(parent, NULL); + ar[(*count)]->name = strdup((char *)name.buf); + ar[(*count)]->data_type = *r.out.type; + ar[(*count)]->data_len = value.len; + ar[(*count)]->data_blk = malloc(value.len); + memcpy(ar[(*count)]->data_blk, value.buffer, value.len); + (*count)++; + ar = realloc(ar, ((*count)+1) * sizeof(REG_VAL *)); + } else break; + } + + talloc_destroy(mem_ctx); + + return True; +} + +static REG_OPS reg_backend_rpc = { + .name = "rpc", + .open_registry = rpc_open_registry, + .close_registry = rpc_close_registry, + .open_root_key = rpc_open_root, + .open_key = rpc_open_key, + .fetch_subkeys = rpc_fetch_subkeys, + .fetch_values = rpc_fetch_values, +}; + +NTSTATUS reg_rpc_init(void) +{ + return register_backend("registry", ®_backend_rpc); +} diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c new file mode 100644 index 0000000000..6c8d7885cb --- /dev/null +++ b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c @@ -0,0 +1,32 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +static REG_OPS reg_backend_wine = { + .name = "wine", +}; + +NTSTATUS reg_wine_init(void) +{ + register_backend("registry", ®_backend_wine); + return NT_STATUS_OK; +} diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c new file mode 100644 index 0000000000..070516b798 --- /dev/null +++ b/source4/lib/registry/tools/regdiff.c @@ -0,0 +1,148 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) +{ + int i, numvals1, numvals2, numkeys2; + + numkeys2 = reg_key_num_subkeys(newkey); + for(i = 0; i < numkeys2; i++) { + REG_KEY *t1 = reg_key_get_subkey_by_index(newkey, i); + REG_KEY *t2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1)); + if(!t2) { + fprintf(out, "[%s]\n", reg_key_get_path(t1)); + } + writediff(t2, t1, out); + } + + numvals2 = reg_key_num_values(newkey); + for(i = 0; i < numvals2; i++) { + REG_VAL *t1 = reg_key_get_value_by_index(newkey, i); + REG_VAL *t2 = reg_key_get_value_by_name(oldkey, reg_val_name(t1)); + if(!t2 || reg_val_size(t2) != reg_val_size(t1) || memcmp(reg_val_data_blk(t1), reg_val_data_blk(t2), reg_val_size(t1))) { + fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(t1), str_regtype(reg_val_type(t1)), reg_val_data_string(t1)); + } + } + + numvals1 = reg_key_num_values(oldkey); + for(i = 0; i < numvals1; i++) { + REG_VAL *t1 = reg_key_get_value_by_index(oldkey, i); + if(!reg_key_get_value_by_name(newkey, reg_val_name(t1))) { + fprintf(out, "\"%s\"=-\n", reg_val_name(t1)); + } + } +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + poptContext pc; + REG_KEY *root; + const char *backend1 = NULL, *backend2 = NULL; + const char *location2; + char *outputfile = NULL; + FILE *fd = stdout; + REG_HANDLE *h2; + REG_KEY *root1 = NULL, *root2; + int from_null = 0; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, + {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, + {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" }, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + case 'b': + if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); + else if(!backend2) backend2 = poptGetOptArg(pc); + break; + } + } + setup_logging(argv[0], True); + + if(!from_null) { + REG_HANDLE *h1; + const char *location1; + location1 = poptGetArg(pc); + if(!location1) { + poptPrintUsage(pc, stderr, 0); + return 1; + } + + if(!backend1) backend1 = "dir"; + + h1 = reg_open(backend1, location1, True); + if(!h1) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); + return 1; + } + + root1 = reg_get_root(h1); + } + + location2 = poptGetArg(pc); + if(!location2) { + poptPrintUsage(pc, stderr, 0); + return 2; + } + + if(!backend2) backend2 = "dir"; + + h2 = reg_open(backend2, location2, True); + if(!h2) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); + return 1; + } + + root2 = reg_get_root(h2); + if(!root2) { + fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2); + return 1; + } + + poptFreeContext(pc); + + if(outputfile) { + fd = fopen(outputfile, "w+"); + if(!fd) { + fprintf(stderr, "Unable to open '%s'\n", outputfile); + return 1; + } + } + + fprintf(fd, "REGEDIT4\n\n"); + fprintf(fd, "; Generated using regdiff\n"); + + writediff(root1, root2, fd); + + fclose(fd); + + return 0; +} diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c new file mode 100644 index 0000000000..f76da7ebf9 --- /dev/null +++ b/source4/lib/registry/tools/regpatch.c @@ -0,0 +1,808 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) 2002, Richard Sharpe, rsharpe@richardsharpe.com + Copyright (C) 2004, Jelmer Vernooij, jelmer@samba.org + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + * Routines to parse a REGEDIT4 file + * + * The file consists of: + * + * REGEDIT4 + * \[[-]key-path\]\n + * * + * + * Format: + * [cmd:]name=type:value + * + * cmd = a|d|c|add|delete|change|as|ds|cs + * + * There can be more than one key-path and value-spec. + * + * Since we want to support more than one type of file format, we + * construct a command-file structure that keeps info about the command file + */ + +#define FMT_UNREC -1 +#define FMT_REGEDIT4 0 +#define FMT_EDITREG1_1 1 + +#define FMT_STRING_REGEDIT4 "REGEDIT4" +#define FMT_STRING_EDITREG1_0 "EDITREG1.0" + +#define CMD_NONE 0 +#define CMD_ADD_KEY 1 +#define CMD_DEL_KEY 2 + +#define CMD_KEY 1 +#define CMD_VAL 2 + +#include + +typedef struct val_spec_list { + struct val_spec_list *next; + char *name; + int type; + char *val; /* Kept as a char string, really? */ +} VAL_SPEC_LIST; + +typedef struct command_s { + int cmd; + char *key; + int val_count; + VAL_SPEC_LIST *val_spec_list, *val_spec_last; +} CMD; + +typedef struct cmd_line { + int len, line_len; + char *line; +} CMD_LINE; + +static void free_val_spec_list(VAL_SPEC_LIST *vl) +{ + if (!vl) return; + if (vl->name) free(vl->name); + if (vl->val) free(vl->val); + free(vl); + +} + +/* + * Some routines to handle lines of info in the command files + */ +static void skip_to_eol(int fd) +{ + int rc; + char ch = 0; + + while ((rc = read(fd, &ch, 1)) == 1) { + if (ch == 0x0A) return; + } + if (rc < 0) { + DEBUG(0, ("Could not read file descriptor: %d, %s\n", + fd, strerror(errno))); + exit(1); + } +} + +static void free_cmd(CMD *cmd) +{ + if (!cmd) return; + + while (cmd->val_spec_list) { + VAL_SPEC_LIST *tmp; + + tmp = cmd->val_spec_list; + cmd->val_spec_list = tmp->next; + free(tmp); + } + + free(cmd); + +} + +static void free_cmd_line(CMD_LINE *cmd_line) +{ + if (cmd_line) { + if (cmd_line->line) free(cmd_line->line); + free(cmd_line); + } +} + +static void print_line(struct cmd_line *cl) +{ + char *pl; + + if (!cl) return; + + pl = smb_xmalloc(cl->line_len + 1); + + strncpy(pl, cl->line, cl->line_len); + pl[cl->line_len] = 0; + + fprintf(stdout, "%s\n", pl); + free(pl); +} + +#define INIT_ALLOC 10 + +/* + * Read a line from the input file. + * NULL returned when EOF and no chars read + * Otherwise we return a cmd_line * + * Exit if other errors + */ +static struct cmd_line *get_cmd_line(int fd) +{ + struct cmd_line *cl = (CMD_LINE *)smb_xmalloc(sizeof(CMD_LINE)); + int i = 0, rc; + unsigned char ch; + + cl->len = INIT_ALLOC; + + /* + * Allocate some space for the line. We extend later if needed. + */ + + cl->line = (char *)smb_xmalloc(INIT_ALLOC); + + /* + * Now read in the chars to EOL. Don't store the EOL in the + * line. What about CR? + */ + + while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') { + if (ch == '\r') continue; /* skip CR */ + if (i == cl->len) { + /* + * Allocate some more memory + */ + if ((cl->line = realloc(cl->line, cl->len + INIT_ALLOC)) == NULL) { + DEBUG(0, ("Unable to realloc space for line: %s\n", + strerror(errno))); + exit(1); + } + cl->len += INIT_ALLOC; + } + cl->line[i] = ch; + i++; + } + + /* read 0 and we were at loc'n 0, return NULL */ + if (rc == 0 && i == 0) { + free_cmd_line(cl); + return NULL; + } + + cl->line_len = i; + + return cl; + +} + +/* + * parse_value: parse out a value. We pull it apart as: + * + * ::= =: + * + * ::= char-string-without-spaces | '"' char-string '"' + * + * If it parsed OK, return the as a string, and the + * value type and value-string in parameters. + * + * The value name can be empty. There can only be one empty name in + * a list of values. A value of - removes the value entirely. + */ + +static char *parse_name(char *nstr) +{ + int len = 0, start = 0; + if (!nstr) return NULL; + + len = strlen(nstr); + + while (len && nstr[len - 1] == ' ') len--; + + nstr[len] = 0; /* Trim any spaces ... if there were none, doesn't matter */ + + /* + * Beginning and end should be '"' or neither should be so + */ + if ((nstr[0] == '"' && nstr[len - 1] != '"') || + (nstr[0] != '"' && nstr[len - 1] == '"')) + return NULL; + + if (nstr[0] == '"') { + start = 1; + len -= 2; + } + + return strndup(&nstr[start], len); +} + +static int parse_value_type(char *tstr) +{ + int len = strlen(tstr); + + while (len && tstr[len - 1] == ' ') len--; + tstr[len] = 0; + + if (strcmp(tstr, "REG_DWORD") == 0) + return REG_DWORD; + else if (strcmp(tstr, "dword") == 0) + return REG_DWORD; + else if (strcmp(tstr, "REG_EXPAND_SZ") == 0) + return REG_EXPAND_SZ; + else if (strcmp(tstr, "REG_BIN") == 0) + return REG_BINARY; + else if (strcmp(tstr, "REG_SZ") == 0) + return REG_SZ; + else if (strcmp(tstr, "REG_MULTI_SZ") == 0) + return REG_MULTI_SZ; + else if (strcmp(tstr, "-") == 0) + return REG_DELETE; + + return 0; +} + +static char *parse_val_str(char *vstr) +{ + + return strndup(vstr, strlen(vstr)); + +} + +static char *parse_value(struct cmd_line *cl, int *vtype, char **val) +{ + char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL; + + if (!cl || !vtype || !val) return NULL; + if (!cl->line_len) return NULL; + + p1 = strndup(cl->line, cl->line_len); + /* FIXME: Better return codes etc ... */ + if (!p1) return NULL; + p2 = strchr(p1, '='); + if (!p2) return NULL; + + *p2 = 0; p2++; /* Split into two strings at p2 */ + + /* Now, parse the name ... */ + + nstr = parse_name(p1); + if (!nstr) goto error; + + /* Now, split the remainder and parse on type and val ... */ + + tstr = p2; + while (*tstr == ' ') tstr++; /* Skip leading white space */ + p2 = strchr(p2, ':'); + + if (p2) { + *p2 = 0; p2++; /* split on the : */ + } + + *vtype = parse_value_type(tstr); + + if (!vtype) goto error; + + if (!p2 || !*p2) return nstr; + + /* Now, parse the value string. It should return a newly malloc'd string */ + + while (*p2 == ' ') p2++; /* Skip leading space */ + vstr = parse_val_str(p2); + + if (!vstr) goto error; + + *val = vstr; + + return nstr; + + error: + if (p1) free(p1); + if (nstr) free(nstr); + if (vstr) free(vstr); + return NULL; +} + +/* + * Parse out a key. Look for a correctly formatted key [...] + * and whether it is a delete or add? A delete is signalled + * by a - in front of the key. + * Assumes that there are no leading and trailing spaces + */ + +static char *parse_key(struct cmd_line *cl, int *cmd) +{ + int start = 1; + char *tmp; + + if (cl->line[0] != '[' || + cl->line[cl->line_len - 1] != ']') return NULL; + if (cl->line_len == 2) return NULL; + *cmd = CMD_ADD_KEY; + if (cl->line[1] == '-') { + if (cl->line_len == 3) return NULL; + start = 2; + *cmd = CMD_DEL_KEY; + } + tmp = smb_xmalloc(cl->line_len - 1 - start + 1); + strncpy(tmp, &cl->line[start], cl->line_len - 1 - start); + tmp[cl->line_len - 1 - start] = 0; + return tmp; +} + +/* + * Parse a line to determine if we have a key or a value + * We only check for key or val ... + */ + +static int parse_line(struct cmd_line *cl) +{ + + if (!cl || cl->len == 0) return 0; + + if (cl->line[0] == '[') /* No further checking for now */ + return CMD_KEY; + else + return CMD_VAL; +} + +/* + * We seek to offset 0, read in the required number of bytes, + * and compare to the correct value. + * We then seek back to the original location + */ +static int regedit4_file_type(int fd) +{ + int cur_ofs = 0; + char desc[9]; + + cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ + if (cur_ofs < 0) { + DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); + exit(1); /* FIXME */ + } + + if (cur_ofs) { + lseek(fd, 0, SEEK_SET); + } + + if (read(fd, desc, 8) < 8) { + DEBUG(0, ("Unable to read command file format\n")); + exit(2); /* FIXME */ + } + + desc[8] = 0; + + if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) { + if (cur_ofs) { + lseek(fd, cur_ofs, SEEK_SET); + } + else { + skip_to_eol(fd); + } + return FMT_REGEDIT4; + } + + return FMT_UNREC; +} + +/* + * Run though the data in the line and strip anything after a comment + * char. + */ +static void strip_comment(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = 0; i < cl->line_len; i++) { + if (cl->line[i] == ';') { + cl->line_len = i; + return; + } + } +} + +/* + * trim leading space + */ + +static void trim_leading_spaces(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = 0; i < cl->line_len; i++) { + if (cl->line[i] != ' '){ + if (i) memcpy(cl->line, &cl->line[i], cl->line_len - i); + return; + } + } +} + +/* + * trim trailing spaces + */ +static void trim_trailing_spaces(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = cl->line_len; i == 0; i--) { + if (cl->line[i-1] != ' ' && + cl->line[i-1] != '\t') { + cl->line_len = i; + } + } +} + +/* + * Get a command ... This consists of possibly multiple lines: + * [key] + * values* + * possibly Empty line + * + * value ::= =':' + * is some path, possibly enclosed in quotes ... + * We alctually look for the next key to terminate a previous key + * if == '-', then it is a delete type. + */ +static CMD *regedit4_get_cmd(int fd) +{ + struct command_s *cmd = NULL; + struct cmd_line *cl = NULL; + struct val_spec_list *vl = NULL; + + cmd = (struct command_s *)smb_xmalloc(sizeof(struct command_s)); + + cmd->cmd = CMD_NONE; + cmd->key = NULL; + cmd->val_count = 0; + cmd->val_spec_list = cmd->val_spec_last = NULL; + while ((cl = get_cmd_line(fd))) { + + /* + * If it is an empty command line, and we already have a key + * then exit from here ... FIXME: Clean up the parser + */ + + if (cl->line_len == 0 && cmd->key) { + free_cmd_line(cl); + break; + } + + strip_comment(cl); /* remove anything beyond a comment char */ + trim_trailing_spaces(cl); + trim_leading_spaces(cl); + + if (cl->line_len == 0) { /* An empty line */ + free_cmd_line(cl); + } + else { /* Else, non-empty ... */ + /* + * Parse out the bits ... + */ + switch (parse_line(cl)) { + case CMD_KEY: + if ((cmd->key = parse_key(cl, &cmd->cmd)) == NULL) { + DEBUG(0, ("Error parsing key from line: ")); + print_line(cl); + DEBUG(0, ("\n")); + } + break; + + case CMD_VAL: + /* + * We need to add the value stuff to the list + * There could be a \ on the end which we need to + * handle at some time + */ + vl = (struct val_spec_list *)smb_xmalloc(sizeof(struct val_spec_list)); + vl->next = NULL; + vl->val = NULL; + vl->name = parse_value(cl, &vl->type, &vl->val); + if (!vl->name) goto error; + if (cmd->val_spec_list == NULL) { + cmd->val_spec_list = cmd->val_spec_last = vl; + } + else { + cmd->val_spec_last->next = vl; + cmd->val_spec_last = vl; + } + cmd->val_count++; + break; + + default: + DEBUG(0, ("Unrecognized line in command file: \n")); + print_line(cl); + break; + } + } + + } + if (!cmd->cmd) goto error; /* End of file ... */ + + return cmd; + + error: + if (vl) free(vl); + if (cmd) free_cmd(cmd); + return NULL; +} + +static int regedit4_exec_cmd(CMD *cmd) +{ + + return 0; +} + +static int editreg_1_0_file_type(int fd) +{ + int cur_ofs = 0; + char desc[11]; + + cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ + if (cur_ofs < 0) { + DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); + exit(1); /* FIXME */ + } + + if (cur_ofs) { + lseek(fd, 0, SEEK_SET); + } + + if (read(fd, desc, 10) < 10) { + DEBUG(0, ("Unable to read command file format\n")); + exit(2); /* FIXME */ + } + + desc[10] = 0; + + if (strcmp(desc, FMT_STRING_EDITREG1_0) == 0) { + lseek(fd, cur_ofs, SEEK_SET); + return FMT_REGEDIT4; + } + + return FMT_UNREC; +} + +static CMD *editreg_1_0_get_cmd(int fd) +{ + return NULL; +} + +static int editreg_1_0_exec_cmd(CMD *cmd) +{ + + return -1; +} + +typedef struct command_ops_s { + int type; + int (*file_type)(int fd); + CMD *(*get_cmd)(int fd); + int (*exec_cmd)(CMD *cmd); +} CMD_OPS; + +CMD_OPS default_cmd_ops[] = { + {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd}, + {1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd}, + {-1, NULL, NULL, NULL} +}; + +typedef struct command_file_s { + char *name; + int type, fd; + CMD_OPS cmd_ops; +} CMD_FILE; + +/* + * Create a new command file structure + */ + +static CMD_FILE *cmd_file_create(char *file) +{ + CMD_FILE *tmp; + struct stat sbuf; + int i = 0; + + /* + * Let's check if the file exists ... + * No use creating the cmd_file structure if the file does not exist + */ + + if (stat(file, &sbuf) < 0) { /* Not able to access file */ + + return NULL; + } + + tmp = (CMD_FILE *)smb_xmalloc(sizeof(CMD_FILE)); + + /* + * Let's fill in some of the fields; + */ + + tmp->name = strdup(file); + + if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) { + free(tmp); + return NULL; + } + + /* + * Now, try to find the format by indexing through the table + */ + while (default_cmd_ops[i].type != -1) { + if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) { + tmp->cmd_ops = default_cmd_ops[i]; + return tmp; + } + i++; + } + + /* + * If we got here, return NULL, as we could not figure out the type + * of command file. + * + * What about errors? + */ + + free(tmp); + return NULL; +} + +/* + * Extract commands from the command file, and execute them. + * We pass a table of command callbacks for that + */ + +//FIXME + +/* + * Main code from here on ... + */ + +/* + * key print function here ... + */ + +/* + * Sec Desc print functions + */ + +char *str_type(unsigned char type); + +int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) +{ + CMD *cmd; + int modified = 0; + CMD_FILE *cmd_file = NULL; + cmd_file = cmd_file_create(cmd_file_name); + + while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) { + + /* + * Now, apply the requests to the tree ... + */ + switch (cmd->cmd) { + case CMD_ADD_KEY: { + REG_KEY *tmp = NULL; + tmp = reg_open_key(reg_get_root(regf), cmd->key); + /* If we found it, apply the other bits, else create such a key */ + if (!tmp) { + if(reg_key_add_name(reg_get_root(regf), cmd->key)) { + tmp = reg_open_key(reg_get_root(regf), cmd->key); + } + modified = 1; + } + + while (cmd->val_count) { + VAL_SPEC_LIST *val = cmd->val_spec_list; + REG_VAL *reg_val = NULL; + + if (val->type == REG_DELETE) { + reg_val = reg_key_get_value_by_name( tmp, val->name); + reg_val_del(reg_val); + modified = 1; + } + else { + /* FIXME + reg_val = nt_add_reg_value(tmp, val->name, val->type, + val->val); */ + modified = 1; + } + + cmd->val_spec_list = val->next; + free_val_spec_list(val); + cmd->val_count--; + } + + break; + } + + case CMD_DEL_KEY: + /* + * Any value does not matter ... + * Find the key if it exists, and delete it ... + */ + + reg_key_del_recursive(reg_open_key(reg_get_root(regf), cmd->key)); + modified = 1; + break; + } + } + free_cmd(cmd); + + return modified; +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + poptContext pc; + REG_KEY *root; + const char *location; + const char *patch; + char *backend = "dir"; + REG_HANDLE *h; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + setup_logging(argv[0], True); + + location = poptGetArg(pc); + if(!location) { + poptPrintUsage(pc, stderr, 0); + return 1; + } + + h = reg_open(backend, location, True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); + return 1; + } + + poptFreeContext(pc); + + patch = poptGetArg(pc); + if(!patch) patch = "/dev/stdin"; + + nt_apply_reg_command_file(h, patch); + + return 0; +} diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c new file mode 100644 index 0000000000..9074d1c716 --- /dev/null +++ b/source4/lib/registry/tools/regshell.c @@ -0,0 +1,243 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + * ck/cd - change key + * ls - list values/keys + * rmval/rm - remove value + * rmkey/rmdir - remove key + * mkkey/mkdir - make key + * help + * exit + */ + +static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) +{ + /* FIXME */ + return NULL; +} + +static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) +{ + REG_KEY *new; + if(argc < 2) { + new = cur; + } else { + new = reg_open_key(cur, argv[1]); + } + + if(!new) new = cur; + + printf("Current path is: %s\n", reg_key_get_path(new)); + + return new; +} + +static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) +{ + int i, num; + num = reg_key_num_subkeys(cur); + for(i = 0; i < num; i++) { + REG_KEY *sub = reg_key_get_subkey_by_index(cur, i); + printf("K %s\n", reg_key_name(sub)); + } + + num = reg_key_num_values(cur); + for(i = 0; i < num; i++) { + REG_VAL *sub = reg_key_get_value_by_index(cur, i); + printf("V %s %s %s\n", reg_val_name(sub), str_regtype(reg_val_type(sub)), reg_val_data_string(sub)); + } + + return NULL; +} +static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) +{ + if(argc < 2) { + fprintf(stderr, "Usage: mkkey \n"); + return NULL; + } + + if(!reg_key_add_name(cur, argv[1])) { + fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]); + return NULL; + } + + fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path(cur)); + + return NULL; +} + +static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) +{ + REG_KEY *key; + if(argc < 2) { + fprintf(stderr, "Usage: rmkey \n"); + return NULL; + } + + key = reg_open_key(cur, argv[1]); + if(!key) { + fprintf(stderr, "No such subkey '%s'\n", argv[1]); + return NULL; + } + + if(!reg_key_del(key)) { + fprintf(stderr, "Error deleting '%s'\n", argv[1]); + } else { + fprintf(stderr, "Successfully deleted '%s'\n", argv[1]); + } + + return NULL; +} + +static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) +{ + REG_VAL *val; + if(argc < 2) { + fprintf(stderr, "Usage: rmval \n"); + return NULL; + } + + val = reg_key_get_value_by_name(cur, argv[1]); + if(!val) { + fprintf(stderr, "No such value '%s'\n", argv[1]); + return NULL; + } + + if(!reg_val_del(val)) { + fprintf(stderr, "Error deleting value '%s'\n", argv[1]); + } else { + fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); + } + + return NULL; +} + +static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) +{ + exit(0); + return NULL; +} + +static REG_KEY *cmd_help(REG_KEY *, int, char **); + +struct { + const char *name; + const char *alias; + const char *help; + REG_KEY *(*handle)(REG_KEY *, int argc, char **argv); +} regshell_cmds[] = { + {"ck", "cd", "Change current key", cmd_ck }, + {"list", "ls", "List values/keys in current key", cmd_ls }, + {"mkkey", "mkdir", "Make new key", cmd_mkkey }, + {"rmval", "rm", "Remove value", cmd_rmval }, + {"rmkey", "rmdir", "Remove key", cmd_rmkey }, + {"set", "update", "Update value", cmd_set }, + {"help", "?", "Help", cmd_help }, + {"exit", "quit", "Exit", cmd_exit }, + {NULL } +}; + +static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) +{ + int i; + printf("Available commands:\n"); + for(i = 0; regshell_cmds[i].name; i++) { + printf("%s - %s\n", regshell_cmds[i].name, regshell_cmds[i].help); + } + return NULL; +} + +REG_KEY *process_cmd(REG_KEY *k, char *line) +{ + int argc; + char **argv = NULL; + int ret, i; + + if ((ret = poptParseArgvString(line, &argc, (const char ***) &argv)) != 0) { + fprintf(stderr, "regshell: %s\n", poptStrerror(ret)); + return k; + } + + for(i = 0; regshell_cmds[i].name; i++) { + if(!strcmp(regshell_cmds[i].name, argv[0]) || + (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) { + return regshell_cmds[i].handle(k, argc, argv); + } + } + + fprintf(stderr, "No such command '%s'\n", argv[0]); + + return k; +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + char *backend = "dir"; + REG_KEY *curkey = NULL;; + poptContext pc; + REG_HANDLE *h; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + h = reg_open(backend, poptPeekArg(pc), True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + return 1; + } + poptFreeContext(pc); + + setup_logging("regtree", True); + + curkey = reg_get_root(h); + + if(!curkey) return 1; + + while(True) { + char *line, *prompt; + + asprintf(&prompt, "%s> ", reg_key_get_path(curkey)); + + line = smb_readline(prompt, NULL, NULL); + + if(!line) + break; + + if(line[0] != '\n') { + REG_KEY *new = process_cmd(curkey, line); + if(new)curkey = new; + } + } + + return 0; +} diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c new file mode 100644 index 0000000000..80cbccf48f --- /dev/null +++ b/source4/lib/registry/tools/regtree.c @@ -0,0 +1,91 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +void print_tree(int l, REG_KEY *p, int fullpath, int novals) +{ + int num_subkeys, i, num_values; + + for(i = 0; i < l; i++) putchar(' '); + if(fullpath) printf("%s\n", reg_key_get_path(p)); + else printf("%s\n", reg_key_name(p)); + + num_subkeys = reg_key_num_subkeys(p); + for(i = 0; i < num_subkeys; i++) { + REG_KEY *subkey = reg_key_get_subkey_by_index(p, i); + print_tree(l+1, subkey, fullpath, novals); + reg_key_free(subkey); + } + + if(!novals) { + num_values = reg_key_num_values(p); + for(i = 0; i < num_values; i++) { + int j; + char *desc; + REG_VAL *value = reg_key_get_value_by_index(p, i); + for(j = 0; j < l+1; j++) putchar(' '); + desc = reg_val_description(value); + printf("%s\n", desc); + free(desc); + reg_val_free(value); + } + } +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + char *backend = "dir"; + poptContext pc; + REG_KEY *root; + REG_HANDLE *h; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, + {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + setup_logging("regtree", True); + + h = reg_open(backend, poptPeekArg(pc), True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + return 1; + } + poptFreeContext(pc); + + root = reg_get_root(h); + if(!root) return 1; + + print_tree(0, root, fullpath, no_values); + + return 0; +} diff --git a/source4/lib/registry/winregistry.pc.in b/source4/lib/registry/winregistry.pc.in new file mode 100644 index 0000000000..ad134da236 --- /dev/null +++ b/source4/lib/registry/winregistry.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: winregistry +Description: Windows registry library +Version: @PACKAGE_VERSION@ +Libs: @LIBS@ @REG_LIBS@ -L${prefix}/lib -lwinregistry +Cflags: -I${includedir} @CFLAGS@ @CFLAGS@ -- cgit From 69c19afb6226e93a244490fa582200364a3b7069 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Apr 2004 09:17:11 +0000 Subject: r31: More registry updates. regdiff/regpatch work now. (This used to be commit 98224f5436695eb265f5d997cf4bc9cf735a4fb9) --- source4/lib/registry/TODO | 4 - source4/lib/registry/common/reg_interface.c | 65 ++++++++- source4/lib/registry/common/reg_objects.c | 2 +- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 63 ++++----- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 25 ++-- source4/lib/registry/tools/regdiff.c | 12 +- source4/lib/registry/tools/regpatch.c | 148 ++++++++------------- 7 files changed, 168 insertions(+), 151 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 26fb8d217d..ac467d0078 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -3,7 +3,6 @@ - use memory pools? - get rid of all the nasty memory leaks.. - security stuff -- finish 'regpatch' - clean up code - rpc_server @@ -22,6 +21,3 @@ reg_backend_ldb: reg_backend_wine.c: - implement - -regpatch.c: - - test/finish diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index dc49dab4c1..d40a855f89 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -187,6 +187,8 @@ REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx) int reg_key_num_subkeys(REG_KEY *key) { + if(!key) return 0; + if(!key->handle->functions->num_subkeys) { if(!key->cache_subkeys) key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); @@ -306,8 +308,12 @@ REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name) BOOL reg_key_del(REG_KEY *key) { - if(key->handle->functions->del_key) - return key->handle->functions->del_key(key); + if(key->handle->functions->del_key) { + if(key->handle->functions->del_key(key)) { + free_cached_keys(key); + return True; + } + } return False; } @@ -349,17 +355,53 @@ BOOL reg_val_del(REG_VAL *val) return False; } - return val->handle->functions->del_value(val); + if(val->handle->functions->del_value(val)) { + free_cached_values(val->parent); + return True; + } + return False; +} + +BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path) +{ + REG_KEY *cur, *prevcur = parent; + char *begin = (char *)path, *end; + + while(1) { + end = strchr(begin, '\\'); + if(end) *end = '\0'; + cur = reg_key_get_subkey_by_name(prevcur, begin); + if(!cur) { + if(!reg_key_add_name(prevcur, begin)) { printf("foo\n"); return False; } + cur = reg_key_get_subkey_by_name(prevcur, begin); + if(!cur) { + DEBUG(0, ("Can't find key after adding it : %s\n", begin)); + return False; + } + } + + if(!end) break; + *end = '\\'; + begin = end+1; + prevcur = cur; + } + return True; } BOOL reg_key_add_name(REG_KEY *parent, const char *name) { + if (!parent) return False; + if (!parent->handle->functions->add_key) { DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); return False; } - return parent->handle->functions->add_key(parent, name); + if(parent->handle->functions->add_key(parent, name)) { + free_cached_keys(parent); + return True; + } + return False; } BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) @@ -377,6 +419,7 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) new = val->handle->functions->add_value(val->parent, val->name, type, data, len); memcpy(val, new, sizeof(REG_VAL)); + free_cached_values(val->parent); return True; } @@ -419,5 +462,19 @@ REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value ret = key->handle->functions->add_value(key, name, type, value, vallen); ret->parent = key; ret->handle = key->handle; + free_cached_values(key); return ret; } + +void free_cached_values(REG_KEY *key) +{ + free(key->cache_values); key->cache_values = NULL; + key->cache_values_count = 0; +} + + +void free_cached_keys(REG_KEY *key) +{ + free(key->cache_subkeys); key->cache_subkeys = NULL; + key->cache_subkeys_count = 0; +} diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 911dc15c8e..8de0065da0 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -161,7 +161,7 @@ char *reg_val_get_path(REG_VAL *v) return NULL; } -char *reg_key_get_path(REG_KEY *k) +const char *reg_key_get_path(REG_KEY *k) { SMB_REG_ASSERT(k); return k->path; diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index baed39b4eb..5fec782e95 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -21,27 +21,11 @@ #include "includes.h" #include "lib/registry/common/registry.h" -static DIR *reg_dir_dir(REG_HANDLE *h, const char *base, const char *name) -{ - char *path = NULL; - DIR *d; - asprintf(&path, "%s/%s/%s", h->location, base, name); - path = reg_path_win2unix(path); - - d = opendir(path); - if(!d) { - printf("Unable to open '%s'\n", path); - return NULL; - } - SAFE_FREE(path); - return d; -} - static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) { char *path; int ret; - asprintf(&path, "%s/%s/%s", parent->handle->location, reg_key_get_path(parent), name); + asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name); path = reg_path_win2unix(path); ret = mkdir(path, 0700); free(path); @@ -50,13 +34,7 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) static BOOL reg_dir_del_key(REG_KEY *k) { - char *path; - int ret; - asprintf(&path, "%s/%s", k->handle->location, reg_key_get_path(k)); - path = reg_path_win2unix(path); - ret = rmdir(path); - free(path); - return (ret == 0); + return (rmdir((char *)k->backend_data) == 0); } static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) @@ -67,32 +45,41 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) DEBUG(0, ("NULL pointer passed as directory name!")); return NULL; } - fullpath = reg_path_win2unix(strdup(name)); - d = reg_dir_dir(h, "", fullpath); - free(fullpath); + asprintf(&fullpath, "%s%s", h->location, name); + fullpath = reg_path_win2unix(fullpath); - if(d) return reg_key_new_abs(name, h, d); - return NULL; + d = opendir(fullpath); + if(!d) { + DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); + SAFE_FREE(fullpath); + return NULL; + } + closedir(d); + + return reg_key_new_abs(name, h, fullpath); } static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) { - DIR *d = (DIR *)k->backend_data; struct dirent *e; int max = 200; + char *fullpath = k->backend_data; REG_KEY **ar; - if(!d) return False; - rewinddir(d); + DIR *d; (*count) = 0; ar = malloc(sizeof(REG_KEY *) * max); + + d = opendir(fullpath); + + if(!d) return False; while((e = readdir(d))) { if(e->d_type == DT_DIR && strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { - char *fullpath = reg_path_win2unix(strdup(k->path)); - ar[(*count)] = reg_key_new_rel(e->d_name, k, reg_dir_dir(k->handle, fullpath, e->d_name)); - free(fullpath); + char *newfullpath; + asprintf(&newfullpath, "%s/%s", fullpath, e->d_name); + ar[(*count)] = reg_key_new_rel(e->d_name, k, newfullpath); if(ar[(*count)])(*count)++; if((*count) == max) { @@ -101,6 +88,8 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) } } } + + closedir(d); *r = ar; return True; @@ -113,7 +102,7 @@ static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) { static void dir_free(REG_KEY *k) { - closedir((DIR *)k->backend_data); + free(k->backend_data); } static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) @@ -132,7 +121,7 @@ static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void * static BOOL reg_dir_del_value(REG_VAL *v) { - char *fullpath = reg_path_win2unix(strdup(reg_val_get_path(v))); + /* FIXME*/ return False; } diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 7e8ad9bf48..796d957076 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -230,9 +230,8 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) { struct winreg_EnumValue r; - struct winreg_EnumValueName name; struct winreg_Uint8buf value; - struct winreg_Uint16buf buf; + struct winreg_String valuename; struct rpc_data *mydata = parent->handle->backend_data; TALLOC_CTX *mem_ctx; uint32 type, requested_len, returned_len; @@ -241,6 +240,12 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) (*count) = 0; + /* Root */ + if(parent->backend_data == parent->handle->backend_data) { + *values = ar; + return True; + } + if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); if(!parent->backend_data) return False; @@ -248,16 +253,8 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) r.in.handle = parent->backend_data; r.in.enum_index = 0; - buf.max_len = 0x7fff; - buf.offset = 0; - buf.len = 0; - buf.buffer = NULL; - - name.len = 0; - name.max_len = buf.max_len *2; - name.buf = &buf; - - r.in.name = r.out.name = &name; + init_winreg_String(&valuename, NULL); + r.in.name = r.out.name = &valuename; type = 0; r.in.type = r.out.type = &type; @@ -280,7 +277,7 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { r.in.enum_index++; ar[(*count)] = reg_val_new(parent, NULL); - ar[(*count)]->name = strdup((char *)name.buf); + ar[(*count)]->name = strdup(r.out.name->name); ar[(*count)]->data_type = *r.out.type; ar[(*count)]->data_len = value.len; ar[(*count)]->data_blk = malloc(value.len); @@ -292,6 +289,8 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) talloc_destroy(mem_ctx); + *values = ar; + return True; } diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 070516b798..5e2b97cb98 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -23,14 +23,22 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) { - int i, numvals1, numvals2, numkeys2; + int i, numkeys1, numvals1, numvals2, numkeys2; + + numkeys1 = reg_key_num_subkeys(oldkey); + for(i = 0; i < numkeys1; i++) { + REG_KEY *t1 = reg_key_get_subkey_by_index(oldkey, i); + if(!reg_key_get_subkey_by_name(newkey, reg_key_name(t1))) { + fprintf(out, "-%s\n", reg_key_get_path(t1)+1); + } + } numkeys2 = reg_key_num_subkeys(newkey); for(i = 0; i < numkeys2; i++) { REG_KEY *t1 = reg_key_get_subkey_by_index(newkey, i); REG_KEY *t2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1)); if(!t2) { - fprintf(out, "[%s]\n", reg_key_get_path(t1)); + fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1); } writediff(t2, t1, out); } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index f76da7ebf9..27f578e37f 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -172,7 +172,7 @@ static struct cmd_line *get_cmd_line(int fd) while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') { if (ch == '\r') continue; /* skip CR */ - if (i == cl->len) { + if (i == cl->len-1) { /* * Allocate some more memory */ @@ -193,6 +193,7 @@ static struct cmd_line *get_cmd_line(int fd) return NULL; } + cl->line[i] = '\0'; cl->line_len = i; return cl; @@ -276,9 +277,9 @@ static char *parse_value(struct cmd_line *cl, int *vtype, char **val) char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL; if (!cl || !vtype || !val) return NULL; - if (!cl->line_len) return NULL; + if (!cl->line[0]) return NULL; - p1 = strndup(cl->line, cl->line_len); + p1 = strdup(cl->line); /* FIXME: Better return codes etc ... */ if (!p1) return NULL; p2 = strchr(p1, '='); @@ -380,7 +381,7 @@ static int regedit4_file_type(int fd) cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ if (cur_ofs < 0) { - DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); + DEBUG(0, ("Unable to get current offset: (%d) %s\n", cur_ofs, strerror(errno))); exit(1); /* FIXME */ } @@ -398,8 +399,7 @@ static int regedit4_file_type(int fd) if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) { if (cur_ofs) { lseek(fd, cur_ofs, SEEK_SET); - } - else { + } else { skip_to_eol(fd); } return FMT_REGEDIT4; @@ -420,47 +420,13 @@ static void strip_comment(struct cmd_line *cl) for (i = 0; i < cl->line_len; i++) { if (cl->line[i] == ';') { + cl->line[i] = '\0'; cl->line_len = i; return; } } } -/* - * trim leading space - */ - -static void trim_leading_spaces(struct cmd_line *cl) -{ - int i; - - if (!cl) return; - - for (i = 0; i < cl->line_len; i++) { - if (cl->line[i] != ' '){ - if (i) memcpy(cl->line, &cl->line[i], cl->line_len - i); - return; - } - } -} - -/* - * trim trailing spaces - */ -static void trim_trailing_spaces(struct cmd_line *cl) -{ - int i; - - if (!cl) return; - - for (i = cl->line_len; i == 0; i--) { - if (cl->line[i-1] != ' ' && - cl->line[i-1] != '\t') { - cl->line_len = i; - } - } -} - /* * Get a command ... This consists of possibly multiple lines: * [key] @@ -497,10 +463,9 @@ static CMD *regedit4_get_cmd(int fd) } strip_comment(cl); /* remove anything beyond a comment char */ - trim_trailing_spaces(cl); - trim_leading_spaces(cl); + trim_string(cl->line, " \t", " \t"); - if (cl->line_len == 0) { /* An empty line */ + if (!cl->line[0]) { /* An empty line */ free_cmd_line(cl); } else { /* Else, non-empty ... */ @@ -625,7 +590,7 @@ typedef struct command_file_s { * Create a new command file structure */ -static CMD_FILE *cmd_file_create(char *file) +static CMD_FILE *cmd_file_create(const char *file) { CMD_FILE *tmp; struct stat sbuf; @@ -637,7 +602,7 @@ static CMD_FILE *cmd_file_create(char *file) */ if (stat(file, &sbuf) < 0) { /* Not able to access file */ - + DEBUG(0,("Stat on %s failed\n", file)); return NULL; } @@ -650,6 +615,7 @@ static CMD_FILE *cmd_file_create(char *file) tmp->name = strdup(file); if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) { + DEBUG(0,("Error opening %s\n", file)); free(tmp); return NULL; } @@ -673,6 +639,7 @@ static CMD_FILE *cmd_file_create(char *file) */ free(tmp); + DEBUG(0,("Unknown type\n")); return NULL; } @@ -711,49 +678,51 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) */ switch (cmd->cmd) { case CMD_ADD_KEY: { - REG_KEY *tmp = NULL; - tmp = reg_open_key(reg_get_root(regf), cmd->key); - /* If we found it, apply the other bits, else create such a key */ - if (!tmp) { - if(reg_key_add_name(reg_get_root(regf), cmd->key)) { - tmp = reg_open_key(reg_get_root(regf), cmd->key); - } - modified = 1; - } - - while (cmd->val_count) { - VAL_SPEC_LIST *val = cmd->val_spec_list; - REG_VAL *reg_val = NULL; - - if (val->type == REG_DELETE) { - reg_val = reg_key_get_value_by_name( tmp, val->name); - reg_val_del(reg_val); - modified = 1; - } - else { - /* FIXME - reg_val = nt_add_reg_value(tmp, val->name, val->type, - val->val); */ - modified = 1; - } - - cmd->val_spec_list = val->next; - free_val_spec_list(val); - cmd->val_count--; - } - - break; + REG_KEY *tmp = NULL; + tmp = reg_open_key(reg_get_root(regf), cmd->key); + /* If we found it, apply the other bits, else create such a key */ + if (!tmp) { + if(reg_key_add_name_recursive(reg_get_root(regf), cmd->key)) { + tmp = reg_open_key(reg_get_root(regf), cmd->key); + } else { + DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); + } + modified = 1; + } + + while (cmd->val_count) { + VAL_SPEC_LIST *val = cmd->val_spec_list; + REG_VAL *reg_val = NULL; + + if (val->type == REG_DELETE) { + reg_val = reg_key_get_value_by_name( tmp, val->name); + reg_val_del(reg_val); + modified = 1; + } + else { + /* FIXME + reg_val = nt_add_reg_value(tmp, val->name, val->type, + val->val); */ + modified = 1; + } + + cmd->val_spec_list = val->next; + free_val_spec_list(val); + cmd->val_count--; + } + + break; } case CMD_DEL_KEY: - /* - * Any value does not matter ... - * Find the key if it exists, and delete it ... - */ - - reg_key_del_recursive(reg_open_key(reg_get_root(regf), cmd->key)); - modified = 1; - break; + /* + * Any value does not matter ... + * Find the key if it exists, and delete it ... + */ + + reg_key_del_recursive(reg_open_key(reg_get_root(regf), cmd->key)); + modified = 1; + break; } } free_cmd(cmd); @@ -779,7 +748,7 @@ int main (int argc, char **argv) }; pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); - + while((opt = poptGetNextOpt(pc)) != -1) { } @@ -797,12 +766,11 @@ int main (int argc, char **argv) return 1; } - poptFreeContext(pc); - patch = poptGetArg(pc); if(!patch) patch = "/dev/stdin"; + poptFreeContext(pc); nt_apply_reg_command_file(h, patch); - + return 0; } -- cgit From 5c49a23a298d37462fc81b470ac35a3fb0ff631e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Apr 2004 10:28:59 +0000 Subject: r36: - Start using memory pools in the registry library - Remove obsolete file (This used to be commit d85b8fb3b74b236fb03cf0931a0f585eec74536a) --- source4/lib/registry/common/reg_display.c | 60 ------------------- source4/lib/registry/common/reg_interface.c | 70 ++++++++++++---------- source4/lib/registry/common/reg_objects.c | 36 ++++++----- source4/lib/registry/common/reg_util.c | 9 ++- source4/lib/registry/common/registry.h | 3 + .../lib/registry/reg_backend_dir/reg_backend_dir.c | 28 ++++----- .../registry/reg_backend_gconf/reg_backend_gconf.c | 37 ++++++------ 7 files changed, 102 insertions(+), 141 deletions(-) delete mode 100644 source4/lib/registry/common/reg_display.c (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_display.c b/source4/lib/registry/common/reg_display.c deleted file mode 100644 index e12f4ba20e..0000000000 --- a/source4/lib/registry/common/reg_display.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Gerald Carter 2001 - Copyright (C) Tim Potter 2000 - Copyright (C) Jelmer Vernooij 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -void display_reg_value(REG_VAL *value) -{ - pstring text; - - switch(reg_val_type(value)) { - case REG_DWORD: - printf("%s: REG_DWORD: 0x%08x\n", reg_val_name(value), - *((uint32 *) reg_val_data_blk(value))); - break; - case REG_SZ: - rpcstr_pull(text, reg_val_data_blk(value), sizeof(text), reg_val_size(value), - STR_TERMINATE); - printf("%s: REG_SZ: %s\n", reg_val_name(value), text); - break; - case REG_BINARY: - printf("%s: REG_BINARY: unknown length value not displayed\n", - reg_val_name(value)); - break; - case REG_MULTI_SZ: { - uint16 *curstr = (uint16 *) reg_val_data_blk(value); - uint8 *start = reg_val_data_blk(value); - printf("%s: REG_MULTI_SZ:\n", reg_val_name(value)); - while ((*curstr != 0) && - ((uint8 *) curstr < start + reg_val_size(value))) { - rpcstr_pull(text, curstr, sizeof(text), -1, - STR_TERMINATE); - printf(" %s\n", text); - curstr += strlen(text) + 1; - } - } - break; - default: - printf("%s: unknown type %d\n", reg_val_name(value), reg_val_type(value)); - } - -} diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index d40a855f89..b6b38e9b62 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -55,7 +55,6 @@ NTSTATUS registry_register(void *_function) return NT_STATUS_OK; } - /* Find a backend in the list of available backends */ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { @@ -74,6 +73,7 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo { struct reg_init_function_entry *entry; static BOOL reg_first_init = True; + TALLOC_CTX *mem_ctx; REG_HANDLE *ret; if(reg_first_init) { @@ -91,12 +91,14 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); return NULL; } - - ret = malloc(sizeof(REG_HANDLE)); + + mem_ctx = talloc_init(backend); + ret = talloc(mem_ctx, sizeof(REG_HANDLE)); ZERO_STRUCTP(ret); - ret->location = location?strdup(location):NULL; + ret->location = location?talloc_strdup(mem_ctx, location):NULL; ret->functions = entry->functions; ret->backend_data = NULL; + ret->mem_ctx = mem_ctx; if(!entry->functions->open_registry) { return ret; @@ -105,15 +107,19 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo if(entry->functions->open_registry(ret, location, try_full_load)) return ret; - SAFE_FREE(ret); + talloc_destroy(mem_ctx); return NULL; } -/* Open a key */ +/* Open a key + * First tries to use the open_key function from the backend + * then falls back to get_subkey_by_name and later get_subkey_by_index + */ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) { char *fullname; REG_KEY *ret = NULL; + TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); @@ -131,16 +137,23 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) while(curbegin && *curbegin) { if(curend)*curend = '\0'; curkey = reg_key_get_subkey_by_name(curkey, curbegin); - if(!curkey) return NULL; + if(!curkey) { + SAFE_FREE(orig); + return NULL; + } if(!curend) break; curbegin = curend + 1; curend = strchr(curbegin, '\\'); } + SAFE_FREE(orig); return curkey; } - asprintf(&fullname, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); + mem_ctx = talloc_init("mem_ctx"); + + fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); + if(!parent->handle->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); @@ -152,8 +165,10 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) if(ret) { ret->handle = parent->handle; ret->path = fullname; - } else - SAFE_FREE(fullname); + talloc_steal(mem_ctx, ret->mem_ctx, fullname); + } + + talloc_destroy(mem_ctx); return ret; } @@ -241,7 +256,7 @@ REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx) } if(ret && !ret->path) { - asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); ret->handle = key->handle; } @@ -270,7 +285,7 @@ REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name) } if(ret && !ret->path) { - asprintf(&ret->path, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); ret->handle = key->handle; } @@ -310,7 +325,9 @@ BOOL reg_key_del(REG_KEY *key) { if(key->handle->functions->del_key) { if(key->handle->functions->del_key(key)) { - free_cached_keys(key); + /* Invalidate cache */ + key->cache_subkeys = NULL; + key->cache_subkeys_count = 0; return True; } } @@ -356,7 +373,8 @@ BOOL reg_val_del(REG_VAL *val) } if(val->handle->functions->del_value(val)) { - free_cached_values(val->parent); + val->parent->cache_values = NULL; + val->parent->cache_values_count = 0; return True; } return False; @@ -398,7 +416,8 @@ BOOL reg_key_add_name(REG_KEY *parent, const char *name) } if(parent->handle->functions->add_key(parent, name)) { - free_cached_keys(parent); + parent->cache_subkeys = NULL; + parent->cache_subkeys_count = 0; return True; } return False; @@ -419,7 +438,8 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) new = val->handle->functions->add_value(val->parent, val->name, type, data, len); memcpy(val, new, sizeof(REG_VAL)); - free_cached_values(val->parent); + val->parent->cache_values = NULL; + val->parent->cache_values_count = 0; return True; } @@ -447,7 +467,7 @@ REG_KEY *reg_get_root(REG_HANDLE *h) if(ret) { ret->handle = h; - ret->path = strdup("\\"); + ret->path = talloc_strdup(ret->mem_ctx, "\\"); } return ret; @@ -462,19 +482,9 @@ REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value ret = key->handle->functions->add_value(key, name, type, value, vallen); ret->parent = key; ret->handle = key->handle; - free_cached_values(key); - return ret; -} -void free_cached_values(REG_KEY *key) -{ - free(key->cache_values); key->cache_values = NULL; + /* Invalidate the cache */ + key->cache_values = NULL; key->cache_values_count = 0; -} - - -void free_cached_keys(REG_KEY *key) -{ - free(key->cache_subkeys); key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; + return ret; } diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 8de0065da0..809829b3e8 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -35,11 +35,12 @@ REG_VAL* reg_val_dup( REG_VAL *val ) { REG_VAL *copy = NULL; + TALLOC_CTX *new_mem_ctx = talloc_init(val->name); if ( !val ) return NULL; - if ( !(copy = malloc( sizeof(REG_VAL) )) ) { + if ( !(copy = talloc( new_mem_ctx, sizeof(REG_VAL) )) ) { DEBUG(0,("dup_registry_value: malloc() failed!\n")); return NULL; } @@ -49,12 +50,13 @@ REG_VAL* reg_val_dup( REG_VAL *val ) memcpy( copy, val, sizeof(REG_VAL) ); if ( val->data_blk ) { - if ( !(copy->data_blk = memdup( val->data_blk, val->data_len )) ) { + if ( !(copy->data_blk = talloc_memdup( new_mem_ctx, val->data_blk, val->data_len )) ) { DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n", val->data_len)); SAFE_FREE( copy ); } } + copy->mem_ctx = new_mem_ctx; return copy; } @@ -71,8 +73,7 @@ void reg_val_free( REG_VAL *val ) if(val->handle->functions->free_val_backend_data) val->handle->functions->free_val_backend_data(val); - SAFE_FREE( val->data_blk ); - SAFE_FREE( val ); + talloc_destroy( val->mem_ctx ); return; } @@ -139,7 +140,6 @@ void reg_key_free(REG_KEY *key) for(i = 0; i < key->cache_values_count; i++) { reg_val_free(key->cache_values[i]); } - SAFE_FREE(key->cache_values); } if(key->cache_subkeys) { @@ -147,12 +147,9 @@ void reg_key_free(REG_KEY *key) for(i = 0; i < key->cache_subkeys_count; i++) { reg_key_free(key->cache_subkeys[i]); } - SAFE_FREE(key->cache_subkeys); } - SAFE_FREE(key->path); - SAFE_FREE(key->name); - SAFE_FREE(key); + talloc_destroy(key->mem_ctx); } char *reg_val_get_path(REG_VAL *v) @@ -170,11 +167,14 @@ const char *reg_key_get_path(REG_KEY *k) /* For use by the backends _ONLY_ */ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) { - REG_KEY *r = malloc(sizeof(REG_KEY)); + REG_KEY *r; + TALLOC_CTX *mem_ctx = talloc_init(path); + r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = h; - r->path = strdup(path); - r->name = strdup(strrchr(path, '\\')?strrchr(path,'\\')+1:path); + r->mem_ctx = mem_ctx; + r->path = talloc_strdup(mem_ctx, path); + r->name = talloc_strdup(mem_ctx, strrchr(path, '\\')?strrchr(path,'\\')+1:path); r->backend_data = data; r->ref = 1; return r; @@ -182,19 +182,25 @@ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) { - REG_KEY *r = malloc(sizeof(REG_KEY)); + REG_KEY *r; + TALLOC_CTX *mem_ctx = talloc_init(name); + r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = k->handle; - r->name = strdup(name); + r->name = talloc_strdup(mem_ctx, name); r->backend_data = data; + r->mem_ctx = mem_ctx; r->ref = 1; return r; } REG_VAL *reg_val_new(REG_KEY *parent, void *data) { - REG_VAL *r = malloc(sizeof(REG_VAL)); + REG_VAL *r; + TALLOC_CTX *mem_ctx = talloc_init("value"); + r = talloc(mem_ctx, sizeof(REG_VAL)); ZERO_STRUCTP(r); + r->mem_ctx = mem_ctx; r->handle = parent->handle; r->backend_data = data; r->ref = 1; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 2941c38cf4..060d053fc2 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -82,7 +82,7 @@ char *reg_val_data_string(REG_VAL *v) return ret; } -const char *reg_val_description(REG_VAL *val) +char *reg_val_description(REG_VAL *val) { char *ret, *ds = reg_val_data_string(val); asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"", str_regtype(reg_val_type(val)), ds); @@ -145,6 +145,9 @@ BOOL reg_split_path( char *path, char **base, char **new_path ) return True; } +/** + * Replace all \'s with /'s + */ char *reg_path_win2unix(char *path) { int i; @@ -153,7 +156,9 @@ char *reg_path_win2unix(char *path) } return path; } - +/** + * Replace all /'s with \'s + */ char *reg_path_unix2win(char *path) { int i; diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 4b29006217..3565a7a585 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -40,6 +40,7 @@ struct reg_key_s { int cache_values_count; REG_KEY **cache_subkeys; int cache_subkeys_count; + TALLOC_CTX *mem_ctx; int ref; }; @@ -52,6 +53,7 @@ struct reg_val_s { REG_HANDLE *handle; REG_KEY *parent; void *backend_data; + TALLOC_CTX *mem_ctx; int ref; }; @@ -107,6 +109,7 @@ struct reg_handle_s { REG_SUBTREE *subtrees; char *location; void *backend_data; + TALLOC_CTX *mem_ctx; }; struct reg_init_function_entry { diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 5fec782e95..9cb15cd285 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -28,7 +28,7 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name); path = reg_path_win2unix(path); ret = mkdir(path, 0700); - free(path); + SAFE_FREE(path); return (ret == 0); } @@ -41,22 +41,26 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) { DIR *d; char *fullpath; + REG_KEY *ret; + TALLOC_CTX *mem_ctx = talloc_init("tmp"); if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); return NULL; } - asprintf(&fullpath, "%s%s", h->location, name); + fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); d = opendir(fullpath); if(!d) { DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); - SAFE_FREE(fullpath); + talloc_destroy(mem_ctx); return NULL; } closedir(d); - - return reg_key_new_abs(name, h, fullpath); + ret = reg_key_new_abs(name, h, fullpath); + talloc_steal(mem_ctx, ret->mem_ctx, fullpath); + talloc_destroy(mem_ctx); + return ret; } static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) @@ -67,7 +71,7 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) REG_KEY **ar; DIR *d; (*count) = 0; - ar = malloc(sizeof(REG_KEY *) * max); + ar = talloc(k->mem_ctx, sizeof(REG_KEY *) * max); d = opendir(fullpath); @@ -78,8 +82,8 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { char *newfullpath; - asprintf(&newfullpath, "%s/%s", fullpath, e->d_name); - ar[(*count)] = reg_key_new_rel(e->d_name, k, newfullpath); + ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); + ar[(*count)]->backend_data = talloc_asprintf(ar[*count]->mem_ctx, "%s/%s", fullpath, e->d_name); if(ar[(*count)])(*count)++; if((*count) == max) { @@ -100,17 +104,12 @@ static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) { return True; } -static void dir_free(REG_KEY *k) -{ - free(k->backend_data); -} - static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) { REG_VAL *ret = reg_val_new(p, NULL); char *fullpath; FILE *fd; - ret->name = name?strdup(name):NULL; + ret->name = name?talloc_strdup(ret->mem_ctx, name):NULL; fullpath = reg_path_win2unix(strdup(reg_val_get_path(ret))); fd = fopen(fullpath, "w+"); @@ -134,7 +133,6 @@ static REG_OPS reg_backend_dir = { .del_key = reg_dir_del_key, .add_value = reg_dir_add_value, .del_value = reg_dir_del_value, - .free_key_backend_data = dir_free }; NTSTATUS reg_dir_init(void) diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 14da2f54e9..71d3361ce2 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -35,34 +35,35 @@ static BOOL reg_close_gconf(REG_HANDLE *h) static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name) { + REG_KEY *ret; char *fullpath = reg_path_win2unix(strdup(name)); /* Check if key exists */ if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { - free(fullpath); + SAFE_FREE(fullpath); return NULL; } - free(fullpath); + ret = reg_key_new_abs(name, h, NULL); + ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath); + SAFE_FREE(fullpath); - return reg_key_new_abs(name, h, NULL); + return ret; } static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) { GSList *entries; GSList *cur; - REG_VAL **ar = malloc(sizeof(REG_VAL *)); - char *fullpath = strdup(reg_key_get_path(p)); - fullpath = reg_path_win2unix(fullpath); + REG_VAL **ar = talloc(p->mem_ctx, sizeof(REG_VAL *)); + char *fullpath = p->backend_data; cur = entries = gconf_client_all_entries((GConfClient*)p->handle->backend_data, fullpath, NULL); - free(fullpath); (*count) = 0; while(cur) { GConfEntry *entry = cur->data; GConfValue *value = gconf_entry_get_value(entry); REG_VAL *newval = reg_val_new(p, NULL); - newval->name = strdup(strrchr(gconf_entry_get_key(entry), '/')+1); + newval->name = talloc_strdup(newval->mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); if(value) { switch(value->type) { case GCONF_VALUE_INVALID: @@ -71,26 +72,26 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) case GCONF_VALUE_STRING: newval->data_type = REG_SZ; - newval->data_blk = strdup(gconf_value_get_string(value)); + newval->data_blk = talloc_strdup(newval->mem_ctx, gconf_value_get_string(value)); newval->data_len = strlen(newval->data_blk); break; case GCONF_VALUE_INT: newval->data_type = REG_DWORD; - newval->data_blk = malloc(sizeof(long)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(long)); *((long *)newval->data_blk) = gconf_value_get_int(value); newval->data_len = sizeof(long); break; case GCONF_VALUE_FLOAT: - newval->data_blk = malloc(sizeof(double)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(double)); newval->data_type = REG_BINARY; *((double *)newval->data_blk) = gconf_value_get_float(value); newval->data_len = sizeof(double); break; case GCONF_VALUE_BOOL: - newval->data_blk = malloc(sizeof(BOOL)); + newval->data_blk = talloc(newval->mem_ctx, sizeof(BOOL)); newval->data_type = REG_BINARY; *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); newval->data_len = sizeof(BOOL); @@ -104,7 +105,7 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) } else newval->data_type = REG_NONE; ar[(*count)] = newval; - ar = realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); + ar = talloc_realloc(p->mem_ctx, ar, sizeof(REG_VAL *) * ((*count)+2)); (*count)++; g_free(cur->data); cur = cur->next; @@ -120,14 +121,13 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) GSList *dirs; GSList *cur; REG_KEY **ar = malloc(sizeof(REG_KEY *)); - char *fullpath = strdup(reg_key_get_path(p)); - fullpath = reg_path_win2unix(fullpath); + char *fullpath = p->backend_data; cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); - free(fullpath); (*count) = 0; while(cur) { - ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle, NULL); + ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle,NULL); + ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, cur->data); ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+2)); (*count)++; g_free(cur->data); @@ -142,11 +142,10 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len) { GError *error = NULL; - char *keypath = reg_path_win2unix(strdup(reg_key_get_path(val->parent))); + char *keypath = val->backend_data; char *valpath; if(val->name)asprintf(&valpath, "%s/%s", keypath, val->name); else valpath = strdup(keypath); - free(keypath); switch(type) { case REG_SZ: -- cgit From 381a903d00ccbc3e80e8eca533d304fed6c13870 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 5 Apr 2004 12:26:23 +0000 Subject: r42: importing .cvsignore files (This used to be commit 11717ae912449bde596ff6cf7d8fddcc86548f15) --- source4/lib/.cvsignore | 3 --- source4/lib/ldb/ldb_tdb/.cvsignore | 7 ------- 2 files changed, 10 deletions(-) delete mode 100644 source4/lib/.cvsignore delete mode 100644 source4/lib/ldb/ldb_tdb/.cvsignore (limited to 'source4/lib') diff --git a/source4/lib/.cvsignore b/source4/lib/.cvsignore deleted file mode 100644 index 07da2225c7..0000000000 --- a/source4/lib/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -*.po -*.po32 - diff --git a/source4/lib/ldb/ldb_tdb/.cvsignore b/source4/lib/ldb/ldb_tdb/.cvsignore deleted file mode 100644 index 8f968d06f4..0000000000 --- a/source4/lib/ldb/ldb_tdb/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -ldbadd -ldbsearch -ldbdel -test.ldb -TAGS -.*~ -*.o -- cgit From 2542ed0ac75d545eef3571bfb19fb39a5b71beb3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Apr 2004 13:50:45 +0000 Subject: r46: Add CreateKey function (still working on it) (This used to be commit 9f13b7c60cc7e6edd095eee96625ee02cd0dd73b) --- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 44 ++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 796d957076..84c3cb8aee 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -39,7 +39,6 @@ static void init_winreg_String(struct winreg_String *name, const char *s) struct winreg_Open ## u r; \ struct winreg_OpenUnknown unknown; \ struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \ - TALLOC_CTX *mem_ctx = talloc_init("openhive"); \ \ unknown.unknown0 = 0x84e0; \ unknown.unknown1 = 0x0000; \ @@ -47,12 +46,10 @@ static void init_winreg_String(struct winreg_String *name, const char *s) r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ - if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, mem_ctx, &r))) {\ + if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\ printf("Error executing open\n");\ return NULL;\ }\ -\ - talloc_destroy(mem_ctx);\ \ return hnd;\ } @@ -83,7 +80,7 @@ struct { static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full) { BOOL res = True; - struct rpc_data *mydata = malloc(sizeof(struct rpc_data)); + struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data)); char *binding = strdup(location); NTSTATUS status; @@ -124,7 +121,7 @@ static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path) char *end = strchr(path+1, '\\'); NTSTATUS status; struct winreg_OpenKey r; - struct policy_handle *key_handle = malloc(sizeof(struct policy_handle)); + struct policy_handle *key_handle = talloc(h->mem_ctx, sizeof(struct policy_handle)); TALLOC_CTX *mem_ctx; if(end) hivename = strndup(path+1, end-path-1); @@ -177,17 +174,16 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) struct winreg_Time tm; struct rpc_data *mydata = parent->handle->backend_data; int i; - REG_KEY **ar = malloc(sizeof(REG_KEY *)); + REG_KEY **ar = talloc(parent->mem_ctx, sizeof(REG_KEY *)); NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *mem_ctx; /* List the hives */ if(parent->backend_data == parent->handle->backend_data) { - REG_KEY **ar = malloc(sizeof(REG_KEY *)); for(i = 0; known_hives[i].name; i++) { ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL); (*count)++; - ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+1)); + ar = talloc_realloc(parent->mem_ctx, ar, sizeof(REG_KEY *) * ((*count)+1)); } *subkeys = ar; @@ -199,7 +195,6 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) if(!parent->backend_data) return False; - mem_ctx = talloc_init("enumkey"); (*count) = 0; r.in.handle = parent->backend_data; keyname.unknown = 0x0000020a; @@ -215,11 +210,11 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) r.in.enum_index = i; r.in.unknown = r.out.unknown = 0x0414; r.in.key_name_len = r.out.key_name_len = 0; - status = dcerpc_winreg_EnumKey(mydata->pipe, mem_ctx, &r); + status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL); (*count)++; - ar = realloc(ar, ((*count)+1) * sizeof(REG_KEY *)); + ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_KEY *)); } } @@ -271,29 +266,38 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) r.in.returned_len = &returned_len; r.out.result.v = 0; - mem_ctx = talloc_init("fetchvalues"); while(1) { - status = dcerpc_winreg_EnumValue(mydata->pipe, mem_ctx, &r); + status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { r.in.enum_index++; ar[(*count)] = reg_val_new(parent, NULL); - ar[(*count)]->name = strdup(r.out.name->name); + ar[(*count)]->name = talloc_strdup(ar[*count]->mem_ctx, r.out.name->name); ar[(*count)]->data_type = *r.out.type; ar[(*count)]->data_len = value.len; - ar[(*count)]->data_blk = malloc(value.len); + ar[(*count)]->data_blk = talloc(ar[*count]->mem_ctx, value.len); memcpy(ar[(*count)]->data_blk, value.buffer, value.len); (*count)++; - ar = realloc(ar, ((*count)+1) * sizeof(REG_VAL *)); + ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_VAL *)); } else break; } - talloc_destroy(mem_ctx); - *values = ar; return True; } +static BOOL rpc_add_key(REG_KEY *parent, const char *name) +{ + /* FIXME */ + return False; +} + +static BOOL rpc_del_key(REG_KEY *k) +{ + /* FIXME */ + return False; +} + static REG_OPS reg_backend_rpc = { .name = "rpc", .open_registry = rpc_open_registry, @@ -302,6 +306,8 @@ static REG_OPS reg_backend_rpc = { .open_key = rpc_open_key, .fetch_subkeys = rpc_fetch_subkeys, .fetch_values = rpc_fetch_values, + .add_key = rpc_add_key, + .del_key = rpc_del_key, }; NTSTATUS reg_rpc_init(void) -- cgit From b96025eb15e3648e77e0e6aa343e23ca2f1156da Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Apr 2004 20:44:33 +0000 Subject: r61: - Implement first call in the winreg rpc server - Add some initial implementation of the ldb backend - More checks in the winreg torture test (This used to be commit ae2b63b6f1821bc4f693cb8e2a5f78718c483c24) --- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 19 ++++++++++++++++++- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 75d5a95187..afa60c5c4a 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -43,9 +43,25 @@ static BOOL ldb_close_registry(REG_HANDLE *h) return True; } +static BOOL ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) +{ + ldb_search(); +} + static REG_KEY *ldb_open_key(REG_HANDLE *h, const char *name) { - /* FIXME */ + struct ldb_context *c = h->backend_data; + char *path; + struct ldb_message **msg; + REG_KEY *key = NULL; + (dn=key=Systems, + if(ldb_search(c, NULL, LDP_SCOPE_BASE, "", NULL,&msg) > 0) { + key = reg_key_new_abs(name, h, base); + } + + ldap_search_free(c, msg); + + return key; } static REG_OPS reg_backend_ldb = { @@ -53,6 +69,7 @@ static REG_OPS reg_backend_ldb = { .open_registry = ldb_open_registry, .close_registry = ldb_close_registry, .open_key = ldb_open_key, + .fetch_subkeys = ldb_fetch_subkeys, }; NTSTATUS reg_ldb_init(void) diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 84c3cb8aee..ad4d537f9b 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -90,7 +90,7 @@ static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), - "jelwin", "dds"); + "tridge", "samba"); if(!NT_STATUS_IS_OK(status)) return False; -- cgit From 509bbf4383f2aad2f2b86b021430ef5a2df935c2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 8 Apr 2004 17:42:03 +0000 Subject: r125: use AC_CONFIG_FILES() instead of AC_OUTPUT() we should have only one AC_OUTPUT() at the end of configure.in metze (This used to be commit 60aa14d463fcd7aa12529f1fad0db64f17e37aaf) --- source4/lib/registry/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 277fd30dd1..146ef92b95 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -13,4 +13,4 @@ SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[]) -AC_OUTPUT(lib/registry/winregistry.pc) +AC_CONFIG_FILES(lib/registry/winregistry.pc) -- cgit From aebfb3b9f415d3c1f6b2a39aee27b072d48893cb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 8 Apr 2004 22:39:47 +0000 Subject: r128: Another registry update. Changes: - Start with the LDB backend - The API is now more windows-like, which should make it easier to use in rpc_server - Added a GTK+ front-end - Added some more IDL More updates will follow, especially in the RPC field.. (This used to be commit 3adffa021779b26047a20f16a3c0b53d74751560) --- source4/lib/ldb/include/proto.h | 126 ---- source4/lib/registry/TODO | 18 +- source4/lib/registry/common/reg_interface.c | 368 +++++----- source4/lib/registry/common/reg_util.c | 22 +- source4/lib/registry/common/registry.h | 55 +- source4/lib/registry/config.m4 | 3 + .../lib/registry/reg_backend_dir/reg_backend_dir.c | 46 +- .../registry/reg_backend_gconf/reg_backend_gconf.c | 54 +- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 75 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 106 +-- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 85 ++- .../registry/reg_backend_wine/reg_backend_wine.c | 1 + source4/lib/registry/tools/gregedit.c | 758 +++++++++++++++++++++ source4/lib/registry/tools/regshell.c | 1 + 14 files changed, 1266 insertions(+), 452 deletions(-) create mode 100644 source4/lib/registry/tools/gregedit.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/proto.h b/source4/lib/ldb/include/proto.h index 8690d96fee..e69de29bb2 100644 --- a/source4/lib/ldb/include/proto.h +++ b/source4/lib/ldb/include/proto.h @@ -1,126 +0,0 @@ -#ifndef _PROTO_H_ -#define _PROTO_H_ - -/* This file is automatically generated with "make proto". DO NOT EDIT */ - - -/* The following definitions come from common/ldb.c */ - -struct ldb_context *ldb_connect(const char *url, unsigned int flags, - const char *options[]); -int ldb_close(struct ldb_context *ldb); -int ldb_search(struct ldb_context *ldb, - const char *base, - enum ldb_scope scope, - const char *expression, - const char *attrs[], struct ldb_message ***res); -int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); -int ldb_add(struct ldb_context *ldb, - const struct ldb_message *message); -int ldb_modify(struct ldb_context *ldb, - const struct ldb_message *message); -int ldb_delete(struct ldb_context *ldb, const char *dn); -const char *ldb_errstring(struct ldb_context *ldb); - -/* The following definitions come from common/ldb_ldif.c */ - -char *ldb_base64_encode(const char *buf, int len); -int ldb_should_b64_encode(const struct ldb_val *val); -int ldif_write(int (*fprintf_fn)(void *, const char *, ...), - void *private, - const struct ldb_message *msg); -void ldif_read_free(struct ldb_message *msg); -struct ldb_message *ldif_read(int (*fgetc_fn)(void *), void *private); -struct ldb_message *ldif_read_file(FILE *f); -struct ldb_message *ldif_read_string(const char *s); -int ldif_write_file(FILE *f, const struct ldb_message *msg); - -/* The following definitions come from common/ldb_parse.c */ - -struct ldb_parse_tree *ldb_parse_tree(const char *s); -void ldb_parse_tree_free(struct ldb_parse_tree *tree); - -/* The following definitions come from common/util.c */ - -void *realloc_array(void *ptr, size_t el_size, unsigned count); -int list_find(const void *needle, - const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn); - -/* The following definitions come from ldb_ldap/ldb_ldap.c */ - -struct ldb_context *lldb_connect(const char *url, - unsigned int flags, - const char *options[]); - -/* The following definitions come from ldb_tdb/ldb_index.c */ - -int ltdb_search_indexed(struct ldb_context *ldb, - const char *base, - enum ldb_scope scope, - struct ldb_parse_tree *tree, - const char *attrs[], struct ldb_message ***res); -int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg); -int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg); - -/* The following definitions come from ldb_tdb/ldb_match.c */ - -int ldb_message_match(struct ldb_context *ldb, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope); - -/* The following definitions come from ldb_tdb/ldb_pack.c */ - -int ltdb_pack_data(struct ldb_context *ctx, - const struct ldb_message *message, - struct TDB_DATA *data); -int ltdb_unpack_data(struct ldb_context *ctx, - const struct TDB_DATA *data, - struct ldb_message *message); - -/* The following definitions come from ldb_tdb/ldb_search.c */ - -int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr); -int ltdb_has_wildcard(const struct ldb_val *val); -void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg); -int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg); -int ltdb_search_dn(struct ldb_context *ldb, char *dn, - const char *attrs[], struct ldb_message ***res); -int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, - const char *attrs[], - unsigned int *count, - struct ldb_message ***res); -int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); -int ltdb_search(struct ldb_context *ldb, const char *base, - enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res); - -/* The following definitions come from ldb_tdb/ldb_tdb.c */ - -struct TDB_DATA ltdb_key(const char *dn); -int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs); -int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn); -struct ldb_context *ltdb_connect(const char *url, - unsigned int flags, - const char *options[]); - -/* The following definitions come from ldb_tdb/ldbadd.c */ - - -/* The following definitions come from ldb_tdb/ldbdel.c */ - - -/* The following definitions come from ldb_tdb/ldbsearch.c */ - - -/* The following definitions come from tools/ldbadd.c */ - - -/* The following definitions come from tools/ldbdel.c */ - - -/* The following definitions come from tools/ldbsearch.c */ - - -#endif /* _PROTO_H_ */ diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index ac467d0078..fc741cea40 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -1,10 +1,6 @@ - support subtrees -- ../../, /bla/blie support in regshell -- use memory pools? -- get rid of all the nasty memory leaks.. -- security stuff -- clean up code -- rpc_server +- ..\..\, \bla\blie support in regshell +- finish rpc_server reg_backend_dir: - value support @@ -15,9 +11,15 @@ reg_backend_nt4: reg_backend_rpc: - value enum support - write support + - rewrite reg_backend_ldb: - - implement + - finish reg_backend_wine.c: - - implement + - finish + +gregedit.c: + - support for editing values / adding values / deleting values + - support for adding/deleting keys + - support for security descriptors diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index b6b38e9b62..9c78ae55fb 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -32,7 +32,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name); /* Register new backend */ NTSTATUS registry_register(void *_function) { - REG_OPS *functions = _function; + struct registry_ops *functions = _function; struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { @@ -69,17 +69,19 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) } /* Open a registry file/host/etc */ -REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_load) +WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h) { struct reg_init_function_entry *entry; static BOOL reg_first_init = True; TALLOC_CTX *mem_ctx; REG_HANDLE *ret; + NTSTATUS status; + WERROR werr; if(reg_first_init) { - if (!NT_STATUS_IS_OK(register_subsystem("registry", registry_register))) { - return False; - } + status = register_subsystem("registry", registry_register); + if (!NT_STATUS_IS_OK(status)) + return WERR_GENERAL_FAILURE; static_init_reg; reg_first_init = False; @@ -89,7 +91,7 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo if (!entry) { DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); - return NULL; + return WERR_GENERAL_FAILURE; } mem_ctx = talloc_init(backend); @@ -99,31 +101,35 @@ REG_HANDLE *reg_open(const char *backend, const char *location, BOOL try_full_lo ret->functions = entry->functions; ret->backend_data = NULL; ret->mem_ctx = mem_ctx; + *h = ret; if(!entry->functions->open_registry) { - return ret; + return WERR_OK; } - if(entry->functions->open_registry(ret, location, try_full_load)) - return ret; + werr = entry->functions->open_registry(ret, location, credentials); + + if(W_ERROR_IS_OK(werr)) + return WERR_OK; talloc_destroy(mem_ctx); - return NULL; + return werr; } /* Open a key * First tries to use the open_key function from the backend * then falls back to get_subkey_by_name and later get_subkey_by_index */ -REG_KEY *reg_open_key(REG_KEY *parent, const char *name) +WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) { char *fullname; + WERROR status; REG_KEY *ret = NULL; TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); - return NULL; + return WERR_INVALID_PARAM; } if(!parent->handle->functions->open_key && @@ -136,10 +142,10 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) while(curbegin && *curbegin) { if(curend)*curend = '\0'; - curkey = reg_key_get_subkey_by_name(curkey, curbegin); - if(!curkey) { + status = reg_key_get_subkey_by_name(curkey, curbegin, result); + if(!NT_STATUS_IS_OK(status)) { SAFE_FREE(orig); - return NULL; + return status; } if(!curend) break; curbegin = curend + 1; @@ -147,255 +153,287 @@ REG_KEY *reg_open_key(REG_KEY *parent, const char *name) } SAFE_FREE(orig); - return curkey; + *result = curkey; + return WERR_OK; } mem_ctx = talloc_init("mem_ctx"); fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); - +\ if(!parent->handle->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); - return NULL; + return WERR_NOT_SUPPORTED; } - ret = parent->handle->functions->open_key(parent->handle, fullname); + status = parent->handle->functions->open_key(parent->handle, fullname, result); - if(ret) { - ret->handle = parent->handle; - ret->path = fullname; - talloc_steal(mem_ctx, ret->mem_ctx, fullname); + if(!NT_STATUS_IS_OK(status)) { + talloc_destroy(mem_ctx); + return status; } + + ret->handle = parent->handle; + ret->path = fullname; + talloc_steal(mem_ctx, ret->mem_ctx, fullname); talloc_destroy(mem_ctx); - return ret; + *result = ret; + + return WERR_OK; } -REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx) +WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) { - REG_VAL *ret; - - if(!key) return NULL; + if(!key) return WERR_INVALID_PARAM; if(!key->handle->functions->get_value_by_index) { if(!key->cache_values) key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); if(idx < key->cache_values_count && idx >= 0) { - ret = reg_val_dup(key->cache_values[idx]); + *val = reg_val_dup(key->cache_values[idx]); } else { - return NULL; + return WERR_NO_MORE_ITEMS; } } else { - ret = key->handle->functions->get_value_by_index(key, idx); + WERROR status = key->handle->functions->get_value_by_index(key, idx, val); + if(!W_ERROR_IS_OK(status)) + return status; } - if(ret) { - ret->parent = key; - ret->handle = key->handle; - } - - return ret; + (*val)->parent = key; + (*val)->handle = key->handle; + return WERR_OK; } -int reg_key_num_subkeys(REG_KEY *key) +WERROR reg_key_num_subkeys(REG_KEY *key, int *count) { - if(!key) return 0; + if(!key) return WERR_INVALID_PARAM; if(!key->handle->functions->num_subkeys) { if(!key->cache_subkeys) key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); - return key->cache_subkeys_count; + *count = key->cache_subkeys_count; + return WERR_OK; } - return key->handle->functions->num_subkeys(key); + return key->handle->functions->num_subkeys(key, count); } -int reg_key_num_values(REG_KEY *key) +WERROR reg_key_num_values(REG_KEY *key, int *count) { - if(!key) return 0; + if(!key) return WERR_INVALID_PARAM; if(!key->handle->functions->num_values) { if(!key->handle->functions->fetch_values) { DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); - return 0; + return WERR_NOT_SUPPORTED; } if(!key->cache_values) key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); - return key->cache_values_count; + *count = key->cache_values_count; + return WERR_OK; } - return key->handle->functions->num_values(key); + return key->handle->functions->num_values(key, count); } -REG_KEY *reg_key_get_subkey_by_index(REG_KEY *key, int idx) +WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) { - REG_KEY *ret = NULL; - - if(!key) return NULL; + if(!key) return WERR_INVALID_PARAM; if(!key->handle->functions->get_subkey_by_index) { if(!key->cache_subkeys) key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); if(idx < key->cache_subkeys_count) { - ret = reg_key_dup(key->cache_subkeys[idx]); + *subkey = reg_key_dup(key->cache_subkeys[idx]); } else { - /* No such key ! */ - return NULL; + return WERR_NO_MORE_ITEMS; } } else { - ret = key->handle->functions->get_subkey_by_index(key, idx); + WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); + if(!NT_STATUS_IS_OK(status)) return status; } - if(ret && !ret->path) { - ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); - ret->handle = key->handle; - } + (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); + (*subkey)->handle = key->handle; - return ret; + + return WERR_OK;; } -REG_KEY *reg_key_get_subkey_by_name(REG_KEY *key, const char *name) +WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey) { - int i, max; + int i; REG_KEY *ret = NULL; + WERROR error = WERR_OK; - if(!key) return NULL; + if(!key) return WERR_INVALID_PARAM; if(key->handle->functions->get_subkey_by_name) { - ret = key->handle->functions->get_subkey_by_name(key,name); + error = key->handle->functions->get_subkey_by_name(key,name,subkey); } else { - max = reg_key_num_subkeys(key); - for(i = 0; i < max; i++) { - REG_KEY *v = reg_key_get_subkey_by_index(key, i); - if(v && !strcmp(v->name, name)) { - ret = v; + for(i = 0; W_ERROR_IS_OK(error); i++) { + error = reg_key_get_subkey_by_index(key, i, subkey); + if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { break; } - reg_key_free(v); + reg_key_free(*subkey); } - } - if(ret && !ret->path) { - ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); - ret->handle = key->handle; } + + if(!W_ERROR_IS_OK(error) && W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + return error; + + ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); + ret->handle = key->handle; + + *subkey = ret; - return ret; + return WERR_OK; } -REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name) +WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) { int i, max; REG_VAL *ret = NULL; + WERROR error = WERR_OK; - if(!key) return NULL; + if(!key) return WERR_INVALID_PARAM; if(key->handle->functions->get_value_by_name) { - ret = key->handle->functions->get_value_by_name(key,name); + error = key->handle->functions->get_value_by_name(key,name, val); } else { - max = reg_key_num_values(key); - for(i = 0; i < max; i++) { - REG_VAL *v = reg_key_get_value_by_index(key, i); - if(v && StrCaseCmp(v->name, name)) { - ret = v; + for(i = 0; W_ERROR_IS_OK(error); i++) { + error = reg_key_get_value_by_index(key, i, val); + if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) { break; } - reg_val_free(v); + reg_val_free(*val); } } + + if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + return error; - if(ret) { - ret->parent = key; - ret->handle = key->handle; - } + (*val)->parent = key; + (*val)->handle = key->handle; - return ret; + return WERR_OK; } -BOOL reg_key_del(REG_KEY *key) +WERROR reg_key_del(REG_KEY *key) { - if(key->handle->functions->del_key) { - if(key->handle->functions->del_key(key)) { - /* Invalidate cache */ - key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; - return True; - } - } + WERROR error; + if(!key) return WERR_INVALID_PARAM; + + + if(!key->handle->functions->del_key) + return WERR_NOT_SUPPORTED; + + error = key->handle->functions->del_key(key); + if(!W_ERROR_IS_OK(error)) return error; - return False; + /* Invalidate cache */ + key->cache_subkeys = NULL; + key->cache_subkeys_count = 0; + return WERR_OK; } -BOOL reg_sync(REG_HANDLE *h, const char *location) +WERROR reg_sync(REG_KEY *h, const char *location) { - if(!h->functions->sync) - return True; + if(!h->handle->functions->sync_key) + return WERR_OK; - return h->functions->sync(h, location); + return h->handle->functions->sync_key(h, location); } -BOOL reg_key_del_recursive(REG_KEY *key) +WERROR reg_key_del_recursive(REG_KEY *key) { BOOL succeed = True; + WERROR error = WERR_OK; int i; /* Delete all values for specified key */ - for(i = 0; i < reg_key_num_values(key); i++) { - if(!reg_val_del(reg_key_get_value_by_index(key, i))) - succeed = False; + for(i = 0; W_ERROR_IS_OK(error); i++) { + REG_VAL *val; + error = reg_key_get_value_by_index(key, i, &val); + if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + return error; + + if(W_ERROR_IS_OK(error)) { + error = reg_val_del(val); + if(!W_ERROR_IS_OK(error)) return error; + } } + error = WERR_OK; + /* Delete all keys below this one */ - for(i = 0; i < reg_key_num_subkeys(key); i++) { - if(!reg_key_del_recursive(reg_key_get_subkey_by_index(key, i))) - succeed = False; - } + for(i = 0; W_ERROR_IS_OK(error); i++) { + REG_KEY *subkey; + + error = reg_key_get_subkey_by_index(key, i, &subkey); + if(!W_ERROR_IS_OK(error)) return error; - if(succeed)reg_key_del(key); + error = reg_key_del_recursive(subkey); + if(!W_ERROR_IS_OK(error)) return error; + } - return succeed; + return reg_key_del(key); } -BOOL reg_val_del(REG_VAL *val) +WERROR reg_val_del(REG_VAL *val) { + WERROR error; + if (!val) return WERR_INVALID_PARAM; + if (!val->handle->functions->del_value) { DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); - return False; + return WERR_NOT_SUPPORTED; } - if(val->handle->functions->del_value(val)) { - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - return True; - } - return False; + error = val->handle->functions->del_value(val); + + if(!W_ERROR_IS_OK(error)) return error; + + val->parent->cache_values = NULL; + val->parent->cache_values_count = 0; + + return WERR_OK; } -BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path) +WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) { REG_KEY *cur, *prevcur = parent; + WERROR error; char *begin = (char *)path, *end; while(1) { end = strchr(begin, '\\'); if(end) *end = '\0'; - cur = reg_key_get_subkey_by_name(prevcur, begin); - if(!cur) { - if(!reg_key_add_name(prevcur, begin)) { printf("foo\n"); return False; } - cur = reg_key_get_subkey_by_name(prevcur, begin); - if(!cur) { - DEBUG(0, ("Can't find key after adding it : %s\n", begin)); - return False; - } + + error = reg_key_get_subkey_by_name(prevcur, begin, &cur); + + /* Key is not there, add it */ + if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { + error = reg_key_add_name(prevcur, begin, 0, NULL, &cur); + if(!W_ERROR_IS_OK(error)) return error; + } + + if(!W_ERROR_IS_OK(error)) { + if(end) *end = '\\'; + return error; } if(!end) break; @@ -403,28 +441,36 @@ BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path) begin = end+1; prevcur = cur; } - return True; + return WERR_OK; } -BOOL reg_key_add_name(REG_KEY *parent, const char *name) +WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **newkey) { - if (!parent) return False; + WERROR error; + + if (!parent) return WERR_INVALID_PARAM; if (!parent->handle->functions->add_key) { DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); - return False; + return WERR_NOT_SUPPORTED; } - if(parent->handle->functions->add_key(parent, name)) { - parent->cache_subkeys = NULL; - parent->cache_subkeys_count = 0; - return True; - } - return False; + error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey); + + if(!W_ERROR_IS_OK(error)) return error; + + (*newkey)->handle = parent->handle; + (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name); + + parent->cache_subkeys = NULL; + parent->cache_subkeys_count = 0; + return WERR_OK; } -BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) +WERROR reg_val_update(REG_VAL *val, int type, void *data, int len) { + WERROR error; + /* A 'real' update function has preference */ if (val->handle->functions->update_value) return val->handle->functions->update_value(val, type, data, len); @@ -433,18 +479,19 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len) if (val->handle->functions->add_value && val->handle->functions->del_value) { REG_VAL *new; - if(!val->handle->functions->del_value(val)) - return False; + if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) + return error; - new = val->handle->functions->add_value(val->parent, val->name, type, data, len); + error = val->handle->functions->add_value(val->parent, val->name, type, data, len); + if(!W_ERROR_IS_OK(error)) return error; memcpy(val, new, sizeof(REG_VAL)); val->parent->cache_values = NULL; val->parent->cache_values_count = 0; - return True; + return WERR_OK; } DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); - return False; + return WERR_NOT_SUPPORTED; } void reg_free(REG_HANDLE *h) @@ -454,37 +501,44 @@ void reg_free(REG_HANDLE *h) h->functions->close_registry(h); } -REG_KEY *reg_get_root(REG_HANDLE *h) +WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key) { - REG_KEY *ret = NULL; + WERROR ret; if(h->functions->open_root_key) { - ret = h->functions->open_root_key(h); + ret = h->functions->open_root_key(h, key); } else if(h->functions->open_key) { - ret = h->functions->open_key(h, "\\"); + ret = h->functions->open_key(h, "\\", key); } else { DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name)); + ret = WERR_NOT_SUPPORTED; } - if(ret) { - ret->handle = h; - ret->path = talloc_strdup(ret->mem_ctx, "\\"); + if(W_ERROR_IS_OK(ret)) { + (*key)->handle = h; + (*key)->path = talloc_strdup((*key)->mem_ctx, "\\"); } return ret; } -REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) { - REG_VAL *ret; + WERROR ret = WERR_OK; if(!key->handle->functions->add_value) - return NULL; + return WERR_NOT_SUPPORTED; ret = key->handle->functions->add_value(key, name, type, value, vallen); - ret->parent = key; - ret->handle = key->handle; + + if(!W_ERROR_IS_OK(ret)) return ret; /* Invalidate the cache */ key->cache_values = NULL; key->cache_values_count = 0; return ret; } + +WERROR reg_save(REG_HANDLE *h, const char *location) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 060d053fc2..5ca104fc2e 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -96,22 +96,26 @@ BOOL reg_val_set_string(REG_VAL *val, char *str) return False; } -REG_VAL *reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname) +WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname, REG_VAL **val) { - REG_KEY *k = reg_key_get_subkey_by_name(key, subname); - if(!k) return NULL; + REG_KEY *k; + WERROR error = reg_key_get_subkey_by_name(key, subname, &k); + if(!W_ERROR_IS_OK(error)) return error; - return reg_key_get_value_by_name(k, valname); + return reg_key_get_value_by_name(k, valname, val); } -BOOL reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len) +WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len) { - REG_KEY *k = reg_key_get_subkey_by_name(key, subname); + REG_KEY *k; REG_VAL *v; - if(!k) return False; + WERROR error; - v = reg_key_get_value_by_name(k, valname); - if(!v) return False; + error = reg_key_get_subkey_by_name(key, subname, &k); + if(!W_ERROR_IS_OK(error)) return error; + + error = reg_key_get_value_by_name(k, valname, &v); + if(!W_ERROR_IS_OK(error)) return error; return reg_val_update(v, type, data, real_len); } diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 3565a7a585..6e12de258d 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -57,42 +57,55 @@ struct reg_val_s { int ref; }; +/* FIXME */ +typedef void (*key_notification_function) (); +typedef void (*value_notification_function) (); + + /* * Container for function pointers to enumeration routines * for virtual registry view */ -struct reg_ops_s { +struct registry_ops { const char *name; - BOOL (*open_registry) (REG_HANDLE *, const char *location, BOOL try_complete_load); - BOOL (*sync)(REG_HANDLE *, const char *location); - BOOL (*close_registry) (REG_HANDLE *); + WERROR (*open_registry) (REG_HANDLE *, const char *location, const char *credentials); + WERROR (*sync_key)(REG_KEY *, const char *location); + WERROR (*close_registry) (REG_HANDLE *); /* Either implement these */ - REG_KEY *(*open_root_key) (REG_HANDLE *); - int (*num_subkeys) (REG_KEY *); - int (*num_values) (REG_KEY *); - REG_KEY *(*get_subkey_by_index) (REG_KEY *, int idx); - REG_KEY *(*get_subkey_by_name) (REG_KEY *, const char *name); - REG_VAL *(*get_value_by_index) (REG_KEY *, int idx); - REG_VAL *(*get_value_by_name) (REG_KEY *, const char *name); + WERROR (*open_root_key) (REG_HANDLE *, REG_KEY **); + WERROR (*num_subkeys) (REG_KEY *, int *count); + WERROR (*num_values) (REG_KEY *, int *count); + WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **); + WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **); + WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **); + WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **); /* Or these */ - REG_KEY *(*open_key) (REG_HANDLE *, const char *name); - BOOL (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); - BOOL (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); + WERROR (*open_key) (REG_HANDLE *, const char *name, REG_KEY **); + WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); + WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); + + /* Security control */ + WERROR (*key_get_sec_desc) (REG_KEY *, SEC_DESC **); + WERROR (*key_set_sec_desc) (REG_KEY *, SEC_DESC *); + + /* Notification */ + WERROR (*request_key_change_notify) (REG_KEY *, key_notification_function); + WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function); /* Key management */ - BOOL (*add_key)(REG_KEY *, const char *name); - BOOL (*del_key)(REG_KEY *); + WERROR (*add_key)(REG_KEY *, const char *name, uint32 access_mask, SEC_DESC *, REG_KEY **); + WERROR (*del_key)(REG_KEY *); /* Value management */ - REG_VAL *(*add_value)(REG_KEY *, const char *name, int type, void *data, int len); - BOOL (*del_value)(REG_VAL *); + WERROR (*add_value)(REG_KEY *, const char *name, int type, void *data, int len); + WERROR (*del_value)(REG_VAL *); /* If update is not available, value will first be deleted and then added * again */ - BOOL (*update_value)(REG_VAL *, int type, void *data, int len); + WERROR (*update_value)(REG_VAL *, int type, void *data, int len); void (*free_key_backend_data) (REG_KEY *); void (*free_val_backend_data) (REG_VAL *); @@ -105,7 +118,7 @@ typedef struct reg_sub_tree_s { } REG_SUBTREE; struct reg_handle_s { - REG_OPS *functions; + struct registry_ops *functions; REG_SUBTREE *subtrees; char *location; void *backend_data; @@ -114,7 +127,7 @@ struct reg_handle_s { struct reg_init_function_entry { /* Function to create a member of the pdb_methods list */ - REG_OPS *functions; + struct registry_ops *functions; struct reg_init_function_entry *prev, *next; }; diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 146ef92b95..90dc50728b 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -8,9 +8,12 @@ LIBWINREG=libwinregistry PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC) CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building reg_gconf])]) +PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) + SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) +SMB_MODULE(reg_ldb, REG, STATIC, lib/registry/reg_backend_ldb/reg_backend_ldb.o) SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[]) AC_CONFIG_FILES(lib/registry/winregistry.pc) diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 9cb15cd285..4daaf3d628 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/registry/common/registry.h" -static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) +static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc) { char *path; int ret; @@ -29,15 +29,16 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name) path = reg_path_win2unix(path); ret = mkdir(path, 0700); SAFE_FREE(path); - return (ret == 0); + if(ret == 0)return WERR_OK; + return WERR_INVALID_PARAM; } -static BOOL reg_dir_del_key(REG_KEY *k) +static WERROR reg_dir_del_key(REG_KEY *k) { - return (rmdir((char *)k->backend_data) == 0); + return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; } -static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) +static WERROR reg_dir_open_key(REG_HANDLE *h, const char *name, REG_KEY **subkey) { DIR *d; char *fullpath; @@ -45,7 +46,7 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) TALLOC_CTX *mem_ctx = talloc_init("tmp"); if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); - return NULL; + return WERR_INVALID_PARAM; } fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); @@ -54,16 +55,17 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name) if(!d) { DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); talloc_destroy(mem_ctx); - return NULL; + return WERR_BADFILE; } closedir(d); ret = reg_key_new_abs(name, h, fullpath); talloc_steal(mem_ctx, ret->mem_ctx, fullpath); talloc_destroy(mem_ctx); - return ret; + *subkey = ret; + return WERR_OK; } -static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) +static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) { struct dirent *e; int max = 200; @@ -75,7 +77,7 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) d = opendir(fullpath); - if(!d) return False; + if(!d) return WERR_INVALID_PARAM; while((e = readdir(d))) { if(e->d_type == DT_DIR && @@ -96,35 +98,35 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) closedir(d); *r = ar; - return True; + return WERR_OK; } -static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) { - if(!loc) return False; - return True; +static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentials) { + if(!loc) return WERR_INVALID_PARAM; + return WERR_OK; } -static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) +static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len, REG_VAL **value) { - REG_VAL *ret = reg_val_new(p, NULL); char *fullpath; FILE *fd; - ret->name = name?talloc_strdup(ret->mem_ctx, name):NULL; - fullpath = reg_path_win2unix(strdup(reg_val_get_path(ret))); + *value = reg_val_new(p, NULL); + (*value)->name = name?talloc_strdup((*value)->mem_ctx, name):NULL; + fullpath = reg_path_win2unix(strdup(reg_val_get_path(*value))); fd = fopen(fullpath, "w+"); /* FIXME */ - return NULL; + return WERR_NOT_SUPPORTED; } -static BOOL reg_dir_del_value(REG_VAL *v) +static WERROR reg_dir_del_value(REG_VAL *v) { /* FIXME*/ - return False; + return WERR_NOT_SUPPORTED; } -static REG_OPS reg_backend_dir = { +static struct registry_ops reg_backend_dir = { .name = "dir", .open_registry = reg_dir_open, .open_key = reg_dir_open_key, diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 71d3361ce2..1acb3cbcec 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -22,18 +22,26 @@ #include "lib/registry/common/registry.h" #include -static BOOL reg_open_gconf(REG_HANDLE *h, const char *location, BOOL try_complete_load) +static WERROR gerror_to_werror(GError *error) +{ + if(error == NULL) return WERR_OK; + /* FIXME */ + return WERR_FOOBAR; +} + +static WERROR reg_open_gconf(REG_HANDLE *h, const char *location, const char *credentials) { h->backend_data = (void *)gconf_client_get_default(); - return True; + if(!h->backend_data) return WERR_FOOBAR; + return WERR_OK; } -static BOOL reg_close_gconf(REG_HANDLE *h) +static WERROR reg_close_gconf(REG_HANDLE *h) { - return True; + return WERR_OK; } -static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name) +static WERROR gconf_open_key (REG_HANDLE *h, const char *name, REG_KEY **key) { REG_KEY *ret; char *fullpath = reg_path_win2unix(strdup(name)); @@ -41,16 +49,17 @@ static REG_KEY *gconf_open_key (REG_HANDLE *h, const char *name) /* Check if key exists */ if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { SAFE_FREE(fullpath); - return NULL; + return WERR_DEST_NOT_FOUND; } ret = reg_key_new_abs(name, h, NULL); ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath); SAFE_FREE(fullpath); - return ret; + *key = ret; + return WERR_OK; } -static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) +static WERROR gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) { GSList *entries; GSList *cur; @@ -113,22 +122,24 @@ static BOOL gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) g_slist_free(entries); *vals = ar; - return True; + return WERR_OK; } -static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) +static WERROR gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) { GSList *dirs; GSList *cur; - REG_KEY **ar = malloc(sizeof(REG_KEY *)); + REG_KEY **ar = talloc_array_p(p->mem_ctx, REG_KEY *, 1); char *fullpath = p->backend_data; cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); (*count) = 0; while(cur) { - ar[(*count)] = reg_key_new_abs(reg_path_unix2win((char *)cur->data), p->handle,NULL); - ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, cur->data); - ar = realloc(ar, sizeof(REG_KEY *) * ((*count)+2)); + char *winpath = reg_path_unix2win(strdup((char *)cur->data)); + ar[(*count)] = reg_key_new_abs(winpath, p->handle,NULL); + free(winpath); + ar[(*count)]->backend_data = reg_path_win2unix(talloc_strdup(ar[*count]->mem_ctx, cur->data)); + ar = talloc_realloc_p(p->mem_ctx, ar, REG_KEY *, (*count)+2); (*count)++; g_free(cur->data); cur = cur->next; @@ -136,10 +147,10 @@ static BOOL gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) g_slist_free(dirs); *subs = ar; - return True; + return WERR_OK; } -static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len) +static WERROR gconf_update_value(REG_VAL *val, int type, void *data, int len) { GError *error = NULL; char *keypath = val->backend_data; @@ -152,22 +163,23 @@ static BOOL gconf_update_value(REG_VAL *val, int type, void *data, int len) case REG_EXPAND_SZ: gconf_client_set_string((GConfClient *)val->handle->backend_data, valpath, data, &error); free(valpath); - return (error == NULL); + return gerror_to_werror(error); case REG_DWORD: gconf_client_set_int((GConfClient *)val->handle->backend_data, valpath, *((int *)data), &error); free(valpath); - return (error == NULL); + return gerror_to_werror(error); default: DEBUG(0, ("Unsupported type: %d\n", type)); free(valpath); - return False; + return WERR_NOT_SUPPORTED; } - return False; + + return WERR_NOT_SUPPORTED; } -static REG_OPS reg_backend_gconf = { +static struct registry_ops reg_backend_gconf = { .name = "gconf", .open_registry = reg_open_gconf, .close_registry = reg_close_gconf, diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index afa60c5c4a..3cc1651519 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -20,51 +20,96 @@ #include "includes.h" #include "lib/registry/common/registry.h" +#include "lib/ldb/include/ldb.h" + +char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) +{ + char *ret = talloc_strdup(mem_ctx, "(dn="); + char *begin = (char *)path; + char *end = NULL; + + while(begin) { + end = strchr(begin, '\\'); + if(end)end = '\0'; + if(end - begin != 0) ret = talloc_asprintf_append(mem_ctx, ret, "key=%s,", begin); + + if(end) { + *end = '\\'; + begin = end+1; + } else begin = NULL; + } + + ret[strlen(ret)-1] = ')'; + return ret; +} /* * Saves the dn as private_data for every key/val */ -static BOOL ldb_open_registry(REG_HANDLE *handle, const char *location, BOOL try_full_load) +static WERROR ldb_open_registry(REG_HANDLE *handle, const char *location, const char *credentials) { struct ldb_context *c; c = ldb_connect(location, 0, NULL); - if(!c) return False; + if(!c) return WERR_FOOBAR; handle->backend_data = c; - return True; + return WERR_OK; } -static BOOL ldb_close_registry(REG_HANDLE *h) +static WERROR ldb_close_registry(REG_HANDLE *h) { - ldb_close(h); - return True; + ldb_close((struct ldb_context *)h->backend_data); + return WERR_OK; } -static BOOL ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) +static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) { - ldb_search(); + struct ldb_context *c = k->handle->backend_data; + char *path; + struct ldb_message **msg; + char *ldap_path; + TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); + REG_KEY *key = NULL; + ldap_path = reg_path_to_ldb(mem_ctx, reg_key_get_path(k)); + + if(ldb_search(c, NULL, LDB_SCOPE_ONELEVEL, ldap_path, NULL,&msg) > 0) { + key = reg_key_new_abs(reg_key_get_path(k), k->handle, ldap_path); + talloc_steal(mem_ctx, key->mem_ctx, ldap_path); + /* FIXME */ + } + + ldap_search_free(c, msg); + talloc_destroy(mem_ctx); + return WERR_OK; } -static REG_KEY *ldb_open_key(REG_HANDLE *h, const char *name) + + +static WERROR ldb_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) { struct ldb_context *c = h->backend_data; char *path; struct ldb_message **msg; - REG_KEY *key = NULL; - (dn=key=Systems, - if(ldb_search(c, NULL, LDP_SCOPE_BASE, "", NULL,&msg) > 0) { - key = reg_key_new_abs(name, h, base); + char *ldap_path; + TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); + ldap_path = reg_path_to_ldb(mem_ctx, name); + + if(ldb_search(c, NULL, LDB_SCOPE_BASE, ldap_path, NULL,&msg) > 0) { + *key = reg_key_new_abs(name, h, ldap_path); + talloc_steal(mem_ctx, (*key)->mem_ctx, ldap_path); + /* FIXME */ } ldap_search_free(c, msg); + talloc_destroy(mem_ctx); - return key; + return WERR_OK;; } -static REG_OPS reg_backend_ldb = { +static struct registry_ops reg_backend_ldb = { .name = "ldb", .open_registry = ldb_open_registry, .close_registry = ldb_close_registry, diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index ef2565bda8..9d90523a75 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -881,7 +881,7 @@ static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, in /* * Process a VK header and return a value */ -static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size) +static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **value) { char val_name[1024]; REGF *regf = parent->handle->backend_data; @@ -889,12 +889,12 @@ static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size) const char *val_type; REG_VAL *tmp = NULL; - if (!vk_hdr) return NULL; + if (!vk_hdr) return WERR_INVALID_PARAM; if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", vk_id, (int)vk_hdr, parent->handle->location)); - return NULL; + return WERR_GENERAL_FAILURE; } nam_len = SVAL(&vk_hdr->nam_len,0); @@ -943,7 +943,8 @@ static REG_VAL *vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size) tmp->data_len = dat_len; } - return tmp; + *value = tmp; + return WERR_OK; } static BOOL vl_verify(VL_TYPE vl, int count, int size) @@ -956,63 +957,67 @@ static BOOL vl_verify(VL_TYPE vl, int count, int size) return True; } -static BOOL lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) { int lf_id; if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n", lf_id, (int)lf_hdr, h->location)); - return False; + return WERR_INVALID_PARAM; } - return True; + return WERR_OK; } -static int lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count) { - int count; + WERROR error; - if(!lf_verify(h, lf_hdr, size)) return 0; + error = lf_verify(h, lf_hdr, size); + if(!W_ERROR_IS_OK(error)) return error; SMB_REG_ASSERT(size < 0); - count = SVAL(&lf_hdr->key_count,0); - DEBUG(2, ("Key Count: %u\n", count)); - if (count <= 0) return 0; + *count = SVAL(&lf_hdr->key_count,0); + DEBUG(2, ("Key Count: %u\n", *count)); + if (*count <= 0) return WERR_INVALID_PARAM; - return count; + return WERR_OK; } -static REG_KEY *nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent); +static WERROR nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **); /* * Process an LF Header and return a list of sub-keys */ -static REG_KEY *lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n) +static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG_KEY **key) { REGF *regf = parent->handle->backend_data; int count, nk_off; NK_HDR *nk_hdr; + WERROR error; - if (!lf_hdr) return NULL; + if (!lf_hdr) return WERR_INVALID_PARAM; - if(!lf_verify(parent->handle, lf_hdr, size)) return NULL; + error = lf_verify(parent->handle, lf_hdr, size); + if(!W_ERROR_IS_OK(error)) return error; SMB_REG_ASSERT(size < 0); count = SVAL(&lf_hdr->key_count,0); DEBUG(2, ("Key Count: %u\n", count)); - if (count <= 0 || n > count) return NULL; + if (count <= 0) return WERR_GENERAL_FAILURE; + if (n >= count) return WERR_NO_MORE_ITEMS; nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); DEBUG(2, ("NK Offset: %0X\n", nk_off)); nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent); + return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent, key); } -static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent) +static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **key) { REGF *regf = h->backend_data; REG_KEY *tmp = NULL, *own; @@ -1022,12 +1027,12 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare int type; char key_name[1024], cls_name[1024]; - if (!nk_hdr) return NULL; + if (!nk_hdr) return WERR_INVALID_PARAM; if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", nk_id, (int)nk_hdr, parent->handle->location)); - return NULL; + return WERR_INVALID_PARAM; } SMB_REG_ASSERT(size < 0); @@ -1047,7 +1052,7 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", sizeof(NK_HDR), name_len, clsname_len)); - /*return NULL;*/ + return WERR_GENERAL_FAILURE; } DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", name_len, clsname_len)); @@ -1062,7 +1067,7 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); if(type == REG_ROOT_KEY && parent) { DEBUG(0,("Root key encountered below root level!\n")); - return NULL; + return WERR_GENERAL_FAILURE; } if(type == REG_ROOT_KEY) tmp = reg_key_new_abs(key_name, h, nk_hdr); @@ -1121,7 +1126,8 @@ static REG_KEY *nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *pare } - return tmp; + *key = tmp; + return WERR_OK; } /* @@ -1559,7 +1565,7 @@ error: return NULL; } -static BOOL nt_close_registry (REG_HANDLE *h) +static WERROR nt_close_registry (REG_HANDLE *h) { REGF *regf = h->backend_data; if (regf->base) munmap(regf->base, regf->sbuf.st_size); @@ -1570,10 +1576,10 @@ static BOOL nt_close_registry (REG_HANDLE *h) regf->sk_count = regf->sk_map_size = 0; free(regf); - return False; + return WERR_OK; } -static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load) +static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials) { REGF *regf = (REGF *)malloc(sizeof(REGF)); REGF_HDR *regf_hdr; @@ -1582,7 +1588,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load memset(regf, 0, sizeof(REGF)); regf->mem_ctx = talloc_init("regf"); - regf->owner_sid_str = def_owner_sid_str; + regf->owner_sid_str = credentials; h->backend_data = regf; DEBUG(5, ("Attempting to load registry file\n")); @@ -1591,7 +1597,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) { DEBUG(0, ("Unable to get header\n")); - return False; + return WERR_GENERAL_FAILURE; } /* Now process that header and start to read the rest in */ @@ -1599,7 +1605,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load if ((regf_id = IVAL(®f_hdr->REGF_ID,0)) != str_to_dword("regf")) { DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n", regf_id, h->location)); - return False; + return WERR_GENERAL_FAILURE; } /* @@ -1608,7 +1614,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load if (!valid_regf_hdr(regf_hdr)) { DEBUG(0, ("Registry file header does not validate: %s\n", h->location)); - return False; + return WERR_GENERAL_FAILURE; } /* Update the last mod date, and then go get the first NK record and on */ @@ -1625,7 +1631,7 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) { DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", hbin_id, h->location)); - return False; + return WERR_GENERAL_FAILURE; } /* @@ -1655,15 +1661,15 @@ static BOOL nt_open_registry (REG_HANDLE *h, const char *location, BOOL try_load h->backend_data = regf; - return True; + return WERR_OK; } -static REG_KEY *nt_get_root_key(REG_HANDLE *h) +static WERROR nt_get_root_key(REG_HANDLE *h, REG_KEY **key) { - return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL); + return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); } -static int nt_num_subkeys(REG_KEY *k) +static WERROR nt_num_subkeys(REG_KEY *k, int *num) { REGF *regf = k->handle->backend_data; LF_HDR *lf_hdr; @@ -1671,19 +1677,23 @@ static int nt_num_subkeys(REG_KEY *k) NK_HDR *nk_hdr = k->backend_data; lf_off = IVAL(&nk_hdr->lf_off,0); DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); - if(lf_off == -1) return 0; + if(lf_off == -1) { + *num = 0; + return WERR_OK; + } lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr)); + return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr), num); } -static int nt_num_values(REG_KEY *k) +static WERROR nt_num_values(REG_KEY *k, int *count) { NK_HDR *nk_hdr = k->backend_data; - return IVAL(&nk_hdr->val_cnt,0); + *count = IVAL(&nk_hdr->val_cnt,0); + return WERR_OK; } -static REG_VAL *nt_value_by_index(REG_KEY *k, int n) +static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) { VL_TYPE *vl; int val_off, vk_off; @@ -1696,10 +1706,10 @@ static REG_VAL *nt_value_by_index(REG_KEY *k, int n) vk_off = IVAL(&vl[n],0); vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr)); + return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr), value); } -static REG_KEY *nt_key_by_index(REG_KEY *k, int n) +static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey) { REGF *regf = k->handle->backend_data; int lf_off; @@ -1714,13 +1724,13 @@ static REG_KEY *nt_key_by_index(REG_KEY *k, int n) if (lf_off != -1) { lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n); + return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); } - return NULL; + return WERR_NO_MORE_ITEMS; } -static REG_OPS reg_backend_nt4 = { +static struct registry_ops reg_backend_nt4 = { .name = "nt4", .open_registry = nt_open_registry, .close_registry = nt_close_registry, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index ad4d537f9b..e61301d6f2 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -77,12 +77,18 @@ struct { { NULL, NULL } }; -static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full) +static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) { - BOOL res = True; struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data)); char *binding = strdup(location); NTSTATUS status; + char *user, *pass; + + if(!credentials || !location) return WERR_INVALID_PARAM; + + user = talloc_strdup(h->mem_ctx, credentials); + pass = strchr(user, '%'); + *pass = '\0'; pass++; ZERO_STRUCTP(mydata); @@ -90,26 +96,26 @@ static BOOL rpc_open_registry(REG_HANDLE *h, const char *location, BOOL try_full DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), - "tridge", "samba"); + user, pass); - if(!NT_STATUS_IS_OK(status)) return False; h->backend_data = mydata; - return True; + return ntstatus_to_werror(status); } -static REG_KEY *rpc_open_root(REG_HANDLE *h) +static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k) { /* There's not really a 'root' key here */ - return reg_key_new_abs("\\", h, h->backend_data); + *k = reg_key_new_abs("\\", h, h->backend_data); + return WERR_OK; } -static BOOL rpc_close_registry(REG_HANDLE *h) +static WERROR rpc_close_registry(REG_HANDLE *h) { dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe); free(h->backend_data); - return True; + return WERR_OK; } static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path) @@ -161,12 +167,15 @@ static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path) return key_handle; } -static REG_KEY *rpc_open_key(REG_HANDLE *h, const char *name) +static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) { - return reg_key_new_abs(name, h, rpc_get_key_handle(h, name)); + struct policy_handle *pol = rpc_get_key_handle(h, name); + if(!pol) return WERR_DEST_NOT_FOUND; + *key = reg_key_new_abs(name, h, pol); + return WERR_OK; } -static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) +static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) { struct winreg_EnumKey r; struct winreg_EnumKeyNameRequest keyname; @@ -188,12 +197,12 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) *subkeys = ar; - return True; + return WERR_OK; } if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); - if(!parent->backend_data) return False; + if(!parent->backend_data) return WERR_GENERAL_FAILURE; (*count) = 0; r.in.handle = parent->backend_data; @@ -219,10 +228,10 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) } *subkeys = ar; - return True; + return r.out.result; } -static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) +static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) { struct winreg_EnumValue r; struct winreg_Uint8buf value; @@ -238,12 +247,12 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) /* Root */ if(parent->backend_data == parent->handle->backend_data) { *values = ar; - return True; + return WERR_OK; } if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); - if(!parent->backend_data) return False; + if(!parent->backend_data) return WERR_GENERAL_FAILURE; r.in.handle = parent->backend_data; r.in.enum_index = 0; @@ -283,22 +292,48 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) *values = ar; - return True; + return r.out.result; } -static BOOL rpc_add_key(REG_KEY *parent, const char *name) +static WERROR rpc_add_key(REG_KEY *parent, const char *name) { /* FIXME */ - return False; + return WERR_NOT_SUPPORTED; } -static BOOL rpc_del_key(REG_KEY *k) +static struct policy_handle*get_hive(REG_KEY *k) { - /* FIXME */ - return False; + int i; + struct rpc_data *mydata = k->handle->backend_data; + for(i = 0; known_hives[i].name; i++) { + if(!strncmp(known_hives[i].name, reg_key_get_path(k)+1, strlen(known_hives[i].name))) + return mydata->hives[i]; + } + return NULL; +} + +static WERROR rpc_del_key(REG_KEY *k) +{ + NTSTATUS status; + struct rpc_data *mydata = k->handle->backend_data; + struct winreg_DeleteKey r; + char *hivepath; + struct policy_handle *hive = get_hive(k); + + printf("first: %s\n", reg_key_get_path(k)); + hivepath = strchr(reg_key_get_path(k), '\\'); + hivepath = strchr(hivepath+1, '\\'); + printf("asfter: %s\n", hivepath+1); + + r.in.handle = hive; + init_winreg_String(&r.in.key, hivepath+1); + + status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r); + + return r.out.result; } -static REG_OPS reg_backend_rpc = { +static struct registry_ops reg_backend_rpc = { .name = "rpc", .open_registry = rpc_open_registry, .close_registry = rpc_close_registry, diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c index 6c8d7885cb..fd7d04bcf0 100644 --- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c +++ b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c @@ -20,6 +20,7 @@ #include "includes.h" #include "lib/registry/common/registry.h" +#include "windows/registry.h" static REG_OPS reg_backend_wine = { .name = "wine", diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c new file mode 100644 index 0000000000..b62fd7ec04 --- /dev/null +++ b/source4/lib/registry/tools/gregedit.c @@ -0,0 +1,758 @@ +/* + Unix SMB/CIFS implementation. + Gtk registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include "includes.h" + +GtkWidget *openfilewin; +GtkWidget *savefilewin; +GtkTreeStore *store_keys; +GtkListStore *store_vals; +GtkWidget *tree_keys; +GtkWidget *aboutwin; +GtkWidget *mainwin; + +GtkWidget *rpcwin; +GtkWidget *rpcwin_host; +GtkWidget *rpcwin_user; +GtkWidget *rpcwin_password; +GtkWidget *save; +GtkWidget *save_as; +GtkWidget* create_openfilewin (void); +GtkWidget* create_savefilewin (void); +static GtkWidget* create_aboutwin (void); +REG_HANDLE *registry = NULL; + +static void gtk_show_werror(WERROR err) +{ + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(mainwin), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Registry error: %s\n", win_errstr(err)); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +static void treeview_add_val(REG_VAL *val) +{ + GtkTreeIter iter; + gtk_list_store_append(store_vals, &iter); + gtk_list_store_set (store_vals, + &iter, + 0, + reg_val_name(val), + 1, + str_regtype(reg_val_type(val)), + 2, + reg_val_data_string(val), + 3, + val, + -1); +} + +static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2) +{ + GtkTreeIter iter, tmpiter; + REG_KEY *k, *sub; + char *name; + GValue value; + WERROR error; + int i; + + /* See if this row has ever had a name gtk_tree_store_set()'ed to it. + If not, read the directory contents */ + gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, + 0, &name, -1); + + if(!name) return; + + gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, 1, &k, -1); + + g_assert(k); + + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(k, i, &sub)); i++) { + /* Replace the blank child with the first directory entry + You may be tempted to remove the blank child node and then + append a new one. Don't. If you remove the blank child + node GTK gets confused and won't expand the parent row. */ + + if(i == 0) { + gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), + &iter, parent); + } else { + gtk_tree_store_append(store_keys, &iter, parent); + } + gtk_tree_store_set (store_keys, + &iter, + 0, + reg_key_name(sub), + 1, + sub, + -1); + + gtk_tree_store_append(store_keys, &tmpiter, &iter); + } + + /* Remove placeholder child */ + if(i == 0) { + gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), + &iter, parent); + gtk_tree_store_remove(store_keys, &iter); + } + + if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); +} + +static void registry_load_root() +{ + REG_KEY *root; + GtkTreeIter iter, tmpiter; + WERROR error; + if(!registry) return; + + error = reg_get_root(registry, &root); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return; + } + + gtk_tree_store_clear(store_keys); + + /* Add the root */ + gtk_tree_store_append(store_keys, &iter, NULL); + gtk_tree_store_set (store_keys, + &iter, + 0, + reg_key_name(root), + 1, + root, + -1); + + gtk_tree_store_append(store_keys, &tmpiter, &iter); + + gtk_widget_set_sensitive( save, True ); + gtk_widget_set_sensitive( save_as, True ); +} + +GtkWidget* create_rpcwin (void) +{ + GtkWidget *dialog_vbox1; + GtkWidget *table1; + GtkWidget *label1; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *dialog_action_area1; + GtkWidget *cancelbutton1; + GtkWidget *okbutton1; + + rpcwin = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (rpcwin), "Connect to remote server"); + + dialog_vbox1 = GTK_DIALOG (rpcwin)->vbox; + gtk_widget_show (dialog_vbox1); + + table1 = gtk_table_new (3, 2, FALSE); + gtk_widget_show (table1); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0); + + label1 = gtk_label_new ("Host:"); + gtk_widget_show (label1); + gtk_table_attach (GTK_TABLE (table1), label1, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label1), 0, 0.5); + + label2 = gtk_label_new ("User:"); + gtk_widget_show (label2); + gtk_table_attach (GTK_TABLE (table1), label2, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5); + + label3 = gtk_label_new ("Password:"); + gtk_widget_show (label3); + gtk_table_attach (GTK_TABLE (table1), label3, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5); + + rpcwin_host = gtk_entry_new (); + gtk_widget_show (rpcwin_host); + gtk_table_attach (GTK_TABLE (table1), rpcwin_host, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + rpcwin_user = gtk_entry_new (); + gtk_widget_show (rpcwin_user); + gtk_table_attach (GTK_TABLE (table1), rpcwin_user, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + rpcwin_password = gtk_entry_new (); + gtk_widget_show (rpcwin_password); + gtk_table_attach (GTK_TABLE (table1), rpcwin_password, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_visibility (GTK_ENTRY (rpcwin_password), FALSE); + + dialog_action_area1 = GTK_DIALOG (rpcwin)->action_area; + gtk_widget_show (dialog_action_area1); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END); + + cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (cancelbutton1); + gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), cancelbutton1, GTK_RESPONSE_CANCEL); + GTK_WIDGET_SET_FLAGS (cancelbutton1, GTK_CAN_DEFAULT); + + okbutton1 = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (okbutton1); + gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), okbutton1, GTK_RESPONSE_OK); + GTK_WIDGET_SET_FLAGS (okbutton1, GTK_CAN_DEFAULT); + + return rpcwin; +} + + +static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data) +{ + gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); + char *filename; + WERROR error; + switch(result) { + case GTK_RESPONSE_OK: + filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin))); + error = reg_open("nt4", filename, NULL, ®istry); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return; + } + registry_load_root(); + break; + default: + break; + } + + gtk_widget_destroy(openfilewin); +} + +void on_open_gconf_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + WERROR error = reg_open("gconf", NULL, NULL, ®istry); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return; + } + + registry_load_root(); +} + +void +on_open_remote_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + char *location, *credentials; + gint result = gtk_dialog_run(GTK_DIALOG(create_rpcwin())); + WERROR error; + switch(result) { + case GTK_RESPONSE_OK: + asprintf(&location, "ncacn_np:%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_host))); + asprintf(&credentials, "%s%%%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_user)), gtk_entry_get_text(GTK_ENTRY(rpcwin_password))); + error = reg_open("rpc", location, credentials, ®istry); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return; + } + free(location); free(credentials); + registry_load_root(); + break; + default: + break; + } + + gtk_widget_destroy(rpcwin); +} + + +void +on_save_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + WERROR error = reg_save(registry, NULL); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + } +} + + +void +on_save_as_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + gint result; + WERROR error; + create_savefilewin(); + result = gtk_dialog_run(GTK_DIALOG(savefilewin)); + switch(result) { + case GTK_RESPONSE_OK: + error = reg_save(registry, gtk_file_selection_get_filename(GTK_FILE_SELECTION(savefilewin))); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + } + break; + + default: + break; + + } + gtk_widget_destroy(savefilewin); +} + + +void +on_quit_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_cut_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + /* FIXME */ +} + + +void +on_copy_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + /* FIXME */ +} + + +void +on_paste_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + /* FIXME */ +} + + +void +on_delete_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + /* FIXME */ +} + + +void +on_about_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + gtk_dialog_run(GTK_DIALOG(create_aboutwin())); + gtk_widget_destroy(aboutwin); +} + +void on_key_activate (GtkTreeView *treeview, + GtkTreePath *path, + gpointer user_data) +{ + int i; + REG_KEY *k; + REG_VAL *val; + WERROR error; + +//FIXME gtk_tree_model_get(GTK_TREE_MODEL(store_keys), iter, 1, &k, -1); + + gtk_list_store_clear(store_vals); + + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(k, i, &val)); i++) { + treeview_add_val(val); + } + + if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); + + return; +} + +GtkWidget* create_mainwin (void) +{ + GtkWidget *vbox1; + GtkWidget *menubar; + GtkWidget *menu_file; + GtkWidget *menu_file_menu; + GtkWidget *open_nt4; + GtkWidget *open_gconf; + GtkWidget *open_remote; + GtkWidget *separatormenuitem1; + GtkWidget *quit; + GtkWidget *men_edit; + GtkWidget *men_edit_menu; + GtkWidget *cut; + GtkWidget *copy; + GtkWidget *paste; + GtkWidget *delete; + GtkCellRenderer *renderer; + GtkTreeViewColumn *curcol; + GtkWidget *help; + GtkWidget *help_menu; + GtkWidget *about; + GtkWidget *hbox1; + GtkWidget *scrolledwindow1; + GtkWidget *scrolledwindow2; + GtkWidget *tree_vals; + GtkWidget *statusbar; + GtkAccelGroup *accel_group; + GtkTreeIter iter, child; + + accel_group = gtk_accel_group_new (); + + mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (mainwin), "Registry editor"); + gtk_window_set_default_size (GTK_WINDOW (mainwin), 642, 562); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (mainwin), vbox1); + + menubar = gtk_menu_bar_new (); + gtk_widget_show (menubar); + gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, FALSE, 0); + + menu_file = gtk_menu_item_new_with_mnemonic ("_File"); + gtk_widget_show (menu_file); + gtk_container_add (GTK_CONTAINER (menubar), menu_file); + + menu_file_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_file), menu_file_menu); + + open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file"); + gtk_widget_show (open_nt4); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); + + open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); + gtk_widget_show (open_gconf); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); + + open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote"); + gtk_widget_show (open_remote); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); + + save = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group); + gtk_widget_show (save); + gtk_widget_set_sensitive( save, False ); + gtk_container_add (GTK_CONTAINER (menu_file_menu), save); + + save_as = gtk_image_menu_item_new_from_stock ("gtk-save-as", accel_group); + gtk_widget_show (save_as); + gtk_widget_set_sensitive( save_as, False ); + gtk_container_add (GTK_CONTAINER (menu_file_menu), save_as); + + separatormenuitem1 = gtk_menu_item_new (); + gtk_widget_show (separatormenuitem1); + gtk_container_add (GTK_CONTAINER (menu_file_menu), separatormenuitem1); + gtk_widget_set_sensitive (separatormenuitem1, FALSE); + + quit = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group); + gtk_widget_show (quit); + gtk_container_add (GTK_CONTAINER (menu_file_menu), quit); + + men_edit = gtk_menu_item_new_with_mnemonic ("_Edit"); + gtk_widget_show (men_edit); + gtk_container_add (GTK_CONTAINER (menubar), men_edit); + + men_edit_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (men_edit), men_edit_menu); + + cut = gtk_image_menu_item_new_from_stock ("gtk-cut", accel_group); + gtk_widget_show (cut); + gtk_widget_set_sensitive(cut, False); + gtk_container_add (GTK_CONTAINER (men_edit_menu), cut); + + copy = gtk_image_menu_item_new_from_stock ("gtk-copy", accel_group); + gtk_widget_show (copy); + gtk_widget_set_sensitive(copy, False); + gtk_container_add (GTK_CONTAINER (men_edit_menu), copy); + + paste = gtk_image_menu_item_new_from_stock ("gtk-paste", accel_group); + gtk_widget_show (paste); + gtk_widget_set_sensitive(paste, False); + gtk_container_add (GTK_CONTAINER (men_edit_menu), paste); + + delete = gtk_image_menu_item_new_from_stock ("gtk-delete", accel_group); + gtk_widget_show (delete); + gtk_widget_set_sensitive(delete, False); + gtk_container_add (GTK_CONTAINER (men_edit_menu), delete); + + help = gtk_menu_item_new_with_mnemonic ("_Help"); + gtk_widget_show (help); + gtk_container_add (GTK_CONTAINER (menubar), help); + + help_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), help_menu); + + about = gtk_menu_item_new_with_mnemonic ("_About"); + gtk_widget_show (about); + gtk_container_add (GTK_CONTAINER (help_menu), about); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow1); + gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow1, TRUE, TRUE, 0); + + tree_keys = gtk_tree_view_new (); + + /* Column names */ + curcol = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title(curcol, "Name"); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(curcol, renderer, True); + + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_keys), curcol); + + gtk_tree_view_column_add_attribute(curcol, renderer, "text", 0); + gtk_widget_show (tree_keys); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), tree_keys); + store_keys = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + gtk_tree_view_set_model(GTK_TREE_VIEW(tree_keys), GTK_TREE_MODEL(store_keys)); + g_object_unref(store_keys); + + g_signal_connect ((gpointer) tree_keys, "row-activated", + G_CALLBACK (on_key_activate), + NULL); + + g_signal_connect ((gpointer) tree_keys, "row-expanded", + G_CALLBACK (expand_key), + NULL); + + scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow2); + gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow2, TRUE, TRUE, 0); + + tree_vals = gtk_tree_view_new (); + /* Column names */ + curcol = gtk_tree_view_column_new_with_attributes ("Name", gtk_cell_renderer_text_new(), NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); + + + curcol = gtk_tree_view_column_new_with_attributes ("Type", gtk_cell_renderer_text_new(), NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); + + curcol = gtk_tree_view_column_new_with_attributes ("Value", gtk_cell_renderer_text_new(), NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); + gtk_widget_show (tree_vals); + gtk_container_add (GTK_CONTAINER (scrolledwindow2), tree_vals); + + store_vals = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + gtk_tree_view_set_model(GTK_TREE_VIEW(tree_vals), GTK_TREE_MODEL(store_vals)); + g_object_unref(store_vals); + + statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar); + gtk_box_pack_start (GTK_BOX (vbox1), statusbar, FALSE, FALSE, 0); + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE); + + g_signal_connect ((gpointer) open_nt4, "activate", + G_CALLBACK (on_open_nt4_activate), + NULL); + g_signal_connect ((gpointer) open_gconf, "activate", + G_CALLBACK (on_open_gconf_activate), + NULL); + g_signal_connect ((gpointer) open_remote, "activate", + G_CALLBACK (on_open_remote_activate), + NULL); + g_signal_connect ((gpointer) save, "activate", + G_CALLBACK (on_save_activate), + NULL); + g_signal_connect ((gpointer) save_as, "activate", + G_CALLBACK (on_save_as_activate), + NULL); + g_signal_connect ((gpointer) quit, "activate", + G_CALLBACK (on_quit_activate), + NULL); + g_signal_connect ((gpointer) cut, "activate", + G_CALLBACK (on_cut_activate), + NULL); + g_signal_connect ((gpointer) copy, "activate", + G_CALLBACK (on_copy_activate), + NULL); + g_signal_connect ((gpointer) paste, "activate", + G_CALLBACK (on_paste_activate), + NULL); + g_signal_connect ((gpointer) delete, "activate", + G_CALLBACK (on_delete_activate), + NULL); + g_signal_connect ((gpointer) about, "activate", + G_CALLBACK (on_about_activate), + NULL); + + gtk_window_add_accel_group (GTK_WINDOW (mainwin), accel_group); + + return mainwin; +} + +static GtkWidget* create_aboutwin (void) +{ + GtkWidget *dialog_vbox1; + GtkWidget *image1; + GtkWidget *label1; + GtkWidget *label2; + GtkWidget *dialog_action_area1; + GtkWidget *closebutton1; + + aboutwin = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (aboutwin), "About GRegEdit"); + gtk_window_set_resizable (GTK_WINDOW (aboutwin), FALSE); + + dialog_vbox1 = GTK_DIALOG (aboutwin)->vbox; + gtk_widget_show (dialog_vbox1); + + /* FIXME: Samba logo ? + image1 = create_pixmap (aboutwin, "samba.png"); + gtk_widget_show (image1); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), image1, FALSE, TRUE, 0); */ + + label1 = gtk_label_new ("GRegEdit 0.1"); + gtk_widget_show (label1); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), label1, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (label1), TRUE); + + label2 = gtk_label_new_with_mnemonic ("(C) 2004 Jelmer Vernooij \nPart of Samba\nhttp://www.samba.org/\n"); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), label2, TRUE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (label2), TRUE); + + dialog_action_area1 = GTK_DIALOG (aboutwin)->action_area; + gtk_widget_show (dialog_action_area1); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END); + + closebutton1 = gtk_button_new_from_stock ("gtk-close"); + gtk_widget_show (closebutton1); + gtk_dialog_add_action_widget (GTK_DIALOG (aboutwin), closebutton1, GTK_RESPONSE_CLOSE); + GTK_WIDGET_SET_FLAGS (closebutton1, GTK_CAN_DEFAULT); + + return aboutwin; +} + + +GtkWidget* create_openfilewin (void) +{ + GtkWidget *ok_button; + GtkWidget *cancel_button; + + openfilewin = gtk_file_selection_new ("Select File"); + gtk_container_set_border_width (GTK_CONTAINER (openfilewin), 10); + + ok_button = GTK_FILE_SELECTION (openfilewin)->ok_button; + gtk_widget_show (ok_button); + GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); + + cancel_button = GTK_FILE_SELECTION (openfilewin)->cancel_button; + gtk_widget_show (cancel_button); + GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); + + return openfilewin; +} + +GtkWidget* create_savefilewin (void) +{ + GtkWidget *ok_button; + GtkWidget *cancel_button; + + savefilewin = gtk_file_selection_new ("Select File"); + gtk_container_set_border_width (GTK_CONTAINER (savefilewin), 10); + + ok_button = GTK_FILE_SELECTION (savefilewin)->ok_button; + gtk_widget_show (ok_button); + GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); + + cancel_button = GTK_FILE_SELECTION (savefilewin)->cancel_button; + gtk_widget_show (cancel_button); + GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); + + return savefilewin; +} + +int main (int argc, char *argv[]) +{ + poptContext pc; + const char *backend = NULL, *credentials = NULL, *location; + int opt; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%%password)", NULL}, + POPT_TABLEEND + }; + + gtk_init (&argc, &argv); + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + location = poptGetArg(pc); + + if(location) { + WERROR error; + + if(!backend) { + if(credentials)backend = "rpc"; + else backend = "nt4"; + } + + error = reg_open(backend, location, credentials, ®istry); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return -1; + } + mainwin = create_mainwin (); + registry_load_root(); + } else + mainwin = create_mainwin (); + + gtk_widget_show (mainwin); + + gtk_main (); + + if(registry)reg_free(registry); + return 0; +} diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 9074d1c716..e6b5fa51ee 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -201,6 +201,7 @@ int main (int argc, char **argv) REG_HANDLE *h; struct poptOption long_options[] = { POPT_AUTOHELP + POPT_COMMON_SAMBA {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, POPT_TABLEEND }; -- cgit From 9cbbf2d55253783adaeceac9bc2f8c9ffe40aa94 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 9 Apr 2004 00:02:20 +0000 Subject: r129: Convert other utilities to new API (This used to be commit 95c9852b1607335eb24025081a251139449fb695) --- source4/lib/registry/tools/regdiff.c | 93 ++++++++++++++++++++++++----------- source4/lib/registry/tools/regpatch.c | 77 ++++++++++++++++++++--------- source4/lib/registry/tools/regshell.c | 47 +++++++++++------- source4/lib/registry/tools/regtree.c | 33 ++++++++----- 4 files changed, 169 insertions(+), 81 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 5e2b97cb98..94cdf8c8af 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -24,41 +24,71 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) { int i, numkeys1, numvals1, numvals2, numkeys2; + REG_KEY *t1,*t2; + REG_VAL *v1, *v2; + WERROR error1, error2; - numkeys1 = reg_key_num_subkeys(oldkey); - for(i = 0; i < numkeys1; i++) { - REG_KEY *t1 = reg_key_get_subkey_by_index(oldkey, i); - if(!reg_key_get_subkey_by_name(newkey, reg_key_name(t1))) { + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(oldkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(newkey, reg_key_name(t1), &t2); + if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "-%s\n", reg_key_get_path(t1)+1); + } else if(!W_ERROR_IS_OK(error2)) { + DEBUG(0, ("Error occured while getting subkey by name: %d\n", error2)); } } - numkeys2 = reg_key_num_subkeys(newkey); - for(i = 0; i < numkeys2; i++) { - REG_KEY *t1 = reg_key_get_subkey_by_index(newkey, i); - REG_KEY *t2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1)); - if(!t2) { + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting subkey by index: %d\n", error1)); + return; + } + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(newkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1), &t2); + if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1); + } else if(!W_ERROR_IS_OK(error2)) { + DEBUG(0, ("Error occured while getting subkey by name: %d\n", error2)); } writediff(t2, t1, out); } - numvals2 = reg_key_num_values(newkey); - for(i = 0; i < numvals2; i++) { - REG_VAL *t1 = reg_key_get_value_by_index(newkey, i); - REG_VAL *t2 = reg_key_get_value_by_name(oldkey, reg_val_name(t1)); - if(!t2 || reg_val_size(t2) != reg_val_size(t1) || memcmp(reg_val_data_blk(t1), reg_val_data_blk(t2), reg_val_size(t1))) { - fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(t1), str_regtype(reg_val_type(t1)), reg_val_data_string(t1)); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting subkey by index: %d\n", error1)); + return; + } + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(newkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(oldkey, reg_val_name(v1), &v2); + if ((W_ERROR_IS_OK(error2) && reg_val_size(v2) != reg_val_size(v1) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1))) + || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(v1), str_regtype(reg_val_type(v1)), reg_val_data_string(v1)); + } + + if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + DEBUG(0, ("Error occured while getting value by name: %d\n", error2)); } } - numvals1 = reg_key_num_values(oldkey); - for(i = 0; i < numvals1; i++) { - REG_VAL *t1 = reg_key_get_value_by_index(oldkey, i); - if(!reg_key_get_value_by_name(newkey, reg_val_name(t1))) { - fprintf(out, "\"%s\"=-\n", reg_val_name(t1)); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting value by index: %d\n", error1)); + return; + } + + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(oldkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(newkey, reg_val_name(v1), &v2); + if(W_ERROR_IS_OK(error2)) { + } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + fprintf(out, "\"%s\"=-\n", reg_val_name(v1)); + } else { + DEBUG(0, ("Error occured while getting value by name: %d\n", error2)); } } + + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting value by index: %d\n", error1)); + return; + } } int main (int argc, char **argv) @@ -69,15 +99,18 @@ int main (int argc, char **argv) REG_KEY *root; const char *backend1 = NULL, *backend2 = NULL; const char *location2; + const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; REG_HANDLE *h2; REG_KEY *root1 = NULL, *root2; int from_null = 0; int fullpath = 0, no_values = 0; + WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, + {"credentials", 'c', POPT_ARG_STRING, NULL, 'c', "credentials", NULL}, {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" }, POPT_TABLEEND @@ -87,7 +120,11 @@ int main (int argc, char **argv) while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { - case 'b': + case 'c': + if(!credentials1 && !from_null) credentials1 = poptGetOptArg(pc); + else if(!credentials2) credentials2 = poptGetOptArg(pc); + break; + case 'b': if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); else if(!backend2) backend2 = poptGetOptArg(pc); break; @@ -106,13 +143,13 @@ int main (int argc, char **argv) if(!backend1) backend1 = "dir"; - h1 = reg_open(backend1, location1, True); - if(!h1) { + error = reg_open(backend1, location1, credentials1, &h1); + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); return 1; } - root1 = reg_get_root(h1); + if(!W_ERROR_IS_OK(reg_get_root(h1, &root1))) return 1; } location2 = poptGetArg(pc); @@ -123,14 +160,14 @@ int main (int argc, char **argv) if(!backend2) backend2 = "dir"; - h2 = reg_open(backend2, location2, True); - if(!h2) { + error = reg_open(backend2, location2, credentials2, &h2); + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); return 1; } - root2 = reg_get_root(h2); - if(!root2) { + error = reg_get_root(h2, &root2); + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2); return 1; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 27f578e37f..9a51b0f7ff 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -664,11 +664,13 @@ static CMD_FILE *cmd_file_create(const char *file) char *str_type(unsigned char type); -int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) +int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) { CMD *cmd; - int modified = 0; + BOOL modified = False; CMD_FILE *cmd_file = NULL; + REG_KEY *tmp = NULL; + WERROR error; cmd_file = cmd_file_create(cmd_file_name); while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) { @@ -677,17 +679,22 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) * Now, apply the requests to the tree ... */ switch (cmd->cmd) { - case CMD_ADD_KEY: { - REG_KEY *tmp = NULL; - tmp = reg_open_key(reg_get_root(regf), cmd->key); + case CMD_ADD_KEY: + error = reg_open_key(root, cmd->key, &tmp); + /* If we found it, apply the other bits, else create such a key */ - if (!tmp) { - if(reg_key_add_name_recursive(reg_get_root(regf), cmd->key)) { - tmp = reg_open_key(reg_get_root(regf), cmd->key); + if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { + if(W_ERROR_IS_OK(reg_key_add_name_recursive(root, cmd->key))) { + error = reg_open_key(root, cmd->key, &tmp); + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key)); + continue; + } } else { DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); + continue; } - modified = 1; + modified = True; } while (cmd->val_count) { @@ -695,15 +702,21 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) REG_VAL *reg_val = NULL; if (val->type == REG_DELETE) { - reg_val = reg_key_get_value_by_name( tmp, val->name); - reg_val_del(reg_val); - modified = 1; + error = reg_key_get_value_by_name( tmp, val->name, ®_val); + if(W_ERROR_IS_OK(error)) { + error = reg_val_del(reg_val); + } + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error removing value '%s'\n", val->name)); + } + modified = True; } else { - /* FIXME - reg_val = nt_add_reg_value(tmp, val->name, val->type, - val->val); */ - modified = 1; + if(!W_ERROR_IS_OK(reg_key_add_value(tmp, val->name, val->type, val->val, strlen(val->val)))) { + DEBUG(0, ("Error adding new value '%s'\n", val->name)); + continue; + } + modified = True; } cmd->val_spec_list = val->next; @@ -712,7 +725,6 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) } break; - } case CMD_DEL_KEY: /* @@ -720,8 +732,18 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) * Find the key if it exists, and delete it ... */ - reg_key_del_recursive(reg_open_key(reg_get_root(regf), cmd->key)); - modified = 1; + error = reg_open_key(root, cmd->key, &tmp); + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); + continue; + } + + error = reg_key_del_recursive(tmp); + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to delete key '%s'\n", cmd->key)); + continue; + } + modified = True; break; } } @@ -737,13 +759,16 @@ int main (int argc, char **argv) poptContext pc; REG_KEY *root; const char *location; + const char *credentials = NULL; const char *patch; - char *backend = "dir"; + const char *backend = "dir"; REG_HANDLE *h; int fullpath = 0, no_values = 0; + WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL}, + {"credentials", 'c', POPT_ARG_STRING, &credentials, 'c', "credentials (user%password", NULL}, POPT_TABLEEND }; @@ -760,7 +785,7 @@ int main (int argc, char **argv) return 1; } - h = reg_open(backend, location, True); + error = reg_open(backend, location, credentials, &h); if(!h) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); return 1; @@ -770,7 +795,15 @@ int main (int argc, char **argv) if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); - nt_apply_reg_command_file(h, patch); + error = reg_get_root(h, &root); + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error opening root!\n")); + return 1; + } + + nt_apply_reg_command_file(root, patch); + + reg_free(h); return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index e6b5fa51ee..d60ca1ff46 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -40,10 +40,14 @@ static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) { REG_KEY *new; + WERROR error; if(argc < 2) { new = cur; } else { - new = reg_open_key(cur, argv[1]); + error = reg_open_key(cur, argv[1], &new); + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error opening specified key\n")); + } } if(!new) new = cur; @@ -56,28 +60,32 @@ static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) { int i, num; - num = reg_key_num_subkeys(cur); - for(i = 0; i < num; i++) { - REG_KEY *sub = reg_key_get_subkey_by_index(cur, i); + WERROR error; + REG_VAL *value; + REG_KEY *sub; + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(cur, i, &sub)); i++) { printf("K %s\n", reg_key_name(sub)); } - num = reg_key_num_values(cur); - for(i = 0; i < num; i++) { - REG_VAL *sub = reg_key_get_value_by_index(cur, i); - printf("V %s %s %s\n", reg_val_name(sub), str_regtype(reg_val_type(sub)), reg_val_data_string(sub)); + if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while browsing thru keys\n")); + } + + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(cur, i, &value)); i++) { + printf("V \"%s\" %s %s\n", reg_val_name(value), str_regtype(reg_val_type(value)), reg_val_data_string(value)); } return NULL; } static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) { + REG_KEY *tmp; if(argc < 2) { fprintf(stderr, "Usage: mkkey \n"); return NULL; } - if(!reg_key_add_name(cur, argv[1])) { + if(!W_ERROR_IS_OK(reg_key_add_name(cur, argv[1], 0, NULL, &tmp))) { fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]); return NULL; } @@ -95,13 +103,12 @@ static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) return NULL; } - key = reg_open_key(cur, argv[1]); - if(!key) { + if(!W_ERROR_IS_OK(reg_open_key(cur, argv[1], &key))) { fprintf(stderr, "No such subkey '%s'\n", argv[1]); return NULL; } - if(!reg_key_del(key)) { + if(!W_ERROR_IS_OK(reg_key_del(key))) { fprintf(stderr, "Error deleting '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted '%s'\n", argv[1]); @@ -118,13 +125,12 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) return NULL; } - val = reg_key_get_value_by_name(cur, argv[1]); - if(!val) { + if(!W_ERROR_IS_OK(reg_key_get_value_by_name(cur, argv[1], &val))) { fprintf(stderr, "No such value '%s'\n", argv[1]); return NULL; } - if(!reg_val_del(val)) { + if(!W_ERROR_IS_OK(reg_val_del(val))) { fprintf(stderr, "Error deleting value '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); @@ -196,13 +202,16 @@ int main (int argc, char **argv) uint32 setparms, checkparms; int opt; char *backend = "dir"; + char *credentials = NULL; REG_KEY *curkey = NULL;; poptContext pc; + WERROR error; REG_HANDLE *h; struct poptOption long_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL}, POPT_TABLEEND }; @@ -211,8 +220,8 @@ int main (int argc, char **argv) while((opt = poptGetNextOpt(pc)) != -1) { } - h = reg_open(backend, poptPeekArg(pc), True); - if(!h) { + error = reg_open(backend, poptPeekArg(pc), credentials, &h); + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); return 1; } @@ -220,9 +229,9 @@ int main (int argc, char **argv) setup_logging("regtree", True); - curkey = reg_get_root(h); + error = reg_get_root(h, &curkey); - if(!curkey) return 1; + if(!W_ERROR_IS_OK(error)) return 1; while(True) { char *line, *prompt; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 80cbccf48f..548a702d48 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -23,31 +23,38 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals) { - int num_subkeys, i, num_values; + REG_KEY *subkey; + REG_VAL *value; + WERROR error; + int i; for(i = 0; i < l; i++) putchar(' '); if(fullpath) printf("%s\n", reg_key_get_path(p)); else printf("%s\n", reg_key_name(p)); - num_subkeys = reg_key_num_subkeys(p); - for(i = 0; i < num_subkeys; i++) { - REG_KEY *subkey = reg_key_get_subkey_by_index(p, i); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(p, i, &subkey)); i++) { print_tree(l+1, subkey, fullpath, novals); reg_key_free(subkey); } + if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p))); + } + if(!novals) { - num_values = reg_key_num_values(p); - for(i = 0; i < num_values; i++) { + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(p, i, &value)); i++) { int j; char *desc; - REG_VAL *value = reg_key_get_value_by_index(p, i); for(j = 0; j < l+1; j++) putchar(' '); desc = reg_val_description(value); printf("%s\n", desc); free(desc); reg_val_free(value); } + + if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p))); + } } } @@ -55,15 +62,17 @@ int main (int argc, char **argv) { uint32 setparms, checkparms; int opt; - char *backend = "dir"; + char *backend = "dir", *credentials = NULL; poptContext pc; REG_KEY *root; REG_HANDLE *h; + WERROR error; int fullpath = 0, no_values = 0; struct poptOption long_options[] = { POPT_AUTOHELP {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, + {"credentials", 'c', POPT_ARG_NONE, &credentials, 0, "credentials (user%password)", NULL}, {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, POPT_TABLEEND }; @@ -75,15 +84,15 @@ int main (int argc, char **argv) setup_logging("regtree", True); - h = reg_open(backend, poptPeekArg(pc), True); - if(!h) { + error = reg_open(backend, poptPeekArg(pc), credentials, &h); + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); return 1; } poptFreeContext(pc); - root = reg_get_root(h); - if(!root) return 1; + error = reg_get_root(h, &root); + if(!W_ERROR_IS_OK(error)) return 1; print_tree(0, root, fullpath, no_values); -- cgit From 040d6261f7281a31a0e0adbf1f6f018de858cffc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Apr 2004 07:28:27 +0000 Subject: r131: mark some scripts executable (This used to be commit fe1a5a8e2564611450bbef0f500ba6d554527fed) --- source4/lib/ldb/tests/test-generic.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 source4/lib/ldb/tests/test-generic.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh old mode 100644 new mode 100755 -- cgit From 42889e5e1e276c8957cc666991364c6f0b6bdc79 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Apr 2004 08:06:39 +0000 Subject: r134: - added ldb to the build of smbd - fixed build of the ldb registry backend (This used to be commit 0b66590330603efaa816fd2348c05a994a1580ef) --- source4/lib/ldb/include/proto.h | 0 source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 5 ++--- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 source4/lib/ldb/include/proto.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/proto.h b/source4/lib/ldb/include/proto.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 3cc1651519..9e561b1e6c 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -20,7 +20,6 @@ #include "includes.h" #include "lib/registry/common/registry.h" -#include "lib/ldb/include/ldb.h" char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) { @@ -81,7 +80,7 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) /* FIXME */ } - ldap_search_free(c, msg); + ldb_search_free(c, msg); talloc_destroy(mem_ctx); return WERR_OK; } @@ -103,7 +102,7 @@ static WERROR ldb_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) /* FIXME */ } - ldap_search_free(c, msg); + ldb_search_free(c, msg); talloc_destroy(mem_ctx); return WERR_OK;; -- cgit From 4d1add159da528b3ba6101e00a0a88b0f35f3de4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Apr 2004 08:07:43 +0000 Subject: r135: some test ldif for an idea I am playing with to replace smb.conf with a ldb Don't panic - I'll explain more when I get a chance (This used to be commit 090afa94a73d7fe13604785fa97ffb71c2be2641) --- source4/lib/ldb/tests/test-config.ldif | 45 ++++++++++++++++++++++++++ source4/lib/ldb/tests/test-default-config.ldif | 17 ++++++++++ 2 files changed, 62 insertions(+) create mode 100644 source4/lib/ldb/tests/test-config.ldif create mode 100644 source4/lib/ldb/tests/test-default-config.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-config.ldif b/source4/lib/ldb/tests/test-config.ldif new file mode 100644 index 0000000000..92592a2d66 --- /dev/null +++ b/source4/lib/ldb/tests/test-config.ldif @@ -0,0 +1,45 @@ +############################## +# global configuration options +dn: cn=Global,cn=Config,cn=Samba +objectclass: globalconfig +Workgroup: VNET3 +UnixCharset: UTF8 +Security: user +Interfaces: vmnet* eth* +NetbiosName: blu +GuestAccount: tridge + +############################## +# [test] share +dn: cn=test,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: test +Comment: a test share +Path: /home/tridge/samba4/prefix/test +ReadOnly: no + +##################################### +# [msdn] a remote proxy share, stored +# on \\msdn\test +dn: cn=msdn,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: msdn +NtvfsHandler: cifs +ReadOnly: no +_CifsServer: msdn +_CifsUser: administrator +_CifsPassword: penguin +_CifsDomain: winxp +_CifsShare: test + + +############################## +# [VisualC] share +dn: cn=visualc,cn=Shares,cn=Config,cn=Samba +objectclass: fileshare +cn: VisualC +Comment: VisualC development +Path: /home/tridge/VisualC +ReadOnly: no +NtvfsHandler: simple + diff --git a/source4/lib/ldb/tests/test-default-config.ldif b/source4/lib/ldb/tests/test-default-config.ldif new file mode 100644 index 0000000000..87b7bcd3cc --- /dev/null +++ b/source4/lib/ldb/tests/test-default-config.ldif @@ -0,0 +1,17 @@ +############################## +# global configuration options +dn: cn=Global,cn=DefaultConfig,cn=Samba +objectclass: globalconfig +Workgroup: WORKGROUP +UnixCharset: UTF8 +Security: user +NetbiosName: blu +GuestAccount: nobody + +############################## +# [_default_] share +dn: cn=_default_,cn=Shares,cn=DefaultConfig,cn=Samba +objectclass: fileshare +cn: _default_ +Path: /tmp +ReadOnly: yes -- cgit From ab53890d59c8d25cefd333c0b15046f8a7ac5f8f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Apr 2004 08:08:19 +0000 Subject: r136: I forgot to add config.m4 for ldb in my ldb commit (This used to be commit 299009fde93a64841738c30422f342004671ce2d) --- source4/lib/ldb/config.m4 | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 source4/lib/ldb/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 new file mode 100644 index 0000000000..6b097c34ec --- /dev/null +++ b/source4/lib/ldb/config.m4 @@ -0,0 +1,7 @@ +SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], + [lib/ldb/ldb_tdb/ldb_pack.o \ + lib/ldb/common/ldb_ldif.o lib/ldb/ldb_tdb/ldb_search.o \ + lib/ldb/common/ldb_parse.o lib/ldb/ldb_tdb/ldb_tdb.o \ + lib/ldb/common/util.o lib/ldb/ldb_ldap/ldb_ldap.o \ + lib/ldb/ldb_tdb/ldb_index.o lib/ldb/ldb_tdb/ldb_match.o], + lib/ldb/include/ldb.h) -- cgit From 177777b05534c86514f5ee79b67532537bfd99dd Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Sat, 10 Apr 2004 06:10:26 +0000 Subject: r141: A number of changes to get things working on FreeBSD and reduce the breakage caused by someone recently ... 1. Add configure check HAVE_COMPARISON_FN_T to see if this is defined. I have not checked this on Linux yet, but will do so soon. 2. Add the definitions of malloc_p, realloc_p etc. 3. Check for LDAP and don't build stuff that depends on LDAP if we don't\ have it. It currently builds on FreeBSD but there is one warning printed out at the end. (This used to be commit 7b34fbe0f2ef175e5504e34e4f3cdf9a0563970f) --- source4/lib/ldb/common/ldb.c | 2 ++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 4 +++- source4/lib/ldb/ldb_tdb/ldb_pack.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 90b77e1e7f..3ba4434e07 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -52,9 +52,11 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, return ltdb_connect(url, flags, options); } +#ifdef HAVE_LDAP if (strncmp(url, "ldap", 4) == 0) { return lldb_connect(url, flags, options); } +#endif /*HAVE_LDAP*/ errno = EINVAL; return NULL; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index e6cbb52cad..25dad914da 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -33,7 +33,8 @@ */ #include "includes.h" -#include "ldb_ldap/ldb_ldap.h" +#if HAVE_LDAP +#include "ldb_ldap.h" #if 0 /* @@ -518,3 +519,4 @@ failed: if (ldb) free(ldb); return NULL; } +#endif /*HAVE_LDAP*/ diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 1b0c8a1857..5964e0751d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb/ldb_tdb.h" +#include "ldb_tdb.h" /* change this if the data format ever changes */ #define LTDB_PACKING_FORMAT 0x26011966 diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index d7a7b7ffbd..5905231b32 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb/ldb_tdb.h" +#include "ldb_tdb.h" /* free a message that has all parts separately allocated diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 95dce498f1..ec90eec03f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb/ldb_tdb.h" +#include "ldb_tdb.h" /* form a TDB_DATA for a record key -- cgit From 91b30df39bfaec8bfa32be40a13fd62008f66b9e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 10 Apr 2004 18:24:45 +0000 Subject: r147: - Remove dublicate ldap tests (richard the current test is in libads/config.m4 :-) - Move sendfile check to ntvfs/config.m4 - Move comparison_fn_t check to build/m4/rewrite.m4 Please do not new tests to configure.in directly, please add them to the subsystems config.m4 file where they belong to or to build/m4/rewrite.m4 if you don't know where to put it for now Thanks I know samba4's build system is not completly rewritten. I have a lot of updatest in my local tree, but it's not complete yet when it's complete I'll write documentation for it:-) metze (This used to be commit 31c23f14d60a4aa41e0500e369f25ed6dc7ddae7) --- source4/lib/ldb/config.m4 | 22 ++++++++++++++++------ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 6b097c34ec..6fdfcf526a 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,7 +1,17 @@ + +SMB_MODULE(libldb_tdb,LIBLDB,STATIC, + [lib/ldb/ldb_tdb/ldb_tdb.o \ + lib/ldb/ldb_tdb/ldb_pack.o \ + lib/ldb/ldb_tdb/ldb_search.o \ + lib/ldb/ldb_tdb/ldb_index.o \ + lib/ldb/ldb_tdb/ldb_match.o]) + +if test x"$with_ldap_support" = x"yes"; then + SMB_MODULE_DEFAULT(libldb_ldap,STATIC) +fi +SMB_MODULE(libldb_ldap,LIBLDB,NOT,[lib/ldb/ldb_ldap/ldb_ldap.o]) + SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], - [lib/ldb/ldb_tdb/ldb_pack.o \ - lib/ldb/common/ldb_ldif.o lib/ldb/ldb_tdb/ldb_search.o \ - lib/ldb/common/ldb_parse.o lib/ldb/ldb_tdb/ldb_tdb.o \ - lib/ldb/common/util.o lib/ldb/ldb_ldap/ldb_ldap.o \ - lib/ldb/ldb_tdb/ldb_index.o lib/ldb/ldb_tdb/ldb_match.o], - lib/ldb/include/ldb.h) + [lib/ldb/common/ldb_ldif.o \ + lib/ldb/common/ldb_parse.o \ + lib/ldb/common/util.o]) diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index edf525f895..30afe223ea 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -5,7 +5,7 @@ struct ltdb_private { unsigned int connect_flags; }; - +#ifdef STANDALONE #define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) #define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0) - +#endif -- cgit From ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Apr 2004 20:18:22 +0000 Subject: r152: a quick airport commit .... added ldbedit, a _really_ useful command added ldbadd, ldbdel, ldbsearch and ldbmodify to build solved lots of timezone issues, we now pass the torture tests with client and server in different zones fixed several build issues I know this breaks the no-LDAP build. Wait till I arrive in San Jose for that fix. (This used to be commit af34710d4da1841653624fe304b1c8d812c0fdd9) --- source4/lib/ldb/Makefile.ldb | 8 +- source4/lib/ldb/common/ldb.c | 2 +- source4/lib/ldb/common/ldb_ldif.c | 22 +- source4/lib/ldb/common/ldb_msg.c | 133 ++++++++ source4/lib/ldb/common/util.c | 6 +- source4/lib/ldb/config.m4 | 46 ++- source4/lib/ldb/include/includes.h | 3 + source4/lib/ldb/include/ldb.h | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 5 +- source4/lib/ldb/ldb_tdb/ldb_pack.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 36 +-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 +- source4/lib/ldb/tools/ldbadd.c | 99 ++++-- source4/lib/ldb/tools/ldbdel.c | 41 ++- source4/lib/ldb/tools/ldbedit.c | 365 +++++++++++++++++++++ source4/lib/ldb/tools/ldbmodify.c | 100 ++++-- source4/lib/ldb/tools/ldbsearch.c | 32 +- source4/lib/replace.c | 2 +- source4/lib/time.c | 593 ++++++++--------------------------- 20 files changed, 927 insertions(+), 576 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_msg.c create mode 100644 source4/lib/ldb/tools/ldbedit.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 0610ccf19b..2a41629852 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -12,13 +12,14 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/ldb_parse.o +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ + common/ldb_parse.o common/ldb_msg.o OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit LIBS = $(LDB_LIB)($(OBJS)) @@ -46,6 +47,9 @@ bin/ldbdel: tools/ldbdel.o $(LIBS) bin/ldbmodify: tools/ldbmodify.o $(LIBS) $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) +bin/ldbedit: tools/ldbedit.o $(LIBS) + $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) + clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 3ba4434e07..146745043f 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -80,7 +80,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { return ldb->ops->search(ldb, base, scope, expression, attrs, res); } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index b4c27c3369..5f2fccfebc 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -90,7 +90,7 @@ char *ldb_base64_encode(const char *buf, int len) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; - unsigned char *d = (unsigned char *)buf; + const unsigned char *d = (const unsigned char *)buf; int bytes = (len*8 + 5)/6; char *out; @@ -222,6 +222,23 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), } for (i=0;inum_elements;i++) { + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + fprintf_fn(private, "add: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_DELETE: + fprintf_fn(private, "delete: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_REPLACE: + fprintf_fn(private, "replace: %s\n", + msg->elements[i].name); + break; + } + } + for (j=0;jelements[i].num_values;j++) { if (ldb_should_b64_encode(&msg->elements[i].values[j])) { ret = fprintf_fn(private, "%s:: ", @@ -246,6 +263,9 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), CHECK_RET; } } + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + fprintf_fn(private, "-\n"); + } } ret = fprintf_fn(private,"\n"); CHECK_RET; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c new file mode 100644 index 0000000000..633cc91f2c --- /dev/null +++ b/source4/lib/ldb/common/ldb_msg.c @@ -0,0 +1,133 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb message component utility functions + * + * Description: functions for manipulating ldb_message structures + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + find an element in a message by attribute name +*/ +struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, + const char *attr_name) +{ + int i; + for (i=0;inum_elements;i++) { + if (strcmp(msg->elements[i].name, attr_name) == 0) { + return &msg->elements[i]; + } + } + return NULL; +} + + +/* + find a value in an element +*/ +struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, + struct ldb_val *val) +{ + int i; + for (i=0;inum_values;i++) { + if (ldb_val_equal(val, &el->values[i])) { + return &el->values[i]; + } + } + return NULL; +} + + +/* + add an empty element to a message +*/ +int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) +{ + struct ldb_message_element *els; + + els = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + if (!els) { + errno = ENOMEM; + return -1; + } + + els[msg->num_elements].values = NULL; + els[msg->num_elements].num_values = 0; + els[msg->num_elements].flags = flags; + els[msg->num_elements].name = strdup(attr_name); + if (!els[msg->num_elements].name) { + return -1; + } + + msg->elements = els; + msg->num_elements++; + + return 0; +} + +/* + add an empty element to a message +*/ +int ldb_msg_add(struct ldb_message *msg, + const struct ldb_message_element *el, + int flags) +{ + if (ldb_msg_add_empty(msg, el->name, flags) != 0) { + return -1; + } + + msg->elements[msg->num_elements-1] = *el; + msg->elements[msg->num_elements-1].flags = flags; + + return 0; +} + +/* + compare two ldb_message_element structures +*/ +int ldb_msg_element_compare(struct ldb_message_element *el1, + struct ldb_message_element *el2) +{ + int i; + + if (el1->num_values != el2->num_values) { + return el1->num_values - el2->num_values; + } + + for (i=0;inum_values;i++) { + if (!ldb_msg_find_val(el2, &el1->values[i])) { + return -1; + } + } + + return 0; +} diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index d198a1ad92..e1a7ada1c6 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -77,11 +77,11 @@ int list_find(const void *needle, int r; test_i = (min_i + max_i) / 2; - r = comp_fn(needle, *(void **)(base_p + (size * test_i))); + r = comp_fn(needle, *(void * const *)(base_p + (size * test_i))); if (r == 0) { /* scan back for first element */ while (test_t > 0 && - comp_fn(needle, *(void **)(base_p + (size * (test_i-1)))) == 0) { + comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) { test_i--; } return test_i; @@ -94,7 +94,7 @@ int list_find(const void *needle, } } - if (comp_fn(needle, *(void **)(base_p + (size * min_i))) == 0) { + if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) { return min_i; } diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 6fdfcf526a..7c4749ab02 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,17 +1,37 @@ - -SMB_MODULE(libldb_tdb,LIBLDB,STATIC, - [lib/ldb/ldb_tdb/ldb_tdb.o \ - lib/ldb/ldb_tdb/ldb_pack.o \ +SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], + [lib/ldb/common/ldb_ldif.o \ + lib/ldb/common/ldb_parse.o \ + lib/ldb/common/ldb_msg.o \ + lib/ldb/common/util.o \ lib/ldb/ldb_tdb/ldb_search.o \ + lib/ldb/ldb_tdb/ldb_tdb.o \ + lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ - lib/ldb/ldb_tdb/ldb_match.o]) + lib/ldb/ldb_tdb/ldb_match.o \ + lib/ldb/ldb_ldap/ldb_ldap.o], + lib/ldb/include/ldb.h) -if test x"$with_ldap_support" = x"yes"; then - SMB_MODULE_DEFAULT(libldb_ldap,STATIC) -fi -SMB_MODULE(libldb_ldap,LIBLDB,NOT,[lib/ldb/ldb_ldap/ldb_ldap.o]) +SMB_SUBSYSTEM(LDBADD,[], + [lib/ldb/tools/ldbadd.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) -SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], - [lib/ldb/common/ldb_ldif.o \ - lib/ldb/common/ldb_parse.o \ - lib/ldb/common/util.o]) +SMB_SUBSYSTEM(LDBDEL,[], + [lib/ldb/tools/ldbdel.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBMODIFY,[], + [lib/ldb/tools/ldbmodify.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBSEARCH,[], + [lib/ldb/tools/ldbsearch.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBEDIT,[], + [lib/ldb/tools/ldbedit.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index ea8540d330..70ad1f3588 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -2,7 +2,9 @@ a temporary includes file until I work on the ldb build system */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include #include @@ -11,6 +13,7 @@ #include #include #include +#include #include "ldb.h" #include "ldb_parse.h" diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 12064bbf75..dc1b1d7732 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -174,7 +174,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res); + char * const attrs[], struct ldb_message ***res); /* free a set of messages returned by ldb_search diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 25dad914da..25af43c569 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -33,8 +33,7 @@ */ #include "includes.h" -#if HAVE_LDAP -#include "ldb_ldap.h" +#include "ldb/ldb_ldap/ldb_ldap.h" #if 0 /* @@ -519,4 +518,4 @@ failed: if (ldb) free(ldb); return NULL; } -#endif /*HAVE_LDAP*/ + diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 5964e0751d..1196e561a2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* change this if the data format ever changes */ #define LTDB_PACKING_FORMAT 0x26011966 diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 5905231b32..9cb5853c94 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* free a message that has all parts separately allocated @@ -55,22 +55,6 @@ static void msg_free_all_parts(struct ldb_message *msg) } -/* - TODO: this should take advantage of the sorted nature of the message - - return index of the attribute, or -1 if not found -*/ -int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr) -{ - int i; - for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, attr) == 0) { - return i; - } - } - return -1; -} - /* duplicate a ldb_val structure */ @@ -193,7 +177,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, } for (i=0;attrs[i];i++) { - int j; + struct ldb_message_element *el; if (strcmp(attrs[i], "*") == 0) { if (msg_add_all_elements(ret, msg) != 0) { @@ -202,17 +186,15 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, } continue; } - j = ldb_msg_find_attr(msg, attrs[i]); - if (j == -1) { + + el = ldb_msg_find_element(msg, attrs[i]); + if (!el) { continue; } - do { - if (msg_add_element(ret, &msg->elements[j]) != 0) { - msg_free_all_parts(ret); - return NULL; - } - } while (++j < msg->num_elements && - strcmp(attrs[i], msg->elements[j].name) == 0); + if (msg_add_element(ret, el) != 0) { + msg_free_all_parts(ret); + return NULL; + } } return ret; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index ec90eec03f..b28d73cbea 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* form a TDB_DATA for a record key diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 30afe223ea..efb0af1c9c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -5,7 +5,9 @@ struct ltdb_private { unsigned int connect_flags; }; -#ifdef STANDALONE +#ifndef IVAL #define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) +#endif +#ifndef SIVAL #define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0) #endif diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 92ed29e6b8..446c0d80f9 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -34,28 +34,28 @@ #include "includes.h" - int main(void) -{ - static struct ldb_context *ldb; - struct ldb_ldif *ldif; - int ret; - int count=0, failures=0; - const char *ldb_url; - - ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } +static int failures; - ldb = ldb_connect(ldb_url, 0, NULL); +static void usage(void) +{ + printf("Usage: ldbadd \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Adds records to a ldb, reading ldif the specified list of files\n\n"); + exit(1); +} - if (!ldb) { - perror("ldb_connect"); - exit(1); - } - while ((ldif = ldif_read_file(stdin))) { +/* + add records from an opened file +*/ +static int process_file(struct ldb_context *ldb, FILE *f) +{ + struct ldb_ldif *ldif; + int ret, count=0; + while ((ldif = ldif_read_file(f))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); @@ -73,6 +73,69 @@ ldif_read_free(ldif); } + return count; +} + + + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + int count=0; + const char *ldb_url; + int opt, i; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + if (argc == 0) { + usage(); + } + + for (i=0;i \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Deletes records from a ldb\n\n"); + exit(1); +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; int ret, i; const char *ldb_url; + int opt; ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + if (!ldb_url) { - ldb_url = "tdb://test.ldb"; + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); } + argc -= optind; + argv += optind; - if (argc < 2) { - printf("Usage: ldbdel \n"); + if (argc < 1) { + usage(); exit(1); } @@ -57,7 +85,7 @@ exit(1); } - for (i=1;idn; + mod.num_elements = 0; + mod.elements = NULL; + + /* look in msg2 to find elements that need to be added + or modified */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg1, msg2->elements[i].name); + + if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) { + continue; + } + + if (ldb_msg_add(&mod, + &msg2->elements[i], + el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { + return -1; + } + } + + /* look in msg1 to find elements that need to be deleted */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg2, msg1->elements[i].name); + if (!el) { + if (ldb_msg_add_empty(&mod, + msg1->elements[i].name, + LDB_FLAG_MOD_DELETE) != 0) { + return -1; + } + } + } + + if (mod.num_elements == 0) { + return 0; + } + + if (ldb_modify(ldb, &mod) != 0) { + fprintf(stderr, "failed to modify %s\n", msg1->dn); + return -1; + } + + return 0; +} + +/* + find dn in msgs[] +*/ +static struct ldb_message *msg_find(struct ldb_message **msgs, int count, + const char *dn) +{ + int i; + for (i=0;idn) == 0) { + return msgs[i]; + } + } + return NULL; +} + +/* + merge the changes in msgs2 into the messages from msgs1 +*/ +static int merge_edits(struct ldb_context *ldb, + struct ldb_message **msgs1, int count1, + struct ldb_message **msgs2, int count2) +{ + int i; + struct ldb_message *msg; + int ret = 0; + + /* do the adds and modifies */ + for (i=0;idn); + if (!msg) { + if (ldb_add(ldb, msgs2[i]) != 0) { + fprintf(stderr, "failed to add %s\n", + msgs2[i]->dn); + return -1; + } + } else { + modify_record(ldb, msg, msgs2[i]); + } + } + + /* do the deletes */ + for (i=0;idn); + if (!msg) { + if (ldb_delete(ldb, msgs1[i]->dn) != 0) { + fprintf(stderr, "failed to delete %s\n", + msgs1[i]->dn); + return -1; + } + } + } + + return ret; +} + +/* + save a set of messages as ldif to a file +*/ +static int save_ldif(FILE *f, struct ldb_message **msgs, int count) +{ + int i; + + fprintf(f, "# returned %d records\n", count); + + for (i=0;imsg; + } + + fclose(f); + unlink(template); + + return merge_edits(ldb, msgs1, count1, msgs2, count2); +} + +static void usage(void) +{ + printf("Usage: ldbedit \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -s base|sub|one choose search scope\n"); + printf(" -b basedn choose baseDN\n"); + printf(" -a edit all records (expression 'dn=*')\n"); + printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n"); + exit(1); +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + struct ldb_message **msgs; + int ret; + const char *expression = NULL; + const char *ldb_url; + const char *basedn = NULL; + int opt; + enum ldb_scope scope = LDB_SCOPE_SUBTREE; + const char *editor; + + ldb_url = getenv("LDB_URL"); + + /* build the editor command to run - + use the same editor priorities as vipw */ + editor = getenv("VISUAL"); + if (!editor) { + editor = getenv("EDITOR"); + } + if (!editor) { + editor = "vi"; + } + + while ((opt = getopt(argc, argv, "ab:e:H:s:")) != EOF) { + switch (opt) { + case 'b': + basedn = optarg; + break; + + case 'H': + ldb_url = optarg; + break; + + case 's': + if (strcmp(optarg, "base") == 0) { + scope = LDB_SCOPE_BASE; + } else if (strcmp(optarg, "sub") == 0) { + scope = LDB_SCOPE_SUBTREE; + } else if (strcmp(optarg, "one") == 0) { + scope = LDB_SCOPE_ONELEVEL; + } + break; + + case 'e': + editor = optarg; + break; + + case 'a': + expression = "dn=*"; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + if (!expression) { + if (argc == 0) { + usage(); + } + expression = argv[0]; + } + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + ret = ldb_search(ldb, basedn, scope, expression, NULL, &msgs); + + if (ret == -1) { + printf("search failed - %s\n", ldb_errstring(ldb)); + exit(1); + } + + if (ret == 0) { + printf("no matching records - cannot edit\n"); + return 0; + } + + do_edit(ldb, msgs, ret, editor); + + if (ret > 0) { + ret = ldb_search_free(ldb, msgs); + if (ret == -1) { + fprintf(stderr, "search_free failed\n"); + exit(1); + } + } + + ldb_close(ldb); + return 0; +} diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index e1cff655db..a93c710a7a 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -34,27 +34,27 @@ #include "includes.h" - int main(void) -{ - static struct ldb_context *ldb; - struct ldb_ldif *ldif; - int ret; - int count=0, failures=0; - const char *ldb_url; - - ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } +static int failures; - ldb = ldb_connect(ldb_url, 0, NULL); - - if (!ldb) { - perror("ldb_connect"); - exit(1); - } +static void usage(void) +{ + printf("Usage: ldbmodify \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Modifies a ldb based upon ldif change records\n\n"); + exit(1); +} - while ((ldif = ldif_read_file(stdin))) { +/* + process modifies for one file +*/ +static int process_file(struct ldb_context *ldb, FILE *f) +{ + struct ldb_ldif *ldif; + int ret, count = 0; + + while ((ldif = ldif_read_file(f))) { switch (ldif->changetype) { case LDB_CHANGETYPE_NONE: case LDB_CHANGETYPE_ADD: @@ -77,6 +77,68 @@ ldif_read_free(ldif); } + return count; +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + int count=0; + const char *ldb_url; + int opt, i; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + if (argc == 0) { + usage(); + exit(1); + } + + for (i=0;i + +static void usage(void) +{ + printf("Usage: ldbsearch \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -s base|sub|one choose search scope\n"); + printf(" -b basedn choose baseDN\n"); + exit(1); +} int main(int argc, char * const argv[]) { - static struct ldb_context *ldb; + struct ldb_context *ldb; struct ldb_message **msgs; int ret, i; const char *expression; - const char * const *attrs = NULL; + char * const *attrs = NULL; const char *ldb_url; const char *basedn = NULL; int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } - while ((opt = getopt(argc, argv, "b:H:s:")) != EOF) { + while ((opt = getopt(argc, argv, "b:H:s:h")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -71,14 +77,24 @@ scope = LDB_SCOPE_ONELEVEL; } break; + + case 'h': + default: + usage(); + break; } } + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + argc -= optind; argv += optind; if (argc < 1) { - printf("Usage: ldbsearch [attrs...]\n"); + usage(); exit(1); } diff --git a/source4/lib/replace.c b/source4/lib/replace.c index a4f3da1a66..cde9ce7a1b 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -445,7 +445,7 @@ char *rep_inet_ntoa(struct in_addr ip) tm2 = *tm; tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); - t -= TimeDiff(t); + t -= TimeDiff(); return t; } diff --git a/source4/lib/time.c b/source4/lib/time.c index 2844da004d..d6c6396996 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. time handling functions - Copyright (C) Andrew Tridgell 1992-1998 + + Copyright (C) Andrew Tridgell 1992-2004 Copyright (C) Stefan (metze) Metzmacher 2002 + 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 @@ -20,36 +22,17 @@ #include "includes.h" -/* - This stuff was largely rewritten by Paul Eggert - in May 1996 - */ - - -int extra_time_offset = 0; - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - #ifndef TIME_T_MIN #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ - : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)) + : ~ (time_t) 0 << (sizeof (time_t) * 8 - 1)) #endif #ifndef TIME_T_MAX #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) #endif -void get_nttime_max(NTTIME *t) -{ - /* FIXME: This is incorrect */ - unix_to_nt_time(t, get_time_t_max()); -} - /******************************************************************* External access to time_t_min and time_t_max. ********************************************************************/ - time_t get_time_t_max(void) { return TIME_T_MAX; @@ -67,225 +50,38 @@ void GetTimeOfDay(struct timeval *tval) #endif } -#define TM_YEAR_BASE 1900 - /******************************************************************* yield the difference between *A and *B, in seconds, ignoring leap seconds ********************************************************************/ static int tm_diff(struct tm *a, struct tm *b) { - int ay = a->tm_year + (TM_YEAR_BASE - 1); - int by = b->tm_year + (TM_YEAR_BASE - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; } /******************************************************************* return the UTC offset in seconds west of UTC, or 0 if it cannot be determined ******************************************************************/ -static int TimeZone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - if (!tm) - return 0; - tm_utc = *tm; - tm = localtime(&t); - if (!tm) - return 0; - return tm_diff(&tm_utc,tm); - -} - -static BOOL done_serverzone_init; - -/* Return the smb serverzone value */ - -static int get_serverzone(void) -{ - static int serverzone; - - if (!done_serverzone_init) { - serverzone = TimeZone(time(NULL)); - - if ((serverzone % 60) != 0) { - DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n")); - } - - DEBUG(4,("Serverzone is %d\n",serverzone)); - - done_serverzone_init = True; - } - - return serverzone; -} - -/* Re-read the smb serverzone value */ - -static struct timeval start_time_hires; - -void TimeInit(void) -{ - done_serverzone_init = False; - get_serverzone(); - /* Save the start time of this process. */ - if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) - GetTimeOfDay(&start_time_hires); -} - -/********************************************************************** - Return a timeval struct of the uptime of this process. As TimeInit is - done before a daemon fork then this is the start time from the parent - daemon start. JRA. -***********************************************************************/ - -void get_process_uptime(struct timeval *ret_time) -{ - struct timeval time_now_hires; - - GetTimeOfDay(&time_now_hires); - ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec; - ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; - if (time_now_hires.tv_usec < start_time_hires.tv_usec) { - ret_time->tv_sec -= 1; - ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec); - } else - ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; -} - -/******************************************************************* -return the same value as TimeZone, but it should be more efficient. - -We keep a table of DST offsets to prevent calling localtime() on each -call of this function. This saves a LOT of time on many unixes. - -Updated by Paul Eggert -********************************************************************/ -static int TimeZoneFaster(time_t t) +int get_time_zone(time_t t) { - static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL; - static int table_size = 0; - int i; - int zone = 0; - - if (t == 0) t = time(NULL); - - /* Tunis has a 8 day DST region, we need to be careful ... */ -#define MAX_DST_WIDTH (365*24*60*60) -#define MAX_DST_SKIP (7*24*60*60) - - for (i=0;i= dst_table[i].start && t <= dst_table[i].end) break; - - if (i MAX_DST_SKIP*2) - t = dst_table[i].start - MAX_DST_SKIP; - else - t = low + (dst_table[i].start-low)/2; - if (TimeZone(t) == zone) - dst_table[i].start = t; - else - low = t; - } - - while (high-60*60 > dst_table[i].end) { - if (high - dst_table[i].end > MAX_DST_SKIP*2) - t = dst_table[i].end + MAX_DST_SKIP; - else - t = high - (high-dst_table[i].end)/2; - if (TimeZone(t) == zone) - dst_table[i].end = t; - else - high = t; - } -#if 0 - DEBUG(1,("Added DST entry from %s ", - asctime(localtime(&dst_table[i].start)))); - DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)), - dst_table[i].zone)); -#endif - } - } - return zone; -} - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time offset - **************************************************************************/ -int TimeDiff(time_t t) -{ - return TimeZoneFaster(t) + 60 * lp_time_offset(); -} - - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time - offset, for a local time value. If ut = lt + LocTimeDiff(lt), then - lt = ut - TimeDiff(ut), but the converse does not necessarily hold near - daylight savings transitions because some local times are ambiguous. - LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions. - +**************************************************************************/ -static int LocTimeDiff(time_t lte) -{ - time_t lt = lte - 60 * lp_time_offset(); - int d = TimeZoneFaster(lt); - time_t t = lt + d; - - /* if overflow occurred, ignore all the adjustments so far */ - if (((lte < lt) ^ (lp_time_offset() < 0)) | ((t < lt) ^ (d < 0))) - t = lte; - - /* now t should be close enough to the true UTC to yield the right answer */ - return TimeDiff(t); -} - - -/**************************************************************************** -try to optimise the localtime call, it can be quite expensive on some machines -****************************************************************************/ -struct tm *LocalTime(time_t *t) -{ - time_t t2 = *t; - - t2 -= TimeDiff(t2); - - return(gmtime(&t2)); + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); } #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) @@ -293,86 +89,36 @@ struct tm *LocalTime(time_t *t) /**************************************************************************** interpret an 8 byte "filetime" structure to a time_t It's originally in "100ns units since jan 1st 1601" - -It appears to be kludge-GMT (at least for file listings). This means -its the GMT you get by taking a localtime and adding the -serverzone. This is NOT the same as GMT in some cases. This routine -converts this to real GMT. ****************************************************************************/ time_t nt_time_to_unix(const NTTIME *nt) -{ - double d; - time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - - if (nt->high == 0) return(0); - - d = ((double)nt->high)*4.0*(double)(1<<30); - d += (nt->low&0xFFF00000); - d *= 1.0e-7; - - /* now adjust by 369 years to make the secs since 1970 */ - d -= TIME_FIXUP_CONSTANT; - - if (!(l_time_min <= d && d <= l_time_max)) - return(0); - - ret = (time_t)(d+0.5); - - /* this takes us from kludge-GMT to real GMT */ - ret -= get_serverzone(); - ret += LocTimeDiff(ret); - - return(ret); -} - -/**************************************************************************** - Convert a NTTIME structure to a time_t. - It's originally in "100ns units". - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 - if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM -****************************************************************************/ - -time_t nt_time_to_unix_abs(NTTIME *nt) { double d; time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - if (nt->high == 0) - return(0); - - if (nt->high==0x80000000 && nt->low==0) - return -1; - - /* reverse the time */ - /* it's a negative value, turn it to positive */ - nt->high=~nt->high; - nt->low=~nt->low; + if (nt->high == 0) { + return 0; + } d = ((double)nt->high)*4.0*(double)(1<<30); d += (nt->low&0xFFF00000); d *= 1.0e-7; - - if (!(l_time_min <= d && d <= l_time_max)) - return(0); + + /* now adjust by 369 years to make the secs since 1970 */ + d -= TIME_FIXUP_CONSTANT; + + if (TIME_T_MIN >= d || d >= TIME_T_MAX) { + return 0; + } ret = (time_t)(d+0.5); - return(ret); + return ret; } + /**************************************************************************** put a 8 byte filetime from a time_t -This takes real GMT as input and converts to kludge-GMT +This takes GMT as input ****************************************************************************/ void unix_to_nt_time(NTTIME *nt, time_t t) { @@ -394,9 +140,6 @@ void unix_to_nt_time(NTTIME *nt, time_t t) return; } - /* this converts GMT to kludge-GMT */ - t -= TimeDiff(t) - get_serverzone(); - d = (double)(t); d += TIME_FIXUP_CONSTANT; d *= 1.0e7; @@ -405,69 +148,15 @@ void unix_to_nt_time(NTTIME *nt, time_t t) nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); } -/**************************************************************************** - Convert a time_t to a NTTIME structure - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 - If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM -****************************************************************************/ - -void unix_to_nt_time_abs(NTTIME *nt, time_t t) -{ - double d; - - if (t==0) { - nt->low = 0; - nt->high = 0; - return; - } - - if (t == TIME_T_MAX) { - nt->low = 0xffffffff; - nt->high = 0x7fffffff; - return; - } - - if (t == -1) { - /* that's what NT uses for infinite */ - nt->low = 0x0; - nt->high = 0x80000000; - return; - } - - d = (double)(t); - d *= 1.0e7; - - nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); - - /* convert to a negative value */ - nt->high=~nt->high; - nt->low=~nt->low; -} - - -/**************************************************************************** -take an NTTIME structure, containing high / low time. convert to unix time. -lkclXXXX this may need 2 SIVALs not a memcpy. we'll see... -****************************************************************************/ -void put_long_date(char *p,time_t t) -{ - NTTIME nt; - unix_to_nt_time(&nt, t); - SIVAL(p, 0, nt.low); - SIVAL(p, 4, nt.high); -} /**************************************************************************** check if it's a null mtime ****************************************************************************/ BOOL null_mtime(time_t mtime) { - if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1) - return True; - return False; + return mtime == 0 || + mtime == (time_t)0xFFFFFFFF || + mtime == (time_t)-1; } /******************************************************************* @@ -496,7 +185,7 @@ static uint16 make_dos_time1(struct tm *t) create a 32 bit dos packed date/time from some parameters This takes a GMT time and returns a packed localtime structure ********************************************************************/ -static uint32 make_dos_date(time_t unixdate) +static uint32 make_dos_date(time_t unixdate, int zone_offset) { struct tm *t; uint32 ret=0; @@ -505,7 +194,9 @@ static uint32 make_dos_date(time_t unixdate) return 0; } - t = LocalTime(&unixdate); + unixdate -= zone_offset; + + t = gmtime(&unixdate); if (!t) { return 0xFFFFFFFF; } @@ -520,9 +211,9 @@ static uint32 make_dos_date(time_t unixdate) put a dos date into a buffer (time/date format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void put_dos_date(char *buf,int offset,time_t unixdate) +void push_dos_date(char *buf, int offset, time_t unixdate, int zone_offset) { - uint32 x = make_dos_date(unixdate); + uint32 x = make_dos_date(unixdate, zone_offset); SIVAL(buf,offset,x); } @@ -530,10 +221,10 @@ void put_dos_date(char *buf,int offset,time_t unixdate) put a dos date into a buffer (date/time format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void put_dos_date2(char *buf,int offset,time_t unixdate) +void push_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) { uint32 x; - x = make_dos_date(unixdate); + x = make_dos_date(unixdate, zone_offset); x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(buf,offset,x); } @@ -543,10 +234,11 @@ put a dos 32 bit "unix like" date into a buffer. This routine takes GMT and converts it to LOCAL time before putting it (most SMBs assume localtime for this sort of date) ********************************************************************/ -void put_dos_date3(char *buf,int offset,time_t unixdate) +void push_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) { - if (!null_mtime(unixdate)) - unixdate -= TimeDiff(unixdate); + if (!null_mtime(unixdate)) { + unixdate -= zone_offset; + } SIVAL(buf,offset,unixdate); } @@ -555,24 +247,24 @@ void put_dos_date3(char *buf,int offset,time_t unixdate) ********************************************************************/ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) { - uint32 p0,p1,p2,p3; + uint32 p0,p1,p2,p3; - p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; - p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; + p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; + p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; - *second = 2*(p0 & 0x1F); - *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); - *hour = (p1>>3)&0xFF; - *day = (p2&0x1F); - *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; - *year = ((p3>>1)&0xFF) + 80; + *second = 2*(p0 & 0x1F); + *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); + *hour = (p1>>3)&0xFF; + *day = (p2&0x1F); + *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; + *year = ((p3>>1)&0xFF) + 80; } /******************************************************************* create a unix date (int GMT) from a dos date (which is actually in localtime) ********************************************************************/ -time_t make_unix_date(void *date_ptr) +time_t pull_dos_date(const uint8 *date_ptr, int zone_offset) { uint32 dos_date=0; struct tm t; @@ -586,16 +278,17 @@ time_t make_unix_date(void *date_ptr) &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; - /* mktime() also does the local to GMT time conversion for us */ - ret = mktime(&t); + ret = timegm(&t); - return(ret); + ret += zone_offset; + + return ret; } /******************************************************************* like make_unix_date() but the words are reversed ********************************************************************/ -time_t make_unix_date2(void *date_ptr) +time_t pull_dos_date2(const uint8 *date_ptr, int zone_offset) { uint32 x,x2; @@ -603,18 +296,19 @@ time_t make_unix_date2(void *date_ptr) x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(&x,0,x2); - return make_unix_date((void *)&x); + return pull_dos_date((void *)&x, zone_offset); } /******************************************************************* create a unix GMT date from a dos date in 32 bit "unix like" format these generally arrive as localtimes, with corresponding DST ******************************************************************/ -time_t make_unix_date3(void *date_ptr) +time_t pull_dos_date3(const uint8 *date_ptr, int zone_offset) { time_t t = (time_t)IVAL(date_ptr,0); - if (!null_mtime(t)) - t += LocTimeDiff(t); + if (!null_mtime(t)) { + t += zone_offset; + } return t; } @@ -624,22 +318,25 @@ return a HTTP/1.0 time string ***************************************************************************/ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) { - char *buf; - fstring tempTime; - struct tm *tm = LocalTime(&t); + char *buf; + char tempTime[60]; + struct tm *tm = localtime(&t); + + if (!tm) { + return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); + } - if (!tm) - buf = talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); - else #ifndef HAVE_STRFTIME - buf = talloc_strdup(mem_ctx, asctime(tm)); - if(buf[strlen(buf)-1] == '\n') - buf[strlen(buf)-1] = 0; -#else /* !HAVE_STRFTIME */ + buf = talloc_strdup(mem_ctx, asctime(tm)); + if (buf[strlen(buf)-1] == '\n') { + buf[strlen(buf)-1] = 0; + } +#else strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); - buf = talloc_strdup(mem_ctx, tempTime); + buf = talloc_strdup(mem_ctx, tempTime); #endif /* !HAVE_STRFTIME */ - return buf; + + return buf; } @@ -647,90 +344,27 @@ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) /**************************************************************************** Return the date and time as a string ****************************************************************************/ - -char *timestring(TALLOC_CTX *mem_ctx, BOOL hires) +char *timestring(TALLOC_CTX *mem_ctx, time_t t) { char *TimeBuf; - fstring tempTime; - struct timeval tp; - time_t t; + char tempTime[80]; struct tm *tm; - if (hires) { - GetTimeOfDay(&tp); - t = (time_t)tp.tv_sec; - } else { - t = time(NULL); - } - tm = LocalTime(&t); + tm = localtime(&t); if (!tm) { - if (hires) { - TimeBuf = talloc_asprintf(mem_ctx, - "%ld.%06ld seconds since the Epoch", - (long)tp.tv_sec, - (long)tp.tv_usec); - } else { - TimeBuf = talloc_asprintf(mem_ctx, - "%ld seconds since the Epoch", - (long)t); - } - } else { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + #ifdef HAVE_STRFTIME - if (hires) { - strftime(tempTime,sizeof(tempTime)-1,"%Y/%m/%d %H:%M:%S",tm); - TimeBuf = talloc_asprintf(mem_ctx, "%s.%06ld", - tempTime, (long)tp.tv_usec); - } else { - strftime(tempTime,100,"%Y/%m/%d %H:%M:%S",tm); - TimeBuf = talloc_strdup(mem_ctx, tempTime); - } + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); #else - if (hires) { - TimeBuf = talloc_asprintf(mem_ctx, - "%s.%06ld", - asctime(tm), - (long)tp.tv_usec); - } else { - TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); - } + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); #endif - } - return(TimeBuf); -} - -/**************************************************************************** - return the best approximation to a 'create time' under UNIX from a stat - structure. -****************************************************************************/ - -time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) -{ - time_t ret, ret1; - - if(S_ISDIR(st->st_mode) && fake_dirs) - return (time_t)315493200L; /* 1/1/1980 */ - - ret = MIN(st->st_ctime, st->st_mtime); - ret1 = MIN(ret, st->st_atime); - - if(ret1 != (time_t)0) - return ret1; - - /* - * One of ctime, mtime or atime was zero (probably atime). - * Just return MIN(ctime, mtime). - */ - return ret; -} - -/**************************************************************************** -initialise an NTTIME to -1, which means "unknown" or "don't expire" -****************************************************************************/ -void init_nt_time(NTTIME *nt) -{ - nt->high = 0x7FFFFFFF; - nt->low = 0xFFFFFFFF; + return TimeBuf; } /**************************************************************************** @@ -738,9 +372,7 @@ check if NTTIME is 0 ****************************************************************************/ BOOL nt_time_is_zero(NTTIME *nt) { - if(nt->high==0) - return True; - return False; + return (nt->high==0); } /* @@ -749,6 +381,27 @@ BOOL nt_time_is_zero(NTTIME *nt) const char *nt_time_string(TALLOC_CTX *mem_ctx, const NTTIME *nt) { time_t t = nt_time_to_unix(nt); - return talloc_strdup(mem_ctx, http_timestring(mem_ctx, t)); + return talloc_strdup(mem_ctx, timestring(mem_ctx, t)); +} + + +/* + put a NTTIME into a packet +*/ +void push_nttime(void *base, uint16 offset, NTTIME *t) +{ + SIVAL(base, offset, t->low); + SIVAL(base, offset+4, t->high); +} + +/* + pull a NTTIME from a packet +*/ +NTTIME pull_nttime(void *base, uint16 offset) +{ + NTTIME ret; + ret.low = IVAL(base, offset); + ret.high = IVAL(base, offset+4); + return ret; } -- cgit From 0446e6addd5de78880f30df70424bc608ba062dd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Apr 2004 01:26:22 +0000 Subject: r157: cope with or without LDAP in ldb sample Makefile (This used to be commit 5004159bf93ccb62d056fa67c18f4a52cdbb2026) --- source4/lib/ldb/Makefile.ldb | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 2a41629852..f1b2c8ad21 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -1,16 +1,24 @@ -OPENLDAP=/home/tridge/samba/openldap/prefix -TDBDIR=../tdb -CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 +# ldap support is optional edit WITH_LDAP to suit +WITH_LDAP=0 + +ifeq ($(WITH_LDAP),1) +OPENLDAP_PREFIX=/home/tridge/samba/openldap/prefix +LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -lldap +LDAP_FLAGS=-DHAVE_LDAP=1 +LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o +endif + +TDBDIR=../tdb -LIB_FLAGS=-Llib -lldb -L$(OPENLDAP)/lib -lldap +CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o -LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o -- cgit From 27db4c6d18b31c2e70211efe3c26816cd5d38b24 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Apr 2004 01:26:53 +0000 Subject: r158: cope with or without LDAP in samba build of ldb (This used to be commit e776ce4f9e6fead235b3cec86d85eb95704f10ef) --- source4/lib/ldb/common/ldb.c | 4 ++-- source4/lib/ldb/config.m4 | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 146745043f..e84473efab 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -52,11 +52,11 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, return ltdb_connect(url, flags, options); } -#ifdef HAVE_LDAP +#if HAVE_LDAP if (strncmp(url, "ldap", 4) == 0) { return lldb_connect(url, flags, options); } -#endif /*HAVE_LDAP*/ +#endif errno = EINVAL; return NULL; diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 7c4749ab02..1541dd6736 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,3 +1,7 @@ +if test x"$HAVE_LDAP" = x"yes"; then +SMB_SUBSYSTEM(LIBLDB_LDAP,[lib/ldb/ldb_ldap/ldb_ldap.o]) +fi + SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], [lib/ldb/common/ldb_ldif.o \ lib/ldb/common/ldb_parse.o \ @@ -8,7 +12,7 @@ SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ lib/ldb/ldb_tdb/ldb_match.o \ - lib/ldb/ldb_ldap/ldb_ldap.o], + \$(LIBLDAP_LDAP_OBJS)], lib/ldb/include/ldb.h) SMB_SUBSYSTEM(LDBADD,[], -- cgit From a7efe6c1c322467b8468399bec7ee294aeaeada8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Apr 2004 01:27:33 +0000 Subject: r159: nicer usage messages when no URL is given (This used to be commit 8655f0b435e06af21d5d9fa210441fbf318673f0) --- source4/lib/ldb/tools/ldbadd.c | 4 ++-- source4/lib/ldb/tools/ldbdel.c | 4 ++-- source4/lib/ldb/tools/ldbedit.c | 6 +++--- source4/lib/ldb/tools/ldbmodify.c | 4 ++-- source4/lib/ldb/tools/ldbsearch.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 446c0d80f9..15febb76e7 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -101,8 +101,8 @@ static int process_file(struct ldb_context *ldb, FILE *f) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n"); - exit(1); + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); } argc -= optind; diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 0e50a68532..48ee07ad25 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -67,8 +67,8 @@ static void usage(void) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n"); - exit(1); + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); } argc -= optind; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index c5eb1349dd..13516e59cf 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -281,7 +281,7 @@ static void usage(void) editor = "vi"; } - while ((opt = getopt(argc, argv, "ab:e:H:s:")) != EOF) { + while ((opt = getopt(argc, argv, "hab:e:H:s:")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -317,8 +317,8 @@ static void usage(void) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n"); - exit(1); + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); } argc -= optind; diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index a93c710a7a..ac32f90c3b 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -103,8 +103,8 @@ static int process_file(struct ldb_context *ldb, FILE *f) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n"); - exit(1); + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); } argc -= optind; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 327feb28ef..45412f6104 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -86,8 +86,8 @@ static void usage(void) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n"); - exit(1); + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); } argc -= optind; -- cgit From 491ce98cc4b794f5c23eabc88004e9540c011fd5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 14:24:47 +0000 Subject: r162: Minor bugfixes: - Don't keep windows open after errors - Don't build ldb backend by default (This used to be commit 1bb64782c6585c02b8792d23b97d3da60aac844c) --- source4/lib/registry/config.m4 | 2 +- source4/lib/registry/tools/gregedit.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 90dc50728b..c00b7cc507 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -14,6 +14,6 @@ SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) -SMB_MODULE(reg_ldb, REG, STATIC, lib/registry/reg_backend_ldb/reg_backend_ldb.o) +SMB_MODULE(reg_ldb, REG, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o) SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[]) AC_CONFIG_FILES(lib/registry/winregistry.pc) diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index b62fd7ec04..2d145e699a 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -242,7 +242,6 @@ GtkWidget* create_rpcwin (void) return rpcwin; } - static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data) { gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); @@ -254,7 +253,7 @@ static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data) error = reg_open("nt4", filename, NULL, ®istry); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(error); - return; + break; } registry_load_root(); break; @@ -291,7 +290,7 @@ on_open_remote_activate (GtkMenuItem *menuitem, error = reg_open("rpc", location, credentials, ®istry); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(error); - return; + break; } free(location); free(credentials); registry_load_root(); -- cgit From 3185ace216586b6f1d676210630206bf00d5474e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Apr 2004 15:03:31 +0000 Subject: r163: - enable ldap in the sample makefile, and use /usr prefix - show number of adds/deletes/modifies after an edit - nicer error messages from ldbedit (This used to be commit 077951f6bcb1d0eba2de76d0df4c186b7fa19a14) --- source4/lib/ldb/Makefile.ldb | 4 ++-- source4/lib/ldb/tools/ldbedit.c | 36 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index f1b2c8ad21..6ff1bcf78e 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -1,9 +1,9 @@ # ldap support is optional edit WITH_LDAP to suit -WITH_LDAP=0 +WITH_LDAP=1 ifeq ($(WITH_LDAP),1) -OPENLDAP_PREFIX=/home/tridge/samba/openldap/prefix +OPENLDAP_PREFIX=/usr LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -lldap LDAP_FLAGS=-DHAVE_LDAP=1 LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 13516e59cf..5ae62d3ac1 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -27,7 +27,7 @@ * * Component: ldbedit * - * Description: utility for ldb editing + * Description: utility for ldb database editing * * Author: Andrew Tridgell */ @@ -36,6 +36,7 @@ /* modify a database record so msg1 becomes msg2 + returns the number of modified elements */ static int modify_record(struct ldb_context *ldb, struct ldb_message *msg1, @@ -44,6 +45,7 @@ static int modify_record(struct ldb_context *ldb, struct ldb_message mod; struct ldb_message_element *el; int i; + int count = 0; mod.dn = msg1->dn; mod.num_elements = 0; @@ -63,6 +65,7 @@ static int modify_record(struct ldb_context *ldb, el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { return -1; } + count++; } /* look in msg1 to find elements that need to be deleted */ @@ -74,6 +77,7 @@ static int modify_record(struct ldb_context *ldb, LDB_FLAG_MOD_DELETE) != 0) { return -1; } + count++; } } @@ -82,11 +86,12 @@ static int modify_record(struct ldb_context *ldb, } if (ldb_modify(ldb, &mod) != 0) { - fprintf(stderr, "failed to modify %s\n", msg1->dn); + fprintf(stderr, "failed to modify %s - %s\n", + msg1->dn, ldb_errstring(ldb)); return -1; } - return 0; + return count; } /* @@ -114,18 +119,22 @@ static int merge_edits(struct ldb_context *ldb, int i; struct ldb_message *msg; int ret = 0; + int adds=0, modifies=0, deletes=0; /* do the adds and modifies */ for (i=0;idn); if (!msg) { if (ldb_add(ldb, msgs2[i]) != 0) { - fprintf(stderr, "failed to add %s\n", - msgs2[i]->dn); + fprintf(stderr, "failed to add %s - %s\n", + msgs2[i]->dn, ldb_errstring(ldb)); return -1; } + adds++; } else { - modify_record(ldb, msg, msgs2[i]); + if (modify_record(ldb, msg, msgs2[i]) > 0) { + modifies++; + } } } @@ -134,13 +143,16 @@ static int merge_edits(struct ldb_context *ldb, msg = msg_find(msgs2, count2, msgs1[i]->dn); if (!msg) { if (ldb_delete(ldb, msgs1[i]->dn) != 0) { - fprintf(stderr, "failed to delete %s\n", - msgs1[i]->dn); + fprintf(stderr, "failed to delete %s - %s\n", + msgs1[i]->dn, ldb_errstring(ldb)); return -1; } + deletes++; } } + printf("# %d adds %d modifies %d deletes\n", adds, modifies, deletes); + return ret; } @@ -151,7 +163,7 @@ static int save_ldif(FILE *f, struct ldb_message **msgs, int count) { int i; - fprintf(f, "# returned %d records\n", count); + fprintf(f, "# editing %d records\n", count); for (i=0;i 0) { ret = ldb_search_free(ldb, msgs); if (ret == -1) { - fprintf(stderr, "search_free failed\n"); + fprintf(stderr, "search_free failed - %s\n", ldb_errstring(ldb)); exit(1); } } -- cgit From 6df152f96495e68426a52bf62be2c44900b7e8cf Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 15:34:18 +0000 Subject: r164: Viewing remote registries with gregedit works now (This used to be commit 697560a117ba19bb44539d6d63cc9143127e29d1) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 4 ++-- source4/lib/registry/tools/regtree.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index e61301d6f2..7c30302e84 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -47,7 +47,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) r.out.handle = hnd;\ \ if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\ - printf("Error executing open\n");\ + DEBUG(0,("Error executing open\n"));\ return NULL;\ }\ \ @@ -89,7 +89,7 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char user = talloc_strdup(h->mem_ctx, credentials); pass = strchr(user, '%'); *pass = '\0'; pass++; - + ZERO_STRUCTP(mydata); status = dcerpc_pipe_connect(&mydata->pipe, binding, diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 548a702d48..b8a5f50496 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -72,7 +72,7 @@ int main (int argc, char **argv) POPT_AUTOHELP {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, - {"credentials", 'c', POPT_ARG_NONE, &credentials, 0, "credentials (user%password)", NULL}, + {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%password)", NULL}, {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, POPT_TABLEEND }; @@ -86,7 +86,7 @@ int main (int argc, char **argv) error = reg_open(backend, poptPeekArg(pc), credentials, &h); if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error)); return 1; } poptFreeContext(pc); -- cgit From 07afafd45df34c4617c9e3e31bcd3130a9e255e3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 16:04:06 +0000 Subject: r165: Add support for viewing registry values in gregedit (This used to be commit 1d8a6d762aa4dab54bb58959cb1e7957a76e5b6e) --- source4/lib/registry/TODO | 3 ++ source4/lib/registry/tools/gregedit.c | 63 ++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index fc741cea40..f84b1c5339 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -19,6 +19,9 @@ reg_backend_ldb: reg_backend_wine.c: - finish +regshell: + - support for security descriptors + gregedit.c: - support for editing values / adding values / deleting values - support for adding/deleting keys diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 2d145e699a..51fad4287d 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -63,23 +63,6 @@ static void gtk_show_werror(WERROR err) gtk_widget_destroy (dialog); } -static void treeview_add_val(REG_VAL *val) -{ - GtkTreeIter iter; - gtk_list_store_append(store_vals, &iter); - gtk_list_store_set (store_vals, - &iter, - 0, - reg_val_name(val), - 1, - str_regtype(reg_val_type(val)), - 2, - reg_val_data_string(val), - 3, - val, - -1); -} - static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2) { GtkTreeIter iter, tmpiter; @@ -394,18 +377,32 @@ void on_key_activate (GtkTreeView *treeview, REG_KEY *k; REG_VAL *val; WERROR error; + GtkTreeIter parent; -//FIXME gtk_tree_model_get(GTK_TREE_MODEL(store_keys), iter, 1, &k, -1); + gtk_tree_model_get_iter(GTK_TREE_MODEL(store_keys), &parent, path); + gtk_tree_model_get(GTK_TREE_MODEL(store_keys), &parent, 1, &k, -1); + + g_assert(k); gtk_list_store_clear(store_vals); for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(k, i, &val)); i++) { - treeview_add_val(val); + GtkTreeIter iter; + gtk_list_store_append(store_vals, &iter); + gtk_list_store_set (store_vals, + &iter, + 0, + reg_val_name(val), + 1, + str_regtype(reg_val_type(val)), + 2, + reg_val_data_string(val), + 3, + val, + -1); } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); - - return; } GtkWidget* create_mainwin (void) @@ -567,15 +564,29 @@ GtkWidget* create_mainwin (void) tree_vals = gtk_tree_view_new (); /* Column names */ - curcol = gtk_tree_view_column_new_with_attributes ("Name", gtk_cell_renderer_text_new(), NULL); + + curcol = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title(curcol, "Name"); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(curcol, renderer, True); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); + gtk_tree_view_column_add_attribute(curcol, renderer, "text", 0); - - curcol = gtk_tree_view_column_new_with_attributes ("Type", gtk_cell_renderer_text_new(), NULL); + curcol = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title(curcol, "Type"); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(curcol, renderer, True); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); - - curcol = gtk_tree_view_column_new_with_attributes ("Value", gtk_cell_renderer_text_new(), NULL); + gtk_tree_view_column_add_attribute(curcol, renderer, "text", 1); + + curcol = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title(curcol, "Value"); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(curcol, renderer, True); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); + gtk_tree_view_column_add_attribute(curcol, renderer, "text", 2); + + gtk_widget_show (tree_vals); gtk_container_add (GTK_CONTAINER (scrolledwindow2), tree_vals); -- cgit From c60c5ebb910a77f6f3f345093794637714eb66e2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 16:37:06 +0000 Subject: r166: Fix enumerating values in nt4 backend (This used to be commit 1a7de762c60177b6e250f81cdeb3466fce148bff) --- source4/lib/registry/common/reg_interface.c | 1 + source4/lib/registry/common/registry.h | 1 + source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 4 ++++ 3 files changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 9c78ae55fb..5e6b4fbac8 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -98,6 +98,7 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia ret = talloc(mem_ctx, sizeof(REG_HANDLE)); ZERO_STRUCTP(ret); ret->location = location?talloc_strdup(mem_ctx, location):NULL; + ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; ret->functions = entry->functions; ret->backend_data = NULL; ret->mem_ctx = mem_ctx; diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 6e12de258d..9d7e17cf56 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -121,6 +121,7 @@ struct reg_handle_s { struct registry_ops *functions; REG_SUBTREE *subtrees; char *location; + char *credentials; void *backend_data; TALLOC_CTX *mem_ctx; }; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 9d90523a75..a7e5051ce4 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1697,12 +1697,16 @@ static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) { VL_TYPE *vl; int val_off, vk_off; + int val_count; VK_HDR *vk_hdr; REGF *regf = k->handle->backend_data; NK_HDR *nk_hdr = k->backend_data; + val_count = IVAL(&nk_hdr->val_cnt,0); val_off = IVAL(&nk_hdr->val_off,0); vl = (VL_TYPE *)LOCN(regf->base, val_off); DEBUG(2, ("Val List Offset: %0X\n", val_off)); + if(n < 0) return WERR_INVALID_PARAM; + if(n >= val_count) return WERR_NO_MORE_ITEMS; vk_off = IVAL(&vl[n],0); vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); -- cgit From 639afabf404d469638bc521b8a7f37e541ccf834 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 23:16:47 +0000 Subject: r168: - Cleanups in rpc backend - Small fixess in nt4 and dir backends - Start on w95 file backend (This used to be commit aa739e8d3c7108f6f2089af2d8d522feacc7f698) --- source4/lib/registry/common/reg_interface.c | 49 ++++- source4/lib/registry/common/registry.h | 4 +- source4/lib/registry/config.m4 | 1 + .../lib/registry/reg_backend_dir/reg_backend_dir.c | 15 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 33 ++-- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 216 +++++++-------------- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 170 ++++++++++++++++ source4/lib/registry/tools/gregedit.c | 11 +- 8 files changed, 307 insertions(+), 192 deletions(-) create mode 100644 source4/lib/registry/reg_backend_w95/reg_backend_w95.c (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 5e6b4fbac8..917b03cf32 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -214,7 +214,11 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->num_subkeys) { + if(key->handle->functions->num_subkeys) { + return key->handle->functions->num_subkeys(key, count); + } + + if(key->handle->functions->fetch_subkeys) { if(!key->cache_subkeys) key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); @@ -222,7 +226,20 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) return WERR_OK; } - return key->handle->functions->num_subkeys(key, count); + if(key->handle->functions->get_subkey_by_index) { + int i; + WERROR error; + REG_KEY *dest; + for(i = 0; W_ERROR_IS_OK(error = key->handle->functions->get_subkey_by_index(key, i, &dest)); i++) { + reg_key_free(dest); + } + + *count = i; + if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK; + return error; + } + + return WERR_NOT_SUPPORTED; } WERROR reg_key_num_values(REG_KEY *key, int *count) @@ -306,8 +323,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) { - int i, max; - REG_VAL *ret = NULL; + int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; @@ -361,7 +377,6 @@ WERROR reg_sync(REG_KEY *h, const char *location) WERROR reg_key_del_recursive(REG_KEY *key) { - BOOL succeed = True; WERROR error = WERR_OK; int i; @@ -543,3 +558,27 @@ WERROR reg_save(REG_HANDLE *h, const char *location) /* FIXME */ return WERR_NOT_SUPPORTED; } + +WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) +{ + char *parent_name; + char *last; + REG_KEY *root; + WERROR error; + + error = reg_get_root(key->handle, &root); + if(!W_ERROR_IS_OK(error)) return error; + + parent_name = strdup(reg_key_get_path(key)); + last = strrchr(parent_name, '\\'); + + if(!last) { + SAFE_FREE(parent_name); + return WERR_FOOBAR; + } + *last = '\0'; + + error = reg_open_key(root, parent_name, parent); + SAFE_FREE(parent_name); + return error; +} diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 9d7e17cf56..208bcae1e1 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -58,8 +58,8 @@ struct reg_val_s { }; /* FIXME */ -typedef void (*key_notification_function) (); -typedef void (*value_notification_function) (); +typedef void (*key_notification_function) (void); +typedef void (*value_notification_function) (void); /* diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index c00b7cc507..d8acb26397 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -11,6 +11,7 @@ PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC) PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) +SMB_MODULE(reg_w95, REG, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 4daaf3d628..375daa319b 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/registry/common/registry.h" -static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc) +static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **result) { char *path; int ret; @@ -29,7 +29,7 @@ static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_m path = reg_path_win2unix(path); ret = mkdir(path, 0700); SAFE_FREE(path); - if(ret == 0)return WERR_OK; + if(ret == 0)return WERR_OK; /* FIXME */ return WERR_INVALID_PARAM; } @@ -83,7 +83,6 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) if(e->d_type == DT_DIR && strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { - char *newfullpath; ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); ar[(*count)]->backend_data = talloc_asprintf(ar[*count]->mem_ctx, "%s/%s", fullpath, e->d_name); if(ar[(*count)])(*count)++; @@ -106,16 +105,8 @@ static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentia return WERR_OK; } -static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len, REG_VAL **value) +static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) { - char *fullpath; - FILE *fd; - *value = reg_val_new(p, NULL); - (*value)->name = name?talloc_strdup((*value)->mem_ctx, name):NULL; - fullpath = reg_path_win2unix(strdup(reg_val_get_path(*value))); - - fd = fopen(fullpath, "w+"); - /* FIXME */ return WERR_NOT_SUPPORTED; } diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index a7e5051ce4..fd91b4fbe6 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -165,7 +165,7 @@ Offset Size Contents To determine the number of values, you have to look at the owner-nk-record! -Der vk-Record +The vk-Record ============= Offset Size Contents 0x0000 Word ID: ASCII-"vk" = 0x6B76 @@ -473,7 +473,7 @@ typedef struct regf_struct_s { int fd; struct stat sbuf; char *base; - int modified; + BOOL modified; NTTIME last_mod_time; NK_HDR *first_key; int sk_count, sk_map_size; @@ -485,7 +485,6 @@ typedef struct regf_struct_s { * keys when we are preparing to write them to a file */ HBIN_BLK *blk_head, *blk_tail, *free_space; - TALLOC_CTX *mem_ctx; } REGF; DWORD str_to_dword(const char *a) { @@ -886,7 +885,6 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val char val_name[1024]; REGF *regf = parent->handle->backend_data; int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - const char *val_type; REG_VAL *tmp = NULL; if (!vk_hdr) return WERR_INVALID_PARAM; @@ -1021,7 +1019,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent { REGF *regf = h->backend_data; REG_KEY *tmp = NULL, *own; - int name_len, clsname_len, sk_off, own_off; + int namlen, clsname_len, sk_off, own_off; unsigned int nk_id; SK_HDR *sk_hdr; int type; @@ -1037,32 +1035,32 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent SMB_REG_ASSERT(size < 0); - name_len = SVAL(&nk_hdr->nam_len,0); + namlen = SVAL(&nk_hdr->nam_len,0); clsname_len = SVAL(&nk_hdr->clsnam_len,0); /* * The value of -size should be ge - * (sizeof(NK_HDR) - 1 + name_len) + * (sizeof(NK_HDR) - 1 + namlen) * The -1 accounts for the fact that we included the first byte of * the name in the structure. clsname_len is the length of the thing * pointed to by clsnam_off */ - if (-size < (sizeof(NK_HDR) - 1 + name_len)) { + if (-size < (sizeof(NK_HDR) - 1 + namlen)) { DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", - sizeof(NK_HDR), name_len, clsname_len)); + sizeof(NK_HDR), namlen, clsname_len)); return WERR_GENERAL_FAILURE; } - DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", name_len, clsname_len)); + DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", namlen, clsname_len)); /* Fish out the key name and process the LF list */ - SMB_REG_ASSERT(name_len < sizeof(key_name)); + SMB_REG_ASSERT(namlen < sizeof(key_name)); - strncpy(key_name, nk_hdr->key_nam, name_len); - key_name[name_len] = '\0'; + strncpy(key_name, nk_hdr->key_nam, namlen); + key_name[namlen] = '\0'; type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); if(type == REG_ROOT_KEY && parent) { @@ -1088,7 +1086,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - tmp->class_name = talloc_strdup_w(regf->mem_ctx, clsnamep); + tmp->class_name = talloc_strdup_w(h->mem_ctx, clsnamep); DEBUGADD(2,(" Class Name: %s\n", cls_name)); @@ -1572,22 +1570,17 @@ static WERROR nt_close_registry (REG_HANDLE *h) regf->base = NULL; close(regf->fd); /* Ignore the error :-) */ - free(regf->sk_map); - regf->sk_count = regf->sk_map_size = 0; - - free(regf); return WERR_OK; } static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials) { - REGF *regf = (REGF *)malloc(sizeof(REGF)); + REGF *regf = (REGF *)talloc_p(h->mem_ctx, REGF); REGF_HDR *regf_hdr; unsigned int regf_id, hbin_id; HBIN_HDR *hbin_hdr; memset(regf, 0, sizeof(REGF)); - regf->mem_ctx = talloc_init("regf"); regf->owner_sid_str = credentials; h->backend_data = regf; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 7c30302e84..f17bdbb3f5 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -20,6 +20,13 @@ #include "includes.h" #include "lib/registry/common/registry.h" +/** + * This is the RPC backend for the registry library. + * + * This backend is a little special. The root key is 'virtual'. All + * of its subkeys are the hives available on the remote server. + */ + static void init_winreg_String(struct winreg_String *name, const char *s) { name->name = s; @@ -35,7 +42,6 @@ static void init_winreg_String(struct winreg_String *name, const char *s) #define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \ { \ - NTSTATUS status; \ struct winreg_Open ## u r; \ struct winreg_OpenUnknown unknown; \ struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \ @@ -66,7 +72,7 @@ struct rpc_data { }; struct { - char *name; + const char *name; struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h); } known_hives[] = { { "HKEY_LOCAL_MACHINE", open_HKLM }, @@ -98,7 +104,6 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char lp_workgroup(), user, pass); - h->backend_data = mydata; return ntstatus_to_werror(status); @@ -118,64 +123,66 @@ static WERROR rpc_close_registry(REG_HANDLE *h) return WERR_OK; } -static struct policy_handle *rpc_get_key_handle(REG_HANDLE *h, const char *path) +static WERROR rpc_key_put_policy_handle(REG_KEY *k) { - char *hivename; - int i = 0; - struct rpc_data *mydata = h->backend_data; - struct policy_handle *hive = NULL; - char *end = strchr(path+1, '\\'); - NTSTATUS status; + struct policy_handle *key_handle, *hive = NULL; struct winreg_OpenKey r; - struct policy_handle *key_handle = talloc(h->mem_ctx, sizeof(struct policy_handle)); - TALLOC_CTX *mem_ctx; - - if(end) hivename = strndup(path+1, end-path-1); - else hivename = strdup(path+1); + int i; + struct rpc_data *mydata = k->handle->backend_data; + char *realkeyname, *hivename; + if(k->backend_data) return WERR_OK; + + /* First, ensure the handle to the hive is opened */ + realkeyname = strchr(k->path, '\\'); + if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1); + else hivename = strdup(k->path+1); for(i = 0; known_hives[i].name; i++) { if(!strcmp(hivename, known_hives[i].name)) { - if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, h); + if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, k->handle); hive = mydata->hives[i]; + break; } } if(!hive) { DEBUG(0, ("No such hive: %s\n", hivename)); - return NULL; + return WERR_FOOBAR; } - DEBUG(2, ("Opening %s, hive: %s\n", path, hivename)); + if(realkeyname[0] == '\\')realkeyname++; - if(!end || !(*end) || !(*(end+1))) return hive; + if(!realkeyname || !(*realkeyname)) { + k->backend_data = hive; + return WERR_OK; + } + + key_handle = talloc(k->mem_ctx, sizeof(struct policy_handle)); + + /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); r.in.handle = hive; - init_winreg_String(&r.in.keyname, end+1); + init_winreg_String(&r.in.keyname, realkeyname); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = key_handle; - - mem_ctx = talloc_init("openkey"); - status = dcerpc_winreg_OpenKey(mydata->pipe, mem_ctx, &r); - talloc_destroy(mem_ctx); - - if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) { - return NULL; - } - return key_handle; + dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r); + + if(W_ERROR_IS_OK(r.out.result)) k->backend_data = key_handle; + + return r.out.result; } static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) { - struct policy_handle *pol = rpc_get_key_handle(h, name); - if(!pol) return WERR_DEST_NOT_FOUND; - *key = reg_key_new_abs(name, h, pol); - return WERR_OK; + WERROR error; + *key = reg_key_new_abs(name, h, NULL); + return rpc_key_put_policy_handle(*key); } -static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) +static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) { struct winreg_EnumKey r; struct winreg_EnumKeyNameRequest keyname; @@ -183,28 +190,22 @@ static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) struct winreg_Time tm; struct rpc_data *mydata = parent->handle->backend_data; int i; - REG_KEY **ar = talloc(parent->mem_ctx, sizeof(REG_KEY *)); - NTSTATUS status = NT_STATUS_OK; + NTSTATUS status; TALLOC_CTX *mem_ctx; - /* List the hives */ - if(parent->backend_data == parent->handle->backend_data) { - for(i = 0; known_hives[i].name; i++) { - ar[i] = reg_key_new_rel(known_hives[i].name, parent, NULL); - (*count)++; - ar = talloc_realloc(parent->mem_ctx, ar, sizeof(REG_KEY *) * ((*count)+1)); - } + /* If parent is the root key, list the hives */ + if(parent->backend_data == mydata) { + if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; - *subkeys = ar; + *subkey = reg_key_new_rel(known_hives[n].name, parent, known_hives[n].open(mydata->pipe, parent->handle)); return WERR_OK; } - if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); - - if(!parent->backend_data) return WERR_GENERAL_FAILURE; + if(!parent->backend_data) { + rpc_key_put_policy_handle(parent); + } - (*count) = 0; r.in.handle = parent->backend_data; keyname.unknown = 0x0000020a; init_winreg_String(&keyname.key_name, NULL); @@ -215,134 +216,59 @@ static WERROR rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys) r.in.last_changed_time = &tm; r.out.result.v = 0; - for(i = 0; NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result); i++) { - r.in.enum_index = i; - r.in.unknown = r.out.unknown = 0x0414; - r.in.key_name_len = r.out.key_name_len = 0; - status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r); - if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - ar[(*count)] = reg_key_new_rel(r.out.out_name->name, parent, NULL); - (*count)++; - ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_KEY *)); - } - } - - *subkeys = ar; - return r.out.result; -} - -static WERROR rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values) -{ - struct winreg_EnumValue r; - struct winreg_Uint8buf value; - struct winreg_String valuename; - struct rpc_data *mydata = parent->handle->backend_data; - TALLOC_CTX *mem_ctx; - uint32 type, requested_len, returned_len; - NTSTATUS status = NT_STATUS_OK; - REG_VAL **ar = malloc(sizeof(REG_VAL *)); - - (*count) = 0; - - /* Root */ - if(parent->backend_data == parent->handle->backend_data) { - *values = ar; - return WERR_OK; + r.in.enum_index = n; + r.in.unknown = r.out.unknown = 0x0414; + r.in.key_name_len = r.out.key_name_len = 0; + status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r); + if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL); } - - if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent)); - - if(!parent->backend_data) return WERR_GENERAL_FAILURE; - - r.in.handle = parent->backend_data; - r.in.enum_index = 0; - - init_winreg_String(&valuename, NULL); - r.in.name = r.out.name = &valuename; - - type = 0; - r.in.type = r.out.type = &type; - value.max_len = 0x7fff; - value.offset = 0; - value.len = 0; - value.buffer = NULL; - - r.in.value = r.out.value = &value; - - requested_len = value.max_len; - r.in.requested_len = &requested_len; - returned_len = 0; - r.in.returned_len = &returned_len; - r.out.result.v = 0; - - while(1) { - status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r); - if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - r.in.enum_index++; - ar[(*count)] = reg_val_new(parent, NULL); - ar[(*count)]->name = talloc_strdup(ar[*count]->mem_ctx, r.out.name->name); - ar[(*count)]->data_type = *r.out.type; - ar[(*count)]->data_len = value.len; - ar[(*count)]->data_blk = talloc(ar[*count]->mem_ctx, value.len); - memcpy(ar[(*count)]->data_blk, value.buffer, value.len); - (*count)++; - ar = talloc_realloc(parent->mem_ctx, ar, ((*count)+1) * sizeof(REG_VAL *)); - } else break; - } - - *values = ar; return r.out.result; } -static WERROR rpc_add_key(REG_KEY *parent, const char *name) +static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key) { + rpc_key_put_policy_handle(parent); /* FIXME */ return WERR_NOT_SUPPORTED; } -static struct policy_handle*get_hive(REG_KEY *k) -{ - int i; - struct rpc_data *mydata = k->handle->backend_data; - for(i = 0; known_hives[i].name; i++) { - if(!strncmp(known_hives[i].name, reg_key_get_path(k)+1, strlen(known_hives[i].name))) - return mydata->hives[i]; - } - return NULL; -} + static WERROR rpc_del_key(REG_KEY *k) { NTSTATUS status; struct rpc_data *mydata = k->handle->backend_data; struct winreg_DeleteKey r; - char *hivepath; - struct policy_handle *hive = get_hive(k); + REG_KEY *parent; + WERROR error = reg_key_get_parent(k, &parent); + if(!W_ERROR_IS_OK(error)) return error; + rpc_key_put_policy_handle(parent); - printf("first: %s\n", reg_key_get_path(k)); - hivepath = strchr(reg_key_get_path(k), '\\'); - hivepath = strchr(hivepath+1, '\\'); - printf("asfter: %s\n", hivepath+1); - - r.in.handle = hive; - init_winreg_String(&r.in.key, hivepath+1); + r.in.handle = parent->backend_data; + init_winreg_String(&r.in.key, k->name); status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r); return r.out.result; } +static void rpc_close_key(REG_KEY *k) +{ + reg_key_free(k); +} + static struct registry_ops reg_backend_rpc = { .name = "rpc", .open_registry = rpc_open_registry, .close_registry = rpc_close_registry, .open_root_key = rpc_open_root, .open_key = rpc_open_key, - .fetch_subkeys = rpc_fetch_subkeys, - .fetch_values = rpc_fetch_values, + .get_subkey_by_index = rpc_get_subkey_by_index, .add_key = rpc_add_key, .del_key = rpc_del_key, + .free_key_backend_data = rpc_close_key, }; NTSTATUS reg_rpc_init(void) diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c new file mode 100644 index 0000000000..79ebd54510 --- /dev/null +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -0,0 +1,170 @@ +/* + Samba Unix/Linux SMB client utility libeditreg.c + Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org + + Backend for Windows '95 registry files. Explanation of file format + comes from http://www.cs.mun.ca/~michael/regutils/. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "lib/registry/common/registry.h" + +/** + * The registry starts with a header that contains pointers to + * the rgdb. + * + * After the main header follows the RGKN header (key index table) */ + +typedef unsigned int DWORD; +typedef unsigned short WORD; + +typedef struct regc_block { + DWORD REGC_ID; /* REGC */ + DWORD uk1; + DWORD rgdb_offset; + DWORD chksum; + WORD num_rgdb; + WORD flags; + DWORD uk2; + DWORD uk3; + DWORD uk4; + DWORD uk5; +} REGC_HDR; + +typedef struct rgkn_block { + DWORD RGKN_ID; /* RGKN */ + DWORD size; + DWORD root_offset; + DWORD free_offset; + DWORD flags; + DWORD chksum; + DWORD uk1; + DWORD uk2; +} RGKN_HDR; + +typedef struct rgkn_key { + DWORD inuse; + DWORD hash; + DWORD next_free; + DWORD parent; + DWORD child; + DWORD next; + WORD id; + WORD rgdb; +} RGKN_KEY; + +typedef struct rgdb_block { + DWORD RGDB_ID; /* RGDB */ + DWORD size; + DWORD unused_size; + WORD flags; + WORD section; + DWORD free_offset; /* -1 if there is no free space */ + WORD max_id; + WORD first_free_id; + DWORD uk1; + DWORD chksum; +} RGDB_HDR; + +typedef struct rgdb_key { + DWORD inuse; + DWORD hash; + DWORD next_free; + DWORD parent; + DWORD child; + DWORD next; + WORD id; + WORD rgdb; +} RGDB_KEY; + +typedef struct rgdb_value { + DWORD type; + DWORD uk1; + DWORD name_len; + DWORD data_len; +} RGDB_VALUE; + +typedef struct regc_struct_s { + int fd; + struct stat sbuf; + BOOL modified; + char *base; +} REGC; + +static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) +{ + REGC *regc = talloc_p(h->mem_ctx, REGC); + REGC_HDR *regc_hdr; + RGKN_HDR *rgkn_hdr; + DWORD regc_id, rgkn_id; + memset(regc, 0, sizeof(REGC)); + h->backend_data = regc; + + if((regc->fd = open(location, O_RDONLY, 0000)) < 0) { + return WERR_FOOBAR; + } + + if(fstat(regc->fd, ®c->sbuf) < 0) { + return WERR_FOOBAR; + } + + regc->base = mmap(0, regc->sbuf.st_size, PROT_READ, MAP_SHARED, regc->fd, 0); + regc_hdr = (REGC_HDR *)regc->base; + + if ((int)regc->base == 1) { + return WERR_FOOBAR; + } + + if ((regc_id = IVAL(®c_hdr->REGC_ID,0)) != str_to_dword("REGC")) { + DEBUG(0, ("Unrecognized Windows 95 registry header id: %0X, %s\n", + regc_id, location)); + return WERR_FOOBAR; + } + + rgkn_hdr = (RGKN_HDR *)regc->base + sizeof(REGC_HDR); + + if ((rgkn_id = IVAL(&rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { + DEBUG(0, ("Unrecognized Windows 95 registry key index id: %0X, %s\n", + rgkn_id, location)); + return WERR_FOOBAR; + } + + //rgkn = (RGKN_KEY *)regc->base + sizeof(REGC_HDR) + sizeof(RGKN_HDR); + + /* FIXME */ + + return WERR_OK; +} + +static WERROR w95_close_reg(REG_HANDLE *h) +{ + REGC *regc = h->backend_data; + if (regc->base) munmap(regc->base, regc->sbuf.st_size); + regc->base = NULL; + close(regc->fd); + return WERR_OK; +} + +static struct registry_ops reg_backend_w95 = { + .name = "w95", + .open_registry = w95_open_reg, + .close_registry = w95_close_reg, +}; + +NTSTATUS reg_w95_init(void) +{ + return register_backend("registry", ®_backend_w95); +} diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 51fad4287d..4fbb1b2705 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -84,6 +84,7 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * g_assert(k); for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(k, i, &sub)); i++) { + int count; /* Replace the blank child with the first directory entry You may be tempted to remove the blank child node and then append a new one. Don't. If you remove the blank child @@ -103,14 +104,8 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * sub, -1); - gtk_tree_store_append(store_keys, &tmpiter, &iter); - } - - /* Remove placeholder child */ - if(i == 0) { - gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), - &iter, parent); - gtk_tree_store_remove(store_keys, &iter); + if(W_ERROR_IS_OK(reg_key_num_subkeys(sub, &count)) && count > 0) + gtk_tree_store_append(store_keys, &tmpiter, &iter); } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); -- cgit From 9d6a284567b832eee6fd47ac48c3471e69c0cc17 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Apr 2004 23:34:23 +0000 Subject: r169: Fix gregedit (This used to be commit 32036375de58327a673a5a85cedb01e8ddfa503a) --- source4/lib/registry/common/reg_objects.c | 27 ++------------------------- source4/lib/registry/tools/gregedit.c | 12 ++++++------ 2 files changed, 8 insertions(+), 31 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 809829b3e8..78260e198f 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -34,31 +34,8 @@ REG_VAL* reg_val_dup( REG_VAL *val ) { - REG_VAL *copy = NULL; - TALLOC_CTX *new_mem_ctx = talloc_init(val->name); - - if ( !val ) - return NULL; - - if ( !(copy = talloc( new_mem_ctx, sizeof(REG_VAL) )) ) { - DEBUG(0,("dup_registry_value: malloc() failed!\n")); - return NULL; - } - - /* copy all the non-pointer initial data */ - - memcpy( copy, val, sizeof(REG_VAL) ); - if ( val->data_blk ) - { - if ( !(copy->data_blk = talloc_memdup( new_mem_ctx, val->data_blk, val->data_len )) ) { - DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n", - val->data_len)); - SAFE_FREE( copy ); - } - } - copy->mem_ctx = new_mem_ctx; - - return copy; + val->ref++; + return val; } /********************************************************************** diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 4fbb1b2705..0c9084ad3e 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -65,19 +65,20 @@ static void gtk_show_werror(WERROR err) static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2) { - GtkTreeIter iter, tmpiter; + GtkTreeIter firstiter, iter, tmpiter; REG_KEY *k, *sub; char *name; GValue value; WERROR error; int i; + gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), &firstiter, parent); + /* See if this row has ever had a name gtk_tree_store_set()'ed to it. If not, read the directory contents */ - gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, - 0, &name, -1); + gtk_tree_model_get(GTK_TREE_MODEL(store_keys), &firstiter, 0, &name, -1); - if(!name) return; + if(name) return; gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, 1, &k, -1); @@ -91,8 +92,7 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * node GTK gets confused and won't expand the parent row. */ if(i == 0) { - gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), - &iter, parent); + iter = firstiter; } else { gtk_tree_store_append(store_keys, &iter, parent); } -- cgit From 24cd656ab0cd6501e321661883ae564c8d548298 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 11:02:38 +0000 Subject: r174: Win95 registry files (like USER.DAT) can now be partially parsed (This used to be commit dd31d3bcbfbb0ef7a96a1b86c1b4c54b650e9fd5) --- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 2 +- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 127 ++++++++++++++------- source4/lib/registry/tools/gregedit.c | 16 ++- 3 files changed, 100 insertions(+), 45 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index fd91b4fbe6..74d7bbd3b1 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -487,7 +487,7 @@ typedef struct regf_struct_s { HBIN_BLK *blk_head, *blk_tail, *free_space; } REGF; -DWORD str_to_dword(const char *a) { +static DWORD str_to_dword(const char *a) { int i; unsigned long ret = 0; for(i = strlen(a)-1; i >= 0; i--) { diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 79ebd54510..8b20b830e1 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -31,18 +31,17 @@ typedef unsigned int DWORD; typedef unsigned short WORD; -typedef struct regc_block { - DWORD REGC_ID; /* REGC */ +typedef struct creg_block { + DWORD CREG_ID; /* CREG */ DWORD uk1; DWORD rgdb_offset; DWORD chksum; WORD num_rgdb; WORD flags; - DWORD uk2; - DWORD uk3; - DWORD uk4; - DWORD uk5; -} REGC_HDR; + DWORD uk2; + DWORD uk3; + DWORD uk4; +} CREG_HDR; typedef struct rgkn_block { DWORD RGKN_ID; /* RGKN */ @@ -56,7 +55,7 @@ typedef struct rgkn_block { } RGKN_HDR; typedef struct rgkn_key { - DWORD inuse; + DWORD type; DWORD hash; DWORD next_free; DWORD parent; @@ -80,7 +79,7 @@ typedef struct rgdb_block { } RGDB_HDR; typedef struct rgdb_key { - DWORD inuse; + DWORD type; DWORD hash; DWORD next_free; DWORD parent; @@ -97,64 +96,112 @@ typedef struct rgdb_value { DWORD data_len; } RGDB_VALUE; -typedef struct regc_struct_s { +typedef struct creg_struct_s { int fd; - struct stat sbuf; BOOL modified; char *base; -} REGC; + struct stat sbuf; + CREG_HDR *creg_hdr; + RGKN_HDR *rgkn_hdr; + char *rgkn; +} CREG; + +static DWORD str_to_dword(const char *a) { + int i; + unsigned long ret = 0; + for(i = strlen(a)-1; i >= 0; i--) { + ret = ret * 0x100 + a[i]; + } + return ret; +} + +#define LOCN(creg, o) (((creg)->base + sizeof(CREG_HDR) + o)) static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) { - REGC *regc = talloc_p(h->mem_ctx, REGC); - REGC_HDR *regc_hdr; - RGKN_HDR *rgkn_hdr; - DWORD regc_id, rgkn_id; - memset(regc, 0, sizeof(REGC)); - h->backend_data = regc; - - if((regc->fd = open(location, O_RDONLY, 0000)) < 0) { + CREG *creg = talloc_p(h->mem_ctx, CREG); + DWORD creg_id, rgkn_id; + memset(creg, 0, sizeof(CREG)); + h->backend_data = creg; + DWORD i, nfree = 0; + DWORD offset; + + if((creg->fd = open(location, O_RDONLY, 0000)) < 0) { return WERR_FOOBAR; } - if(fstat(regc->fd, ®c->sbuf) < 0) { + if (fstat(creg->fd, &creg->sbuf) < 0) { return WERR_FOOBAR; - } + } - regc->base = mmap(0, regc->sbuf.st_size, PROT_READ, MAP_SHARED, regc->fd, 0); - regc_hdr = (REGC_HDR *)regc->base; + creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0); + + if ((int)creg->base == 1) { + DEBUG(0,("Could not mmap file: %s, %s\n", location, strerror(errno))); + return WERR_FOOBAR; + } - if ((int)regc->base == 1) { - return WERR_FOOBAR; - } - - if ((regc_id = IVAL(®c_hdr->REGC_ID,0)) != str_to_dword("REGC")) { - DEBUG(0, ("Unrecognized Windows 95 registry header id: %0X, %s\n", - regc_id, location)); + creg->creg_hdr = (CREG_HDR *)creg->base; + + if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) { + DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n", + creg_id, location)); return WERR_FOOBAR; } - rgkn_hdr = (RGKN_HDR *)regc->base + sizeof(REGC_HDR); + creg->rgkn_hdr = (RGKN_HDR *)LOCN(creg, 0); - if ((rgkn_id = IVAL(&rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { - DEBUG(0, ("Unrecognized Windows 95 registry key index id: %0X, %s\n", + if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { + DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", rgkn_id, location)); return WERR_FOOBAR; } - //rgkn = (RGKN_KEY *)regc->base + sizeof(REGC_HDR) + sizeof(RGKN_HDR); +#if 0 + for(i = 0; i < creg->rgkn_hdr->size; i+=sizeof(RGKN_KEY)) { + RGKN_KEY *key = (RGKN_KEY *)LOCN(creg, sizeof(RGKN_HDR) + i); + if(nfree > 0) { + nfree--; + } else if(key->type == 0) { + DEBUG(0,("Not used\n")); + /* Not used */ + } else if(key->type == 0x80000000) { + DEBUG(0,("Regular key\n")); + /* Regular key */ + } else { + DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type)); + } + } - /* FIXME */ + curpos += creg->rgkn_hdr->size + sizeof(RGKN_HDR); +#endif + offset = creg->rgkn_hdr->size; + + DEBUG(0, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); + for(i = 0; i < creg->creg_hdr->num_rgdb; i++) { + RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN(creg, offset); + + if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { + DEBUG(0, ("unrecognized rgdb entry: %4s, %s\n", + &rgdb_hdr->RGDB_ID, location)); + return WERR_FOOBAR; + } else { + DEBUG(0, ("Valid rgdb entry\n")); + } + + offset+=rgdb_hdr->size; + } + return WERR_OK; } static WERROR w95_close_reg(REG_HANDLE *h) { - REGC *regc = h->backend_data; - if (regc->base) munmap(regc->base, regc->sbuf.st_size); - regc->base = NULL; - close(regc->fd); + CREG *creg = h->backend_data; + if (creg->base) munmap(creg->base, creg->sbuf.st_size); + creg->base = NULL; + close(creg->fd); return WERR_OK; } diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 0c9084ad3e..10e5f45468 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -220,7 +220,7 @@ GtkWidget* create_rpcwin (void) return rpcwin; } -static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data) +static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) { gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); char *filename; @@ -228,7 +228,7 @@ static void on_open_nt4_activate (GtkMenuItem *menuitem, gpointer user_data) switch(result) { case GTK_RESPONSE_OK: filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin))); - error = reg_open("nt4", filename, NULL, ®istry); + error = reg_open(user_data, filename, NULL, ®istry); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(error); break; @@ -407,6 +407,7 @@ GtkWidget* create_mainwin (void) GtkWidget *menu_file; GtkWidget *menu_file_menu; GtkWidget *open_nt4; + GtkWidget *open_w95; GtkWidget *open_gconf; GtkWidget *open_remote; GtkWidget *separatormenuitem1; @@ -455,6 +456,10 @@ GtkWidget* create_mainwin (void) gtk_widget_show (open_nt4); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); + open_w95 = gtk_image_menu_item_new_with_mnemonic("_Open Win9x file"); + gtk_widget_show (open_w95); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); + open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); gtk_widget_show (open_gconf); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); @@ -595,8 +600,11 @@ GtkWidget* create_mainwin (void) gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE); g_signal_connect ((gpointer) open_nt4, "activate", - G_CALLBACK (on_open_nt4_activate), - NULL); + G_CALLBACK (on_open_file_activate), + "nt4"); + g_signal_connect ((gpointer) open_w95, "activate", + G_CALLBACK (on_open_file_activate), + "w95"); g_signal_connect ((gpointer) open_gconf, "activate", G_CALLBACK (on_open_gconf_activate), NULL); -- cgit From 49d54f0298de9dcee8d0fcb7e193429b80a8c8b1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 17:43:22 +0000 Subject: r181: Parsing windows '95 registry files now works (including values) (This used to be commit 4d6ce648567060b9922343971d7aafd545341439) --- source4/lib/registry/common/reg_interface.c | 8 +- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 225 +++++++++++++++++---- 2 files changed, 188 insertions(+), 45 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 917b03cf32..696a504d87 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -268,7 +268,10 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->get_subkey_by_index) { + if(key->handle->functions->get_subkey_by_index) { + WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); + if(!NT_STATUS_IS_OK(status)) return status; + } else if(key->handle->functions->fetch_subkeys) { if(!key->cache_subkeys) key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); @@ -278,8 +281,7 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) return WERR_NO_MORE_ITEMS; } } else { - WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); - if(!NT_STATUS_IS_OK(status)) return status; + return WERR_NOT_SUPPORTED; } (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 8b20b830e1..0b6b6db358 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -26,7 +26,19 @@ * The registry starts with a header that contains pointers to * the rgdb. * - * After the main header follows the RGKN header (key index table) */ + * After the main header follows the RGKN header (key index table). + * The RGKN keys are listed after each other. They are put into + * blocks, the first having a length of 0x2000 bytes, the others + * being 0x1000 bytes long. + * + * After the RGKN header follow one or more RGDB blocks. These blocks + * contain keys. A key is followed by its name and its values. + * + * Values are followed by their name and then their data. + * + * Basically the idea is that the RGKN contains the associations between + * the keys and the RGDB contains the actual data. + */ typedef unsigned int DWORD; typedef unsigned short WORD; @@ -54,17 +66,22 @@ typedef struct rgkn_block { DWORD uk2; } RGKN_HDR; -typedef struct rgkn_key { - DWORD type; - DWORD hash; - DWORD next_free; - DWORD parent; - DWORD child; - DWORD next; +typedef struct reg_id { WORD id; WORD rgdb; +} REG_ID; + +typedef struct rgkn_key { + DWORD type; /* 0x00000000 = normal key, 0x80000000 = free block */ + DWORD hash; /* Contains either hash or size of free blocks that follows */ + DWORD next_free; + DWORD parent_offset; + DWORD first_child_offset; + DWORD next_offset; + REG_ID id; } RGKN_KEY; + typedef struct rgdb_block { DWORD RGDB_ID; /* RGDB */ DWORD size; @@ -79,21 +96,19 @@ typedef struct rgdb_block { } RGDB_HDR; typedef struct rgdb_key { - DWORD type; - DWORD hash; - DWORD next_free; - DWORD parent; - DWORD child; - DWORD next; - WORD id; - WORD rgdb; + DWORD size; + REG_ID id; + DWORD used_size; + WORD name_len; + WORD num_values; + DWORD uk1; } RGDB_KEY; typedef struct rgdb_value { DWORD type; DWORD uk1; - DWORD name_len; - DWORD data_len; + WORD name_len; + WORD data_len; } RGDB_VALUE; typedef struct creg_struct_s { @@ -103,9 +118,16 @@ typedef struct creg_struct_s { struct stat sbuf; CREG_HDR *creg_hdr; RGKN_HDR *rgkn_hdr; - char *rgkn; + RGDB_KEY ***rgdb_keys; } CREG; +#define RGKN_START_SIZE 0x2000 +#define RGKN_INC_SIZE 0x1000 + +#define LOCN_RGKN(creg, o) ((RGKN_KEY *)((creg)->base + sizeof(CREG_HDR) + o)) +#define LOCN_RGDB_BLOCK(creg, o) (((creg)->base + (creg)->creg_hdr->rgdb_offset + o)) +#define LOCN_RGDB_KEY(creg, rgdb, id) ((RGDB_KEY *)((creg)->rgdb_keys[(rgdb)][(id)])) + static DWORD str_to_dword(const char *a) { int i; unsigned long ret = 0; @@ -115,7 +137,86 @@ static DWORD str_to_dword(const char *a) { return ret; } -#define LOCN(creg, o) (((creg)->base + sizeof(CREG_HDR) + o)) +static DWORD calc_hash(const char *str) { + DWORD ret = 0; + int i; + for(i = 0; str[i] && str[i] != '\\'; i++) { + ret+=toupper(str[i]); + } + return ret; +} + +static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off) +{ + off_t i; + for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) { + RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i); + if(key->type == 0) { + DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, key->hash)); + } else if(key->type == 0x80000000) { + DEBUG(3,("free\n")); + i += key->hash; + } else { + DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type)); + } + } +} + +static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) +{ + DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size; + DWORD offset = 0; + + while(offset < used_size) { + RGDB_KEY *key = (RGDB_KEY *)(((char *)rgdb_hdr) + sizeof(RGDB_HDR) + offset); + + if(!(key->id.id == 0xFFFF && key->id.rgdb == 0xFFFF))creg->rgdb_keys[key->id.rgdb][key->id.id] = key; + offset += key->size; + } +} + +static WERROR w95_open_root (REG_HANDLE *h, REG_KEY **key) +{ + CREG *creg = h->backend_data; + + /* First element in rgkn should be root key */ + *key = reg_key_new_abs("\\", h, LOCN_RGKN(creg, sizeof(RGKN_HDR))); + + return WERR_OK; +} + +static WERROR w95_get_subkey_by_index (REG_KEY *parent, int n, REG_KEY **key) +{ + CREG *creg = parent->handle->backend_data; + RGKN_KEY *rgkn_key = parent->backend_data; + RGKN_KEY *child; + DWORD child_offset; + DWORD cur = 0; + + /* Get id of first child */ + child_offset = rgkn_key->first_child_offset; + + while(child_offset != 0xFFFFFFFF) { + child = LOCN_RGKN(creg, child_offset); + + /* n == cur ? return! */ + if(cur == n) { + RGDB_KEY *rgdb_key; + char *name; + rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); + name = strndup((char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); + *key = reg_key_new_rel(name, parent, child); + SAFE_FREE(name); + return WERR_OK; + } + + cur++; + + child_offset = child->next_offset; + } + + return WERR_NO_MORE_ITEMS; +} static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) { @@ -124,7 +225,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre memset(creg, 0, sizeof(CREG)); h->backend_data = creg; DWORD i, nfree = 0; - DWORD offset; + DWORD offset, end_offset; if((creg->fd = open(location, O_RDONLY, 0000)) < 0) { return WERR_FOOBAR; @@ -149,7 +250,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre return WERR_FOOBAR; } - creg->rgkn_hdr = (RGKN_HDR *)LOCN(creg, 0); + creg->rgkn_hdr = (RGKN_HDR *)LOCN_RGKN(creg, 0); if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", @@ -157,38 +258,39 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre return WERR_FOOBAR; } -#if 0 - for(i = 0; i < creg->rgkn_hdr->size; i+=sizeof(RGKN_KEY)) { - RGKN_KEY *key = (RGKN_KEY *)LOCN(creg, sizeof(RGKN_HDR) + i); - if(nfree > 0) { - nfree--; - } else if(key->type == 0) { - DEBUG(0,("Not used\n")); - /* Not used */ - } else if(key->type == 0x80000000) { - DEBUG(0,("Regular key\n")); - /* Regular key */ - } else { - DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type)); - } - } +#if 0 + /* If'ed out because we only need to parse this stuff when allocating new + * entries (which we don't do at the moment */ + /* First parse the 0x2000 long block */ + parse_rgkn_block(creg, sizeof(RGKN_HDR), 0x2000); - curpos += creg->rgkn_hdr->size + sizeof(RGKN_HDR); + /* Then parse the other 0x1000 length blocks */ + for(offset = 0x2000; offset < creg->rgkn_hdr->size; offset+=0x1000) { + parse_rgkn_block(creg, offset, offset+0x1000); + } #endif - offset = creg->rgkn_hdr->size; - DEBUG(0, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); + creg->rgdb_keys = talloc_array_p(h->mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); + + offset = 0; + DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); for(i = 0; i < creg->creg_hdr->num_rgdb; i++) { - RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN(creg, offset); + RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset); if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { DEBUG(0, ("unrecognized rgdb entry: %4s, %s\n", &rgdb_hdr->RGDB_ID, location)); return WERR_FOOBAR; } else { - DEBUG(0, ("Valid rgdb entry\n")); + DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); } + + creg->rgdb_keys[i] = talloc_array_p(h->mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); + memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); + + parse_rgdb_block(creg, rgdb_hdr); + offset+=rgdb_hdr->size; } @@ -205,10 +307,49 @@ static WERROR w95_close_reg(REG_HANDLE *h) return WERR_OK; } + +static WERROR w95_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +{ + RGKN_KEY *rgkn_key = k->backend_data; + RGDB_VALUE *val; + DWORD i; + DWORD offset = 0; + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->handle->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + + if(!rgdb_key) return WERR_FOOBAR; + + *count = rgdb_key->num_values; + + if((*count) == 0) return WERR_OK; + + (*values) = talloc_array_p(k->mem_ctx, REG_VAL *, (*count)+1); + for(i = 0; i < rgdb_key->num_values; i++) { + RGDB_VALUE *val = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); + (*values)[i] = reg_val_new(k, val); + + /* Name */ + (*values)[i]->name = talloc_strndup(k->mem_ctx, (char *)val+sizeof(RGDB_VALUE), val->name_len); + + /* Value */ + (*values)[i]->data_len = val->data_len; + (*values)[i]->data_blk = talloc_memdup((*values)[i]->mem_ctx, (char *)val+sizeof(RGDB_VALUE)+val->name_len, val->data_len); + + /* Type */ + (*values)[i]->data_type = val->type; + + offset+=sizeof(RGDB_VALUE) + val->name_len + val->data_len; + } + + return WERR_OK; +} + static struct registry_ops reg_backend_w95 = { .name = "w95", .open_registry = w95_open_reg, .close_registry = w95_close_reg, + .open_root_key = w95_open_root, + .fetch_values = w95_fetch_values, + .get_subkey_by_index = w95_get_subkey_by_index, }; NTSTATUS reg_w95_init(void) -- cgit From 4019324f7633c029c3cf461ed8d15433fc7609ea Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 18:02:54 +0000 Subject: r182: Fix a couple of segfaults (This used to be commit db5d7062e69b456a89b17525e5a0177f93c90c83) --- source4/lib/registry/TODO | 3 +++ source4/lib/registry/common/reg_objects.c | 3 +++ source4/lib/registry/common/reg_util.c | 4 ++-- source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index f84b1c5339..9b0dbe4c71 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -4,6 +4,9 @@ reg_backend_dir: - value support + +reg_backend_w95.c: + - write support reg_backend_nt4: - write support diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 78260e198f..3f721c107e 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -47,6 +47,9 @@ void reg_val_free( REG_VAL *val ) if ( !val ) return; + val->ref--; + if(val->ref) return; + if(val->handle->functions->free_val_backend_data) val->handle->functions->free_val_backend_data(val); diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 5ca104fc2e..82b8d06679 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -45,10 +45,10 @@ char *reg_val_data_string(REG_VAL *v) switch (reg_val_type(v)) { case REG_SZ: /* FIXME: Convert to ascii */ - return strdup(reg_val_data_blk(v)); + return strndup(reg_val_data_blk(v), reg_val_size(v)); case REG_EXPAND_SZ: - return strdup(reg_val_data_blk(v)); + return strndup(reg_val_data_blk(v), reg_val_size(v)); case REG_BINARY: ret = malloc(reg_val_size(v) * 3 + 2); diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 0b6b6db358..31abd69854 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -204,6 +204,10 @@ static WERROR w95_get_subkey_by_index (REG_KEY *parent, int n, REG_KEY **key) RGDB_KEY *rgdb_key; char *name; rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); + if(!rgdb_key) { + DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); + return WERR_FOOBAR; + } name = strndup((char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); *key = reg_key_new_rel(name, parent, child); SAFE_FREE(name); -- cgit From b4d6cbd380b09d0638102137b589555cb4e1c285 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 18:46:48 +0000 Subject: r183: More bugfixes (This used to be commit 88911bbcca574adbf6ea4f0759a68f2961b05d6b) --- source4/lib/registry/common/reg_interface.c | 40 ++++++++++++----------------- source4/lib/registry/tools/regshell.c | 9 +++---- 2 files changed, 21 insertions(+), 28 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 696a504d87..5753de1bca 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -124,8 +124,7 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) { char *fullname; - WERROR status; - REG_KEY *ret = NULL; + WERROR error; TALLOC_CTX *mem_ctx; if(!parent) { @@ -143,10 +142,10 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) while(curbegin && *curbegin) { if(curend)*curend = '\0'; - status = reg_key_get_subkey_by_name(curkey, curbegin, result); - if(!NT_STATUS_IS_OK(status)) { + error = reg_key_get_subkey_by_name(curkey, curbegin, result); + if(!W_ERROR_IS_OK(error)) { SAFE_FREE(orig); - return status; + return error; } if(!curend) break; curbegin = curend + 1; @@ -168,21 +167,19 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) return WERR_NOT_SUPPORTED; } - status = parent->handle->functions->open_key(parent->handle, fullname, result); + error = parent->handle->functions->open_key(parent->handle, fullname, result); - if(!NT_STATUS_IS_OK(status)) { + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); - return status; + return error; } - ret->handle = parent->handle; - ret->path = fullname; - talloc_steal(mem_ctx, ret->mem_ctx, fullname); + (*result)->handle = parent->handle; + (*result)->path = fullname; + talloc_steal(mem_ctx, (*result)->mem_ctx, fullname); talloc_destroy(mem_ctx); - *result = ret; - return WERR_OK; } @@ -294,32 +291,29 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey) { int i; - REG_KEY *ret = NULL; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; if(key->handle->functions->get_subkey_by_name) { error = key->handle->functions->get_subkey_by_name(key,name,subkey); - } else { + } else if(key->handle->functions->get_subkey_by_index || key->handle->functions->fetch_subkeys) { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(key, i, subkey); if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { - break; + return error; } reg_key_free(*subkey); } - + } else { + return WERR_NOT_SUPPORTED; } - if(!W_ERROR_IS_OK(error) && W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) - return error; + if(!W_ERROR_IS_OK(error)) return error; - ret->path = talloc_asprintf(ret->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", ret->name); - ret->handle = key->handle; + (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); + (*subkey)->handle = key->handle; - *subkey = ret; - return WERR_OK; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index d60ca1ff46..18399b5bda 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -39,18 +39,17 @@ static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) { - REG_KEY *new; + REG_KEY *new = NULL; WERROR error; if(argc < 2) { new = cur; } else { error = reg_open_key(cur, argv[1], &new); if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error opening specified key\n")); + DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error))); + return NULL; } - } - - if(!new) new = cur; + } printf("Current path is: %s\n", reg_key_get_path(new)); -- cgit From 198a92cb77ef2070957f18da0a8b6a48d01dbe9b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 20:07:50 +0000 Subject: r187: RPC registry backend fixes (This used to be commit f832d6776cb10f5c7d7ed83e6f66e4d28a461916) --- source4/lib/registry/common/reg_interface.c | 11 +- source4/lib/registry/common/reg_objects.c | 3 + .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 141 +++++++++++++++++---- source4/lib/registry/tools/regtree.c | 2 +- 4 files changed, 127 insertions(+), 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 5753de1bca..fdbb7345d2 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -187,7 +187,12 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->get_value_by_index) { + if(key->handle->functions->get_value_by_index) { + WERROR status = key->handle->functions->get_value_by_index(key, idx, val); + if(!W_ERROR_IS_OK(status)) + return status; + + } else if(key->handle->functions->fetch_values) { if(!key->cache_values) key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); @@ -197,9 +202,7 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) return WERR_NO_MORE_ITEMS; } } else { - WERROR status = key->handle->functions->get_value_by_index(key, idx, val); - if(!W_ERROR_IS_OK(status)) - return status; + return WERR_NOT_SUPPORTED; } (*val)->parent = key; diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 3f721c107e..787ec52127 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -163,11 +163,14 @@ REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) { REG_KEY *r; + const char *parent_path = k?reg_key_get_path(k):""; TALLOC_CTX *mem_ctx = talloc_init(name); r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = k->handle; r->name = talloc_strdup(mem_ctx, name); + + r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name); r->backend_data = data; r->mem_ctx = mem_ctx; r->ref = 1; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index f17bdbb3f5..f5a7127ed6 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -71,6 +71,12 @@ struct rpc_data { struct policy_handle *hives[10]; }; +struct rpc_key_data { + struct policy_handle pol; + int num_subkeys; + int num_values; +}; + struct { const char *name; struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h); @@ -119,21 +125,30 @@ static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k) static WERROR rpc_close_registry(REG_HANDLE *h) { dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe); - free(h->backend_data); return WERR_OK; } -static WERROR rpc_key_put_policy_handle(REG_KEY *k) +static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) { - struct policy_handle *key_handle, *hive = NULL; + struct policy_handle *hive = NULL; struct winreg_OpenKey r; int i; struct rpc_data *mydata = k->handle->backend_data; + struct rpc_key_data *mykeydata; char *realkeyname, *hivename; - if(k->backend_data) return WERR_OK; + + if(k->backend_data) { + *data = k->backend_data; + return WERR_OK; + } + + k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data); + *data = mykeydata; + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; /* First, ensure the handle to the hive is opened */ - realkeyname = strchr(k->path, '\\'); + realkeyname = strchr(k->path+1, '\\'); if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1); else hivename = strdup(k->path+1); @@ -150,15 +165,13 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k) return WERR_FOOBAR; } - if(realkeyname[0] == '\\')realkeyname++; + if(realkeyname && realkeyname[0] == '\\')realkeyname++; if(!realkeyname || !(*realkeyname)) { - k->backend_data = hive; + mykeydata->pol = *hive; return WERR_OK; } - key_handle = talloc(k->mem_ctx, sizeof(struct policy_handle)); - /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); @@ -166,20 +179,19 @@ static WERROR rpc_key_put_policy_handle(REG_KEY *k) init_winreg_String(&r.in.keyname, realkeyname); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; - r.out.handle = key_handle; + r.out.handle = &mykeydata->pol; dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r); - if(W_ERROR_IS_OK(r.out.result)) k->backend_data = key_handle; - return r.out.result; } static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) { WERROR error; + struct rpc_key_data *mykeydata; *key = reg_key_new_abs(name, h, NULL); - return rpc_key_put_policy_handle(*key); + return rpc_key_put_rpc_data(*key, &mykeydata); } static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) @@ -189,6 +201,8 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) struct winreg_String classname; struct winreg_Time tm; struct rpc_data *mydata = parent->handle->backend_data; + struct rpc_key_data *mykeydata = parent->backend_data; + WERROR error; int i; NTSTATUS status; TALLOC_CTX *mem_ctx; @@ -196,17 +210,14 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) /* If parent is the root key, list the hives */ if(parent->backend_data == mydata) { if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; - - *subkey = reg_key_new_rel(known_hives[n].name, parent, known_hives[n].open(mydata->pipe, parent->handle)); - - return WERR_OK; + *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL); + return rpc_key_put_rpc_data(*subkey, &mykeydata); } - if(!parent->backend_data) { - rpc_key_put_policy_handle(parent); - } + error = rpc_key_put_rpc_data(parent, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; - r.in.handle = parent->backend_data; + r.in.handle = &mykeydata->pol; keyname.unknown = 0x0000020a; init_winreg_String(&keyname.key_name, NULL); init_winreg_String(&classname, NULL); @@ -229,24 +240,56 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key) { - rpc_key_put_policy_handle(parent); + struct rpc_key_data *mykeydata; + WERROR error = rpc_key_put_rpc_data(parent, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; + /* FIXME */ return WERR_NOT_SUPPORTED; } +static WERROR rpc_query_key(REG_KEY *k) +{ + NTSTATUS status; + struct winreg_QueryInfoKey r; + struct rpc_data *mydata = k->handle->backend_data; + struct rpc_key_data *mykeydata; + WERROR error = rpc_key_put_rpc_data(k, &mykeydata); + + r.in.handle = &mykeydata->pol; + init_winreg_String(&r.in.class, NULL); + + status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r); + + if (!NT_STATUS_IS_OK(status)) { + printf("QueryInfoKey failed - %s\n", nt_errstr(status)); + return ntstatus_to_werror(status); + } + + if (W_ERROR_IS_OK(r.out.result)) { + mykeydata->num_subkeys = r.out.num_subkeys; + mykeydata->num_values = r.out.num_values; + } + return r.out.result; +} static WERROR rpc_del_key(REG_KEY *k) { NTSTATUS status; struct rpc_data *mydata = k->handle->backend_data; + struct rpc_key_data *mykeydata; struct winreg_DeleteKey r; REG_KEY *parent; - WERROR error = reg_key_get_parent(k, &parent); + WERROR error; + + error = reg_key_get_parent(k, &parent); + if(!W_ERROR_IS_OK(error)) return error; + + error = rpc_key_put_rpc_data(parent, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; - rpc_key_put_policy_handle(parent); - r.in.handle = parent->backend_data; + r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.key, k->name); status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r); @@ -259,6 +302,52 @@ static void rpc_close_key(REG_KEY *k) reg_key_free(k); } +static WERROR rpc_num_values(REG_KEY *key, int *count) { + struct rpc_key_data *mykeydata; + WERROR error; + + /* Root is a special case */ + if(key->backend_data == key->handle->backend_data) { + *count = 0; + return WERR_OK; + } + + error = rpc_key_put_rpc_data(key, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; + + if(mykeydata->num_values == -1) { + WERROR error = rpc_query_key(key); + if(!W_ERROR_IS_OK(error)) return error; + } + + *count = mykeydata->num_values; + return WERR_OK; +} + +static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { + struct rpc_key_data *mykeydata; + WERROR error; + + /* Root is a special case */ + if(key->backend_data == key->handle->backend_data) { + int i; + for(i = 0; known_hives[i].name; i++); + *count = i; + return WERR_OK; + } + + error = rpc_key_put_rpc_data(key, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; + + if(mykeydata->num_subkeys == -1) { + WERROR error = rpc_query_key(key); + if(!W_ERROR_IS_OK(error)) return error; + } + + *count = mykeydata->num_subkeys; + return WERR_OK; +} + static struct registry_ops reg_backend_rpc = { .name = "rpc", .open_registry = rpc_open_registry, @@ -269,6 +358,8 @@ static struct registry_ops reg_backend_rpc = { .add_key = rpc_add_key, .del_key = rpc_del_key, .free_key_backend_data = rpc_close_key, + .num_subkeys = rpc_num_subkeys, + .num_values = rpc_num_values, }; NTSTATUS reg_rpc_init(void) diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index b8a5f50496..eb32b1e55e 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -38,7 +38,7 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals) } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p))); + DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path(p), win_errstr(error))); } if(!novals) { -- cgit From 17ddb68b54c6c550bc4614d33f7da69fc5f75633 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 12 Apr 2004 21:59:41 +0000 Subject: r190: More RPC updates (This used to be commit 0a67057e9626c1539f964e978537e24544784263) --- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 53 ++++++++++++++++++++++ source4/lib/registry/tools/regtree.c | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index f5a7127ed6..472a851638 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -75,6 +75,8 @@ struct rpc_key_data { struct policy_handle pol; int num_subkeys; int num_values; + int max_valnamelen; + int max_valdatalen; }; struct { @@ -194,6 +196,54 @@ static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) return rpc_key_put_rpc_data(*key, &mykeydata); } +static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) +{ + struct winreg_EnumValue r; + struct winreg_Uint8buf vb; + struct winreg_Uint16buf bn; + struct rpc_data *mydata = parent->handle->backend_data; + struct winreg_EnumValueName vn; + NTSTATUS status; + struct rpc_key_data *mykeydata = parent->backend_data; + uint32 type = 0x0, requested_len = 0, returned_len = 0; + + /* FIXME */ + + r.in.handle = &mykeydata->pol; + r.in.enum_index = n; + r.in.type = r.out.type = &type; + r.in.requested_len = r.out.requested_len = &requested_len; + r.in.returned_len = r.out.returned_len = &returned_len; + bn.max_len = mykeydata->max_valnamelen*3; + bn.offset = 0; + bn.len = 0; + bn.buffer = NULL; + vn.max_len = mykeydata->max_valnamelen*3; + vn.buf = &bn; + r.in.name = r.out.name = &vn; + vb.max_len = mykeydata->max_valdatalen*3; + vb.offset = 0x0; + vb.len = 0x0; + vb.buffer = NULL; + r.in.value = r.out.value = &vb; + + status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); + } + + if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + *value = reg_val_new(parent, NULL); + (*value)->name = (char *)r.out.name->buf->buffer; + (*value)->data_type = type; + (*value)->data_len = r.out.value->len; + (*value)->data_blk = r.out.value->buffer; + return WERR_OK; + } + + return r.out.result; +} + static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) { struct winreg_EnumKey r; @@ -269,6 +319,8 @@ static WERROR rpc_query_key(REG_KEY *k) if (W_ERROR_IS_OK(r.out.result)) { mykeydata->num_subkeys = r.out.num_subkeys; mykeydata->num_values = r.out.num_values; + mykeydata->max_valnamelen = r.out.max_valnamelen; + mykeydata->max_valdatalen = r.out.max_valbufsize; } return r.out.result; @@ -355,6 +407,7 @@ static struct registry_ops reg_backend_rpc = { .open_root_key = rpc_open_root, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, + .get_value_by_index = rpc_get_value_by_index, .add_key = rpc_add_key, .del_key = rpc_del_key, .free_key_backend_data = rpc_close_key, diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index eb32b1e55e..3e74db2557 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -53,7 +53,7 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals) } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching subkeys for '%s'\n", reg_key_get_path(p))); + DEBUG(0, ("Error occured while fetching values for '%s': %s\n", reg_key_get_path(p), win_errstr(error))); } } } -- cgit From 662013e60e777e3db43470eddcfdfbcbeded2e5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Apr 2004 13:39:07 +0000 Subject: r194: fixed compile with ldap (This used to be commit 3b4b528dc65bcb3b0de674e1d90c767244c94402) --- source4/lib/ldb/config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 1541dd6736..737ff8b6f6 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,4 +1,4 @@ -if test x"$HAVE_LDAP" = x"yes"; then +if test x"$with_ldap_support" = x"yes"; then SMB_SUBSYSTEM(LIBLDB_LDAP,[lib/ldb/ldb_ldap/ldb_ldap.o]) fi @@ -12,7 +12,7 @@ SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ lib/ldb/ldb_tdb/ldb_match.o \ - \$(LIBLDAP_LDAP_OBJS)], + \$(LIBLDB_LDAP_OBJS)], lib/ldb/include/ldb.h) SMB_SUBSYSTEM(LDBADD,[], -- cgit From 2199a6ffa909d1b53c7f4a3b87634432980c78d9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 13 Apr 2004 15:56:37 +0000 Subject: r199: More registry rpc updates (This used to be commit 02ddf78e5563b15cb45ae4bc6234469be0dc0210) --- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 43 ++++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 472a851638..6d1b293ee5 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -91,6 +91,8 @@ struct { { NULL, NULL } }; +static WERROR rpc_query_key(REG_KEY *k); + static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) { struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data)); @@ -204,27 +206,43 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) struct rpc_data *mydata = parent->handle->backend_data; struct winreg_EnumValueName vn; NTSTATUS status; - struct rpc_key_data *mykeydata = parent->backend_data; + struct rpc_key_data *mykeydata; uint32 type = 0x0, requested_len = 0, returned_len = 0; + WERROR error; + + error = rpc_key_put_rpc_data(parent, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; + + /* Root is a special case */ + if(parent->backend_data == parent->handle->backend_data) { + return WERR_NO_MORE_ITEMS; + } + + if(mykeydata->num_values == -1) { + error = rpc_query_key(parent); + if(!W_ERROR_IS_OK(error)) return error; + } + + requested_len = mykeydata->max_valdatalen; - /* FIXME */ - r.in.handle = &mykeydata->pol; r.in.enum_index = n; r.in.type = r.out.type = &type; r.in.requested_len = r.out.requested_len = &requested_len; r.in.returned_len = r.out.returned_len = &returned_len; - bn.max_len = mykeydata->max_valnamelen*3; - bn.offset = 0; - bn.len = 0; - bn.buffer = NULL; - vn.max_len = mykeydata->max_valnamelen*3; - vn.buf = &bn; + vn.max_len = mykeydata->max_valnamelen * 2; + vn.len = 0; + vn.buf = NULL; + if(vn.max_len > 0) { + vn.len = 0; + vn.max_len = mykeydata->max_valnamelen*2; + vn.buf = ""; + } r.in.name = r.out.name = &vn; - vb.max_len = mykeydata->max_valdatalen*3; + vb.max_len = mykeydata->max_valdatalen; vb.offset = 0x0; vb.len = 0x0; - vb.buffer = NULL; + vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen); r.in.value = r.out.value = &vb; status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r); @@ -234,10 +252,11 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { *value = reg_val_new(parent, NULL); - (*value)->name = (char *)r.out.name->buf->buffer; + (*value)->name = r.out.name->buf; (*value)->data_type = type; (*value)->data_len = r.out.value->len; (*value)->data_blk = r.out.value->buffer; + exit(1); return WERR_OK; } -- cgit From c7a60a178f4b28f40d70f7b0c12bec6ab7af7846 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Tue, 13 Apr 2004 17:34:37 +0000 Subject: r200: fix compile errors (This used to be commit c64132ddc6396a599a2e13b893e8abf1f731478f) --- source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 3 ++- source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 74d7bbd3b1..9a3005457e 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1575,11 +1575,12 @@ static WERROR nt_close_registry (REG_HANDLE *h) static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials) { - REGF *regf = (REGF *)talloc_p(h->mem_ctx, REGF); + REGF *regf; REGF_HDR *regf_hdr; unsigned int regf_id, hbin_id; HBIN_HDR *hbin_hdr; + regf = (REGF *)talloc_p(h->mem_ctx, REGF); memset(regf, 0, sizeof(REGF)); regf->owner_sid_str = credentials; h->backend_data = regf; diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 31abd69854..cd07e0a179 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -224,13 +224,15 @@ static WERROR w95_get_subkey_by_index (REG_KEY *parent, int n, REG_KEY **key) static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) { - CREG *creg = talloc_p(h->mem_ctx, CREG); + CREG *creg; DWORD creg_id, rgkn_id; - memset(creg, 0, sizeof(CREG)); - h->backend_data = creg; DWORD i, nfree = 0; DWORD offset, end_offset; + creg = talloc_p(h->mem_ctx, CREG); + memset(creg, 0, sizeof(CREG)); + h->backend_data = creg; + if((creg->fd = open(location, O_RDONLY, 0000)) < 0) { return WERR_FOOBAR; } -- cgit From b8ae2559a74134a98480ff6e36c72beb3ab050c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Apr 2004 16:02:30 +0000 Subject: r218: added a comment regarding the %c strftime() warning (This used to be commit 03c5dd88558bdd9ca714e6842ea65fa3b667657e) --- source4/lib/time.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index d6c6396996..0aef931fe0 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -358,6 +358,10 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) } #ifdef HAVE_STRFTIME + /* some versions of gcc complain about using %c. This is a bug + in the gcc warning, not a bug in this code. See a recent + strftime() manual page for details. + */ strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); TimeBuf = talloc_strdup(mem_ctx, tempTime); #else -- cgit From 6de32ddc2dbfe0685f361ed1a0dc11dff8ca19e5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 Apr 2004 21:39:03 +0000 Subject: r274: Be somewhat more POSIX compatible (This used to be commit c98a234d02d6190cf99ab1c9ff7b029f929e292a) --- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 28 +++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 375daa319b..960d5f3e04 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -80,22 +80,32 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) if(!d) return WERR_INVALID_PARAM; while((e = readdir(d))) { - if(e->d_type == DT_DIR && - strcmp(e->d_name, ".") && + if( strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { - ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); - ar[(*count)]->backend_data = talloc_asprintf(ar[*count]->mem_ctx, "%s/%s", fullpath, e->d_name); - if(ar[(*count)])(*count)++; + struct stat stbuf; + char *thispath; + + /* Check if file is a directory */ + asprintf(&thispath, "%s/%s", fullpath, e->d_name); + stat(thispath, &stbuf); - if((*count) == max) { - max+=200; - ar = realloc(ar, sizeof(REG_KEY *) * max); + if(S_ISDIR(stbuf.st_mode)) { + ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); + ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, thispath); + if(ar[(*count)])(*count)++; + + if((*count) == max) { + max+=200; + ar = realloc(ar, sizeof(REG_KEY *) * max); + } } + + SAFE_FREE(thispath); } } closedir(d); - + *r = ar; return WERR_OK; } -- cgit From ced7fa4b45adaf2807a5dc84de4fd0dfbcfed55a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Apr 2004 06:17:50 +0000 Subject: r323: added rough password quality checking in generate_random_str(), so we generate passwords that are likely to be accepted by the win2003 quality checks (This used to be commit 5954969f278e7f23190fe7301bfdc608f480eef6) --- source4/lib/genrand.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index e2e66f7e58..1423419961 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -242,6 +242,27 @@ void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) } } + +/* + very basic password quality checker +*/ +static BOOL check_password_quality(const char *s) +{ + int has_digit=0, has_capital=0, has_lower=0; + while (*s) { + if (isdigit(*s)) { + has_digit++; + } else if (isupper(*s)) { + has_capital++; + } else if (islower(*s)) { + has_lower++; + } + s++; + } + + return has_digit && has_lower && has_capital; +} + /******************************************************************* Use the random number generator to generate a random string. ********************************************************************/ @@ -257,11 +278,19 @@ char *generate_random_str(size_t len) if (len > sizeof(retstr)-1) len = sizeof(retstr) -1; - generate_random_buffer( retstr, len, False); + +again: + generate_random_buffer(retstr, len, False); for (i = 0; i < len; i++) - retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ]; + retstr[i] = c_list[retstr[i] % (sizeof(c_list)-1) ]; retstr[i] = '\0'; + /* we need to make sure the random string passes basic quality tests + or it might be rejected by windows as a password */ + if (len >= 7 && !check_password_quality(retstr)) { + goto again; + } + return (char *)retstr; } -- cgit From 493a37ba663686b7bee3f7093d6650a24250f101 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 Apr 2004 04:21:22 +0000 Subject: r335: added much better handling of servers that die unexpectedly during a request (a dead socket). I discovered this when testing against Sun's PC-NetLink. cleaned up the naming of some of the samr requests add IDL and test code for samr_QueryGroupMember(), samr_SetMemberAttributesOfGroup() and samr_Shutdown(). (actually, I didn't leave the samr_Shutdown() test in, as its fatal to windows servers due to doing exactly what it says it does). (This used to be commit 925bc2622c105dee4ffff809c6c35cd209a839f8) --- source4/lib/util_sock.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 95e0c5fe0c..57d3715cfc 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -187,6 +187,11 @@ ssize_t read_data(int fd, char *buffer, size_t N) ssize_t ret; size_t total=0; + if (fd == -1) { + errno = EIO; + return -1; + } + while (total < N) { ret = sys_read(fd,buffer + total,N - total); if (ret == 0) { @@ -209,6 +214,11 @@ ssize_t write_data(int fd, const char *buffer, size_t N) size_t total=0; ssize_t ret; + if (fd == -1) { + errno = EIO; + return -1; + } + while (total < N) { ret = sys_write(fd, buffer + total, N - total); if (ret == -1) { -- cgit From 07882b5460121c4ed100f9655935501f7cf23856 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 Apr 2004 13:05:27 +0000 Subject: r343: added automatic reindexing of the database when the index list changes (This used to be commit a811640ce408373a5c2c0ee2c125bd735d96d5e1) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 66 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 12 +++++++ 2 files changed, 78 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 8cda8abff8..95162ae575 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/ldb_tdb/ldb_tdb.h" struct dn_list { unsigned int count; @@ -723,3 +724,68 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) return 0; } + + +/* + traversal function that deletes all @INDEX records +*/ +static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) +{ + if (strncmp(key.dptr, "@INDEX:", 7) == 0) { + return tdb_delete(tdb, key); + } + return 0; +} + +/* + traversal function that adds @INDEX records during a re index +*/ +static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) +{ + struct ldb_context *ldb = state; + struct ldb_message msg; + int ret; + + if (strncmp(key.dptr, "DN=@", 4) == 0 || + strncmp(key.dptr, "DN=", 3) != 0) { + return 0; + } + + ret = ltdb_unpack_data(ldb, &data, &msg); + if (ret != 0) { + return -1; + } + + msg.dn = key.dptr+3; + + ret = ltdb_index_add(ldb, &msg); + + ltdb_unpack_data_free(&msg); + + return ret; +} + +/* + force a complete reindex of the database +*/ +int ltdb_reindex(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private; + int ret; + + /* first traverse the database deleting any @INDEX records */ + ret = tdb_traverse(ltdb->tdb, delete_index, NULL); + if (ret == -1) { + errno = EIO; + return -1; + } + + /* now traverse adding any indexes for normal LDB records */ + ret = tdb_traverse(ltdb->tdb, re_index, ldb); + if (ret == -1) { + errno = EIO; + return -1; + } + + return 0; +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index b28d73cbea..34cff41794 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -148,6 +148,10 @@ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) ret = ltdb_store(ldb, msg, TDB_INSERT); + if (strcmp(msg->dn, "@INDEXLIST") == 0) { + ltdb_reindex(ldb); + } + ltdb_unlock(ldb); return ret; @@ -206,6 +210,10 @@ static int ltdb_delete(struct ldb_context *ldb, const char *dn) ltdb_search_dn1_free(ldb, &msg); + if (strcmp(dn, "@INDEXLIST") == 0) { + ltdb_reindex(ldb); + } + ltdb_unlock(ldb); return ret; @@ -430,6 +438,10 @@ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) /* we've made all the mods - save the modified record back into the database */ ret = ltdb_store(ldb, &msg2, TDB_MODIFY); + if (strcmp(msg2.dn, "@INDEXLIST") == 0) { + ltdb_reindex(ldb); + } + free(tdb_key.dptr); free(tdb_data.dptr); ltdb_unpack_data_free(&msg2); -- cgit From 803b5d8aa46f5a26a31b65992e5aa34e3df9495c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 Apr 2004 13:09:53 +0000 Subject: r344: fixed deletion of index records (This used to be commit 246f17cd4a7851042739574f1e07b113c44275c7) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 95162ae575..05ae2bbc14 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -731,7 +731,7 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) */ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { - if (strncmp(key.dptr, "@INDEX:", 7) == 0) { + if (strncmp(key.dptr, "DN=@INDEX:", 10) == 0) { return tdb_delete(tdb, key); } return 0; -- cgit From f3d3b3c8091ad4540c330c07662540440affb96e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 25 Apr 2004 22:15:48 +0000 Subject: r355: Fix a bunch of compiler warnings in the registry code. (This used to be commit 0be7a866dc39e2d63c9c114d0f668287259e7c9e) --- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 11 ++++++++--- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 14 ++++---------- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 15 +++++++++------ source4/lib/registry/tools/regdiff.c | 21 +++++++++------------ source4/lib/registry/tools/regpatch.c | 2 -- source4/lib/registry/tools/regshell.c | 3 +-- source4/lib/registry/tools/regtree.c | 1 - 7 files changed, 31 insertions(+), 36 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 9a3005457e..ff39954a9f 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -945,6 +945,8 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val return WERR_OK; } +#if 0 /* unused */ + static BOOL vl_verify(VL_TYPE vl, int count, int size) { if(!vl) return False; @@ -955,6 +957,8 @@ static BOOL vl_verify(VL_TYPE vl, int count, int size) return True; } +#endif + static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) { int lf_id; @@ -1128,6 +1132,8 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent return WERR_OK; } +#if 0 /* unused */ + /* * Allocate a new hbin block, set up the header for the block etc */ @@ -1463,8 +1469,6 @@ static unsigned int nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) } -#if 0 - /* * Store a KEY in the file ... * @@ -1534,7 +1538,6 @@ static int nt_store_reg_key(REG_HANDLE *regf, REG_KEY *key) error: return 0; } -#endif /* * Store the registry header ... @@ -1563,6 +1566,8 @@ error: return NULL; } +#endif + static WERROR nt_close_registry (REG_HANDLE *h) { REGF *regf = h->backend_data; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 6d1b293ee5..a24df893fb 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -192,7 +192,6 @@ static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) { - WERROR error; struct rpc_key_data *mykeydata; *key = reg_key_new_abs(name, h, NULL); return rpc_key_put_rpc_data(*key, &mykeydata); @@ -202,7 +201,6 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) { struct winreg_EnumValue r; struct winreg_Uint8buf vb; - struct winreg_Uint16buf bn; struct rpc_data *mydata = parent->handle->backend_data; struct winreg_EnumValueName vn; NTSTATUS status; @@ -272,9 +270,7 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) struct rpc_data *mydata = parent->handle->backend_data; struct rpc_key_data *mykeydata = parent->backend_data; WERROR error; - int i; NTSTATUS status; - TALLOC_CTX *mem_ctx; /* If parent is the root key, list the hives */ if(parent->backend_data == mydata) { @@ -321,10 +317,8 @@ static WERROR rpc_query_key(REG_KEY *k) { NTSTATUS status; struct winreg_QueryInfoKey r; - struct rpc_data *mydata = k->handle->backend_data; - struct rpc_key_data *mykeydata; - WERROR error = rpc_key_put_rpc_data(k, &mykeydata); - + struct rpc_data *mydata = k->handle->backend_data; + struct rpc_key_data *mykeydata; r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.class, NULL); @@ -387,7 +381,7 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) { if(!W_ERROR_IS_OK(error)) return error; if(mykeydata->num_values == -1) { - WERROR error = rpc_query_key(key); + error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; } @@ -411,7 +405,7 @@ static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { if(!W_ERROR_IS_OK(error)) return error; if(mykeydata->num_subkeys == -1) { - WERROR error = rpc_query_key(key); + error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; } diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index cd07e0a179..80108fd541 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -137,6 +137,8 @@ static DWORD str_to_dword(const char *a) { return ret; } +#if 0 /* unused */ + static DWORD calc_hash(const char *str) { DWORD ret = 0; int i; @@ -152,7 +154,7 @@ static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off) for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) { RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i); if(key->type == 0) { - DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, key->hash)); + DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, (long)key->hash)); } else if(key->type == 0x80000000) { DEBUG(3,("free\n")); i += key->hash; @@ -162,6 +164,8 @@ static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off) } } +#endif + static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) { DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size; @@ -226,8 +230,8 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre { CREG *creg; DWORD creg_id, rgkn_id; - DWORD i, nfree = 0; - DWORD offset, end_offset; + DWORD i; + DWORD offset; creg = talloc_p(h->mem_ctx, CREG); memset(creg, 0, sizeof(CREG)); @@ -284,8 +288,8 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset); if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { - DEBUG(0, ("unrecognized rgdb entry: %4s, %s\n", - &rgdb_hdr->RGDB_ID, location)); + DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n", + rgdb_hdr->RGDB_ID, location)); return WERR_FOOBAR; } else { DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); @@ -317,7 +321,6 @@ static WERROR w95_close_reg(REG_HANDLE *h) static WERROR w95_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) { RGKN_KEY *rgkn_key = k->backend_data; - RGDB_VALUE *val; DWORD i; DWORD offset = 0; RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->handle->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 94cdf8c8af..305a7a1e46 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -23,7 +23,7 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) { - int i, numkeys1, numvals1, numvals2, numkeys2; + int i; REG_KEY *t1,*t2; REG_VAL *v1, *v2; WERROR error1, error2; @@ -33,12 +33,12 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "-%s\n", reg_key_get_path(t1)+1); } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", error2)); + DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } } if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", error1)); + DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } @@ -47,13 +47,13 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1); } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", error2)); + DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } writediff(t2, t1, out); } if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", error1)); + DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } @@ -65,12 +65,12 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - DEBUG(0, ("Error occured while getting value by name: %d\n", error2)); + DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); } } if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", error1)); + DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; } @@ -81,22 +81,20 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\"%s\"=-\n", reg_val_name(v1)); } else { - DEBUG(0, ("Error occured while getting value by name: %d\n", error2)); + DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); } } if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", error1)); + DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; } } int main (int argc, char **argv) { - uint32 setparms, checkparms; int opt; poptContext pc; - REG_KEY *root; const char *backend1 = NULL, *backend2 = NULL; const char *location2; const char *credentials1= NULL, *credentials2 = NULL; @@ -105,7 +103,6 @@ int main (int argc, char **argv) REG_HANDLE *h2; REG_KEY *root1 = NULL, *root2; int from_null = 0; - int fullpath = 0, no_values = 0; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 9a51b0f7ff..e632edaa49 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -754,7 +754,6 @@ int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) int main (int argc, char **argv) { - uint32 setparms, checkparms; int opt; poptContext pc; REG_KEY *root; @@ -763,7 +762,6 @@ int main (int argc, char **argv) const char *patch; const char *backend = "dir"; REG_HANDLE *h; - int fullpath = 0, no_values = 0; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 18399b5bda..8ee2a65d06 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -58,7 +58,7 @@ static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) { - int i, num; + int i; WERROR error; REG_VAL *value; REG_KEY *sub; @@ -198,7 +198,6 @@ REG_KEY *process_cmd(REG_KEY *k, char *line) int main (int argc, char **argv) { - uint32 setparms, checkparms; int opt; char *backend = "dir"; char *credentials = NULL; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 3e74db2557..94018bdc5c 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -60,7 +60,6 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals) int main (int argc, char **argv) { - uint32 setparms, checkparms; int opt; char *backend = "dir", *credentials = NULL; poptContext pc; -- cgit From 888240138203123222c5a983616b524f9325f606 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Apr 2004 07:10:16 +0000 Subject: r373: use a much larger default tdb hash size in ldb (This used to be commit 54f47c45b8f828ad5ddaa630d0c1e673f2c74b7a) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 34cff41794..a4eb83a20e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -524,7 +524,8 @@ struct ldb_context *ltdb_connect(const char *url, open_flags = O_CREAT | O_RDWR; } - tdb = tdb_open(path, 0, tdb_flags, open_flags, 0666); + /* note that we use quite a large default hash size */ + tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); if (!tdb) { return NULL; } -- cgit From ee0489fff69533d04318de249aabd8d1d021d285 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 Apr 2004 06:43:35 +0000 Subject: r380: make sure that ldbedit -a works with all tdb and LDAP backends (This used to be commit b5cb5a1e62a4b9df6f163082498942553662436e) --- source4/lib/ldb/tools/ldbedit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 5ae62d3ac1..07ed66d68a 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -318,7 +318,7 @@ static void usage(void) break; case 'a': - expression = "objectclass=*"; + expression = "(|(objectclass=*)(dn=*))"; break; case 'h': -- cgit From 6411aa483f9233af098b4893ad67ebd2fd9d5868 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 Apr 2004 07:05:28 +0000 Subject: r381: make the code more C++ friendly (This used to be commit 8acecc7f27e25ab876fffffe43ae75b5f77aff77) --- source4/lib/ldb/common/ldb.c | 2 +- source4/lib/ldb/include/ldb.h | 4 ++-- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 14 +++++++------- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 4 ++-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 16 ++++++++-------- 6 files changed, 21 insertions(+), 21 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index e84473efab..66d3696786 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -119,7 +119,7 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const char *dn) { - return ldb->ops->delete(ldb, dn); + return ldb->ops->delete_record(ldb, dn); } /* diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index dc1b1d7732..d010d8dd40 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -128,7 +128,7 @@ struct ldb_backend_ops { int (*search_free)(struct ldb_context *, struct ldb_message **); int (*add)(struct ldb_context *, const struct ldb_message *); int (*modify)(struct ldb_context *, const struct ldb_message *); - int (*delete)(struct ldb_context *, const char *); + int (*delete_record)(struct ldb_context *, const char *); const char * (*errstring)(struct ldb_context *); }; @@ -137,7 +137,7 @@ struct ldb_backend_ops { */ struct ldb_context { /* a private pointer for the backend to use */ - void *private; + void *private_data; /* the operations provided by the backend */ const struct ldb_backend_ops *ops; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 25af43c569..510f28a45e 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -71,7 +71,7 @@ static const char *lldb_option_find(const struct lldb_private *lldb, const char static int lldb_close(struct ldb_context *ldb) { int i, ret = 0; - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) { ret = -1; @@ -94,7 +94,7 @@ static int lldb_close(struct ldb_context *ldb) */ static int lldb_delete(struct ldb_context *ldb, const char *dn) { - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; int ret = 0; lldb->last_rc = ldap_delete_s(lldb->ldap, dn); @@ -204,7 +204,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, const char **attrs, struct ldb_message ***res) { - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; int count, msg_count; LDAPMessage *ldapres, *msg; @@ -388,7 +388,7 @@ failed: */ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) { - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; LDAPMod **mods; int ret = 0; @@ -410,7 +410,7 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) */ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) { - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; LDAPMod **mods; int ret = 0; @@ -432,7 +432,7 @@ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) */ static const char *lldb_errstring(struct ldb_context *ldb) { - struct lldb_private *lldb = ldb->private; + struct lldb_private *lldb = ldb->private_data; return ldap_err2string(lldb->last_rc); } @@ -481,7 +481,7 @@ struct ldb_context *lldb_connect(const char *url, } ldb->ops = &lldb_ops; - ldb->private = lldb; + ldb->private_data = lldb; if (options) { /* take a copy of the options array, so we don't have to rely diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 05ae2bbc14..d4e6c95d63 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -770,7 +770,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * */ int ltdb_reindex(struct ldb_context *ldb) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; int ret; /* first traverse the database deleting any @INDEX records */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 9cb5853c94..9a2287e20e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -237,7 +237,7 @@ void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) */ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; int ret; TDB_DATA tdb_key, tdb_data; @@ -427,7 +427,7 @@ static int ltdb_search_full(struct ldb_context *ldb, struct ldb_parse_tree *tree, const char *attrs[], struct ldb_message ***res) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; int ret; struct ltdb_search_info sinfo; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index a4eb83a20e..ff0c0a53b7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -63,7 +63,7 @@ struct TDB_DATA ltdb_key(const char *dn) */ static int ltdb_lock(struct ldb_context *ldb) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; TDB_DATA key; int ret; @@ -84,7 +84,7 @@ static int ltdb_lock(struct ldb_context *ldb) */ static void ltdb_unlock(struct ldb_context *ldb) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; TDB_DATA key; key = ltdb_key("LDBLOCK"); @@ -102,7 +102,7 @@ static void ltdb_unlock(struct ldb_context *ldb) */ int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; TDB_DATA tdb_key, tdb_data; int ret; @@ -164,7 +164,7 @@ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) */ int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; TDB_DATA tdb_key; int ret; @@ -357,7 +357,7 @@ static int msg_delete_element(struct ldb_message *msg, */ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; TDB_DATA tdb_key, tdb_data; struct ldb_message msg2; int ret, i, j; @@ -465,7 +465,7 @@ unlock_fail: */ static int ltdb_close(struct ldb_context *ldb) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; int ret; ret = tdb_close(ltdb->tdb); free(ltdb); @@ -479,7 +479,7 @@ static int ltdb_close(struct ldb_context *ldb) */ static const char *ltdb_errstring(struct ldb_context *ldb) { - struct ltdb_private *ltdb = ldb->private; + struct ltdb_private *ltdb = ldb->private_data; return tdb_errorstr(ltdb->tdb); } @@ -548,7 +548,7 @@ struct ldb_context *ltdb_connect(const char *url, return NULL; } - ldb->private = ltdb; + ldb->private_data = ltdb; ldb->ops = <db_ops; return ldb; -- cgit From b0b97592be312b3553ac31cc3f3cb994de06e506 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 28 Apr 2004 07:32:37 +0000 Subject: r382: More C++ friendliness fixes. (This used to be commit e96f3a2005cf6f4da2ecd4670a35eab1b4f250d0) --- source4/lib/ldb/common/ldb_ldif.c | 10 +++++----- source4/lib/ldb/include/ldb.h | 6 +++--- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 5f2fccfebc..2eaee28eb6 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -410,7 +410,7 @@ void ldif_read_free(struct ldb_ldif *ldif) if (msg->elements[i].values) free(msg->elements[i].values); } if (msg->elements) free(msg->elements); - if (msg->private) free(msg->private); + if (msg->private_data) free(msg->private_data); free(ldif); } @@ -444,7 +444,7 @@ static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned fla /* read from a LDIF source, creating a ldb_message */ -struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private) +struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) { struct ldb_ldif *ldif; struct ldb_message *msg; @@ -463,14 +463,14 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private) msg->dn = NULL; msg->elements = NULL; msg->num_elements = 0; - msg->private = NULL; + msg->private_data = NULL; - chunk = next_chunk(fgetc_fn, private); + chunk = next_chunk(fgetc_fn, private_data); if (!chunk) { goto failed; } - msg->private = chunk; + msg->private_data = chunk; s = chunk; if (next_attr(&s, &attr, &value) != 0) { diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index d010d8dd40..ef00cdf32c 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -86,7 +86,7 @@ struct ldb_message { char *dn; unsigned int num_elements; struct ldb_message_element *elements; - void *private; /* private to the backend */ + void *private_data; /* private to the backend */ }; enum ldb_changetype { @@ -210,10 +210,10 @@ const char *ldb_errstring(struct ldb_context *ldb); ldif manipulation functions */ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), - void *private, + void *private_data, const struct ldb_ldif *ldif); void ldif_read_free(struct ldb_ldif *); -struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private); +struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data); struct ldb_ldif *ldif_read_file(FILE *f); struct ldb_ldif *ldif_read_string(const char *s); int ldif_write_file(FILE *f, const struct ldb_ldif *msg); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 510f28a45e..55c083b44c 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -264,7 +264,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, (*res)[msg_count]->num_elements = 0; (*res)[msg_count]->elements = NULL; - (*res)[msg_count]->private = NULL; + (*res)[msg_count]->private_data = NULL; /* loop over all attributes */ for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr); diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index d4e6c95d63..a23fc2d525 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -576,7 +576,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, } msg.num_elements = 0; msg.elements = NULL; - msg.private = NULL; + msg.private_data = NULL; } free(dn_key); diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 9a2287e20e..fe84091303 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -166,7 +166,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, ret->num_elements = 0; ret->elements = NULL; - ret->private = NULL; + ret->private_data = NULL; if (!attrs) { if (msg_add_all_elements(ret, msg) != 0) { @@ -221,7 +221,7 @@ void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { int i; if (msg->dn) free(msg->dn); - if (msg->private) free(msg->private); + if (msg->private_data) free(msg->private_data); for (i=0;inum_elements;i++) { if (msg->elements[i].values) free(msg->elements[i].values); } @@ -258,7 +258,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message free(tdb_data.dptr); return -1; } - msg->private = tdb_data.dptr; + msg->private_data = tdb_data.dptr; msg->num_elements = 0; msg->elements = NULL; -- cgit From a00c266702ca81a3689996198590b5b69a967940 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 Apr 2004 13:06:25 +0000 Subject: r387: more C++ friendly changes (This used to be commit ac0c525a8b8a05cc275fb9f4c1dcfd749604c85f) --- source4/lib/ldb/common/ldb.c | 4 +-- source4/lib/ldb/common/ldb_ldif.c | 54 +++++++++++++++++++-------------------- source4/lib/ldb/include/ldb.h | 4 +-- 3 files changed, 31 insertions(+), 31 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 66d3696786..f61ddecdc7 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -101,7 +101,7 @@ int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->ops->add(ldb, message); + return ldb->ops->add_record(ldb, message); } /* @@ -110,7 +110,7 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->ops->modify(ldb, message); + return ldb->ops->modify_record(ldb, message); } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 2eaee28eb6..fcf0150557 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -143,17 +143,17 @@ int ldb_should_b64_encode(const struct ldb_val *val) /* write a line folded string onto a file */ -static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private, +static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data, const char *buf, size_t length, int start_pos) { int i; int total=0, ret; for (i=0;imsg; - ret = fprintf_fn(private, "dn: %s\n", msg->dn); + ret = fprintf_fn(private_data, "dn: %s\n", msg->dn); CHECK_RET; if (ldif->changetype != LDB_CHANGETYPE_NONE) { @@ -217,7 +217,7 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), fprintf(stderr,"Invalid changetype\n"); return -1; } - ret = fprintf_fn(private, "changetype: %s\n", ldb_changetypes[i].name); + ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name); CHECK_RET; } @@ -225,15 +225,15 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_ADD: - fprintf_fn(private, "add: %s\n", + fprintf_fn(private_data, "add: %s\n", msg->elements[i].name); break; case LDB_FLAG_MOD_DELETE: - fprintf_fn(private, "delete: %s\n", + fprintf_fn(private_data, "delete: %s\n", msg->elements[i].name); break; case LDB_FLAG_MOD_REPLACE: - fprintf_fn(private, "replace: %s\n", + fprintf_fn(private_data, "replace: %s\n", msg->elements[i].name); break; } @@ -241,33 +241,33 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), for (j=0;jelements[i].num_values;j++) { if (ldb_should_b64_encode(&msg->elements[i].values[j])) { - ret = fprintf_fn(private, "%s:: ", + ret = fprintf_fn(private_data, "%s:: ", msg->elements[i].name); CHECK_RET; - ret = base64_encode_f(fprintf_fn, private, + ret = base64_encode_f(fprintf_fn, private_data, msg->elements[i].values[j].data, msg->elements[i].values[j].length, strlen(msg->elements[i].name)+3); CHECK_RET; - ret = fprintf_fn(private, "\n"); + ret = fprintf_fn(private_data, "\n"); CHECK_RET; } else { - ret = fprintf_fn(private, "%s: ", msg->elements[i].name); + ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name); CHECK_RET; - ret = fold_string(fprintf_fn, private, + ret = fold_string(fprintf_fn, private_data, msg->elements[i].values[j].data, msg->elements[i].values[j].length, strlen(msg->elements[i].name)+2); CHECK_RET; - ret = fprintf_fn(private, "\n"); + ret = fprintf_fn(private_data, "\n"); CHECK_RET; } } if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { - fprintf_fn(private, "-\n"); + fprintf_fn(private_data, "-\n"); } } - ret = fprintf_fn(private,"\n"); + ret = fprintf_fn(private_data,"\n"); CHECK_RET; return total; @@ -282,14 +282,14 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), caller frees */ -static char *next_chunk(int (*fgetc_fn)(void *), void *private) +static char *next_chunk(int (*fgetc_fn)(void *), void *private_data) { size_t alloc_size=0, chunk_size = 0; char *chunk = NULL; int c; int in_comment = 0; - while ((c = fgetc_fn(private)) != EOF) { + while ((c = fgetc_fn(private_data)) != EOF) { if (chunk_size+1 >= alloc_size) { char *c2; alloc_size += 1024; @@ -578,9 +578,9 @@ struct ldif_read_file_state { FILE *f; }; -static int fgetc_file(void *private) +static int fgetc_file(void *private_data) { - struct ldif_read_file_state *state = private; + struct ldif_read_file_state *state = private_data; return fgetc(state->f); } @@ -599,9 +599,9 @@ struct ldif_read_string_state { const char *s; }; -static int fgetc_string(void *private) +static int fgetc_string(void *private_data) { - struct ldif_read_string_state *state = private; + struct ldif_read_string_state *state = private_data; if (state->s[0] != 0) { return *state->s++; } @@ -623,9 +623,9 @@ struct ldif_write_file_state { FILE *f; }; -static int fprintf_file(void *private, const char *fmt, ...) +static int fprintf_file(void *private_data, const char *fmt, ...) { - struct ldif_write_file_state *state = private; + struct ldif_write_file_state *state = private_data; int ret; va_list ap; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index ef00cdf32c..6369ab683a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -126,8 +126,8 @@ struct ldb_backend_ops { int (*search)(struct ldb_context *, const char *, enum ldb_scope, const char *, const char *[], struct ldb_message ***); int (*search_free)(struct ldb_context *, struct ldb_message **); - int (*add)(struct ldb_context *, const struct ldb_message *); - int (*modify)(struct ldb_context *, const struct ldb_message *); + int (*add_record)(struct ldb_context *, const struct ldb_message *); + int (*modify_record)(struct ldb_context *, const struct ldb_message *); int (*delete_record)(struct ldb_context *, const char *); const char * (*errstring)(struct ldb_context *); }; -- cgit From 4c991c6edd2a46d7452096ba80c00e7ab4c95924 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 30 Apr 2004 12:52:58 +0000 Subject: r425: add some comments to ugly code parts we should take care of 'char *' and 'const char *' and DO NOT mix them! Jelmer: please fix this metze (This used to be commit cd609eb2fe9303825d5562047d57fd553b2601bd) --- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index fdbb7345d2..3600ab62ea 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -160,7 +160,6 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) mem_ctx = talloc_init("mem_ctx"); fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); -\ if(!parent->handle->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); @@ -432,6 +431,7 @@ WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) { REG_KEY *cur, *prevcur = parent; WERROR error; + /* FIXME: we should never write to a 'const char *' !!! --metze */ char *begin = (char *)path, *end; while(1) { diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index a24df893fb..de2c2261b9 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -234,6 +234,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) if(vn.max_len > 0) { vn.len = 0; vn.max_len = mykeydata->max_valnamelen*2; + /* FIXME: we should not point a 'char *' to a const buffer!!! --metze*/ vn.buf = ""; } r.in.name = r.out.name = &vn; -- cgit From 0dad5a34273bf5cadcfd4a36d69bdffbf69eb073 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 May 2004 09:45:56 +0000 Subject: r435: a major upgrade for ldb - added the ability to mark record attributes as being CASE_INSENSITIVE, WILDCARD or INTEGER. - added the ability to support objectclass subclasses, and to search by a parent class - added internal support for case insensitive versus case sensitive indexing (not UTF8 compliant yet) - cleaned up a number of const warnings - added a number of helper functions for fetching integers, strings and doubles - added a in-memory cache for important database properties, supported by a database sequence number - changed some variable names to avoid conflicts with C++ (This used to be commit f2bf06f25c2e6c744817711c7bedbd1d3b52f994) --- source4/lib/ldb/Makefile.ldb | 8 +- source4/lib/ldb/common/ldb_ldif.c | 30 +++-- source4/lib/ldb/common/ldb_msg.c | 71 +++++++++- source4/lib/ldb/common/ldb_utf8.c | 87 ++++++++++++ source4/lib/ldb/config.m4 | 2 + source4/lib/ldb/include/includes.h | 1 + source4/lib/ldb/include/ldb.h | 8 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 17 ++- source4/lib/ldb/ldb_tdb/ldb_cache.c | 229 ++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_index.c | 75 ++++++----- source4/lib/ldb/ldb_tdb/ldb_match.c | 165 +++++++++++++++++++++-- source4/lib/ldb/ldb_tdb/ldb_pack.c | 56 ++++++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 56 +++++--- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 186 ++++++++++++++++++++------ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 36 +++++ source4/lib/ldb/tests/test-attribs.ldif | 13 ++ source4/lib/ldb/tests/test-generic.sh | 4 +- source4/lib/ldb/tools/ldbedit.c | 2 +- 18 files changed, 904 insertions(+), 142 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_utf8.c create mode 100644 source4/lib/ldb/ldb_tdb/ldb_cache.c create mode 100644 source4/lib/ldb/tests/test-attribs.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 6ff1bcf78e..ba8c040f9c 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -17,11 +17,12 @@ LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ - ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o + ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ + ldb_tdb/ldb_cache.o COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ - common/ldb_parse.o common/ldb_msg.o + common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) @@ -66,3 +67,6 @@ proto: etags: etags */*.[ch] + +test: + tests/test-tdb.sh diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index fcf0150557..1ca585ca80 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -407,6 +407,7 @@ void ldif_read_free(struct ldb_ldif *ldif) struct ldb_message *msg = &ldif->msg; int i; for (i=0;inum_elements;i++) { + if (msg->elements[i].name) free(msg->elements[i].name); if (msg->elements[i].values) free(msg->elements[i].values); } if (msg->elements) free(msg->elements); @@ -431,11 +432,16 @@ static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned fla el = &msg->elements[msg->num_elements]; - el->name = name; + el->name = strdup(name); el->num_values = 0; el->values = NULL; el->flags = flags; + if (!el->name) { + errno = ENOMEM; + return -1; + } + msg->num_elements++; return 0; @@ -478,7 +484,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) } /* first line must be a dn */ - if (strcmp(attr, "dn") != 0) { + if (ldb_attr_cmp(attr, "dn") != 0) { fprintf(stderr, "First line must be a dn not '%s'\n", attr); goto failed; } @@ -489,10 +495,10 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) struct ldb_message_element *el; int empty = 0; - if (strcmp(attr, "changetype") == 0) { + if (ldb_attr_cmp(attr, "changetype") == 0) { int i; for (i=0;ldb_changetypes[i].name;i++) { - if (strcmp((char *)value.data, ldb_changetypes[i].name) == 0) { + if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) { ldif->changetype = ldb_changetypes[i].changetype; break; } @@ -505,19 +511,19 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) continue; } - if (strcmp(attr, "add") == 0) { + if (ldb_attr_cmp(attr, "add") == 0) { flags = LDB_FLAG_MOD_ADD; empty = 1; } - if (strcmp(attr, "delete") == 0) { + if (ldb_attr_cmp(attr, "delete") == 0) { flags = LDB_FLAG_MOD_DELETE; empty = 1; } - if (strcmp(attr, "replace") == 0) { + if (ldb_attr_cmp(attr, "replace") == 0) { flags = LDB_FLAG_MOD_REPLACE; empty = 1; } - if (strcmp(attr, "-") == 0) { + if (ldb_attr_cmp(attr, "-") == 0) { flags = 0; continue; } @@ -531,7 +537,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) el = &msg->elements[msg->num_elements-1]; - if (msg->num_elements > 0 && strcmp(attr, el->name) == 0 && + if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) { /* its a continuation */ el->values = @@ -549,11 +555,11 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) if (!msg->elements) { goto failed; } - msg->elements[msg->num_elements].flags = flags; - msg->elements[msg->num_elements].name = attr; el = &msg->elements[msg->num_elements]; + el->flags = flags; + el->name = strdup(attr); el->values = malloc_p(struct ldb_val); - if (!el->values) { + if (!el->values || !el->name) { goto failed; } el->num_values = 1; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 633cc91f2c..8eb8a8c5ef 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -43,23 +43,40 @@ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, { int i; for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, attr_name) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { return &msg->elements[i]; } } return NULL; } +/* + see if two ldb_val structures contain exactly the same data + return 1 for a match, 0 for a mis-match +*/ +int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) return 0; + + if (v1->length == 0) return 1; + + if (memcmp(v1->data, v2->data, v1->length) == 0) { + return 1; + } + + return 0; +} /* find a value in an element + assumes case sensitive comparison */ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, struct ldb_val *val) { int i; for (i=0;inum_values;i++) { - if (ldb_val_equal(val, &el->values[i])) { + if (ldb_val_equal_exact(val, &el->values[i])) { return &el->values[i]; } } @@ -113,6 +130,7 @@ int ldb_msg_add(struct ldb_message *msg, /* compare two ldb_message_element structures + assumes case senistive comparison */ int ldb_msg_element_compare(struct ldb_message_element *el1, struct ldb_message_element *el2) @@ -131,3 +149,52 @@ int ldb_msg_element_compare(struct ldb_message_element *el1, return 0; } + + +/* + convenience functions to return common types from a message + these return the first value if the attribute is multi-valued +*/ +int ldb_msg_find_int(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtol(el->values[0].data, NULL, 0); +} + +unsigned int ldb_msg_find_uint(const struct ldb_message *msg, + const char *attr_name, + int default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtoul(el->values[0].data, NULL, 0); +} + +double ldb_msg_find_double(const struct ldb_message *msg, + const char *attr_name, + double default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return strtod(el->values[0].data, NULL); +} + +const char *ldb_msg_find_string(const struct ldb_message *msg, + const char *attr_name, + const char *default_value) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return default_value; + } + return el->values[0].data; +} diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c new file mode 100644 index 0000000000..7767b0955e --- /dev/null +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -0,0 +1,87 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb utf8 handling + * + * Description: case folding and case comparison for UTF8 strings + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +/* + TODO: + a simple case folding function - will be replaced by a UTF8 aware function later +*/ +char *ldb_casefold(const char *s) +{ + int i; + char *ret = strdup(s); + if (!s) { + errno = ENOMEM; + return NULL; + } + for (i=0;ret[i];i++) { + ret[i] = toupper(ret[i]); + } + return ret; +} + +/* + a caseless compare, optimised for 7 bit + TODO: doesn't yet handle UTF8 +*/ +static int ldb_caseless_cmp(const char *s1, const char *s2) +{ + int i; + for (i=0;s1[i] != 0;i++) { + int c1 = toupper(s1[i]), c2 = toupper(s2[i]); + if (c1 != c2) { + return c1 - c2; + } + } + return s2[i]; +} + +/* + compare two basedn fields + return 0 for match +*/ +int ldb_dn_cmp(const char *dn1, const char *dn2) +{ + return ldb_caseless_cmp(dn1, dn2); +} + +/* + compare two attributes + return 0 for match +*/ +int ldb_attr_cmp(const char *dn1, const char *dn2) +{ + return ldb_caseless_cmp(dn1, dn2); +} diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 737ff8b6f6..444e65bfab 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -7,11 +7,13 @@ SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], lib/ldb/common/ldb_parse.o \ lib/ldb/common/ldb_msg.o \ lib/ldb/common/util.o \ + lib/ldb/common/ldb_utf8.o \ lib/ldb/ldb_tdb/ldb_search.o \ lib/ldb/ldb_tdb/ldb_tdb.o \ lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ lib/ldb/ldb_tdb/ldb_match.o \ + lib/ldb/ldb_tdb/ldb_cache.o \ \$(LIBLDB_LDAP_OBJS)], lib/ldb/include/ldb.h) diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 70ad1f3588..485d7157b8 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "ldb.h" #include "ldb_parse.h" diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 6369ab683a..215671c98a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -124,7 +124,7 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_backend_ops { int (*close)(struct ldb_context *); int (*search)(struct ldb_context *, const char *, enum ldb_scope, - const char *, const char *[], struct ldb_message ***); + const char *, char * const [], struct ldb_message ***); int (*search_free)(struct ldb_context *, struct ldb_message **); int (*add_record)(struct ldb_context *, const struct ldb_message *); int (*modify_record)(struct ldb_context *, const struct ldb_message *); @@ -206,6 +206,11 @@ int ldb_delete(struct ldb_context *ldb, const char *dn); */ const char *ldb_errstring(struct ldb_context *ldb); +/* + casefold a string (should be UTF8, but at the moment it isn't) +*/ +char *ldb_casefold(const char *s); + /* ldif manipulation functions */ @@ -217,3 +222,4 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data); struct ldb_ldif *ldif_read_file(FILE *f); struct ldb_ldif *ldif_read_string(const char *s); int ldif_write_file(FILE *f, const struct ldb_ldif *msg); + diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 55c083b44c..8723beeadc 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -96,6 +96,11 @@ static int lldb_delete(struct ldb_context *ldb, const char *dn) { struct lldb_private *lldb = ldb->private_data; int ret = 0; + + /* ignore ltdb specials */ + if (dn[0] == '@') { + return 0; + } lldb->last_rc = ldap_delete_s(lldb->ldap, dn); if (lldb->last_rc != LDAP_SUCCESS) { @@ -202,7 +207,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg, */ static int lldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char **attrs, struct ldb_message ***res) + char * const *attrs, struct ldb_message ***res) { struct lldb_private *lldb = ldb->private_data; int count, msg_count; @@ -392,6 +397,11 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) LDAPMod **mods; int ret = 0; + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + mods = lldb_msg_to_mods(msg, 0); lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods); @@ -414,6 +424,11 @@ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) LDAPMod **mods; int ret = 0; + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + mods = lldb_msg_to_mods(msg, 1); lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods); diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c new file mode 100644 index 0000000000..5d61fd35b3 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -0,0 +1,229 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb tdb cache functions + * + * Description: cache special records in a ldb/tdb + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb/ldb_tdb/ldb_tdb.h" + +/* + initialise the baseinfo record +*/ +static int ltdb_baseinfo_init(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + struct ldb_message msg; + struct ldb_message_element el; + struct ldb_val val; + + ltdb->sequence_number = 0; + + msg.num_elements = 1; + msg.elements = ⪙ + msg.dn = LTDB_BASEINFO; + el.name = LTDB_SEQUENCE_NUMBER; + el.values = &val; + el.num_values = 1; + el.flags = 0; + val.data = "0"; + val.length = 1; + + return ltdb_store(ldb, &msg, TDB_INSERT); +} + +/* + free any cache records + */ +void ltdb_cache_free(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + + ltdb->sequence_number = 0; + ltdb_search_dn1_free(ldb, <db->cache.baseinfo); + ltdb_search_dn1_free(ldb, <db->cache.indexlist); + ltdb_search_dn1_free(ldb, <db->cache.subclasses); + ltdb_search_dn1_free(ldb, <db->cache.attributes); + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + memset(<db->cache, 0, sizeof(ltdb->cache)); +} + +/* + load the cache records +*/ +int ltdb_cache_load(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + double seq; + + ltdb_search_dn1_free(ldb, <db->cache.baseinfo); + + if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { + return -1; + } + + /* possibly initialise the baseinfo */ + if (!ltdb->cache.baseinfo.dn) { + if (ltdb_baseinfo_init(ldb) != 0) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { + return -1; + } + } + + /* if the current internal sequence number is the same as the one + in the database then assume the rest of the cache is OK */ + seq = ldb_msg_find_double(<db->cache.baseinfo, LTDB_SEQUENCE_NUMBER, 0); + if (seq == ltdb->sequence_number) { + return 0; + } + ltdb->sequence_number = seq; + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute)); + + ltdb_search_dn1_free(ldb, <db->cache.indexlist); + ltdb_search_dn1_free(ldb, <db->cache.subclasses); + ltdb_search_dn1_free(ldb, <db->cache.attributes); + + if (ltdb_search_dn1(ldb, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { + return -1; + } + + return 0; +} + + +/* + increase the sequence number to indicate a database change +*/ +int ltdb_increase_sequence_number(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + struct ldb_message msg; + struct ldb_message_element el; + struct ldb_val val; + char *s = NULL; + int ret; + + asprintf(&s, "%.0f", ltdb->sequence_number+1); + if (!s) { + errno = ENOMEM; + return -1; + } + + msg.num_elements = 1; + msg.elements = ⪙ + msg.dn = LTDB_BASEINFO; + el.name = LTDB_SEQUENCE_NUMBER; + el.values = &val; + el.num_values = 1; + el.flags = LDB_FLAG_MOD_REPLACE; + val.data = s; + val.length = strlen(s); + + ret = ltdb_modify_internal(ldb, &msg); + + free(s); + + if (ret == 0) { + ltdb->sequence_number += 1; + } + + return ret; +} + + +/* + return the attribute flags from the @ATTRIBUTES record + for the given attribute +*/ +int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) +{ + struct ltdb_private *ltdb = ldb->private_data; + const char *attrs; + const struct { + const char *name; + int value; + } names[] = { + { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, + { "INTEGER", LTDB_FLAG_INTEGER }, + { "WILDCARD", LTDB_FLAG_WILDCARD }, + { NULL, 0} + }; + size_t len; + int i, ret=0; + + if (ltdb->cache.last_attribute.name && + ldb_attr_cmp(ltdb->cache.last_attribute.name, attr_name) == 0) { + return ltdb->cache.last_attribute.flags; + } + + /* objectclass is a special default case */ + if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) { + ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE; + } + + attrs = ldb_msg_find_string(<db->cache.attributes, attr_name, NULL); + + if (!attrs) { + return ret; + } + + /* we avoid using strtok and friends due to their nasty + interface. This is a little trickier, but much nicer + from a C interface point of view */ + while ((len = strcspn(attrs, " ,")) > 0) { + for (i=0;names[i].name;i++) { + if (strncmp(names[i].name, attrs, len) == 0 && + names[i].name[len] == 0) { + ret |= names[i].value; + } + } + attrs += len; + attrs += strspn(attrs, " ,"); + } + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + + ltdb->cache.last_attribute.name = strdup(attr_name); + ltdb->cache.last_attribute.flags = ret; + + return ret; +} diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index a23fc2d525..c4243e9b40 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -63,12 +63,12 @@ static char *ldb_dn_key(const char *attr, const struct ldb_val *value) if (ldb_should_b64_encode(value)) { char *vstr = ldb_base64_encode(value->data, value->length); if (!vstr) return NULL; - asprintf(&ret, "@INDEX:%s::%s", attr, vstr); + asprintf(&ret, "%s:%s::%s", LTDB_INDEX, attr, vstr); free(vstr); return ret; } - asprintf(&ret, "@INDEX:%s:%s", attr, (char *)value->data); + asprintf(&ret, "%s:%s:%s", LTDB_INDEX, attr, (char *)value->data); return ret; } @@ -80,11 +80,11 @@ static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, { int i, j; for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, "@IDXATTR") == 0) { + if (ldb_attr_cmp(msg->elements[i].name, LTDB_IDXATTR) == 0) { const struct ldb_message_element *el = &msg->elements[i]; for (j=0;jnum_values;j++) { - if (strcmp((char *)el->values[j].data, attr) == 0) { + if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) { if (v_idx) { *v_idx = j; } @@ -114,7 +114,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* if the value is a wildcard then we can't do a match via indexing */ - if (ltdb_has_wildcard(&tree->u.simple.value)) { + if (ltdb_has_wildcard(ldb, tree->u.simple.attr, &tree->u.simple.value)) { return -1; } @@ -138,7 +138,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, for (i=0;iprivate_data; struct dn_list dn_list; int ret; - /* find the list of indexed fields */ - ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); - if (ret != 1) { + if (ltdb->cache.indexlist.num_elements == 0) { /* no index list? must do full search */ return -1; } - ret = ltdb_index_dn(ldb, tree, &index_list, &dn_list); - ltdb_search_dn1_free(ldb, &index_list); + ret = ltdb_index_dn(ldb, tree, <db->cache.indexlist, &dn_list); if (ret == 1) { /* we've got a candidate list - now filter by the full tree @@ -493,7 +490,7 @@ int ltdb_search_indexed(struct ldb_context *ldb, static int ltdb_index_add1_new(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_message_element *el, - const char *dn) + char *dn) { struct ldb_message_element *el2; @@ -504,7 +501,7 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, } msg->elements = el2; - msg->elements[msg->num_elements].name = "@IDX"; + msg->elements[msg->num_elements].name = LTDB_IDX; msg->elements[msg->num_elements].num_values = 0; msg->elements[msg->num_elements].values = malloc_p(struct ldb_val); if (!msg->elements[msg->num_elements].values) { @@ -527,7 +524,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_message_element *el, int idx, - const char *dn) + char *dn) { struct ldb_val *v2; @@ -549,7 +546,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, /* add an index entry for one message element */ -static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, +static int ltdb_index_add1(struct ldb_context *ldb, char *dn, struct ldb_message_element *el, int v_idx) { struct ldb_message msg; @@ -582,7 +579,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, free(dn_key); for (i=0;iprivate_data; int ret, i, j; - struct ldb_message index_list; - /* find the list of indexed fields */ - ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); - if (ret != 1) { - /* no indexed fields or an error */ - return ret; + if (ltdb->cache.indexlist.num_elements == 0) { + /* no indexed fields */ + return 0; } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); + ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, NULL); if (ret == -1) { continue; } for (j=0;jelements[i].num_values;j++) { ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i], j); if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); return -1; } } } - ltdb_search_dn1_free(ldb, &index_list); - return 0; } @@ -698,25 +690,23 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, */ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) { + struct ltdb_private *ltdb = ldb->private_data; int ret, i, j; - struct ldb_message index_list; /* find the list of indexed fields */ - ret = ltdb_search_dn1(ldb, "@INDEXLIST", &index_list); - if (ret != 1) { - /* no indexed fields or an error */ - return ret; + if (ltdb->cache.indexlist.num_elements == 0) { + /* no indexed fields */ + return 0; } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); + ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, NULL); if (ret == -1) { continue; } for (j=0;jelements[i].num_values;j++) { ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i], j); if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); return -1; } } @@ -731,7 +721,8 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) */ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { - if (strncmp(key.dptr, "DN=@INDEX:", 10) == 0) { + const char *dn = "DN=" LTDB_INDEX ":"; + if (strncmp(key.dptr, dn, strlen(dn)) == 0) { return tdb_delete(tdb, key); } return 0; @@ -756,7 +747,9 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return -1; } - msg.dn = key.dptr+3; + if (!msg.dn) { + msg.dn = key.dptr+3; + } ret = ltdb_index_add(ldb, &msg); @@ -773,6 +766,12 @@ int ltdb_reindex(struct ldb_context *ldb) struct ltdb_private *ltdb = ldb->private_data; int ret; + ltdb_cache_free(ldb); + + if (ltdb_cache_load(ldb) != 0) { + return -1; + } + /* first traverse the database deleting any @INDEX records */ ret = tdb_traverse(ltdb->tdb, delete_index, NULL); if (ret == -1) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 6f29726ee7..26e0eebfe7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -33,14 +33,162 @@ */ #include "includes.h" +#include "ldb/ldb_tdb/ldb_tdb.h" +/* + see if two ldb_val structures contain the same data as integers + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2) +{ + int i1, i2; + + i1 = strtol(v1->data, NULL, 0); + i2 = strtol(v2->data, NULL, 0); + + return i1 == i2; +} + +/* + see if two ldb_val structures contain the same data as case insensitive strings + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal_case_insensitive(const struct ldb_val *v1, + const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return 0; + } + if (strncasecmp(v1->data, v2->data, v1->length) == 0) { + return 1; + } + return 0; +} + +/* + see if two ldb_val structures contain the same data with wildcards + and case insensitive + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal_wildcard_ci(const struct ldb_val *v1, + const struct ldb_val *v2) +{ + char *s1, *s2; + int ret; + + if (!v1->data || !v2->data) { + return v1->data == v2->data; + } + + s1 = ldb_casefold(v1->data); + if (!s1) { + return -1; + } + + s2 = ldb_casefold(v2->data); + if (!s2) { + return -1; + } + + ret = fnmatch(s2, s1, 0); + + free(s1); + free(s2); + + if (ret == 0) { + return 1; + } + + return 0; +} + +/* + see if two ldb_val structures contain the same data with wildcards + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal_wildcard(const struct ldb_val *v1, + const struct ldb_val *v2, + int flags) +{ + if (flags & LTDB_FLAG_CASE_INSENSITIVE) { + return ldb_val_equal_wildcard_ci(v1, v2); + } + if (!v1->data || !v2->data) { + return v1->data == v2->data; + } + if (fnmatch(v2->data, v1->data, 0) == 0) { + return 1; + } + return 0; +} + + +/* + see if two objectclasses are considered equal. This handles + the subclass attributes + + v1 contains the in-database value, v2 contains the value + that the user gave + + return 1 for a match, 0 for a mis-match +*/ +static int ldb_val_equal_objectclass(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + struct ltdb_private *ltdb = ldb->private_data; + int i; + + if (ldb_val_equal_case_insensitive(v1, v2) == 1) { + return 1; + } + + for (i=0;icache.subclasses.num_elements;i++) { + struct ldb_message_element *el = <db->cache.subclasses.elements[i]; + if (ldb_attr_cmp(el->name, v2->data) == 0) { + int j; + for (j=0;jnum_values;j++) { + if (ldb_val_equal_objectclass(ldb, v1, &el->values[j])) { + return 1; + } + } + } + } + + return 0; +} + + /* see if two ldb_val structures contain the same data + + v1 contains the in-database value, v2 contains the value + that the user gave + return 1 for a match, 0 for a mis-match */ -int ldb_val_equal(const struct ldb_val *v1, const struct ldb_val *v2) +int ldb_val_equal(struct ldb_context *ldb, + const char *attr_name, + const struct ldb_val *v1, const struct ldb_val *v2) { + int flags = ltdb_attribute_flags(ldb, attr_name); + + if (flags & LTDB_FLAG_OBJECTCLASS) { + return ldb_val_equal_objectclass(ldb, v1, v2); + } + + if (flags & LTDB_FLAG_INTEGER) { + return ldb_val_equal_integer(v1, v2); + } + + if (flags & LTDB_FLAG_WILDCARD) { + return ldb_val_equal_wildcard(v1, v2, flags); + } + + if (flags & LTDB_FLAG_CASE_INSENSITIVE) { + return ldb_val_equal_case_insensitive(v1, v2); + } + if (v1->length != v2->length) return 0; if (v1->length == 0) return 1; @@ -66,7 +214,7 @@ static int scope_match(const char *dn, const char *base, enum ldb_scope scope) base_len = strlen(base); dn_len = strlen(dn); - if (strcmp(dn, base) == 0) { + if (ldb_dn_cmp(dn, base) == 0) { return 1; } @@ -79,7 +227,7 @@ static int scope_match(const char *dn, const char *base, enum ldb_scope scope) break; case LDB_SCOPE_ONELEVEL: - if (strcmp(dn + (dn_len - base_len), base) == 0 && + if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && dn[dn_len - base_len - 1] == ',' && strchr(dn, ',') == &dn[dn_len - base_len - 1]) { return 1; @@ -88,7 +236,7 @@ static int scope_match(const char *dn, const char *base, enum ldb_scope scope) case LDB_SCOPE_SUBTREE: default: - if (strcmp(dn + (dn_len - base_len), base) == 0 && + if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && dn[dn_len - base_len - 1] == ',') { return 1; } @@ -114,20 +262,21 @@ static int match_leaf(struct ldb_context *ldb, return 0; } - if (strcmp(tree->u.simple.attr, "dn") == 0) { + if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { if (strcmp(tree->u.simple.value.data, "*") == 0) { return 1; } - return strcmp(msg->dn, tree->u.simple.value.data) == 0; + return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; } for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, tree->u.simple.attr) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, tree->u.simple.attr) == 0) { if (strcmp(tree->u.simple.value.data, "*") == 0) { return 1; } for (j=0;jelements[i].num_values;j++) { - if (ldb_val_equal(&msg->elements[i].values[j], + if (ldb_val_equal(ldb, msg->elements[i].name, + &msg->elements[i].values[j], &tree->u.simple.value)) { return 1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 1196e561a2..3ded595259 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -36,7 +36,10 @@ #include "ldb/ldb_tdb/ldb_tdb.h" /* change this if the data format ever changes */ -#define LTDB_PACKING_FORMAT 0x26011966 +#define LTDB_PACKING_FORMAT 0x26011967 + +/* old packing formats */ +#define LTDB_PACKING_FORMAT_NODN 0x26011966 /* pack a ldb message into a linear buffer in a TDB_DATA @@ -53,10 +56,13 @@ int ltdb_pack_data(struct ldb_context *ctx, int i, j; size_t size; char *p; + size_t len; /* work out how big it needs to be */ size = 8; + size += 1 + strlen(message->dn); + for (i=0;inum_elements;i++) { if (message->elements[i].num_values == 0) { continue; @@ -79,9 +85,14 @@ int ltdb_pack_data(struct ldb_context *ctx, SIVAL(p, 0, LTDB_PACKING_FORMAT); SIVAL(p, 4, message->num_elements); p += 8; + + /* the dn needs to be packed so we can be case preserving + while hashing on a case folded dn */ + len = strlen(message->dn); + memcpy(p, message->dn, len+1); + p += len + 1; for (i=0;inum_elements;i++) { - size_t len; if (message->elements[i].num_values == 0) { continue; } @@ -133,33 +144,49 @@ int ltdb_unpack_data(struct ldb_context *ctx, char *p; unsigned int remaining; int i, j; + unsigned format; + size_t len; message->elements = NULL; p = data->dptr; - if (data->dsize < 4) { + if (data->dsize < 8) { errno = EIO; goto failed; } - if (IVAL(p, 0) != LTDB_PACKING_FORMAT) { - /* this is where we will cope with upgrading the - format if/when the format is ever changed */ + format = IVAL(p, 0); + message->num_elements = IVAL(p, 4); + p += 8; + + remaining = data->dsize - 8; + + switch (format) { + case LTDB_PACKING_FORMAT_NODN: + message->dn = NULL; + break; + + case LTDB_PACKING_FORMAT: + len = strnlen(p, remaining); + if (len == remaining) { + errno = EIO; + goto failed; + } + message->dn = p; + remaining -= len + 1; + p += len + 1; + break; + + default: errno = EIO; goto failed; } - message->num_elements = IVAL(p, 4); - p += 8; - if (message->num_elements == 0) { message->elements = NULL; return 0; } - /* basic sanity check */ - remaining = data->dsize - 8; - if (message->num_elements > remaining / 6) { errno = EIO; goto failed; @@ -174,12 +201,15 @@ int ltdb_unpack_data(struct ldb_context *ctx, } for (i=0;inum_elements;i++) { - size_t len; if (remaining < 10) { errno = EIO; goto failed; } len = strnlen(p, remaining-6); + if (len == remaining-6) { + errno = EIO; + goto failed; + } message->elements[i].flags = 0; message->elements[i].name = p; remaining -= len + 1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index fe84091303..7059030212 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -148,7 +148,7 @@ static int msg_add_all_elements(struct ldb_message *ret, */ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, const struct ldb_message *msg, - const char **attrs) + char * const *attrs) { struct ldb_message *ret; int i; @@ -205,11 +205,20 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, /* see if a ldb_val is a wildcard */ -int ltdb_has_wildcard(const struct ldb_val *val) +int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, + const struct ldb_val *val) { - if (val->length == 1 && ((char *)val->data)[0] == '*') { + int flags; + + if (strpbrk(val->data, "*?") == NULL) { + return 0; + } + + flags = ltdb_attribute_flags(ldb, attr_name); + if (flags & LTDB_FLAG_WILDCARD) { return 1; } + return 0; } @@ -220,12 +229,12 @@ int ltdb_has_wildcard(const struct ldb_val *val) void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { int i; - if (msg->dn) free(msg->dn); if (msg->private_data) free(msg->private_data); for (i=0;inum_elements;i++) { if (msg->elements[i].values) free(msg->elements[i].values); } if (msg->elements) free(msg->elements); + memset(msg, 0, sizeof(*msg)); } @@ -242,7 +251,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message TDB_DATA tdb_key, tdb_data; /* form the key */ - tdb_key = ltdb_key(dn); + tdb_key = ltdb_key(ldb, dn); if (!tdb_key.dptr) { return -1; } @@ -253,11 +262,6 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message return 0; } - msg->dn = strdup(dn); - if (!msg->dn) { - free(tdb_data.dptr); - return -1; - } msg->private_data = tdb_data.dptr; msg->num_elements = 0; msg->elements = NULL; @@ -268,6 +272,14 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message return -1; } + if (!msg->dn) { + msg->dn = strdup(dn); + } + if (!msg->dn) { + free(tdb_data.dptr); + return -1; + } + return 1; } @@ -276,7 +288,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message search the database for a single simple dn */ int ltdb_search_dn(struct ldb_context *ldb, char *dn, - const char *attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { int ret; struct ldb_message msg, *msg2; @@ -312,7 +324,7 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, return 0 on success, -1 on failure */ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, - const char *attrs[], + char * const attrs[], unsigned int *count, struct ldb_message ***res) { @@ -350,7 +362,7 @@ struct ltdb_search_info { struct ldb_parse_tree *tree; const char *base; enum ldb_scope scope; - const char **attrs; + char * const *attrs; struct ldb_message **msgs; int failures; int count; @@ -371,8 +383,6 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi return 0; } - msg.dn = key.dptr + 3; - /* unpack the record */ ret = ltdb_unpack_data(sinfo->ldb, &data, &msg); if (ret == -1) { @@ -380,6 +390,10 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi return 0; } + if (!msg.dn) { + msg.dn = key.dptr + 3; + } + /* see if it matches the given expression */ if (!ldb_message_match(sinfo->ldb, &msg, sinfo->tree, sinfo->base, sinfo->scope)) { @@ -425,7 +439,7 @@ static int ltdb_search_full(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - const char *attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; int ret; @@ -458,11 +472,15 @@ static int ltdb_search_full(struct ldb_context *ldb, */ int ltdb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { struct ldb_parse_tree *tree; int ret; + if (ltdb_cache_load(ldb) != 0) { + return -1; + } + *res = NULL; /* form a parse tree for the expression */ @@ -472,8 +490,8 @@ int ltdb_search(struct ldb_context *ldb, const char *base, } if (tree->operation == LDB_OP_SIMPLE && - strcmp(tree->u.simple.attr, "dn") == 0 && - !ltdb_has_wildcard(&tree->u.simple.value)) { + ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 && + !ltdb_has_wildcard(ldb, tree->u.simple.attr, &tree->u.simple.value)) { /* yay! its a nice simple one */ ret = ltdb_search_dn(ldb, tree->u.simple.value.data, attrs, res); } else { diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index ff0c0a53b7..eb2decfe31 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -38,24 +38,70 @@ /* form a TDB_DATA for a record key caller frees + + note that the key for a record can depend on whether the + dn refers to a case sensitive index record or not */ -struct TDB_DATA ltdb_key(const char *dn) +struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn) { TDB_DATA key; char *key_str = NULL; + char *dn_folded = NULL; + const char *prefix = LTDB_INDEX ":"; + const char *s; + int flags; + + /* + most DNs are case insensitive. The exception is index DNs for + case sensitive attributes + */ + if (strncmp(dn, prefix, strlen(prefix)) == 0 && + (s = strchr(dn+strlen(prefix), ':'))) { + char *attr_name, *attr_name_folded; + attr_name = strndup(dn+strlen(prefix), (s-(dn+strlen(prefix)))); + if (!attr_name) { + goto failed; + } + flags = ltdb_attribute_flags(ldb, attr_name); + + if (flags & LTDB_FLAG_CASE_INSENSITIVE) { + dn_folded = ldb_casefold(dn); + } else { + attr_name_folded = ldb_casefold(attr_name); + if (!attr_name_folded) { + goto failed; + } + asprintf(&dn_folded, "%s:%s:%s", + prefix, attr_name_folded, + s+1); + free(attr_name_folded); + } + free(attr_name); + } else { + dn_folded = ldb_casefold(dn); + } + + if (!dn_folded) { + goto failed; + } + + asprintf(&key_str, "DN=%s", dn_folded); + free(dn_folded); - asprintf(&key_str, "DN=%s", dn); if (!key_str) { - errno = ENOMEM; - key.dptr = NULL; - key.dsize = 0; - return key; + goto failed; } key.dptr = key_str; key.dsize = strlen(key_str)+1; return key; + +failed: + errno = ENOMEM; + key.dptr = NULL; + key.dsize = 0; + return key; } /* @@ -67,7 +113,7 @@ static int ltdb_lock(struct ldb_context *ldb) TDB_DATA key; int ret; - key = ltdb_key("LDBLOCK"); + key = ltdb_key(ldb, "LDBLOCK"); if (!key.dptr) { return -1; } @@ -87,7 +133,7 @@ static void ltdb_unlock(struct ldb_context *ldb) struct ltdb_private *ltdb = ldb->private_data; TDB_DATA key; - key = ltdb_key("LDBLOCK"); + key = ltdb_key(ldb, "LDBLOCK"); if (!key.dptr) { return; } @@ -97,6 +143,28 @@ static void ltdb_unlock(struct ldb_context *ldb) free(key.dptr); } + +/* + we've made a modification to a dn - possibly reindex and + update sequence number +*/ +static int ltdb_modified(struct ldb_context *ldb, const char *dn) +{ + int ret = 0; + + if (strcmp(dn, LTDB_INDEXLIST) == 0 || + strcmp(dn, LTDB_ATTRIBUTES) == 0) { + ret = ltdb_reindex(ldb); + } + + if (ret == 0 && + strcmp(dn, LTDB_BASEINFO) != 0) { + ret = ltdb_increase_sequence_number(ldb); + } + + return ret; +} + /* store a record into the db */ @@ -106,7 +174,7 @@ int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) TDB_DATA tdb_key, tdb_data; int ret; - tdb_key = ltdb_key(msg->dn); + tdb_key = ltdb_key(ldb, msg->dn); if (!tdb_key.dptr) { return -1; } @@ -145,15 +213,19 @@ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) if (ltdb_lock(ldb) != 0) { return -1; } + + if (ltdb_cache_load(ldb) != 0) { + ltdb_unlock(ldb); + return -1; + } ret = ltdb_store(ldb, msg, TDB_INSERT); - if (strcmp(msg->dn, "@INDEXLIST") == 0) { - ltdb_reindex(ldb); + if (ret == 0) { + ltdb_modified(ldb, msg->dn); } ltdb_unlock(ldb); - return ret; } @@ -168,7 +240,7 @@ int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) TDB_DATA tdb_key; int ret; - tdb_key = ltdb_key(dn); + tdb_key = ltdb_key(ldb, dn); if (!tdb_key.dptr) { return -1; } @@ -191,6 +263,11 @@ static int ltdb_delete(struct ldb_context *ldb, const char *dn) return -1; } + if (ltdb_cache_load(ldb) != 0) { + ltdb_unlock(ldb); + return -1; + } + /* in case any attribute of the message was indexed, we need to fetch the old record */ ret = ltdb_search_dn1(ldb, dn, &msg); @@ -210,8 +287,8 @@ static int ltdb_delete(struct ldb_context *ldb, const char *dn) ltdb_search_dn1_free(ldb, &msg); - if (strcmp(dn, "@INDEXLIST") == 0) { - ltdb_reindex(ldb); + if (ret == 0) { + ltdb_modified(ldb, dn); } ltdb_unlock(ldb); @@ -234,7 +311,7 @@ static int find_element(const struct ldb_message *msg, const char *name) { int i; for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, name) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { return i; } } @@ -301,7 +378,7 @@ static int msg_delete_attribute(struct ldb_message *msg, const char *name) } for (i=0;inum_elements;i++) { - if (strcmp(msg->elements[i].name, name) != 0) { + if (ldb_attr_cmp(msg->elements[i].name, name) != 0) { el2[count++] = msg->elements[i]; } else { if (msg->elements[i].values) free(msg->elements[i].values); @@ -320,7 +397,8 @@ static int msg_delete_attribute(struct ldb_message *msg, const char *name) return 0 on success, -1 on failure */ -static int msg_delete_element(struct ldb_message *msg, +static int msg_delete_element(struct ldb_context *ldb, + struct ldb_message *msg, const char *name, const struct ldb_val *val) { @@ -335,7 +413,7 @@ static int msg_delete_element(struct ldb_message *msg, el = &msg->elements[i]; for (i=0;inum_values;i++) { - if (ldb_val_equal(&el->values[i], val)) { + if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], sizeof(el->values[i])*el->num_values-(i+1)); @@ -348,43 +426,42 @@ static int msg_delete_element(struct ldb_message *msg, return -1; } + /* - modify a record + modify a record - internal interface yuck - this is O(n^2). Luckily n is usually small so we probably get away with it, but if we ever have really large attribute lists then we'll need to look at this again */ -static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) { struct ltdb_private *ltdb = ldb->private_data; TDB_DATA tdb_key, tdb_data; struct ldb_message msg2; int ret, i, j; - if (ltdb_lock(ldb) != 0) { - return -1; - } - - tdb_key = ltdb_key(msg->dn); + tdb_key = ltdb_key(ldb, msg->dn); if (!tdb_key.dptr) { - goto unlock_fail; + return -1; } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); if (!tdb_data.dptr) { free(tdb_key.dptr); - goto unlock_fail; + return -1; } ret = ltdb_unpack_data(ldb, &tdb_data, &msg2); if (ret == -1) { free(tdb_key.dptr); free(tdb_data.dptr); - goto unlock_fail; + return -1; } - msg2.dn = msg->dn; + if (!msg2.dn) { + msg2.dn = msg->dn; + } for (i=0;inum_elements;i++) { switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { @@ -425,9 +502,10 @@ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) break; } for (j=0;jelements[i].num_values;j++) { - if (msg_delete_element(&msg2, - msg->elements[i].name, - &msg->elements[i].values[j]) != 0) { + if (msg_delete_element(ldb, + &msg2, + msg->elements[i].name, + &msg->elements[i].values[j]) != 0) { goto failed; } } @@ -438,26 +516,43 @@ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) /* we've made all the mods - save the modified record back into the database */ ret = ltdb_store(ldb, &msg2, TDB_MODIFY); - if (strcmp(msg2.dn, "@INDEXLIST") == 0) { - ltdb_reindex(ldb); - } - free(tdb_key.dptr); free(tdb_data.dptr); ltdb_unpack_data_free(&msg2); - ltdb_unlock(ldb); - return ret; failed: free(tdb_key.dptr); free(tdb_data.dptr); ltdb_unpack_data_free(&msg2); + return -1; +} + +/* + modify a record +*/ +static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +{ + int ret; + + if (ltdb_lock(ldb) != 0) { + return -1; + } + + if (ltdb_cache_load(ldb) != 0) { + ltdb_unlock(ldb); + return -1; + } + + ret = ltdb_modify_internal(ldb, msg); + + if (ret == 0) { + ltdb_modified(ldb, msg->dn); + } -unlock_fail: ltdb_unlock(ldb); - - return -1; + + return ret; } /* @@ -467,6 +562,9 @@ static int ltdb_close(struct ldb_context *ldb) { struct ltdb_private *ltdb = ldb->private_data; int ret; + + ltdb_cache_free(ldb); + ret = tdb_close(ltdb->tdb); free(ltdb); free(ldb); @@ -538,7 +636,9 @@ struct ldb_context *ltdb_connect(const char *url, } ltdb->tdb = tdb; - + ltdb->sequence_number = 0; + + memset(<db->cache, 0, sizeof(ltdb->cache)); ldb = malloc_p(struct ldb_context); if (!ldb) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index efb0af1c9c..e87027db63 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -3,8 +3,44 @@ struct ltdb_private { TDB_CONTEXT *tdb; unsigned int connect_flags; + + /* a double is used for portability and ease of string + handling. It has plenty of digits of precision */ + double sequence_number; + + struct { + struct ldb_message baseinfo; + struct ldb_message indexlist; + struct ldb_message attributes; + struct ldb_message subclasses; + + struct { + char *name; + int flags; + } last_attribute; + } cache; }; +/* special record types */ +#define LTDB_INDEX "@INDEX" +#define LTDB_INDEXLIST "@INDEXLIST" +#define LTDB_IDX "@IDX" +#define LTDB_IDXATTR "@IDXATTR" +#define LTDB_BASEINFO "@BASEINFO" +#define LTDB_ATTRIBUTES "@ATTRIBUTES" +#define LTDB_SUBCLASSES "@SUBCLASSES" + +/* special attribute types */ +#define LTDB_SEQUENCE_NUMBER "sequenceNumber" +#define LTDB_OBJECTCLASS "objectClass" + +/* well known attribute flags */ +#define LTDB_FLAG_CASE_INSENSITIVE (1<<0) +#define LTDB_FLAG_INTEGER (1<<1) +#define LTDB_FLAG_WILDCARD (1<<2) +#define LTDB_FLAG_OBJECTCLASS (1<<3) + + #ifndef IVAL #define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) #endif diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif new file mode 100644 index 0000000000..bfa51b05fa --- /dev/null +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -0,0 +1,13 @@ +dn: @ATTRIBUTES +uid: CASE_INSENSITIVE WILDCARD +dn: CASE_INSENSITIVE + +dn: @SUBCLASSES +top: domain +top: person +domain: domainDNS +person: organizationalPerson +person: fooPerson +organizationalPerson: user +organizationalPerson: OpenLDAPperson +user: computer diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 41f5707e9c..79db49bb48 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -1,8 +1,8 @@ echo "Adding base elements" -bin/ldbadd < tests/test.ldif +bin/ldbadd tests/test.ldif echo "Modifying elements" -bin/ldbmodify < tests/test-modify.ldif +bin/ldbmodify tests/test-modify.ldif echo "Showing modified record" bin/ldbsearch '(uid=uham)' diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 07ed66d68a..eb95ed3267 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -102,7 +102,7 @@ static struct ldb_message *msg_find(struct ldb_message **msgs, int count, { int i; for (i=0;idn) == 0) { + if (ldb_dn_cmp(dn, msgs[i]->dn) == 0) { return msgs[i]; } } -- cgit From 3c117a484316f963114cbeb1ba83872cfa95d854 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 May 2004 10:39:32 +0000 Subject: r436: fixed indexing of objectclass with subclasses (This used to be commit 4d92e6f79f52ec0d580dfda2a91b4afc95838ff4) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 65 ++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index c4243e9b40..6c21ae2986 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -96,6 +96,7 @@ static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, return -1; } + /* return a list of dn's that might match a simple indexed search or */ @@ -168,6 +169,68 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, return 1; } +/* + return a list of dn's that might match a simple indexed search on + the special objectclass attribute + */ +static int ltdb_index_dn_objectclass(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + struct ltdb_private *ltdb = ldb->private_data; + int i; + int ret; + const char *target = tree->u.simple.value.data; + static int list_union(struct dn_list *, const struct dn_list *); + + list->count = 0; + list->dn = NULL; + + ret = ltdb_index_dn_simple(ldb, tree, index_list, list); + + for (i=0;icache.subclasses.num_elements;i++) { + struct ldb_message_element *el = <db->cache.subclasses.elements[i]; + if (ldb_attr_cmp(el->name, target) == 0) { + int j; + for (j=0;jnum_values;j++) { + struct ldb_parse_tree tree2; + struct dn_list list2; + tree2.operation = LDB_OP_SIMPLE; + tree2.u.simple.attr = LTDB_OBJECTCLASS; + tree2.u.simple.value = el->values[j]; + if (ltdb_index_dn_objectclass(ldb, &tree2, + index_list, &list2) == 1) { + if (list->count == 0) { + *list = list2; + ret = 1; + } else { + list_union(list, &list2); + dn_list_free(&list2); + } + } + } + } + } + + return ret; +} + +/* + return a list of dn's that might match a leaf indexed search + */ +static int ltdb_index_dn_leaf(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_message *index_list, + struct dn_list *list) +{ + if (ldb_attr_cmp(tree->u.simple.attr, LTDB_OBJECTCLASS) == 0) { + return ltdb_index_dn_objectclass(ldb, tree, index_list, list); + } + return ltdb_index_dn_simple(ldb, tree, index_list, list); +} + + /* list intersection list = list & list2 @@ -393,7 +456,7 @@ static int ltdb_index_dn(struct ldb_context *ldb, switch (tree->operation) { case LDB_OP_SIMPLE: - ret = ltdb_index_dn_simple(ldb, tree, index_list, list); + ret = ltdb_index_dn_leaf(ldb, tree, index_list, list); break; case LDB_OP_AND: -- cgit From 29bc1f5c605b53635eea805cdd3ca6b2873bc792 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 May 2004 14:04:33 +0000 Subject: r437: fixed handling of a corner case with multi-valued indexing (This used to be commit b38612185657512419c4b3dc806cf1183e0db0cb) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 8 ++++++++ source4/lib/ldb/ldb_tdb/ldb_search.c | 6 ++++++ 2 files changed, 14 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 6c21ae2986..76e17cdfd5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -590,6 +590,14 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, char *dn) { struct ldb_val *v2; + int i; + + /* for multi-valued attributes we can end up with repeats */ + for (i=0;ielements[idx].num_values;i++) { + if (strcmp(dn, msg->elements[idx].values[i].data) == 0) { + return 0; + } + } v2 = realloc_p(msg->elements[idx].values, struct ldb_val, diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 7059030212..1dce8f83a2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -204,12 +204,18 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, /* see if a ldb_val is a wildcard + return 1 if yes, 0 if no */ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, const struct ldb_val *val) { int flags; + /* all attribute types recognise the "*" wildcard */ + if (val->length == 1 && strncmp((char *)val->data, "*", 1) == 0) { + return 1; + } + if (strpbrk(val->data, "*?") == NULL) { return 0; } -- cgit From 585d87a9590ecf64681700d70c37e5276ee8514a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 May 2004 05:16:15 +0000 Subject: r442: fixed some uninitialised variables pointed out by gcc -O3 (This used to be commit ff31cfb941b77e99e648011a6b7639b2a5923a6a) --- source4/lib/ldb/common/util.c | 3 +-- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/ldb/tools/ldbmodify.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index e1a7ada1c6..534d07c1df 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -73,14 +73,13 @@ int list_find(const void *needle, max_i = nmemb-1; while (min_i < max_i) { - size_t test_t; int r; test_i = (min_i + max_i) / 2; r = comp_fn(needle, *(void * const *)(base_p + (size * test_i))); if (r == 0) { /* scan back for first element */ - while (test_t > 0 && + while (test_i > 0 && comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) { test_i--; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 76e17cdfd5..987ee017b6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -452,7 +452,7 @@ static int ltdb_index_dn(struct ldb_context *ldb, const struct ldb_message *index_list, struct dn_list *list) { - int ret; + int ret = -1; switch (tree->operation) { case LDB_OP_SIMPLE: diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index ac32f90c3b..bc29369a5c 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -52,7 +52,7 @@ static void usage(void) static int process_file(struct ldb_context *ldb, FILE *f) { struct ldb_ldif *ldif; - int ret, count = 0; + int ret = -1, count = 0; while ((ldif = ldif_read_file(f))) { switch (ldif->changetype) { -- cgit From 78aa8f181469b24f7ad836c2b7b8629c33f9f6b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 May 2004 10:06:45 +0000 Subject: r444: - added the beginnings of a ldb test suite and benchmark - updated the test slapd config to use bdb and indexing (This used to be commit 7ad0858c060ee212a33434dc4be75e7a0cd1a0e3) --- source4/lib/ldb/Makefile.ldb | 5 +- source4/lib/ldb/include/includes.h | 2 + source4/lib/ldb/tests/init_slapd.sh | 2 +- source4/lib/ldb/tests/slapd.conf | 12 +- source4/lib/ldb/tests/start_slapd.sh | 3 +- source4/lib/ldb/tests/test-index.ldif | 3 +- source4/lib/ldb/tests/test.ldif | 3 + source4/lib/ldb/tools/ldbtest.c | 247 ++++++++++++++++++++++++++++++++++ 8 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 source4/lib/ldb/tools/ldbtest.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index ba8c040f9c..dfd429ecc8 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -11,7 +11,7 @@ endif TDBDIR=../tdb -CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +CFLAGS=-Wall -O3 -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o @@ -59,6 +59,9 @@ bin/ldbmodify: tools/ldbmodify.o $(LIBS) bin/ldbedit: tools/ldbedit.o $(LIBS) $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) +bin/ldbtest: tools/ldbtest.o $(LIBS) + $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) + clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 485d7157b8..7ee6876f48 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "ldb.h" #include "ldb_parse.h" diff --git a/source4/lib/ldb/tests/init_slapd.sh b/source4/lib/ldb/tests/init_slapd.sh index 94dca71791..67eecb031c 100755 --- a/source4/lib/ldb/tests/init_slapd.sh +++ b/source4/lib/ldb/tests/init_slapd.sh @@ -1,6 +1,6 @@ #!/bin/sh -export PATH=/home/tridge/samba/openldap/prefix/sbin:/home/tridge/samba/openldap/prefix/bin:/home/tridge/samba/openldap/prefix/libexec:$PATH +export PATH=/usr/sbin:$PATH rm -rf tests/tmp/db mkdir -p tests/tmp/db diff --git a/source4/lib/ldb/tests/slapd.conf b/source4/lib/ldb/tests/slapd.conf index cb71eb3963..10d15b541c 100644 --- a/source4/lib/ldb/tests/slapd.conf +++ b/source4/lib/ldb/tests/slapd.conf @@ -14,12 +14,14 @@ access to * by * write allow update_anon bind_anon_dn +modulepath /usr/lib/ldap +moduleload back_bdb + defaultsearchbase "o=University of Michigan,c=US" -database ldbm +backend bdb +database bdb suffix "o=University of Michigan,c=US" directory tests/tmp/db - -index objectClass eq -index drink eq -index title eq +index objectClass eq +index uid eq diff --git a/source4/lib/ldb/tests/start_slapd.sh b/source4/lib/ldb/tests/start_slapd.sh index d000eec9a4..d03a0fca32 100755 --- a/source4/lib/ldb/tests/start_slapd.sh +++ b/source4/lib/ldb/tests/start_slapd.sh @@ -1,8 +1,7 @@ #!/bin/sh -export PATH=/home/tridge/samba/openldap/prefix/sbin:/home/tridge/samba/openldap/prefix/bin:/home/tridge/samba/openldap/prefix/libexec:$PATH +export PATH=/usr/sbin:$PATH mkdir -p tests/tmp/db slapd -f tests/slapd.conf -h "`tests/ldapi_url.sh`" $* - diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index fe9c79d1a2..0f1268c44f 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -1,4 +1,3 @@ dn: @INDEXLIST -@IDXATTR: drink -@IDXATTR: title +@IDXATTR: uid @IDXATTR: objectclass diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif index 72d52a25f8..2d7e1f95de 100644 --- a/source4/lib/ldb/tests/test.ldif +++ b/source4/lib/ldb/tests/test.ldif @@ -414,3 +414,6 @@ pager: +1 313 555 2844 facsimiletelephonenumber: +1 313 555 9700 telephonenumber: +1 313 555 5331 +dn: ou=Ldb Test,ou=People,o=University of Michigan,c=US +objectclass: organizationalUnit +ou: Ldb Test diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c new file mode 100644 index 0000000000..b7d1d22db8 --- /dev/null +++ b/source4/lib/ldb/tools/ldbtest.c @@ -0,0 +1,247 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbtest + * + * Description: utility to test ldb + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +static struct timeval tp1,tp2; + +static void start_timer() +{ + gettimeofday(&tp1,NULL); +} + +static double end_timer() +{ + gettimeofday(&tp2,NULL); + return((tp2.tv_sec - tp1.tv_sec) + + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); +} + +static void add_records(struct ldb_context *ldb, + const char *basedn, + int count) +{ + struct ldb_message msg; + int i; + + for (i=0;i= nrecords && ret > 0) { + printf("Found %s !? - %d\n", expr, ret); + exit(1); + } + + if (ret > 0) { + ldb_search_free(ldb, res); + } + + printf("testing uid %d/%d - %d \r", i, uid, ret); + fflush(stdout); + + free(expr); + } + + printf("\n"); +} + +static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) +{ + printf("Adding %d records\n", nrecords); + + add_records(ldb, "ou=Ldb Test,ou=People,o=University of Michigan,c=US", + nrecords); + + printf("Starting search on uid\n"); + + start_timer(); + + search_uid(ldb, nrecords, nsearches); + + printf("uid search took %.2f seconds\n", end_timer()); +} + + +static void usage(void) +{ + printf("Usage: ldbtest \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -r nrecords database size to use\n"); + printf(" -s nsearches number of searches to do\n"); + printf("\n"); + printf("tests ldb API\n\n"); + exit(1); +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + const char *ldb_url; + int opt; + int nrecords = 5000; + int nsearches = 2000; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:r:s:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'r': + nrecords = atoi(optarg); + break; + + case 's': + nsearches = atoi(optarg); + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + srandom(1); + + start_test(ldb, nrecords, nsearches); + + ldb_close(ldb); + + return 0; +} -- cgit From cd16ca987675d70526010072dfe8552a1cbf87d9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 May 2004 04:24:30 +0000 Subject: r452: move from first-fit to best-fit in tdb record allocation. For a situation where we are continually increasing the size of a record (such as ldb index records) this reduces the resulting tdb size by a factor of over 100x, due to reductions in fragmentation. It appears to have no noticable effect on the speed in other cases. (This used to be commit b61d7f8bbc0c01d648ce204ffb6ea657e0b04c03) --- source4/lib/tdb/tdb.c | 145 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 48 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c index 47ba2cb52c..c8ac7babad 100644 --- a/source4/lib/tdb/tdb.c +++ b/source4/lib/tdb/tdb.c @@ -530,7 +530,7 @@ static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) return 0; } - printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); @@ -609,7 +609,8 @@ int tdb_printfreelist(TDB_CONTEXT *tdb) return -1; } - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len ); + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); total_free += rec.rec_len; /* move to the next record */ @@ -850,6 +851,66 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) return -1; } + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + */ +static tdb_off tdb_allocate_ofs(TDB_CONTEXT *tdb, tdb_len length, tdb_off rec_ptr, + struct list_struct *rec, tdb_off last_ptr) +{ + struct list_struct newrec; + tdb_off newrec_ptr; + + memset(&newrec, '\0', sizeof(newrec)); + + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else { + newrec_ptr = 0; + } + + /* Remove allocated record from the free list */ + if (ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { + return 0; + } + } + + /* all done - return the new record offset */ + return rec_ptr; +} + /* allocate some space from the free list. The offset returned points to a unconnected list_struct within the database with room for at least length bytes of total data @@ -860,9 +921,10 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, struct list_struct *rec) { tdb_off rec_ptr, last_ptr, newrec_ptr; - struct list_struct newrec; - - memset(&newrec, '\0', sizeof(newrec)); + struct { + tdb_off rec_ptr, last_ptr; + tdb_len rec_len; + } bestfit; if (tdb_lock(tdb, -1, F_WRLCK) == -1) return 0; @@ -877,59 +939,46 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) goto fail; - /* keep looking until we find a freelist record big enough */ + bestfit.rec_ptr = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ while (rec_ptr) { - if (rec_free_read(tdb, rec_ptr, rec) == -1) + if (rec_free_read(tdb, rec_ptr, rec) == -1) { goto fail; + } if (rec->rec_len >= length) { - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else - newrec_ptr = 0; - - /* Remove allocated record from the free list */ - if (ofs_write(tdb, last_ptr, &rec->next) == -1) - goto fail; - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (rec_write(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) - goto fail; - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) - goto fail; + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + /* consider a fit to be good enough if we aren't wasting more than half the space */ + if (bestfit.rec_len < 2*length) { + break; + } } - - /* all done - return the new record offset */ - tdb_unlock(tdb, -1, F_WRLCK); - return rec_ptr; } + /* move to the next record */ last_ptr = rec_ptr; rec_ptr = rec->next; } + + if (bestfit.rec_ptr != 0) { + if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + /* we didn't find enough space. See if we can expand the database and if we can then try again */ if (tdb_expand(tdb, length + sizeof(*rec)) == 0) -- cgit From 1cc8db013226fada2249e4e210a7b020e8e31564 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 May 2004 04:25:48 +0000 Subject: r453: added a comment about indexing on objectclass (its usually a bad idea) (This used to be commit f88760c3cc81324d3d339702b411603139af6224) --- source4/lib/ldb/tests/test-index.ldif | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index 0f1268c44f..6b2e921ebd 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -1,3 +1,6 @@ dn: @INDEXLIST @IDXATTR: uid -@IDXATTR: objectclass +# it is much better not to index on objectclass if nearly +# all the records are the same class (the index is expensive +# to maintain, and doesn't really gain anything) +# @IDXATTR: objectclass -- cgit From b96695ca23f8d1d95ed2e038ea66e6a0580356c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 May 2004 09:34:18 +0000 Subject: r454: allow a non-URL form of a filename to be used in ldb_connect(). This makes it a little easier to work with the ldb tools (This used to be commit 03df31cef025b2087531579437d6bae1ec36e82f) --- source4/lib/ldb/common/ldb.c | 3 ++- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index f61ddecdc7..ac77f306e9 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -48,7 +48,8 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, const char *options[]) { - if (strncmp(url, "tdb:", 4) == 0) { + if (strncmp(url, "tdb:", 4) == 0 || + strchr(url, ':') == NULL) { return ltdb_connect(url, flags, options); } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index eb2decfe31..92b88e4fb5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -607,13 +607,16 @@ struct ldb_context *ltdb_connect(const char *url, struct ldb_context *ldb; /* parse the url */ - if (strncmp(url, "tdb://", 6) != 0) { - errno = EINVAL; - return NULL; + if (strchr(url, ':')) { + if (strncmp(url, "tdb://", 6) != 0) { + errno = EINVAL; + return NULL; + } + path = url+6; + } else { + path = url; } - path = url+6; - tdb_flags = TDB_DEFAULT; if (flags & LDB_FLG_RDONLY) { -- cgit From 208e09747c242ab5bd59a658033db49efa8d8696 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 May 2004 14:51:26 +0000 Subject: r456: - added -i option to ldbsearch - fixed sorting bug in ldb index handing (This used to be commit cdd48e2b9b3ca6be5503eec401e09db162408ac8) --- source4/lib/ldb/common/ldb.c | 2 +- source4/lib/ldb/common/util.c | 7 ++- source4/lib/ldb/include/ldb.h | 4 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 13 ++++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 12 +++--- source4/lib/ldb/tools/ldbsearch.c | 84 ++++++++++++++++++++++-------------- 7 files changed, 75 insertions(+), 49 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index ac77f306e9..ce21d1d9e2 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -81,7 +81,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const attrs[], struct ldb_message ***res) + const char * const *attrs, struct ldb_message ***res) { return ldb->ops->search(ldb, base, scope, expression, attrs, res); } diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index 534d07c1df..22bbc8334e 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -85,10 +85,13 @@ int list_find(const void *needle, } return test_i; } - if (r == -1) { + if (r < 0) { + if (test_i == 0) { + return -1; + } max_i = test_i - 1; } - if (r == 1) { + if (r > 0) { min_i = test_i + 1; } } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 215671c98a..c0521ecffa 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -124,7 +124,7 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_backend_ops { int (*close)(struct ldb_context *); int (*search)(struct ldb_context *, const char *, enum ldb_scope, - const char *, char * const [], struct ldb_message ***); + const char *, const char * const [], struct ldb_message ***); int (*search_free)(struct ldb_context *, struct ldb_message **); int (*add_record)(struct ldb_context *, const struct ldb_message *); int (*modify_record)(struct ldb_context *, const struct ldb_message *); @@ -174,7 +174,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const attrs[], struct ldb_message ***res); + const char * const *attrs, struct ldb_message ***res); /* free a set of messages returned by ldb_search diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 8723beeadc..26c29122ad 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -207,7 +207,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg, */ static int lldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const *attrs, struct ldb_message ***res) + const char * const *attrs, struct ldb_message ***res) { struct lldb_private *lldb = ldb->private_data; int count, msg_count; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 987ee017b6..d250bc10be 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -96,6 +96,11 @@ static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, return -1; } +/* used in sorting dn lists */ +static int list_cmp(const char **s1, const char **s2) +{ + return strcmp(*s1, *s2); +} /* return a list of dn's that might match a simple indexed search or @@ -164,7 +169,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, ltdb_search_dn1_free(ldb, &msg); - qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) strcmp); + qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp); return 1; } @@ -309,7 +314,7 @@ static int list_union(struct dn_list *list, const struct dn_list *list2) } if (list->count != count) { - qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)strcmp); + qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp); } return 0; @@ -483,7 +488,7 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree const char *base, enum ldb_scope scope, const struct dn_list *dn_list, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { int i; unsigned int count = 0; @@ -523,7 +528,7 @@ int ltdb_search_indexed(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; struct dn_list dn_list; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 1dce8f83a2..cce865e052 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -148,7 +148,7 @@ static int msg_add_all_elements(struct ldb_message *ret, */ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, const struct ldb_message *msg, - char * const *attrs) + const char * const *attrs) { struct ldb_message *ret; int i; @@ -294,7 +294,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message search the database for a single simple dn */ int ltdb_search_dn(struct ldb_context *ldb, char *dn, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { int ret; struct ldb_message msg, *msg2; @@ -330,7 +330,7 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, return 0 on success, -1 on failure */ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, - char * const attrs[], + const char * const attrs[], unsigned int *count, struct ldb_message ***res) { @@ -368,7 +368,7 @@ struct ltdb_search_info { struct ldb_parse_tree *tree; const char *base; enum ldb_scope scope; - char * const *attrs; + const char * const *attrs; struct ldb_message **msgs; int failures; int count; @@ -445,7 +445,7 @@ static int ltdb_search_full(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; int ret; @@ -478,7 +478,7 @@ static int ltdb_search_full(struct ldb_context *ldb, */ int ltdb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ldb_parse_tree *tree; int ret; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 45412f6104..e8275e87c1 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -41,24 +41,59 @@ static void usage(void) printf(" -H ldb_url choose the database (or $LDB_URL)\n"); printf(" -s base|sub|one choose search scope\n"); printf(" -b basedn choose baseDN\n"); + printf(" -i read search expressions from stdin\n"); exit(1); } +static void do_search(struct ldb_context *ldb, + const char *basedn, + int scope, + const char *expression, + const char * const *attrs) +{ + int ret, i; + struct ldb_message **msgs; + + ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); + if (ret == -1) { + printf("search failed - %s\n", ldb_errstring(ldb)); + return; + } + + printf("# returned %d records\n", ret); + + for (i=0;i 0) { + ret = ldb_search_free(ldb, msgs); + if (ret == -1) { + fprintf(stderr, "search_free failed\n"); + exit(1); + } + } +} + int main(int argc, char * const argv[]) { struct ldb_context *ldb; - struct ldb_message **msgs; - int ret, i; - const char *expression; - char * const *attrs = NULL; + const char * const * attrs = NULL; const char *ldb_url; const char *basedn = NULL; int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; + int interactive = 0; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "b:H:s:h")) != EOF) { + while ((opt = getopt(argc, argv, "b:H:s:hi")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -78,6 +113,10 @@ static void usage(void) } break; + case 'i': + interactive = 1; + break; + case 'h': default: usage(); @@ -93,7 +132,7 @@ static void usage(void) argc -= optind; argv += optind; - if (argc < 1) { + if (argc < 1 && !interactive) { usage(); exit(1); } @@ -102,40 +141,19 @@ static void usage(void) attrs = argv+1; } - expression = argv[0]; - ldb = ldb_connect(ldb_url, 0, NULL); - if (!ldb) { perror("ldb_connect"); exit(1); } - ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); - - if (ret == -1) { - printf("search failed - %s\n", ldb_errstring(ldb)); - exit(1); - } - - printf("# returned %d records\n", ret); - - for (i=0;i 0) { - ret = ldb_search_free(ldb, msgs); - if (ret == -1) { - fprintf(stderr, "search_free failed\n"); - exit(1); + if (interactive) { + char line[1024]; + while (fgets(line, sizeof(line), stdin)) { + do_search(ldb, basedn, scope, line, attrs); } + } else { + do_search(ldb, basedn, scope, argv[0], attrs); } ldb_close(ldb); -- cgit From d6f20f8e92bbbf7b8ac5ace83aae15bad8ef8bba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 May 2004 05:58:22 +0000 Subject: r462: added an explanation about the rather complex ltdb_key() function (This used to be commit 894e44022d16d9ff43f421fb15495845710000ab) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 92b88e4fb5..c674f0c27e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -54,6 +54,15 @@ struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn) /* most DNs are case insensitive. The exception is index DNs for case sensitive attributes + + there are 3 cases dealt with in this code: + + 1) if the dn doesn't start with @INDEX: then uppercase whole dn + 2) if the dn starts with @INDEX:attr and 'attr' is a case insensitive + attribute then uppercase whole dn + 3) if the dn starts with @INDEX:attr and 'attr' is a case sensitive + attribute then uppercase up to the value of the attribute, but + not the value itself */ if (strncmp(dn, prefix, strlen(prefix)) == 0 && (s = strchr(dn+strlen(prefix), ':'))) { -- cgit From 73744d1ed6ba3b2d003eb029b9e9a0296ce895e6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 May 2004 05:58:52 +0000 Subject: r463: build ldb with debugging when standalone (This used to be commit 77269e7ad6f569585d5fad37ee63169c4eee3f01) --- source4/lib/ldb/Makefile.ldb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index dfd429ecc8..d05ad546a2 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -11,7 +11,7 @@ endif TDBDIR=../tdb -CFLAGS=-Wall -O3 -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o -- cgit From 6a8355a6282563e3198c05dd6eb82107e449682c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 4 May 2004 13:18:29 +0000 Subject: r467: hopefully get the buildfarm compiling fine now... metze (This used to be commit d15f0e18bb43608c611cfe78fc79db9ee10e1eb2) --- source4/lib/registry/tools/gregedit.c | 6 ++++-- source4/lib/registry/tools/regdiff.c | 4 ++-- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 6 +++--- source4/lib/registry/tools/regtree.c | 5 +++-- 5 files changed, 13 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 10e5f45468..4bbde9a37d 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -723,10 +723,12 @@ GtkWidget* create_savefilewin (void) return savefilewin; } -int main (int argc, char *argv[]) + int main(int argc, char *argv[]) { poptContext pc; - const char *backend = NULL, *credentials = NULL, *location; + const char *backend = NULL; + const char *credentials = NULL; + const char *location; int opt; struct poptOption long_options[] = { POPT_AUTOHELP diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 305a7a1e46..c3633ef0af 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -59,7 +59,7 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(newkey, i, &v1)); i++) { error2 = reg_key_get_value_by_name(oldkey, reg_val_name(v1), &v2); - if ((W_ERROR_IS_OK(error2) && reg_val_size(v2) != reg_val_size(v1) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1))) + if (((W_ERROR_IS_OK(error2) && reg_val_size(v2) != reg_val_size(v1)) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1))) || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(v1), str_regtype(reg_val_type(v1)), reg_val_data_string(v1)); } @@ -91,7 +91,7 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } } -int main (int argc, char **argv) + int main(int argc, char **argv) { int opt; poptContext pc; diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index e632edaa49..d4b036afe9 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -752,7 +752,7 @@ int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) return modified; } -int main (int argc, char **argv) + int main(int argc, char **argv) { int opt; poptContext pc; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 8ee2a65d06..b78f4256f0 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -199,9 +199,9 @@ REG_KEY *process_cmd(REG_KEY *k, char *line) int main (int argc, char **argv) { int opt; - char *backend = "dir"; - char *credentials = NULL; - REG_KEY *curkey = NULL;; + const char *backend = "dir"; + const char *credentials = NULL; + REG_KEY *curkey = NULL; poptContext pc; WERROR error; REG_HANDLE *h; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 94018bdc5c..4d0d4b2909 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -58,10 +58,11 @@ void print_tree(int l, REG_KEY *p, int fullpath, int novals) } } -int main (int argc, char **argv) + int main(int argc, char **argv) { int opt; - char *backend = "dir", *credentials = NULL; + const char *backend = "dir"; + const char *credentials = NULL; poptContext pc; REG_KEY *root; REG_HANDLE *h; -- cgit From 2c367686fcff32a45c0af84225a8b47d95149e18 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 May 2004 13:41:08 +0000 Subject: r468: fixed timegm() on broken systems (This used to be commit a3d639d04ff25deabd299ea24917adde9192ed38) --- source4/lib/replace.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index cde9ce7a1b..d0de601079 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -437,6 +437,7 @@ char *rep_inet_ntoa(struct in_addr ip) { struct tm tm2, tm3; time_t t; + static int zone = -1; tm2 = *tm; @@ -445,7 +446,10 @@ char *rep_inet_ntoa(struct in_addr ip) tm2 = *tm; tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); - t -= TimeDiff(); + if (zone == -1) { + zone = get_time_zone(); + } + t -= zone; return t; } -- cgit From af66c31e44bcb052f35f9b1de8e997149fddac89 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 May 2004 22:53:47 +0000 Subject: r476: i forgot the argument to get_time_zone() (This used to be commit 34ff18839c97dbb77c76097b4484ebec398da192) --- source4/lib/replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index d0de601079..189c5bc04d 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -447,7 +447,7 @@ char *rep_inet_ntoa(struct in_addr ip) tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); if (zone == -1) { - zone = get_time_zone(); + zone = get_time_zone(t); } t -= zone; -- cgit From 232bc1503fc0e3f85b4711f077d2566dc0f0c823 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 May 2004 04:27:29 +0000 Subject: r490: - expanded the test suite to test modify and delete operations - made yet another attempt to make ldb const clean. - "make test" now runs both the tdb and ldap backend tests, and run the ldbtest utility with and without indexing - added prototypes in ldb.h for ldb_msg_*() public functions (This used to be commit 01e87406768cb5a98ac8530a2f361a4987a36cd3) --- source4/lib/ldb/Makefile.ldb | 13 +++-- source4/lib/ldb/common/ldb.c | 2 +- source4/lib/ldb/common/ldb_ldif.c | 5 +- source4/lib/ldb/include/ldb.h | 45 +++++++++++++++- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_cache.c | 36 ++++++++++--- source4/lib/ldb/ldb_tdb/ldb_index.c | 22 ++++++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 12 ++--- source4/lib/ldb/tests/init_slapd.sh | 8 ++- source4/lib/ldb/tests/test-generic.sh | 15 ++++-- source4/lib/ldb/tests/test-tdb.sh | 1 + source4/lib/ldb/tools/ldbsearch.c | 4 +- source4/lib/ldb/tools/ldbtest.c | 98 ++++++++++++++++++++++++++++++++--- 13 files changed, 222 insertions(+), 41 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index d05ad546a2..0b8fdfe28f 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -11,7 +11,7 @@ endif TDBDIR=../tdb -CFLAGS=-Wall -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o @@ -28,7 +28,7 @@ OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbtest LIBS = $(LDB_LIB)($(OBJS)) @@ -71,5 +71,12 @@ proto: etags: etags */*.[ch] -test: +test-tdb: + @echo "STARTING TDB BACKEND TEST" tests/test-tdb.sh + +test-ldap: + @echo "STARTING LDAP BACKEND TEST" + tests/test-ldap.sh + +test: test-tdb test-ldap diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index ce21d1d9e2..86d0dd9e9b 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -81,7 +81,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) + char * const *attrs, struct ldb_message ***res) { return ldb->ops->search(ldb, base, scope, expression, attrs, res); } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 1ca585ca80..ef782e90e3 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -343,7 +343,7 @@ static char *next_chunk(int (*fgetc_fn)(void *), void *private_data) /* simple ldif attribute parser */ -static int next_attr(char **s, char **attr, struct ldb_val *value) +static int next_attr(char **s, const char **attr, struct ldb_val *value) { char *p; int base64_encoded = 0; @@ -454,7 +454,8 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) { struct ldb_ldif *ldif; struct ldb_message *msg; - char *attr=NULL, *chunk=NULL, *s; + const char *attr=NULL; + char *chunk=NULL, *s; struct ldb_val value; unsigned flags = 0; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index c0521ecffa..cee72c3c21 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -124,7 +124,7 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_backend_ops { int (*close)(struct ldb_context *); int (*search)(struct ldb_context *, const char *, enum ldb_scope, - const char *, const char * const [], struct ldb_message ***); + const char *, char * const [], struct ldb_message ***); int (*search_free)(struct ldb_context *, struct ldb_message **); int (*add_record)(struct ldb_context *, const struct ldb_message *); int (*modify_record)(struct ldb_context *, const struct ldb_message *); @@ -174,7 +174,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res); + char * const *attrs, struct ldb_message ***res); /* free a set of messages returned by ldb_search @@ -223,3 +223,44 @@ struct ldb_ldif *ldif_read_file(FILE *f); struct ldb_ldif *ldif_read_string(const char *s); int ldif_write_file(FILE *f, const struct ldb_ldif *msg); + +/* useful functions for ldb_message structure manipulation */ + +/* find an element within an message */ +struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, + const char *attr_name); + +/* compare two ldb_val values - return 0 on match */ +int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2); + +/* find a value within an ldb_message_element */ +struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, + struct ldb_val *val); + +/* add a new empty element to a ldb_message */ +int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags); + +/* add a element to a ldb_message */ +int ldb_msg_add(struct ldb_message *msg, + const struct ldb_message_element *el, + int flags); + +/* compare two message elements - return 0 on match */ +int ldb_msg_element_compare(struct ldb_message_element *el1, + struct ldb_message_element *el2); + +/* find elements in a message and convert to a specific type, with + a give default value if not found. Assumes that elements are + single valued */ +int ldb_msg_find_int(const struct ldb_message *msg, + const char *attr_name, + int default_value); +unsigned int ldb_msg_find_uint(const struct ldb_message *msg, + const char *attr_name, + int default_value); +double ldb_msg_find_double(const struct ldb_message *msg, + const char *attr_name, + double default_value); +const char *ldb_msg_find_string(const struct ldb_message *msg, + const char *attr_name, + const char *default_value); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 26c29122ad..8723beeadc 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -207,7 +207,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg, */ static int lldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) + char * const *attrs, struct ldb_message ***res) { struct lldb_private *lldb = ldb->private_data; int count, msg_count; diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 5d61fd35b3..3c6ce63c2b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -44,20 +44,42 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) struct ldb_message msg; struct ldb_message_element el; struct ldb_val val; + int ret; ltdb->sequence_number = 0; msg.num_elements = 1; msg.elements = ⪙ - msg.dn = LTDB_BASEINFO; - el.name = LTDB_SEQUENCE_NUMBER; + msg.dn = strdup(LTDB_BASEINFO); + if (!msg.dn) { + errno = ENOMEM; + return -1; + } + el.name = strdup(LTDB_SEQUENCE_NUMBER); + if (!el.name) { + free(msg.dn); + errno = ENOMEM; + return -1; + } el.values = &val; el.num_values = 1; el.flags = 0; - val.data = "0"; + val.data = strdup("0"); + if (!val.data) { + free(el.name); + free(msg.dn); + errno = ENOMEM; + return -1; + } val.length = 1; - return ltdb_store(ldb, &msg, TDB_INSERT); + ret = ltdb_store(ldb, &msg, TDB_INSERT); + + free(msg.dn); + free(el.name); + free(val.data); + + return ret; } /* @@ -150,8 +172,8 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) msg.num_elements = 1; msg.elements = ⪙ - msg.dn = LTDB_BASEINFO; - el.name = LTDB_SEQUENCE_NUMBER; + msg.dn = strdup(LTDB_BASEINFO); + el.name = strdup(LTDB_SEQUENCE_NUMBER); el.values = &val; el.num_values = 1; el.flags = LDB_FLAG_MOD_REPLACE; @@ -161,6 +183,8 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) ret = ltdb_modify_internal(ldb, &msg); free(s); + free(msg.dn); + free(el.name); if (ret == 0) { ltdb->sequence_number += 1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index d250bc10be..0b9581e52f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -202,7 +202,10 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, struct ldb_parse_tree tree2; struct dn_list list2; tree2.operation = LDB_OP_SIMPLE; - tree2.u.simple.attr = LTDB_OBJECTCLASS; + tree2.u.simple.attr = strdup(LTDB_OBJECTCLASS); + if (!tree2.u.simple.attr) { + return -1; + } tree2.u.simple.value = el->values[j]; if (ltdb_index_dn_objectclass(ldb, &tree2, index_list, &list2) == 1) { @@ -214,6 +217,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, dn_list_free(&list2); } } + free(tree2.u.simple.attr); } } } @@ -488,7 +492,7 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree const char *base, enum ldb_scope scope, const struct dn_list *dn_list, - const char * const attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { int i; unsigned int count = 0; @@ -528,7 +532,7 @@ int ltdb_search_indexed(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; struct dn_list dn_list; @@ -569,7 +573,10 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, } msg->elements = el2; - msg->elements[msg->num_elements].name = LTDB_IDX; + msg->elements[msg->num_elements].name = strdup(LTDB_IDX); + if (!msg->elements[msg->num_elements].name) { + return -1; + } msg->elements[msg->num_elements].num_values = 0; msg->elements[msg->num_elements].values = malloc_p(struct ldb_val); if (!msg->elements[msg->num_elements].values) { @@ -627,7 +634,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, { struct ldb_message msg; char *dn_key; - int ret, i; + int ret, i, added=0; dn_key = ldb_dn_key(el->name, &el->values[v_idx]); if (!dn_key) { @@ -661,6 +668,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, } if (i == msg.num_elements) { + added = 1; ret = ltdb_index_add1_new(ldb, &msg, el, dn); } else { ret = ltdb_index_add1_add(ldb, &msg, el, i, dn); @@ -670,6 +678,10 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, ret = ltdb_store(ldb, &msg, TDB_REPLACE); } + if (added) { + free(msg.elements[i].name); + } + ltdb_search_dn1_free(ldb, &msg); return ret; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index cce865e052..1dce8f83a2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -148,7 +148,7 @@ static int msg_add_all_elements(struct ldb_message *ret, */ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, const struct ldb_message *msg, - const char * const *attrs) + char * const *attrs) { struct ldb_message *ret; int i; @@ -294,7 +294,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message search the database for a single simple dn */ int ltdb_search_dn(struct ldb_context *ldb, char *dn, - const char * const attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { int ret; struct ldb_message msg, *msg2; @@ -330,7 +330,7 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, return 0 on success, -1 on failure */ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, - const char * const attrs[], + char * const attrs[], unsigned int *count, struct ldb_message ***res) { @@ -368,7 +368,7 @@ struct ltdb_search_info { struct ldb_parse_tree *tree; const char *base; enum ldb_scope scope; - const char * const *attrs; + char * const *attrs; struct ldb_message **msgs; int failures; int count; @@ -445,7 +445,7 @@ static int ltdb_search_full(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; int ret; @@ -478,7 +478,7 @@ static int ltdb_search_full(struct ldb_context *ldb, */ int ltdb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char * const attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { struct ldb_parse_tree *tree; int ret; diff --git a/source4/lib/ldb/tests/init_slapd.sh b/source4/lib/ldb/tests/init_slapd.sh index 67eecb031c..65700f6c18 100755 --- a/source4/lib/ldb/tests/init_slapd.sh +++ b/source4/lib/ldb/tests/init_slapd.sh @@ -5,7 +5,11 @@ export PATH=/usr/sbin:$PATH rm -rf tests/tmp/db mkdir -p tests/tmp/db -killall slapd +if pidof slapd > /dev/null; then + killall slapd +fi sleep 2 -killall -9 slapd +if pidof slapd > /dev/null; then + killall -9 slapd +fi slapadd -f tests/slapd.conf < tests/init.ldif || exit 1 diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 79db49bb48..794b451074 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -1,8 +1,17 @@ echo "Adding base elements" -bin/ldbadd tests/test.ldif +bin/ldbadd tests/test.ldif || exit 1 echo "Modifying elements" -bin/ldbmodify tests/test-modify.ldif +bin/ldbmodify tests/test-modify.ldif || exit 1 echo "Showing modified record" -bin/ldbsearch '(uid=uham)' +bin/ldbsearch '(uid=uham)' || exit 1 + +echo "Starting ldbtest" +time bin/ldbtest -r 1000 -s 100 || exit 1 + +echo "Adding index" +bin/ldbadd tests/test-index.ldif || exit 1 + +echo "Starting ldbtest indexed" +time bin/ldbtest -r 1000 -s 5000 || exit 1 diff --git a/source4/lib/ldb/tests/test-tdb.sh b/source4/lib/ldb/tests/test-tdb.sh index 1e21accac5..316828c31c 100755 --- a/source4/lib/ldb/tests/test-tdb.sh +++ b/source4/lib/ldb/tests/test-tdb.sh @@ -6,3 +6,4 @@ export LDB_URL="tdb://test.ldb" rm -f test.ldb . tests/test-generic.sh + diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index e8275e87c1..541024dd2d 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -49,7 +49,7 @@ static void do_search(struct ldb_context *ldb, const char *basedn, int scope, const char *expression, - const char * const *attrs) + char * const *attrs) { int ret, i; struct ldb_message **msgs; @@ -84,7 +84,7 @@ static void do_search(struct ldb_context *ldb, int main(int argc, char * const argv[]) { struct ldb_context *ldb; - const char * const * attrs = NULL; + char * const * attrs = NULL; const char *ldb_url; const char *basedn = NULL; int opt; diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index b7d1d22db8..bcb8bdcb16 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -36,12 +36,12 @@ static struct timeval tp1,tp2; -static void start_timer() +static void start_timer(void) { gettimeofday(&tp1,NULL); } -static double end_timer() +static double end_timer(void) { gettimeofday(&tp2,NULL); return((tp2.tv_sec - tp1.tv_sec) + @@ -108,6 +108,8 @@ static void add_records(struct ldb_context *ldb, vals[5][0].data = name; vals[5][0].length = strlen(vals[5][0].data); + ldb_delete(ldb, msg.dn); + if (ldb_add(ldb, &msg) != 0) { printf("Add of %s failed - %s\n", name, ldb_errstring(ldb)); exit(1); @@ -126,6 +128,83 @@ static void add_records(struct ldb_context *ldb, printf("\n"); } +static void modify_records(struct ldb_context *ldb, + const char *basedn, + int count) +{ + struct ldb_message msg; + int i; + + for (i=0;i Date: Thu, 6 May 2004 04:40:15 +0000 Subject: r502: modified ldb to allow the use of an external pool memory allocator. The way to use this is to call ldb_set_alloc() with a function pointer to whatever memory allocator you like. It includes a context pointer to allow for pool based allocators. (This used to be commit 3955c482e6c2c9e975a4bb809ec8cb6068e48e34) --- source4/lib/ldb/Makefile.ldb | 3 +- source4/lib/ldb/common/ldb_alloc.c | 174 +++++++++++++++++++++++++++++ source4/lib/ldb/common/ldb_ldif.c | 80 +++++++------ source4/lib/ldb/common/ldb_msg.c | 13 ++- source4/lib/ldb/common/ldb_parse.c | 205 ++++++++++------------------------ source4/lib/ldb/common/ldb_utf8.c | 4 +- source4/lib/ldb/common/util.c | 18 --- source4/lib/ldb/config.m4 | 1 + source4/lib/ldb/include/includes.h | 6 - source4/lib/ldb/include/ldb.h | 71 ++++++++++-- source4/lib/ldb/include/ldb_parse.h | 4 + source4/lib/ldb/ldb_ldap/ldb_ldap.c | 93 +++++++-------- source4/lib/ldb/ldb_tdb/ldb_cache.c | 65 ++++++----- source4/lib/ldb/ldb_tdb/ldb_index.c | 121 +++++++++++--------- source4/lib/ldb/ldb_tdb/ldb_match.c | 18 +-- source4/lib/ldb/ldb_tdb/ldb_pack.c | 24 ++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 109 ++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 106 ++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 3 + source4/lib/ldb/tests/test-generic.sh | 12 +- source4/lib/ldb/tools/ldbadd.c | 4 +- source4/lib/ldb/tools/ldbedit.c | 17 +-- source4/lib/ldb/tools/ldbmodify.c | 4 +- source4/lib/ldb/tools/ldbsearch.c | 26 +++-- source4/lib/ldb/tools/ldbtest.c | 4 +- 25 files changed, 693 insertions(+), 492 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_alloc.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 0b8fdfe28f..0a0b95f7fe 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -22,7 +22,8 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ - common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o + common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ + common/ldb_alloc.o OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) diff --git a/source4/lib/ldb/common/ldb_alloc.c b/source4/lib/ldb/common/ldb_alloc.c new file mode 100644 index 0000000000..667759e832 --- /dev/null +++ b/source4/lib/ldb/common/ldb_alloc.c @@ -0,0 +1,174 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb alloc + * + * Description: functions for memory allocation + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + this allows the user to choose their own allocation function +*/ +int ldb_set_alloc(struct ldb_context *ldb, + void *(*alloc)(void *context, void *ptr, size_t size), + void *context) +{ + ldb->alloc_ops.alloc = alloc; + ldb->alloc_ops.context = context; + return 0; +} + +/* + this is the default memory allocation function +*/ +static void *ldb_default_alloc(void *context, void *ptr, size_t size) +{ + /* by setting LDB_ALLOC_OFS to non-zero the test suite can + catch any places where we incorrectly use the libc alloc + funcitons directly */ +#define LDB_ALLOC_OFS 4 + /* we don't assume a modern realloc function */ + if (ptr == NULL) { + ptr = malloc(size+LDB_ALLOC_OFS); + if (ptr) return ((char *)ptr)+LDB_ALLOC_OFS; + return NULL; + } + if (size == 0) { + free(((char *)ptr)-LDB_ALLOC_OFS); + return NULL; + } + ptr = realloc(((char *)ptr)-LDB_ALLOC_OFS, size+LDB_ALLOC_OFS); + if (ptr) { + return ((char *)ptr)+LDB_ALLOC_OFS; + } + return NULL; +} + +/* + all memory allocation goes via this function +*/ +void *ldb_realloc(struct ldb_context *ldb, void *ptr, size_t size) +{ + if (!ldb->alloc_ops.alloc) { + ldb_set_alloc(ldb, ldb_default_alloc, NULL); + } + return ldb->alloc_ops.alloc(ldb->alloc_ops.context, ptr, size); +} + +void *ldb_malloc(struct ldb_context *ldb, size_t size) +{ + return ldb_realloc(ldb, NULL, size); +} + +void ldb_free(struct ldb_context *ldb, void *ptr) +{ + if (ptr != NULL) { + ldb_realloc(ldb, ptr, 0); + } +} + +void *ldb_strndup(struct ldb_context *ldb, const char *str, size_t maxlen) +{ + size_t len = strnlen(str, maxlen); + void *ret; + ret = ldb_realloc(ldb, NULL, len+1); + if (ret) { + memcpy(ret, str, len); + ((char *)ret)[len] = 0; + } + return ret; +} + +void *ldb_strdup(struct ldb_context *ldb, const char *str) +{ + size_t len = strlen(str); + void *ret; + ret = ldb_realloc(ldb, NULL, len+1); + if (ret) { + memcpy(ret, str, len+1); + } + return ret; +} + +/* + a ldb wrapper for asprintf(), using ldb_malloc() +*/ +int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) +{ + int len, len2; + va_list ap; + + *strp = NULL; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + if (len < 0) { + return len; + } + + *strp = ldb_malloc(ldb, len+1); + if (! *strp) { + return -1; + } + + va_start(ap, fmt); + len2 = vsnprintf(*strp, len+1, fmt, ap); + va_end(ap); + + if (len2 != len) { + /* buggy (or non-C99) vsnprintf function */ + ldb_free(ldb, *strp); + return -1; + } + + return len; +} + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *ldb_realloc_array(struct ldb_context *ldb, + void *ptr, size_t el_size, unsigned count) +{ +#define MAX_MALLOC_SIZE 0x7fffffff + + if (count == 0 || + count >= MAX_MALLOC_SIZE/el_size) { + return NULL; + } + if (!ptr) { + return ldb_malloc(ldb, el_size * count); + } + return ldb_realloc(ldb, ptr, el_size * count); +} + diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index ef782e90e3..451276c48d 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -86,7 +86,7 @@ static int base64_decode(char *s) encode as base64 caller frees */ -char *ldb_base64_encode(const char *buf, int len) +char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; @@ -94,7 +94,7 @@ char *ldb_base64_encode(const char *buf, int len) int bytes = (len*8 + 5)/6; char *out; - out = malloc(bytes+2); + out = ldb_malloc(ldb, bytes+2); if (!out) return NULL; for (i=0;ielements[i].name); CHECK_RET; - ret = base64_encode_f(fprintf_fn, private_data, + ret = base64_encode_f(ldb, fprintf_fn, private_data, msg->elements[i].values[j].data, msg->elements[i].values[j].length, strlen(msg->elements[i].name)+3); @@ -282,7 +285,8 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), caller frees */ -static char *next_chunk(int (*fgetc_fn)(void *), void *private_data) +static char *next_chunk(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data) { size_t alloc_size=0, chunk_size = 0; char *chunk = NULL; @@ -293,9 +297,9 @@ static char *next_chunk(int (*fgetc_fn)(void *), void *private_data) if (chunk_size+1 >= alloc_size) { char *c2; alloc_size += 1024; - c2 = realloc_p(chunk, char, alloc_size); + c2 = ldb_realloc_p(ldb, chunk, char, alloc_size); if (!c2) { - free(chunk); + ldb_free(ldb, chunk); errno = ENOMEM; return NULL; } @@ -402,27 +406,29 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) /* free a message from a ldif_read */ -void ldif_read_free(struct ldb_ldif *ldif) +void ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif) { struct ldb_message *msg = &ldif->msg; int i; for (i=0;inum_elements;i++) { - if (msg->elements[i].name) free(msg->elements[i].name); - if (msg->elements[i].values) free(msg->elements[i].values); + if (msg->elements[i].name) ldb_free(ldb, msg->elements[i].name); + if (msg->elements[i].values) ldb_free(ldb, msg->elements[i].values); } - if (msg->elements) free(msg->elements); - if (msg->private_data) free(msg->private_data); - free(ldif); + if (msg->elements) ldb_free(ldb, msg->elements); + if (msg->private_data) ldb_free(ldb, msg->private_data); + ldb_free(ldb, ldif); } /* add an empty element */ -static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned flags) +static int msg_add_empty(struct ldb_context *ldb, + struct ldb_message *msg, const char *name, unsigned flags) { struct ldb_message_element *el2, *el; - el2 = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + el2 = ldb_realloc_p(ldb, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!el2) { errno = ENOMEM; return -1; @@ -432,7 +438,7 @@ static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned fla el = &msg->elements[msg->num_elements]; - el->name = strdup(name); + el->name = ldb_strdup(ldb, name); el->num_values = 0; el->values = NULL; el->flags = flags; @@ -450,7 +456,8 @@ static int msg_add_empty(struct ldb_message *msg, const char *name, unsigned fla /* read from a LDIF source, creating a ldb_message */ -struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) +struct ldb_ldif *ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data) { struct ldb_ldif *ldif; struct ldb_message *msg; @@ -461,7 +468,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) value.data = NULL; - ldif = malloc_p(struct ldb_ldif); + ldif = ldb_malloc_p(ldb, struct ldb_ldif); if (!ldif) return NULL; ldif->changetype = LDB_CHANGETYPE_NONE; @@ -472,7 +479,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) msg->num_elements = 0; msg->private_data = NULL; - chunk = next_chunk(fgetc_fn, private_data); + chunk = next_chunk(ldb, fgetc_fn, private_data); if (!chunk) { goto failed; } @@ -530,7 +537,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) } if (empty) { - if (msg_add_empty(msg, (char *)value.data, flags) != 0) { + if (msg_add_empty(ldb, msg, (char *)value.data, flags) != 0) { goto failed; } continue; @@ -542,7 +549,8 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) flags == el->flags) { /* its a continuation */ el->values = - realloc_p(el->values, struct ldb_val, el->num_values+1); + ldb_realloc_p(ldb, el->values, + struct ldb_val, el->num_values+1); if (!el->values) { goto failed; } @@ -550,16 +558,16 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) el->num_values++; } else { /* its a new attribute */ - msg->elements = realloc_p(msg->elements, - struct ldb_message_element, - msg->num_elements+1); + msg->elements = ldb_realloc_p(ldb, msg->elements, + struct ldb_message_element, + msg->num_elements+1); if (!msg->elements) { goto failed; } el = &msg->elements[msg->num_elements]; el->flags = flags; - el->name = strdup(attr); - el->values = malloc_p(struct ldb_val); + el->name = ldb_strdup(ldb, attr); + el->values = ldb_malloc_p(ldb, struct ldb_val); if (!el->values || !el->name) { goto failed; } @@ -572,7 +580,7 @@ struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data) return ldif; failed: - if (ldif) ldif_read_free(ldif); + if (ldif) ldif_read_free(ldb, ldif); return NULL; } @@ -591,11 +599,11 @@ static int fgetc_file(void *private_data) return fgetc(state->f); } -struct ldb_ldif *ldif_read_file(FILE *f) +struct ldb_ldif *ldif_read_file(struct ldb_context *ldb, FILE *f) { struct ldif_read_file_state state; state.f = f; - return ldif_read(fgetc_file, &state); + return ldif_read(ldb, fgetc_file, &state); } @@ -615,11 +623,11 @@ static int fgetc_string(void *private_data) return EOF; } -struct ldb_ldif *ldif_read_string(const char *s) +struct ldb_ldif *ldif_read_string(struct ldb_context *ldb, const char *s) { struct ldif_read_string_state state; state.s = s; - return ldif_read(fgetc_string, &state); + return ldif_read(ldb, fgetc_string, &state); } @@ -642,9 +650,9 @@ static int fprintf_file(void *private_data, const char *fmt, ...) return ret; } -int ldif_write_file(FILE *f, const struct ldb_ldif *ldif) +int ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif) { struct ldif_write_file_state state; state.f = f; - return ldif_write(fprintf_file, &state, ldif); + return ldif_write(ldb, fprintf_file, &state, ldif); } diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 8eb8a8c5ef..5976db81b6 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -87,11 +87,13 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, /* add an empty element to a message */ -int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) +int ldb_msg_add_empty(struct ldb_context *ldb, + struct ldb_message *msg, const char *attr_name, int flags) { struct ldb_message_element *els; - els = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + els = ldb_realloc_p(ldb, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!els) { errno = ENOMEM; return -1; @@ -100,7 +102,7 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) els[msg->num_elements].values = NULL; els[msg->num_elements].num_values = 0; els[msg->num_elements].flags = flags; - els[msg->num_elements].name = strdup(attr_name); + els[msg->num_elements].name = ldb_strdup(ldb, attr_name); if (!els[msg->num_elements].name) { return -1; } @@ -114,11 +116,12 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) /* add an empty element to a message */ -int ldb_msg_add(struct ldb_message *msg, +int ldb_msg_add(struct ldb_context *ldb, + struct ldb_message *msg, const struct ldb_message_element *el, int flags) { - if (ldb_msg_add_empty(msg, el->name, flags) != 0) { + if (ldb_msg_add_empty(ldb, msg, el->name, flags) != 0) { return -1; } diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 4f8d469e6c..75eb44fcc0 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -59,7 +59,7 @@ a filter is defined by: /* return next token element. Caller frees */ -static char *ldb_parse_lex(const char **s) +static char *ldb_parse_lex(struct ldb_context *ldb, const char **s) { const char *p = *s; char *ret; @@ -75,7 +75,7 @@ static char *ldb_parse_lex(const char **s) if (strchr("()&|=!", *p)) { (*s) = p+1; - ret = strndup(p, 1); + ret = ldb_strndup(ldb, p, 1); if (!ret) { errno = ENOMEM; } @@ -90,7 +90,7 @@ static char *ldb_parse_lex(const char **s) return NULL; } - ret = strndup(*s, p - *s); + ret = ldb_strndup(ldb, *s, p - *s); if (!ret) { errno = ENOMEM; } @@ -122,46 +122,42 @@ static const char *match_brace(const char *s) } -static struct ldb_parse_tree *ldb_parse_filter(const char **s); +static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const char **s); /* ::= */ -static struct ldb_parse_tree *ldb_parse_simple(const char *s) +static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const char *s) { char *eq, *val, *l; struct ldb_parse_tree *ret; - l = ldb_parse_lex(&s); + l = ldb_parse_lex(ldb, &s); if (!l) { - fprintf(stderr, "Unexpected end of expression\n"); return NULL; } if (strchr("()&|=", *l)) { - fprintf(stderr, "Unexpected token '%s'\n", l); - free(l); + ldb_free(ldb, l); return NULL; } - eq = ldb_parse_lex(&s); + eq = ldb_parse_lex(ldb, &s); if (!eq || strcmp(eq, "=") != 0) { - fprintf(stderr, "Expected '='\n"); - free(l); - if (eq) free(eq); + ldb_free(ldb, l); + if (eq) ldb_free(ldb, eq); return NULL; } - free(eq); + ldb_free(ldb, eq); - val = ldb_parse_lex(&s); + val = ldb_parse_lex(ldb, &s); if (val && strchr("()&|=", *val)) { - fprintf(stderr, "Unexpected token '%s'\n", val); - free(l); - if (val) free(val); + ldb_free(ldb, l); + if (val) ldb_free(ldb, val); return NULL; } - ret = malloc_p(struct ldb_parse_tree); + ret = ldb_malloc_p(ldb, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -182,11 +178,12 @@ static struct ldb_parse_tree *ldb_parse_simple(const char *s) ::= '|' ::= | */ -static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const char *s) +static struct ldb_parse_tree *ldb_parse_filterlist(struct ldb_context *ldb, + enum ldb_parse_op op, const char *s) { struct ldb_parse_tree *ret, *next; - ret = malloc_p(struct ldb_parse_tree); + ret = ldb_malloc_p(ldb, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -194,31 +191,31 @@ static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const c ret->operation = op; ret->u.list.num_elements = 1; - ret->u.list.elements = malloc_p(struct ldb_parse_tree *); + ret->u.list.elements = ldb_malloc_p(ldb, struct ldb_parse_tree *); if (!ret->u.list.elements) { errno = ENOMEM; - free(ret); + ldb_free(ldb, ret); return NULL; } - ret->u.list.elements[0] = ldb_parse_filter(&s); + ret->u.list.elements[0] = ldb_parse_filter(ldb, &s); if (!ret->u.list.elements[0]) { - free(ret->u.list.elements); - free(ret); + ldb_free(ldb, ret->u.list.elements); + ldb_free(ldb, ret); return NULL; } while (isspace(*s)) s++; - while (*s && (next = ldb_parse_filter(&s))) { + while (*s && (next = ldb_parse_filter(ldb, &s))) { struct ldb_parse_tree **e; - e = realloc_p(ret->u.list.elements, - struct ldb_parse_tree *, - ret->u.list.num_elements+1); + e = ldb_realloc_p(ldb, ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements+1); if (!e) { errno = ENOMEM; - ldb_parse_tree_free(next); - ldb_parse_tree_free(ret); + ldb_parse_tree_free(ldb, next); + ldb_parse_tree_free(ldb, ret); return NULL; } ret->u.list.elements = e; @@ -234,20 +231,20 @@ static struct ldb_parse_tree *ldb_parse_filterlist(enum ldb_parse_op op, const c /* ::= '!' */ -static struct ldb_parse_tree *ldb_parse_not(const char *s) +static struct ldb_parse_tree *ldb_parse_not(struct ldb_context *ldb, const char *s) { struct ldb_parse_tree *ret; - ret = malloc_p(struct ldb_parse_tree); + ret = ldb_malloc_p(ldb, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; } ret->operation = LDB_OP_NOT; - ret->u.not.child = ldb_parse_filter(&s); + ret->u.not.child = ldb_parse_filter(ldb, &s); if (!ret->u.not.child) { - free(ret); + ldb_free(ldb, ret); return NULL; } @@ -258,67 +255,64 @@ static struct ldb_parse_tree *ldb_parse_not(const char *s) parse a filtercomp ::= | | | */ -static struct ldb_parse_tree *ldb_parse_filtercomp(const char *s) +static struct ldb_parse_tree *ldb_parse_filtercomp(struct ldb_context *ldb, + const char *s) { while (isspace(*s)) s++; switch (*s) { case '&': - return ldb_parse_filterlist(LDB_OP_AND, s+1); + return ldb_parse_filterlist(ldb, LDB_OP_AND, s+1); case '|': - return ldb_parse_filterlist(LDB_OP_OR, s+1); + return ldb_parse_filterlist(ldb, LDB_OP_OR, s+1); case '!': - return ldb_parse_not(s+1); + return ldb_parse_not(ldb, s+1); case '(': case ')': - fprintf(stderr, "Unexpected token '%c'\n", *s); return NULL; } - return ldb_parse_simple(s); + return ldb_parse_simple(ldb, s); } /* ::= '(' ')' */ -static struct ldb_parse_tree *ldb_parse_filter(const char **s) +static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const char **s) { char *l, *s2; const char *p, *p2; struct ldb_parse_tree *ret; - l = ldb_parse_lex(s); + l = ldb_parse_lex(ldb, s); if (!l) { - fprintf(stderr, "Unexpected end of expression\n"); return NULL; } if (strcmp(l, "(") != 0) { - free(l); - fprintf(stderr, "Expected '('\n"); + ldb_free(ldb, l); return NULL; } - free(l); + ldb_free(ldb, l); p = match_brace(*s); if (!p) { - fprintf(stderr, "Parse error - mismatched braces\n"); return NULL; } p2 = p + 1; - s2 = strndup(*s, p - *s); + s2 = ldb_strndup(ldb, *s, p - *s); if (!s2) { errno = ENOMEM; return NULL; } - ret = ldb_parse_filtercomp(s2); - free(s2); + ret = ldb_parse_filtercomp(ldb, s2); + ldb_free(ldb, s2); *s = p2; @@ -331,130 +325,43 @@ static struct ldb_parse_tree *ldb_parse_filter(const char **s) expression ::= | */ -struct ldb_parse_tree *ldb_parse_tree(const char *s) +struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s) { while (isspace(*s)) s++; if (*s == '(') { - return ldb_parse_filter(&s); + return ldb_parse_filter(ldb, &s); } - return ldb_parse_simple(s); + return ldb_parse_simple(ldb, s); } /* free a parse tree returned from ldb_parse_tree() */ -void ldb_parse_tree_free(struct ldb_parse_tree *tree) +void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree) { int i; switch (tree->operation) { case LDB_OP_SIMPLE: - free(tree->u.simple.attr); - if (tree->u.simple.value.data) free(tree->u.simple.value.data); + ldb_free(ldb, tree->u.simple.attr); + if (tree->u.simple.value.data) ldb_free(ldb, tree->u.simple.value.data); break; case LDB_OP_AND: case LDB_OP_OR: for (i=0;iu.list.num_elements;i++) { - ldb_parse_tree_free(tree->u.list.elements[i]); + ldb_parse_tree_free(ldb, tree->u.list.elements[i]); } - if (tree->u.list.elements) free(tree->u.list.elements); + if (tree->u.list.elements) ldb_free(ldb, tree->u.list.elements); break; case LDB_OP_NOT: - ldb_parse_tree_free(tree->u.not.child); + ldb_parse_tree_free(ldb, tree->u.not.child); break; } - free(tree); + ldb_free(ldb, tree); } -#if TEST_PROGRAM -/* - return a string representation of a parse tree - used for debugging -*/ -static char *tree_string(struct ldb_parse_tree *tree) -{ - char *s = NULL; - char *s1, *s2; - int i; - - switch (tree->operation) { - case LDB_OP_SIMPLE: - asprintf(&s, "( %s = \"%s\" )", tree->u.simple.attr, - (char *)tree->u.simple.value.data); - break; - - case LDB_OP_AND: - case LDB_OP_OR: - asprintf(&s, "( %c", tree->operation==LDB_OP_AND?'&':'|'); - if (!s) return NULL; - - for (i=0;iu.list.num_elements;i++) { - s1 = tree_string(tree->u.list.elements[i]); - if (!s1) { - free(s); - return NULL; - } - asprintf(&s2, "%s %s", s, s1); - free(s); - free(s1); - s = s2; - } - if (!s) { - return NULL; - } - asprintf(&s2, "%s )", s); - free(s); - s = s2; - break; - - case LDB_OP_NOT: - s1 = tree_string(tree->u.not.child); - asprintf(&s, "( ! %s )", s1); - free(s1); - break; - } - return s; -} - - -/* - print a tree - */ -static void print_tree(struct ldb_parse_tree *tree) -{ - char *s = tree_string(tree); - printf("%s\n", s); - free(s); -} - - - int main(void) -{ - char line[1000]; - int ret = 0; - - while (fgets(line, sizeof(line)-1, stdin)) { - struct ldb_parse_tree *tree; - - if (line[strlen(line)-1] == '\n') { - line[strlen(line)-1] = 0; - } - tree = ldb_parse_tree(line); - if (!tree) { - fprintf(stderr, "Failed to parse\n"); - ret = 1; - continue; - } - print_tree(tree); - ldb_parse_tree_free(tree); - } - - return ret; -} -#endif /* TEST_PROGRAM */ - diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 7767b0955e..1e467d23af 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -38,10 +38,10 @@ TODO: a simple case folding function - will be replaced by a UTF8 aware function later */ -char *ldb_casefold(const char *s) +char *ldb_casefold(struct ldb_context *ldb, const char *s) { int i; - char *ret = strdup(s); + char *ret = ldb_strdup(ldb, s); if (!s) { errno = ENOMEM; return NULL; diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index 22bbc8334e..68537a7864 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -35,24 +35,6 @@ #include "includes.h" -#define MAX_MALLOC_SIZE 0x7fffffff - -/* - realloc an array, checking for integer overflow in the array size -*/ -void *realloc_array(void *ptr, size_t el_size, unsigned count) -{ - if (count == 0 || - count >= MAX_MALLOC_SIZE/el_size) { - return NULL; - } - if (!ptr) { - return malloc(el_size * count); - } - return realloc(ptr, el_size * count); -} - - /* find an element in a list, using the given comparison function and assuming that the list is already sorted using comp_fn diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 444e65bfab..975da5a4a6 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -8,6 +8,7 @@ SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], lib/ldb/common/ldb_msg.o \ lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ + lib/ldb/common/ldb_alloc.o \ lib/ldb/ldb_tdb/ldb_search.o \ lib/ldb/ldb_tdb/ldb_tdb.o \ lib/ldb/ldb_tdb/ldb_pack.o \ diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 7ee6876f48..bf61a983e0 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -18,11 +18,5 @@ #include #include #include "ldb.h" -#include "ldb_parse.h" - -#define malloc_p(type) (type *)malloc(sizeof(type)) -#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) -#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) - #include "tdb/tdb.h" #include "proto.h" diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index cee72c3c21..852389d415 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -32,6 +32,9 @@ * Author: Andrew Tridgell */ +#ifndef _LDB_H_ +#define _LDB_H_ 1 + /* major restrictions as compared to normal LDAP: @@ -46,7 +49,6 @@ */ - /* an individual lump of data in a result comes in this format. The pointer will usually be to a UTF-8 string if the application is @@ -58,6 +60,9 @@ struct ldb_val { void *data; }; +#include "ldb_parse.h" + + /* these flags are used in ldd_message_element.flags fields. The LDA_FLAGS_MOD_* flags are used in ldap_modify() calls to specify whether attributes are being added, deleted or modified */ @@ -130,8 +135,24 @@ struct ldb_backend_ops { int (*modify_record)(struct ldb_context *, const struct ldb_message *); int (*delete_record)(struct ldb_context *, const char *); const char * (*errstring)(struct ldb_context *); + + /* this is called when the alloc ops changes to ensure we + don't have any old allocated data in the context */ + void (*cache_free)(struct ldb_context *); }; + +/* + the user can optionally supply a allocator function. It is presumed + it will act like a modern realloc(), with a context ptr to allow + for pool allocators +*/ +struct ldb_alloc_ops { + void *(*alloc)(void *context, void *ptr, size_t size); + void *context; +}; + + /* every ldb connection is started by establishing a ldb_context */ @@ -141,6 +162,9 @@ struct ldb_context { /* the operations provided by the backend */ const struct ldb_backend_ops *ops; + + /* memory allocation info */ + struct ldb_alloc_ops alloc_ops; }; @@ -209,19 +233,21 @@ const char *ldb_errstring(struct ldb_context *ldb); /* casefold a string (should be UTF8, but at the moment it isn't) */ -char *ldb_casefold(const char *s); +char *ldb_casefold(struct ldb_context *ldb, const char *s); /* ldif manipulation functions */ -int ldif_write(int (*fprintf_fn)(void *, const char *, ...), +int ldif_write(struct ldb_context *ldb, + int (*fprintf_fn)(void *, const char *, ...), void *private_data, const struct ldb_ldif *ldif); -void ldif_read_free(struct ldb_ldif *); -struct ldb_ldif *ldif_read(int (*fgetc_fn)(void *), void *private_data); -struct ldb_ldif *ldif_read_file(FILE *f); -struct ldb_ldif *ldif_read_string(const char *s); -int ldif_write_file(FILE *f, const struct ldb_ldif *msg); +void ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *); +struct ldb_ldif *ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data); +struct ldb_ldif *ldif_read_file(struct ldb_context *ldb, FILE *f); +struct ldb_ldif *ldif_read_string(struct ldb_context *ldb, const char *s); +int ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); /* useful functions for ldb_message structure manipulation */ @@ -238,10 +264,12 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, struct ldb_val *val); /* add a new empty element to a ldb_message */ -int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags); +int ldb_msg_add_empty(struct ldb_context *ldb, + struct ldb_message *msg, const char *attr_name, int flags); /* add a element to a ldb_message */ -int ldb_msg_add(struct ldb_message *msg, +int ldb_msg_add(struct ldb_context *ldb, + struct ldb_message *msg, const struct ldb_message_element *el, int flags); @@ -264,3 +292,26 @@ double ldb_msg_find_double(const struct ldb_message *msg, const char *ldb_msg_find_string(const struct ldb_message *msg, const char *attr_name, const char *default_value); + + +/* + this allows the user to choose their own allocation function + the allocation function should behave like a modern realloc() + function, which means that: + malloc(size) == alloc(context, NULL, size) + free(ptr) == alloc(context, ptr, 0) + realloc(ptr, size) == alloc(context, ptr, size) + The context argument is provided to allow for pool based allocators, + which often take a context argument +*/ +int ldb_set_alloc(struct ldb_context *ldb, + void *(*alloc)(void *context, void *ptr, size_t size), + void *context); + + +/* these are used as type safe versions of the ldb allocation functions */ +#define ldb_malloc_p(ldb, type) (type *)ldb_malloc(ldb, sizeof(type)) +#define ldb_malloc_array_p(ldb, type, count) (type *)ldb_realloc_array(ldb, NULL, sizeof(type), count) +#define ldb_realloc_p(ldb, p, type, count) (type *)ldb_realloc_array(ldb, p, sizeof(type), count) + +#endif diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h index c0d5806cc9..930799d7b6 100644 --- a/source4/lib/ldb/include/ldb_parse.h +++ b/source4/lib/ldb/include/ldb_parse.h @@ -32,6 +32,8 @@ * Author: Andrew Tridgell */ +#ifndef _LDB_PARSE_H +#define _LDB_PARSE_H 1 enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT}; @@ -51,3 +53,5 @@ struct ldb_parse_tree { } not; } u; }; + +#endif diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 8723beeadc..7e7d047f25 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -77,13 +77,15 @@ static int lldb_close(struct ldb_context *ldb) ret = -1; } + ldb_set_alloc(ldb, NULL, NULL); + if (lldb->options) { for (i=0;lldb->options[i];i++) { - free(lldb->options[i]); + ldb_free(ldb, lldb->options[i]); } - free(lldb->options); + ldb_free(ldb, lldb->options); } - free(lldb); + ldb_free(ldb, lldb); free(ldb); return ret; @@ -116,18 +118,18 @@ static int lldb_delete(struct ldb_context *ldb, const char *dn) static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) { int i, j; - free(msg->dn); + ldb_free(ldb, msg->dn); for (i=0;inum_elements;i++) { - free(msg->elements[i].name); + ldb_free(ldb, msg->elements[i].name); for (j=0;jelements[i].num_values;j++) { if (msg->elements[i].values[j].data) { - free(msg->elements[i].values[j].data); + ldb_free(ldb, msg->elements[i].values[j].data); } } - free(msg->elements[i].values); + ldb_free(ldb, msg->elements[i].values); } - if (msg->elements) free(msg->elements); - free(msg); + if (msg->elements) ldb_free(ldb, msg->elements); + ldb_free(ldb, msg); return 0; } @@ -142,7 +144,7 @@ static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res) return -1; } } - free(res); + ldb_free(ldb, res); return 0; } @@ -150,7 +152,8 @@ static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res) /* add a single set of ldap message values to a ldb_message */ -static int lldb_add_msg_attr(struct ldb_message *msg, +static int lldb_add_msg_attr(struct ldb_context *ldb, + struct ldb_message *msg, const char *attr, struct berval **bval) { int count, i; @@ -162,8 +165,8 @@ static int lldb_add_msg_attr(struct ldb_message *msg, return -1; } - el = realloc_p(msg->elements, struct ldb_message_element, - msg->num_elements + 1); + el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, + msg->num_elements + 1); if (!el) { errno = ENOMEM; return -1; @@ -173,7 +176,7 @@ static int lldb_add_msg_attr(struct ldb_message *msg, el = &msg->elements[msg->num_elements]; - el->name = strdup(attr); + el->name = ldb_strdup(ldb, attr); if (!el->name) { errno = ENOMEM; return -1; @@ -181,14 +184,14 @@ static int lldb_add_msg_attr(struct ldb_message *msg, el->flags = 0; el->num_values = 0; - el->values = malloc_array_p(struct ldb_val, count); + el->values = ldb_malloc_array_p(ldb, struct ldb_val, count); if (!el->values) { errno = ENOMEM; return -1; } for (i=0;ivalues[i].data = malloc(bval[i]->bv_len); + el->values[i].data = ldb_malloc(ldb, bval[i]->bv_len); if (!el->values[i].data) { return -1; } @@ -225,7 +228,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, return count; } - (*res) = malloc_array_p(struct ldb_message *, count+1); + (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1); if (! *res) { ldap_msgfree(ldapres); errno = ENOMEM; @@ -249,7 +252,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, break; } - (*res)[msg_count] = malloc_p(struct ldb_message); + (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message); if (!(*res)[msg_count]) { goto failed; } @@ -260,7 +263,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, goto failed; } - (*res)[msg_count]->dn = strdup(dn); + (*res)[msg_count]->dn = ldb_strdup(ldb, dn); ldap_memfree(dn); if (!(*res)[msg_count]->dn) { goto failed; @@ -279,7 +282,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, bval = ldap_get_values_len(lldb->ldap, msg, attr); if (bval) { - lldb_add_msg_attr((*res)[msg_count], attr, bval); + lldb_add_msg_attr(ldb, (*res)[msg_count], attr, bval); ldap_value_free_len(bval); } @@ -303,7 +306,7 @@ failed: /* free a set of mods from lldb_msg_to_mods() */ -static void lldb_mods_free(LDAPMod **mods) +static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods) { int i, j; @@ -312,13 +315,13 @@ static void lldb_mods_free(LDAPMod **mods) for (i=0;mods[i];i++) { if (mods[i]->mod_vals.modv_bvals) { for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) { - free(mods[i]->mod_vals.modv_bvals[j]); + ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]); } - free(mods[i]->mod_vals.modv_bvals); + ldb_free(ldb, mods[i]->mod_vals.modv_bvals); } - free(mods[i]); + ldb_free(ldb, mods[i]); } - free(mods); + ldb_free(ldb, mods); } @@ -326,13 +329,14 @@ static void lldb_mods_free(LDAPMod **mods) convert a ldb_message structure to a list of LDAPMod structures ready for ldap_add() or ldap_modify() */ -static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) +static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, + const struct ldb_message *msg, int use_flags) { LDAPMod **mods; int i, j, num_mods = 0; /* allocate maximum number of elements needed */ - mods = malloc_array_p(LDAPMod *, msg->num_elements+1); + mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1); if (!mods) { errno = ENOMEM; return NULL; @@ -342,7 +346,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) for (i=0;inum_elements;i++) { const struct ldb_message_element *el = &msg->elements[i]; - mods[num_mods] = malloc_p(LDAPMod); + mods[num_mods] = ldb_malloc_p(ldb, LDAPMod); if (!mods[num_mods]) { goto failed; } @@ -362,14 +366,15 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) } } mods[num_mods]->mod_type = el->name; - mods[num_mods]->mod_vals.modv_bvals = malloc_array_p(struct berval *, - 1+el->num_values); + mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb, + struct berval *, + 1+el->num_values); if (!mods[num_mods]->mod_vals.modv_bvals) { goto failed; } for (j=0;jnum_values;j++) { - mods[num_mods]->mod_vals.modv_bvals[j] = malloc_p(struct berval); + mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval); if (!mods[num_mods]->mod_vals.modv_bvals[j]) { goto failed; } @@ -383,7 +388,7 @@ static LDAPMod **lldb_msg_to_mods(const struct ldb_message *msg, int use_flags) return mods; failed: - lldb_mods_free(mods); + lldb_mods_free(ldb, mods); return NULL; } @@ -402,14 +407,14 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) return 0; } - mods = lldb_msg_to_mods(msg, 0); + mods = lldb_msg_to_mods(ldb, msg, 0); lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } - lldb_mods_free(mods); + lldb_mods_free(ldb, mods); return ret; } @@ -429,14 +434,14 @@ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) return 0; } - mods = lldb_msg_to_mods(msg, 1); + mods = lldb_msg_to_mods(ldb, msg, 1); lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } - lldb_mods_free(mods); + lldb_mods_free(ldb, mods); return ret; } @@ -474,15 +479,15 @@ struct ldb_context *lldb_connect(const char *url, struct lldb_private *lldb = NULL; int i; - ldb = malloc_p(struct ldb_context); + ldb = calloc(1, sizeof(struct ldb_context)); if (!ldb) { errno = ENOMEM; goto failed; } - lldb = malloc_p(struct lldb_private); + lldb = ldb_malloc_p(ldb, struct lldb_private); if (!lldb) { - free(ldb); + ldb_free(ldb, ldb); errno = ENOMEM; goto failed; } @@ -503,14 +508,14 @@ struct ldb_context *lldb_connect(const char *url, on the caller keeping it around (it might be dynamic) */ for (i=0;options[i];i++) ; - lldb->options = malloc_array_p(char *, i+1); + lldb->options = ldb_malloc_array_p(ldb, char *, i+1); if (!lldb->options) { goto failed; } for (i=0;options[i];i++) { lldb->options[i+1] = NULL; - lldb->options[i] = strdup(options[i]); + lldb->options[i] = ldb_strdup(ldb, options[i]); if (!lldb->options[i]) { goto failed; } @@ -522,14 +527,14 @@ struct ldb_context *lldb_connect(const char *url, failed: if (lldb && lldb->options) { for (i=0;lldb->options[i];i++) { - free(lldb->options[i]); + ldb_free(ldb, lldb->options[i]); } - free(lldb->options); + ldb_free(ldb, lldb->options); } if (lldb && lldb->ldap) { ldap_unbind(lldb->ldap); } - if (lldb) free(lldb); + ldb_free(ldb, lldb); if (ldb) free(ldb); return NULL; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 3c6ce63c2b..6734de9fd8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -50,24 +50,24 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) msg.num_elements = 1; msg.elements = ⪙ - msg.dn = strdup(LTDB_BASEINFO); + msg.dn = ldb_strdup(ldb, LTDB_BASEINFO); if (!msg.dn) { errno = ENOMEM; return -1; } - el.name = strdup(LTDB_SEQUENCE_NUMBER); + el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER); if (!el.name) { - free(msg.dn); + ldb_free(ldb, msg.dn); errno = ENOMEM; return -1; } el.values = &val; el.num_values = 1; el.flags = 0; - val.data = strdup("0"); + val.data = ldb_strdup(ldb, "0"); if (!val.data) { - free(el.name); - free(msg.dn); + ldb_free(ldb, el.name); + ldb_free(ldb, msg.dn); errno = ENOMEM; return -1; } @@ -75,9 +75,9 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) ret = ltdb_store(ldb, &msg, TDB_INSERT); - free(msg.dn); - free(el.name); - free(val.data); + ldb_free(ldb, msg.dn); + ldb_free(ldb, el.name); + ldb_free(ldb, val.data); return ret; } @@ -88,6 +88,8 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) void ltdb_cache_free(struct ldb_context *ldb) { struct ltdb_private *ltdb = ldb->private_data; + struct ldb_alloc_ops alloc = ldb->alloc_ops; + ldb->alloc_ops.alloc = NULL; ltdb->sequence_number = 0; ltdb_search_dn1_free(ldb, <db->cache.baseinfo); @@ -95,8 +97,10 @@ void ltdb_cache_free(struct ldb_context *ldb) ltdb_search_dn1_free(ldb, <db->cache.subclasses); ltdb_search_dn1_free(ldb, <db->cache.attributes); - if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + ldb_free(ldb, ltdb->cache.last_attribute.name); memset(<db->cache, 0, sizeof(ltdb->cache)); + + ldb->alloc_ops = alloc; } /* @@ -106,20 +110,23 @@ int ltdb_cache_load(struct ldb_context *ldb) { struct ltdb_private *ltdb = ldb->private_data; double seq; + struct ldb_alloc_ops alloc = ldb->alloc_ops; + + ldb->alloc_ops.alloc = NULL; ltdb_search_dn1_free(ldb, <db->cache.baseinfo); if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { - return -1; + goto failed; } /* possibly initialise the baseinfo */ if (!ltdb->cache.baseinfo.dn) { if (ltdb_baseinfo_init(ldb) != 0) { - return -1; + goto failed; } if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { - return -1; + goto failed; } } @@ -127,11 +134,11 @@ int ltdb_cache_load(struct ldb_context *ldb) in the database then assume the rest of the cache is OK */ seq = ldb_msg_find_double(<db->cache.baseinfo, LTDB_SEQUENCE_NUMBER, 0); if (seq == ltdb->sequence_number) { - return 0; + goto done; } ltdb->sequence_number = seq; - if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + ldb_free(ldb, ltdb->cache.last_attribute.name); memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute)); ltdb_search_dn1_free(ldb, <db->cache.indexlist); @@ -139,16 +146,22 @@ int ltdb_cache_load(struct ldb_context *ldb) ltdb_search_dn1_free(ldb, <db->cache.attributes); if (ltdb_search_dn1(ldb, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { - return -1; + goto failed; } if (ltdb_search_dn1(ldb, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { - return -1; + goto failed; } if (ltdb_search_dn1(ldb, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { - return -1; + goto failed; } +done: + ldb->alloc_ops = alloc; return 0; + +failed: + ldb->alloc_ops = alloc; + return -1; } @@ -164,7 +177,7 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) char *s = NULL; int ret; - asprintf(&s, "%.0f", ltdb->sequence_number+1); + ldb_asprintf(ldb, &s, "%.0f", ltdb->sequence_number+1); if (!s) { errno = ENOMEM; return -1; @@ -172,8 +185,8 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) msg.num_elements = 1; msg.elements = ⪙ - msg.dn = strdup(LTDB_BASEINFO); - el.name = strdup(LTDB_SEQUENCE_NUMBER); + msg.dn = ldb_strdup(ldb, LTDB_BASEINFO); + el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER); el.values = &val; el.num_values = 1; el.flags = LDB_FLAG_MOD_REPLACE; @@ -182,9 +195,9 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) ret = ltdb_modify_internal(ldb, &msg); - free(s); - free(msg.dn); - free(el.name); + ldb_free(ldb, s); + ldb_free(ldb, msg.dn); + ldb_free(ldb, el.name); if (ret == 0) { ltdb->sequence_number += 1; @@ -244,9 +257,9 @@ int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) attrs += strspn(attrs, " ,"); } - if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + if (ltdb->cache.last_attribute.name) ldb_free(ldb, ltdb->cache.last_attribute.name); - ltdb->cache.last_attribute.name = strdup(attr_name); + ltdb->cache.last_attribute.name = ldb_strdup(ldb, attr_name); ltdb->cache.last_attribute.flags = ret; return ret; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 0b9581e52f..07077281ce 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -43,32 +43,33 @@ struct dn_list { /* free a struct dn_list */ -static void dn_list_free(struct dn_list *list) +static void dn_list_free(struct ldb_context *ldb, struct dn_list *list) { int i; for (i=0;icount;i++) { - free(list->dn[i]); + ldb_free(ldb, list->dn[i]); } - if (list->dn) free(list->dn); + ldb_free(ldb, list->dn); } /* return the dn key to be used for an index caller frees */ -static char *ldb_dn_key(const char *attr, const struct ldb_val *value) +static char *ldb_dn_key(struct ldb_context *ldb, + const char *attr, const struct ldb_val *value) { char *ret = NULL; if (ldb_should_b64_encode(value)) { - char *vstr = ldb_base64_encode(value->data, value->length); + char *vstr = ldb_base64_encode(ldb, value->data, value->length); if (!vstr) return NULL; - asprintf(&ret, "%s:%s::%s", LTDB_INDEX, attr, vstr); - free(vstr); + ldb_asprintf(ldb, &ret, "%s:%s::%s", LTDB_INDEX, attr, vstr); + ldb_free(ldb, vstr); return ret; } - asprintf(&ret, "%s:%s:%s", LTDB_INDEX, attr, (char *)value->data); + ldb_asprintf(ldb, &ret, "%s:%s:%s", LTDB_INDEX, attr, (char *)value->data); return ret; } @@ -132,11 +133,11 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* the attribute is indexed. Pull the list of DNs that match the search criterion */ - dn = ldb_dn_key(tree->u.simple.attr, &tree->u.simple.value); + dn = ldb_dn_key(ldb, tree->u.simple.attr, &tree->u.simple.value); if (!dn) return -1; ret = ltdb_search_dn1(ldb, dn, &msg); - free(dn); + ldb_free(ldb, dn); if (ret == 0 || ret == -1) { return ret; } @@ -150,16 +151,16 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, el = &msg.elements[i]; - list->dn = malloc_array_p(char *, el->num_values); + list->dn = ldb_malloc_array_p(ldb, char *, el->num_values); if (!list->dn) { break; } for (j=0;jnum_values;j++) { list->dn[list->count] = - strdup((char *)el->values[j].data); + ldb_strdup(ldb, (char *)el->values[j].data); if (!list->dn[list->count]) { - dn_list_free(list); + dn_list_free(ldb, list); ltdb_search_dn1_free(ldb, &msg); return -1; } @@ -202,7 +203,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, struct ldb_parse_tree tree2; struct dn_list list2; tree2.operation = LDB_OP_SIMPLE; - tree2.u.simple.attr = strdup(LTDB_OBJECTCLASS); + tree2.u.simple.attr = ldb_strdup(ldb, LTDB_OBJECTCLASS); if (!tree2.u.simple.attr) { return -1; } @@ -214,10 +215,10 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, ret = 1; } else { list_union(list, &list2); - dn_list_free(&list2); + dn_list_free(ldb, &list2); } } - free(tree2.u.simple.attr); + ldb_free(ldb, tree2.u.simple.attr); } } } @@ -245,20 +246,21 @@ static int ltdb_index_dn_leaf(struct ldb_context *ldb, list = list & list2 relies on the lists being sorted */ -static int list_intersect(struct dn_list *list, const struct dn_list *list2) +static int list_intersect(struct ldb_context *ldb, + struct dn_list *list, const struct dn_list *list2) { struct dn_list list3; int i; if (list->count == 0 || list2->count == 0) { /* 0 & X == 0 */ - dn_list_free(list); + dn_list_free(ldb, list); return 0; } - list3.dn = malloc_array_p(char *, list->count); + list3.dn = ldb_malloc_array_p(ldb, char *, list->count); if (!list3.dn) { - dn_list_free(list); + dn_list_free(ldb, list); return -1; } list3.count = 0; @@ -269,11 +271,11 @@ static int list_intersect(struct dn_list *list, const struct dn_list *list2) list3.dn[list3.count] = list->dn[i]; list3.count++; } else { - free(list->dn[i]); + ldb_free(ldb, list->dn[i]); } } - free(list->dn); + ldb_free(ldb, list->dn); list->dn = list3.dn; list->count = list3.count; @@ -286,7 +288,8 @@ static int list_intersect(struct dn_list *list, const struct dn_list *list2) list = list | list2 relies on the lists being sorted */ -static int list_union(struct dn_list *list, const struct dn_list *list2) +static int list_union(struct ldb_context *ldb, + struct dn_list *list, const struct dn_list *list2) { int i; char **d; @@ -294,13 +297,13 @@ static int list_union(struct dn_list *list, const struct dn_list *list2) if (list->count == 0 && list2->count == 0) { /* 0 | 0 == 0 */ - dn_list_free(list); + dn_list_free(ldb, list); return 0; } - d = realloc_p(list->dn, char *, list->count + list2->count); + d = ldb_realloc_p(ldb, list->dn, char *, list->count + list2->count); if (!d) { - dn_list_free(list); + dn_list_free(ldb, list); return -1; } list->dn = d; @@ -308,9 +311,9 @@ static int list_union(struct dn_list *list, const struct dn_list *list2) for (i=0;icount;i++) { if (list_find(list2->dn[i], list->dn, count, sizeof(char *), (comparison_fn_t)strcmp) == -1) { - list->dn[list->count] = strdup(list2->dn[i]); + list->dn[list->count] = ldb_strdup(ldb, list2->dn[i]); if (!list->dn[list->count]) { - dn_list_free(list); + dn_list_free(ldb, list); return -1; } list->count++; @@ -359,7 +362,7 @@ static int ltdb_index_dn_or(struct ldb_context *ldb, if (v == -1) { /* 1 || X == 1 */ - dn_list_free(list); + dn_list_free(ldb, list); return -1; } @@ -367,16 +370,16 @@ static int ltdb_index_dn_or(struct ldb_context *ldb, ret = 1; *list = list2; } else { - if (list_union(list, &list2) == -1) { - dn_list_free(&list2); + if (list_union(ldb, list, &list2) == -1) { + dn_list_free(ldb, &list2); return -1; } - dn_list_free(&list2); + dn_list_free(ldb, &list2); } } if (list->count == 0) { - dn_list_free(list); + dn_list_free(ldb, list); return 0; } @@ -424,7 +427,7 @@ static int ltdb_index_dn_and(struct ldb_context *ldb, if (v == 0) { /* 0 && X == 0 */ - dn_list_free(list); + dn_list_free(ldb, list); return 0; } @@ -436,15 +439,15 @@ static int ltdb_index_dn_and(struct ldb_context *ldb, ret = 1; *list = list2; } else { - if (list_intersect(list, &list2) == -1) { - dn_list_free(&list2); + if (list_intersect(ldb, list, &list2) == -1) { + dn_list_free(ldb, &list2); return -1; } - dn_list_free(&list2); + dn_list_free(ldb, &list2); } if (list->count == 0) { - if (list->dn) free(list->dn); + if (list->dn) ldb_free(ldb, list->dn); return 0; } } @@ -550,7 +553,7 @@ int ltdb_search_indexed(struct ldb_context *ldb, and extract the needed attributes */ ret = ldb_index_filter(ldb, tree, base, scope, &dn_list, attrs, res); - dn_list_free(&dn_list); + dn_list_free(ldb, &dn_list); } return ret; @@ -567,18 +570,19 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, struct ldb_message_element *el2; /* add another entry */ - el2 = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + el2 = ldb_realloc_p(ldb, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!el2) { return -1; } msg->elements = el2; - msg->elements[msg->num_elements].name = strdup(LTDB_IDX); + msg->elements[msg->num_elements].name = ldb_strdup(ldb, LTDB_IDX); if (!msg->elements[msg->num_elements].name) { return -1; } msg->elements[msg->num_elements].num_values = 0; - msg->elements[msg->num_elements].values = malloc_p(struct ldb_val); + msg->elements[msg->num_elements].values = ldb_malloc_p(ldb, struct ldb_val); if (!msg->elements[msg->num_elements].values) { return -1; } @@ -611,9 +615,9 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, } } - v2 = realloc_p(msg->elements[idx].values, - struct ldb_val, - msg->elements[idx].num_values+1); + v2 = ldb_realloc_p(ldb, msg->elements[idx].values, + struct ldb_val, + msg->elements[idx].num_values+1); if (!v2) { return -1; } @@ -634,23 +638,24 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, { struct ldb_message msg; char *dn_key; - int ret, i, added=0; + int ret, i, added=0, added_dn=0; - dn_key = ldb_dn_key(el->name, &el->values[v_idx]); + dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); if (!dn_key) { return -1; } ret = ltdb_search_dn1(ldb, dn_key, &msg); if (ret == -1) { - free(dn_key); + ldb_free(ldb, dn_key); return -1; } if (ret == 0) { - msg.dn = strdup(dn_key); + added_dn = 1; + msg.dn = ldb_strdup(ldb, dn_key); if (!msg.dn) { - free(dn_key); + ldb_free(ldb, dn_key); errno = ENOMEM; return -1; } @@ -659,7 +664,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, msg.private_data = NULL; } - free(dn_key); + ldb_free(ldb, dn_key); for (i=0;iname, &el->values[v_idx]); + dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); if (!dn_key) { return -1; } ret = ltdb_search_dn1(ldb, dn_key, &msg); if (ret == -1) { - free(dn_key); + ldb_free(ldb, dn_key); return -1; } @@ -743,6 +751,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, /* it wasn't indexed. Did we have an earlier error? If we did then its gone now */ ltdb_search_dn1_free(ldb, &msg); + ldb_free(ldb, dn_key); return 0; } @@ -750,6 +759,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, if (i == -1) { /* it ain't there. hmmm */ ltdb_search_dn1_free(ldb, &msg); + ldb_free(ldb, dn_key); return 0; } @@ -768,6 +778,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, } ltdb_search_dn1_free(ldb, &msg); + ldb_free(ldb, dn_key); return ret; } @@ -841,7 +852,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * ret = ltdb_index_add(ldb, &msg); - ltdb_unpack_data_free(&msg); + ltdb_unpack_data_free(ldb, &msg); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 26e0eebfe7..80d147cb43 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -71,7 +71,8 @@ static int ldb_val_equal_case_insensitive(const struct ldb_val *v1, and case insensitive return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_wildcard_ci(const struct ldb_val *v1, +static int ldb_val_equal_wildcard_ci(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) { char *s1, *s2; @@ -81,20 +82,20 @@ static int ldb_val_equal_wildcard_ci(const struct ldb_val *v1, return v1->data == v2->data; } - s1 = ldb_casefold(v1->data); + s1 = ldb_casefold(ldb, v1->data); if (!s1) { return -1; } - s2 = ldb_casefold(v2->data); + s2 = ldb_casefold(ldb, v2->data); if (!s2) { return -1; } ret = fnmatch(s2, s1, 0); - free(s1); - free(s2); + ldb_free(ldb, s1); + ldb_free(ldb, s2); if (ret == 0) { return 1; @@ -107,12 +108,13 @@ static int ldb_val_equal_wildcard_ci(const struct ldb_val *v1, see if two ldb_val structures contain the same data with wildcards return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_wildcard(const struct ldb_val *v1, +static int ldb_val_equal_wildcard(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2, int flags) { if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - return ldb_val_equal_wildcard_ci(v1, v2); + return ldb_val_equal_wildcard_ci(ldb, v1, v2); } if (!v1->data || !v2->data) { return v1->data == v2->data; @@ -182,7 +184,7 @@ int ldb_val_equal(struct ldb_context *ldb, } if (flags & LTDB_FLAG_WILDCARD) { - return ldb_val_equal_wildcard(v1, v2, flags); + return ldb_val_equal_wildcard(ldb, v1, v2, flags); } if (flags & LTDB_FLAG_CASE_INSENSITIVE) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 3ded595259..a32197e2cf 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -49,7 +49,7 @@ caller frees the data buffer after use */ -int ltdb_pack_data(struct ldb_context *ctx, +int ltdb_pack_data(struct ldb_context *ldb, const struct ldb_message *message, struct TDB_DATA *data) { @@ -74,7 +74,7 @@ int ltdb_pack_data(struct ldb_context *ctx, } /* allocate it */ - data->dptr = malloc(size); + data->dptr = ldb_malloc(ldb, size); if (!data->dptr) { errno = ENOMEM; return -1; @@ -116,14 +116,15 @@ int ltdb_pack_data(struct ldb_context *ctx, /* free the memory allocated from a ltdb_unpack_data() */ -void ltdb_unpack_data_free(struct ldb_message *message) +void ltdb_unpack_data_free(struct ldb_context *ldb, + struct ldb_message *message) { int i; for (i=0;inum_elements;i++) { - if (message->elements[i].values) free(message->elements[i].values); + if (message->elements[i].values) ldb_free(ldb, message->elements[i].values); } - if (message->elements) free(message->elements); + if (message->elements) ldb_free(ldb, message->elements); } @@ -137,7 +138,7 @@ void ltdb_unpack_data_free(struct ldb_message *message) TDB_DATA data. This means the caller only has to free the elements and values arrays. This can be done with ltdb_unpack_data_free() */ -int ltdb_unpack_data(struct ldb_context *ctx, +int ltdb_unpack_data(struct ldb_context *ldb, const struct TDB_DATA *data, struct ldb_message *message) { @@ -192,8 +193,8 @@ int ltdb_unpack_data(struct ldb_context *ctx, goto failed; } - message->elements = malloc_array_p(struct ldb_message_element, - message->num_elements); + message->elements = ldb_malloc_array_p(ldb, struct ldb_message_element, + message->num_elements); if (!message->elements) { errno = ENOMEM; @@ -217,8 +218,9 @@ int ltdb_unpack_data(struct ldb_context *ctx, message->elements[i].num_values = IVAL(p, 0); message->elements[i].values = NULL; if (message->elements[i].num_values != 0) { - message->elements[i].values = malloc_array_p(struct ldb_val, - message->elements[i].num_values); + message->elements[i].values = ldb_malloc_array_p(ldb, + struct ldb_val, + message->elements[i].num_values); if (!message->elements[i].values) { errno = ENOMEM; goto failed; @@ -242,7 +244,7 @@ int ltdb_unpack_data(struct ldb_context *ctx, return 0; failed: - ltdb_unpack_data_free(message); + ltdb_unpack_data_free(ldb, message); return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 1dce8f83a2..5ee4449dee 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -38,27 +38,27 @@ /* free a message that has all parts separately allocated */ -static void msg_free_all_parts(struct ldb_message *msg) +static void msg_free_all_parts(struct ldb_context *ldb, struct ldb_message *msg) { int i, j; - if (msg->dn) free(msg->dn); + ldb_free(ldb, msg->dn); for (i=0;inum_elements;i++) { - if (msg->elements[i].name) free(msg->elements[i].name); + ldb_free(ldb, msg->elements[i].name); for (j=0;jelements[i].num_values;j++) { - if (msg->elements[i].values[j].data) - free(msg->elements[i].values[j].data); + ldb_free(ldb, msg->elements[i].values[j].data); } - if (msg->elements[i].values) free(msg->elements[i].values); + ldb_free(ldb, msg->elements[i].values); } - free(msg->elements); - free(msg); + ldb_free(ldb, msg->elements); + ldb_free(ldb, msg); } /* duplicate a ldb_val structure */ -struct ldb_val ldb_val_dup(const struct ldb_val *v) +struct ldb_val ldb_val_dup(struct ldb_context *ldb, + const struct ldb_val *v) { struct ldb_val v2; v2.length = v->length; @@ -69,7 +69,7 @@ struct ldb_val ldb_val_dup(const struct ldb_val *v) /* the +1 is to cope with buggy C library routines like strndup that look one byte beyond */ - v2.data = malloc(v->length+1); + v2.data = ldb_malloc(ldb, v->length+1); if (!v2.data) { v2.length = 0; return v2; @@ -85,12 +85,13 @@ struct ldb_val ldb_val_dup(const struct ldb_val *v) /* add one element to a message */ -static int msg_add_element(struct ldb_message *ret, const struct ldb_message_element *el) +static int msg_add_element(struct ldb_context *ldb, + struct ldb_message *ret, const struct ldb_message_element *el) { int i; struct ldb_message_element *e2, *elnew; - e2 = realloc_p(ret->elements, struct ldb_message_element, ret->num_elements+1); + e2 = ldb_realloc_p(ldb, ret->elements, struct ldb_message_element, ret->num_elements+1); if (!e2) { return -1; } @@ -98,13 +99,13 @@ static int msg_add_element(struct ldb_message *ret, const struct ldb_message_ele elnew = &e2[ret->num_elements]; - elnew->name = strdup(el->name); + elnew->name = ldb_strdup(ldb, el->name); if (!elnew->name) { return -1; } if (el->num_values) { - elnew->values = malloc_array_p(struct ldb_val, el->num_values); + elnew->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values); if (!elnew->values) { return -1; } @@ -113,7 +114,7 @@ static int msg_add_element(struct ldb_message *ret, const struct ldb_message_ele } for (i=0;inum_values;i++) { - elnew->values[i] = ldb_val_dup(&el->values[i]); + elnew->values[i] = ldb_val_dup(ldb, &el->values[i]); if (elnew->values[i].length != el->values[i].length) { return -1; } @@ -129,12 +130,12 @@ static int msg_add_element(struct ldb_message *ret, const struct ldb_message_ele /* add all elements from one message into another */ -static int msg_add_all_elements(struct ldb_message *ret, +static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret, const struct ldb_message *msg) { int i; for (i=0;inum_elements;i++) { - if (msg_add_element(ret, &msg->elements[i]) != 0) { + if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { return -1; } } @@ -153,14 +154,14 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, struct ldb_message *ret; int i; - ret = malloc_p(struct ldb_message); + ret = ldb_malloc_p(ldb, struct ldb_message); if (!ret) { return NULL; } - ret->dn = strdup(msg->dn); + ret->dn = ldb_strdup(ldb, msg->dn); if (!ret->dn) { - free(ret); + ldb_free(ldb, ret); return NULL; } @@ -169,8 +170,8 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, ret->private_data = NULL; if (!attrs) { - if (msg_add_all_elements(ret, msg) != 0) { - msg_free_all_parts(ret); + if (msg_add_all_elements(ldb, ret, msg) != 0) { + msg_free_all_parts(ldb, ret); return NULL; } return ret; @@ -180,8 +181,8 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, struct ldb_message_element *el; if (strcmp(attrs[i], "*") == 0) { - if (msg_add_all_elements(ret, msg) != 0) { - msg_free_all_parts(ret); + if (msg_add_all_elements(ldb, ret, msg) != 0) { + msg_free_all_parts(ldb, ret); return NULL; } continue; @@ -191,8 +192,8 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, if (!el) { continue; } - if (msg_add_element(ret, el) != 0) { - msg_free_all_parts(ret); + if (msg_add_element(ldb, ret, el) != 0) { + msg_free_all_parts(ldb, ret); return NULL; } } @@ -235,11 +236,11 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { int i; - if (msg->private_data) free(msg->private_data); + ldb_free(ldb, msg->private_data); for (i=0;inum_elements;i++) { - if (msg->elements[i].values) free(msg->elements[i].values); + ldb_free(ldb, msg->elements[i].values); } - if (msg->elements) free(msg->elements); + ldb_free(ldb, msg->elements); memset(msg, 0, sizeof(*msg)); } @@ -254,7 +255,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message { struct ltdb_private *ltdb = ldb->private_data; int ret; - TDB_DATA tdb_key, tdb_data; + TDB_DATA tdb_key, tdb_data, tdb_data2; /* form the key */ tdb_key = ltdb_key(ldb, dn); @@ -263,26 +264,35 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); if (!tdb_data.dptr) { return 0; } - msg->private_data = tdb_data.dptr; + tdb_data2.dptr = ldb_malloc(ldb, tdb_data.dsize); + if (!tdb_data2.dptr) { + free(tdb_data.dptr); + return -1; + } + memcpy(tdb_data2.dptr, tdb_data.dptr, tdb_data.dsize); + free(tdb_data.dptr); + tdb_data2.dsize = tdb_data.dsize; + + msg->private_data = tdb_data2.dptr; msg->num_elements = 0; msg->elements = NULL; - ret = ltdb_unpack_data(ldb, &tdb_data, msg); + ret = ltdb_unpack_data(ldb, &tdb_data2, msg); if (ret == -1) { - free(tdb_data.dptr); + free(tdb_data2.dptr); return -1; } if (!msg->dn) { - msg->dn = strdup(dn); + msg->dn = ldb_strdup(ldb, dn); } if (!msg->dn) { - free(tdb_data.dptr); + ldb_free(ldb, tdb_data2.dptr); return -1; } @@ -312,9 +322,9 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, return -1; } - *res = malloc_array_p(struct ldb_message *, 2); + *res = ldb_malloc_array_p(ldb, struct ldb_message *, 2); if (! *res) { - msg_free_all_parts(msg2); + msg_free_all_parts(ldb, msg2); return -1; } @@ -344,9 +354,9 @@ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, } /* add to the results list */ - res2 = realloc_p(*res, struct ldb_message *, (*count)+2); + res2 = ldb_realloc_p(ldb, *res, struct ldb_message *, (*count)+2); if (!res2) { - msg_free_all_parts(msg2); + msg_free_all_parts(ldb, msg2); return -1; } @@ -403,7 +413,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi /* see if it matches the given expression */ if (!ldb_message_match(sinfo->ldb, &msg, sinfo->tree, sinfo->base, sinfo->scope)) { - ltdb_unpack_data_free(&msg); + ltdb_unpack_data_free(sinfo->ldb, &msg); return 0; } @@ -413,7 +423,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi sinfo->failures++; } - ltdb_unpack_data_free(&msg); + ltdb_unpack_data_free(sinfo->ldb, &msg); return ret; } @@ -424,15 +434,18 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi */ int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) { + struct ltdb_private *ltdb = ldb->private_data; int i; + ltdb->last_err_string = NULL; + if (!msgs) return 0; for (i=0;msgs[i];i++) { - msg_free_all_parts(msgs[i]); + msg_free_all_parts(ldb, msgs[i]); } - free(msgs); + ldb_free(ldb, msgs); return 0; } @@ -480,9 +493,12 @@ int ltdb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, char * const attrs[], struct ldb_message ***res) { + struct ltdb_private *ltdb = ldb->private_data; struct ldb_parse_tree *tree; int ret; + ltdb->last_err_string = NULL; + if (ltdb_cache_load(ldb) != 0) { return -1; } @@ -490,8 +506,9 @@ int ltdb_search(struct ldb_context *ldb, const char *base, *res = NULL; /* form a parse tree for the expression */ - tree = ldb_parse_tree(expression); + tree = ldb_parse_tree(ldb, expression); if (!tree) { + ltdb->last_err_string = "expression parse failed"; return -1; } @@ -507,7 +524,7 @@ int ltdb_search(struct ldb_context *ldb, const char *base, } } - ldb_parse_tree_free(tree); + ldb_parse_tree_free(ldb, tree); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index c674f0c27e..eb28bc4938 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -67,35 +67,35 @@ struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn) if (strncmp(dn, prefix, strlen(prefix)) == 0 && (s = strchr(dn+strlen(prefix), ':'))) { char *attr_name, *attr_name_folded; - attr_name = strndup(dn+strlen(prefix), (s-(dn+strlen(prefix)))); + attr_name = ldb_strndup(ldb, dn+strlen(prefix), (s-(dn+strlen(prefix)))); if (!attr_name) { goto failed; } flags = ltdb_attribute_flags(ldb, attr_name); if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - dn_folded = ldb_casefold(dn); + dn_folded = ldb_casefold(ldb, dn); } else { - attr_name_folded = ldb_casefold(attr_name); + attr_name_folded = ldb_casefold(ldb, attr_name); if (!attr_name_folded) { goto failed; } - asprintf(&dn_folded, "%s:%s:%s", + ldb_asprintf(ldb, &dn_folded, "%s:%s:%s", prefix, attr_name_folded, s+1); - free(attr_name_folded); + ldb_free(ldb, attr_name_folded); } - free(attr_name); + ldb_free(ldb, attr_name); } else { - dn_folded = ldb_casefold(dn); + dn_folded = ldb_casefold(ldb, dn); } if (!dn_folded) { goto failed; } - asprintf(&key_str, "DN=%s", dn_folded); - free(dn_folded); + ldb_asprintf(ldb, &key_str, "DN=%s", dn_folded); + ldb_free(ldb, dn_folded); if (!key_str) { goto failed; @@ -129,7 +129,7 @@ static int ltdb_lock(struct ldb_context *ldb) ret = tdb_chainlock(ltdb->tdb, key); - free(key.dptr); + ldb_free(ldb, key.dptr); return ret; } @@ -149,7 +149,7 @@ static void ltdb_unlock(struct ldb_context *ldb) tdb_chainunlock(ltdb->tdb, key); - free(key.dptr); + ldb_free(ldb, key.dptr); } @@ -190,7 +190,7 @@ int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) ret = ltdb_pack_data(ldb, msg, &tdb_data); if (ret == -1) { - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); return -1; } @@ -205,8 +205,8 @@ int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) } done: - free(tdb_key.dptr); - free(tdb_data.dptr); + ldb_free(ldb, tdb_key.dptr); + ldb_free(ldb, tdb_data.dptr); return ret; } @@ -217,8 +217,11 @@ done: */ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) { + struct ltdb_private *ltdb = ldb->private_data; int ret; + ltdb->last_err_string = NULL; + if (ltdb_lock(ldb) != 0) { return -1; } @@ -255,7 +258,7 @@ int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) } ret = tdb_delete(ltdb->tdb, tdb_key); - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); return ret; } @@ -265,9 +268,12 @@ int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) */ static int ltdb_delete(struct ldb_context *ldb, const char *dn) { + struct ltdb_private *ltdb = ldb->private_data; int ret; struct ldb_message msg; + ltdb->last_err_string = NULL; + if (ltdb_lock(ldb) != 0) { return -1; } @@ -335,12 +341,13 @@ static int find_element(const struct ldb_message *msg, const char *name) returns 0 on success, -1 on failure (and sets errno) */ -static int msg_add_element(struct ldb_message *msg, struct ldb_message_element *el) +static int msg_add_element(struct ldb_context *ldb, + struct ldb_message *msg, struct ldb_message_element *el) { struct ldb_message_element *e2; int i; - e2 = realloc_p(msg->elements, struct ldb_message_element, + e2 = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!e2) { errno = ENOMEM; @@ -355,7 +362,7 @@ static int msg_add_element(struct ldb_message *msg, struct ldb_message_element * e2->flags = el->flags; e2->values = NULL; if (el->num_values != 0) { - e2->values = malloc_array_p(struct ldb_val, el->num_values); + e2->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values); if (!e2->values) { free(e2->name); errno = ENOMEM; @@ -375,12 +382,13 @@ static int msg_add_element(struct ldb_message *msg, struct ldb_message_element * /* delete all elements having a specified attribute name */ -static int msg_delete_attribute(struct ldb_message *msg, const char *name) +static int msg_delete_attribute(struct ldb_context *ldb, + struct ldb_message *msg, const char *name) { int i, count=0; struct ldb_message_element *el2; - el2 = malloc_array_p(struct ldb_message_element, msg->num_elements); + el2 = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); if (!el2) { errno = ENOMEM; return -1; @@ -390,12 +398,12 @@ static int msg_delete_attribute(struct ldb_message *msg, const char *name) if (ldb_attr_cmp(msg->elements[i].name, name) != 0) { el2[count++] = msg->elements[i]; } else { - if (msg->elements[i].values) free(msg->elements[i].values); + ldb_free(ldb, msg->elements[i].values); } } msg->num_elements = count; - if (msg->elements) free(msg->elements); + ldb_free(ldb, msg->elements); msg->elements = el2; return 0; @@ -425,7 +433,7 @@ static int msg_delete_element(struct ldb_context *ldb, if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], - sizeof(el->values[i])*el->num_values-(i+1)); + sizeof(el->values[i])*(el->num_values-(i+1))); } el->num_values--; return 0; @@ -463,7 +471,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) ret = ltdb_unpack_data(ldb, &tdb_data, &msg2); if (ret == -1) { - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); return -1; } @@ -483,7 +491,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) errno = EEXIST; goto failed; } - if (msg_add_element(&msg2, &msg->elements[i]) != 0) { + if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { goto failed; } break; @@ -491,11 +499,11 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) case LDB_FLAG_MOD_REPLACE: /* replace all elements of this attribute name with the elements listed */ - if (msg_delete_attribute(&msg2, msg->elements[i].name) != 0) { + if (msg_delete_attribute(ldb, &msg2, msg->elements[i].name) != 0) { goto failed; } /* add the replacement element */ - if (msg_add_element(&msg2, &msg->elements[i]) != 0) { + if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { goto failed; } break; @@ -504,8 +512,8 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) /* we could be being asked to delete all values or just some values */ if (msg->elements[i].num_values == 0) { - if (msg_delete_attribute(&msg2, - msg->elements[i].name) != 0) { + if (msg_delete_attribute(ldb, &msg2, + msg->elements[i].name) != 0) { goto failed; } break; @@ -525,15 +533,15 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) /* we've made all the mods - save the modified record back into the database */ ret = ltdb_store(ldb, &msg2, TDB_MODIFY); - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(&msg2); + ltdb_unpack_data_free(ldb, &msg2); return ret; failed: - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(&msg2); + ltdb_unpack_data_free(ldb, &msg2); return -1; } @@ -542,8 +550,11 @@ failed: */ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) { + struct ltdb_private *ltdb = ldb->private_data; int ret; + ltdb->last_err_string = NULL; + if (ltdb_lock(ldb) != 0) { return -1; } @@ -572,10 +583,13 @@ static int ltdb_close(struct ldb_context *ldb) struct ltdb_private *ltdb = ldb->private_data; int ret; + ltdb->last_err_string = NULL; + ltdb_cache_free(ldb); + ldb_set_alloc(ldb, NULL, NULL); ret = tdb_close(ltdb->tdb); - free(ltdb); + ldb_free(ldb, ltdb); free(ldb); return ret; } @@ -587,6 +601,9 @@ static int ltdb_close(struct ldb_context *ldb) static const char *ltdb_errstring(struct ldb_context *ldb) { struct ltdb_private *ltdb = ldb->private_data; + if (ltdb->last_err_string) { + return ltdb->last_err_string; + } return tdb_errorstr(ltdb->tdb); } @@ -598,7 +615,8 @@ static const struct ldb_backend_ops ltdb_ops = { ltdb_add, ltdb_modify, ltdb_delete, - ltdb_errstring + ltdb_errstring, + ltdb_cache_free }; @@ -615,6 +633,12 @@ struct ldb_context *ltdb_connect(const char *url, TDB_CONTEXT *tdb; struct ldb_context *ldb; + ldb = calloc(1, sizeof(struct ldb_context)); + if (!ldb) { + errno = ENOMEM; + return NULL; + } + /* parse the url */ if (strchr(url, ':')) { if (strncmp(url, "tdb://", 6) != 0) { @@ -637,12 +661,14 @@ struct ldb_context *ltdb_connect(const char *url, /* note that we use quite a large default hash size */ tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); if (!tdb) { + free(ldb); return NULL; } - ltdb = malloc_p(struct ltdb_private); + ltdb = ldb_malloc_p(ldb, struct ltdb_private); if (!ltdb) { tdb_close(tdb); + free(ldb); errno = ENOMEM; return NULL; } @@ -652,14 +678,6 @@ struct ldb_context *ltdb_connect(const char *url, memset(<db->cache, 0, sizeof(ltdb->cache)); - ldb = malloc_p(struct ldb_context); - if (!ldb) { - tdb_close(tdb); - free(ltdb); - errno = ENOMEM; - return NULL; - } - ldb->private_data = ltdb; ldb->ops = <db_ops; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index e87027db63..c791cbe201 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -19,6 +19,9 @@ struct ltdb_private { int flags; } last_attribute; } cache; + + /* error if an internal ldb+tdb error */ + const char *last_err_string; }; /* special record types */ diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 794b451074..6db57967df 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -1,17 +1,17 @@ echo "Adding base elements" -bin/ldbadd tests/test.ldif || exit 1 +$VALGRIND bin/ldbadd tests/test.ldif || exit 1 echo "Modifying elements" -bin/ldbmodify tests/test-modify.ldif || exit 1 +$VALGRIND bin/ldbmodify tests/test-modify.ldif || exit 1 echo "Showing modified record" -bin/ldbsearch '(uid=uham)' || exit 1 +$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 echo "Starting ldbtest" -time bin/ldbtest -r 1000 -s 100 || exit 1 +time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 echo "Adding index" -bin/ldbadd tests/test-index.ldif || exit 1 +$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 echo "Starting ldbtest indexed" -time bin/ldbtest -r 1000 -s 5000 || exit 1 +time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 15febb76e7..6d89f67e0f 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -55,7 +55,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) struct ldb_ldif *ldif; int ret, count=0; - while ((ldif = ldif_read_file(f))) { + while ((ldif = ldif_read_file(ldb, f))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); @@ -70,7 +70,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } else { count++; } - ldif_read_free(ldif); + ldif_read_free(ldb, ldif); } return count; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index eb95ed3267..57c54cad40 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -60,7 +60,7 @@ static int modify_record(struct ldb_context *ldb, continue; } - if (ldb_msg_add(&mod, + if (ldb_msg_add(ldb, &mod, &msg2->elements[i], el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { return -1; @@ -72,7 +72,7 @@ static int modify_record(struct ldb_context *ldb, for (i=0;inum_elements;i++) { el = ldb_msg_find_element(msg2, msg1->elements[i].name); if (!el) { - if (ldb_msg_add_empty(&mod, + if (ldb_msg_add_empty(ldb, &mod, msg1->elements[i].name, LDB_FLAG_MOD_DELETE) != 0) { return -1; @@ -159,7 +159,8 @@ static int merge_edits(struct ldb_context *ldb, /* save a set of messages as ldif to a file */ -static int save_ldif(FILE *f, struct ldb_message **msgs, int count) +static int save_ldif(struct ldb_context *ldb, + FILE *f, struct ldb_message **msgs, int count) { int i; @@ -172,7 +173,7 @@ static int save_ldif(FILE *f, struct ldb_message **msgs, int count) ldif.changetype = LDB_CHANGETYPE_NONE; ldif.msg = *msgs[i]; - ldif_write_file(f, &ldif); + ldif_write_file(ldb, f, &ldif); } return 0; @@ -211,13 +212,13 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun return -1; } - if (save_ldif(f, msgs1, count1) != 0) { + if (save_ldif(ldb, f, msgs1, count1) != 0) { return -1; } fclose(f); - asprintf(&cmd, "%s %s", editor, template); + ldb_asprintf(ldb, &cmd, "%s %s", editor, template); if (!cmd) { unlink(template); @@ -242,8 +243,8 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun return -1; } - while ((ldif = ldif_read_file(f))) { - msgs2 = realloc_p(msgs2, struct ldb_message *, count2+1); + while ((ldif = ldif_read_file(ldb, f))) { + msgs2 = ldb_realloc_p(ldb, msgs2, struct ldb_message *, count2+1); if (!msgs2) { fprintf(stderr, "out of memory"); return -1; diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index bc29369a5c..6ac8e366c7 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -54,7 +54,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) struct ldb_ldif *ldif; int ret = -1, count = 0; - while ((ldif = ldif_read_file(f))) { + while ((ldif = ldif_read_file(ldb, f))) { switch (ldif->changetype) { case LDB_CHANGETYPE_NONE: case LDB_CHANGETYPE_ADD: @@ -74,7 +74,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } else { count++; } - ldif_read_free(ldif); + ldif_read_free(ldb, ldif); } return count; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 541024dd2d..edda31b793 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -45,11 +45,11 @@ static void usage(void) exit(1); } -static void do_search(struct ldb_context *ldb, - const char *basedn, - int scope, - const char *expression, - char * const *attrs) +static int do_search(struct ldb_context *ldb, + const char *basedn, + int scope, + const char *expression, + char * const *attrs) { int ret, i; struct ldb_message **msgs; @@ -57,7 +57,7 @@ static void do_search(struct ldb_context *ldb, ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); if (ret == -1) { printf("search failed - %s\n", ldb_errstring(ldb)); - return; + return -1; } printf("# returned %d records\n", ret); @@ -69,7 +69,7 @@ static void do_search(struct ldb_context *ldb, ldif.changetype = LDB_CHANGETYPE_NONE; ldif.msg = *msgs[i]; - ldif_write_file(stdout, &ldif); + ldif_write_file(ldb, stdout, &ldif); } if (ret > 0) { @@ -79,6 +79,8 @@ static void do_search(struct ldb_context *ldb, exit(1); } } + + return 0; } int main(int argc, char * const argv[]) @@ -89,7 +91,7 @@ static void do_search(struct ldb_context *ldb, const char *basedn = NULL; int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; - int interactive = 0; + int interactive = 0, ret=0; ldb_url = getenv("LDB_URL"); @@ -150,12 +152,14 @@ static void do_search(struct ldb_context *ldb, if (interactive) { char line[1024]; while (fgets(line, sizeof(line), stdin)) { - do_search(ldb, basedn, scope, line, attrs); + if (do_search(ldb, basedn, scope, line, attrs) == -1) { + ret = -1; + } } } else { - do_search(ldb, basedn, scope, argv[0], attrs); + ret = do_search(ldb, basedn, scope, argv[0], attrs); } ldb_close(ldb); - return 0; + return ret; } diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index bcb8bdcb16..e7db767387 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -84,7 +84,7 @@ static void add_records(struct ldb_context *ldb, el[2].name = "uid"; el[2].num_values = 1; el[2].values = vals[2]; - vals[2][0].data = ldb_casefold(name); + vals[2][0].data = ldb_casefold(ldb, name); vals[2][0].length = strlen(vals[2][0].data); el[3].flags = 0; @@ -121,7 +121,7 @@ static void add_records(struct ldb_context *ldb, free(name); free(msg.dn); free(vals[1][0].data); - free(vals[2][0].data); + ldb_free(ldb, vals[2][0].data); free(vals[3][0].data); } -- cgit From 9261ceb89e3394da3d41197354a7da723678187e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 May 2004 04:45:29 +0000 Subject: r504: fixed a bad call to list_union() (This used to be commit 4404056cd5fd65d72a38ea474fe330281b3ee19e) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 07077281ce..877955a9b7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -188,7 +188,8 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, int i; int ret; const char *target = tree->u.simple.value.data; - static int list_union(struct dn_list *, const struct dn_list *); + static int list_union(struct ldb_context *, + struct dn_list *, const struct dn_list *); list->count = 0; list->dn = NULL; @@ -214,7 +215,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, *list = list2; ret = 1; } else { - list_union(list, &list2); + list_union(ldb, list, &list2); dn_list_free(ldb, &list2); } } -- cgit From cec1bc8fd71511a35de652dbc2a688df0770e2f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 May 2004 05:53:35 +0000 Subject: r507: the new ldb code will use talloc_free() a lot, so I have made talloc_free() O(1) in preparation. This also halves the number of malloc() calls and increases our internal consistency checking, without breaking valgrind testing. (This used to be commit 2331d4e76e40ff08215853f747f7063213ac92ce) --- source4/lib/talloc.c | 288 +++++++++++++++++++++++++++------------------------ 1 file changed, 151 insertions(+), 137 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 59d4eac500..92e0d52d2d 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -33,20 +33,11 @@ 3) when _all_ of the memory allocated using this context is no longer needed use talloc_destroy() - talloc does not zero the memory. It guarantees memory of a - TALLOC_ALIGN alignment + talloc does not zero the memory. @sa talloc.h */ -/** - * @todo We could allocate both the talloc_chunk structure, and the - * memory it contains all in one allocation, which might be a bit - * faster and perhaps use less memory overhead. - * - * That smells like a premature optimization, though. -- mbp - **/ - /** * If you want testing for memory corruption use valgrind **/ @@ -54,11 +45,15 @@ #include "includes.h" #define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC 0x06052004 +#define TALLOC_MAGIC_FREE 0x3421abcd struct talloc_chunk { - struct talloc_chunk *next; + struct talloc_chunk *next, *prev; + TALLOC_CTX *context; size_t size; void *ptr; + unsigned magic; }; @@ -160,26 +155,26 @@ static TALLOC_CTX *talloc_init_internal(void) /** Allocate a bit of memory from the specified pool **/ void *talloc(TALLOC_CTX *t, size_t size) { - void *p; struct talloc_chunk *tc; - if (!t || size == 0) return NULL; + if (!t || size == 0) { + return NULL; + } - p = malloc(size); - if (p) { - tc = malloc(sizeof(*tc)); - if (tc) { - tc->ptr = p; - tc->size = size; - tc->next = t->list; - t->list = tc; - t->total_alloc_size += size; - } - else { - SAFE_FREE(p); - } + tc = malloc(sizeof(*tc)+size); + if (!tc) { + return NULL; } - return p; + + tc->context = t; + tc->size = size; + tc->magic = TALLOC_MAGIC; + + DLIST_ADD(t->list, tc); + + t->total_alloc_size += size; + + return (void *)(tc+1); } /** A talloc version of realloc */ @@ -199,37 +194,134 @@ void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size) } /* realloc(NULL) is equavalent to malloc() */ - if (ptr == NULL) + if (ptr == NULL) { return talloc(t, size); + } - for (tc=t->list; tc; tc=tc->next) { - if (tc->ptr == ptr) { - new_ptr = Realloc(ptr, size); - if (new_ptr) { - t->total_alloc_size += (size - tc->size); - tc->size = size; - tc->ptr = new_ptr; - } - return new_ptr; - } + tc = ((struct talloc_chunk *)ptr)-1; + + if (tc->context != t) { + DEBUG(0,("Bad talloc context passed to talloc_realloc\n")); + return NULL; } - return NULL; + + if (tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad talloc magic 0x%08x in talloc_realloc\n", tc->magic)); + return NULL; + } + + /* by resetting magic we catch users of the old memory */ + tc->magic = TALLOC_MAGIC_FREE; + + new_ptr = realloc(tc, size + sizeof(*tc)); + if (!new_ptr) { + tc->magic = TALLOC_MAGIC; + return NULL; + } + + if (tc == t->list) { + t->list = new_ptr; + } + tc = new_ptr; + tc->magic = TALLOC_MAGIC; + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + t->total_alloc_size += (size - tc->size); + tc->size = size; + + return (void *)(tc+1); } +/* + free a lump from a pool. Use sparingly please. +*/ +void talloc_free(TALLOC_CTX *ctx, void *ptr) +{ + struct talloc_chunk *tc; + + if (!ptr || !ctx->list) return; + + tc = ((struct talloc_chunk *)ptr)-1; + + if (tc->context != ctx) { + DEBUG(0,("Bad talloc context passed to talloc_free\n")); + } + + if (tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad talloc magic 0x%08x in talloc_free\n", tc->magic)); + } + + DLIST_REMOVE(ctx->list, tc); + + ctx->total_alloc_size -= tc->size; + tc->magic = TALLOC_MAGIC_FREE; + + free(tc); +} + + +/* + move a lump of memory from one talloc context to another + return the ptr on success, or NULL if it could not be found + in the old context or could not be transferred +*/ +void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, void *ptr) +{ + struct talloc_chunk *tc; + + if (!ptr) { + return NULL; + } + + tc = ((struct talloc_chunk *)ptr)-1; + + if (tc->context != old_ctx) { + DEBUG(0,("Bad talloc context passed to talloc_steal\n")); + return NULL; + } + + if (tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad talloc magic 0x%08x in talloc_steal\n", tc->magic)); + return NULL; + } + + DLIST_REMOVE(old_ctx->list, tc); + DLIST_ADD(new_ctx->list, tc); + + tc->context = new_ctx; + + old_ctx->total_alloc_size -= tc->size; + new_ctx->total_alloc_size += tc->size; + + return ptr; +} + + + /** Destroy all the memory allocated inside @p t, but not @p t * itself. */ void talloc_destroy_pool(TALLOC_CTX *t) { - struct talloc_chunk *c; - - if (!t) + if (!t) { return; + } while (t->list) { - c = t->list->next; - SAFE_FREE(t->list->ptr); - SAFE_FREE(t->list); - t->list = c; + struct talloc_chunk *tc = t->list; + if (tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad magic 0x%08x in talloc_destroy_pool\n", + tc->magic)); + return; + } + DLIST_REMOVE(t->list, tc); + tc->magic = TALLOC_MAGIC_FREE; + free(tc); } t->total_alloc_size = 0; @@ -305,14 +397,6 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) return ret; } -/** strdup_w with a talloc */ -smb_ucs2_t *talloc_strdup_w(TALLOC_CTX *t, const smb_ucs2_t *p) -{ - if (p) - return talloc_memdup(t, p, (strlen_w(p) + 1) * sizeof(smb_ucs2_t)); - return NULL; -} - /** * Perform string formatting, and return a pointer to newly allocated * memory holding the result, inside a memory pool. @@ -463,99 +547,19 @@ void talloc_get_allocation(TALLOC_CTX *t, size_t *total_bytes, int *n_chunks) { - struct talloc_chunk *chunk; + struct talloc_chunk *tc; if (t) { *total_bytes = 0; *n_chunks = 0; - for (chunk = t->list; chunk; chunk = chunk->next) { + for (tc = t->list; tc; tc = tc->next) { n_chunks[0]++; - *total_bytes += chunk->size; + *total_bytes += tc->size; } } } - -/* - free a lump from a pool. Use sparingly please. -*/ -void talloc_free(TALLOC_CTX *ctx, void *ptr) -{ - struct talloc_chunk *tc; - - if (!ptr || !ctx->list) return; - - /* as a special case, see if its the first element in the - list */ - if (ctx->list->ptr == ptr) { - ctx->total_alloc_size -= ctx->list->size; - tc = ctx->list; - ctx->list = ctx->list->next; - free(tc); - free(ptr); - return; - } - - /* find it in the context */ - for (tc=ctx->list; tc->next; tc=tc->next) { - if (tc->next->ptr == ptr) break; - } - - if (tc->next) { - struct talloc_chunk *tc2 = tc->next; - ctx->total_alloc_size -= tc->next->size; - tc->next = tc->next->next; - free(tc2); - free(ptr); - } else { - DEBUG(0,("Attempt to free non-allocated chunk in context '%s'\n", - ctx->name)); - } -} - - -/* - move a lump of memory from one talloc context to another - return the ptr on success, or NULL if it could not be found - in the old context or could not be transferred -*/ -const void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, const void *ptr) -{ - struct talloc_chunk *tc, *tc2; - - if (!ptr || !old_ctx->list) return NULL; - - /* as a special case, see if its the first element in the - list */ - if (old_ctx->list->ptr == ptr) { - tc = old_ctx->list; - old_ctx->list = old_ctx->list->next; - tc->next = new_ctx->list; - new_ctx->list = tc; - old_ctx->total_alloc_size -= tc->size; - new_ctx->total_alloc_size += tc->size; - return ptr; - } - - /* find it in the old context */ - for (tc=old_ctx->list; tc->next; tc=tc->next) { - if (tc->next->ptr == ptr) break; - } - - if (!tc->next) return NULL; - - /* move it to the new context */ - tc2 = tc->next; - tc->next = tc->next->next; - tc2->next = new_ctx->list; - new_ctx->list = tc2; - old_ctx->total_alloc_size -= tc2->size; - new_ctx->total_alloc_size += tc2->size; - - return ptr; -} - /* realloc an array, checking for integer overflow in the array size */ @@ -568,4 +572,14 @@ void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned return talloc_realloc(ctx, ptr, el_size * count); } + +/* + we really should get rid of this +*/ +void *talloc_strdup_w(TALLOC_CTX *mem_ctx, void *s) +{ + size_t len = strlen_w(s); + return talloc_memdup(mem_ctx, s, (len+1)*2); +} + /** @} */ -- cgit From 7216d23ba5eef36872196eaeb0b629fe0cf272c5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 May 2004 07:30:51 +0000 Subject: r509: fixed a memory handling bug that affects ldb with memory pools that change with each request (This used to be commit 18695cefa16b867427e3ca2fb0d787d850ea25c3) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 6734de9fd8..87e9538d01 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -226,6 +226,7 @@ int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) }; size_t len; int i, ret=0; + struct ldb_alloc_ops alloc = ldb->alloc_ops; if (ltdb->cache.last_attribute.name && ldb_attr_cmp(ltdb->cache.last_attribute.name, attr_name) == 0) { @@ -257,10 +258,14 @@ int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) attrs += strspn(attrs, " ,"); } - if (ltdb->cache.last_attribute.name) ldb_free(ldb, ltdb->cache.last_attribute.name); + ldb->alloc_ops.alloc = NULL; + + ldb_free(ldb, ltdb->cache.last_attribute.name); ltdb->cache.last_attribute.name = ldb_strdup(ldb, attr_name); ltdb->cache.last_attribute.flags = ret; + + ldb->alloc_ops = alloc; return ret; } -- cgit From 68293565de0b799dcc51e001dabf53adf88ee7ad Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 May 2004 09:55:05 +0000 Subject: r513: added a generic ldb debug system to allow the Samba debug functions to be cleanly interfaced to ldb (This used to be commit 74b89d5f960d6b936751e3f057b4540eb80b79cd) --- source4/lib/ldb/Makefile.ldb | 2 +- source4/lib/ldb/common/ldb.c | 24 +++++++++-- source4/lib/ldb/common/ldb_debug.c | 84 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/common/ldb_ldif.c | 10 +++-- source4/lib/ldb/config.m4 | 1 + source4/lib/ldb/include/ldb.h | 29 +++++++++++++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/tools/ldbadd.c | 2 + source4/lib/ldb/tools/ldbdel.c | 2 + source4/lib/ldb/tools/ldbedit.c | 2 + source4/lib/ldb/tools/ldbmodify.c | 2 + source4/lib/ldb/tools/ldbsearch.c | 2 + source4/lib/ldb/tools/ldbtest.c | 2 + 13 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_debug.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 0a0b95f7fe..1623b74f6c 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -23,7 +23,7 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ - common/ldb_alloc.o + common/ldb_alloc.o common/ldb_debug.o OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 86d0dd9e9b..b8f61e017a 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -68,6 +68,7 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, */ int ldb_close(struct ldb_context *ldb) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_close"); return ldb->ops->close(ldb); } @@ -83,7 +84,12 @@ int ldb_search(struct ldb_context *ldb, const char *expression, char * const *attrs, struct ldb_message ***res) { - return ldb->ops->search(ldb, base, scope, expression, attrs, res); + int ret; + ret = ldb->ops->search(ldb, base, scope, expression, attrs, res); + + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_search(%s) -> %d records\n", + expression, ret); + return ret; } /* @@ -102,7 +108,10 @@ int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->ops->add_record(ldb, message); + int ret; + ret = ldb->ops->add_record(ldb, message); + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_add(%s) -> %d\n", message->dn, ret); + return ret; } /* @@ -111,7 +120,11 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->ops->modify_record(ldb, message); + int ret; + ret = ldb->ops->modify_record(ldb, message); + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_modify(%s) -> %d\n", + message->dn, ret); + return ret; } @@ -120,7 +133,10 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const char *dn) { - return ldb->ops->delete_record(ldb, dn); + int ret; + ret = ldb->ops->delete_record(ldb, dn); + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_delete(%s) -> %d\n", dn, ret); + return ret; } /* diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c new file mode 100644 index 0000000000..d59f9284b0 --- /dev/null +++ b/source4/lib/ldb/common/ldb_debug.c @@ -0,0 +1,84 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb debug + * + * Description: functions for printing debug messages + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + this allows the user to choose their own debug function +*/ +int ldb_set_debug(struct ldb_context *ldb, + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap), + void *context) +{ + ldb->debug_ops.debug = debug; + ldb->debug_ops.context = context; + return 0; +} + +/* + debug function for ldb_set_debug_stderr +*/ +static void ldb_debug_stderr(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + if (level <= LDB_DEBUG_WARNING) { + vfprintf(stderr, fmt, ap); + } +} + +/* + convenience function to setup debug messages on stderr + messages of level LDB_DEBUG_WARNING and higher are printed +*/ +int ldb_set_debug_stderr(struct ldb_context *ldb) +{ + return ldb_set_debug(ldb, ldb_debug_stderr, ldb); +} + +/* + log a message +*/ +void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) +{ + va_list ap; + if (ldb->debug_ops.debug == NULL) { + return; + } + va_start(ap, fmt); + ldb->debug_ops.debug(ldb->debug_ops.context, level, fmt, ap); + va_end(ap); +} + diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 451276c48d..513e2dd365 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -217,7 +217,8 @@ int ldif_write(struct ldb_context *ldb, } } if (!ldb_changetypes[i].name) { - fprintf(stderr,"Invalid changetype\n"); + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n", + ldif->changetype); return -1; } ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name); @@ -493,7 +494,8 @@ struct ldb_ldif *ldif_read(struct ldb_context *ldb, /* first line must be a dn */ if (ldb_attr_cmp(attr, "dn") != 0) { - fprintf(stderr, "First line must be a dn not '%s'\n", attr); + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n", + attr); goto failed; } @@ -512,8 +514,8 @@ struct ldb_ldif *ldif_read(struct ldb_context *ldb, } } if (!ldb_changetypes[i].name) { - fprintf(stderr,"Bad changetype '%s'\n", - (char *)value.data); + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Bad ldif changetype '%s'\n",(char *)value.data); } flags = 0; continue; diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 975da5a4a6..f450acce00 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -9,6 +9,7 @@ SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_alloc.o \ + lib/ldb/common/ldb_debug.o \ lib/ldb/ldb_tdb/ldb_search.o \ lib/ldb/ldb_tdb/ldb_tdb.o \ lib/ldb/ldb_tdb/ldb_pack.o \ diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 852389d415..adb6c31952 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -152,6 +152,21 @@ struct ldb_alloc_ops { void *context; }; +/* debugging uses one of the following levels */ +enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, + LDB_DEBUG_WARNING, LDB_DEBUG_TRACE}; + +/* + the user can optionally supply a debug function. The function + is based on the vfprintf() style of interface, but with the addition + of a severity level +*/ +struct ldb_debug_ops { + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap); + void *context; +}; + /* every ldb connection is started by establishing a ldb_context @@ -165,6 +180,9 @@ struct ldb_context { /* memory allocation info */ struct ldb_alloc_ops alloc_ops; + + /* memory allocation info */ + struct ldb_debug_ops debug_ops; }; @@ -308,6 +326,17 @@ int ldb_set_alloc(struct ldb_context *ldb, void *(*alloc)(void *context, void *ptr, size_t size), void *context); +/* + this allows the user to set a debug function for error reporting +*/ +int ldb_set_debug(struct ldb_context *ldb, + void (*debug)(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap), + void *context); + +/* this sets up debug to print messages on stderr */ +int ldb_set_debug_stderr(struct ldb_context *ldb); + /* these are used as type safe versions of the ldb allocation functions */ #define ldb_malloc_p(ldb, type) (type *)ldb_malloc(ldb, sizeof(type)) diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 7e7d047f25..7e959e7854 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -248,7 +248,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, if (msg_count == count) { /* hmm, got too many? */ - fprintf(stderr,"Too many messages?!\n"); + ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n"); break; } diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 6d89f67e0f..a45021c1d9 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -115,6 +115,8 @@ static int process_file(struct ldb_context *ldb, FILE *f) exit(1); } + ldb_set_debug_stderr(ldb); + if (argc == 0) { usage(); } diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 48ee07ad25..880713b25a 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -85,6 +85,8 @@ static void usage(void) exit(1); } + ldb_set_debug_stderr(ldb); + for (i=0;i Date: Fri, 7 May 2004 23:54:41 +0000 Subject: r574: - another attempt at const cleanliness in ldb - fixed a problem with searching for values containing an '=' sign - fixed the semantics of attempting an attribute deletion on an attribute that doesn't exist. - added some more ldb_msg_*() utilities (This used to be commit 62b4ec367d170330d837b0f1fe5cd13205a53b59) --- source4/lib/ldb/common/ldb.c | 2 +- source4/lib/ldb/common/ldb_msg.c | 47 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/common/ldb_parse.c | 18 +++++++------ source4/lib/ldb/include/ldb.h | 4 +-- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 4 +-- source4/lib/ldb/ldb_tdb/ldb_search.c | 12 ++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 10 ++++++-- source4/lib/ldb/tests/test-modify.ldif | 6 +++++ source4/lib/ldb/tools/ldbedit.c | 2 +- source4/lib/ldb/tools/ldbmodify.c | 4 +++ source4/lib/ldb/tools/ldbsearch.c | 6 ++--- source4/lib/ldb/tools/ldbtest.c | 31 ++++++++++++++-------- 13 files changed, 111 insertions(+), 37 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index b8f61e017a..c6e8d37671 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -82,7 +82,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const *attrs, struct ldb_message ***res) + const char * const *attrs, struct ldb_message ***res) { int ret; ret = ldb->ops->search(ldb, base, scope, expression, attrs, res); diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 5976db81b6..01f32751e1 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -131,6 +131,53 @@ int ldb_msg_add(struct ldb_context *ldb, return 0; } +/* + add a value to a message +*/ +int ldb_msg_add_value(struct ldb_context *ldb, + struct ldb_message *msg, + char *attr_name, + struct ldb_val *val) +{ + struct ldb_message_element *el; + struct ldb_val *vals; + + el = ldb_msg_find_element(msg, attr_name); + if (!el) { + ldb_msg_add_empty(ldb, msg, attr_name, 0); + el = ldb_msg_find_element(msg, attr_name); + } + if (!el) { + return -1; + } + + vals = ldb_realloc_p(ldb, el->values, struct ldb_val, el->num_values+1); + if (!vals) { + errno = ENOMEM; + return -1; + } + el->values = vals; + el->values[el->num_values] = *val; + el->num_values++; + + return 0; +} + + +/* + add a string element to a message +*/ +int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, + char *attr_name, char *str) +{ + struct ldb_val val; + + val.data = str; + val.length = strlen(str); + + return ldb_msg_add_value(ldb, msg, attr_name, &val); +} + /* compare two ldb_message_element structures assumes case senistive comparison diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 75eb44fcc0..5d2a42fd20 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -56,10 +56,12 @@ a filter is defined by: ::= '=' | '~=' | '<=' | '>=' */ +#define LDB_ALL_SEP "()&|=!" + /* return next token element. Caller frees */ -static char *ldb_parse_lex(struct ldb_context *ldb, const char **s) +static char *ldb_parse_lex(struct ldb_context *ldb, const char **s, const char *sep) { const char *p = *s; char *ret; @@ -73,7 +75,7 @@ static char *ldb_parse_lex(struct ldb_context *ldb, const char **s) return NULL; } - if (strchr("()&|=!", *p)) { + if (strchr(sep, *p)) { (*s) = p+1; ret = ldb_strndup(ldb, p, 1); if (!ret) { @@ -82,7 +84,7 @@ static char *ldb_parse_lex(struct ldb_context *ldb, const char **s) return ret; } - while (*p && (isalnum(*p) || !strchr("()&|=!", *p))) { + while (*p && (isalnum(*p) || !strchr(sep, *p))) { p++; } @@ -132,7 +134,7 @@ static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const ch char *eq, *val, *l; struct ldb_parse_tree *ret; - l = ldb_parse_lex(ldb, &s); + l = ldb_parse_lex(ldb, &s, LDB_ALL_SEP); if (!l) { return NULL; } @@ -142,7 +144,7 @@ static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const ch return NULL; } - eq = ldb_parse_lex(ldb, &s); + eq = ldb_parse_lex(ldb, &s, LDB_ALL_SEP); if (!eq || strcmp(eq, "=") != 0) { ldb_free(ldb, l); if (eq) ldb_free(ldb, eq); @@ -150,8 +152,8 @@ static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const ch } ldb_free(ldb, eq); - val = ldb_parse_lex(ldb, &s); - if (val && strchr("()&|=", *val)) { + val = ldb_parse_lex(ldb, &s, ")"); + if (val && strchr("()&|", *val)) { ldb_free(ldb, l); if (val) ldb_free(ldb, val); return NULL; @@ -288,7 +290,7 @@ static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const ch const char *p, *p2; struct ldb_parse_tree *ret; - l = ldb_parse_lex(ldb, s); + l = ldb_parse_lex(ldb, s, LDB_ALL_SEP); if (!l) { return NULL; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index adb6c31952..7215bf5705 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -129,7 +129,7 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_backend_ops { int (*close)(struct ldb_context *); int (*search)(struct ldb_context *, const char *, enum ldb_scope, - const char *, char * const [], struct ldb_message ***); + const char *, const char * const [], struct ldb_message ***); int (*search_free)(struct ldb_context *, struct ldb_message **); int (*add_record)(struct ldb_context *, const struct ldb_message *); int (*modify_record)(struct ldb_context *, const struct ldb_message *); @@ -216,7 +216,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const *attrs, struct ldb_message ***res); + const char * const *attrs, struct ldb_message ***res); /* free a set of messages returned by ldb_search diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 7e959e7854..d96bfd62d3 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -210,7 +210,7 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, */ static int lldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const *attrs, struct ldb_message ***res) + const char * const *attrs, struct ldb_message ***res) { struct lldb_private *lldb = ldb->private_data; int count, msg_count; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 877955a9b7..0e9f3e3c55 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -496,7 +496,7 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree const char *base, enum ldb_scope scope, const struct dn_list *dn_list, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { int i; unsigned int count = 0; @@ -536,7 +536,7 @@ int ltdb_search_indexed(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; struct dn_list dn_list; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 5ee4449dee..60eaf3117c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -149,7 +149,7 @@ static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret */ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, const struct ldb_message *msg, - char * const *attrs) + const char * const *attrs) { struct ldb_message *ret; int i; @@ -304,7 +304,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message search the database for a single simple dn */ int ltdb_search_dn(struct ldb_context *ldb, char *dn, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { int ret; struct ldb_message msg, *msg2; @@ -340,7 +340,7 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, return 0 on success, -1 on failure */ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, - char * const attrs[], + const char * const attrs[], unsigned int *count, struct ldb_message ***res) { @@ -378,7 +378,7 @@ struct ltdb_search_info { struct ldb_parse_tree *tree; const char *base; enum ldb_scope scope; - char * const *attrs; + const char * const *attrs; struct ldb_message **msgs; int failures; int count; @@ -458,7 +458,7 @@ static int ltdb_search_full(struct ldb_context *ldb, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; int ret; @@ -491,7 +491,7 @@ static int ltdb_search_full(struct ldb_context *ldb, */ int ltdb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - char * const attrs[], struct ldb_message ***res) + const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = ldb->private_data; struct ldb_parse_tree *tree; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index eb28bc4938..09d1618ffc 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -436,10 +436,13 @@ static int msg_delete_element(struct ldb_context *ldb, sizeof(el->values[i])*(el->num_values-(i+1))); } el->num_values--; + if (el->num_values == 0) { + return msg_delete_attribute(ldb, msg, name); + } return 0; } } - + return -1; } @@ -488,7 +491,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) already exists */ ret = find_element(&msg2, msg->elements[i].name); if (ret != -1) { - errno = EEXIST; + ltdb->last_err_string = "Attribute exists"; goto failed; } if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { @@ -500,6 +503,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) /* replace all elements of this attribute name with the elements listed */ if (msg_delete_attribute(ldb, &msg2, msg->elements[i].name) != 0) { + ltdb->last_err_string = "No such attribute"; goto failed; } /* add the replacement element */ @@ -514,6 +518,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) if (msg->elements[i].num_values == 0) { if (msg_delete_attribute(ldb, &msg2, msg->elements[i].name) != 0) { + ltdb->last_err_string = "No such attribute"; goto failed; } break; @@ -523,6 +528,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) &msg2, msg->elements[i].name, &msg->elements[i].values[j]) != 0) { + ltdb->last_err_string = "No such attribute"; goto failed; } } diff --git a/source4/lib/ldb/tests/test-modify.ldif b/source4/lib/ldb/tests/test-modify.ldif index 521c6d8b56..78d8353d3c 100644 --- a/source4/lib/ldb/tests/test-modify.ldif +++ b/source4/lib/ldb/tests/test-modify.ldif @@ -12,3 +12,9 @@ telephonenumber: +61 412 666 929 - delete: telephonenumber telephonenumber: +61 2 6260 6012 +- +delete: telephonenumber +telephonenumber: +61 412 666 929 +- +add: telephonenumber +telephonenumber: +61 412 666 929 diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 739c3b6301..debe06c231 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -218,7 +218,7 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun fclose(f); - ldb_asprintf(ldb, &cmd, "%s %s", editor, template); + asprintf(&cmd, "%s %s", editor, template); if (!cmd) { unlink(template); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 9f7cbe4527..828b7d4865 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -144,6 +144,10 @@ static int process_file(struct ldb_context *ldb, FILE *f) ldb_close(ldb); printf("Modified %d records with %d failures\n", count, failures); + + if (failures != 0) { + return -1; + } return 0; } diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index f80f81b50e..478601ec7e 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -49,7 +49,7 @@ static int do_search(struct ldb_context *ldb, const char *basedn, int scope, const char *expression, - char * const *attrs) + const char * const *attrs) { int ret, i; struct ldb_message **msgs; @@ -86,7 +86,7 @@ static int do_search(struct ldb_context *ldb, int main(int argc, char * const argv[]) { struct ldb_context *ldb; - char * const * attrs = NULL; + const char * const * attrs = NULL; const char *ldb_url; const char *basedn = NULL; int opt; @@ -140,7 +140,7 @@ static int do_search(struct ldb_context *ldb, } if (argc > 1) { - attrs = argv+1; + attrs = (const char * const *)(argv+1); } ldb = ldb_connect(ldb_url, 0, NULL); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index fc224115f5..d7b4023895 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -59,7 +59,8 @@ static void add_records(struct ldb_context *ldb, struct ldb_message_element el[6]; struct ldb_val vals[6][1]; char *name; - + int j; + asprintf(&name, "Test%d", i); asprintf(&msg.dn, "cn=%s,%s", name, basedn); @@ -67,42 +68,42 @@ static void add_records(struct ldb_context *ldb, msg.elements = el; el[0].flags = 0; - el[0].name = "cn"; + el[0].name = strdup("cn"); el[0].num_values = 1; el[0].values = vals[0]; vals[0][0].data = name; vals[0][0].length = strlen(name); el[1].flags = 0; - el[1].name = "title"; + el[1].name = strdup("title"); el[1].num_values = 1; el[1].values = vals[1]; asprintf((char **)&vals[1][0].data, "The title of %s", name); vals[1][0].length = strlen(vals[1][0].data); el[2].flags = 0; - el[2].name = "uid"; + el[2].name = strdup("uid"); el[2].num_values = 1; el[2].values = vals[2]; vals[2][0].data = ldb_casefold(ldb, name); vals[2][0].length = strlen(vals[2][0].data); el[3].flags = 0; - el[3].name = "mail"; + el[3].name = strdup("mail"); el[3].num_values = 1; el[3].values = vals[3]; asprintf((char **)&vals[3][0].data, "%s@example.com", name); vals[3][0].length = strlen(vals[3][0].data); el[4].flags = 0; - el[4].name = "objectClass"; + el[4].name = strdup("objectClass"); el[4].num_values = 1; el[4].values = vals[4]; - vals[4][0].data = "OpenLDAPperson"; + vals[4][0].data = strdup("OpenLDAPperson"); vals[4][0].length = strlen(vals[4][0].data); el[5].flags = 0; - el[5].name = "sn"; + el[5].name = strdup("sn"); el[5].num_values = 1; el[5].values = vals[5]; vals[5][0].data = name; @@ -118,11 +119,15 @@ static void add_records(struct ldb_context *ldb, printf("adding uid %s\r", name); fflush(stdout); + for (j=0;j Date: Fri, 7 May 2004 23:56:57 +0000 Subject: r576: added a ldap_timestring() function (needed for fields like whenChanged in SAM db) (This used to be commit b2a63555189fea41184a2cac796945bca4e98995) --- source4/lib/time.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 0aef931fe0..0bc5fcd3fc 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -339,6 +339,25 @@ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) return buf; } +/*************************************************************************** +return a LDAP time string + ***************************************************************************/ +char *ldap_timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + struct tm *tm = gmtime(&t); + + if (!tm) { + return NULL; + } + + /* formatted like: 20040408072012.0Z */ + return talloc_asprintf(mem_ctx, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); +} + /**************************************************************************** -- cgit From d2c7b5cd338d41f9b47113ec21b36a12fe10c3fc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 May 2004 03:44:47 +0000 Subject: r583: fixed two bugs in the handling of index entry deletion (This used to be commit 7b5f3370e6c078bf506ac3eb24fb330d4aee7688) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 19 +++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 ++ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 0e9f3e3c55..3febdaa711 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -77,11 +77,11 @@ static char *ldb_dn_key(struct ldb_context *ldb, see if a attribute value is in the list of indexed attributes */ static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, - int *v_idx) + int *v_idx, const char *key) { int i, j; for (i=0;inum_elements;i++) { - if (ldb_attr_cmp(msg->elements[i].name, LTDB_IDXATTR) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, key) == 0) { const struct ldb_message_element *el = &msg->elements[i]; for (j=0;jnum_values;j++) { @@ -127,7 +127,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* if the attribute isn't in the list of indexed attributes then this node needs a full search */ - if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL) == -1) { + if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL, LTDB_IDXATTR) == -1) { return -1; } @@ -711,7 +711,8 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, NULL); + ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, + NULL, LTDB_IDXATTR); if (ret == -1) { continue; } @@ -751,13 +752,14 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, if (ret == 0) { /* it wasn't indexed. Did we have an earlier error? If we did then its gone now */ - ltdb_search_dn1_free(ldb, &msg); + ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn_key %s was not indexed\n", dn_key); ldb_free(ldb, dn_key); return 0; } - i = ldb_msg_find_idx(&msg, dn, &j); + i = ldb_msg_find_idx(&msg, dn, &j, LTDB_IDX); if (i == -1) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn %s not found in %s\n", dn, dn_key); /* it ain't there. hmmm */ ltdb_search_dn1_free(ldb, &msg); ldb_free(ldb, dn_key); @@ -767,7 +769,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, if (j != msg.elements[i].num_values - 1) { memmove(&msg.elements[i].values[j], &msg.elements[i].values[j+1], - (msg.elements[i].num_values-1) * + (msg.elements[i].num_values-(j+1)) * sizeof(msg.elements[i].values[0])); } msg.elements[i].num_values--; @@ -800,7 +802,8 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, NULL); + ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, + NULL, LTDB_IDXATTR); if (ret == -1) { continue; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 60eaf3117c..e2c83202e9 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -257,6 +257,8 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message int ret; TDB_DATA tdb_key, tdb_data, tdb_data2; + memset(msg, 0, sizeof(*msg)); + /* form the key */ tdb_key = ltdb_key(ldb, dn); if (!tdb_key.dptr) { -- cgit From 35ffc464541366ba1da0a332afae203b68512010 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 8 May 2004 14:42:45 +0000 Subject: r587: added server code for samr_EnumDomainUsers, and started adding samr_SetUserInfo and samr_QueryUserInfo (This used to be commit e0db9659a85b59e52fbe033a94b411d6c64d9f9c) --- source4/lib/time.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 0bc5fcd3fc..65b85b2180 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -428,3 +428,21 @@ NTTIME pull_nttime(void *base, uint16 offset) return ret; } + +/* + parse a nttime as a integer in a string and return a NTTIME +*/ +NTTIME nttime_from_string(const char *s) +{ + double t = 0; + const double t32 = 4294967296.0; + NTTIME ret; + /* i wish we could rely on 64 bit systems and sscanf %llu */ + if (sscanf(s, "%lf", &t) != 1) { + ret.low = 0; + ret.high = 0; + } + ret.high = t / t32; + ret.low = t - (ret.high*t32); + return ret; +} -- cgit From 54a695f7edf7c40a92391aa94ddbbd2db8b11ec3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 May 2004 09:39:47 +0000 Subject: r601: added the server code for all the samr_SetUserInfo and samr_QueryUserInfo levels except for the password set levels. This means that a large part of the RPC-SAMR torture test now runs correctly against Samba4 (This used to be commit ec0a51898f543578e755207d81ed5c1524861c64) --- source4/lib/ldb/common/ldb_msg.c | 36 ++++++++++++++++++++++-------------- source4/lib/time.c | 26 ++++++++++++++++++-------- 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 01f32751e1..59d480a33a 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -136,7 +136,7 @@ int ldb_msg_add(struct ldb_context *ldb, */ int ldb_msg_add_value(struct ldb_context *ldb, struct ldb_message *msg, - char *attr_name, + const char *attr_name, struct ldb_val *val) { struct ldb_message_element *el; @@ -200,51 +200,59 @@ int ldb_msg_element_compare(struct ldb_message_element *el1, return 0; } - /* convenience functions to return common types from a message these return the first value if the attribute is multi-valued */ +const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); + if (!el || el->num_values == 0) { + return NULL; + } + return &el->values[0]; +} + int ldb_msg_find_int(const struct ldb_message *msg, const char *attr_name, int default_value) { - struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); - if (!el || el->num_values == 0) { + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { return default_value; } - return strtol(el->values[0].data, NULL, 0); + return strtol(v->data, NULL, 0); } unsigned int ldb_msg_find_uint(const struct ldb_message *msg, const char *attr_name, int default_value) { - struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); - if (!el || el->num_values == 0) { + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { return default_value; } - return strtoul(el->values[0].data, NULL, 0); + return strtoul(v->data, NULL, 0); } double ldb_msg_find_double(const struct ldb_message *msg, const char *attr_name, double default_value) { - struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); - if (!el || el->num_values == 0) { + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { return default_value; } - return strtod(el->values[0].data, NULL); + return strtod(v->data, NULL); } const char *ldb_msg_find_string(const struct ldb_message *msg, const char *attr_name, const char *default_value) { - struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name); - if (!el || el->num_values == 0) { + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { return default_value; } - return el->values[0].data; + return v->data; } diff --git a/source4/lib/time.c b/source4/lib/time.c index 65b85b2180..ba650668c5 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -428,21 +428,31 @@ NTTIME pull_nttime(void *base, uint16 offset) return ret; } +/* + convert a NTTIME to a double in 100-nano-seconds since 1601 +*/ +double nttime_to_double_nt(NTTIME t) +{ + const double t32 = 4294967296.0; + return t.high*t32 + t.low; +} /* - parse a nttime as a integer in a string and return a NTTIME + convert a double in 100-nano-seconds since 1601 to a NTTIME */ -NTTIME nttime_from_string(const char *s) +NTTIME nttime_from_double_nt(double t) { - double t = 0; const double t32 = 4294967296.0; NTTIME ret; - /* i wish we could rely on 64 bit systems and sscanf %llu */ - if (sscanf(s, "%lf", &t) != 1) { - ret.low = 0; - ret.high = 0; - } ret.high = t / t32; ret.low = t - (ret.high*t32); return ret; } + +/* + parse a nttime as a large integer in a string and return a NTTIME +*/ +NTTIME nttime_from_string(const char *s) +{ + return nttime_from_double_nt(strtod(s, NULL)); +} -- cgit From 51d5ddecc60b6e33e1d542cb92b2fe6736849398 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 May 2004 12:30:30 +0000 Subject: r606: added a HIDDEN attribute on fields in ldb (in @ATTRIBUTES). This allows you to mark an attribute as only appearing in searches that explicitly name it. It will be used for attributes like nTSecurityDescriptor (This used to be commit f5cd3d733b71368ea652f8a4d653d87f45ff983f) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 1 + source4/lib/ldb/ldb_tdb/ldb_search.c | 4 ++++ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 1 + 3 files changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 87e9538d01..2a879f384c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -222,6 +222,7 @@ int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, { "INTEGER", LTDB_FLAG_INTEGER }, { "WILDCARD", LTDB_FLAG_WILDCARD }, + { "HIDDEN", LTDB_FLAG_HIDDEN }, { NULL, 0} }; size_t len; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index e2c83202e9..25e22b3dd4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -135,6 +135,10 @@ static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret { int i; for (i=0;inum_elements;i++) { + int flags = ltdb_attribute_flags(ldb, msg->elements[i].name); + if (flags & LTDB_FLAG_HIDDEN) { + continue; + } if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index c791cbe201..b678aac631 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -42,6 +42,7 @@ struct ltdb_private { #define LTDB_FLAG_INTEGER (1<<1) #define LTDB_FLAG_WILDCARD (1<<2) #define LTDB_FLAG_OBJECTCLASS (1<<3) +#define LTDB_FLAG_HIDDEN (1<<4) #ifndef IVAL -- cgit From 5dc73338d22ce95299ed62b73d1c15c94581495e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 9 May 2004 12:30:33 +0000 Subject: r607: When our code is looking for an 'empty' data blob some of it tests the .length, other code checks the .data. Ensure that we always NULL the .data, so that talloc-based blobs behave just like their direct malloc equivalents. Andrew Bartlett (This used to be commit 64121aa1a9d037d3969f24be62f4521611c89888) --- source4/lib/data_blob.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index b5d1b4076e..3667d453b9 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -108,6 +108,7 @@ void data_blob_free(DATA_BLOB *d) if (d->free) { (d->free)(d); } + d->data = NULL; d->length = 0; } } -- cgit From 55fa62be31c9027d84be0e4caad3ee59d78ca1b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 May 2004 12:37:35 +0000 Subject: r609: allow ldbedit to take a list of attributes to edit, just like ldbsearch. This allows you to edit the description of all users using something like: ldbedit 'objectclass=user' description and not get overwhelmed with fields. It also allows you to edit HIDDEN attributes by specifying them explicitly (This used to be commit dd83d39de23cdf8c574005829972dae8dc6bee6a) --- source4/lib/ldb/tools/ldbedit.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index debe06c231..7e41702422 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -260,7 +260,7 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun static void usage(void) { - printf("Usage: ldbedit \n"); + printf("Usage: ldbedit \n"); printf("Options:\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); printf(" -s base|sub|one choose search scope\n"); @@ -281,6 +281,7 @@ static void usage(void) int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; const char *editor; + const char * const * attrs = NULL; ldb_url = getenv("LDB_URL"); @@ -342,6 +343,12 @@ static void usage(void) usage(); } expression = argv[0]; + argc--; + argv++; + } + + if (argc > 0) { + attrs = (const char * const *)argv; } ldb = ldb_connect(ldb_url, 0, NULL); @@ -353,7 +360,7 @@ static void usage(void) ldb_set_debug_stderr(ldb); - ret = ldb_search(ldb, basedn, scope, expression, NULL, &msgs); + ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); if (ret == -1) { printf("search failed - %s\n", ldb_errstring(ldb)); -- cgit From 0f581e4af943a7e5dfd71d1c308ac668f287aed3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 May 2004 11:23:50 +0000 Subject: r623: setUserInfo level 24 (password set) now works in the SAMR server. This includes all of the password complexity, password history and other password restrictions. (This used to be commit cb070b9084d95cf5178edbef951b75eab62b7220) --- source4/lib/genrand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 1423419961..f891ac883a 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -246,7 +246,7 @@ void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) /* very basic password quality checker */ -static BOOL check_password_quality(const char *s) +BOOL check_password_quality(const char *s) { int has_digit=0, has_capital=0, has_lower=0; while (*s) { -- cgit From b2d1f7890765fca5a119d43f4906e885c245005f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 12 May 2004 16:13:32 +0000 Subject: r655: Fix if() logic (This used to be commit 09096cfc3e1b35b4ac944cf84bfdec6ee44e06bf) --- source4/lib/registry/tools/regdiff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index c3633ef0af..888270f61f 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -24,7 +24,7 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) { int i; - REG_KEY *t1,*t2; + REG_KEY *t1, *t2; REG_VAL *v1, *v2; WERROR error1, error2; @@ -59,7 +59,7 @@ void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(newkey, i, &v1)); i++) { error2 = reg_key_get_value_by_name(oldkey, reg_val_name(v1), &v2); - if (((W_ERROR_IS_OK(error2) && reg_val_size(v2) != reg_val_size(v1)) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1))) + if ((W_ERROR_IS_OK(error2) && (reg_val_size(v2) != reg_val_size(v1) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1)))) || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(v1), str_regtype(reg_val_type(v1)), reg_val_data_string(v1)); } -- cgit From f236700ef67d4f93ec56ec7808584552e94e0dfe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 10:20:53 +0000 Subject: r665: merge over the new build system from my tmp branch to the main SAMBA_4_0 tree. NOTE: that it's not completely ready, but it's functional:-) metze (This used to be commit c78a2ddb28ec50d6570a83b1f66f18a5c3621731) --- source4/lib/basic.m4 | 46 +++++------ source4/lib/cmdline/config.m4 | 8 +- source4/lib/iconv.m4 | 2 +- source4/lib/ldb/config.m4 | 58 ++++---------- source4/lib/ldb/config.mk | 88 ++++++++++++++++++++++ source4/lib/popt/config.m4 | 7 +- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/config.m4 | 34 ++++++--- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 2 +- .../registry/reg_backend_gconf/reg_backend_gconf.c | 2 +- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 4 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 2 +- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 2 +- .../registry/reg_backend_wine/reg_backend_wine.c | 2 +- source4/lib/registry/tools/gregedit.c | 39 ++++------ source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 4 +- source4/lib/registry/tools/regtree.c | 2 +- 20 files changed, 189 insertions(+), 121 deletions(-) create mode 100644 source4/lib/ldb/config.mk (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index 712a4826b7..ac5f82440e 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -1,26 +1,26 @@ dnl # LIB BASIC subsystem SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], - [lib/debug.o lib/fault.o \ - lib/getsmbpass.o lib/interface.o \ - lib/interfaces.o lib/pidfile.o lib/replace.o \ - lib/signal.o lib/system.o lib/sendfile.o lib/time.o \ - lib/genrand.o lib/username.o \ - lib/util_getent.o lib/util_pw.o lib/smbrun.o \ - lib/bitmap.o lib/snprintf.o lib/dprintf.o \ - lib/xfile.o lib/wins_srv.o \ - lib/util_str.o lib/util_sid.o lib/util_uuid.o \ - lib/util_unistr.o lib/util_file.o lib/data_blob.o \ - lib/util.o lib/util_sock.o \ - lib/talloc.o lib/substitute.o lib/fsusage.o \ - lib/ms_fnmatch.o lib/select.o lib/messages.o \ - lib/tallocmsg.o lib/dmallocmsg.o \ - lib/smbpasswd.o \ - nsswitch/wb_client.o nsswitch/wb_common.o \ - lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ - lib/gencache.o lib/module.o lib/mutex.o \ - lib/ldap_escape.o lib/events.o \ - lib/crypto/crc32.o lib/crypto/md5.o \ - lib/crypto/hmacmd5.o lib/crypto/md4.o \ - lib/tdb/tdb.o lib/tdb/spinlock.o lib/tdb/tdbutil.o \$(CHARSET_OBJS)], - lib/libbasic_public_proto.h) + [lib/debug.o lib/fault.o + lib/getsmbpass.o lib/interface.o + lib/interfaces.o lib/pidfile.o lib/replace.o + lib/signal.o lib/system.o lib/sendfile.o lib/time.o + lib/genrand.o lib/username.o + lib/util_getent.o lib/util_pw.o lib/smbrun.o + lib/bitmap.o lib/snprintf.o lib/dprintf.o + lib/xfile.o lib/wins_srv.o + lib/util_str.o lib/util_sid.o lib/util_uuid.o + lib/util_unistr.o lib/util_file.o lib/data_blob.o + lib/util.o lib/util_sock.o + lib/talloc.o lib/substitute.o lib/fsusage.o + lib/ms_fnmatch.o lib/select.o lib/messages.o + lib/tallocmsg.o lib/dmallocmsg.o + lib/smbpasswd.o + nsswitch/wb_client.o nsswitch/wb_common.o + lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o + lib/gencache.o lib/module.o lib/mutex.o + lib/ldap_escape.o lib/events.o + lib/crypto/crc32.o lib/crypto/md5.o + lib/crypto/hmacmd5.o lib/crypto/md4.o + lib/tdb/tdb.o lib/tdb/spinlock.o lib/tdb/tdbutil.o],[], + [CHARSET]) diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index 6e9a8f4508..8316dff10f 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -72,8 +72,10 @@ AC_CHECK_LIB(readline, rl_completion_matches, TMP_LIBCMDLINE_OBJS="lib/cmdline/readline.o lib/cmdline/popt_common.o" TMP_LIBCMDLINE_LIBS="$TERMLIBS" +#hack... +LIBS="$LIBS $TERMLIBS" + SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], - [], - [], - [${TMP_LIBCMDLINE_LIBS}]) + [ALLLIBS], + [LIBPOPT]) diff --git a/source4/lib/iconv.m4 b/source4/lib/iconv.m4 index 26512ff326..282fa69b2d 100644 --- a/source4/lib/iconv.m4 +++ b/source4/lib/iconv.m4 @@ -63,4 +63,4 @@ if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; th Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) fi -SMB_SUBSYSTEM(CHARSET,lib/iconv.o,lib/charcnv.o) +SMB_SUBSYSTEM(CHARSET,lib/iconv.o,lib/charcnv.o,[${TMP_CHARSET_LIBS}]) diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index f450acce00..16805132fd 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,45 +1,19 @@ if test x"$with_ldap_support" = x"yes"; then -SMB_SUBSYSTEM(LIBLDB_LDAP,[lib/ldb/ldb_ldap/ldb_ldap.o]) + SMB_MODULE_DEFAULT(libldb_ldap,STATIC) fi -SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], - [lib/ldb/common/ldb_ldif.o \ - lib/ldb/common/ldb_parse.o \ - lib/ldb/common/ldb_msg.o \ - lib/ldb/common/util.o \ - lib/ldb/common/ldb_utf8.o \ - lib/ldb/common/ldb_alloc.o \ - lib/ldb/common/ldb_debug.o \ - lib/ldb/ldb_tdb/ldb_search.o \ - lib/ldb/ldb_tdb/ldb_tdb.o \ - lib/ldb/ldb_tdb/ldb_pack.o \ - lib/ldb/ldb_tdb/ldb_index.o \ - lib/ldb/ldb_tdb/ldb_match.o \ - lib/ldb/ldb_tdb/ldb_cache.o \ - \$(LIBLDB_LDAP_OBJS)], - lib/ldb/include/ldb.h) - -SMB_SUBSYSTEM(LDBADD,[], - [lib/ldb/tools/ldbadd.o \ - \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], - lib/ldb/include/proto.h) - -SMB_SUBSYSTEM(LDBDEL,[], - [lib/ldb/tools/ldbdel.o \ - \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], - lib/ldb/include/proto.h) - -SMB_SUBSYSTEM(LDBMODIFY,[], - [lib/ldb/tools/ldbmodify.o \ - \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], - lib/ldb/include/proto.h) - -SMB_SUBSYSTEM(LDBSEARCH,[], - [lib/ldb/tools/ldbsearch.o \ - \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], - lib/ldb/include/proto.h) - -SMB_SUBSYSTEM(LDBEDIT,[], - [lib/ldb/tools/ldbedit.o \ - \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], - lib/ldb/include/proto.h) +SMB_MODULE_MK(libldb_ldap,LIBLDB,NOT,lib/ldb/config.mk) + +SMB_MODULE_MK(libldb_tdb,LIBLDB,STATIC,lib/ldb/config.mk) + +SMB_SUBSYSTEM_MK(LIBLDB,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbadd,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbdel,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbmodify,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbsearch,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbedit,lib/ldb/config.mk) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk new file mode 100644 index 0000000000..c44d3e6bf0 --- /dev/null +++ b/source4/lib/ldb/config.mk @@ -0,0 +1,88 @@ +################################################ +# Start MODULE libldb_ldap +[MODULE::libldb_ldap] +INIT_OBJ_FILES = \ + lib/ldb/ldb_ldap/ldb_ldap.o +# End MODULE libldb_tdb +################################################ + +################################################ +# Start MODULE libldb_tdb +[MODULE::libldb_tdb] +INIT_OBJ_FILES = \ + lib/ldb/ldb_tdb/ldb_tdb.o +ADD_OBJ_FILES = \ + lib/ldb/ldb_tdb/ldb_search.o \ + lib/ldb/ldb_tdb/ldb_pack.o \ + lib/ldb/ldb_tdb/ldb_index.o \ + lib/ldb/ldb_tdb/ldb_match.o \ + lib/ldb/ldb_tdb/ldb_cache.o +# End MODULE libldb_tdb +################################################ + +################################################ +# Start SUBSYSTEM LIBLDB +[SUBSYSTEM::LIBLDB] +INIT_OBJ_FILES = \ + lib/ldb/common/ldb.o +ADD_OBJ_FILES = \ + lib/ldb/common/ldb_ldif.o \ + lib/ldb/common/ldb_parse.o \ + lib/ldb/common/ldb_msg.o \ + lib/ldb/common/util.o \ + lib/ldb/common/ldb_utf8.o \ + lib/ldb/common/ldb_alloc.o \ + lib/ldb/common/ldb_debug.o +# +# End SUBSYSTEM LIBLDB +################################################ + +################################################ +# Start BINARY ldbadd +[BINARY::ldbadd] +OBJ_FILES= \ + lib/ldb/tools/ldbadd.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB +# End BINARY ldbadd +################################################ + +################################################ +# Start BINARY ldbdel +[BINARY::ldbdel] +OBJ_FILES= \ + lib/ldb/tools/ldbdel.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB +# End BINARY ldbdel +################################################ + +################################################ +# Start BINARY ldbmodify +[BINARY::ldbmodify] +OBJ_FILES= \ + lib/ldb/tools/ldbmodify.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB +# End BINARY ldbmodify +################################################ + +################################################ +# Start BINARY ldbsearch +[BINARY::ldbsearch] +OBJ_FILES= \ + lib/ldb/tools/ldbsearch.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB +# End BINARY ldbsearch +################################################ + +################################################ +# Start BINARY ldbedit +[BINARY::ldbedit] +OBJ_FILES= \ + lib/ldb/tools/ldbedit.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB +# End BINARY ldbedit +################################################ diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index 6ac5d91079..5af1d08d20 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -33,8 +33,9 @@ else AC_MSG_RESULT(no) fi +#hack +LIBS="$LIBS ${TMP_LIBPOPT_LIBS}" + SMB_SUBSYSTEM(LIBPOPT,[], [${TMP_LIBPOPT_OBJS}], - [], - [], - [${TMP_LIBPOPT_LIBS}]) + []) diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 3600ab62ea..4d1726c542 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -83,7 +83,7 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia if (!NT_STATUS_IS_OK(status)) return WERR_GENERAL_FAILURE; - static_init_reg; + static_init_registry; reg_first_init = False; } diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index d8acb26397..af4470d983 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -5,16 +5,28 @@ if test t$BLDSHARED = ttrue; then fi LIBWINREG=libwinregistry -PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(reg_gconf,STATIC) - CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building reg_gconf])]) +PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(registry_gconf,STATIC) + CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building registry_gconf])]) +AC_CONFIG_FILES(lib/registry/winregistry.pc) -PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) +SMB_BINARY_ENABLE(gregedit,NO) -SMB_MODULE(reg_nt4, REG, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) -SMB_MODULE(reg_w95, REG, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) -SMB_MODULE(reg_dir, REG, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) -SMB_MODULE(reg_rpc, REG, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o) -SMB_MODULE(reg_gconf, REG, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [$GCONF_LIBS]) -SMB_MODULE(reg_ldb, REG, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o) -SMB_SUBSYSTEM(REG,lib/registry/common/reg_interface.o,[lib/registry/common/reg_objects.o lib/registry/common/reg_util.o],lib/registry/common/winregistry_proto.h,[]) -AC_CONFIG_FILES(lib/registry/winregistry.pc) +PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ SMB_BINARY_ENABLE(gregedit,YES) + CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) + +SMB_MODULE(registry_nt4, REGISTRY, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) +SMB_MODULE(registry_w95, REGISTRY, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) +SMB_MODULE(registry_dir, REGISTRY, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) +SMB_MODULE(registry_rpc, REGISTRY, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o,[],[],[LIBSMB]) +SMB_MODULE(registry_gconf, REGISTRY, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o]) +SMB_MODULE(registry_ldb, REGISTRY, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o,[],[],[LIBLDB]) +SMB_SUBSYSTEM(REGISTRY,lib/registry/common/reg_interface.o, + [lib/registry/common/reg_objects.o lib/registry/common/reg_util.o], + [], + [LIBBASIC]) + +SMB_BINARY(regdiff, [REG], [BIN], lib/registry/tools/regdiff.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_BINARY(regpatch, [REG], [BIN], lib/registry/tools/regpatch.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_BINARY(regshell, [REG], [BIN], lib/registry/tools/regshell.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_BINARY(regtree, [REG], [BIN], lib/registry/tools/regtree.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 960d5f3e04..517324fdd2 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -138,7 +138,7 @@ static struct registry_ops reg_backend_dir = { .del_value = reg_dir_del_value, }; -NTSTATUS reg_dir_init(void) +NTSTATUS registry_dir_init(void) { return register_backend("registry", ®_backend_dir); } diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 1acb3cbcec..8f9fd6625b 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -194,7 +194,7 @@ static struct registry_ops reg_backend_gconf = { */ }; -NTSTATUS reg_gconf_init(void) +NTSTATUS registry_gconf_init(void) { return register_backend("registry", ®_backend_gconf); } diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 9e561b1e6c..498dc6991b 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/registry/common/registry.h" -char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) +static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) { char *ret = talloc_strdup(mem_ctx, "(dn="); char *begin = (char *)path; @@ -116,7 +116,7 @@ static struct registry_ops reg_backend_ldb = { .fetch_subkeys = ldb_fetch_subkeys, }; -NTSTATUS reg_ldb_init(void) +NTSTATUS registry_ldb_init(void) { return register_backend("registry", ®_backend_ldb); } diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index ff39954a9f..cb3c284811 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1752,7 +1752,7 @@ static struct registry_ops reg_backend_nt4 = { */ }; -NTSTATUS reg_nt4_init(void) +NTSTATUS registry_nt4_init(void) { return register_backend("registry", ®_backend_nt4); } diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index de2c2261b9..0b2919366d 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -429,7 +429,7 @@ static struct registry_ops reg_backend_rpc = { .num_values = rpc_num_values, }; -NTSTATUS reg_rpc_init(void) +NTSTATUS registry_rpc_init(void) { return register_backend("registry", ®_backend_rpc); } diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 80108fd541..c5d2e24103 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -361,7 +361,7 @@ static struct registry_ops reg_backend_w95 = { .get_subkey_by_index = w95_get_subkey_by_index, }; -NTSTATUS reg_w95_init(void) +NTSTATUS registry_w95_init(void) { return register_backend("registry", ®_backend_w95); } diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c index fd7d04bcf0..249af27e13 100644 --- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c +++ b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c @@ -26,7 +26,7 @@ static REG_OPS reg_backend_wine = { .name = "wine", }; -NTSTATUS reg_wine_init(void) +NTSTATUS registry_wine_init(void) { register_backend("registry", ®_backend_wine); return NT_STATUS_OK; diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 4bbde9a37d..b5751ca00b 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -142,7 +142,7 @@ static void registry_load_root() gtk_widget_set_sensitive( save_as, True ); } -GtkWidget* create_rpcwin (void) +static GtkWidget* create_rpcwin (void) { GtkWidget *dialog_vbox1; GtkWidget *table1; @@ -242,7 +242,7 @@ static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) gtk_widget_destroy(openfilewin); } -void on_open_gconf_activate (GtkMenuItem *menuitem, +static void on_open_gconf_activate (GtkMenuItem *menuitem, gpointer user_data) { WERROR error = reg_open("gconf", NULL, NULL, ®istry); @@ -254,8 +254,7 @@ void on_open_gconf_activate (GtkMenuItem *menuitem, registry_load_root(); } -void -on_open_remote_activate (GtkMenuItem *menuitem, +static void on_open_remote_activate (GtkMenuItem *menuitem, gpointer user_data) { char *location, *credentials; @@ -281,8 +280,7 @@ on_open_remote_activate (GtkMenuItem *menuitem, } -void -on_save_activate (GtkMenuItem *menuitem, +static void on_save_activate (GtkMenuItem *menuitem, gpointer user_data) { WERROR error = reg_save(registry, NULL); @@ -292,8 +290,7 @@ on_save_activate (GtkMenuItem *menuitem, } -void -on_save_as_activate (GtkMenuItem *menuitem, +static void on_save_as_activate (GtkMenuItem *menuitem, gpointer user_data) { gint result; @@ -316,55 +313,49 @@ on_save_as_activate (GtkMenuItem *menuitem, } -void -on_quit_activate (GtkMenuItem *menuitem, +static void on_quit_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk_main_quit(); } -void -on_cut_activate (GtkMenuItem *menuitem, +static void on_cut_activate (GtkMenuItem *menuitem, gpointer user_data) { /* FIXME */ } -void -on_copy_activate (GtkMenuItem *menuitem, +static void on_copy_activate (GtkMenuItem *menuitem, gpointer user_data) { /* FIXME */ } -void -on_paste_activate (GtkMenuItem *menuitem, +static void on_paste_activate (GtkMenuItem *menuitem, gpointer user_data) { /* FIXME */ } -void -on_delete_activate (GtkMenuItem *menuitem, +static void on_delete_activate (GtkMenuItem *menuitem, gpointer user_data) { /* FIXME */ } -void -on_about_activate (GtkMenuItem *menuitem, +static void on_about_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk_dialog_run(GTK_DIALOG(create_aboutwin())); gtk_widget_destroy(aboutwin); } -void on_key_activate (GtkTreeView *treeview, +static void on_key_activate (GtkTreeView *treeview, GtkTreePath *path, gpointer user_data) { @@ -400,7 +391,7 @@ void on_key_activate (GtkTreeView *treeview, if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); } -GtkWidget* create_mainwin (void) +static GtkWidget* create_mainwin (void) { GtkWidget *vbox1; GtkWidget *menubar; @@ -685,7 +676,7 @@ static GtkWidget* create_aboutwin (void) } -GtkWidget* create_openfilewin (void) +static GtkWidget* create_openfilewin (void) { GtkWidget *ok_button; GtkWidget *cancel_button; @@ -704,7 +695,7 @@ GtkWidget* create_openfilewin (void) return openfilewin; } -GtkWidget* create_savefilewin (void) +static GtkWidget* create_savefilewin (void) { GtkWidget *ok_button; GtkWidget *cancel_button; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 888270f61f..d9419208cd 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -21,7 +21,7 @@ #include "includes.h" -void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) +static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) { int i; REG_KEY *t1, *t2; diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index d4b036afe9..64c2637a0c 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -664,7 +664,7 @@ static CMD_FILE *cmd_file_create(const char *file) char *str_type(unsigned char type); -int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) +static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) { CMD *cmd; BOOL modified = False; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index b78f4256f0..e8b01081e8 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -173,7 +173,7 @@ static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) return NULL; } -REG_KEY *process_cmd(REG_KEY *k, char *line) +static REG_KEY *process_cmd(REG_KEY *k, char *line) { int argc; char **argv = NULL; @@ -196,7 +196,7 @@ REG_KEY *process_cmd(REG_KEY *k, char *line) return k; } -int main (int argc, char **argv) + int main(int argc, char **argv) { int opt; const char *backend = "dir"; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 4d0d4b2909..477c63af2c 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -21,7 +21,7 @@ #include "includes.h" -void print_tree(int l, REG_KEY *p, int fullpath, int novals) +static void print_tree(int l, REG_KEY *p, int fullpath, int novals) { REG_KEY *subkey; REG_VAL *value; -- cgit From 9c4a4514633e1b2296ab610b600b27fe439404fa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 10:38:11 +0000 Subject: r668: fix the build metze (This used to be commit ba5e71f59e0547aa8329661c7fec73a6469726a5) --- source4/lib/registry/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index af4470d983..85b0fad41a 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -18,7 +18,7 @@ SMB_MODULE(registry_nt4, REGISTRY, STATIC, lib/registry/reg_backend_nt4/reg_back SMB_MODULE(registry_w95, REGISTRY, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) SMB_MODULE(registry_dir, REGISTRY, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(registry_rpc, REGISTRY, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o,[],[],[LIBSMB]) -SMB_MODULE(registry_gconf, REGISTRY, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o]) +SMB_MODULE(registry_gconf, REGISTRY, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o) SMB_MODULE(registry_ldb, REGISTRY, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o,[],[],[LIBLDB]) SMB_SUBSYSTEM(REGISTRY,lib/registry/common/reg_interface.o, [lib/registry/common/reg_objects.o lib/registry/common/reg_util.o], -- cgit From 0a690c12a14b96a3f50b1e37875944cb3cf2b967 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 10:53:52 +0000 Subject: r672: disable gregedit for now metze (This used to be commit 63600a2a9b2607130efe8e4336a48b5e9584d929) --- source4/lib/registry/config.m4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 85b0fad41a..ebe9a49439 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -11,7 +11,8 @@ AC_CONFIG_FILES(lib/registry/winregistry.pc) SMB_BINARY_ENABLE(gregedit,NO) -PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ SMB_BINARY_ENABLE(gregedit,YES) +#disable grpedit for now +PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ SMB_BINARY_ENABLE(gregedit,NO) CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) SMB_MODULE(registry_nt4, REGISTRY, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) -- cgit From 0b7f81e0f6e4a8eb8cd514541dcd39ebed07b7f0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 11:32:39 +0000 Subject: r673: disable registry_gconf for now metze (This used to be commit 5bbf0c240730fc27b7341eb7c6891c7741640e74) --- source4/lib/registry/config.m4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index ebe9a49439..7aafd2af71 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -5,7 +5,8 @@ if test t$BLDSHARED = ttrue; then fi LIBWINREG=libwinregistry -PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(registry_gconf,STATIC) +#disable registry_gconf for now +PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(registry_gconf,NOT) CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building registry_gconf])]) AC_CONFIG_FILES(lib/registry/winregistry.pc) -- cgit From 14832874ee24f7c658882c9323e4c0b98b13ceda Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 13:36:14 +0000 Subject: r681: don't init r.out.result.v metze (This used to be commit f7ded36699dabecf31ccaf765d667b7240822f8d) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 0b2919366d..c63ab20b82 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -291,7 +291,6 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) r.in.class = &classname; tm.low = tm.high = 0x7fffffff; r.in.last_changed_time = &tm; - r.out.result.v = 0; r.in.enum_index = n; r.in.unknown = r.out.unknown = 0x0414; -- cgit From d12e825042d1f108051eb6e205340dee444d5591 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 13 May 2004 15:34:56 +0000 Subject: r685: The SAM is dead! Long live the new SAM! ;-) This commit kills passdb, which was only hosting the auth subsystem. With the work tridge has done on Samba4's SAM backend, this can (and now is) all hosted on ldb. The auth_sam.c file now references this backend. You will need to assign your users passwords in ldb - adding a new line: unicodePwd: myPass to a record, using ldbedit, should be sufficient. Naturally, this assumes you have had your personal SAMR provisioning tutorial from tridge. Everybody else can still use the anonymous logins. Andrew Bartlett (This used to be commit 2aa0b55fb86648731d5f2201fa5a6aa993b7ca48) --- source4/lib/username.c | 46 ------ source4/lib/util_getent.c | 22 --- source4/lib/util_sid.c | 400 ++++++++++------------------------------------ 3 files changed, 81 insertions(+), 387 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/username.c b/source4/lib/username.c index 2d6cd651c5..3af9dbd027 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -25,16 +25,6 @@ static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N); static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N); -/***************************************************************** - Check if a user or group name is local (this is a *local* name for - *local* people, there's nothing for you here...). -*****************************************************************/ - -static BOOL name_is_local(const char *name) -{ - return !(strchr_m(name, *lp_winbind_separator())); -} - /***************************************************************** Splits passed user or group name to domain and user/group name parts Returns True if name was splitted and False otherwise. @@ -398,42 +388,6 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr if(user_in_group_list(user, *list +2, groups, n_groups)) return True; } - } else if (!name_is_local(*list)) { - /* - * If user name did not match and token is not - * a unix group and the token has a winbind separator in the - * name then see if it is a Windows group. - */ - - DOM_SID g_sid; - enum SID_NAME_USE name_type; - BOOL winbind_answered = False; - BOOL ret; - fstring groupname, domain; - - /* Parse a string of the form DOMAIN/user into a domain and a user */ - - char *p = strchr(*list,*lp_winbind_separator()); - - DEBUG(10,("user_in_list: checking if user |%s| is in winbind group |%s|\n", user, *list)); - - if (p) { - fstrcpy(groupname, p+1); - fstrcpy(domain, *list); - domain[PTR_DIFF(p, *list)] = 0; - - /* Check to see if name is a Windows group */ - if (winbind_lookup_name(domain, groupname, &g_sid, &name_type) && name_type == SID_NAME_DOM_GRP) { - - /* Check if user name is in the Windows group */ - ret = user_in_winbind_group_list(user, *list, &winbind_answered); - - if (winbind_answered && ret == True) { - DEBUG(10,("user_in_list: user |%s| is in winbind group |%s|\n", user, *list)); - return ret; - } - } - } } list++; diff --git a/source4/lib/util_getent.c b/source4/lib/util_getent.c index 32641dbf83..599e4bb917 100644 --- a/source4/lib/util_getent.c +++ b/source4/lib/util_getent.c @@ -249,29 +249,7 @@ struct sys_userlist *get_users_in_group(const char *gname) { struct sys_userlist *list_head = NULL; struct group *gptr; - fstring domain; - fstring groupname; - DOM_SID sid; - enum SID_NAME_USE name_type; - /* No point using winbind if we can't split it in the - first place */ - if (split_domain_and_name(gname, domain, groupname)) { - - /* - * If we're doing this via winbindd, don't do the - * entire group list enumeration as we know this is - * pointless (and slow). - */ - - if (winbind_lookup_name(domain, groupname, &sid, &name_type) - && name_type == SID_NAME_DOM_GRP) { - if ((gptr = (struct group *)getgrnam(gname)) == NULL) - return NULL; - return add_members_to_userlist(list_head, gptr); - } - } - #if !defined(BROKEN_GETGRNAM) if ((gptr = (struct group *)getgrnam(gname)) == NULL) return NULL; diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 44bb4cebb1..505555fe7e 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -28,29 +28,29 @@ * Some useful sids */ -DOM_SID global_sid_World_Domain; /* Everyone domain */ -DOM_SID global_sid_World; /* Everyone */ -DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner domain */ -DOM_SID global_sid_NT_Authority; /* NT Authority */ -DOM_SID global_sid_System; /* System */ -DOM_SID global_sid_NULL; /* NULL sid */ -DOM_SID global_sid_Authenticated_Users; /* All authenticated rids */ -DOM_SID global_sid_Network; /* Network rids */ - -DOM_SID global_sid_Creator_Owner; /* Creator Owner */ -DOM_SID global_sid_Creator_Group; /* Creator Group */ -DOM_SID global_sid_Anonymous; /* Anonymous login */ - -DOM_SID global_sid_Builtin; /* Local well-known domain */ -DOM_SID global_sid_Builtin_Administrators; /* Builtin administrators */ -DOM_SID global_sid_Builtin_Users; /* Builtin users */ -DOM_SID global_sid_Builtin_Guests; /* Builtin guest users */ -DOM_SID global_sid_Builtin_Power_Users; /* Builtin power users */ -DOM_SID global_sid_Builtin_Account_Operators; /* Builtin account operators */ -DOM_SID global_sid_Builtin_Server_Operators; /* Builtin server operators */ -DOM_SID global_sid_Builtin_Print_Operators; /* Builtin print operators */ -DOM_SID global_sid_Builtin_Backup_Operators; /* Builtin backup operators */ -DOM_SID global_sid_Builtin_Replicator; /* Builtin replicator */ +struct dom_sid *global_sid_World_Domain; /* Everyone domain */ +struct dom_sid *global_sid_World; /* Everyone */ +struct dom_sid *global_sid_Creator_Owner_Domain; /* Creator Owner domain */ +struct dom_sid *global_sid_NT_Authority; /* NT Authority */ +struct dom_sid *global_sid_System; /* System */ +struct dom_sid *global_sid_NULL; /* NULL sid */ +struct dom_sid *global_sid_Authenticated_Users; /* All authenticated rids */ +struct dom_sid *global_sid_Network; /* Network rids */ + +struct dom_sid *global_sid_Creator_Owner; /* Creator Owner */ +struct dom_sid *global_sid_Creator_Group; /* Creator Group */ +struct dom_sid *global_sid_Anonymous; /* Anonymous login */ + +struct dom_sid *global_sid_Builtin; /* Local well-known domain */ +struct dom_sid *global_sid_Builtin_Administrators; /* Builtin administrators */ +struct dom_sid *global_sid_Builtin_Users; /* Builtin users */ +struct dom_sid *global_sid_Builtin_Guests; /* Builtin guest users */ +struct dom_sid *global_sid_Builtin_Power_Users; /* Builtin power users */ +struct dom_sid *global_sid_Builtin_Account_Operators; /* Builtin account operators */ +struct dom_sid *global_sid_Builtin_Server_Operators; /* Builtin server operators */ +struct dom_sid *global_sid_Builtin_Print_Operators; /* Builtin print operators */ +struct dom_sid *global_sid_Builtin_Backup_Operators; /* Builtin backup operators */ +struct dom_sid *global_sid_Builtin_Replicator; /* Builtin replicator */ #define SECURITY_NULL_SID_AUTHORITY 0 #define SECURITY_WORLD_SID_AUTHORITY 1 @@ -58,23 +58,6 @@ DOM_SID global_sid_Builtin_Replicator; /* Builtin replicator */ #define SECURITY_CREATOR_SID_AUTHORITY 3 #define SECURITY_NT_AUTHORITY 5 -/* - * An NT compatible anonymous token. - */ - -static DOM_SID anon_sid_array[3]; - -NT_USER_TOKEN anonymous_token = { - 3, - anon_sid_array -}; - -static DOM_SID system_sid_array[4]; -NT_USER_TOKEN system_token = { - 1, - system_sid_array -}; - /**************************************************************************** Lookup string names for SID types. ****************************************************************************/ @@ -117,60 +100,47 @@ const char *sid_type_lookup(uint32 sid_type) void generate_wellknown_sids(void) { static BOOL initialised = False; + static TALLOC_CTX *mem_ctx; if (initialised) return; + mem_ctx = talloc_init("Well known groups, global static context"); + if (!mem_ctx) + return; + /* SECURITY_NULL_SID_AUTHORITY */ - string_to_sid(&global_sid_NULL, "S-1-0-0"); + global_sid_NULL = dom_sid_parse_talloc(mem_ctx, "S-1-0-0"); /* SECURITY_WORLD_SID_AUTHORITY */ - string_to_sid(&global_sid_World_Domain, "S-1-1"); - string_to_sid(&global_sid_World, "S-1-1-0"); + global_sid_World_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-1"); + global_sid_World = dom_sid_parse_talloc(mem_ctx, "S-1-1-0"); /* SECURITY_CREATOR_SID_AUTHORITY */ - string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); - string_to_sid(&global_sid_Creator_Owner, "S-1-3-0"); - string_to_sid(&global_sid_Creator_Group, "S-1-3-1"); + global_sid_Creator_Owner_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-3"); + global_sid_Creator_Owner = dom_sid_parse_talloc(mem_ctx, "S-1-3-0"); + global_sid_Creator_Group = dom_sid_parse_talloc(mem_ctx, "S-1-3-1"); /* SECURITY_NT_AUTHORITY */ - string_to_sid(&global_sid_NT_Authority, "S-1-5"); - string_to_sid(&global_sid_Network, "S-1-5-2"); - string_to_sid(&global_sid_Anonymous, "S-1-5-7"); - string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11"); - string_to_sid(&global_sid_System, "S-1-5-18"); + global_sid_NT_Authority = dom_sid_parse_talloc(mem_ctx, "S-1-5"); + global_sid_Network = dom_sid_parse_talloc(mem_ctx, "S-1-5-2"); + global_sid_Anonymous = dom_sid_parse_talloc(mem_ctx, "S-1-5-7"); + global_sid_Authenticated_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-11"); + global_sid_System = dom_sid_parse_talloc(mem_ctx, "S-1-5-18"); /* SECURITY_BUILTIN_DOMAIN_RID */ - string_to_sid(&global_sid_Builtin, "S-1-5-32"); - string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544"); - string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545"); - string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546"); - string_to_sid(&global_sid_Builtin_Power_Users, "S-1-5-32-547"); - string_to_sid(&global_sid_Builtin_Account_Operators, "S-1-5-32-548"); - string_to_sid(&global_sid_Builtin_Server_Operators, "S-1-5-32-549"); - string_to_sid(&global_sid_Builtin_Print_Operators, "S-1-5-32-550"); - string_to_sid(&global_sid_Builtin_Backup_Operators, "S-1-5-32-551"); - string_to_sid(&global_sid_Builtin_Replicator, "S-1-5-32-552"); - - /* Create the anon token. */ - sid_copy( &anonymous_token.user_sids[0], &global_sid_World); - sid_copy( &anonymous_token.user_sids[1], &global_sid_Network); - sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous); - - /* Create the system token. */ - sid_copy( &system_token.user_sids[0], &global_sid_System); - - initialised = True; -} + global_sid_Builtin = dom_sid_parse_talloc(mem_ctx, "S-1-5-32"); + global_sid_Builtin_Administrators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-544"); + global_sid_Builtin_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545"); + global_sid_Builtin_Guests = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-546"); + global_sid_Builtin_Power_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-547"); + global_sid_Builtin_Account_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-548"); + global_sid_Builtin_Server_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-549"); + global_sid_Builtin_Print_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-550"); + global_sid_Builtin_Backup_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-551"); + global_sid_Builtin_Replicator = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-552"); -/************************************************************************** - Create the SYSTEM token. -***************************************************************************/ - -NT_USER_TOKEN *get_system_token(void) -{ - generate_wellknown_sids(); /* The token is initialised here */ - return &system_token; + initialised = True; } /************************************************************************** @@ -208,153 +178,31 @@ void split_domain_name(const char *fullname, char *domain, char *name) fullname, domain, name)); } -/**************************************************************************** - Test if a SID is wellknown and resolvable. -****************************************************************************/ - -BOOL resolvable_wellknown_sid(DOM_SID *sid) -{ - uint32 ia = (sid->id_auth[5]) + - (sid->id_auth[4] << 8 ) + - (sid->id_auth[3] << 16) + - (sid->id_auth[2] << 24); - - if (sid->sid_rev_num != SEC_DESC_REVISION || sid->num_auths < 1) - return False; - - return (ia == SECURITY_WORLD_SID_AUTHORITY || - ia == SECURITY_CREATOR_SID_AUTHORITY); -} - /***************************************************************** Convert a SID to an ascii string. *****************************************************************/ -char *sid_to_string(fstring sidstr_out, const DOM_SID *sid) +char *sid_to_string(fstring sidstr_out, const struct dom_sid *sid) { - char subauth[16]; - int i; - uint32 ia; - - if (!sid) { - fstrcpy(sidstr_out, "(NULL SID)"); - return sidstr_out; - } - - /* - * BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 - * in a range of 2^48. - */ - ia = (sid->id_auth[5]) + - (sid->id_auth[4] << 8 ) + - (sid->id_auth[3] << 16) + - (sid->id_auth[2] << 24); - - slprintf(sidstr_out, sizeof(fstring) - 1, "S-%u-%lu", (unsigned int)sid->sid_rev_num, (unsigned long)ia); - - for (i = 0; i < sid->num_auths; i++) { - slprintf(subauth, sizeof(subauth)-1, "-%lu", (unsigned long)sid->sub_auths[i]); - fstrcat(sidstr_out, subauth); + char *tmp_string; + TALLOC_CTX *mem_ctx; + if (!(mem_ctx = talloc_init("sid_to_string temp context"))) { + return NULL; } + tmp_string = dom_sid_string(mem_ctx, sid); + if (!tmp_string) + return NULL; + + fstrcpy(sidstr_out, tmp_string); return sidstr_out; } -/***************************************************************** - Useful function for debug lines. -*****************************************************************/ - -const char *sid_string_talloc(TALLOC_CTX *mem_ctx, const DOM_SID *sid) -{ - fstring tempSid; - sid_to_string(tempSid, sid); - return talloc_strdup(mem_ctx, tempSid); -} - -/***************************************************************** - Convert a string to a SID. Returns True on success, False on fail. -*****************************************************************/ - -BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) -{ - pstring tok; - char *q; - const char *p; - /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ - uint32 ia; - - if (StrnCaseCmp( sidstr, "S-", 2)) { - DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr)); - return False; - } - - memset((char *)sidout, '\0', sizeof(DOM_SID)); - - p = q = strdup(sidstr + 2); - if (p == NULL) { - DEBUG(0, ("string_to_sid: out of memory!\n")); - return False; - } - - if (!next_token(&p, tok, "-", sizeof(tok))) { - DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); - SAFE_FREE(q); - return False; - } - - /* Get the revision number. */ - sidout->sid_rev_num = (uint8)strtoul(tok, NULL, 10); - - if (!next_token(&p, tok, "-", sizeof(tok))) { - DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr)); - SAFE_FREE(q); - return False; - } - - /* identauth in decimal should be < 2^32 */ - ia = (uint32)strtoul(tok, NULL, 10); - - /* NOTE - the ia value is in big-endian format. */ - sidout->id_auth[0] = 0; - sidout->id_auth[1] = 0; - sidout->id_auth[2] = (ia & 0xff000000) >> 24; - sidout->id_auth[3] = (ia & 0x00ff0000) >> 16; - sidout->id_auth[4] = (ia & 0x0000ff00) >> 8; - sidout->id_auth[5] = (ia & 0x000000ff); - - sidout->num_auths = 0; - - while(next_token(&p, tok, "-", sizeof(tok)) && - sidout->num_auths < MAXSUBAUTHS) { - /* - * NOTE - the subauths are in native machine-endian format. They - * are converted to little-endian when linearized onto the wire. - */ - sid_append_rid(sidout, (uint32)strtoul(tok, NULL, 10)); - } - - SAFE_FREE(q); - return True; -} - -/***************************************************************** - Add a rid to the end of a sid -*****************************************************************/ - -BOOL sid_append_rid(DOM_SID *sid, uint32 rid) -{ - if (sid->num_auths < MAXSUBAUTHS) { - sid->sub_auths[sid->num_auths++] = rid; - return True; - } - return False; -} - /***************************************************************** Removes the last rid from the end of a sid *****************************************************************/ -BOOL sid_split_rid(DOM_SID *sid, uint32 *rid) +BOOL sid_split_rid(struct dom_sid *sid, uint32 *rid) { if (sid->num_auths > 0) { sid->num_auths--; @@ -368,7 +216,7 @@ BOOL sid_split_rid(DOM_SID *sid, uint32 *rid) Return the last rid from the end of a sid *****************************************************************/ -BOOL sid_peek_rid(const DOM_SID *sid, uint32 *rid) +BOOL sid_peek_rid(const struct dom_sid *sid, uint32 *rid) { if (!sid || !rid) return False; @@ -385,7 +233,7 @@ BOOL sid_peek_rid(const DOM_SID *sid, uint32 *rid) and check the sid against the exp_dom_sid *****************************************************************/ -BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 *rid) +BOOL sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32 *rid) { if (!exp_dom_sid || !sid || !rid) return False; @@ -399,72 +247,11 @@ BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 * return sid_peek_rid(sid, rid); } -/***************************************************************** - Copies a sid -*****************************************************************/ - -void sid_copy(DOM_SID *dst, const DOM_SID *src) -{ - int i; - - ZERO_STRUCTP(dst); - - dst->sid_rev_num = src->sid_rev_num; - dst->num_auths = src->num_auths; - - memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth)); - - for (i = 0; i < src->num_auths; i++) - dst->sub_auths[i] = src->sub_auths[i]; -} - -/***************************************************************** - Write a sid out into on-the-wire format. -*****************************************************************/ - -BOOL sid_linearize(char *outbuf, size_t len, const DOM_SID *sid) -{ - size_t i; - - if (len < sid_size(sid)) - return False; - - SCVAL(outbuf,0,sid->sid_rev_num); - SCVAL(outbuf,1,sid->num_auths); - memcpy(&outbuf[2], sid->id_auth, 6); - for(i = 0; i < sid->num_auths; i++) - SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]); - - return True; -} - -/***************************************************************** - Parse a on-the-wire SID to a DOM_SID. -*****************************************************************/ - -BOOL sid_parse(const char *inbuf, size_t len, DOM_SID *sid) -{ - int i; - if (len < 8) - return False; - - ZERO_STRUCTP(sid); - - sid->sid_rev_num = CVAL(inbuf, 0); - sid->num_auths = CVAL(inbuf, 1); - memcpy(sid->id_auth, inbuf+2, 6); - if (len < 8 + sid->num_auths*4) - return False; - for (i=0;inum_auths;i++) - sid->sub_auths[i] = IVAL(inbuf, 8+i*4); - return True; -} - /***************************************************************** Compare the auth portion of two sids. *****************************************************************/ -static int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2) +static int sid_compare_auth(const struct dom_sid *sid1, const struct dom_sid *sid2) { int i; @@ -489,7 +276,7 @@ static int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2) Compare two sids. *****************************************************************/ -int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2) +int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) { int i; @@ -516,7 +303,7 @@ int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2) this just compares the leading sub-auths *****************************************************************/ -int sid_compare_domain(const DOM_SID *sid1, const DOM_SID *sid2) +int sid_compare_domain(const struct dom_sid *sid1, const struct dom_sid *sid2) { int n, i; @@ -533,40 +320,36 @@ int sid_compare_domain(const DOM_SID *sid1, const DOM_SID *sid2) Compare two sids. *****************************************************************/ -BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) +BOOL sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2) { return sid_compare(sid1, sid2) == 0; } - /***************************************************************** - Check if the SID is the builtin SID (S-1-5-32). + Write a sid out into on-the-wire format. *****************************************************************/ -BOOL sid_check_is_builtin(const DOM_SID *sid) +BOOL sid_linearize(char *outbuf, size_t len, const struct dom_sid *sid) { - return sid_equal(sid, &global_sid_Builtin); -} + size_t i; -/***************************************************************** - Check if the SID is one of the builtin SIDs (S-1-5-32-a). -*****************************************************************/ + if (len < sid_size(sid)) + return False; -BOOL sid_check_is_in_builtin(const DOM_SID *sid) -{ - DOM_SID dom_sid; - uint32 rid; + SCVAL(outbuf,0,sid->sid_rev_num); + SCVAL(outbuf,1,sid->num_auths); + memcpy(&outbuf[2], sid->id_auth, 6); + for(i = 0; i < sid->num_auths; i++) + SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]); - sid_copy(&dom_sid, sid); - sid_split_rid(&dom_sid, &rid); - - return sid_equal(&dom_sid, &global_sid_Builtin); + return True; } + /***************************************************************** Calculates size of a sid. *****************************************************************/ -size_t sid_size(const DOM_SID *sid) +size_t sid_size(const struct dom_sid *sid) { if (sid == NULL) return 0; @@ -574,33 +357,12 @@ size_t sid_size(const DOM_SID *sid) return sid->num_auths * sizeof(uint32) + 8; } -/***************************************************************** - Returns true if SID is internal (and non-mappable). -*****************************************************************/ - -BOOL non_mappable_sid(DOM_SID *sid) -{ - DOM_SID dom; - uint32 rid; - - sid_copy(&dom, sid); - sid_split_rid(&dom, &rid); - - if (sid_equal(&dom, &global_sid_Builtin)) - return True; - - if (sid_equal(&dom, &global_sid_NT_Authority)) - return True; - - return False; -} - /***************************************************************** Return the binary string representation of a DOM_SID. Caller must free. *****************************************************************/ -char *sid_binstring(const DOM_SID *sid) +char *sid_binstring(const struct dom_sid *sid) { char *buf, *s; int len = sid_size(sid); -- cgit From 0048335d9e3e0c7db61f6a325a3d7f49037810c3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 May 2004 15:37:57 +0000 Subject: r686: - Add SMB_EXT_LIB_FROM_PKGCONFIG() - Build gregedit and registry_gconf again if the required libs are found (gconf and gtk) (This used to be commit a63b704c36f2f5b52e932b6b2c99e7d664c9bdc7) --- source4/lib/registry/config.m4 | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 7aafd2af71..da2c84d5c6 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -5,22 +5,28 @@ if test t$BLDSHARED = ttrue; then fi LIBWINREG=libwinregistry -#disable registry_gconf for now -PKG_CHECK_MODULES(GCONF, gconf-2.0, [ SMB_MODULE_DEFAULT(registry_gconf,NOT) - CFLAGS="$CFLAGS $GCONF_CFLAGS";], [AC_MSG_WARN([GConf not found, not building registry_gconf])]) AC_CONFIG_FILES(lib/registry/winregistry.pc) -SMB_BINARY_ENABLE(gregedit,NO) +SMB_BINARY_ENABLE(gregedit, NO) +SMB_MODULE_DEFAULT(registry_gconf, NOT) -#disable grpedit for now -PKG_CHECK_MODULES(GTK, glib-2.0 gtk+-2.0, [ SMB_BINARY_ENABLE(gregedit,NO) - CFLAGS="$CFLAGS $GTK_CFLAGS"; ], [ AC_MSG_WARN([Will be unable to build gregedit])]) +SMB_EXT_LIB_FROM_PKGCONFIG(gconf, gconf-2.0) + +if test t$SMB_EXT_LIB_ENABLE_gconf = tYES; then + SMB_MODULE_DEFAULT(registry_gconf, STATIC) +fi + +SMB_EXT_LIB_FROM_PKGCONFIG(gtk, [glib-2.0 gtk+-2.0]) + +if test t$SMB_EXT_LIB_ENABLE_gtk = tYES; then + SMB_BINARY_ENABLE(gregedit, YES) +fi SMB_MODULE(registry_nt4, REGISTRY, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) SMB_MODULE(registry_w95, REGISTRY, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) SMB_MODULE(registry_dir, REGISTRY, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) SMB_MODULE(registry_rpc, REGISTRY, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o,[],[],[LIBSMB]) -SMB_MODULE(registry_gconf, REGISTRY, NOT, lib/registry/reg_backend_gconf/reg_backend_gconf.o) +SMB_MODULE(registry_gconf, REGISTRY, STATIC, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [gconf]) SMB_MODULE(registry_ldb, REGISTRY, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o,[],[],[LIBLDB]) SMB_SUBSYSTEM(REGISTRY,lib/registry/common/reg_interface.o, [lib/registry/common/reg_objects.o lib/registry/common/reg_util.o], @@ -31,4 +37,5 @@ SMB_BINARY(regdiff, [REG], [BIN], lib/registry/tools/regdiff.o,[],[CONFIG LIBBAS SMB_BINARY(regpatch, [REG], [BIN], lib/registry/tools/regpatch.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) SMB_BINARY(regshell, [REG], [BIN], lib/registry/tools/regshell.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) SMB_BINARY(regtree, [REG], [BIN], lib/registry/tools/regtree.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[gtk],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) + -- cgit From d5ba19d0088f65e308443a32dd39c11d6ba8983d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 16:15:46 +0000 Subject: r690: - ignore source/tags - add support for shared libraries - enable libldb shared lib when --enable-experimental metze (This used to be commit dcef69dc54a2575e7f57d67d1983482b4ff57bdb) --- source4/lib/ldb/config.m4 | 6 ++++++ source4/lib/ldb/config.mk | 11 +++++++++++ 2 files changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 16805132fd..5206a0fbfe 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -8,6 +8,12 @@ SMB_MODULE_MK(libldb_tdb,LIBLDB,STATIC,lib/ldb/config.mk) SMB_SUBSYSTEM_MK(LIBLDB,lib/ldb/config.mk) +if test x"$experimental" = x"yes"; then + SMB_LIBRARY_ENABLE(libldb,YES) +fi + +SMB_LIBRARY_MK(libldb,lib/ldb/config.mk) + SMB_BINARY_MK(ldbadd,lib/ldb/config.mk) SMB_BINARY_MK(ldbdel,lib/ldb/config.mk) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index c44d3e6bf0..e4789c50b1 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -37,6 +37,17 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBLDB ################################################ +################################################ +# Start LIBRARY LIBLDB +[LIBRARY::libldb] +MAJOR_VERSION = 0 +MINOR_VERSION = 0 +RELEASE_VERSION = 1 +REQUIRED_SUBSYSTEMS = LIBLDB +# +# End LIBRARY LIBLDB +################################################ + ################################################ # Start BINARY ldbadd [BINARY::ldbadd] -- cgit From 76d50e0d264e7d000fe8c0bb332b083084f2e1d8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 May 2004 16:45:01 +0000 Subject: r692: Add libwinregistry (This used to be commit 0ace3bf289777c30310a05e66fd674337413f0d8) --- source4/lib/registry/config.m4 | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index da2c84d5c6..7b05cbb982 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -39,3 +39,8 @@ SMB_BINARY(regshell, [REG], [BIN], lib/registry/tools/regshell.o,[],[CONFIG LIBB SMB_BINARY(regtree, [REG], [BIN], lib/registry/tools/regtree.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[gtk],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +if test x"$experimental" = xyes; then + SMB_LIBRARY_ENABLE(libwinregistry, YES) +fi + +SMB_LIBRARY(libwinregistry, 0, 0, 1, , , REGISTRY) -- cgit From 072ef868c333f47cb3f2bf04a8edcf80c944b85e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 May 2004 16:47:32 +0000 Subject: r693: Make static (This used to be commit 30d3915c760ac5ee5e632539a3503fc7fed9cc63) --- source4/lib/registry/tools/gregedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index b5751ca00b..7b06b2266f 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -47,8 +47,8 @@ GtkWidget *rpcwin_user; GtkWidget *rpcwin_password; GtkWidget *save; GtkWidget *save_as; -GtkWidget* create_openfilewin (void); -GtkWidget* create_savefilewin (void); +static GtkWidget* create_openfilewin (void); +static GtkWidget* create_savefilewin (void); static GtkWidget* create_aboutwin (void); REG_HANDLE *registry = NULL; -- cgit From ace1c1f816afe2104f830c9a0f76048e8ea2b0c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 18:06:45 +0000 Subject: r697: make use of SMB_EXT_LIB for LDAP and KRB5 metze (This used to be commit b054f7d4906d1d2b96b352af09c6bdcf96553c2a) --- source4/lib/ldb/config.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index e4789c50b1..09d4d421fb 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -3,6 +3,8 @@ [MODULE::libldb_ldap] INIT_OBJ_FILES = \ lib/ldb/ldb_ldap/ldb_ldap.o +REQUIRED_LIBRARIES = \ + LDAP # End MODULE libldb_tdb ################################################ @@ -43,7 +45,8 @@ ADD_OBJ_FILES = \ MAJOR_VERSION = 0 MINOR_VERSION = 0 RELEASE_VERSION = 1 -REQUIRED_SUBSYSTEMS = LIBLDB +REQUIRED_SUBSYSTEMS = \ + LIBLDB # # End LIBRARY LIBLDB ################################################ -- cgit From 77c30ebe9eaf72bdbfb519e252ad6d070c984fad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 May 2004 20:12:26 +0000 Subject: r700: fix SMB_LIBRARY() to disable the lib by default metze (This used to be commit b6ac3021f275ba6b0ee0035933c290db4e8bda00) --- source4/lib/registry/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 7b05cbb982..77508063fc 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -39,7 +39,7 @@ SMB_BINARY(regshell, [REG], [BIN], lib/registry/tools/regshell.o,[],[CONFIG LIBB SMB_BINARY(regtree, [REG], [BIN], lib/registry/tools/regtree.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[gtk],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -if test x"$experimental" = xyes; then +if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libwinregistry, YES) fi -- cgit From f2548cd87339eca45b19b9f8173844ca932c96c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 May 2004 00:22:26 +0000 Subject: r711: don't hide attributes inside the special ldb_tdb records (so the fact that a attribute is hidden is not itself hidden!) (This used to be commit b42d1f39842ac25fee2238040ac01321f71a79c5) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 25e22b3dd4..6b38a28296 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -136,7 +136,7 @@ static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret int i; for (i=0;inum_elements;i++) { int flags = ltdb_attribute_flags(ldb, msg->elements[i].name); - if (flags & LTDB_FLAG_HIDDEN) { + if ((msg->dn[0] != '@') && (flags & LTDB_FLAG_HIDDEN)) { continue; } if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { -- cgit From 71e22ef6b8c427a02df7ee5c9b36ccf61dc9a050 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 14 May 2004 00:26:37 +0000 Subject: r714: make sure ldb formats are portable between big/little endian machines (This used to be commit 166a664a00d2befe30978072e6f3f266b18ba9f4) --- source4/lib/ldb/ldb_tdb/ldb_pack.c | 32 ++++++++++++++++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 8 -------- 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index a32197e2cf..8d1051be94 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -41,6 +41,22 @@ /* old packing formats */ #define LTDB_PACKING_FORMAT_NODN 0x26011966 +/* use a portable integer format */ +static void put_uint32(unsigned char *p, int ofs, unsigned int val) +{ + p += ofs; + p[0] = val&0xFF; + p[1] = (val>>8) & 0xFF; + p[2] = (val>>16) & 0xFF; + p[3] = (val>>24) & 0xFF; +} + +static unsigned int pull_uint32(unsigned char *p, int ofs) +{ + p += ofs; + return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); +} + /* pack a ldb message into a linear buffer in a TDB_DATA @@ -82,8 +98,8 @@ int ltdb_pack_data(struct ldb_context *ldb, data->dsize = size; p = data->dptr; - SIVAL(p, 0, LTDB_PACKING_FORMAT); - SIVAL(p, 4, message->num_elements); + put_uint32(p, 0, LTDB_PACKING_FORMAT); + put_uint32(p, 4, message->num_elements); p += 8; /* the dn needs to be packed so we can be case preserving @@ -99,10 +115,10 @@ int ltdb_pack_data(struct ldb_context *ldb, len = strlen(message->elements[i].name); memcpy(p, message->elements[i].name, len+1); p += len + 1; - SIVAL(p, 0, message->elements[i].num_values); + put_uint32(p, 0, message->elements[i].num_values); p += 4; for (j=0;jelements[i].num_values;j++) { - SIVAL(p, 0, message->elements[i].values[j].length); + put_uint32(p, 0, message->elements[i].values[j].length); memcpy(p+4, message->elements[i].values[j].data, message->elements[i].values[j].length); p[4+message->elements[i].values[j].length] = 0; @@ -156,8 +172,8 @@ int ltdb_unpack_data(struct ldb_context *ldb, goto failed; } - format = IVAL(p, 0); - message->num_elements = IVAL(p, 4); + format = pull_uint32(p, 0); + message->num_elements = pull_uint32(p, 4); p += 8; remaining = data->dsize - 8; @@ -215,7 +231,7 @@ int ltdb_unpack_data(struct ldb_context *ldb, message->elements[i].name = p; remaining -= len + 1; p += len + 1; - message->elements[i].num_values = IVAL(p, 0); + message->elements[i].num_values = pull_uint32(p, 0); message->elements[i].values = NULL; if (message->elements[i].num_values != 0) { message->elements[i].values = ldb_malloc_array_p(ldb, @@ -228,7 +244,7 @@ int ltdb_unpack_data(struct ldb_context *ldb, } p += 4; for (j=0;jelements[i].num_values;j++) { - len = IVAL(p, 0); + len = pull_uint32(p, 0); if (len > remaining-5) { errno = EIO; goto failed; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index b678aac631..b6660c5825 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -43,11 +43,3 @@ struct ltdb_private { #define LTDB_FLAG_WILDCARD (1<<2) #define LTDB_FLAG_OBJECTCLASS (1<<3) #define LTDB_FLAG_HIDDEN (1<<4) - - -#ifndef IVAL -#define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) -#endif -#ifndef SIVAL -#define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0) -#endif -- cgit From 0f14ae46f34ac767f18d7de086f9994f4502bc48 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 14 May 2004 01:15:16 +0000 Subject: r715: Finish the ldb conversion for the auth_sam module. Andrew Bartlett (This used to be commit 099151cdabd40e724b36482c0ffc169d231146d2) --- source4/lib/util_sid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 505555fe7e..6f63e25c5d 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -206,7 +206,8 @@ BOOL sid_split_rid(struct dom_sid *sid, uint32 *rid) { if (sid->num_auths > 0) { sid->num_auths--; - *rid = sid->sub_auths[sid->num_auths]; + if (rid) + *rid = sid->sub_auths[sid->num_auths]; return True; } return False; -- cgit From a2273116fbb5890680c11fecba1bfd0026b7dd9b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 May 2004 12:09:21 +0000 Subject: r728: - let libldb_tdb depend on new subsystem LIBTDB - remove tdb logging helper functions out of LIBTDB subsystem - build libtdb shared lib with 'make library_libtdb' the libs are not usable for now, tridge: please remove the dependecy of CatchSignal() and smb_panic() from libtdb maybe use function pointers in the TDB_CONTEXT then run make library_libtdb and then make build/tests/trivial.o and then gcc -o trivial -L./bin -ltdb and then gcc -o trivial -L./bin -lldb metze (This used to be commit 520b9762161d9b5d5223b42910494af80fd5c1e3) --- source4/lib/basic.m4 | 6 +-- source4/lib/ldb/config.mk | 2 + source4/lib/tdb/config.m4 | 9 +++++ source4/lib/tdb/config.mk | 23 ++++++++++++ source4/lib/tdb/tdb.h | 2 + source4/lib/tdb/tdbutil.c | 93 +++++++++++++++++------------------------------ source4/lib/tdb_helper.c | 67 ++++++++++++++++++++++++++++++++++ 7 files changed, 140 insertions(+), 62 deletions(-) create mode 100644 source4/lib/tdb/config.m4 create mode 100644 source4/lib/tdb/config.mk create mode 100644 source4/lib/tdb_helper.c (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index ac5f82440e..b575bad9b8 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -21,6 +21,6 @@ SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], lib/gencache.o lib/module.o lib/mutex.o lib/ldap_escape.o lib/events.o lib/crypto/crc32.o lib/crypto/md5.o - lib/crypto/hmacmd5.o lib/crypto/md4.o - lib/tdb/tdb.o lib/tdb/spinlock.o lib/tdb/tdbutil.o],[], - [CHARSET]) + lib/crypto/hmacmd5.o lib/crypto/md4.o + lib/tdb_helper.o],[], + [LIBTDB CHARSET]) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 09d4d421fb..677c31ac28 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -19,6 +19,8 @@ ADD_OBJ_FILES = \ lib/ldb/ldb_tdb/ldb_index.o \ lib/ldb/ldb_tdb/ldb_match.o \ lib/ldb/ldb_tdb/ldb_cache.o +REQUIRED_SUBSYSTEMS = \ + LIBTDB # End MODULE libldb_tdb ################################################ diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 new file mode 100644 index 0000000000..12d88ed6a8 --- /dev/null +++ b/source4/lib/tdb/config.m4 @@ -0,0 +1,9 @@ + +SMB_SUBSYSTEM_MK(LIBTDB,lib/tdb/config.mk) + +if test x"$experimental" = x"yes"; then + SMB_LIBRARY_ENABLE(libtdb,YES) +fi + +SMB_LIBRARY_MK(libtdb,lib/tdb/config.mk) + diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk new file mode 100644 index 0000000000..797c793ce3 --- /dev/null +++ b/source4/lib/tdb/config.mk @@ -0,0 +1,23 @@ +################################################ +# Start SUBSYSTEM LIBTDB +[SUBSYSTEM::LIBTDB] +INIT_OBJ_FILES = \ + lib/tdb/tdb.o +ADD_OBJ_FILES = \ + lib/tdb/tdbutil.o \ + lib/tdb/spinlock.o +# +# End SUBSYSTEM LIBLDB +################################################ + +################################################ +# Start LIBRARY LIBTDB +[LIBRARY::libtdb] +MAJOR_VERSION = 0 +MINOR_VERSION = 0 +RELEASE_VERSION = 1 +REQUIRED_SUBSYSTEMS = \ + LIBTDB +# +# End LIBRARY LIBLDB +################################################ diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h index 281925068c..73a0ea8f83 100644 --- a/source4/lib/tdb/tdb.h +++ b/source4/lib/tdb/tdb.h @@ -105,6 +105,8 @@ typedef struct tdb_context { int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; +void tdb_debug(TDB_CONTEXT *, int , const char *, ...); + typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index 4a4423d2ce..9a0e8b0c44 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -51,7 +51,7 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) Lock a chain with timeout (in seconds). ****************************************************************************/ -static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) { /* Allow tdb_chainlock to be interrupted by an alarm. */ int ret; @@ -72,8 +72,8 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, alarm(0); CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); if (gotalarm) { - DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", - timeout, key.dptr, tdb->name )); + tdb_debug(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb->name ); /* TODO: If we time out waiting for a lock, it might * be nice to use F_GETLK to get the pid of the * process currently holding the lock and print that @@ -89,7 +89,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, Write lock a chain. Return -1 if timeout or lock failed. ****************************************************************************/ -int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) { return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); } @@ -384,7 +384,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv integers and strings. ****************************************************************************/ -size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) +size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; uint8 bt; @@ -452,8 +452,8 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) } break; default: - DEBUG(0,("Unknown tdb_pack format %c in %s\n", - c, fmt)); + tdb_debug(tdb, 0,"Unknown tdb_pack format %c in %s\n", + c, fmt); len = 0; break; } @@ -467,8 +467,8 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) va_end(ap); - DEBUG(18,("tdb_pack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + tdb_debug(tdb, 18,"tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); } @@ -478,7 +478,7 @@ size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...) integers and strings. ****************************************************************************/ -int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) +int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; uint8 *bt; @@ -559,8 +559,8 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) memcpy(*b, buf+4, *i); break; default: - DEBUG(0,("Unknown tdb_unpack format %c in %s\n", - c, fmt)); + tdb_debug(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + c, fmt); len = 0; break; @@ -572,8 +572,8 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) va_end(ap); - DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0))); + tdb_debug(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); @@ -591,22 +591,22 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) * * @return length of the packed representation of the whole structure **/ -size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) +size_t tdb_sid_pack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, DOM_SID* sid) { int idx; size_t len = 0; if (!sid || !pack_buf) return -1; - len += tdb_pack(pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, + len += tdb_pack(tdb, pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, sid->num_auths); for (idx = 0; idx < 6; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); + len += tdb_pack(tdb, pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); } for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_pack(pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); + len += tdb_pack(tdb, pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); } return len; @@ -622,65 +622,40 @@ size_t tdb_sid_pack(char* pack_buf, int bufsize, DOM_SID* sid) * * @return size of structure unpacked from buffer **/ -size_t tdb_sid_unpack(char* pack_buf, int bufsize, DOM_SID* sid) +size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, DOM_SID* sid) { int idx, len = 0; if (!sid || !pack_buf) return -1; - len += tdb_unpack(pack_buf + len, bufsize - len, "bb", + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb", &sid->sid_rev_num, &sid->num_auths); for (idx = 0; idx < 6; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); } for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_unpack(pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); } return len; } + /**************************************************************************** - Log tdb messages via DEBUG(). + Print out debug messages. ****************************************************************************/ -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +void tdb_debug(TDB_CONTEXT *tdb, int level, const char *fmt, ...) { va_list ap; - char *ptr = NULL; - - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - - if (!ptr || !*ptr) + if (tdb->log_fn == NULL) { return; - - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); - SAFE_FREE(ptr); -} - -/**************************************************************************** - Like tdb_open() but also setup a logging function that redirects to - the samba DEBUG() system. -****************************************************************************/ - -TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - TDB_CONTEXT *tdb; - - if (!lp_use_mmap()) - tdb_flags |= TDB_NOMMAP; - - tdb = tdb_open_ex(name, hash_size, tdb_flags, - open_flags, mode, tdb_log); - if (!tdb) - return NULL; - - return tdb; + } + va_start(ap, fmt); + tdb->log_fn(tdb, level, fmt, ap); + va_end(ap); } @@ -715,11 +690,11 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) /* duplicate key string to ensure null-termination */ char *key_str = (char*) strndup(key.dptr, key.dsize); if (!key_str) { - DEBUG(0, ("tdb_search_keys: strndup() failed!\n")); + tdb_debug(tdb, 0, "tdb_search_keys: strndup() failed!\n"); smb_panic("strndup failed!\n"); } - - DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern)); + + tdb_debug(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); next = tdb_nextkey(tdb, key); @@ -732,7 +707,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) DLIST_ADD_END(list, rec, TDB_LIST_NODE *); - DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern)); + tdb_debug(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); } else { free(key.dptr); } diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c new file mode 100644 index 0000000000..121243bd0f --- /dev/null +++ b/source4/lib/tdb_helper.c @@ -0,0 +1,67 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + + +/**************************************************************************** + Log tdb messages via DEBUG(). +****************************************************************************/ + +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (!ptr || !*ptr) + return; + + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + SAFE_FREE(ptr); +} + +/**************************************************************************** + Like tdb_open() but also setup a logging function that redirects to + the samba DEBUG() system. +****************************************************************************/ + +TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + TDB_CONTEXT *tdb; + + if (!lp_use_mmap()) + tdb_flags |= TDB_NOMMAP; + + tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, tdb_log); + if (!tdb) + return NULL; + + return tdb; +} -- cgit From 53f2f8254b39b346c6ee718debd79bfc41207ec3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 14 May 2004 13:07:20 +0000 Subject: r734: Fix crash bug (This used to be commit 178cd902fc7069e3d613c46fc4845101a0229655) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index c63ab20b82..af3a6ac214 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -316,14 +316,19 @@ static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, static WERROR rpc_query_key(REG_KEY *k) { NTSTATUS status; + WERROR error; struct winreg_QueryInfoKey r; struct rpc_data *mydata = k->handle->backend_data; - struct rpc_key_data *mykeydata; + struct rpc_key_data *mykeydata; + r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.class, NULL); - + + error = rpc_key_put_rpc_data(k, &mykeydata); + if(!W_ERROR_IS_OK(error)) return error; + status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r); - + if (!NT_STATUS_IS_OK(status)) { printf("QueryInfoKey failed - %s\n", nt_errstr(status)); return ntstatus_to_werror(status); -- cgit From 064e7447bebd715c8351d9a0ee31f648990f2336 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 15 May 2004 07:51:38 +0000 Subject: r743: Start on a NETLOGON server in Samba4. Currently this only authentiates the machine, not real users. As a consequence of running the Samba4 NETLOGON test against Samba4, I found a number of issues in the SAMR server, which I have addressed. There are more templates in the provison.ldif for this reason. I also added some debug to our credentials code, and fixed some bugs in the auth_sam module. The static buffer in generate_random_string() bit me badly, so I removed it in favor of a talloc based system. Andrew Bartlett (This used to be commit 94624e519b66def97758b8a48a01ffe9029176f0) --- source4/lib/genrand.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index f891ac883a..fdd4bb14fc 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -269,15 +269,14 @@ BOOL check_password_quality(const char *s) static char c_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; -char *generate_random_str(size_t len) +char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) { - static unsigned char retstr[256]; size_t i; - memset(retstr, '\0', sizeof(retstr)); + char *retstr = talloc(mem_ctx, len + 1); - if (len > sizeof(retstr)-1) - len = sizeof(retstr) -1; + if (!retstr) + return NULL; again: generate_random_buffer(retstr, len, False); @@ -292,5 +291,5 @@ again: goto again; } - return (char *)retstr; + return retstr; } -- cgit From 4219ec1dece35452c3887b2013e636105fc44f33 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 May 2004 13:20:30 +0000 Subject: r790: started working on some documentation (manual pages) for ldb (This used to be commit dcb9d1a897f7186824e997064902f3d50bad1887) --- source4/lib/ldb/man/build_manpages.sh | 11 +++ source4/lib/ldb/man/man3/ldb.3 | 165 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/man/man3/ldb.yo | 133 +++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100755 source4/lib/ldb/man/build_manpages.sh create mode 100644 source4/lib/ldb/man/man3/ldb.3 create mode 100644 source4/lib/ldb/man/man3/ldb.yo (limited to 'source4/lib') diff --git a/source4/lib/ldb/man/build_manpages.sh b/source4/lib/ldb/man/build_manpages.sh new file mode 100755 index 0000000000..5e5e698ac4 --- /dev/null +++ b/source4/lib/ldb/man/build_manpages.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +for f in man/man3/*.yo; do + base=`basename $f .yo`; + man=man/man3/$base.3; + + if test $f -nt $man; then + echo Creating $man from $f + yodl2man -o $man $f || rm -f $man + fi +done diff --git a/source4/lib/ldb/man/man3/ldb.3 b/source4/lib/ldb/man/man3/ldb.3 new file mode 100644 index 0000000000..d6e20035c6 --- /dev/null +++ b/source4/lib/ldb/man/man3/ldb.3 @@ -0,0 +1,165 @@ +.TH "ldb" "3" "May 2004" "" "" +.SH "NAME" +ldb \- A light-weight database library +.PP +.SH "SYNOPSIS" +.PP +\fB#include \fP +.PP +.SH "DESCRIPTION" +.PP +ldb is a light weight embedded database library and API\&. With a +programming interface that is very similar to LDAP, ldb can store its +data either in a tdb(3) database or in a real LDAP database\&. +.PP +When used with the tdb backend ldb does not require any database +daemon\&. Instead, ldb function calls are processed immediately by the +ldb library, which does IO directly on the database, while allowing +multiple readers/writers using operating system byte range locks\&. This +leads to an API with very low overheads, often resulting in speeds of +more than 10x what can be achieved with a more traditional LDAP +architecture\&. +.PP +It a taxonomy of databases ldb would sit half way between key/value +pair databases (such as berkley db or tdb) and a full LDAP +database\&. With a structured attribute oriented API like LDAP and good +indexing capabilities, ldb can be used for quite sophisticated +applications that need a light weight database, without the +administrative overhead of a full LDAP installation\&. +.PP +Included with ldb are a number of useful command line tools for +manipulating a ldb database\&. These tools are similar in style to the +equivalent ldap command line tools\&. +.PP +In its default mode of operation with a tdb backend, ldb can also be +seen as a "schema-less LDAP"\&. By default ldb does not require a +schema, which greatly reduces the complexity of getting started with +ldb databases\&. As the complexity of you application grows you can take +advantage of some of the optional schema-like attributes that ldb +offers, or you can migrate to using the full LDAP api while keeping +your exiting ldb code\&. +.PP +If you are new to ldb, then I suggest starting with the manual pages +for ldbsearch(1) and ldbedit(1), and experimenting with a local +database\&. Then I suggest you look at the ldb_connect(3) and +ldb_search(3) manual pages\&. +.PP +.SH "INDEX" +.PP +.IP +.IP "\fBldbsearch(1)\fP" +command line ldb search utility +.IP +.IP "\fBldbedit(1)\fP" +edit all or part of a ldb databse using your +favourite editor +.IP +.IP "\fBldbedit(1)\fP" +edit all or part of a ldb databse using your +favourite editor +.IP +.IP "\fBldbadd(1)\fP" +add records to a ldb database using LDIF formatted input +.IP +.IP "\fBldbdel(1)\fP" +delete records from a ldb database +.IP +.IP "\fBldbmodify(1)\fP" +modify records in a ldb database using LDIF +formatted input +.IP +.IP "\fBldb_connect(3)\fP" +connect to a ldb backend +.IP +.IP "\fBldb_close(3)\fP" +close a connection to a ldb backend +.IP +.IP "\fBldb_search(3)\fP" +perform a database search +.IP +.IP "\fBldb_search_free(3)\fP" +free the results of a ldb_search +.IP +.IP "\fBldb_add(3)\fP" +add a record to the database +.IP +.IP "\fBldb_delete(3)\fP" +delete a record from the database +.IP +.IP "\fBldb_modify(3)\fP" +modify a record in the database +.IP +.IP "\fBldb_errstring(3)\fP" +retrieve extended error information from the +last operation +.IP +.IP "\fBldb_ldif_write(3)\fP" +write a LDIF formatted message +.IP +.IP "\fBldb_ldif_write_\fB3\fP\fP" +write a LDIF formatted message to a file +.IP +.IP "\fBldb_ldif_read(3)\fP" +read a LDIF formatted message +.IP +.IP "\fBldb_ldif_read_free(3)\fP" +free the result of a ldb_ldif_read() +.IP +.IP "\fBldb_ldif_read_\fB3\fP\fP" +read a LDIF message from a file +.IP +.IP "\fBldb_ldif_read_string(3)\fP" +read a LDIF message from a string +.IP +.IP "\fBldb_msg_find_element(3)\fP" +find an element in a ldb_message +.IP +.IP "\fBldb_val_equal_exact(3)\fP" +compare two ldb_val structures +.IP +.IP "\fBldb_msg_find_val(3)\fP" +find an element by value +.IP +.IP "\fBldb_msg_add_empty(3)\fP" +add an empty message element to a ldb_message +.IP +.IP "\fBldb_msg_add(3)\fP" +add a non-empty message element to a ldb_message +.IP +.IP "\fBldb_msg_element_compare(3)\fP" +compare two ldb_message_element structures +.IP +.IP "\fBldb_msg_find_int(3)\fP" +return an integer value from a ldb_message +.IP +.IP "\fBldb_msg_find_uint(3)\fP" +return an unsigned integer value from a ldb_message +.IP +.IP "\fBldb_msg_find_double(3)\fP" +return a double value from a ldb_message +.IP +.IP "\fBldb_msg_find_string(3)\fP" +return a string value from a ldb_message +.IP +.IP "\fBldb_set_alloc(3)\fP" +set the memory allocation function to be used by ldb +.IP +.IP "\fBldb_set_debug(3)\fP" +set a debug handler to be used by ldb +.IP +.IP "\fBldb_set_debug_stderr(3)\fP" +set a debug handler for stderr output +.IP +.PP +.SH "AUTHOR" +.PP +ldb was written by Andrew Tridgell +http://samba\&.org/~tridge/ +.PP +If you wish to report a problem or make a suggestion then please see +the http://ldb\&.samba\&.org/ web site for +current contact and maintainer information\&. +.PP +ldb is released under the GNU Lesser General Public License version 2 +or later\&. Please see the file COPYING for license details\&. +.PP diff --git a/source4/lib/ldb/man/man3/ldb.yo b/source4/lib/ldb/man/man3/ldb.yo new file mode 100644 index 0000000000..ce8a590fbc --- /dev/null +++ b/source4/lib/ldb/man/man3/ldb.yo @@ -0,0 +1,133 @@ +manpage(ldb)(3)(May 2004)()() +manpagename(ldb)(A light-weight database library) + +manpagesynopsis() + + bf(#include ) + +manpagedescription() + +ldb is a light weight embedded database library and API. With a +programming interface that is very similar to LDAP, ldb can store its +data either in a tdb(3) database or in a real LDAP database. + +When used with the tdb backend ldb does not require any database +daemon. Instead, ldb function calls are processed immediately by the +ldb library, which does IO directly on the database, while allowing +multiple readers/writers using operating system byte range locks. This +leads to an API with very low overheads, often resulting in speeds of +more than 10x what can be achieved with a more traditional LDAP +architecture. + +It a taxonomy of databases ldb would sit half way between key/value +pair databases (such as berkley db or tdb) and a full LDAP +database. With a structured attribute oriented API like LDAP and good +indexing capabilities, ldb can be used for quite sophisticated +applications that need a light weight database, without the +administrative overhead of a full LDAP installation. + +Included with ldb are a number of useful command line tools for +manipulating a ldb database. These tools are similar in style to the +equivalent ldap command line tools. + +In its default mode of operation with a tdb backend, ldb can also be +seen as a "schema-less LDAP". By default ldb does not require a +schema, which greatly reduces the complexity of getting started with +ldb databases. As the complexity of you application grows you can take +advantage of some of the optional schema-like attributes that ldb +offers, or you can migrate to using the full LDAP api while keeping +your exiting ldb code. + +If you are new to ldb, then I suggest starting with the manual pages +for ldbsearch(1) and ldbedit(1), and experimenting with a local +database. Then I suggest you look at the ldb_connect(3) and +ldb_search(3) manual pages. + +manpagesection(INDEX) + +startdit() + +dit(bf(ldbsearch(1))) command line ldb search utility + +dit(bf(ldbedit(1))) edit all or part of a ldb databse using your +favourite editor + +dit(bf(ldbedit(1))) edit all or part of a ldb databse using your +favourite editor + +dit(bf(ldbadd(1))) add records to a ldb database using LDIF formatted input + +dit(bf(ldbdel(1))) delete records from a ldb database + +dit(bf(ldbmodify(1))) modify records in a ldb database using LDIF +formatted input + +dit(bf(ldb_connect(3))) connect to a ldb backend + +dit(bf(ldb_close(3))) close a connection to a ldb backend + +dit(bf(ldb_search(3))) perform a database search + +dit(bf(ldb_search_free(3))) free the results of a ldb_search + +dit(bf(ldb_add(3))) add a record to the database + +dit(bf(ldb_delete(3))) delete a record from the database + +dit(bf(ldb_modify(3))) modify a record in the database + +dit(bf(ldb_errstring(3))) retrieve extended error information from the +last operation + +dit(bf(ldb_ldif_write(3))) write a LDIF formatted message + +dit(bf(ldb_ldif_write_file(3))) write a LDIF formatted message to a file + +dit(bf(ldb_ldif_read(3))) read a LDIF formatted message + +dit(bf(ldb_ldif_read_free(3))) free the result of a ldb_ldif_read() + +dit(bf(ldb_ldif_read_file(3))) read a LDIF message from a file + +dit(bf(ldb_ldif_read_string(3))) read a LDIF message from a string + +dit(bf(ldb_msg_find_element(3))) find an element in a ldb_message + +dit(bf(ldb_val_equal_exact(3))) compare two ldb_val structures + +dit(bf(ldb_msg_find_val(3))) find an element by value + +dit(bf(ldb_msg_add_empty(3))) add an empty message element to a ldb_message + +dit(bf(ldb_msg_add(3))) add a non-empty message element to a ldb_message + +dit(bf(ldb_msg_element_compare(3))) compare two ldb_message_element structures + +dit(bf(ldb_msg_find_int(3))) return an integer value from a ldb_message + +dit(bf(ldb_msg_find_uint(3))) return an unsigned integer value from a ldb_message + +dit(bf(ldb_msg_find_double(3))) return a double value from a ldb_message + +dit(bf(ldb_msg_find_string(3))) return a string value from a ldb_message + +dit(bf(ldb_set_alloc(3))) set the memory allocation function to be used by ldb + +dit(bf(ldb_set_debug(3))) set a debug handler to be used by ldb + +dit(bf(ldb_set_debug_stderr(3))) set a debug handler for stderr output + +enddit() + +manpageauthor() + +ldb was written by Andrew Tridgell +url(http://samba.org/~tridge/)(http://samba.org/~tridge/) + +If you wish to report a problem or make a suggestion then please see +the url(http://ldb.samba.org/)(http://ldb.samba.org/) web site for +current contact and maintainer information. + +ldb is released under the GNU Lesser General Public License version 2 +or later. Please see the file COPYING for license details. + -- cgit From 0a083d1e08a7f7dfcf8abf5866ceb0eee52509e7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 May 2004 13:21:30 +0000 Subject: r791: added ldb man page build to ldb makefile (This used to be commit ec38392888d20991abe18dd3e6ca226a62c7d4ae) --- source4/lib/ldb/Makefile.ldb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 1623b74f6c..392407a46e 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -35,7 +35,7 @@ LIBS = $(LDB_LIB)($(OBJS)) DIRS = lib bin -all: $(DIRS) $(BINS) $(LIBS) +all: $(DIRS) $(BINS) $(LIBS) manpages lib: mkdir -p lib @@ -63,8 +63,11 @@ bin/ldbedit: tools/ldbedit.o $(LIBS) bin/ldbtest: tools/ldbtest.o $(LIBS) $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) +manpages: + man/build_manpages.sh + clean: - rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) + rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) man/man?/*.[13] proto: mkproto.pl */*.c > include/proto.h -- cgit From f0a8f718ff474009300af6746fa0fbb61c649ea9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 May 2004 13:25:06 +0000 Subject: r792: - changed the ldb ldif_* functions to be in the ldb_ namespace - added better error reporting in ldbdel - fixed a bug in handling packing of records which contain elements with no values (it caused db corruption) - allow search with "dn" as target attribute (This used to be commit 36575396234e3d35dbd442c8f1ff54a17ae64e64) --- source4/lib/ldb/common/ldb_ldif.c | 28 ++++++++++++++-------------- source4/lib/ldb/common/ldb_parse.c | 1 + source4/lib/ldb/include/ldb.h | 23 ++++++++++------------- source4/lib/ldb/ldb_tdb/ldb_index.c | 1 + source4/lib/ldb/ldb_tdb/ldb_match.c | 1 + source4/lib/ldb/ldb_tdb/ldb_pack.c | 20 +++++++++++++++++--- source4/lib/ldb/ldb_tdb/ldb_search.c | 28 +++++++++++++++++++++++++++- source4/lib/ldb/tools/ldbadd.c | 4 ++-- source4/lib/ldb/tools/ldbdel.c | 3 ++- source4/lib/ldb/tools/ldbedit.c | 4 ++-- source4/lib/ldb/tools/ldbmodify.c | 4 ++-- source4/lib/ldb/tools/ldbsearch.c | 2 +- 12 files changed, 80 insertions(+), 39 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 513e2dd365..c120ee5f4e 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -196,10 +196,10 @@ static const struct { /* write to ldif, using a caller supplied write method */ -int ldif_write(struct ldb_context *ldb, - int (*fprintf_fn)(void *, const char *, ...), - void *private_data, - const struct ldb_ldif *ldif) +int ldb_ldif_write(struct ldb_context *ldb, + int (*fprintf_fn)(void *, const char *, ...), + void *private_data, + const struct ldb_ldif *ldif) { int i, j; int total=0, ret; @@ -407,7 +407,7 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) /* free a message from a ldif_read */ -void ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif) +void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif) { struct ldb_message *msg = &ldif->msg; int i; @@ -457,8 +457,8 @@ static int msg_add_empty(struct ldb_context *ldb, /* read from a LDIF source, creating a ldb_message */ -struct ldb_ldif *ldif_read(struct ldb_context *ldb, - int (*fgetc_fn)(void *), void *private_data) +struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data) { struct ldb_ldif *ldif; struct ldb_message *msg; @@ -582,7 +582,7 @@ struct ldb_ldif *ldif_read(struct ldb_context *ldb, return ldif; failed: - if (ldif) ldif_read_free(ldb, ldif); + if (ldif) ldb_ldif_read_free(ldb, ldif); return NULL; } @@ -601,11 +601,11 @@ static int fgetc_file(void *private_data) return fgetc(state->f); } -struct ldb_ldif *ldif_read_file(struct ldb_context *ldb, FILE *f) +struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f) { struct ldif_read_file_state state; state.f = f; - return ldif_read(ldb, fgetc_file, &state); + return ldb_ldif_read(ldb, fgetc_file, &state); } @@ -625,11 +625,11 @@ static int fgetc_string(void *private_data) return EOF; } -struct ldb_ldif *ldif_read_string(struct ldb_context *ldb, const char *s) +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s) { struct ldif_read_string_state state; state.s = s; - return ldif_read(ldb, fgetc_string, &state); + return ldb_ldif_read(ldb, fgetc_string, &state); } @@ -652,9 +652,9 @@ static int fprintf_file(void *private_data, const char *fmt, ...) return ret; } -int ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif) +int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif) { struct ldif_write_file_state state; state.f = f; - return ldif_write(ldb, fprintf_file, &state, ldif); + return ldb_ldif_write(ldb, fprintf_file, &state, ldif); } diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 5d2a42fd20..d61d65548c 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -42,6 +42,7 @@ */ #include "includes.h" +#include "ldb/include/ldb_parse.h" /* diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 7215bf5705..448d5607a8 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -60,9 +60,6 @@ struct ldb_val { void *data; }; -#include "ldb_parse.h" - - /* these flags are used in ldd_message_element.flags fields. The LDA_FLAGS_MOD_* flags are used in ldap_modify() calls to specify whether attributes are being added, deleted or modified */ @@ -256,16 +253,16 @@ char *ldb_casefold(struct ldb_context *ldb, const char *s); /* ldif manipulation functions */ -int ldif_write(struct ldb_context *ldb, - int (*fprintf_fn)(void *, const char *, ...), - void *private_data, - const struct ldb_ldif *ldif); -void ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *); -struct ldb_ldif *ldif_read(struct ldb_context *ldb, - int (*fgetc_fn)(void *), void *private_data); -struct ldb_ldif *ldif_read_file(struct ldb_context *ldb, FILE *f); -struct ldb_ldif *ldif_read_string(struct ldb_context *ldb, const char *s); -int ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); +int ldb_ldif_write(struct ldb_context *ldb, + int (*fprintf_fn)(void *, const char *, ...), + void *private_data, + const struct ldb_ldif *ldif); +void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *); +struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, + int (*fgetc_fn)(void *), void *private_data); +struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f); +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s); +int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); /* useful functions for ldb_message structure manipulation */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 3febdaa711..b4ca666287 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/ldb_tdb/ldb_tdb.h" +#include "ldb/include/ldb_parse.h" struct dn_list { unsigned int count; diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 80d147cb43..05a2826d4d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/ldb_tdb/ldb_tdb.h" +#include "ldb/include/ldb_parse.h" /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 8d1051be94..e71679646e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -69,11 +69,17 @@ int ltdb_pack_data(struct ldb_context *ldb, const struct ldb_message *message, struct TDB_DATA *data) { - int i, j; + int i, j, real_elements=0; size_t size; char *p; size_t len; + for (i=0;inum_elements;i++) { + if (message->elements[i].num_values != 0) { + real_elements++; + } + } + /* work out how big it needs to be */ size = 8; @@ -99,7 +105,7 @@ int ltdb_pack_data(struct ldb_context *ldb, p = data->dptr; put_uint32(p, 0, LTDB_PACKING_FORMAT); - put_uint32(p, 4, message->num_elements); + put_uint32(p, 4, real_elements); p += 8; /* the dn needs to be packed so we can be case preserving @@ -211,12 +217,14 @@ int ltdb_unpack_data(struct ldb_context *ldb, message->elements = ldb_malloc_array_p(ldb, struct ldb_message_element, message->num_elements); - if (!message->elements) { errno = ENOMEM; goto failed; } + memset(message->elements, 0, + message->num_elements * sizeof(struct ldb_message_element)); + for (i=0;inum_elements;i++) { if (remaining < 10) { errno = EIO; @@ -243,6 +251,7 @@ int ltdb_unpack_data(struct ldb_context *ldb, } } p += 4; + remaining -= 4; for (j=0;jelements[i].num_values;j++) { len = pull_uint32(p, 0); if (len > remaining-5) { @@ -257,6 +266,11 @@ int ltdb_unpack_data(struct ldb_context *ldb, } } + if (remaining != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: %d bytes unread in ltdb_unpack_data\n", remaining); + } + return 0; failed: diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 6b38a28296..d97444a6e8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/ldb_tdb/ldb_tdb.h" +#include "ldb/include/ldb_parse.h" /* free a message that has all parts separately allocated @@ -192,6 +193,31 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, continue; } + if (ldb_attr_cmp(attrs[i], "dn") == 0) { + struct ldb_message_element el2; + struct ldb_val val; + + el2.flags = 0; + el2.name = ldb_strdup(ldb, "dn"); + if (!el2.name) { + msg_free_all_parts(ldb, ret); + ldb_free(ldb, el2.name); + return NULL; + } + el2.num_values = 1; + el2.values = &val; + val.data = ret->dn; + val.length = strlen(ret->dn); + + if (msg_add_element(ldb, ret, &el2) != 0) { + msg_free_all_parts(ldb, ret); + ldb_free(ldb, el2.name); + return NULL; + } + ldb_free(ldb, el2.name); + continue; + } + el = ldb_msg_find_element(msg, attrs[i]); if (!el) { continue; @@ -290,7 +316,7 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message ret = ltdb_unpack_data(ldb, &tdb_data2, msg); if (ret == -1) { - free(tdb_data2.dptr); + ldb_free(ldb, tdb_data2.dptr); return -1; } diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index a45021c1d9..9383197ed0 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -55,7 +55,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) struct ldb_ldif *ldif; int ret, count=0; - while ((ldif = ldif_read_file(ldb, f))) { + while ((ldif = ldb_ldif_read_file(ldb, f))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); @@ -70,7 +70,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } else { count++; } - ldif_read_free(ldb, ldif); + ldb_ldif_read_free(ldb, ldif); } return count; diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 880713b25a..2977357ced 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -90,7 +90,8 @@ static void usage(void) for (i=0;ichangetype) { case LDB_CHANGETYPE_NONE: case LDB_CHANGETYPE_ADD: @@ -74,7 +74,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } else { count++; } - ldif_read_free(ldb, ldif); + ldb_ldif_read_free(ldb, ldif); } return count; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 478601ec7e..137299d89b 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -69,7 +69,7 @@ static int do_search(struct ldb_context *ldb, ldif.changetype = LDB_CHANGETYPE_NONE; ldif.msg = *msgs[i]; - ldif_write_file(ldb, stdout, &ldif); + ldb_ldif_write_file(ldb, stdout, &ldif); } if (ret > 0) { -- cgit From b047b71b45d8a7718373d336b52365f884716b65 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 21 May 2004 16:39:12 +0000 Subject: r808: fix libtdb build by ifedffing out an smb_panic() and copying over CatchSignal fn from lib/signal changing it's name to TdbCatchSignal (This used to be commit e1afaa1e9c8de5615030015b1360529b450d2047) --- source4/lib/tdb/tdbutil.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index 9a0e8b0c44..f0fa048bb6 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -35,6 +35,46 @@ static void gotalarm_sig(void) gotalarm = 1; } + +/******************************************************************* + THIS is a copy of the function CatchSignal found in lib/signal.c + I need to copy it there to avoid sucking all of the samba source + into tdb. + + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +********************************************************************/ + +static void (*TdbCatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + + + /*************************************************************** Make a TDB_DATA and keep the const warning in one place ****************************************************************/ @@ -59,7 +99,7 @@ static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, u tdb_set_lock_alarm(&gotalarm); if (timeout) { - CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + TdbCatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); alarm(timeout); } @@ -70,7 +110,7 @@ static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, u if (timeout) { alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + TdbCatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); if (gotalarm) { tdb_debug(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", timeout, key.dptr, tdb->name ); @@ -689,11 +729,12 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) for (key = tdb_firstkey(tdb); key.dptr; key = next) { /* duplicate key string to ensure null-termination */ char *key_str = (char*) strndup(key.dptr, key.dsize); +#if 0 if (!key_str) { tdb_debug(tdb, 0, "tdb_search_keys: strndup() failed!\n"); smb_panic("strndup failed!\n"); } - +#endif tdb_debug(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); next = tdb_nextkey(tdb, key); -- cgit From 054453b5849d97bb244e3e45b5d5f92155311f8b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 22 May 2004 00:52:04 +0000 Subject: r811: make the ldb_modify REPLACE semantics better match LDAP (ie. no error on the attribute not existing and allow an empty replace) (This used to be commit 1418b667d9041430786089713eafee63dd7b4a28) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 09d1618ffc..d60504ff17 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -501,13 +501,12 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) case LDB_FLAG_MOD_REPLACE: /* replace all elements of this attribute name with the elements - listed */ - if (msg_delete_attribute(ldb, &msg2, msg->elements[i].name) != 0) { - ltdb->last_err_string = "No such attribute"; - goto failed; - } - /* add the replacement element */ - if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { + listed. The attribute not existing is not an error */ + msg_delete_attribute(ldb, &msg2, msg->elements[i].name); + + /* add the replacement element, if not empty */ + if (msg->elements[i].num_values != 0 && + msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { goto failed; } break; -- cgit From 93076cb9bc56a515bbefb6d88470d6776169779a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 22 May 2004 07:55:48 +0000 Subject: r816: - Make use of tridge's new samdb_result_sid_prefix() helper function. - Remove legacy sid_to_string (which contained a memleak) - Remove some unused parts of lib/util_sid.c Andrew Bartlett (This used to be commit 7c69a85984e47c004ddfd9bb5eadcb3191b56f9d) --- source4/lib/util_sid.c | 70 -------------------------------------------------- 1 file changed, 70 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 6f63e25c5d..5ce72a6f51 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -143,76 +143,6 @@ void generate_wellknown_sids(void) initialised = True; } -/************************************************************************** - Splits a name of format \DOMAIN\name or name into its two components. - Sets the DOMAIN name to lp_netbios_name() if it has not been specified. -***************************************************************************/ - -void split_domain_name(const char *fullname, char *domain, char *name) -{ - pstring full_name; - const char *sep; - char *p; - - sep = lp_winbind_separator(); - - *domain = *name = '\0'; - - if (fullname[0] == sep[0] || fullname[0] == '\\') - fullname++; - - pstrcpy(full_name, fullname); - p = strchr_m(full_name+1, '\\'); - if (!p) p = strchr_m(full_name+1, sep[0]); - - if (p != NULL) { - *p = 0; - fstrcpy(domain, full_name); - fstrcpy(name, p+1); - } else { - fstrcpy(domain, lp_netbios_name()); - fstrcpy(name, full_name); - } - - DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n", - fullname, domain, name)); -} - -/***************************************************************** - Convert a SID to an ascii string. -*****************************************************************/ - -char *sid_to_string(fstring sidstr_out, const struct dom_sid *sid) -{ - char *tmp_string; - TALLOC_CTX *mem_ctx; - if (!(mem_ctx = talloc_init("sid_to_string temp context"))) { - return NULL; - } - - tmp_string = dom_sid_string(mem_ctx, sid); - if (!tmp_string) - return NULL; - - fstrcpy(sidstr_out, tmp_string); - return sidstr_out; -} - -/***************************************************************** - Removes the last rid from the end of a sid -*****************************************************************/ - -BOOL sid_split_rid(struct dom_sid *sid, uint32 *rid) -{ - if (sid->num_auths > 0) { - sid->num_auths--; - if (rid) - *rid = sid->sub_auths[sid->num_auths]; - return True; - } - return False; -} - /***************************************************************** Return the last rid from the end of a sid *****************************************************************/ -- cgit From 1ca75ec3bb5d001958d02a8d05a63c44269e57b8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 22 May 2004 11:36:20 +0000 Subject: r819: Fix seg fault in rpc backend, found by Andrew Bartlett (This used to be commit d4cc4b3d682eb828208a621fe6b795f3e77c746a) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index af3a6ac214..74b25884d6 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -321,11 +321,11 @@ static WERROR rpc_query_key(REG_KEY *k) struct rpc_data *mydata = k->handle->backend_data; struct rpc_key_data *mykeydata; - r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.class, NULL); error = rpc_key_put_rpc_data(k, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; + r.in.handle = &mykeydata->pol; status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r); -- cgit From bf52e242f53aeaac33eea69fbdfb3477634b90fb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 22 May 2004 18:49:25 +0000 Subject: r825: - Introduce support for multiple roots (or 'hives') - Clean up rpc backend (possible now that multiple hives are supported) (This used to be commit 8cd1b6bc70510fe576135a66351e9e3ea895c9ff) --- source4/lib/registry/common/reg_interface.c | 62 +++++++- source4/lib/registry/common/reg_objects.c | 7 + source4/lib/registry/common/registry.h | 24 +-- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 10 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 5 +- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 168 ++++++++------------- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 8 +- source4/lib/registry/tools/gregedit.c | 31 ++-- source4/lib/registry/tools/regdiff.c | 32 ++-- source4/lib/registry/tools/regpatch.c | 19 +-- source4/lib/registry/tools/regshell.c | 3 +- source4/lib/registry/tools/regtree.c | 12 +- 12 files changed, 213 insertions(+), 168 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 4d1726c542..3e5a545f9a 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -117,6 +117,25 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia return werr; } +WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result) +{ + REG_KEY *hive; + WERROR error; + int i, hivelength; + + if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; + else hivelength = strlen(name); + + for(i = 0; W_ERROR_IS_OK(error); i++) { + error = reg_get_hive(handle, i, &hive); + if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { + return reg_open_key(hive, name, result); + } + } + + return error; +} + /* Open a key * First tries to use the open_key function from the backend * then falls back to get_subkey_by_name and later get_subkey_by_index @@ -166,7 +185,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) return WERR_NOT_SUPPORTED; } - error = parent->handle->functions->open_key(parent->handle, fullname, result); + error = parent->handle->functions->open_key(parent->handle, parent->hive, fullname, result); if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); @@ -175,6 +194,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) (*result)->handle = parent->handle; (*result)->path = fullname; + (*result)->hive = parent->hive; talloc_steal(mem_ctx, (*result)->mem_ctx, fullname); talloc_destroy(mem_ctx); @@ -285,6 +305,7 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); (*subkey)->handle = key->handle; + (*subkey)->hive = key->hive; return WERR_OK;; @@ -315,6 +336,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); (*subkey)->handle = key->handle; + (*subkey)->hive = key->hive; return WERR_OK; } @@ -427,6 +449,25 @@ WERROR reg_val_del(REG_VAL *val) return WERR_OK; } +WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name) +{ + REG_KEY *hive; + WERROR error; + int i, hivelength; + + if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; + else hivelength = strlen(name); + + for(i = 0; W_ERROR_IS_OK(error); i++) { + error = reg_get_hive(handle, i, &hive); + if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { + return reg_key_add_name_recursive(hive, name); + } + } + + return error; +} + WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) { REG_KEY *cur, *prevcur = parent; @@ -516,21 +557,26 @@ void reg_free(REG_HANDLE *h) h->functions->close_registry(h); } -WERROR reg_get_root(REG_HANDLE *h, REG_KEY **key) +WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key) { WERROR ret; - if(h->functions->open_root_key) { - ret = h->functions->open_root_key(h, key); + + if(h->functions->get_hive) { + ret = h->functions->get_hive(h, hivenum, key); } else if(h->functions->open_key) { - ret = h->functions->open_key(h, "\\", key); + if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key); + else ret = WERR_NO_MORE_ITEMS; } else { - DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key method implemented\n", h->functions->name)); + DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name)); ret = WERR_NOT_SUPPORTED; } if(W_ERROR_IS_OK(ret)) { (*key)->handle = h; - (*key)->path = talloc_strdup((*key)->mem_ctx, "\\"); + if(!(*key)->path) { + (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name); + } + (*key)->hive = hivenum; } return ret; @@ -565,7 +611,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) REG_KEY *root; WERROR error; - error = reg_get_root(key->handle, &root); + error = reg_get_hive(key->handle, key->hive, &root); if(!W_ERROR_IS_OK(error)) return error; parent_name = strdup(reg_key_get_path(key)); diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 787ec52127..7a92f413ff 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -139,6 +139,12 @@ char *reg_val_get_path(REG_VAL *v) } const char *reg_key_get_path(REG_KEY *k) +{ + SMB_REG_ASSERT(k); + return strchr(k->path, '\\')?strchr(k->path, '\\')+1:k->path; +} + +const char *reg_key_get_path_abs(REG_KEY *k) { SMB_REG_ASSERT(k); return k->path; @@ -168,6 +174,7 @@ REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) r = talloc(mem_ctx, sizeof(REG_KEY)); ZERO_STRUCTP(r); r->handle = k->handle; + r->hive = k->hive; r->name = talloc_strdup(mem_ctx, name); r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name); diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 208bcae1e1..d4e8cccade 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -40,6 +40,7 @@ struct reg_key_s { int cache_values_count; REG_KEY **cache_subkeys; int cache_subkeys_count; + int hive; TALLOC_CTX *mem_ctx; int ref; }; @@ -61,10 +62,14 @@ struct reg_val_s { typedef void (*key_notification_function) (void); typedef void (*value_notification_function) (void); - /* * Container for function pointers to enumeration routines * for virtual registry view + * + * Backends can provide : + * - just one hive (example: nt4, w95) + * - several hives (example: rpc) + * */ struct registry_ops { @@ -73,17 +78,23 @@ struct registry_ops { WERROR (*sync_key)(REG_KEY *, const char *location); WERROR (*close_registry) (REG_HANDLE *); + /* Implement this one */ + WERROR (*get_hive) (REG_HANDLE *, int , REG_KEY **); + + /* Or this one */ + WERROR (*open_key) (REG_HANDLE *, int hive, const char *name, REG_KEY **); + /* Either implement these */ - WERROR (*open_root_key) (REG_HANDLE *, REG_KEY **); WERROR (*num_subkeys) (REG_KEY *, int *count); WERROR (*num_values) (REG_KEY *, int *count); WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **); + /* Can not contain more then one level */ WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **); WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **); + /* Can not contain more then one level */ WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **); /* Or these */ - WERROR (*open_key) (REG_HANDLE *, const char *name, REG_KEY **); WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); @@ -111,15 +122,8 @@ struct registry_ops { void (*free_val_backend_data) (REG_VAL *); }; -typedef struct reg_sub_tree_s { - char *path; - REG_HANDLE *handle; - struct reg_sub_tree_s *prev, *next; -} REG_SUBTREE; - struct reg_handle_s { struct registry_ops *functions; - REG_SUBTREE *subtrees; char *location; char *credentials; void *backend_data; diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 517324fdd2..cb61864d0c 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -38,16 +38,22 @@ static WERROR reg_dir_del_key(REG_KEY *k) return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; } -static WERROR reg_dir_open_key(REG_HANDLE *h, const char *name, REG_KEY **subkey) +static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **subkey) { DIR *d; char *fullpath; REG_KEY *ret; - TALLOC_CTX *mem_ctx = talloc_init("tmp"); + TALLOC_CTX *mem_ctx; + + if(hive != 0) return WERR_NO_MORE_ITEMS; + if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); return WERR_INVALID_PARAM; } + + + mem_ctx = talloc_init("tmp"); fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index cb3c284811..255389624e 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1663,8 +1663,9 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char return WERR_OK; } -static WERROR nt_get_root_key(REG_HANDLE *h, REG_KEY **key) +static WERROR nt_get_root_key(REG_HANDLE *h, int hive, REG_KEY **key) { + if(hive != 0) return WERR_NO_MORE_ITEMS; return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); } @@ -1737,7 +1738,7 @@ static struct registry_ops reg_backend_nt4 = { .name = "nt4", .open_registry = nt_open_registry, .close_registry = nt_close_registry, - .open_root_key = nt_get_root_key, + .get_hive = nt_get_root_key, .num_subkeys = nt_num_subkeys, .num_values = nt_num_values, .get_subkey_by_index = nt_key_by_index, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 74b25884d6..d863568c17 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -22,9 +22,6 @@ /** * This is the RPC backend for the registry library. - * - * This backend is a little special. The root key is 'virtual'. All - * of its subkeys are the hives available on the remote server. */ static void init_winreg_String(struct winreg_String *name, const char *s) @@ -40,11 +37,11 @@ static void init_winreg_String(struct winreg_String *name, const char *s) } -#define openhive(u) static struct policy_handle *open_ ## u(struct dcerpc_pipe *p, REG_HANDLE *h) \ +#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \ { \ struct winreg_Open ## u r; \ struct winreg_OpenUnknown unknown; \ - struct policy_handle *hnd = malloc(sizeof(struct policy_handle)); \ + NTSTATUS status; \ \ unknown.unknown0 = 0x84e0; \ unknown.unknown1 = 0x0000; \ @@ -52,12 +49,13 @@ static void init_winreg_String(struct winreg_String *name, const char *s) r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ - if (!NT_STATUS_IS_OK(dcerpc_winreg_Open ## u(p, h->mem_ctx, &r))) {\ + status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \ + if (NT_STATUS_IS_ERR(status)) {\ DEBUG(0,("Error executing open\n"));\ - return NULL;\ + return ntstatus_to_werror(status);\ }\ \ - return hnd;\ + return r.out.result;\ } openhive(HKLM) @@ -66,11 +64,6 @@ openhive(HKPD) openhive(HKU) openhive(HKCR) -struct rpc_data { - struct dcerpc_pipe *pipe; - struct policy_handle *hives[10]; -}; - struct rpc_key_data { struct policy_handle pol; int num_subkeys; @@ -81,7 +74,7 @@ struct rpc_key_data { struct { const char *name; - struct policy_handle *(*open) (struct dcerpc_pipe *p, REG_HANDLE *h); + WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h); } known_hives[] = { { "HKEY_LOCAL_MACHINE", open_HKLM }, { "HKEY_CURRENT_USER", open_HKCU }, @@ -95,7 +88,6 @@ static WERROR rpc_query_key(REG_KEY *k); static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) { - struct rpc_data *mydata = talloc(h->mem_ctx, sizeof(struct rpc_data)); char *binding = strdup(location); NTSTATUS status; char *user, *pass; @@ -106,40 +98,42 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char pass = strchr(user, '%'); *pass = '\0'; pass++; - ZERO_STRUCTP(mydata); - - status = dcerpc_pipe_connect(&mydata->pipe, binding, + status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), user, pass); - - h->backend_data = mydata; return ntstatus_to_werror(status); } -static WERROR rpc_open_root(REG_HANDLE *h, REG_KEY **k) +static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k) { - /* There's not really a 'root' key here */ - *k = reg_key_new_abs("\\", h, h->backend_data); - return WERR_OK; + struct rpc_key_data *mykeydata; + WERROR error; + if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; + *k = reg_key_new_abs(known_hives[n].name, h, NULL); + (*k)->backend_data = mykeydata = talloc_p((*k)->mem_ctx, struct rpc_key_data); + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; + error = known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &mykeydata->pol); + return error; } static WERROR rpc_close_registry(REG_HANDLE *h) { - dcerpc_pipe_close(((struct rpc_data *)h->backend_data)->pipe); + dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data); return WERR_OK; } static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) { - struct policy_handle *hive = NULL; struct winreg_OpenKey r; int i; struct rpc_data *mydata = k->handle->backend_data; + WERROR error; + REG_KEY *hivekey; struct rpc_key_data *mykeydata; - char *realkeyname, *hivename; if(k->backend_data) { *data = k->backend_data; @@ -151,57 +145,55 @@ static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) mykeydata->num_values = -1; mykeydata->num_subkeys = -1; - /* First, ensure the handle to the hive is opened */ - realkeyname = strchr(k->path+1, '\\'); - if(realkeyname) hivename = strndup(k->path+1, realkeyname-k->path-1); - else hivename = strdup(k->path+1); - - for(i = 0; known_hives[i].name; i++) { - if(!strcmp(hivename, known_hives[i].name)) { - if(!mydata->hives[i]) mydata->hives[i] = known_hives[i].open(mydata->pipe, k->handle); - hive = mydata->hives[i]; - break; - } - } - - if(!hive) { - DEBUG(0, ("No such hive: %s\n", hivename)); - return WERR_FOOBAR; - } - - if(realkeyname && realkeyname[0] == '\\')realkeyname++; - - if(!realkeyname || !(*realkeyname)) { - mykeydata->pol = *hive; - return WERR_OK; - } - /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); - r.in.handle = hive; - init_winreg_String(&r.in.keyname, realkeyname); + error = rpc_get_hive(k->handle, k->hive, &hivekey); + if(!W_ERROR_IS_OK(error))return error; + r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol); + init_winreg_String(&r.in.keyname, reg_key_get_path(k)); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; - dcerpc_winreg_OpenKey(mydata->pipe, k->mem_ctx, &r); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); return r.out.result; } -static WERROR rpc_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) +static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key) { struct rpc_key_data *mykeydata; + struct winreg_OpenKey r; + REG_KEY *hivekey; + WERROR error; + *key = reg_key_new_abs(name, h, NULL); - return rpc_key_put_rpc_data(*key, &mykeydata); + + (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data); + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; + + /* Then, open the handle using the hive */ + + memset(&r, 0, sizeof(struct winreg_OpenKey)); + error = rpc_get_hive(h, hive, &hivekey); + if(!W_ERROR_IS_OK(error))return error; + r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol); + init_winreg_String(&r.in.keyname, name); + r.in.unknown = 0x00000000; + r.in.access_mask = 0x02000000; + r.out.handle = &mykeydata->pol; + + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r); + + return r.out.result; } static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) { struct winreg_EnumValue r; struct winreg_Uint8buf vb; - struct rpc_data *mydata = parent->handle->backend_data; struct winreg_EnumValueName vn; NTSTATUS status; struct rpc_key_data *mykeydata; @@ -211,11 +203,6 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) error = rpc_key_put_rpc_data(parent, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; - /* Root is a special case */ - if(parent->backend_data == parent->handle->backend_data) { - return WERR_NO_MORE_ITEMS; - } - if(mykeydata->num_values == -1) { error = rpc_query_key(parent); if(!W_ERROR_IS_OK(error)) return error; @@ -244,7 +231,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen); r.in.value = r.out.value = &vb; - status = dcerpc_winreg_EnumValue(mydata->pipe, parent->mem_ctx, &r); + status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); } @@ -273,13 +260,6 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) WERROR error; NTSTATUS status; - /* If parent is the root key, list the hives */ - if(parent->backend_data == mydata) { - if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; - *subkey = reg_key_new_rel(known_hives[n].name, parent, NULL); - return rpc_key_put_rpc_data(*subkey, &mykeydata); - } - error = rpc_key_put_rpc_data(parent, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; @@ -295,7 +275,7 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) r.in.enum_index = n; r.in.unknown = r.out.unknown = 0x0414; r.in.key_name_len = r.out.key_name_len = 0; - status = dcerpc_winreg_EnumKey(mydata->pipe, parent->mem_ctx, &r); + status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL); } @@ -306,7 +286,9 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key) { struct rpc_key_data *mykeydata; - WERROR error = rpc_key_put_rpc_data(parent, &mykeydata); + WERROR error; + + error = rpc_key_put_rpc_data(parent, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; /* FIXME */ @@ -318,16 +300,15 @@ static WERROR rpc_query_key(REG_KEY *k) NTSTATUS status; WERROR error; struct winreg_QueryInfoKey r; - struct rpc_data *mydata = k->handle->backend_data; struct rpc_key_data *mykeydata; - init_winreg_String(&r.in.class, NULL); - error = rpc_key_put_rpc_data(k, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; + + init_winreg_String(&r.in.class, NULL); r.in.handle = &mykeydata->pol; - status = dcerpc_winreg_QueryInfoKey(mydata->pipe, k->mem_ctx, &r); + status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("QueryInfoKey failed - %s\n", nt_errstr(status)); @@ -347,22 +328,21 @@ static WERROR rpc_query_key(REG_KEY *k) static WERROR rpc_del_key(REG_KEY *k) { NTSTATUS status; - struct rpc_data *mydata = k->handle->backend_data; - struct rpc_key_data *mykeydata; + struct rpc_key_data *mykeydata = k->backend_data; struct winreg_DeleteKey r; REG_KEY *parent; WERROR error; error = reg_key_get_parent(k, &parent); if(!W_ERROR_IS_OK(error)) return error; - + error = rpc_key_put_rpc_data(parent, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; - + r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.key, k->name); - status = dcerpc_winreg_DeleteKey(mydata->pipe, k->mem_ctx, &r); + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); return r.out.result; } @@ -373,15 +353,9 @@ static void rpc_close_key(REG_KEY *k) } static WERROR rpc_num_values(REG_KEY *key, int *count) { - struct rpc_key_data *mykeydata; + struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - /* Root is a special case */ - if(key->backend_data == key->handle->backend_data) { - *count = 0; - return WERR_OK; - } - error = rpc_key_put_rpc_data(key, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; @@ -395,20 +369,12 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) { } static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { - struct rpc_key_data *mykeydata; + struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - - /* Root is a special case */ - if(key->backend_data == key->handle->backend_data) { - int i; - for(i = 0; known_hives[i].name; i++); - *count = i; - return WERR_OK; - } - + error = rpc_key_put_rpc_data(key, &mykeydata); if(!W_ERROR_IS_OK(error)) return error; - + if(mykeydata->num_subkeys == -1) { error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; @@ -422,7 +388,7 @@ static struct registry_ops reg_backend_rpc = { .name = "rpc", .open_registry = rpc_open_registry, .close_registry = rpc_close_registry, - .open_root_key = rpc_open_root, + .get_hive = rpc_get_hive, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, .get_value_by_index = rpc_get_value_by_index, diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index c5d2e24103..b014f4da66 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -179,12 +179,14 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) } } -static WERROR w95_open_root (REG_HANDLE *h, REG_KEY **key) +static WERROR w95_open_root (REG_HANDLE *h, int hive, REG_KEY **key) { CREG *creg = h->backend_data; + + if(hive != 0) return WERR_NO_MORE_ITEMS; /* First element in rgkn should be root key */ - *key = reg_key_new_abs("\\", h, LOCN_RGKN(creg, sizeof(RGKN_HDR))); + *key = reg_key_new_abs("", h, LOCN_RGKN(creg, sizeof(RGKN_HDR))); return WERR_OK; } @@ -356,7 +358,7 @@ static struct registry_ops reg_backend_w95 = { .name = "w95", .open_registry = w95_open_reg, .close_registry = w95_close_reg, - .open_root_key = w95_open_root, + .get_hive = w95_open_root, .fetch_values = w95_fetch_values, .get_subkey_by_index = w95_get_subkey_by_index, }; diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 7b06b2266f..e8800c6ee9 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -1,6 +1,6 @@ /* Unix SMB/CIFS implementation. - Gtk registry frontend + GTK+ registry frontend Copyright (C) Jelmer Vernooij 2004 @@ -115,20 +115,25 @@ static void registry_load_root() { REG_KEY *root; GtkTreeIter iter, tmpiter; - WERROR error; + WERROR error = WERR_OK; + int i = 0; if(!registry) return; - error = reg_get_root(registry, &root); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - return; - } - gtk_tree_store_clear(store_keys); - /* Add the root */ - gtk_tree_store_append(store_keys, &iter, NULL); - gtk_tree_store_set (store_keys, + while(1) { + error = reg_get_hive(registry, i, &root); + if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { + return; + } + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(error); + return; + } + + /* Add the root */ + gtk_tree_store_append(store_keys, &iter, NULL); + gtk_tree_store_set (store_keys, &iter, 0, reg_key_name(root), @@ -136,7 +141,9 @@ static void registry_load_root() root, -1); - gtk_tree_store_append(store_keys, &tmpiter, &iter); + gtk_tree_store_append(store_keys, &tmpiter, &iter); + i++; + } gtk_widget_set_sensitive( save, True ); gtk_widget_set_sensitive( save_as, True ); diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index d9419208cd..7520e653bb 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -100,10 +100,11 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; - REG_HANDLE *h2; + REG_HANDLE *h1, *h2; REG_KEY *root1 = NULL, *root2; int from_null = 0; - WERROR error; + int i; + WERROR error, error2; struct poptOption long_options[] = { POPT_AUTOHELP {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, @@ -130,7 +131,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) setup_logging(argv[0], True); if(!from_null) { - REG_HANDLE *h1; const char *location1; location1 = poptGetArg(pc); if(!location1) { @@ -145,8 +145,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); return 1; } - - if(!W_ERROR_IS_OK(reg_get_root(h1, &root1))) return 1; } location2 = poptGetArg(pc); @@ -163,12 +161,6 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) return 1; } - error = reg_get_root(h2, &root2); - if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2); - return 1; - } - poptFreeContext(pc); if(outputfile) { @@ -182,7 +174,23 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) fprintf(fd, "REGEDIT4\n\n"); fprintf(fd, "; Generated using regdiff\n"); - writediff(root1, root2, fd); + error2 = error = WERR_OK; + + for(i = 0; ; i++) { + if(backend1) error = reg_get_hive(h1, i, &root1); + else root1 = NULL; + + if(!W_ERROR_IS_OK(error)) break; + + if(backend2) error2 = reg_get_hive(h2, i, &root2); + else root2 = NULL; + + if(!W_ERROR_IS_OK(error2)) break; + + writediff(root1, root2, fd); + + if(!root1 && !root2) break; + } fclose(fd); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 64c2637a0c..77c0f710c1 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -664,7 +664,7 @@ static CMD_FILE *cmd_file_create(const char *file) char *str_type(unsigned char type); -static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) +static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) { CMD *cmd; BOOL modified = False; @@ -680,12 +680,12 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) */ switch (cmd->cmd) { case CMD_ADD_KEY: - error = reg_open_key(root, cmd->key, &tmp); + error = reg_open_key_abs(r, cmd->key, &tmp); /* If we found it, apply the other bits, else create such a key */ if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - if(W_ERROR_IS_OK(reg_key_add_name_recursive(root, cmd->key))) { - error = reg_open_key(root, cmd->key, &tmp); + if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) { + error = reg_open_key_abs(r, cmd->key, &tmp); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key)); continue; @@ -732,7 +732,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) * Find the key if it exists, and delete it ... */ - error = reg_open_key(root, cmd->key, &tmp); + error = reg_open_key_abs(r, cmd->key, &tmp); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); continue; @@ -756,7 +756,6 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) { int opt; poptContext pc; - REG_KEY *root; const char *location; const char *credentials = NULL; const char *patch; @@ -793,13 +792,7 @@ static int nt_apply_reg_command_file(REG_KEY *root, const char *cmd_file_name) if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); - error = reg_get_root(h, &root); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error opening root!\n")); - return 1; - } - - nt_apply_reg_command_file(root, patch); + nt_apply_reg_command_file(h, patch); reg_free(h); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index e8b01081e8..26312ad4bc 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -27,6 +27,7 @@ * rmval/rm - remove value * rmkey/rmdir - remove key * mkkey/mkdir - make key + * ch - change hive * help * exit */ @@ -227,7 +228,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) setup_logging("regtree", True); - error = reg_get_root(h, &curkey); + error = reg_get_hive(h, 0, &curkey); if(!W_ERROR_IS_OK(error)) return 1; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 477c63af2c..e583194a56 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -60,7 +60,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) int main(int argc, char **argv) { - int opt; + int opt, i; const char *backend = "dir"; const char *credentials = NULL; poptContext pc; @@ -91,10 +91,14 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) } poptFreeContext(pc); - error = reg_get_root(h, &root); - if(!W_ERROR_IS_OK(error)) return 1; + error = WERR_OK; - print_tree(0, root, fullpath, no_values); + for(i = 0; W_ERROR_IS_OK(error); i++) { + error = reg_get_hive(h, i, &root); + if(!W_ERROR_IS_OK(error)) return 1; + + print_tree(0, root, fullpath, no_values); + } return 0; } -- cgit From f11cc69df34c39f545669eb83b0dbf23227db558 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 May 2004 00:30:17 +0000 Subject: r826: removed a pile of old code, in preparation for a new ACL handling system. I'd like to get rid of DOM_SID completely soon (This used to be commit e306e27cf333e176195a47b19e3de591b4a59650) --- source4/lib/genparser.c | 775 ------------------------------------------ source4/lib/genparser_samba.c | 200 ----------- source4/lib/tdb/tdbutil.c | 62 ---- source4/lib/util_seaccess.c | 490 -------------------------- source4/lib/util_sid.c | 2 +- 5 files changed, 1 insertion(+), 1528 deletions(-) delete mode 100644 source4/lib/genparser.c delete mode 100644 source4/lib/genparser_samba.c delete mode 100644 source4/lib/util_seaccess.c (limited to 'source4/lib') diff --git a/source4/lib/genparser.c b/source4/lib/genparser.c deleted file mode 100644 index 0f5d26620b..0000000000 --- a/source4/lib/genparser.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - Copyright (C) Andrew Tridgell 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - automatic marshalling/unmarshalling system for C structures -*/ - -#include "includes.h" - -/* encode a buffer of bytes into a escaped string */ -static char *encode_bytes(TALLOC_CTX *mem_ctx, const char *ptr, unsigned len) -{ - const char *hexdig = "0123456789abcdef"; - char *ret, *p; - unsigned i; - ret = talloc(mem_ctx, len*3 + 1); /* worst case size */ - if (!ret) return NULL; - for (p=ret,i=0;i>4]; - p[2] = hexdig[c&0xF]; - p += 3; - } - } - - *p = 0; - - return ret; -} - -/* decode an escaped string from encode_bytes() into a buffer */ -static char *decode_bytes(TALLOC_CTX *mem_ctx, const char *s, unsigned *len) -{ - char *ret, *p; - unsigned i; - int slen = strlen(s) + 1; - - ret = talloc(mem_ctx, slen); /* worst case length */ - if (!ret) - return NULL; - memset(ret, 0, slen); - - if (*s == '{') s++; - - for (p=ret,i=0;s[i];i++) { - if (s[i] == '}') { - break; - } else if (s[i] == '\\') { - unsigned v; - if (sscanf(&s[i+1], "%02x", &v) != 1 || v > 255) { - return NULL; - } - *(unsigned char *)p = v; - p++; - i += 2; - } else { - *p++ = s[i]; - } - } - *p = 0; - - (*len) = (unsigned)(p - ret); - - return ret; -} - -/* the add*() functions deal with adding things to a struct - parse_string */ - -/* allocate more space if needed */ -static int addgen_alloc(TALLOC_CTX *mem_ctx, struct parse_string *p, int n) -{ - if (p->length + n <= p->allocated) return 0; - p->allocated = p->length + n + 200; - p->s = talloc_realloc(mem_ctx, p->s, p->allocated); - if (!p->s) { - errno = ENOMEM; - return -1; - } - return 0; -} - -/* add a character to the buffer */ -static int addchar(TALLOC_CTX *mem_ctx, struct parse_string *p, char c) -{ - if (addgen_alloc(mem_ctx, p, 2) != 0) { - return -1; - } - p->s[p->length++] = c; - p->s[p->length] = 0; - return 0; -} - -/* add a string to the buffer */ -int addstr(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *s) -{ - int len = strlen(s); - if (addgen_alloc(mem_ctx, p, len+1) != 0) { - return -1; - } - memcpy(p->s + p->length, s, len+1); - p->length += len; - return 0; -} - -/* add a string to the buffer with a tab prefix */ -static int addtabbed(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *s, unsigned indent) -{ - int len = strlen(s); - if (addgen_alloc(mem_ctx, p, indent+len+1) != 0) { - return -1; - } - while (indent--) { - p->s[p->length++] = '\t'; - } - memcpy(p->s + p->length, s, len+1); - p->length += len; - return 0; -} - -/* note! this can only be used for results up to 60 chars wide! */ -int addshort(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *fmt, ...) -{ - char buf[60]; - int n; - va_list ap; - va_start(ap, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - if (addgen_alloc(mem_ctx, p, n + 1) != 0) { - return -1; - } - if (n != 0) { - memcpy(p->s + p->length, buf, n); - } - p->length += n; - p->s[p->length] = 0; - return 0; -} - -/* - this is here to make it easier for people to write dump functions - for their own types - */ -int gen_addgen(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *fmt, ...) -{ - char *buf = NULL; - int n; - va_list ap; - va_start(ap, fmt); - n = vasprintf(&buf, fmt, ap); - va_end(ap); - if (addgen_alloc(mem_ctx, p, n + 1) != 0) { - if (buf) free(buf); - return -1; - } - if (n != 0) { - memcpy(p->s + p->length, buf, n); - } - p->length += n; - p->s[p->length] = 0; - if (buf) free(buf); - return 0; -} - -/* dump a enumerated type */ -int gen_dump_enum(TALLOC_CTX *mem_ctx, - const struct enum_struct *einfo, - struct parse_string *p, - const char *ptr, - unsigned indent) -{ - unsigned v = *(const unsigned *)ptr; - int i; - for (i=0;einfo[i].name;i++) { - if (v == einfo[i].value) { - addstr(mem_ctx, p, einfo[i].name); - return 0; - } - } - /* hmm, maybe we should just fail? */ - return gen_dump_unsigned(mem_ctx, p, ptr, indent); -} - -/* dump a single non-array element, hanlding struct and enum */ -static int gen_dump_one(TALLOC_CTX *mem_ctx, - struct parse_string *p, - const struct parse_struct *pinfo, - const char *ptr, - unsigned indent) -{ - if (pinfo->dump_fn == gen_dump_char && pinfo->ptr_count == 1) { - char *s = encode_bytes(mem_ctx, ptr, strlen(ptr)); - if (addchar(mem_ctx, p,'{') || - addstr(mem_ctx, p, s) || - addstr(mem_ctx, p, "}")) { - return -1; - } - return 0; - } - - return pinfo->dump_fn(mem_ctx, p, ptr, indent); -} - -/* handle dumping of an array of arbitrary type */ -static int gen_dump_array(TALLOC_CTX *mem_ctx, - struct parse_string *p, - const struct parse_struct *pinfo, - const char *ptr, - int array_len, - int indent) -{ - int i, count=0; - - /* special handling of fixed length strings */ - if (array_len != 0 && - pinfo->ptr_count == 0 && - pinfo->dump_fn == gen_dump_char) { - char *s = encode_bytes(mem_ctx, ptr, array_len); - if (!s) return -1; - if (addtabbed(mem_ctx, p, pinfo->name, indent) || - addstr(mem_ctx, p, " = {") || - addstr(mem_ctx, p, s) || - addstr(mem_ctx, p, "}\n")) { - return -1; - } - free(s); - return 0; - } - - for (i=0;isize; - - /* generic pointer dereference */ - if (pinfo->ptr_count) { - p2 = *(const char **)ptr; - size = sizeof(void *); - } - - if ((count || pinfo->ptr_count) && - !(pinfo->flags & FLAG_ALWAYS) && - all_zero(ptr, size)) { - ptr += size; - continue; - } - if (count == 0) { - if (addtabbed(mem_ctx, p, pinfo->name, indent) || - addshort(mem_ctx, p, " = %u:", i)) { - return -1; - } - } else { - if (addshort(mem_ctx, p, ", %u:", i) != 0) { - return -1; - } - } - if (gen_dump_one(mem_ctx, p, pinfo, p2, indent) != 0) { - return -1; - } - ptr += size; - count++; - } - if (count) { - return addstr(mem_ctx, p, "\n"); - } - return 0; -} - -/* find a variable by name in a loaded structure and return its value - as an integer. Used to support dynamic arrays */ -static int find_var(const struct parse_struct *pinfo, - const char *data, - const char *var) -{ - int i; - const char *ptr; - - /* this allows for constant lengths */ - if (isdigit(*var)) { - return atoi(var); - } - - for (i=0;pinfo[i].name;i++) { - if (strcmp(pinfo[i].name, var) == 0) break; - } - if (!pinfo[i].name) return -1; - - ptr = data + pinfo[i].offset; - - switch (pinfo[i].size) { - case sizeof(int): - return *(const int *)ptr; - case sizeof(char): - return *(const char *)ptr; - } - - return -1; -} - - -int gen_dump_struct(TALLOC_CTX *mem_ctx, - const struct parse_struct *pinfo, - struct parse_string *p, - const char *ptr, - unsigned indent) -{ - char *s = gen_dump(mem_ctx, pinfo, ptr, indent+1); - if (!s) return -1; - if (addstr(mem_ctx, p, "{\n") || - addstr(mem_ctx, p, s) || - addtabbed(mem_ctx, p, "}", indent)) { - return -1; - } - return 0; -} - -static int gen_dump_string(TALLOC_CTX *mem_ctx, - struct parse_string *p, - const struct parse_struct *pinfo, - const char *data, - unsigned indent) -{ - const char *ptr = *(const char **)data; - char *s = encode_bytes(mem_ctx, ptr, strlen(ptr)); - if (addtabbed(mem_ctx, p, pinfo->name, indent) || - addstr(mem_ctx, p, " = ") || - addchar(mem_ctx, p, '{') || - addstr(mem_ctx, p, s) || - addstr(mem_ctx, p, "}\n")) { - return -1; - } - return 0; -} - -/* - find the length of a nullterm array -*/ -static int len_nullterm(const char *ptr, int size, int array_len) -{ - int len; - - if (size == 1) { - len = strnlen(ptr, array_len); - } else { - for (len=0; len < array_len; len++) { - if (all_zero(ptr+len*size, size)) break; - } - } - - if (len == 0) len = 1; - - return len; -} - - -/* the generic dump routine. Scans the parse information for this structure - and processes it recursively */ -char *gen_dump(TALLOC_CTX *mem_ctx, - const struct parse_struct *pinfo, - const char *data, - unsigned indent) -{ - struct parse_string p; - int i; - - p.length = 0; - p.allocated = 0; - p.s = NULL; - - if (addstr(mem_ctx, &p, "") != 0) { - return NULL; - } - - for (i=0;pinfo[i].name;i++) { - const char *ptr = data + pinfo[i].offset; - unsigned size = pinfo[i].size; - - if (pinfo[i].ptr_count) { - size = sizeof(void *); - } - - /* special handling for array types */ - if (pinfo[i].array_len) { - unsigned len = pinfo[i].array_len; - if (pinfo[i].flags & FLAG_NULLTERM) { - len = len_nullterm(ptr, size, len); - } - if (gen_dump_array(mem_ctx, &p, &pinfo[i], ptr, - len, indent)) { - goto failed; - } - continue; - } - - /* and dynamically sized arrays */ - if (pinfo[i].dynamic_len) { - int len = find_var(pinfo, data, pinfo[i].dynamic_len); - struct parse_struct p2 = pinfo[i]; - if (len < 0) { - goto failed; - } - if (len > 0) { - if (pinfo[i].flags & FLAG_NULLTERM) { - len = len_nullterm(*(const char **)ptr, - pinfo[i].size, len); - } - p2.ptr_count--; - p2.dynamic_len = NULL; - if (gen_dump_array(mem_ctx, &p, &p2, - *(const char **)ptr, - len, indent) != 0) { - goto failed; - } - } - continue; - } - - /* don't dump zero elements */ - if (!(pinfo[i].flags & FLAG_ALWAYS) && all_zero(ptr, size)) continue; - - /* assume char* is a null terminated string */ - if (pinfo[i].size == 1 && pinfo[i].ptr_count == 1 && - pinfo[i].dump_fn == gen_dump_char) { - if (gen_dump_string(mem_ctx, &p, &pinfo[i], ptr, indent) != 0) { - goto failed; - } - continue; - } - - /* generic pointer dereference */ - if (pinfo[i].ptr_count) { - ptr = *(const char **)ptr; - } - - if (addtabbed(mem_ctx, &p, pinfo[i].name, indent) || - addstr(mem_ctx, &p, " = ") || - gen_dump_one(mem_ctx, &p, &pinfo[i], ptr, indent) || - addstr(mem_ctx, &p, "\n")) { - goto failed; - } - } - return p.s; - -failed: - return NULL; -} - -/* search for a character in a string, skipping over sections within - matching braces */ -static char *match_braces(char *s, char c) -{ - int depth = 0; - while (*s) { - switch (*s) { - case '}': - depth--; - break; - case '{': - depth++; - break; - } - if (depth == 0 && *s == c) { - return s; - } - s++; - } - return s; -} - -/* parse routine for enumerated types */ -int gen_parse_enum(TALLOC_CTX *mem_ctx, - const struct enum_struct *einfo, - char *ptr, - const char *str) -{ - unsigned v; - int i; - - if (isdigit(*str)) { - if (sscanf(str, "%u", &v) != 1) { - errno = EINVAL; - return -1; - } - *(unsigned *)ptr = v; - return 0; - } - - for (i=0;einfo[i].name;i++) { - if (strcmp(einfo[i].name, str) == 0) { - *(unsigned *)ptr = einfo[i].value; - return 0; - } - } - - /* unknown enum value?? */ - return -1; -} - - -/* parse all base types */ -static int gen_parse_base(TALLOC_CTX *mem_ctx, - const struct parse_struct *pinfo, - char *ptr, - const char *str) -{ - if (pinfo->parse_fn == gen_parse_char && pinfo->ptr_count==1) { - unsigned len; - char *s = decode_bytes(mem_ctx, str, &len); - if (!s) return -1; - *(char **)ptr = s; - return 0; - } - - if (pinfo->ptr_count) { - unsigned size = pinfo->ptr_count>1?sizeof(void *):pinfo->size; - struct parse_struct p2 = *pinfo; - *(void **)ptr = talloc(mem_ctx, size); - if (! *(void **)ptr) { - return -1; - } - memset(*(void **)ptr, 0, size); - ptr = *(char **)ptr; - p2.ptr_count--; - return gen_parse_base(mem_ctx, &p2, ptr, str); - } - - return pinfo->parse_fn(mem_ctx, ptr, str); -} - -/* parse a generic array */ -static int gen_parse_array(TALLOC_CTX *mem_ctx, - const struct parse_struct *pinfo, - char *ptr, - const char *str, - int array_len) -{ - char *p, *p2; - unsigned size = pinfo->size; - - /* special handling of fixed length strings */ - if (array_len != 0 && - pinfo->ptr_count == 0 && - pinfo->dump_fn == gen_dump_char) { - unsigned len = 0; - char *s = decode_bytes(mem_ctx, str, &len); - if (!s || (len > array_len)) return -1; - memset(ptr, 0, array_len); - memcpy(ptr, s, len); - return 0; - } - - if (pinfo->ptr_count) { - size = sizeof(void *); - } - - while (*str) { - unsigned idx; - int done; - - idx = atoi(str); - p = strchr(str,':'); - if (!p) break; - p++; - p2 = match_braces(p, ','); - done = (*p2 != ','); - *p2 = 0; - - if (*p == '{') { - p++; - p[strlen(p)-1] = 0; - } - - if (gen_parse_base(mem_ctx, pinfo, ptr + idx*size, p) != 0) { - return -1; - } - - if (done) break; - str = p2+1; - } - - return 0; -} - -/* parse one element, hanlding dynamic and static arrays */ -static int gen_parse_one(TALLOC_CTX *mem_ctx, - const struct parse_struct *pinfo, - const char *name, - char *data, - const char *str) -{ - int i; - for (i=0;pinfo[i].name;i++) { - if (strcmp(pinfo[i].name, name) == 0) { - break; - } - } - if (pinfo[i].name == NULL) { - return 0; - } - - if (pinfo[i].array_len) { - return gen_parse_array(mem_ctx, &pinfo[i], - data+pinfo[i].offset, - str, pinfo[i].array_len); - } - - if (pinfo[i].dynamic_len) { - int len = find_var(pinfo, data, pinfo[i].dynamic_len); - if (len < 0) { - errno = EINVAL; - return -1; - } - if (len > 0) { - struct parse_struct p2 = pinfo[i]; - char *ptr; - unsigned size = pinfo[i].ptr_count>1?sizeof(void*):pinfo[i].size; - ptr = talloc(mem_ctx, len*size); - if (!ptr) { - errno = ENOMEM; - return -1; - } - memset(ptr, 0, len*size); - *((char **)(data + pinfo[i].offset)) = ptr; - p2.ptr_count--; - p2.dynamic_len = NULL; - return gen_parse_array(mem_ctx, &p2, ptr, str, len); - } - return 0; - } - - return gen_parse_base(mem_ctx, &pinfo[i], data + pinfo[i].offset, str); -} - -int gen_parse_struct(TALLOC_CTX * mem_ctx, const struct parse_struct *pinfo, char *ptr, const char *str) -{ - return gen_parse(mem_ctx, pinfo, ptr, str); -} - -/* the main parse routine */ -int gen_parse(TALLOC_CTX *mem_ctx, const struct parse_struct *pinfo, char *data, const char *s) -{ - char *str, *s0; - - s0 = strdup(s); - str = s0; - - while (*str) { - char *p; - char *name; - char *value; - - /* skip leading whitespace */ - while (isspace(*str)) str++; - - p = strchr(str, '='); - if (!p) break; - value = p+1; - while (p > str && isspace(*(p-1))) { - p--; - } - - *p = 0; - name = str; - - while (isspace(*value)) value++; - - if (*value == '{') { - str = match_braces(value, '}'); - value++; - } else { - str = match_braces(value, '\n'); - } - - *str++ = 0; - - if (gen_parse_one(mem_ctx, pinfo, name, data, value) != 0) { - free(s0); - return -1; - } - } - - free(s0); - return 0; -} - - - -/* for convenience supply some standard dumpers and parsers here */ - -int gen_parse_char(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(unsigned char *)ptr = atoi(str); - return 0; -} - -int gen_parse_int(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(int *)ptr = atoi(str); - return 0; -} - -int gen_parse_unsigned(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(unsigned *)ptr = strtoul(str, NULL, 10); - return 0; -} - -int gen_parse_time_t(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(time_t *)ptr = strtoul(str, NULL, 10); - return 0; -} - -int gen_parse_double(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(double *)ptr = atof(str); - return 0; -} - -int gen_parse_float(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(float *)ptr = atof(str); - return 0; -} - -int gen_dump_char(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(unsigned char *)(ptr)); -} - -int gen_dump_int(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%d", *(int *)(ptr)); -} - -int gen_dump_unsigned(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(unsigned *)(ptr)); -} - -int gen_dump_time_t(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(time_t *)(ptr)); -} - -int gen_dump_double(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%lg", *(double *)(ptr)); -} - -int gen_dump_float(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%g", *(float *)(ptr)); -} diff --git a/source4/lib/genparser_samba.c b/source4/lib/genparser_samba.c deleted file mode 100644 index bece587747..0000000000 --- a/source4/lib/genparser_samba.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - Copyright (C) Andrew Tridgell 2002 - Copyright (C) Simo Sorce 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "genparser_samba.h" - -/* PARSE functions */ - -int gen_parse_uint8(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(uint8 *)ptr = atoi(str); - return 0; -} - -int gen_parse_uint16(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(uint16 *)ptr = atoi(str); - return 0; -} - -int gen_parse_uint32(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - *(uint32 *)ptr = strtoul(str, NULL, 10); - return 0; -} - -int gen_parse_NTTIME(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - if(sscanf(str, "%u,%u", &(((NTTIME *)(ptr))->high), &(((NTTIME *)(ptr))->low)) != 2) { - errno = EINVAL; - return -1; - } - return 0; -} - -int gen_parse_DOM_SID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - if(!string_to_sid((DOM_SID *)ptr, str)) return -1; - return 0; -} - -int gen_parse_SEC_ACCESS(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - ((SEC_ACCESS *)ptr)->mask = strtoul(str, NULL, 10); - return 0; -} - -int gen_parse_GUID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - int info[GUID_SIZE]; - int i; - char *sc; - char *p; - char *m; - - m = strdup(str); - if (!m) return -1; - sc = m; - - memset(info, 0, sizeof(info)); - for (i = 0; i < GUID_SIZE; i++) { - p = strchr(sc, ','); - if (p != NULL) p = '\0'; - info[i] = atoi(sc); - if (p != NULL) sc = p + 1; - } - free(m); - - for (i = 0; i < GUID_SIZE; i++) { - ((GUID *)ptr)->info[i] = info[i]; - } - - return 0; -} - -int gen_parse_SEC_ACE(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - return gen_parse_struct(mem_ctx, pinfo_security_ace_info, ptr, str); -} - -int gen_parse_SEC_ACL(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - return gen_parse_struct(mem_ctx, pinfo_security_acl_info, ptr, str); -} - -int gen_parse_SEC_DESC(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - return gen_parse_struct(mem_ctx, pinfo_security_descriptor_info, ptr, str); -} - -int gen_parse_LUID_ATTR(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - return gen_parse_struct(mem_ctx, pinfo_luid_attr_info, ptr, str); -} - -int gen_parse_LUID(TALLOC_CTX *mem_ctx, char *ptr, const char *str) -{ - if(sscanf(str, "%u,%u", &(((LUID *)(ptr))->high), &(((LUID *)(ptr))->low)) != 2) { - errno = EINVAL; - return -1; - } - return 0; -} - - - -/* DUMP functions */ - -int gen_dump_uint8(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(uint8 *)(ptr)); -} - -int gen_dump_uint16(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(uint16 *)(ptr)); -} - -int gen_dump_uint32(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", *(uint32 *)(ptr)); -} - -int gen_dump_NTTIME(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - uint32 low, high; - - high = ((NTTIME *)(ptr))->high; - low = ((NTTIME *)(ptr))->low; - return addshort(mem_ctx, p, "%u,%u", high, low); -} - -int gen_dump_DOM_SID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - fstring sidstr; - - sid_to_string(sidstr, (DOM_SID *)ptr); - return addstr(mem_ctx, p, sidstr); -} - -int gen_dump_SEC_ACCESS(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return addshort(mem_ctx, p, "%u", ((SEC_ACCESS *)ptr)->mask); -} - -int gen_dump_GUID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - int i, r; - - for (i = 0; i < (GUID_SIZE - 1); i++) { - if (!(r = addshort(mem_ctx, p, "%d,", ((GUID *)ptr)->info[i]))) return r; - } - return addshort(mem_ctx, p, "%d", ((GUID *)ptr)->info[i]); -} - -int gen_dump_SEC_ACE(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return gen_dump_struct(mem_ctx, pinfo_security_ace_info, p, ptr, indent); -} - -int gen_dump_SEC_ACL(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return gen_dump_struct(mem_ctx, pinfo_security_acl_info, p, ptr, indent); -} - -int gen_dump_SEC_DESC(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return gen_dump_struct(mem_ctx, pinfo_security_descriptor_info, p, ptr, indent); -} - -int gen_dump_LUID_ATTR(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - return gen_dump_struct(mem_ctx, pinfo_luid_attr_info, p, ptr, indent); -} - -int gen_dump_LUID(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) -{ - uint32 low, high; - - high = ((LUID *)(ptr))->high; - low = ((LUID *)(ptr))->low; - return addshort(mem_ctx, p, "%u,%u", high, low); -} - diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c index f0fa048bb6..62841ddfc2 100644 --- a/source4/lib/tdb/tdbutil.c +++ b/source4/lib/tdb/tdbutil.c @@ -621,68 +621,6 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) return -1; } - -/** - * Pack SID passed by pointer - * - * @param pack_buf pointer to buffer which is to be filled with packed data - * @param bufsize size of packing buffer - * @param sid pointer to sid to be packed - * - * @return length of the packed representation of the whole structure - **/ -size_t tdb_sid_pack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx; - size_t len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_pack(tdb, pack_buf + len, bufsize - len, "bb", sid->sid_rev_num, - sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_pack(tdb, pack_buf + len, bufsize - len, "b", sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_pack(tdb, pack_buf + len, bufsize - len, "d", sid->sub_auths[idx]); - } - - return len; -} - - -/** - * Unpack SID into a pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param sid pointer to sid structure to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, DOM_SID* sid) -{ - int idx, len = 0; - - if (!sid || !pack_buf) return -1; - - len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb", - &sid->sid_rev_num, &sid->num_auths); - - for (idx = 0; idx < 6; idx++) { - len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); - } - - for (idx = 0; idx < MAXSUBAUTHS; idx++) { - len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); - } - - return len; -} - - /**************************************************************************** Print out debug messages. ****************************************************************************/ diff --git a/source4/lib/util_seaccess.c b/source4/lib/util_seaccess.c deleted file mode 100644 index 9d56a0d850..0000000000 --- a/source4/lib/util_seaccess.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Copyright (C) Luke Kenneth Casson Leighton 1996-2000. - Copyright (C) Tim Potter 2000. - Copyright (C) Re-written by Jeremy Allison 2000. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#error SAMBA4 clean up -#error this file should be (re)moved -#error and all unused stuff should go - -#include "includes.h" - -extern DOM_SID global_sid_Builtin; - -/********************************************************************************** - Check if this ACE has a SID in common with the token. -**********************************************************************************/ - -static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) -{ - size_t i; - - for (i = 0; i < token->num_sids; i++) { - if (sid_equal(&ace->trustee, &token->user_sids[i])) - return True; - } - - return False; -} - -/********************************************************************************* - Check an ACE against a SID. We return the remaining needed permission - bits not yet granted. Zero means permission allowed (no more needed bits). -**********************************************************************************/ - -static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired, - NTSTATUS *status) -{ - uint32 mask = ace->info.mask; - - /* - * Inherit only is ignored. - */ - - if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - return acc_desired; - } - - /* - * If this ACE has no SID in common with the token, - * ignore it as it cannot be used to make an access - * determination. - */ - - if (!token_sid_in_ace( token, ace)) - return acc_desired; - - switch (ace->type) { - case SEC_ACE_TYPE_ACCESS_ALLOWED: - /* - * This is explicitly allowed. - * Remove the bits from the remaining - * access required. Return the remaining - * bits needed. - */ - acc_desired &= ~mask; - break; - case SEC_ACE_TYPE_ACCESS_DENIED: - /* - * This is explicitly denied. - * If any bits match terminate here, - * we are denied. - */ - if (acc_desired & mask) { - *status = NT_STATUS_ACCESS_DENIED; - return 0xFFFFFFFF; - } - break; - case SEC_ACE_TYPE_SYSTEM_ALARM: - case SEC_ACE_TYPE_SYSTEM_AUDIT: - *status = NT_STATUS_NOT_IMPLEMENTED; - return 0xFFFFFFFF; - default: - *status = NT_STATUS_INVALID_PARAMETER; - return 0xFFFFFFFF; - } - - return acc_desired; -} - -/********************************************************************************* - Maximum access was requested. Calculate the max possible. Fail if it doesn't - include other bits requested. -**********************************************************************************/ - -static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32 *granted, - uint32 desired, - NTSTATUS *status) -{ - uint32 acc_denied = 0; - uint32 acc_granted = 0; - size_t i; - - for ( i = 0 ; i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - uint32 mask = ace->info.mask; - - if (!token_sid_in_ace( token, ace)) - continue; - - switch (ace->type) { - case SEC_ACE_TYPE_ACCESS_ALLOWED: - acc_granted |= (mask & ~acc_denied); - break; - case SEC_ACE_TYPE_ACCESS_DENIED: - acc_denied |= (mask & ~acc_granted); - break; - case SEC_ACE_TYPE_SYSTEM_ALARM: - case SEC_ACE_TYPE_SYSTEM_AUDIT: - *status = NT_STATUS_NOT_IMPLEMENTED; - *granted = 0; - return False; - default: - *status = NT_STATUS_INVALID_PARAMETER; - *granted = 0; - return False; - } - } - - /* - * If we were granted no access, or we desired bits that we - * didn't get, then deny. - */ - - if ((acc_granted == 0) || ((acc_granted & desired) != desired)) { - *status = NT_STATUS_ACCESS_DENIED; - *granted = 0; - return False; - } - - /* - * Return the access we did get. - */ - - *granted = acc_granted; - *status = NT_STATUS_OK; - return True; -} - -/* Map generic access rights to object specific rights. This technique is - used to give meaning to assigning read, write, execute and all access to - objects. Each type of object has its own mapping of generic to object - specific access rights. */ - -void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping) -{ - uint32 old_mask = *access_mask; - - if (*access_mask & GENERIC_READ_ACCESS) { - *access_mask &= ~GENERIC_READ_ACCESS; - *access_mask |= mapping->generic_read; - } - - if (*access_mask & GENERIC_WRITE_ACCESS) { - *access_mask &= ~GENERIC_WRITE_ACCESS; - *access_mask |= mapping->generic_write; - } - - if (*access_mask & GENERIC_EXECUTE_ACCESS) { - *access_mask &= ~GENERIC_EXECUTE_ACCESS; - *access_mask |= mapping->generic_execute; - } - - if (*access_mask & GENERIC_ALL_ACCESS) { - *access_mask &= ~GENERIC_ALL_ACCESS; - *access_mask |= mapping->generic_all; - } - - if (old_mask != *access_mask) { - DEBUG(10, ("se_map_generic(): mapped mask 0x%08x to 0x%08x\n", - old_mask, *access_mask)); - } -} - -/* Map standard access rights to object specific rights. This technique is - used to give meaning to assigning read, write, execute and all access to - objects. Each type of object has its own mapping of standard to object - specific access rights. */ - -void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping) -{ - uint32 old_mask = *access_mask; - - if (*access_mask & READ_CONTROL_ACCESS) { - *access_mask &= ~READ_CONTROL_ACCESS; - *access_mask |= mapping->std_read; - } - - if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS)) { - *access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS); - *access_mask |= mapping->std_all; - } - - if (old_mask != *access_mask) { - DEBUG(10, ("se_map_standard(): mapped mask 0x%08x to 0x%08x\n", - old_mask, *access_mask)); - } -} - -/***************************************************************************** - Check access rights of a user against a security descriptor. Look at - each ACE in the security descriptor until an access denied ACE denies - any of the desired rights to the user or any of the users groups, or one - or more ACEs explicitly grant all requested access rights. See - "Access-Checking" document in MSDN. -*****************************************************************************/ - -BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, - uint32 acc_desired, uint32 *acc_granted, - NTSTATUS *status) -{ - extern NT_USER_TOKEN anonymous_token; - size_t i; - SEC_ACL *the_acl; - fstring sid_str; - uint32 tmp_acc_desired = acc_desired; - - if (!status || !acc_granted) - return False; - - if (!token) - token = &anonymous_token; - - *status = NT_STATUS_OK; - *acc_granted = 0; - - DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n", - (unsigned int)acc_desired, (unsigned int)token->num_sids, - sid_to_string(sid_str, &token->user_sids[0]))); - - /* - * No security descriptor or security descriptor with no DACL - * present allows all access. - */ - - /* ACL must have something in it */ - - if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) { - *status = NT_STATUS_OK; - *acc_granted = acc_desired; - DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n")); - return True; - } - - /* The user sid is the first in the token */ - if (DEBUGLVL(3)) { - DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) )); - - for (i = 1; i < token->num_sids; i++) { - DEBUGADD(3, ("se_access_check: also %s\n", - sid_to_string(sid_str, &token->user_sids[i]))); - } - } - - /* Is the token the owner of the SID ? */ - - if (sd->owner_sid) { - for (i = 0; i < token->num_sids; i++) { - if (sid_equal(&token->user_sids[i], sd->owner_sid)) { - /* - * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL. - */ - if (tmp_acc_desired & WRITE_DAC_ACCESS) - tmp_acc_desired &= ~WRITE_DAC_ACCESS; - if (tmp_acc_desired & READ_CONTROL_ACCESS) - tmp_acc_desired &= ~READ_CONTROL_ACCESS; - } - } - } - - the_acl = sd->dacl; - - if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) { - tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS; - return get_max_access( the_acl, token, acc_granted, tmp_acc_desired, - status); - } - - for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - - DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n", - (unsigned int)i, ace->type, ace->flags, - sid_to_string(sid_str, &ace->trustee), - (unsigned int) ace->info.mask, - (unsigned int)tmp_acc_desired )); - - tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status); - if (NT_STATUS_V(*status)) { - *acc_granted = 0; - DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, nt_errstr(*status))); - return False; - } - } - - /* - * If there are no more desired permissions left then - * access was allowed. - */ - - if (tmp_acc_desired == 0) { - *acc_granted = acc_desired; - *status = NT_STATUS_OK; - DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired )); - return True; - } - - *acc_granted = 0; - *status = NT_STATUS_ACCESS_DENIED; - DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired )); - return False; -} - -/* Create a child security descriptor using another security descriptor as - the parent container. This child object can either be a container or - non-container object. */ - -SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, - BOOL child_container) -{ - SEC_DESC_BUF *sdb; - SEC_DESC *sd; - SEC_ACL *new_dacl, *the_acl; - SEC_ACE *new_ace_list = NULL; - unsigned int new_ace_list_ndx = 0, i; - size_t size; - - /* Currently we only process the dacl when creating the child. The - sacl should also be processed but this is left out as sacls are - not implemented in Samba at the moment.*/ - - the_acl = parent_ctr->dacl; - - if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) - return NULL; - - for (i = 0; the_acl && i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; - uint8 new_flags = 0; - BOOL inherit = False; - fstring sid_str; - - /* The OBJECT_INHERIT_ACE flag causes the ACE to be - inherited by non-container children objects. Container - children objects will inherit it as an INHERIT_ONLY - ACE. */ - - if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { - - if (!child_container) { - new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; - } else { - new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } - - inherit = True; - } - - /* The CONAINER_INHERIT_ACE flag means all child container - objects will inherit and use the ACE. */ - - if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { - if (!child_container) { - inherit = False; - } else { - new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; - } - } - - /* The INHERIT_ONLY_ACE is not used by the se_access_check() - function for the parent container, but is inherited by - all child objects as a normal ACE. */ - - if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - /* Move along, nothing to see here */ - } - - /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE - is inherited by child objects but not grandchildren - objects. We clear the object inherit and container - inherit flags in the inherited ACE. */ - - if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { - new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* Add ACE to ACE list */ - - if (!inherit) - continue; - - init_sec_access(&new_ace->info, ace->info.mask); - init_sec_ace(new_ace, &ace->trustee, ace->type, - new_ace->info, new_flags); - - sid_to_string(sid_str, &ace->trustee); - - DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " - " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, - ace->type, ace->flags, ace->info.mask, - sid_str, new_ace->type, new_ace->flags, - new_ace->info.mask)); - - new_ace_list_ndx++; - } - - /* Create child security descriptor to return */ - - new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); - - /* Use the existing user and group sids. I don't think this is - correct. Perhaps the user and group should be passed in as - parameters by the caller? */ - - sd = make_sec_desc(ctx, SEC_DESC_REVISION, - parent_ctr->owner_sid, - parent_ctr->grp_sid, - parent_ctr->sacl, - new_dacl, &size); - - sdb = make_sec_desc_buf(ctx, size, sd); - - return sdb; -} - -/******************************************************************* - samr_make_sam_obj_sd - ********************************************************************/ - -NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) -{ - extern DOM_SID global_sid_World; - DOM_SID adm_sid; - DOM_SID act_sid; - - SEC_ACE ace[3]; - SEC_ACCESS mask; - - SEC_ACL *psa = NULL; - - sid_copy(&adm_sid, &global_sid_Builtin); - sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); - - sid_copy(&act_sid, &global_sid_Builtin); - sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); - - /*basic access for every one*/ - init_sec_access(&mask, GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ); - init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /*full access for builtin aliases Administrators and Account Operators*/ - init_sec_access(&mask, GENERIC_RIGHTS_SAM_ALL_ACCESS); - init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) - return NT_STATUS_NO_MEMORY; - - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) - return NT_STATUS_NO_MEMORY; - - return NT_STATUS_OK; -} diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 5ce72a6f51..56f5abd611 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -289,7 +289,7 @@ size_t sid_size(const struct dom_sid *sid) } /***************************************************************** - Return the binary string representation of a DOM_SID. + Return the binary string representation of a struct dom_sid. Caller must free. *****************************************************************/ -- cgit From f7a7192eff21fb48e4bd41ce65d0c0c175d4a1fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 May 2004 00:40:25 +0000 Subject: r827: remove a few more unused functions that we are unlikely to use again (This used to be commit 121dd9ba0038f6e076c464cddad0b788fe6076fa) --- source4/lib/util_str.c | 227 +--------------------------------------------- source4/lib/util_unistr.c | 37 -------- 2 files changed, 1 insertion(+), 263 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 07fdf334fd..7bdec8c1e9 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -88,11 +88,6 @@ BOOL next_token_nr(const char **ptr, char *buff, const char *sep, size_t bufsize static uint16 tmpbuf[sizeof(pstring)]; -void set_first_token(char *ptr) -{ - last_ptr = ptr; -} - /** Convert list of tokens to array; dependent on above routine. Uses last_ptr from above - bit of a hack. @@ -155,7 +150,7 @@ int StrCaseCmp(const char *s, const char *t) Case insensitive string compararison, length limited. **/ -int StrnCaseCmp(const char *s, const char *t, size_t n) +static int StrnCaseCmp(const char *s, const char *t, size_t n) { pstring buf1, buf2; unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); @@ -266,17 +261,6 @@ void string_replace(char *s,char oldc,char newc) } } -/** - Skip past some strings in a buffer. -**/ - -char *skip_string(char *buf,size_t n) -{ - while (n--) - buf += strlen(buf) + 1; - return(buf); -} - /** Count the number of characters in a string. Normally this will be the same as the number of bytes in a string for single byte strings, @@ -384,27 +368,6 @@ size_t count_chars(const char *s,char c) return(count); } -/** -Return True if a string consists only of one particular character. -**/ - -BOOL str_is_all(const char *s,char c) -{ - smb_ucs2_t *ptr; - - if(s == NULL) - return False; - if(!*s) - return False; - - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - for(ptr=tmpbuf;*ptr;ptr++) - if(*ptr!=UCS2_CHAR(c)) - return False; - - return True; -} - /** Safe string copy into a known length string. maxlength does not include the terminating zero. @@ -554,73 +517,6 @@ char *StrnCpy(char *dest,const char *src,size_t n) return(dest); } -/** - Like strncpy but copies up to the character marker. always null terminates. - returns a pointer to the character marker in the source string (src). -**/ - -char *strncpyn(char *dest, const char *src, size_t n, char c) -{ - char *p; - size_t str_len; - - p = strchr_m(src, c); - if (p == NULL) { - DEBUG(5, ("strncpyn: separator character (%c) not found\n", c)); - return NULL; - } - - str_len = PTR_DIFF(p, src); - strncpy(dest, src, MIN(n, str_len)); - dest[str_len] = '\0'; - - return p; -} - -/** - Routine to get hex characters and turn them into a 16 byte array. - the array can be variable length, and any non-hex-numeric - characters are skipped. "0xnn" or "0Xnn" is specially catered - for. - - valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" - -**/ - -size_t strhex_to_str(char *p, size_t len, const char *strhex) -{ - size_t i; - size_t num_chars = 0; - unsigned char lonybble, hinybble; - const char *hexchars = "0123456789ABCDEF"; - char *p1 = NULL, *p2 = NULL; - - for (i = 0; i < len && strhex[i] != 0; i++) { - if (strnequal(hexchars, "0x", 2)) { - i++; /* skip two chars */ - continue; - } - - if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) - break; - - i++; /* next hex digit */ - - if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) - break; - - /* get the two nybbles */ - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - p[num_chars] = (hinybble << 4) | lonybble; - num_chars++; - - p1 = NULL; - p2 = NULL; - } - return num_chars; -} /** Check if a string is part of a list. @@ -737,76 +633,6 @@ void string_sub(char *s,const char *pattern, const char *insert, size_t len) } } -void pstring_sub(char *s,const char *pattern,const char *insert) -{ - string_sub(s, pattern, insert, sizeof(pstring)); -} - -/** - Similar to string_sub, but it will accept only allocated strings - and may realloc them so pay attention at what you pass on no - pointers inside strings, no pstrings or const may be passed - as string. -**/ - -char *realloc_string_sub(char *string, const char *pattern, const char *insert) -{ - char *p, *in; - char *s; - ssize_t ls,lp,li,ld, i; - - if (!insert || !pattern || !*pattern || !string || !*string) - return NULL; - - s = string; - - in = strdup(insert); - if (!in) { - DEBUG(0, ("realloc_string_sub: out of memory!\n")); - return NULL; - } - ls = (ssize_t)strlen(s); - lp = (ssize_t)strlen(pattern); - li = (ssize_t)strlen(insert); - ld = li - lp; - for (i=0;i 0) { - char *t = Realloc(string, ls + ld + 1); - if (!t) { - DEBUG(0, ("realloc_string_sub: out of memory!\n")); - SAFE_FREE(in); - return NULL; - } - string = t; - p = t + (p - s); - } - if (li != lp) { - memmove(p+li,p+lp,strlen(p+lp)+1); - } - memcpy(p, in, li); - s = p + li; - ls += ld; - } - SAFE_FREE(in); - return string; -} /** Similar to string_sub() but allows for any character to be substituted. @@ -849,30 +675,6 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) } } -/** - Splits out the front and back at a separator. -**/ - -void split_at_last_component(char *path, char *front, char sep, char *back) -{ - char *p = strrchr_m(path, sep); - - if (p != NULL) - *p = 0; - - if (front != NULL) - pstrcpy(front, path); - - if (p != NULL) { - if (back != NULL) - pstrcpy(back, p+1); - *p = '\\'; - } else { - if (back != NULL) - back[0] = 0; - } -} - /** Write an octal as a string. **/ @@ -887,17 +689,6 @@ const char *octal_string(int i) } -/** - Truncate a string at a specified length. -**/ - -char *string_truncate(char *s, int length) -{ - if (s && strlen(s) > length) - s[length] = 0; - return s; -} - /** Strchr and strrchr_m are very hard to do on general multi-byte strings. We convert via ucs2 for now. @@ -957,21 +748,6 @@ void strlower_m(char *s) unix_strlower(s,strlen(s)+1,s,strlen(s)+1); } -/** - Duplicate convert a string to lower case. -**/ - -char *strdup_lower(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_lower: Out of memory!\n")); - return NULL; - } - strlower_m(t); - return t; -} - /** Convert a string to upper case. **/ @@ -1344,7 +1120,6 @@ char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) return *ipstr_list; } - /** * Allocate and initialise an ipstr list using ip adresses * passed as arguments. diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 5e48d716b9..76ebadc3ef 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -257,24 +257,6 @@ static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) } -/******************************************************************* -wide strstr() -********************************************************************/ -const smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) -{ - const smb_ucs2_t *r; - size_t inslen; - - if (!s || !*s || !ins || !*ins) return NULL; - inslen = strlen_w(ins); - r = s; - while ((r = strchr_w(r, *ins))) { - if (strncmp_w(r, ins, inslen) == 0) return r; - r++; - } - return NULL; -} - /******************************************************************* Convert a string to lower case. return True if any char is converted @@ -320,25 +302,6 @@ int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) return (tolower_w(*a) - tolower_w(*b)); } -/******************************************************************* -copy a string with max len -********************************************************************/ - -smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max) -{ - size_t len; - - if (!dest || !src) return NULL; - - for (len = 0; (src[len] != 0) && (len < max); len++) - dest[len] = src[len]; - while (len < max) - dest[len++] = 0; - - return dest; -} - - /******************************************************************* replace any occurence of oldc with newc in unicode string ********************************************************************/ -- cgit From f371d2454298b0e64978c04056da5635d7e72921 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 12:01:20 +0000 Subject: r828: Some fixes in the core and regshell concerning hives and unicode (This used to be commit 25c27b176c9905f3968e955f33a6db41b0102a38) --- source4/lib/registry/common/reg_interface.c | 14 +++++++------- source4/lib/registry/common/reg_objects.c | 2 +- source4/lib/registry/common/registry.h | 2 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 5 ++++- source4/lib/registry/tools/regshell.c | 21 +++++++++++++++++---- source4/lib/registry/tools/regtree.c | 6 +++--- 6 files changed, 33 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 3e5a545f9a..e748c836cf 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -176,15 +176,15 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) return WERR_OK; } - mem_ctx = talloc_init("mem_ctx"); - - fullname = talloc_asprintf(mem_ctx, "%s%s%s", parent->path, parent->path[strlen(parent->path)-1] == '\\'?"":"\\", name); - if(!parent->handle->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); return WERR_NOT_SUPPORTED; } + mem_ctx = talloc_init("mem_ctx"); + + fullname = talloc_asprintf(mem_ctx, "%s%s%s", reg_key_get_path(parent), strlen(reg_key_get_path(parent))?"\\":"", name); + error = parent->handle->functions->open_key(parent->handle, parent->hive, fullname, result); if(!W_ERROR_IS_OK(error)) { @@ -193,7 +193,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) } (*result)->handle = parent->handle; - (*result)->path = fullname; + (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; talloc_steal(mem_ctx, (*result)->mem_ctx, fullname); @@ -303,7 +303,7 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) return WERR_NOT_SUPPORTED; } - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); + (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); (*subkey)->handle = key->handle; (*subkey)->hive = key->hive; @@ -334,7 +334,7 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk if(!W_ERROR_IS_OK(error)) return error; - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s%s%s", key->path, key->path[strlen(key->path)-1] == '\\'?"":"\\", (*subkey)->name); + (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); (*subkey)->handle = key->handle; (*subkey)->hive = key->hive; diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 7a92f413ff..0109a1f8fe 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -141,7 +141,7 @@ char *reg_val_get_path(REG_VAL *v) const char *reg_key_get_path(REG_KEY *k) { SMB_REG_ASSERT(k); - return strchr(k->path, '\\')?strchr(k->path, '\\')+1:k->path; + return strchr(k->path, '\\')?strchr(k->path, '\\')+1:""; } const char *reg_key_get_path_abs(REG_KEY *k) diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index d4e8cccade..5325a89086 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -31,7 +31,7 @@ struct reg_key_s { char *name; /* Name of the key */ char *path; /* Full path to the key */ - smb_ucs2_t *class_name; /* Name of key class */ + char *class_name; /* Name of key class */ NTTIME last_mod; /* Time last modified */ SEC_DESC *security; REG_HANDLE *handle; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 255389624e..a28f1880db 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1085,12 +1085,15 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent if (clsname_len) { /* Just print in Ascii for now */ smb_ucs2_t *clsnamep; int clsnam_off; + char *clsnameu; clsnam_off = IVAL(&nk_hdr->clsnam_off,0); clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - tmp->class_name = talloc_strdup_w(h->mem_ctx, clsnamep); + clsnameu = acnv_u2ux(clsnamep); + tmp->class_name = talloc_strdup(tmp->mem_ctx, clsnameu); + SAFE_FREE(clsnameu); DEBUGADD(2,(" Class Name: %s\n", cls_name)); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 26312ad4bc..dbddaa5dcf 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -32,6 +32,12 @@ * exit */ +static REG_KEY *cmd_pwd(REG_KEY *cur, int argc, char **argv) +{ + printf("%s\n", reg_key_get_path_abs(cur)); + return cur; +} + static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) { /* FIXME */ @@ -52,7 +58,7 @@ static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) } } - printf("Current path is: %s\n", reg_key_get_path(new)); + printf("Current path is: %s\n", reg_key_get_path_abs(new)); return new; } @@ -68,7 +74,7 @@ static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while browsing thru keys\n")); + DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error))); } for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(cur, i, &value)); i++) { @@ -90,7 +96,7 @@ static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) return NULL; } - fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path(cur)); + fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path_abs(cur)); return NULL; } @@ -139,6 +145,11 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) return NULL; } +static REG_KEY *cmd_hive(REG_KEY *cur, int argc, char **argv) +{ + /* FIXME */ +} + static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) { exit(0); @@ -154,10 +165,12 @@ struct { REG_KEY *(*handle)(REG_KEY *, int argc, char **argv); } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, + {"ch", "hive", "Change current hive", cmd_hive }, {"list", "ls", "List values/keys in current key", cmd_ls }, {"mkkey", "mkdir", "Make new key", cmd_mkkey }, {"rmval", "rm", "Remove value", cmd_rmval }, {"rmkey", "rmdir", "Remove key", cmd_rmkey }, + {"pwd", "pwk", "Printing current key", cmd_pwd }, {"set", "update", "Update value", cmd_set }, {"help", "?", "Help", cmd_help }, {"exit", "quit", "Exit", cmd_exit }, @@ -235,7 +248,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) while(True) { char *line, *prompt; - asprintf(&prompt, "%s> ", reg_key_get_path(curkey)); + asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey)); line = smb_readline(prompt, NULL, NULL); diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index e583194a56..b1ca9b3fb2 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -29,7 +29,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) int i; for(i = 0; i < l; i++) putchar(' '); - if(fullpath) printf("%s\n", reg_key_get_path(p)); + if(fullpath) printf("%s\n", reg_key_get_path_abs(p)); else printf("%s\n", reg_key_name(p)); for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(p, i, &subkey)); i++) { @@ -38,7 +38,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); } if(!novals) { @@ -53,7 +53,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching values for '%s': %s\n", reg_key_get_path(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching values for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); } } } -- cgit From 4a137a7cf154955db5d1b1bb67017575a428d737 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 12:12:50 +0000 Subject: r829: Implement 'hive' command (This used to be commit 2a87981bd0a79f0d685441d690e2f810d6ed86d0) --- source4/lib/registry/common/reg_objects.c | 5 +++++ source4/lib/registry/tools/regshell.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 0109a1f8fe..168ee946e8 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -93,6 +93,11 @@ uint32 reg_val_type( REG_VAL *val ) /********************************************************************** *********************************************************************/ +REG_HANDLE *reg_key_handle (REG_KEY *key) +{ + return key->handle; +} + char *reg_key_name( REG_KEY *key ) { return key->name; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index dbddaa5dcf..b843e91120 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -147,7 +147,21 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) static REG_KEY *cmd_hive(REG_KEY *cur, int argc, char **argv) { - /* FIXME */ + int i; + WERROR error = WERR_OK; + for(i = 0; W_ERROR_IS_OK(error); i++) { + REG_KEY *hive; + error = reg_get_hive(reg_key_handle(cur), i, &hive); + if(!W_ERROR_IS_OK(error)) break; + + if(argc == 1) { + printf("%s\n", reg_key_name(hive)); + } else if(!strcmp(reg_key_name(hive), argv[1])) { + return hive; + } + reg_key_free(hive); + } + return NULL; } static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) -- cgit From a64be8dbdd9e3e2aecb696b38925cc8f15a91f36 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 12:37:55 +0000 Subject: r830: Use pull_ucs2_talloc() instead of acnv_u2ux() and fix a memory leak. (This used to be commit ad88561becf59cd38a3e329e68cbe5518a3373d7) --- source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index a28f1880db..e4f9447488 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -919,7 +919,7 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val if (dat_len&0x7FFFFFFF) { - char *dtmp = (char *)malloc(dat_len&0x7FFFFFFF); + char *dtmp = (char *)talloc(tmp->mem_ctx, dat_len&0x7FFFFFFF); tmp->data_blk = dtmp; @@ -1085,15 +1085,12 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent if (clsname_len) { /* Just print in Ascii for now */ smb_ucs2_t *clsnamep; int clsnam_off; - char *clsnameu; clsnam_off = IVAL(&nk_hdr->clsnam_off,0); clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - clsnameu = acnv_u2ux(clsnamep); - tmp->class_name = talloc_strdup(tmp->mem_ctx, clsnameu); - SAFE_FREE(clsnameu); + pull_ucs2_talloc(tmp->mem_ctx, &tmp->class_name, clsnamep); DEBUGADD(2,(" Class Name: %s\n", cls_name)); -- cgit From 5b5e793d1637da2521fbb43028bc7547f4ed58d3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 23 May 2004 12:44:53 +0000 Subject: r831: These functions duplicate the push/pull charcnv interfaces that we use everywhere else in the Samba code, so remove them for clarity. (ok, so also just never liked the names ;-) Andrew Bartlett (This used to be commit 5f5786ad5ff6cc133a143476e8968b00ed057a62) --- source4/lib/charcnv.c | 83 --------------------------------------------------- 1 file changed, 83 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 11b0e64dce..ed56d9d0cc 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -841,86 +841,3 @@ ssize_t pull_string_talloc(TALLOC_CTX *ctx, char **dest, const void *src, size_t return src_len; } -/** - Convert from ucs2 to unix charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -char *acnv_u2ux(const smb_ucs2_t *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t); - dlen = convert_string_allocate(CH_UCS2, CH_UNIX, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} - -/** - Convert from unix to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_uxu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} - -/** - Convert from ucs2 to dos charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -char *acnv_u2dos(const smb_ucs2_t *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t); - dlen = convert_string_allocate(CH_UCS2, CH_DOS, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} - -/** - Convert from dos to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_dosu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} -- cgit From b4c23f5a52ca5f3fa93e42f95efc74f5d6b47d50 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 13:50:56 +0000 Subject: r832: Only show menu items for backends if they're present (This used to be commit 9228aeeafd956a2885b5f1dfaa6feacb555b7483) --- source4/lib/registry/common/reg_interface.c | 31 +++++++++++++++++----------- source4/lib/registry/tools/gregedit.c | 32 ++++++++++++++++++----------- 2 files changed, 39 insertions(+), 24 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index e748c836cf..93e5b60984 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -58,7 +58,19 @@ NTSTATUS registry_register(void *_function) /* Find a backend in the list of available backends */ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { - struct reg_init_function_entry *entry = backends; + struct reg_init_function_entry *entry; + static BOOL reg_first_init = True; + + if(reg_first_init) { + status = register_subsystem("registry", registry_register); + if (!NT_STATUS_IS_OK(status)) + return WERR_GENERAL_FAILURE; + + static_init_registry; + reg_first_init = False; + } + + entry = backends; while(entry) { if (strcmp(entry->functions->name, name)==0) return entry; @@ -68,25 +80,20 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) return NULL; } +BOOL reg_has_backend(const char *backend) +{ + return reg_find_backend_entry(backend)?True:False; +} + /* Open a registry file/host/etc */ WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h) { struct reg_init_function_entry *entry; - static BOOL reg_first_init = True; TALLOC_CTX *mem_ctx; REG_HANDLE *ret; NTSTATUS status; WERROR werr; - - if(reg_first_init) { - status = register_subsystem("registry", registry_register); - if (!NT_STATUS_IS_OK(status)) - return WERR_GENERAL_FAILURE; - - static_init_registry; - reg_first_init = False; - } - + entry = reg_find_backend_entry(backend); if (!entry) { diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index e8800c6ee9..5b78292061 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -450,21 +450,29 @@ static GtkWidget* create_mainwin (void) menu_file_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_file), menu_file_menu); - open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file"); - gtk_widget_show (open_nt4); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); + if(reg_has_backend("nt4")) { + open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file"); + gtk_widget_show (open_nt4); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); + } - open_w95 = gtk_image_menu_item_new_with_mnemonic("_Open Win9x file"); - gtk_widget_show (open_w95); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); + if(reg_has_backend("w95")) { + open_w95 = gtk_image_menu_item_new_with_mnemonic("_Open Win9x file"); + gtk_widget_show (open_w95); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); + } - open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); - gtk_widget_show (open_gconf); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); + if(reg_has_backend("gconf")) { + open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); + gtk_widget_show (open_gconf); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); + } - open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote"); - gtk_widget_show (open_remote); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); + if(reg_has_backend("rpc")) { + open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote"); + gtk_widget_show (open_remote); + gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); + } save = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group); gtk_widget_show (save); -- cgit From f0d7ae39c00627ebc1e43927ae5df42762e73d95 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 13:55:52 +0000 Subject: r833: Compile error (This used to be commit e4f6ca85223b86beac237398ea5474f4f56404a2) --- source4/lib/registry/common/reg_interface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 93e5b60984..6acedb3591 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -60,11 +60,12 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { struct reg_init_function_entry *entry; static BOOL reg_first_init = True; + NTSTATUS status; if(reg_first_init) { status = register_subsystem("registry", registry_register); if (!NT_STATUS_IS_OK(status)) - return WERR_GENERAL_FAILURE; + return NULL; static_init_registry; reg_first_init = False; -- cgit From 25ed82e7ee84a069661c3dd8b0f808049ee7fa88 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 23 May 2004 14:18:08 +0000 Subject: r834: Fix gconf and dir backends (This used to be commit fe5166ee88d401cdd493644af4876e803f546aef) --- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 9 +++++++ .../registry/reg_backend_gconf/reg_backend_gconf.c | 17 +++++++++++-- source4/lib/registry/tools/gregedit.c | 28 ++++++++++++---------- 3 files changed, 40 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index cb61864d0c..c7ed95d80f 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -127,6 +127,14 @@ static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *da return WERR_NOT_SUPPORTED; } +static WERROR reg_dir_get_hive(REG_HANDLE *h, int hive, REG_KEY **key) +{ + if(hive != 0) return WERR_NO_MORE_ITEMS; + *key = reg_key_new_abs("", h, NULL); + (*key)->backend_data = talloc_strdup((*key)->mem_ctx, h->location); + return WERR_OK; +} + static WERROR reg_dir_del_value(REG_VAL *v) { /* FIXME*/ @@ -137,6 +145,7 @@ static struct registry_ops reg_backend_dir = { .name = "dir", .open_registry = reg_dir_open, .open_key = reg_dir_open_key, + .get_hive = reg_dir_get_hive, .fetch_subkeys = reg_dir_fetch_subkeys, .add_key = reg_dir_add_key, .del_key = reg_dir_del_key, diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 8f9fd6625b..c705a2e3cb 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -41,10 +41,22 @@ static WERROR reg_close_gconf(REG_HANDLE *h) return WERR_OK; } -static WERROR gconf_open_key (REG_HANDLE *h, const char *name, REG_KEY **key) +static WERROR gconf_get_hive (REG_HANDLE *h, int hivenum, REG_KEY **key) +{ + if(hivenum != 0) return WERR_NO_MORE_ITEMS; + *key = reg_key_new_abs("", h, NULL); + (*key)->backend_data = talloc_strdup((*key)->mem_ctx, "/"); + return WERR_OK; +} + +static WERROR gconf_open_key (REG_HANDLE *h, int hivenum, const char *name, REG_KEY **key) { REG_KEY *ret; - char *fullpath = reg_path_win2unix(strdup(name)); + char *fullpath; + + if(hivenum != 0) return WERR_NO_MORE_ITEMS; + + fullpath = reg_path_win2unix(strdup(name)); /* Check if key exists */ if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { @@ -183,6 +195,7 @@ static struct registry_ops reg_backend_gconf = { .name = "gconf", .open_registry = reg_open_gconf, .close_registry = reg_close_gconf, + .get_hive = gconf_get_hive, .open_key = gconf_open_key, .fetch_subkeys = gconf_fetch_subkeys, .fetch_values = gconf_fetch_values, diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index 5b78292061..d878461bff 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -454,24 +454,40 @@ static GtkWidget* create_mainwin (void) open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file"); gtk_widget_show (open_nt4); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); + + g_signal_connect ((gpointer) open_nt4, "activate", + G_CALLBACK (on_open_file_activate), + "nt4"); } if(reg_has_backend("w95")) { open_w95 = gtk_image_menu_item_new_with_mnemonic("_Open Win9x file"); gtk_widget_show (open_w95); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); + + g_signal_connect ((gpointer) open_w95, "activate", + G_CALLBACK (on_open_file_activate), + "w95"); } if(reg_has_backend("gconf")) { open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); gtk_widget_show (open_gconf); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); + + g_signal_connect ((gpointer) open_gconf, "activate", + G_CALLBACK (on_open_gconf_activate), + NULL); } if(reg_has_backend("rpc")) { open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote"); gtk_widget_show (open_remote); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); + + g_signal_connect ((gpointer) open_remote, "activate", + G_CALLBACK (on_open_remote_activate), + NULL); } save = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group); @@ -605,18 +621,6 @@ static GtkWidget* create_mainwin (void) gtk_box_pack_start (GTK_BOX (vbox1), statusbar, FALSE, FALSE, 0); gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE); - g_signal_connect ((gpointer) open_nt4, "activate", - G_CALLBACK (on_open_file_activate), - "nt4"); - g_signal_connect ((gpointer) open_w95, "activate", - G_CALLBACK (on_open_file_activate), - "w95"); - g_signal_connect ((gpointer) open_gconf, "activate", - G_CALLBACK (on_open_gconf_activate), - NULL); - g_signal_connect ((gpointer) open_remote, "activate", - G_CALLBACK (on_open_remote_activate), - NULL); g_signal_connect ((gpointer) save, "activate", G_CALLBACK (on_save_activate), NULL); -- cgit From ea0717b2e2e03f79a10dd4f605ed85069a559dc8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 15:45:37 +0000 Subject: r845: convert SUBSYSTEM LIBBASIC to a .mk file metze (This used to be commit 81f50fbc95c8c81a18dc1e87a76c53657a24af7b) --- source4/lib/basic.m4 | 25 +------------------- source4/lib/basic.mk | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 source4/lib/basic.mk (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index b575bad9b8..b233c842db 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -1,26 +1,3 @@ dnl # LIB BASIC subsystem -SMB_SUBSYSTEM(LIBBASIC,[lib/version.o], - [lib/debug.o lib/fault.o - lib/getsmbpass.o lib/interface.o - lib/interfaces.o lib/pidfile.o lib/replace.o - lib/signal.o lib/system.o lib/sendfile.o lib/time.o - lib/genrand.o lib/username.o - lib/util_getent.o lib/util_pw.o lib/smbrun.o - lib/bitmap.o lib/snprintf.o lib/dprintf.o - lib/xfile.o lib/wins_srv.o - lib/util_str.o lib/util_sid.o lib/util_uuid.o - lib/util_unistr.o lib/util_file.o lib/data_blob.o - lib/util.o lib/util_sock.o - lib/talloc.o lib/substitute.o lib/fsusage.o - lib/ms_fnmatch.o lib/select.o lib/messages.o - lib/tallocmsg.o lib/dmallocmsg.o - lib/smbpasswd.o - nsswitch/wb_client.o nsswitch/wb_common.o - lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o - lib/gencache.o lib/module.o lib/mutex.o - lib/ldap_escape.o lib/events.o - lib/crypto/crc32.o lib/crypto/md5.o - lib/crypto/hmacmd5.o lib/crypto/md4.o - lib/tdb_helper.o],[], - [LIBTDB CHARSET]) +SMB_SUBSYSTEM_MK(LIBBASIC,lib/basic.mk) diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk new file mode 100644 index 0000000000..78acb5bb1c --- /dev/null +++ b/source4/lib/basic.mk @@ -0,0 +1,64 @@ +# LIB BASIC subsystem + +############################## +# Start SUBSYSTEM LIBBASIC +[SUBSYSTEM::LIBBASIC] +INIT_OBJ_FILES = lib/version.o +ADD_OBJ_FILES = \ + lib/debug.o \ + lib/fault.o \ + lib/getsmbpass.o \ + lib/interface.o \ + lib/interfaces.o \ + lib/pidfile.o \ + lib/replace.o \ + lib/signal.o \ + lib/system.o \ + lib/sendfile.o \ + lib/time.o \ + lib/genrand.o \ + lib/username.o \ + lib/util_getent.o \ + lib/util_pw.o \ + lib/smbrun.o \ + lib/bitmap.o \ + lib/snprintf.o \ + lib/dprintf.o \ + lib/xfile.o \ + lib/wins_srv.o \ + lib/util_str.o \ + lib/util_sid.o \ + lib/util_uuid.o \ + lib/util_unistr.o \ + lib/util_file.o \ + lib/data_blob.o \ + lib/util.o \ + lib/util_sock.o \ + lib/talloc.o \ + lib/substitute.o \ + lib/fsusage.o \ + lib/ms_fnmatch.o \ + lib/select.o \ + lib/messages.o \ + lib/tallocmsg.o \ + lib/dmallocmsg.o \ + lib/smbpasswd.o \ + nsswitch/wb_client.o \ + nsswitch/wb_common.o \ + lib/pam_errors.o \ + intl/lang_tdb.o \ + lib/account_pol.o \ + lib/gencache.o \ + lib/module.o \ + lib/mutex.o \ + lib/ldap_escape.o \ + lib/events.o \ + lib/crypto/crc32.o \ + lib/crypto/md5.o \ + lib/crypto/hmacmd5.o \ + lib/crypto/md4.o \ + lib/tdb_helper.o +REQUIRED_SUBSYSTEMS = \ + LIBTDB CHARSET +# End SUBSYSTEM LIBBASIC +############################## -- cgit From a3d61e0485c70ec5215c34b6caf40e2e6c6c5338 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 16:27:23 +0000 Subject: r848: convert lib/tdb into the same layout as lib/ldb metze (This used to be commit bacab322ce89979f0ad0811cd15b73d81eceb69d) --- source4/lib/tdb/README | 167 --- source4/lib/tdb/common/spinlock.c | 481 ++++++++ source4/lib/tdb/common/tdb.c | 2139 ++++++++++++++++++++++++++++++++++++ source4/lib/tdb/common/tdbutil.c | 718 ++++++++++++ source4/lib/tdb/config.mk | 6 +- source4/lib/tdb/docs/README | 167 +++ source4/lib/tdb/docs/tdb.magic | 10 + source4/lib/tdb/include/spinlock.h | 59 + source4/lib/tdb/include/tdb.h | 153 +++ source4/lib/tdb/include/tdbutil.h | 37 + source4/lib/tdb/spinlock.c | 481 -------- source4/lib/tdb/spinlock.h | 59 - source4/lib/tdb/tdb.c | 2139 ------------------------------------ source4/lib/tdb/tdb.h | 153 --- source4/lib/tdb/tdb.magic | 10 - source4/lib/tdb/tdbutil.c | 718 ------------ source4/lib/tdb/tdbutil.h | 37 - source4/lib/tdb/tools/Makefile | 29 + source4/lib/tdb/tools/tdbbackup.c | 149 +++ source4/lib/tdb/tools/tdbdump.c | 89 ++ source4/lib/tdb/tools/tdbtest.c | 263 +++++ source4/lib/tdb/tools/tdbtool.c | 547 +++++++++ source4/lib/tdb/tools/tdbtorture.c | 227 ++++ 23 files changed, 5071 insertions(+), 3767 deletions(-) delete mode 100644 source4/lib/tdb/README create mode 100644 source4/lib/tdb/common/spinlock.c create mode 100644 source4/lib/tdb/common/tdb.c create mode 100644 source4/lib/tdb/common/tdbutil.c create mode 100644 source4/lib/tdb/docs/README create mode 100644 source4/lib/tdb/docs/tdb.magic create mode 100644 source4/lib/tdb/include/spinlock.h create mode 100644 source4/lib/tdb/include/tdb.h create mode 100644 source4/lib/tdb/include/tdbutil.h delete mode 100644 source4/lib/tdb/spinlock.c delete mode 100644 source4/lib/tdb/spinlock.h delete mode 100644 source4/lib/tdb/tdb.c delete mode 100644 source4/lib/tdb/tdb.h delete mode 100644 source4/lib/tdb/tdb.magic delete mode 100644 source4/lib/tdb/tdbutil.c delete mode 100644 source4/lib/tdb/tdbutil.h create mode 100644 source4/lib/tdb/tools/Makefile create mode 100644 source4/lib/tdb/tools/tdbbackup.c create mode 100644 source4/lib/tdb/tools/tdbdump.c create mode 100644 source4/lib/tdb/tools/tdbtest.c create mode 100644 source4/lib/tdb/tools/tdbtool.c create mode 100644 source4/lib/tdb/tools/tdbtorture.c (limited to 'source4/lib') diff --git a/source4/lib/tdb/README b/source4/lib/tdb/README deleted file mode 100644 index fac3eacb4d..0000000000 --- a/source4/lib/tdb/README +++ /dev/null @@ -1,167 +0,0 @@ -tdb - a trivial database system -tridge@linuxcare.com December 1999 -================================== - -This is a simple database API. It was inspired by the realisation that -in Samba we have several ad-hoc bits of code that essentially -implement small databases for sharing structures between parts of -Samba. As I was about to add another I realised that a generic -database module was called for to replace all the ad-hoc bits. - -I based the interface on gdbm. I couldn't use gdbm as we need to be -able to have multiple writers to the databases at one time. - -Compilation ------------ - -add HAVE_MMAP=1 to use mmap instead of read/write -add TDB_DEBUG=1 for verbose debug info -add NOLOCK=1 to disable locking code - -Testing -------- - -Compile tdbtest.c and link with gdbm for testing. tdbtest will perform -identical operations via tdb and gdbm then make sure the result is the -same - -Also included is tdbtool, which allows simple database manipulation -on the commandline. - -tdbtest and tdbtool are not built as part of Samba, but are included -for completeness. - -Interface ---------- - -The interface is very similar to gdbm except for the following: - -- different open interface. The tdb_open call is more similar to a - traditional open() -- no tdbm_reorganise() function -- no tdbm_sync() function. No operations are cached in the library anyway -- added a tdb_traverse() function for traversing the whole database - -A general rule for using tdb is that the caller frees any returned -TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA -return value called p. This is the same as gdbm. - -here is a full list of tdb functions with brief descriptions. - - ----------------------------------------------------------------------- -TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) - - open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the database - file. A flags value of O_WRONLY is invalid - - The hash size is advisory, use zero for a default value. - - return is NULL on error - - possible tdb_flags are: - TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open - TDB_INTERNAL - don't use a file, instaed store the data in - memory. The filename is ignored in this case. - TDB_NOLOCK - don't do any locking - TDB_NOMMAP - don't use mmap - ----------------------------------------------------------------------- -char *tdb_error(TDB_CONTEXT *tdb); - - return a error string for the last tdb error - ----------------------------------------------------------------------- -int tdb_close(TDB_CONTEXT *tdb); - - close a database - ----------------------------------------------------------------------- -int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf); - - update an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1 - ----------------------------------------------------------------------- -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); - - fetch an entry in the database given a key - if the return value has a null dptr then a error occurred - - caller must free the resulting data - ----------------------------------------------------------------------- -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); - - check if an entry in the database exists - - note that 1 is returned if the key is found and 0 is returned if not found - this doesn't match the conventions in the rest of this module, but is - compatible with gdbm - ----------------------------------------------------------------------- -int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, - TDB_DATA key, TDB_DATA dbuf, void *state), void *state); - - traverse the entire database - calling fn(tdb, key, data, state) on each - element. - - return -1 on error or the record count traversed - - if fn is NULL then it is not called - - a non-zero return value from fn() indicates that the traversal should stop - ----------------------------------------------------------------------- -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); - - find the first entry in the database and return its key - - the caller must free the returned data - ----------------------------------------------------------------------- -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); - - find the next entry in the database, returning its key - - the caller must free the returned data - ----------------------------------------------------------------------- -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); - - delete an entry in the database given a key - ----------------------------------------------------------------------- -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); - - store an element in the database, replacing any existing element - with the same key - - If flag==TDB_INSERT then don't overwrite an existing entry - If flag==TDB_MODIFY then don't create a new entry - - return 0 on success, -1 on failure - ----------------------------------------------------------------------- -int tdb_writelock(TDB_CONTEXT *tdb); - - lock the database. If we already have it locked then don't do anything - ----------------------------------------------------------------------- -int tdb_writeunlock(TDB_CONTEXT *tdb); - unlock the database - ----------------------------------------------------------------------- -int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key); - - lock one hash chain. This is meant to be used to reduce locking - contention - it cannot guarantee how many records will be locked - ----------------------------------------------------------------------- -int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key); - - unlock one hash chain diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c new file mode 100644 index 0000000000..1b789d4daa --- /dev/null +++ b/source4/lib/tdb/common/spinlock.c @@ -0,0 +1,481 @@ +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Anton Blanchard 2001 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#if HAVE_CONFIG_H +#include +#endif + +#if STANDALONE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" +#include "spinlock.h" + +#define DEBUG +#else +#include "includes.h" +#endif + +#ifdef USE_SPINLOCKS + +/* + * ARCH SPECIFIC + */ + +#if defined(SPARC_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int result; + + asm volatile("ldstub [%1], %0" + : "=r" (result) + : "r" (lock) + : "memory"); + + return (result == 0) ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#elif defined(POWERPC_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int result; + + __asm__ __volatile__( +"1: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + li %0,0\n\ + bne- 2f\n\ + li %0,1\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r"(result) + : "r"(lock) + : "cr0", "memory"); + + return (result == 1) ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("eieio":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#elif defined(INTEL_SPINLOCKS) + +static inline int __spin_trylock(spinlock_t *lock) +{ + int oldval; + + asm volatile("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0) + : "memory"); + + return oldval > 0 ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 1; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 1; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 1); +} + +#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730) + +/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See + * sync(3) for the details of the intrinsic operations. + * + * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. + */ + +#if defined(STANDALONE) + +/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ +#define inline __inline + +#endif /* STANDALONE */ + +/* Returns 0 if the lock is acquired, EBUSY otherwise. */ +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int val; + val = __lock_test_and_set(lock, 1); + return val == 0 ? 0 : EBUSY; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + __lock_release(lock); +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + __lock_release(lock); +} + +/* Returns 1 if the lock is held, 0 otherwise. */ +static inline int __spin_is_locked(spinlock_t *lock) +{ + unsigned int val; + val = __add_and_fetch(lock, 0); + return val; +} + +#elif defined(MIPS_SPINLOCKS) + +static inline unsigned int load_linked(unsigned long addr) +{ + unsigned int res; + + __asm__ __volatile__("ll\t%0,(%1)" + : "=r" (res) + : "r" (addr)); + + return res; +} + +static inline unsigned int store_conditional(unsigned long addr, unsigned int value) +{ + unsigned int res; + + __asm__ __volatile__("sc\t%0,(%2)" + : "=r" (res) + : "0" (value), "r" (addr)); + return res; +} + +static inline int __spin_trylock(spinlock_t *lock) +{ + unsigned int mw; + + do { + mw = load_linked(lock); + if (mw) + return EBUSY; + } while (!store_conditional(lock, 1)); + + asm volatile("":::"memory"); + + return 0; +} + +static inline void __spin_unlock(spinlock_t *lock) +{ + asm volatile("":::"memory"); + *lock = 0; +} + +static inline void __spin_lock_init(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int __spin_is_locked(spinlock_t *lock) +{ + return (*lock != 0); +} + +#else +#error Need to implement spinlock code in spinlock.c +#endif + +/* + * OS SPECIFIC + */ + +static void yield_cpu(void) +{ + struct timespec tm; + +#ifdef USE_SCHED_YIELD + sched_yield(); +#else + /* Linux will busy loop for delays < 2ms on real time tasks */ + tm.tv_sec = 0; + tm.tv_nsec = 2000000L + 1; + nanosleep(&tm, NULL); +#endif +} + +static int this_is_smp(void) +{ +#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN) + return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0; +#else + return 0; +#endif +} + +/* + * GENERIC + */ + +static int smp_machine = 0; + +static inline void __spin_lock(spinlock_t *lock) +{ + int ntries = 0; + + while(__spin_trylock(lock)) { + while(__spin_is_locked(lock)) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __read_lock(tdb_rwlock_t *rwlock) +{ + int ntries = 0; + + while(1) { + __spin_lock(&rwlock->lock); + + if (!(rwlock->count & RWLOCK_BIAS)) { + rwlock->count++; + __spin_unlock(&rwlock->lock); + return; + } + + __spin_unlock(&rwlock->lock); + + while(rwlock->count & RWLOCK_BIAS) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __write_lock(tdb_rwlock_t *rwlock) +{ + int ntries = 0; + + while(1) { + __spin_lock(&rwlock->lock); + + if (rwlock->count == 0) { + rwlock->count |= RWLOCK_BIAS; + __spin_unlock(&rwlock->lock); + return; + } + + __spin_unlock(&rwlock->lock); + + while(rwlock->count != 0) { + if (smp_machine && ntries++ < MAX_BUSY_LOOPS) + continue; + yield_cpu(); + } + } +} + +static void __write_unlock(tdb_rwlock_t *rwlock) +{ + __spin_lock(&rwlock->lock); + +#ifdef DEBUG + if (!(rwlock->count & RWLOCK_BIAS)) + fprintf(stderr, "bug: write_unlock\n"); +#endif + + rwlock->count &= ~RWLOCK_BIAS; + __spin_unlock(&rwlock->lock); +} + +static void __read_unlock(tdb_rwlock_t *rwlock) +{ + __spin_lock(&rwlock->lock); + +#ifdef DEBUG + if (!rwlock->count) + fprintf(stderr, "bug: read_unlock\n"); + + if (rwlock->count & RWLOCK_BIAS) + fprintf(stderr, "bug: read_unlock\n"); +#endif + + rwlock->count--; + __spin_unlock(&rwlock->lock); +} + +/* TDB SPECIFIC */ + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) +{ + tdb_rwlock_t *rwlocks; + + if (!tdb->map_ptr) return -1; + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + + switch(rw_type) { + case F_RDLCK: + __read_lock(&rwlocks[list+1]); + break; + + case F_WRLCK: + __write_lock(&rwlocks[list+1]); + break; + + default: + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + +/* unlock the database. */ +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) +{ + tdb_rwlock_t *rwlocks; + + if (!tdb->map_ptr) return -1; + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + + switch(rw_type) { + case F_RDLCK: + __read_unlock(&rwlocks[list+1]); + break; + + case F_WRLCK: + __write_unlock(&rwlocks[list+1]); + break; + + default: + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + + return 0; +} + +int tdb_create_rwlocks(int fd, unsigned int hash_size) +{ + unsigned size, i; + tdb_rwlock_t *rwlocks; + + size = TDB_SPINLOCK_SIZE(hash_size); + rwlocks = malloc(size); + if (!rwlocks) + return -1; + + for(i = 0; i < hash_size+1; i++) { + __spin_lock_init(&rwlocks[i].lock); + rwlocks[i].count = 0; + } + + /* Write it out (appending to end) */ + if (write(fd, rwlocks, size) != size) { + free(rwlocks); + return -1; + } + smp_machine = this_is_smp(); + free(rwlocks); + return 0; +} + +int tdb_clear_spinlocks(TDB_CONTEXT *tdb) +{ + tdb_rwlock_t *rwlocks; + unsigned i; + + if (tdb->header.rwlocks == 0) return 0; + if (!tdb->map_ptr) return -1; + + /* We're mmapped here */ + rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); + for(i = 0; i < tdb->header.hash_size+1; i++) { + __spin_lock_init(&rwlocks[i].lock); + rwlocks[i].count = 0; + } + return 0; +} +#else +int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } + +/* Non-spinlock version: remove spinlock pointer */ +int tdb_clear_spinlocks(TDB_CONTEXT *tdb) +{ + tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks + - (char *)&tdb->header); + + tdb->header.rwlocks = 0; + if (lseek(tdb->fd, off, SEEK_SET) != off + || write(tdb->fd, (void *)&tdb->header.rwlocks, + sizeof(tdb->header.rwlocks)) + != sizeof(tdb->header.rwlocks)) + return -1; + return 0; +} +#endif diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c new file mode 100644 index 0000000000..c8ac7babad --- /dev/null +++ b/source4/lib/tdb/common/tdb.c @@ -0,0 +1,2139 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* NOTE: If you use tdbs under valgrind, and in particular if you run + * tdbtorture, you may get spurious "uninitialized value" warnings. I + * think this is because valgrind doesn't understand that the mmap'd + * area may be written to by other processes. Memory can, from the + * point of view of the grinded process, spontaneously become + * initialized. + * + * I can think of a few solutions. [mbp 20030311] + * + * 1 - Write suppressions for Valgrind so that it doesn't complain + * about this. Probably the most reasonable but people need to + * remember to use them. + * + * 2 - Use IO not mmap when running under valgrind. Not so nice. + * + * 3 - Use the special valgrind macros to mark memory as valid at the + * right time. Probably too hard -- the process just doesn't know. + */ + +#ifdef STANDALONE +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" +#include "spinlock.h" +#else +#include "includes.h" +#endif + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_ALIGNMENT 4 +#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) +#define DEFAULT_HASH_SIZE 131 +#define TDB_PAGE_SIZE 0x2000 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) +#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) + + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) +TDB_DATA tdb_null; + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static TDB_CONTEXT *tdbs = NULL; + +static int tdb_munmap(TDB_CONTEXT *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +static void tdb_mmap(TDB_CONTEXT *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +static void *convert(void *buf, u32 size) +{ + u32 i, *p = buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) + +/* the body of the database is made of one list_struct for the free space + plus a separate data list for each hash value */ +struct list_struct { + tdb_off next; /* offset of the next record in the list */ + tdb_len rec_len; /* total byte length of record */ + tdb_len key_len; /* byte length of key */ + tdb_len data_len; /* byte length of data */ + u32 full_hash; /* the full 32 bit hash of the key */ + u32 magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + u32 totalsize; (tailer) + } + */ +}; + +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ +static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, + int rw_type, int lck_type, int probe) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) + return 0; + if ((rw_type == F_WRLCK) && (tdb->read_only)) { + errno = EACCES; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = 1; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) + break; + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + if (errno == EINTR && palarm_fired && *palarm_fired) + tdb->ecode = TDB_ERR_LOCK_TIMEOUT; + else + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); + } + /* Was it an alarm timeout ? */ + if (errno == EINTR && palarm_fired && *palarm_fired) { + TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); + return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); + } + /* Otherwise - generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (errno != EAGAIN) { + TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", + tdb->fd, offset, rw_type, lck_type, + strerror(errno))); + } + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + +/* lock a list in the database. list -1 is the alloc list */ +static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) +{ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (tdb->locked[list+1].count == 0) { + if (!tdb->read_only && tdb->header.rwlocks) { + if (tdb_spinlock(tdb, list, ltype)) { + TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n", + list, ltype)); + return -1; + } + } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { + TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", + list, ltype, strerror(errno))); + return -1; + } + tdb->locked[list+1].ltype = ltype; + } + tdb->locked[list+1].count++; + return 0; +} + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) +{ + int ret = -1; + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + if (tdb->locked[list+1].count==0) { + TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); + return ret; + } + + if (tdb->locked[list+1].count == 1) { + /* Down to last nested lock: unlock underneath */ + if (!tdb->read_only && tdb->header.rwlocks) { + ret = tdb_spinunlock(tdb, list, ltype); + } else { + ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + } + } else { + ret = 0; + } + tdb->locked[list+1].count--; + + if (ret) + TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + +/* This is based on the hash algorithm from gdbm */ +static u32 tdb_hash(TDB_DATA *key) +{ + u32 value; /* Used to compute the hash value. */ + u32 i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (fstat(tdb->fd, &st) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + + if (st.st_size < (size_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) +{ + if (tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) + memcpy(off + (char *)tdb->map_ptr, buf, len); +#ifdef HAVE_PWRITE + else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { +#else + else if (lseek(tdb->fd, off, SEEK_SET) != off + || write(tdb->fd, buf, len) != (ssize_t)len) { +#endif + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + return 0; +} + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) +{ + if (tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) + memcpy(buf, off + (char *)tdb->map_ptr, len); +#ifdef HAVE_PREAD + else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { +#else + else if (lseek(tdb->fd, off, SEEK_SET) != off + || read(tdb->fd, buf, len) != (ssize_t)len) { +#endif + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + if (cv) + convert(buf, len); + return 0; +} + +/* read a lump of data, allocating the space for it */ +static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) +{ + char *buf; + + if (!(buf = malloc(len))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_OOM, buf); + } + if (tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* read/write a tdb_off */ +static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) +{ + return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} +static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) +{ + tdb_off off = *d; + return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + +/* read/write a record */ +static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + return tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} +static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + struct list_struct r = *rec; + return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +/* read a freelist record and check for simple errors */ +static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) +{ + if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, 0,"rec_free_read non-free magic at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, + const struct list_struct *rec) +{ + tdb_off totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), + &totalsize); +} + +static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) +{ + struct list_struct rec; + tdb_off tailer_ofs, tailer; + + if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); + if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) +{ + tdb_off rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(TDB_CONTEXT *tdb) +{ + int i; + for (i=0;iheader.hash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(TDB_CONTEXT *tdb) +{ + int ret; + long total_free = 0; + tdb_off offset, rec_ptr; + struct list_struct rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) +{ + tdb_off last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); +} + +/* Add an element into the freelist. Merge adjacent records if + neccessary. */ +static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) +{ + tdb_off right, left; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); + goto fail; + } + + /* Look right first (I'm an Australian, dammit) */ + right = offset + sizeof(*rec) + rec->rec_len; + if (right + sizeof(*rec) <= tdb->map_size) { + struct list_struct r; + + if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + } + } + +left: + /* Look left */ + left = offset - sizeof(tdb_off); + if (left > TDB_DATA_START(tdb->header.hash_size)) { + struct list_struct l; + tdb_off leftsize; + + /* Read in tailer and jump back to header */ + if (ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + left = offset - leftsize; + + /* Now read in record */ + if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, left, l.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); + goto update; + } else { + offset = left; + rec->rec_len += leftsize; + } + } + } + +update: + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + rec_write(tdb, offset, rec) == -1 || + ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) +{ + char buf[1024]; +#if HAVE_FTRUNCATE_EXTEND + if (ftruncate(tdb->fd, size+addition) != 0) { + TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } +#else + char b = 0; + +#ifdef HAVE_PWRITE + if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { +#else + if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || + write(tdb->fd, &b, 1) != 1) { +#endif + TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } +#endif + + /* now fill the file with something. This ensures that the file isn't sparse, which would be + very bad if we ran out of disk. This must be done with write, not via mmap */ + memset(buf, 0x42, sizeof(buf)); + while (addition) { + int n = addition>sizeof(buf)?sizeof(buf):addition; +#ifdef HAVE_PWRITE + int ret = pwrite(tdb->fd, buf, n, size); +#else + int ret; + if (lseek(tdb->fd, size, SEEK_SET) != size) + return -1; + ret = write(tdb->fd, buf, n); +#endif + if (ret != n) { + TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", + n, strerror(errno))); + return -1; + } + addition -= n; + size += n; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) +{ + struct list_struct rec; + tdb_off offset; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 10 more records, and round + the database up to a multiple of TDB_PAGE_SIZE */ + size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) + tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size); + else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + */ +static tdb_off tdb_allocate_ofs(TDB_CONTEXT *tdb, tdb_len length, tdb_off rec_ptr, + struct list_struct *rec, tdb_off last_ptr) +{ + struct list_struct newrec; + tdb_off newrec_ptr; + + memset(&newrec, '\0', sizeof(newrec)); + + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else { + newrec_ptr = 0; + } + + /* Remove allocated record from the free list */ + if (ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { + return 0; + } + } + + /* all done - return the new record offset */ + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected list_struct within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, + struct list_struct *rec) +{ + tdb_off rec_ptr, last_ptr, newrec_ptr; + struct { + tdb_off rec_ptr, last_ptr; + tdb_len rec_len; + } bestfit; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + bestfit.rec_ptr = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + if (rec_free_read(tdb, rec_ptr, rec) == -1) { + goto fail; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + /* consider a fit to be good enough if we aren't wasting more than half the space */ + if (bestfit.rec_len < 2*length) { + break; + } + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + } + + if (bestfit.rec_ptr != 0) { + if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) +{ + struct tdb_header *newdb; + int size, ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); + if (!(newdb = calloc(size, 1))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; +#ifdef USE_SPINLOCKS + newdb->rwlocks = size; +#endif + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + if (write(tdb->fd, newdb, size) != size) + ret = -1; + else + ret = tdb_create_rwlocks(tdb->fd, hash_size); + + fail: + SAFE_FREE(newdb); + return ret; +} + +/* Returns 0 on fail. On success, return offset of record, and fills + in rec */ +static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, + struct list_struct *r) +{ + tdb_off rec_ptr; + + /* read in the hash top */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { + char *k; + /* a very likely hit - read the key */ + k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), + r->key_len); + if (!k) + return 0; + + if (memcmp(key.dptr, k, key.dsize) == 0) { + SAFE_FREE(k); + return rec_ptr; + } + SAFE_FREE(k); + } + rec_ptr = r->next; + } + return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); +} + +/* If they do lockkeys, check that this hash is one they locked */ +static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) +{ + u32 i; + if (!tdb->lockedkeys) + return 1; + for (i = 0; i < tdb->lockedkeys[0]; i++) + if (tdb->lockedkeys[i+1] == hash) + return 1; + return TDB_ERRCODE(TDB_ERR_NOLOCK, 0); +} + +/* As tdb_find, but if you succeed, keep the lock */ +static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec) +{ + u32 rec_ptr; + + if (!tdb_keylocked(tdb, hash)) + return 0; + if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) + return 0; + if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) + tdb_unlock(tdb, BUCKET(hash), locktype); + return rec_ptr; +} + +enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_NOEXIST, "Record does not exist"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(TDB_CONTEXT *tdb) +{ + u32 i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + +/* update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. +*/ + +static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) +{ + struct list_struct rec; + tdb_off rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) + return -1; + + /* must be long enough key, data and tailer */ + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + dbuf.dptr, dbuf.dsize) == -1) + return -1; + + if (dbuf.dsize != rec.data_len) { + /* update size */ + rec.data_len = dbuf.dsize; + return rec_write(tdb, rec_ptr, &rec); + } + + return 0; +} + +/* find an entry in the database given a key */ +/* If an entry doesn't exist tdb_err will be set to + * TDB_ERR_NOEXIST. If a key has no data attached + * tdb_err will not be set. Both will return a + * zero pptr and zero dsize. + */ + +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) +{ + tdb_off rec_ptr; + struct list_struct rec; + TDB_DATA ret; + u32 hash; + + /* find which hash bucket it is in */ + hash = tdb_hash(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) + return tdb_null; + + if (rec.data_len) + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); + else + ret.dptr = NULL; + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; +} + +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +{ + struct list_struct rec; + + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; +} + +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_exists_hash(tdb, key, hash); +} + +/* record lock stops delete underneath */ +static int lock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; +} +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ + +static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ + +static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); +} +/* fcntl locks don't stack: avoid unlocking someone else's */ +static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) +{ + struct tdb_traverse_lock *i; + u32 count = 0; + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); +} + +/* actually delete an entry in the database given the offset */ +static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) +{ + tdb_off last_ptr, i; + struct list_struct lastrec; + + if (tdb->read_only) return -1; + + if (write_lock_record(tdb, rec_ptr) == -1) { + /* Someone traversing here: mark it as dead */ + rec->magic = TDB_DEAD_MAGIC; + return rec_write(tdb, rec_ptr, rec); + } + if (write_unlock_record(tdb, rec_ptr) != 0) + return -1; + + /* find previous record in hash chain */ + if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + return -1; + for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) + if (rec_read(tdb, i, &lastrec) == -1) + return -1; + + /* unlink it: next ptr is at start of record. */ + if (last_ptr == 0) + last_ptr = TDB_HASH_TOP(rec->full_hash); + if (ofs_write(tdb, last_ptr, &rec->next) == -1) + return -1; + + /* recover the space */ + if (tdb_free(tdb, rec_ptr, rec) == -1) + return -1; + return 0; +} + +/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ +static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, + struct list_struct *rec) +{ + int want_next = (tlock->off != 0); + + /* No traversal allows if you've called tdb_lockkeys() */ + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) + return -1; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off current; + if (rec_read(tdb, tlock->off, rec) == -1) + goto fail; + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (!tdb->read_only && + do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, F_WRLCK); + want_next = 0; + } + /* We finished iteration without finding anything */ + return TDB_ERRCODE(TDB_SUCCESS, 0); + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); + return -1; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private) +{ + TDB_DATA key, dbuf; + struct list_struct rec; + struct tdb_traverse_lock tl = { NULL, 0, 0 }; + int ret, count = 0; + + /* This was in the initializaton, above, but the IRIX compiler + * did not like it. crh + */ + tl.next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = &tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) + goto out; + if (unlock_record(tdb, tl.off) != 0) + TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { + ret = -1; + goto out; + } + if (fn && fn(tdb, key, dbuf, private)) { + /* They want us to terminate traversal */ + ret = count; + if (unlock_record(tdb, tl.off) != 0) { + TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + tdb->travlocks.next = tl.next; + SAFE_FREE(key.dptr); + return count; + } + SAFE_FREE(key.dptr); + } +out: + tdb->travlocks.next = tl.next; + if (ret < 0) + return -1; + else + return count; +} + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) +{ + TDB_DATA key; + struct list_struct rec; + + /* release any old lock */ + if (unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) + return tdb_null; + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) +{ + u32 oldhash; + TDB_DATA key = tdb_null; + struct list_struct rec; + char *k = NULL; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) + return tdb_null; + if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + return tdb_null; + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec); + if (!tdb->travlocks.off) + return tdb_null; + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + return key; +} + +/* delete an entry in the database given a key */ +static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +{ + tdb_off rec_ptr; + struct list_struct rec; + int ret; + + if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) + return -1; + ret = do_delete(tdb, rec_ptr, &rec); + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); + return ret; +} + +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_delete_hash(tdb, key, hash); +} + +/* store an element in the database, replacing any existing element + with the same key + + return 0 on success, -1 on failure +*/ +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +{ + struct list_struct rec; + u32 hash; + tdb_off rec_ptr; + char *p = NULL; + int ret = 0; + + /* find which hash bucket it is in */ + hash = tdb_hash(&key); + if (!tdb_keylocked(tdb, hash)) + return -1; + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + /* check for it existing, on insert. */ + if (flag == TDB_INSERT) { + if (tdb_exists_hash(tdb, key, hash)) { + tdb->ecode = TDB_ERR_EXISTS; + goto fail; + } + } else { + /* first try in-place update, on modify or replace. */ + if (tdb_update_hash(tdb, key, hash, dbuf) == 0) + goto out; + if (tdb->ecode == TDB_ERR_NOEXIST && + flag == TDB_MODIFY) { + /* if the record doesn't exist and we are in TDB_MODIFY mode then + we should fail the store */ + goto fail; + } + } + /* reset the error code potentially set by the tdb_update() */ + tdb->ecode = TDB_SUCCESS; + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + if (flag != TDB_INSERT) + tdb_delete_hash(tdb, key, hash); + + /* Copy key+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + memcpy(p, key.dptr, key.dsize); + if (dbuf.dsize) + memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); + + /* we have to allocate some space */ + if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec))) + goto fail; + + /* Read hash top into next ptr */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (rec_write(tdb, rec_ptr, &rec) == -1 + || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + out: + SAFE_FREE(p); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; +fail: + ret = -1; + goto out; +} + +/* Attempt to append data to an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. Record must be locked before calling. +*/ +static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) +{ + struct list_struct rec; + tdb_off rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) + return -1; + + /* Append of 0 is always ok. */ + if (new_dbuf.dsize == 0) + return 0; + + /* must be long enough for key, old data + new data and tailer */ + if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { + /* No room. */ + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, + new_dbuf.dptr, new_dbuf.dsize) == -1) + return -1; + + /* update size */ + rec.data_len += new_dbuf.dsize; + return rec_write(tdb, rec_ptr, &rec); +} + +/* Append to an entry. Create if not exist. */ + +int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +{ + struct list_struct rec; + u32 hash; + tdb_off rec_ptr; + char *p = NULL; + int ret = 0; + size_t new_data_size = 0; + + /* find which hash bucket it is in */ + hash = tdb_hash(&key); + if (!tdb_keylocked(tdb, hash)) + return -1; + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + /* first try in-place. */ + if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) + goto out; + + /* reset the error code potentially set by the tdb_append_inplace() */ + tdb->ecode = TDB_SUCCESS; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { + if (tdb->ecode != TDB_ERR_NOEXIST) + goto fail; + + /* Not found - create. */ + + ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); + goto out; + } + + new_data_size = rec.data_len + new_dbuf.dsize; + + /* Copy key+old_value+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + new_data_size))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + /* Copy the key in place. */ + memcpy(p, key.dptr, key.dsize); + + /* Now read the old data into place. */ + if (rec.data_len && + tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) + goto fail; + + /* Finally append the new data. */ + if (new_dbuf.dsize) + memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + + tdb_delete_hash(tdb, key, hash); + + if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) + goto fail; + + /* Read hash top into next ptr */ + if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = new_data_size; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (rec_write(tdb, rec_ptr, &rec) == -1 + || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 + || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + + out: + SAFE_FREE(p); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; + +fail: + ret = -1; + goto out; +} + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + TDB_CONTEXT *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL); +} + + +TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn) +{ + TDB_CONTEXT *tdb; + struct stat st; + int rev = 0, locked = 0; + unsigned char *vp; + u32 vertest; + + if (!(tdb = calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb->fd = -1; + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->lockedkeys = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + tdb->log_fn = log_fn; + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* ensure there is only one process initialising at once */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 + || (tdb->header.version != TDB_VERSION + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { + /* its not a valid database - possibly initialise it */ + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } + vp = (unsigned char *)&tdb->header.version; + vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | + (((u32)vp[2]) << 8) | (u32)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, st.st_dev, st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); + if (!tdb->locked) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "failed to allocate lock structure for %s\n", + name)); + errno = ENOMEM; + goto fail; + } + tdb_mmap(tdb); + if (locked) { + if (!tdb->read_only) + if (tdb_clear_spinlocks(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to clear spinlock\n")); + goto fail; + } + if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + /* leave this lock in place to indicate it's in use */ + if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) + goto fail; + } + + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(TDB_CONTEXT *tdb) +{ + TDB_CONTEXT **i; + int ret = 0; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + ret = close(tdb->fd); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb->lockedkeys); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* lock/unlock entire database */ +int tdb_lockall(TDB_CONTEXT *tdb) +{ + u32 i; + + /* There are no locks on read-only dbs */ + if (tdb->read_only) + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + for (i = 0; i < tdb->header.hash_size; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < tdb->header.hash_size) { + u32 j; + + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + + return 0; +} +void tdb_unlockall(TDB_CONTEXT *tdb) +{ + u32 i; + for (i=0; i < tdb->header.hash_size; i++) + tdb_unlock(tdb, i, F_WRLCK); +} + +int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) +{ + u32 i, j, hash; + + /* Can't lock more keys if already locked */ + if (tdb->lockedkeys) + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + if (!(tdb->lockedkeys = malloc(sizeof(u32) * (number+1)))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + /* First number in array is # keys */ + tdb->lockedkeys[0] = number; + + /* Insertion sort by bucket */ + for (i = 0; i < number; i++) { + hash = tdb_hash(&keys[i]); + for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++); + memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j)); + tdb->lockedkeys[j+1] = hash; + } + /* Finally, lock in order */ + for (i = 0; i < number; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < number) { + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + SAFE_FREE(tdb->lockedkeys); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + return 0; +} + +/* Unlock the keys previously locked by tdb_lockkeys() */ +void tdb_unlockkeys(TDB_CONTEXT *tdb) +{ + u32 i; + if (!tdb->lockedkeys) + return; + for (i = 0; i < tdb->lockedkeys[0]; i++) + tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK); + SAFE_FREE(tdb->lockedkeys); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); +} + +int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); +} + +int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); +} + + +/* register a loging function */ +void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) +{ + tdb->log_fn = fn; +} + + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(TDB_CONTEXT *tdb) +{ + struct stat st; + + if (tdb->flags & TDB_INTERNAL) + return 0; /* Nothing to do. */ + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { + TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(void) +{ + TDB_CONTEXT *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + /* Ensure no clear-if-first. */ + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_reopen(tdb) != 0) + return -1; + } + + return 0; +} diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c new file mode 100644 index 0000000000..62841ddfc2 --- /dev/null +++ b/source4/lib/tdb/common/tdbutil.c @@ -0,0 +1,718 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1992-1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +static sig_atomic_t gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + + +/******************************************************************* + THIS is a copy of the function CatchSignal found in lib/signal.c + I need to copy it there to avoid sucking all of the samba source + into tdb. + + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +********************************************************************/ + +static void (*TdbCatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + + + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = dptr; + ret.dsize = dsize; + return ret; +} + +/**************************************************************************** + Lock a chain with timeout (in seconds). +****************************************************************************/ + +static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +{ + /* Allow tdb_chainlock to be interrupted by an alarm. */ + int ret; + gotalarm = 0; + tdb_set_lock_alarm(&gotalarm); + + if (timeout) { + TdbCatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + if (rw_type == F_RDLCK) + ret = tdb_chainlock_read(tdb, key); + else + ret = tdb_chainlock(tdb, key); + + if (timeout) { + alarm(0); + TdbCatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) { + tdb_debug(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb->name ); + /* TODO: If we time out waiting for a lock, it might + * be nice to use F_GETLK to get the pid of the + * process currently holding the lock and print that + * as part of the debugging message. -- mbp */ + return -1; + } + } + + return ret; +} + +/**************************************************************************** + Write lock a chain. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +{ + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return -1 if timeout or lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32 value by a arbitrary blob key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + int32 ret; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(int32)) { + SAFE_FREE(data.dptr); + return -1; + } + + ret = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return ret; +} + +/**************************************************************************** + Fetch a int32 value by string key, return -1 if not found. + Output is int32 in native byte order. +****************************************************************************/ + +int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); +} + +/**************************************************************************** + Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + int32 v_store; + + SIVAL(&v_store,0,v); + data.dptr = (void *)&v_store; + data.dsize = sizeof(int32); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32 value by string key, return 0 on success, -1 on failure. + Input is int32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) +{ + return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); +} + +/**************************************************************************** + Fetch a uint32 value by a arbitrary blob key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(uint32)) { + SAFE_FREE(data.dptr); + return False; + } + + *value = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return True; +} + +/**************************************************************************** + Fetch a uint32 value by string key, return -1 if not found. + Output is uint32 in native byte order. +****************************************************************************/ + +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +{ + return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} + +/**************************************************************************** + Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + uint32 v_store; + BOOL ret = True; + + SIVAL(&v_store, 0, value); + data.dptr = (void *)&v_store; + data.dsize = sizeof(uint32); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) + ret = False; + + return ret; +} + +/**************************************************************************** + Store a uint32 value by string key, return 0 on success, -1 on failure. + Input is uint32 in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +{ + return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -1 + on failure. +****************************************************************************/ + +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) +{ + int32 val; + int32 ret = -1; + + if (tdb_lock_bystring(tdb, keystr,0) == -1) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) == -1) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +{ + uint32 val; + BOOL ret = False; + + if (tdb_lock_bystring(tdb, keystr,0) == -1) + return False; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = True; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8 bt; + uint16 w; + uint32 d; + int i; + void *p; + int len; + char *s; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c = *fmt++)) { + case 'b': /* unsigned 8-bit integer */ + len = 1; + bt = (uint8)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, bt); + break; + case 'w': /* unsigned 16-bit integer */ + len = 2; + w = (uint16)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, w); + break; + case 'd': /* signed 32-bit integer (standard int in most systems) */ + len = 4; + d = va_arg(ap, uint32); + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'p': /* pointer */ + len = 4; + p = va_arg(ap, void *); + d = p?1:0; + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'P': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'f': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'B': /* fixed-length string */ + i = va_arg(ap, int); + s = va_arg(ap, char *); + len = 4+i; + if (bufsize && bufsize >= len) { + SIVAL(buf, 0, i); + memcpy(buf+4, s, i); + } + break; + default: + tdb_debug(tdb, 0,"Unknown tdb_pack format %c in %s\n", + c, fmt); + len = 0; + break; + } + + buf += len; + if (bufsize) + bufsize -= len; + if (bufsize < 0) + bufsize = 0; + } + + va_end(ap); + + tdb_debug(tdb, 18,"tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + + return PTR_DIFF(buf, buf0); +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8 *bt; + uint16 *w; + uint32 *d; + int len; + int *i; + void **p; + char *s, **b; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + + va_start(ap, fmt); + + while (*fmt) { + switch ((c=*fmt++)) { + case 'b': + len = 1; + bt = va_arg(ap, uint8 *); + if (bufsize < len) + goto no_space; + *bt = SVAL(buf, 0); + break; + case 'w': + len = 2; + w = va_arg(ap, uint16 *); + if (bufsize < len) + goto no_space; + *w = SVAL(buf, 0); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32 *); + if (bufsize < len) + goto no_space; + *d = IVAL(buf, 0); + break; + case 'p': + len = 4; + p = va_arg(ap, void **); + if (bufsize < len) + goto no_space; + *p = (void *)IVAL(buf, 0); + break; + case 'P': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(pstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'f': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(fstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'B': + i = va_arg(ap, int *); + b = va_arg(ap, char **); + len = 4; + if (bufsize < len) + goto no_space; + *i = IVAL(buf, 0); + if (! *i) { + *b = NULL; + break; + } + len += *i; + if (bufsize < len) + goto no_space; + *b = (char *)malloc(*i); + if (! *b) + goto no_space; + memcpy(*b, buf+4, *i); + break; + default: + tdb_debug(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + c, fmt); + + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + tdb_debug(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + + return PTR_DIFF(buf, buf0); + + no_space: + return -1; +} + +/**************************************************************************** + Print out debug messages. +****************************************************************************/ + +void tdb_debug(TDB_CONTEXT *tdb, int level, const char *fmt, ...) +{ + va_list ap; + if (tdb->log_fn == NULL) { + return; + } + va_start(ap, fmt); + tdb->log_fn(tdb, level, fmt, ap); + va_end(ap); +} + + +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + +/** + * Search across the whole tdb for keys that match the given pattern + * return the result as a list of keys + * + * @param tdb pointer to opened tdb file context + * @param pattern searching pattern used by fnmatch(3) functions + * + * @return list of keys found by looking up with given pattern + **/ +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) +{ + TDB_DATA key, next; + TDB_LIST_NODE *list = NULL; + TDB_LIST_NODE *rec = NULL; + + for (key = tdb_firstkey(tdb); key.dptr; key = next) { + /* duplicate key string to ensure null-termination */ + char *key_str = (char*) strndup(key.dptr, key.dsize); +#if 0 + if (!key_str) { + tdb_debug(tdb, 0, "tdb_search_keys: strndup() failed!\n"); + smb_panic("strndup failed!\n"); + } +#endif + tdb_debug(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); + + next = tdb_nextkey(tdb, key); + + /* do the pattern checking */ + if (fnmatch(pattern, key_str, 0) == 0) { + rec = (TDB_LIST_NODE*) malloc(sizeof(*rec)); + ZERO_STRUCTP(rec); + + rec->node_key = key; + + DLIST_ADD_END(list, rec, TDB_LIST_NODE *); + + tdb_debug(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); + } else { + free(key.dptr); + } + + /* free duplicated key string */ + free(key_str); + } + + return list; + +} + + +/** + * Free the list returned by tdb_search_keys + * + * @param node list of results found by tdb_search_keys + **/ +void tdb_search_list_free(TDB_LIST_NODE* node) +{ + TDB_LIST_NODE *next_node; + + while (node) { + next_node = node->next; + SAFE_FREE(node->node_key.dptr); + SAFE_FREE(node); + node = next_node; + } +} diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 797c793ce3..96641f8da7 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -2,10 +2,10 @@ # Start SUBSYSTEM LIBTDB [SUBSYSTEM::LIBTDB] INIT_OBJ_FILES = \ - lib/tdb/tdb.o + lib/tdb/common/tdb.o ADD_OBJ_FILES = \ - lib/tdb/tdbutil.o \ - lib/tdb/spinlock.o + lib/tdb/common/tdbutil.o \ + lib/tdb/common/spinlock.o # # End SUBSYSTEM LIBLDB ################################################ diff --git a/source4/lib/tdb/docs/README b/source4/lib/tdb/docs/README new file mode 100644 index 0000000000..fac3eacb4d --- /dev/null +++ b/source4/lib/tdb/docs/README @@ -0,0 +1,167 @@ +tdb - a trivial database system +tridge@linuxcare.com December 1999 +================================== + +This is a simple database API. It was inspired by the realisation that +in Samba we have several ad-hoc bits of code that essentially +implement small databases for sharing structures between parts of +Samba. As I was about to add another I realised that a generic +database module was called for to replace all the ad-hoc bits. + +I based the interface on gdbm. I couldn't use gdbm as we need to be +able to have multiple writers to the databases at one time. + +Compilation +----------- + +add HAVE_MMAP=1 to use mmap instead of read/write +add TDB_DEBUG=1 for verbose debug info +add NOLOCK=1 to disable locking code + +Testing +------- + +Compile tdbtest.c and link with gdbm for testing. tdbtest will perform +identical operations via tdb and gdbm then make sure the result is the +same + +Also included is tdbtool, which allows simple database manipulation +on the commandline. + +tdbtest and tdbtool are not built as part of Samba, but are included +for completeness. + +Interface +--------- + +The interface is very similar to gdbm except for the following: + +- different open interface. The tdb_open call is more similar to a + traditional open() +- no tdbm_reorganise() function +- no tdbm_sync() function. No operations are cached in the library anyway +- added a tdb_traverse() function for traversing the whole database + +A general rule for using tdb is that the caller frees any returned +TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA +return value called p. This is the same as gdbm. + +here is a full list of tdb functions with brief descriptions. + + +---------------------------------------------------------------------- +TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) + + open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the database + file. A flags value of O_WRONLY is invalid + + The hash size is advisory, use zero for a default value. + + return is NULL on error + + possible tdb_flags are: + TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open + TDB_INTERNAL - don't use a file, instaed store the data in + memory. The filename is ignored in this case. + TDB_NOLOCK - don't do any locking + TDB_NOMMAP - don't use mmap + +---------------------------------------------------------------------- +char *tdb_error(TDB_CONTEXT *tdb); + + return a error string for the last tdb error + +---------------------------------------------------------------------- +int tdb_close(TDB_CONTEXT *tdb); + + close a database + +---------------------------------------------------------------------- +int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf); + + update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1 + +---------------------------------------------------------------------- +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); + + fetch an entry in the database given a key + if the return value has a null dptr then a error occurred + + caller must free the resulting data + +---------------------------------------------------------------------- +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); + + check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm + +---------------------------------------------------------------------- +int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, + TDB_DATA key, TDB_DATA dbuf, void *state), void *state); + + traverse the entire database - calling fn(tdb, key, data, state) on each + element. + + return -1 on error or the record count traversed + + if fn is NULL then it is not called + + a non-zero return value from fn() indicates that the traversal should stop + +---------------------------------------------------------------------- +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); + + find the first entry in the database and return its key + + the caller must free the returned data + +---------------------------------------------------------------------- +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); + + find the next entry in the database, returning its key + + the caller must free the returned data + +---------------------------------------------------------------------- +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); + + delete an entry in the database given a key + +---------------------------------------------------------------------- +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); + + store an element in the database, replacing any existing element + with the same key + + If flag==TDB_INSERT then don't overwrite an existing entry + If flag==TDB_MODIFY then don't create a new entry + + return 0 on success, -1 on failure + +---------------------------------------------------------------------- +int tdb_writelock(TDB_CONTEXT *tdb); + + lock the database. If we already have it locked then don't do anything + +---------------------------------------------------------------------- +int tdb_writeunlock(TDB_CONTEXT *tdb); + unlock the database + +---------------------------------------------------------------------- +int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key); + + lock one hash chain. This is meant to be used to reduce locking + contention - it cannot guarantee how many records will be locked + +---------------------------------------------------------------------- +int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key); + + unlock one hash chain diff --git a/source4/lib/tdb/docs/tdb.magic b/source4/lib/tdb/docs/tdb.magic new file mode 100644 index 0000000000..f5619e7327 --- /dev/null +++ b/source4/lib/tdb/docs/tdb.magic @@ -0,0 +1,10 @@ +# Magic file(1) information about tdb files. +# +# Install this into /etc/magic or the corresponding location for your +# system, or pass as a -m argument to file(1). + +# You may use and redistribute this file without restriction. + +0 string TDB\ file TDB database +>32 lelong =0x2601196D version 6, little-endian +>>36 lelong x hash size %d bytes diff --git a/source4/lib/tdb/include/spinlock.h b/source4/lib/tdb/include/spinlock.h new file mode 100644 index 0000000000..967fe37457 --- /dev/null +++ b/source4/lib/tdb/include/spinlock.h @@ -0,0 +1,59 @@ +#ifndef __SPINLOCK_H__ +#define __SPINLOCK_H__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "tdb.h" + +#ifdef USE_SPINLOCKS + +#define RWLOCK_BIAS 0x1000UL + +/* OS SPECIFIC */ +#define MAX_BUSY_LOOPS 1000 +#undef USE_SCHED_YIELD + +/* ARCH SPECIFIC */ +/* We should make sure these are padded to a cache line */ +#if defined(SPARC_SPINLOCKS) +typedef volatile char spinlock_t; +#elif defined(POWERPC_SPINLOCKS) +typedef volatile unsigned long spinlock_t; +#elif defined(INTEL_SPINLOCKS) +typedef volatile int spinlock_t; +#elif defined(MIPS_SPINLOCKS) +typedef volatile unsigned long spinlock_t; +#else +#error Need to implement spinlock code in spinlock.h +#endif + +typedef struct { + spinlock_t lock; + volatile int count; +} tdb_rwlock_t; + +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_create_rwlocks(int fd, unsigned int hash_size); +int tdb_clear_spinlocks(TDB_CONTEXT *tdb); + +#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) + +#else /* !USE_SPINLOCKS */ +#if 0 +#define tdb_create_rwlocks(fd, hash_size) 0 +#define tdb_spinlock(tdb, list, rw_type) (-1) +#define tdb_spinunlock(tdb, list, rw_type) (-1) +#else +int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); +int tdb_create_rwlocks(int fd, unsigned int hash_size); +#endif +int tdb_clear_spinlocks(TDB_CONTEXT *tdb); +#define TDB_SPINLOCK_SIZE(hash_size) 0 + +#endif + +#endif diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h new file mode 100644 index 0000000000..73a0ea8f83 --- /dev/null +++ b/source4/lib/tdb/include/tdb.h @@ -0,0 +1,153 @@ +#ifndef __TDB_H__ +#define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* flags to tdb_store() */ +#define TDB_REPLACE 1 +#define TDB_INSERT 2 +#define TDB_MODIFY 3 + +/* flags for tdb_open() */ +#define TDB_DEFAULT 0 /* just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 +#define TDB_INTERNAL 2 /* don't store on disk */ +#define TDB_NOLOCK 4 /* don't do any locking */ +#define TDB_NOMMAP 8 /* don't use mmap */ +#define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ + +#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) + +/* error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST}; + +#ifndef u32 +#define u32 unsigned +#endif + +typedef struct TDB_DATA { + char *dptr; + size_t dsize; +} TDB_DATA; + +typedef u32 tdb_len; +typedef u32 tdb_off; + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + u32 version; /* version of the code */ + u32 hash_size; /* number of hash entries */ + tdb_off rwlocks; + tdb_off reserved[31]; +}; + +struct tdb_lock_type { + u32 count; + u32 ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + u32 off; + u32 hash; +}; + +/* this is the context structure that is returned from a db open */ +typedef struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + struct tdb_lock_type *locked; /* array of chain locks */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + u32 flags; /* the flags passed to tdb_open */ + u32 *lockedkeys; /* array of locked keys: first is #keys */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ + int open_flags; /* flags used in the open - needed by reopen */ +} TDB_CONTEXT; + +void tdb_debug(TDB_CONTEXT *, int , const char *, ...); + +typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); + +TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); +TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn); + +int tdb_reopen(TDB_CONTEXT *tdb); +int tdb_reopen_all(void); +void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); +enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); +const char *tdb_errorstr(TDB_CONTEXT *tdb); +TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(TDB_CONTEXT *tdb); +TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); +TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); +void tdb_unlockkeys(TDB_CONTEXT *tdb); +int tdb_lockall(TDB_CONTEXT *tdb); +void tdb_unlockall(TDB_CONTEXT *tdb); + +/* Low level locking functions: use with care */ +void tdb_set_lock_alarm(sig_atomic_t *palarm); +int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(TDB_CONTEXT *tdb); +int tdb_printfreelist(TDB_CONTEXT *tdb); + +extern TDB_DATA tdb_null; + +#ifdef __cplusplus +} +#endif + +#endif /* tdb.h */ diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h new file mode 100644 index 0000000000..01473446a1 --- /dev/null +++ b/source4/lib/tdb/include/tdbutil.h @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + Copyright (C) Andrew Tridgell 1999 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDBUTIL_H__ +#define __TDBUTIL_H__ + + +/* single node of a list returned by tdb_search_keys */ +typedef struct keys_node +{ + struct keys_node *prev, *next; + TDB_DATA node_key; +} TDB_LIST_NODE; + + +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); +void tdb_search_list_free(TDB_LIST_NODE*); + + +#endif /* __TDBUTIL_H__ */ diff --git a/source4/lib/tdb/spinlock.c b/source4/lib/tdb/spinlock.c deleted file mode 100644 index 1b789d4daa..0000000000 --- a/source4/lib/tdb/spinlock.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - trivial database library - - Copyright (C) Anton Blanchard 2001 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#if HAVE_CONFIG_H -#include -#endif - -#if STANDALONE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tdb.h" -#include "spinlock.h" - -#define DEBUG -#else -#include "includes.h" -#endif - -#ifdef USE_SPINLOCKS - -/* - * ARCH SPECIFIC - */ - -#if defined(SPARC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - asm volatile("ldstub [%1], %0" - : "=r" (result) - : "r" (lock) - : "memory"); - - return (result == 0) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(POWERPC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - __asm__ __volatile__( -"1: lwarx %0,0,%1\n\ - cmpwi 0,%0,0\n\ - li %0,0\n\ - bne- 2f\n\ - li %0,1\n\ - stwcx. %0,0,%1\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r"(result) - : "r"(lock) - : "cr0", "memory"); - - return (result == 1) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("eieio":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(INTEL_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - int oldval; - - asm volatile("xchgl %0,%1" - : "=r" (oldval), "=m" (*lock) - : "0" (0) - : "memory"); - - return oldval > 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 1; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 1; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 1); -} - -#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730) - -/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See - * sync(3) for the details of the intrinsic operations. - * - * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. - */ - -#if defined(STANDALONE) - -/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ -#define inline __inline - -#endif /* STANDALONE */ - -/* Returns 0 if the lock is acquired, EBUSY otherwise. */ -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int val; - val = __lock_test_and_set(lock, 1); - return val == 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - __lock_release(lock); -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - __lock_release(lock); -} - -/* Returns 1 if the lock is held, 0 otherwise. */ -static inline int __spin_is_locked(spinlock_t *lock) -{ - unsigned int val; - val = __add_and_fetch(lock, 0); - return val; -} - -#elif defined(MIPS_SPINLOCKS) - -static inline unsigned int load_linked(unsigned long addr) -{ - unsigned int res; - - __asm__ __volatile__("ll\t%0,(%1)" - : "=r" (res) - : "r" (addr)); - - return res; -} - -static inline unsigned int store_conditional(unsigned long addr, unsigned int value) -{ - unsigned int res; - - __asm__ __volatile__("sc\t%0,(%2)" - : "=r" (res) - : "0" (value), "r" (addr)); - return res; -} - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int mw; - - do { - mw = load_linked(lock); - if (mw) - return EBUSY; - } while (!store_conditional(lock, 1)); - - asm volatile("":::"memory"); - - return 0; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#else -#error Need to implement spinlock code in spinlock.c -#endif - -/* - * OS SPECIFIC - */ - -static void yield_cpu(void) -{ - struct timespec tm; - -#ifdef USE_SCHED_YIELD - sched_yield(); -#else - /* Linux will busy loop for delays < 2ms on real time tasks */ - tm.tv_sec = 0; - tm.tv_nsec = 2000000L + 1; - nanosleep(&tm, NULL); -#endif -} - -static int this_is_smp(void) -{ -#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN) - return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0; -#else - return 0; -#endif -} - -/* - * GENERIC - */ - -static int smp_machine = 0; - -static inline void __spin_lock(spinlock_t *lock) -{ - int ntries = 0; - - while(__spin_trylock(lock)) { - while(__spin_is_locked(lock)) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __read_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (!(rwlock->count & RWLOCK_BIAS)) { - rwlock->count++; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count & RWLOCK_BIAS) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (rwlock->count == 0) { - rwlock->count |= RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count != 0) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!(rwlock->count & RWLOCK_BIAS)) - fprintf(stderr, "bug: write_unlock\n"); -#endif - - rwlock->count &= ~RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); -} - -static void __read_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!rwlock->count) - fprintf(stderr, "bug: read_unlock\n"); - - if (rwlock->count & RWLOCK_BIAS) - fprintf(stderr, "bug: read_unlock\n"); -#endif - - rwlock->count--; - __spin_unlock(&rwlock->lock); -} - -/* TDB SPECIFIC */ - -/* lock a list in the database. list -1 is the alloc list */ -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_lock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_lock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* unlock the database. */ -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_unlock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_unlock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - return 0; -} - -int tdb_create_rwlocks(int fd, unsigned int hash_size) -{ - unsigned size, i; - tdb_rwlock_t *rwlocks; - - size = TDB_SPINLOCK_SIZE(hash_size); - rwlocks = malloc(size); - if (!rwlocks) - return -1; - - for(i = 0; i < hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - - /* Write it out (appending to end) */ - if (write(fd, rwlocks, size) != size) { - free(rwlocks); - return -1; - } - smp_machine = this_is_smp(); - free(rwlocks); - return 0; -} - -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_rwlock_t *rwlocks; - unsigned i; - - if (tdb->header.rwlocks == 0) return 0; - if (!tdb->map_ptr) return -1; - - /* We're mmapped here */ - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - for(i = 0; i < tdb->header.hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - return 0; -} -#else -int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } - -/* Non-spinlock version: remove spinlock pointer */ -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks - - (char *)&tdb->header); - - tdb->header.rwlocks = 0; - if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, (void *)&tdb->header.rwlocks, - sizeof(tdb->header.rwlocks)) - != sizeof(tdb->header.rwlocks)) - return -1; - return 0; -} -#endif diff --git a/source4/lib/tdb/spinlock.h b/source4/lib/tdb/spinlock.h deleted file mode 100644 index 967fe37457..0000000000 --- a/source4/lib/tdb/spinlock.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __SPINLOCK_H__ -#define __SPINLOCK_H__ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "tdb.h" - -#ifdef USE_SPINLOCKS - -#define RWLOCK_BIAS 0x1000UL - -/* OS SPECIFIC */ -#define MAX_BUSY_LOOPS 1000 -#undef USE_SCHED_YIELD - -/* ARCH SPECIFIC */ -/* We should make sure these are padded to a cache line */ -#if defined(SPARC_SPINLOCKS) -typedef volatile char spinlock_t; -#elif defined(POWERPC_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#elif defined(INTEL_SPINLOCKS) -typedef volatile int spinlock_t; -#elif defined(MIPS_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#else -#error Need to implement spinlock code in spinlock.h -#endif - -typedef struct { - spinlock_t lock; - volatile int count; -} tdb_rwlock_t; - -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); - -#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) - -#else /* !USE_SPINLOCKS */ -#if 0 -#define tdb_create_rwlocks(fd, hash_size) 0 -#define tdb_spinlock(tdb, list, rw_type) (-1) -#define tdb_spinunlock(tdb, list, rw_type) (-1) -#else -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -#endif -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); -#define TDB_SPINLOCK_SIZE(hash_size) 0 - -#endif - -#endif diff --git a/source4/lib/tdb/tdb.c b/source4/lib/tdb/tdb.c deleted file mode 100644 index c8ac7babad..0000000000 --- a/source4/lib/tdb/tdb.c +++ /dev/null @@ -1,2139 +0,0 @@ - /* - Unix SMB/CIFS implementation. - - trivial database library - - Copyright (C) Andrew Tridgell 1999-2004 - Copyright (C) Paul `Rusty' Russell 2000 - Copyright (C) Jeremy Allison 2000-2003 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* NOTE: If you use tdbs under valgrind, and in particular if you run - * tdbtorture, you may get spurious "uninitialized value" warnings. I - * think this is because valgrind doesn't understand that the mmap'd - * area may be written to by other processes. Memory can, from the - * point of view of the grinded process, spontaneously become - * initialized. - * - * I can think of a few solutions. [mbp 20030311] - * - * 1 - Write suppressions for Valgrind so that it doesn't complain - * about this. Probably the most reasonable but people need to - * remember to use them. - * - * 2 - Use IO not mmap when running under valgrind. Not so nice. - * - * 3 - Use the special valgrind macros to mark memory as valid at the - * right time. Probably too hard -- the process just doesn't know. - */ - -#ifdef STANDALONE -#if HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tdb.h" -#include "spinlock.h" -#else -#include "includes.h" -#endif - -#define TDB_MAGIC_FOOD "TDB file\n" -#define TDB_VERSION (0x26011967 + 6) -#define TDB_MAGIC (0x26011999U) -#define TDB_FREE_MAGIC (~TDB_MAGIC) -#define TDB_DEAD_MAGIC (0xFEE1DEAD) -#define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) -#define DEFAULT_HASH_SIZE 131 -#define TDB_PAGE_SIZE 0x2000 -#define FREELIST_TOP (sizeof(struct tdb_header)) -#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) -#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) -#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) -#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) -#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) -#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) - - -/* NB assumes there is a local variable called "tdb" that is the - * current context, also takes doubly-parenthesized print-style - * argument. */ -#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) - -/* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) -#endif - -#define BUCKET(hash) ((hash) % tdb->header.hash_size) -TDB_DATA tdb_null; - -/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ -static TDB_CONTEXT *tdbs = NULL; - -static int tdb_munmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return 0; - -#ifdef HAVE_MMAP - if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->map_size); - if (ret != 0) - return ret; - } -#endif - tdb->map_ptr = NULL; - return 0; -} - -static void tdb_mmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return; - -#ifdef HAVE_MMAP - if (!(tdb->flags & TDB_NOMMAP)) { - tdb->map_ptr = mmap(NULL, tdb->map_size, - PROT_READ|(tdb->read_only? 0:PROT_WRITE), - MAP_SHARED|MAP_FILE, tdb->fd, 0); - - /* - * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! - */ - - if (tdb->map_ptr == MAP_FAILED) { - tdb->map_ptr = NULL; - TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", - tdb->map_size, strerror(errno))); - } - } else { - tdb->map_ptr = NULL; - } -#else - tdb->map_ptr = NULL; -#endif -} - -/* Endian conversion: we only ever deal with 4 byte quantities */ -static void *convert(void *buf, u32 size) -{ - u32 i, *p = buf; - for (i = 0; i < size / 4; i++) - p[i] = TDB_BYTEREV(p[i]); - return buf; -} -#define DOCONV() (tdb->flags & TDB_CONVERT) -#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) - -/* the body of the database is made of one list_struct for the free space - plus a separate data list for each hash value */ -struct list_struct { - tdb_off next; /* offset of the next record in the list */ - tdb_len rec_len; /* total byte length of record */ - tdb_len key_len; /* byte length of key */ - tdb_len data_len; /* byte length of data */ - u32 full_hash; /* the full 32 bit hash of the key */ - u32 magic; /* try to catch errors */ - /* the following union is implied: - union { - char record[rec_len]; - struct { - char key[key_len]; - char data[data_len]; - } - u32 totalsize; (tailer) - } - */ -}; - -/*************************************************************** - Allow a caller to set a "alarm" flag that tdb can check to abort - a blocking lock on SIGALRM. -***************************************************************/ - -static sig_atomic_t *palarm_fired; - -void tdb_set_lock_alarm(sig_atomic_t *palarm) -{ - palarm_fired = palarm; -} - -/* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset. - - On error, errno is also set so that errors are passed back properly - through tdb_open(). */ -static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, - int rw_type, int lck_type, int probe) -{ - struct flock fl; - int ret; - - if (tdb->flags & TDB_NOLOCK) - return 0; - if ((rw_type == F_WRLCK) && (tdb->read_only)) { - errno = EACCES; - return -1; - } - - fl.l_type = rw_type; - fl.l_whence = SEEK_SET; - fl.l_start = offset; - fl.l_len = 1; - fl.l_pid = 0; - - do { - ret = fcntl(tdb->fd,lck_type,&fl); - if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) - break; - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - if (errno == EINTR && palarm_fired && *palarm_fired) - tdb->ecode = TDB_ERR_LOCK_TIMEOUT; - else - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - } - /* Was it an alarm timeout ? */ - if (errno == EINTR && palarm_fired && *palarm_fired) { - TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); - } - /* Otherwise - generic lock error. errno set by fcntl. - * EAGAIN is an expected return from non-blocking - * locks. */ - if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, - strerror(errno))); - } - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* lock a list in the database. list -1 is the alloc list */ -static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) -{ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", - list, ltype)); - return -1; - } - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Since fcntl locks don't nest, we do a lock for the first one, - and simply bump the count for future ones */ - if (tdb->locked[list+1].count == 0) { - if (!tdb->read_only && tdb->header.rwlocks) { - if (tdb_spinlock(tdb, list, ltype)) { - TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n", - list, ltype)); - return -1; - } - } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { - TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", - list, ltype, strerror(errno))); - return -1; - } - tdb->locked[list+1].ltype = ltype; - } - tdb->locked[list+1].count++; - return 0; -} - -/* unlock the database: returns void because it's too late for errors. */ - /* changed to return int it may be interesting to know there - has been an error --simo */ -static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) -{ - int ret = -1; - - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Sanity checks */ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); - return ret; - } - - if (tdb->locked[list+1].count==0) { - TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); - return ret; - } - - if (tdb->locked[list+1].count == 1) { - /* Down to last nested lock: unlock underneath */ - if (!tdb->read_only && tdb->header.rwlocks) { - ret = tdb_spinunlock(tdb, list, ltype); - } else { - ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); - } - } else { - ret = 0; - } - tdb->locked[list+1].count--; - - if (ret) - TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); - return ret; -} - -/* This is based on the hash algorithm from gdbm */ -static u32 tdb_hash(TDB_DATA *key) -{ - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) - value = (value + (key->dptr[i] << (i*5 % 24))); - - return (1103515243 * value + 12345); -} - -/* check for an out of bounds access - if it is out of bounds then - see if the database has been expanded by someone else and expand - if necessary - note that "len" is the minimum length needed for the db -*/ -static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) -{ - struct stat st; - if (len <= tdb->map_size) - return 0; - if (tdb->flags & TDB_INTERNAL) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", - (int)len, (int)tdb->map_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (fstat(tdb->fd, &st) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - - if (st.st_size < (size_t)len) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", - (int)len, (int)st.st_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - /* Unmap, update size, remap */ - if (tdb_munmap(tdb) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - tdb->map_size = st.st_size; - tdb_mmap(tdb); - return 0; -} - -/* write a lump of data at a specified offset */ -static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(off + (char *)tdb->map_ptr, buf, len); -#ifdef HAVE_PWRITE - else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - return 0; -} - -/* read a lump of data at a specified offset, maybe convert */ -static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(buf, off + (char *)tdb->map_ptr, len); -#ifdef HAVE_PREAD - else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || read(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - if (cv) - convert(buf, len); - return 0; -} - -/* read a lump of data, allocating the space for it */ -static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) -{ - char *buf; - - if (!(buf = malloc(len))) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", - len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_OOM, buf); - } - if (tdb_read(tdb, offset, buf, len, 0) == -1) { - SAFE_FREE(buf); - return NULL; - } - return buf; -} - -/* read/write a tdb_off */ -static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); -} -static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - tdb_off off = *d; - return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); -} - -/* read/write a record */ -static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - if (TDB_BAD_MAGIC(rec)) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - return tdb_oob(tdb, rec->next+sizeof(*rec), 0); -} -static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - struct list_struct r = *rec; - return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); -} - -/* read a freelist record and check for simple errors */ -static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) -{ - if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - - if (rec->magic == TDB_MAGIC) { - /* this happens when a app is showdown while deleting a record - we should - not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic at offset=%d - fixing\n", - rec->magic, off)); - rec->magic = TDB_FREE_MAGIC; - if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) - return -1; - } - - if (rec->magic != TDB_FREE_MAGIC) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", - rec->magic, off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) - return -1; - return 0; -} - -/* update a record tailer (must hold allocation lock) */ -static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, - const struct list_struct *rec) -{ - tdb_off totalsize; - - /* Offset of tailer from record header */ - totalsize = sizeof(*rec) + rec->rec_len; - return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), - &totalsize); -} - -static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) -{ - struct list_struct rec; - tdb_off tailer_ofs, tailer; - - if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - printf("ERROR: failed to read record at %u\n", offset); - return 0; - } - - printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", - offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); - - tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); - if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { - printf("ERROR: failed to read tailer at %u\n", tailer_ofs); - return rec.next; - } - - if (tailer != rec.rec_len + sizeof(rec)) { - printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); - } - return rec.next; -} - -static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) -{ - tdb_off rec_ptr, top; - - top = TDB_HASH_TOP(i); - - if (tdb_lock(tdb, i, F_WRLCK) != 0) - return -1; - - if (ofs_read(tdb, top, &rec_ptr) == -1) - return tdb_unlock(tdb, i, F_WRLCK); - - if (rec_ptr) - printf("hash=%d\n", i); - - while (rec_ptr) { - rec_ptr = tdb_dump_record(tdb, rec_ptr); - } - - return tdb_unlock(tdb, i, F_WRLCK); -} - -void tdb_dump_all(TDB_CONTEXT *tdb) -{ - int i; - for (i=0;iheader.hash_size;i++) { - tdb_dump_chain(tdb, i); - } - printf("freelist:\n"); - tdb_dump_chain(tdb, -1); -} - -int tdb_printfreelist(TDB_CONTEXT *tdb) -{ - int ret; - long total_free = 0; - tdb_off offset, rec_ptr; - struct list_struct rec; - - if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) - return ret; - - offset = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, offset, &rec_ptr) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - } - - printf("freelist top=[0x%08x]\n", rec_ptr ); - while (rec_ptr) { - if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - if (rec.magic != TDB_FREE_MAGIC) { - printf("bad magic 0x%08x in free list\n", rec.magic); - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", - rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); - total_free += rec.rec_len; - - /* move to the next record */ - rec_ptr = rec.next; - } - printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, - (int)total_free); - - return tdb_unlock(tdb, -1, F_WRLCK); -} - -/* Remove an element from the freelist. Must have alloc lock. */ -static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) -{ - tdb_off last_ptr, i; - - /* read in the freelist top */ - last_ptr = FREELIST_TOP; - while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { - if (i == off) { - /* We've found it! */ - return ofs_write(tdb, last_ptr, &next); - } - /* Follow chain (next offset is at start of record) */ - last_ptr = i; - } - TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); -} - -/* Add an element into the freelist. Merge adjacent records if - neccessary. */ -static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - tdb_off right, left; - - /* Allocation and tailer lock */ - if (tdb_lock(tdb, -1, F_WRLCK) != 0) - return -1; - - /* set an initial tailer, so if we fail we don't leave a bogus record */ - if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); - goto fail; - } - - /* Look right first (I'm an Australian, dammit) */ - right = offset + sizeof(*rec) + rec->rec_len; - if (right + sizeof(*rec) <= tdb->map_size) { - struct list_struct r; - - if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); - goto left; - } - - /* If it's free, expand to include it. */ - if (r.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); - goto left; - } - rec->rec_len += sizeof(r) + r.rec_len; - } - } - -left: - /* Look left */ - left = offset - sizeof(tdb_off); - if (left > TDB_DATA_START(tdb->header.hash_size)) { - struct list_struct l; - tdb_off leftsize; - - /* Read in tailer and jump back to header */ - if (ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); - goto update; - } - left = offset - leftsize; - - /* Now read in record */ - if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); - goto update; - } - - /* If it's free, expand to include it. */ - if (l.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); - goto update; - } else { - offset = left; - rec->rec_len += leftsize; - } - } - } - -update: - if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); - goto fail; - } - - /* Now, prepend to free list */ - rec->magic = TDB_FREE_MAGIC; - - if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || - rec_write(tdb, offset, rec) == -1 || - ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); - goto fail; - } - - /* And we're done. */ - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* expand a file. we prefer to use ftruncate, as that is what posix - says to use for mmap expansion */ -static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) -{ - char buf[1024]; -#if HAVE_FTRUNCATE_EXTEND - if (ftruncate(tdb->fd, size+addition) != 0) { - TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#else - char b = 0; - -#ifdef HAVE_PWRITE - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { -#else - if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || - write(tdb->fd, &b, 1) != 1) { -#endif - TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#endif - - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ - memset(buf, 0x42, sizeof(buf)); - while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; -#ifdef HAVE_PWRITE - int ret = pwrite(tdb->fd, buf, n, size); -#else - int ret; - if (lseek(tdb->fd, size, SEEK_SET) != size) - return -1; - ret = write(tdb->fd, buf, n); -#endif - if (ret != n) { - TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); - return -1; - } - addition -= n; - size += n; - } - return 0; -} - - -/* expand the database at least size bytes by expanding the underlying - file and doing the mmap again if necessary */ -static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) -{ - struct list_struct rec; - tdb_off offset; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); - return -1; - } - - /* must know about any previous expansions by another process */ - tdb_oob(tdb, tdb->map_size + 1, 1); - - /* always make room for at least 10 more records, and round - the database up to a multiple of TDB_PAGE_SIZE */ - size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; - - if (!(tdb->flags & TDB_INTERNAL)) - tdb_munmap(tdb); - - /* - * We must ensure the file is unmapped before doing this - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - if (expand_file(tdb, tdb->map_size, size) != 0) - goto fail; - } - - tdb->map_size += size; - - if (tdb->flags & TDB_INTERNAL) - tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size); - else { - /* - * We must ensure the file is remapped before adding the space - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* We're ok if the mmap fails as we'll fallback to read/write */ - tdb_mmap(tdb); - } - - /* form a new freelist record */ - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = size - sizeof(rec); - - /* link it into the free list */ - offset = tdb->map_size - size; - if (tdb_free(tdb, offset, &rec) == -1) - goto fail; - - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* - the core of tdb_allocate - called when we have decided which - free list entry to use - */ -static tdb_off tdb_allocate_ofs(TDB_CONTEXT *tdb, tdb_len length, tdb_off rec_ptr, - struct list_struct *rec, tdb_off last_ptr) -{ - struct list_struct newrec; - tdb_off newrec_ptr; - - memset(&newrec, '\0', sizeof(newrec)); - - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else { - newrec_ptr = 0; - } - - /* Remove allocated record from the free list */ - if (ofs_write(tdb, last_ptr, &rec->next) == -1) { - return 0; - } - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (rec_write(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { - return 0; - } - } - - /* all done - return the new record offset */ - return rec_ptr; -} - -/* allocate some space from the free list. The offset returned points - to a unconnected list_struct within the database with room for at - least length bytes of total data - - 0 is returned if the space could not be allocated - */ -static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, - struct list_struct *rec) -{ - tdb_off rec_ptr, last_ptr, newrec_ptr; - struct { - tdb_off rec_ptr, last_ptr; - tdb_len rec_len; - } bestfit; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) - return 0; - - /* Extra bytes required for tailer */ - length += sizeof(tdb_off); - - again: - last_ptr = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) - goto fail; - - bestfit.rec_ptr = 0; - - /* - this is a best fit allocation strategy. Originally we used - a first fit strategy, but it suffered from massive fragmentation - issues when faced with a slowly increasing record size. - */ - while (rec_ptr) { - if (rec_free_read(tdb, rec_ptr, rec) == -1) { - goto fail; - } - - if (rec->rec_len >= length) { - if (bestfit.rec_ptr == 0 || - rec->rec_len < bestfit.rec_len) { - bestfit.rec_len = rec->rec_len; - bestfit.rec_ptr = rec_ptr; - bestfit.last_ptr = last_ptr; - /* consider a fit to be good enough if we aren't wasting more than half the space */ - if (bestfit.rec_len < 2*length) { - break; - } - } - } - - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec->next; - } - - if (bestfit.rec_ptr != 0) { - if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { - goto fail; - } - - newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); - tdb_unlock(tdb, -1, F_WRLCK); - return newrec_ptr; - } - - /* we didn't find enough space. See if we can expand the - database and if we can then try again */ - if (tdb_expand(tdb, length + sizeof(*rec)) == 0) - goto again; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return 0; -} - -/* initialise a new database with a specified hash size */ -static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) -{ - struct tdb_header *newdb; - int size, ret = -1; - - /* We make it up in memory, then write it out if not internal */ - size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); - if (!(newdb = calloc(size, 1))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - - /* Fill in the header */ - newdb->version = TDB_VERSION; - newdb->hash_size = hash_size; -#ifdef USE_SPINLOCKS - newdb->rwlocks = size; -#endif - if (tdb->flags & TDB_INTERNAL) { - tdb->map_size = size; - tdb->map_ptr = (char *)newdb; - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Convert the `ondisk' version if asked. */ - CONVERT(*newdb); - return 0; - } - if (lseek(tdb->fd, 0, SEEK_SET) == -1) - goto fail; - - if (ftruncate(tdb->fd, 0) == -1) - goto fail; - - /* This creates an endian-converted header, as if read from disk */ - CONVERT(*newdb); - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Don't endian-convert the magic food! */ - memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); - if (write(tdb->fd, newdb, size) != size) - ret = -1; - else - ret = tdb_create_rwlocks(tdb->fd, hash_size); - - fail: - SAFE_FREE(newdb); - return ret; -} - -/* Returns 0 on fail. On success, return offset of record, and fills - in rec */ -static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, - struct list_struct *r) -{ - tdb_off rec_ptr; - - /* read in the hash top */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) - return 0; - - /* keep looking until we find the right record */ - while (rec_ptr) { - if (rec_read(tdb, rec_ptr, r) == -1) - return 0; - - if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { - char *k; - /* a very likely hit - read the key */ - k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), - r->key_len); - if (!k) - return 0; - - if (memcmp(key.dptr, k, key.dsize) == 0) { - SAFE_FREE(k); - return rec_ptr; - } - SAFE_FREE(k); - } - rec_ptr = r->next; - } - return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); -} - -/* If they do lockkeys, check that this hash is one they locked */ -static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) -{ - u32 i; - if (!tdb->lockedkeys) - return 1; - for (i = 0; i < tdb->lockedkeys[0]; i++) - if (tdb->lockedkeys[i+1] == hash) - return 1; - return TDB_ERRCODE(TDB_ERR_NOLOCK, 0); -} - -/* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec) -{ - u32 rec_ptr; - - if (!tdb_keylocked(tdb, hash)) - return 0; - if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) - return 0; - if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) - tdb_unlock(tdb, BUCKET(hash), locktype); - return rec_ptr; -} - -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) -{ - return tdb->ecode; -} - -static struct tdb_errname { - enum TDB_ERROR ecode; const char *estring; -} emap[] = { {TDB_SUCCESS, "Success"}, - {TDB_ERR_CORRUPT, "Corrupt database"}, - {TDB_ERR_IO, "IO Error"}, - {TDB_ERR_LOCK, "Locking error"}, - {TDB_ERR_OOM, "Out of memory"}, - {TDB_ERR_EXISTS, "Record exists"}, - {TDB_ERR_NOLOCK, "Lock exists on other keys"}, - {TDB_ERR_NOEXIST, "Record does not exist"} }; - -/* Error string for the last tdb error */ -const char *tdb_errorstr(TDB_CONTEXT *tdb) -{ - u32 i; - for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) - if (tdb->ecode == emap[i].ecode) - return emap[i].estring; - return "Invalid error code"; -} - -/* update an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. -*/ - -static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) -{ - struct list_struct rec; - tdb_off rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* must be long enough key, data and tailer */ - if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, - dbuf.dptr, dbuf.dsize) == -1) - return -1; - - if (dbuf.dsize != rec.data_len) { - /* update size */ - rec.data_len = dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); - } - - return 0; -} - -/* find an entry in the database given a key */ -/* If an entry doesn't exist tdb_err will be set to - * TDB_ERR_NOEXIST. If a key has no data attached - * tdb_err will not be set. Both will return a - * zero pptr and zero dsize. - */ - -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) -{ - tdb_off rec_ptr; - struct list_struct rec; - TDB_DATA ret; - u32 hash; - - /* find which hash bucket it is in */ - hash = tdb_hash(&key); - if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) - return tdb_null; - - if (rec.data_len) - ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - else - ret.dptr = NULL; - ret.dsize = rec.data_len; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return ret; -} - -/* check if an entry in the database exists - - note that 1 is returned if the key is found and 0 is returned if not found - this doesn't match the conventions in the rest of this module, but is - compatible with gdbm -*/ -static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) -{ - struct list_struct rec; - - if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) - return 0; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return 1; -} - -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) -{ - u32 hash = tdb_hash(&key); - return tdb_exists_hash(tdb, key, hash); -} - -/* record lock stops delete underneath */ -static int lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; -} -/* - Write locks override our own fcntl readlocks, so check it here. - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - return -1; - return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); -} - -/* - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); -} -/* fcntl locks don't stack: avoid unlocking someone else's */ -static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - u32 count = 0; - - if (off == 0) - return 0; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - count++; - return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); -} - -/* actually delete an entry in the database given the offset */ -static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) -{ - tdb_off last_ptr, i; - struct list_struct lastrec; - - if (tdb->read_only) return -1; - - if (write_lock_record(tdb, rec_ptr) == -1) { - /* Someone traversing here: mark it as dead */ - rec->magic = TDB_DEAD_MAGIC; - return rec_write(tdb, rec_ptr, rec); - } - if (write_unlock_record(tdb, rec_ptr) != 0) - return -1; - - /* find previous record in hash chain */ - if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) - return -1; - for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) - if (rec_read(tdb, i, &lastrec) == -1) - return -1; - - /* unlink it: next ptr is at start of record. */ - if (last_ptr == 0) - last_ptr = TDB_HASH_TOP(rec->full_hash); - if (ofs_write(tdb, last_ptr, &rec->next) == -1) - return -1; - - /* recover the space */ - if (tdb_free(tdb, rec_ptr, rec) == -1) - return -1; - return 0; -} - -/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ -static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, - struct list_struct *rec) -{ - int want_next = (tlock->off != 0); - - /* No traversal allows if you've called tdb_lockkeys() */ - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - - /* Lock each chain from the start one. */ - for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { - if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) - return -1; - - /* No previous record? Start at top of chain. */ - if (!tlock->off) { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), - &tlock->off) == -1) - goto fail; - } else { - /* Otherwise unlock the previous record. */ - if (unlock_record(tdb, tlock->off) != 0) - goto fail; - } - - if (want_next) { - /* We have offset of old record: grab next */ - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - tlock->off = rec->next; - } - - /* Iterate through chain */ - while( tlock->off) { - tdb_off current; - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } - /* Try to clean dead ones from old traverses */ - current = tlock->off; - tlock->off = rec->next; - if (!tdb->read_only && - do_delete(tdb, current, rec) != 0) - goto fail; - } - tdb_unlock(tdb, tlock->hash, F_WRLCK); - want_next = 0; - } - /* We finished iteration without finding anything */ - return TDB_ERRCODE(TDB_SUCCESS, 0); - - fail: - tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); - return -1; -} - -/* traverse the entire database - calling fn(tdb, key, data) on each element. - return -1 on error or the record count traversed - if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop - */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private) -{ - TDB_DATA key, dbuf; - struct list_struct rec; - struct tdb_traverse_lock tl = { NULL, 0, 0 }; - int ret, count = 0; - - /* This was in the initializaton, above, but the IRIX compiler - * did not like it. crh - */ - tl.next = tdb->travlocks.next; - - /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = &tl; - - /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { - count++; - /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { - ret = -1; - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) - goto out; - if (unlock_record(tdb, tl.off) != 0) - TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); - goto out; - } - key.dsize = rec.key_len; - dbuf.dptr = key.dptr + rec.key_len; - dbuf.dsize = rec.data_len; - - /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { - ret = -1; - goto out; - } - if (fn && fn(tdb, key, dbuf, private)) { - /* They want us to terminate traversal */ - ret = count; - if (unlock_record(tdb, tl.off) != 0) { - TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; - ret = -1; - } - tdb->travlocks.next = tl.next; - SAFE_FREE(key.dptr); - return count; - } - SAFE_FREE(key.dptr); - } -out: - tdb->travlocks.next = tl.next; - if (ret < 0) - return -1; - else - return count; -} - -/* find the first entry in the database and return its key */ -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) -{ - TDB_DATA key; - struct list_struct rec; - - /* release any old lock */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - tdb->travlocks.off = tdb->travlocks.hash = 0; - - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) - return tdb_null; - /* now read the key */ - key.dsize = rec.key_len; - key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); - if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); - return key; -} - -/* find the next entry in the database, returning its key */ -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) -{ - u32 oldhash; - TDB_DATA key = tdb_null; - struct list_struct rec; - char *k = NULL; - - /* Is locked key the old key? If so, traverse will be reliable. */ - if (tdb->travlocks.off) { - if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) - return tdb_null; - if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 - || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), - rec.key_len)) - || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { - /* No, it wasn't: unlock it and start from scratch */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - return tdb_null; - tdb->travlocks.off = 0; - } - - SAFE_FREE(k); - } - - if (!tdb->travlocks.off) { - /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec); - if (!tdb->travlocks.off) - return tdb_null; - tdb->travlocks.hash = BUCKET(rec.full_hash); - if (lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); - return tdb_null; - } - } - oldhash = tdb->travlocks.hash; - - /* Grab next record: locks chain and returned record, - unlocks old record */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { - key.dsize = rec.key_len; - key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), - key.dsize); - /* Unlock the chain of this new record */ - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - } - /* Unlock the chain of old record */ - if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - return key; -} - -/* delete an entry in the database given a key */ -static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) -{ - tdb_off rec_ptr; - struct list_struct rec; - int ret; - - if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) - return -1; - ret = do_delete(tdb, rec_ptr, &rec); - if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); - return ret; -} - -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) -{ - u32 hash = tdb_hash(&key); - return tdb_delete_hash(tdb, key, hash); -} - -/* store an element in the database, replacing any existing element - with the same key - - return 0 on success, -1 on failure -*/ -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) -{ - struct list_struct rec; - u32 hash; - tdb_off rec_ptr; - char *p = NULL; - int ret = 0; - - /* find which hash bucket it is in */ - hash = tdb_hash(&key); - if (!tdb_keylocked(tdb, hash)) - return -1; - if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) - return -1; - - /* check for it existing, on insert. */ - if (flag == TDB_INSERT) { - if (tdb_exists_hash(tdb, key, hash)) { - tdb->ecode = TDB_ERR_EXISTS; - goto fail; - } - } else { - /* first try in-place update, on modify or replace. */ - if (tdb_update_hash(tdb, key, hash, dbuf) == 0) - goto out; - if (tdb->ecode == TDB_ERR_NOEXIST && - flag == TDB_MODIFY) { - /* if the record doesn't exist and we are in TDB_MODIFY mode then - we should fail the store */ - goto fail; - } - } - /* reset the error code potentially set by the tdb_update() */ - tdb->ecode = TDB_SUCCESS; - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - if (flag != TDB_INSERT) - tdb_delete_hash(tdb, key, hash); - - /* Copy key+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { - tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - memcpy(p, key.dptr, key.dsize); - if (dbuf.dsize) - memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); - - /* we have to allocate some space */ - if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec))) - goto fail; - - /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = dbuf.dsize; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; - } - out: - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; -fail: - ret = -1; - goto out; -} - -/* Attempt to append data to an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. Record must be locked before calling. -*/ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) -{ - struct list_struct rec; - tdb_off rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* Append of 0 is always ok. */ - if (new_dbuf.dsize == 0) - return 0; - - /* must be long enough for key, old data + new data and tailer */ - if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { - /* No room. */ - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, - new_dbuf.dptr, new_dbuf.dsize) == -1) - return -1; - - /* update size */ - rec.data_len += new_dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); -} - -/* Append to an entry. Create if not exist. */ - -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) -{ - struct list_struct rec; - u32 hash; - tdb_off rec_ptr; - char *p = NULL; - int ret = 0; - size_t new_data_size = 0; - - /* find which hash bucket it is in */ - hash = tdb_hash(&key); - if (!tdb_keylocked(tdb, hash)) - return -1; - if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) - return -1; - - /* first try in-place. */ - if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) - goto out; - - /* reset the error code potentially set by the tdb_append_inplace() */ - tdb->ecode = TDB_SUCCESS; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { - if (tdb->ecode != TDB_ERR_NOEXIST) - goto fail; - - /* Not found - create. */ - - ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); - goto out; - } - - new_data_size = rec.data_len + new_dbuf.dsize; - - /* Copy key+old_value+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + new_data_size))) { - tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - /* Copy the key in place. */ - memcpy(p, key.dptr, key.dsize); - - /* Now read the old data into place. */ - if (rec.data_len && - tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) - goto fail; - - /* Finally append the new data. */ - if (new_dbuf.dsize) - memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - - tdb_delete_hash(tdb, key, hash); - - if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) - goto fail; - - /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = new_data_size; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; - } - - out: - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; - -fail: - ret = -1; - goto out; -} - -static int tdb_already_open(dev_t device, - ino_t ino) -{ - TDB_CONTEXT *i; - - for (i = tdbs; i; i = i->next) { - if (i->device == device && i->inode == ino) { - return 1; - } - } - - return 0; -} - -/* open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the - database file. A flags value of O_WRONLY is invalid. The hash size - is advisory, use zero for a default value. - - Return is NULL on error, in which case errno is also set. Don't - try to call tdb_error or tdb_errname, just do strerror(errno). - - @param name may be NULL for internal databases. */ -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL); -} - - -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn) -{ - TDB_CONTEXT *tdb; - struct stat st; - int rev = 0, locked = 0; - unsigned char *vp; - u32 vertest; - - if (!(tdb = calloc(1, sizeof *tdb))) { - /* Can't log this */ - errno = ENOMEM; - goto fail; - } - tdb->fd = -1; - tdb->name = NULL; - tdb->map_ptr = NULL; - tdb->lockedkeys = NULL; - tdb->flags = tdb_flags; - tdb->open_flags = open_flags; - tdb->log_fn = log_fn; - - if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", - name)); - errno = EINVAL; - goto fail; - } - - if (hash_size == 0) - hash_size = DEFAULT_HASH_SIZE; - if ((open_flags & O_ACCMODE) == O_RDONLY) { - tdb->read_only = 1; - /* read only databases don't do locking or clear if first */ - tdb->flags |= TDB_NOLOCK; - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - /* internal databases don't mmap or lock, and start off cleared */ - if (tdb->flags & TDB_INTERNAL) { - tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); - goto fail; - } - goto internal; - } - - if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by open(2) */ - } - - /* ensure there is only one process initialising at once */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by tdb_brlock */ - } - - /* we need to zero database if we are the only one with it open */ - if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { - open_flags |= O_CREAT; - if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to truncate %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by ftruncate */ - } - } - - if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 - || (tdb->header.version != TDB_VERSION - && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { - /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { - errno = EIO; /* ie bad format or something */ - goto fail; - } - rev = (tdb->flags & TDB_CONVERT); - } - vp = (unsigned char *)&tdb->header.version; - vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | - (((u32)vp[2]) << 8) | (u32)vp[3]; - tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; - if (!rev) - tdb->flags &= ~TDB_CONVERT; - else { - tdb->flags |= TDB_CONVERT; - convert(&tdb->header, sizeof(tdb->header)); - } - if (fstat(tdb->fd, &st) == -1) - goto fail; - - /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "%s (%d,%d) is already open in this process\n", - name, st.st_dev, st.st_ino)); - errno = EBUSY; - goto fail; - } - - if (!(tdb->name = (char *)strdup(name))) { - errno = ENOMEM; - goto fail; - } - - tdb->map_size = st.st_size; - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); - if (!tdb->locked) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "failed to allocate lock structure for %s\n", - name)); - errno = ENOMEM; - goto fail; - } - tdb_mmap(tdb); - if (locked) { - if (!tdb->read_only) - if (tdb_clear_spinlocks(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to clear spinlock\n")); - goto fail; - } - if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to take ACTIVE_LOCK on %s: %s\n", - name, strerror(errno))); - goto fail; - } - - } - - /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if - we didn't get the initial exclusive lock as we need to let all other - users know we're using it. */ - - if (tdb_flags & TDB_CLEAR_IF_FIRST) { - /* leave this lock in place to indicate it's in use */ - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) - goto fail; - } - - - internal: - /* Internal (memory-only) databases skip all the code above to - * do with disk files, and resume here by releasing their - * global lock and hooking into the active list. */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) - goto fail; - tdb->next = tdbs; - tdbs = tdb; - return tdb; - - fail: - { int save_errno = errno; - - if (!tdb) - return NULL; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); - SAFE_FREE(tdb->locked); - SAFE_FREE(tdb); - errno = save_errno; - return NULL; - } -} - -/** - * Close a database. - * - * @returns -1 for error; 0 for success. - **/ -int tdb_close(TDB_CONTEXT *tdb) -{ - TDB_CONTEXT **i; - int ret = 0; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - ret = close(tdb->fd); - SAFE_FREE(tdb->locked); - SAFE_FREE(tdb->lockedkeys); - - /* Remove from contexts list */ - for (i = &tdbs; *i; i = &(*i)->next) { - if (*i == tdb) { - *i = tdb->next; - break; - } - } - - memset(tdb, 0, sizeof(*tdb)); - SAFE_FREE(tdb); - - return ret; -} - -/* lock/unlock entire database */ -int tdb_lockall(TDB_CONTEXT *tdb) -{ - u32 i; - - /* There are no locks on read-only dbs */ - if (tdb->read_only) - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - for (i = 0; i < tdb->header.hash_size; i++) - if (tdb_lock(tdb, i, F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < tdb->header.hash_size) { - u32 j; - - for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - - return 0; -} -void tdb_unlockall(TDB_CONTEXT *tdb) -{ - u32 i; - for (i=0; i < tdb->header.hash_size; i++) - tdb_unlock(tdb, i, F_WRLCK); -} - -int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) -{ - u32 i, j, hash; - - /* Can't lock more keys if already locked */ - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - if (!(tdb->lockedkeys = malloc(sizeof(u32) * (number+1)))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - /* First number in array is # keys */ - tdb->lockedkeys[0] = number; - - /* Insertion sort by bucket */ - for (i = 0; i < number; i++) { - hash = tdb_hash(&keys[i]); - for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++); - memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j)); - tdb->lockedkeys[j+1] = hash; - } - /* Finally, lock in order */ - for (i = 0; i < number; i++) - if (tdb_lock(tdb, i, F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < number) { - for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); - SAFE_FREE(tdb->lockedkeys); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - return 0; -} - -/* Unlock the keys previously locked by tdb_lockkeys() */ -void tdb_unlockkeys(TDB_CONTEXT *tdb) -{ - u32 i; - if (!tdb->lockedkeys) - return; - for (i = 0; i < tdb->lockedkeys[0]; i++) - tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK); - SAFE_FREE(tdb->lockedkeys); -} - -/* lock/unlock one hash chain. This is meant to be used to reduce - contention - it cannot guarantee how many records will be locked */ -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); -} - -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); -} - -int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); -} - -int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); -} - - -/* register a loging function */ -void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) -{ - tdb->log_fn = fn; -} - - -/* reopen a tdb - this can be used after a fork to ensure that we have an independent - seek pointer from our parent and to re-establish locks */ -int tdb_reopen(TDB_CONTEXT *tdb) -{ - struct stat st; - - if (tdb->flags & TDB_INTERNAL) - return 0; /* Nothing to do. */ - if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); - goto fail; - } - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); - tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); - if (tdb->fd == -1) { - TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); - goto fail; - } - if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); - goto fail; - } - if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); - goto fail; - } - tdb_mmap(tdb); - if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { - TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); - goto fail; - } - - return 0; - -fail: - tdb_close(tdb); - return -1; -} - -/* reopen all tdb's */ -int tdb_reopen_all(void) -{ - TDB_CONTEXT *tdb; - - for (tdb=tdbs; tdb; tdb = tdb->next) { - /* Ensure no clear-if-first. */ - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_reopen(tdb) != 0) - return -1; - } - - return 0; -} diff --git a/source4/lib/tdb/tdb.h b/source4/lib/tdb/tdb.h deleted file mode 100644 index 73a0ea8f83..0000000000 --- a/source4/lib/tdb/tdb.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __TDB_H__ -#define __TDB_H__ - -/* - Unix SMB/CIFS implementation. - - trivial database library - - Copyright (C) Andrew Tridgell 1999-2004 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* flags to tdb_store() */ -#define TDB_REPLACE 1 -#define TDB_INSERT 2 -#define TDB_MODIFY 3 - -/* flags for tdb_open() */ -#define TDB_DEFAULT 0 /* just a readability place holder */ -#define TDB_CLEAR_IF_FIRST 1 -#define TDB_INTERNAL 2 /* don't store on disk */ -#define TDB_NOLOCK 4 /* don't do any locking */ -#define TDB_NOMMAP 8 /* don't use mmap */ -#define TDB_CONVERT 16 /* convert endian (internal use) */ -#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ - -#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) - -/* error codes */ -enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, - TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, - TDB_ERR_NOEXIST}; - -#ifndef u32 -#define u32 unsigned -#endif - -typedef struct TDB_DATA { - char *dptr; - size_t dsize; -} TDB_DATA; - -typedef u32 tdb_len; -typedef u32 tdb_off; - -/* this is stored at the front of every database */ -struct tdb_header { - char magic_food[32]; /* for /etc/magic */ - u32 version; /* version of the code */ - u32 hash_size; /* number of hash entries */ - tdb_off rwlocks; - tdb_off reserved[31]; -}; - -struct tdb_lock_type { - u32 count; - u32 ltype; -}; - -struct tdb_traverse_lock { - struct tdb_traverse_lock *next; - u32 off; - u32 hash; -}; - -/* this is the context structure that is returned from a db open */ -typedef struct tdb_context { - char *name; /* the name of the database */ - void *map_ptr; /* where it is currently mapped */ - int fd; /* open file descriptor for the database */ - tdb_len map_size; /* how much space has been mapped */ - int read_only; /* opened read-only */ - struct tdb_lock_type *locked; /* array of chain locks */ - enum TDB_ERROR ecode; /* error code for last tdb error */ - struct tdb_header header; /* a cached copy of the header */ - u32 flags; /* the flags passed to tdb_open */ - u32 *lockedkeys; /* array of locked keys: first is #keys */ - struct tdb_traverse_lock travlocks; /* current traversal locks */ - struct tdb_context *next; /* all tdbs to avoid multiple opens */ - dev_t device; /* uniquely identifies this tdb */ - ino_t inode; /* uniquely identifies this tdb */ - void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ - int open_flags; /* flags used in the open - needed by reopen */ -} TDB_CONTEXT; - -void tdb_debug(TDB_CONTEXT *, int , const char *, ...); - -typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); -typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); - -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode); -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn); - -int tdb_reopen(TDB_CONTEXT *tdb); -int tdb_reopen_all(void); -void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); -const char *tdb_errorstr(TDB_CONTEXT *tdb); -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); -int tdb_close(TDB_CONTEXT *tdb); -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); -void tdb_unlockkeys(TDB_CONTEXT *tdb); -int tdb_lockall(TDB_CONTEXT *tdb); -void tdb_unlockall(TDB_CONTEXT *tdb); - -/* Low level locking functions: use with care */ -void tdb_set_lock_alarm(sig_atomic_t *palarm); -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); - -/* Debug functions. Not used in production. */ -void tdb_dump_all(TDB_CONTEXT *tdb); -int tdb_printfreelist(TDB_CONTEXT *tdb); - -extern TDB_DATA tdb_null; - -#ifdef __cplusplus -} -#endif - -#endif /* tdb.h */ diff --git a/source4/lib/tdb/tdb.magic b/source4/lib/tdb/tdb.magic deleted file mode 100644 index f5619e7327..0000000000 --- a/source4/lib/tdb/tdb.magic +++ /dev/null @@ -1,10 +0,0 @@ -# Magic file(1) information about tdb files. -# -# Install this into /etc/magic or the corresponding location for your -# system, or pass as a -m argument to file(1). - -# You may use and redistribute this file without restriction. - -0 string TDB\ file TDB database ->32 lelong =0x2601196D version 6, little-endian ->>36 lelong x hash size %d bytes diff --git a/source4/lib/tdb/tdbutil.c b/source4/lib/tdb/tdbutil.c deleted file mode 100644 index 62841ddfc2..0000000000 --- a/source4/lib/tdb/tdbutil.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - Unix SMB/CIFS implementation. - tdb utility functions - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include - -/* these are little tdb utility functions that are meant to make - dealing with a tdb database a little less cumbersome in Samba */ - -static sig_atomic_t gotalarm; - -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - - -/******************************************************************* - THIS is a copy of the function CatchSignal found in lib/signal.c - I need to copy it there to avoid sucking all of the samba source - into tdb. - - Catch a signal. This should implement the following semantics: - - 1) The handler remains installed after being called. - 2) The signal should be blocked during handler execution. -********************************************************************/ - -static void (*TdbCatchSignal(int signum,void (*handler)(int )))(int) -{ -#ifdef HAVE_SIGACTION - struct sigaction act; - struct sigaction oldact; - - ZERO_STRUCT(act); - - act.sa_handler = handler; -#ifdef SA_RESTART - /* - * We *want* SIGALRM to interrupt a system call. - */ - if(signum != SIGALRM) - act.sa_flags = SA_RESTART; -#endif - sigemptyset(&act.sa_mask); - sigaddset(&act.sa_mask,signum); - sigaction(signum,&act,&oldact); - return oldact.sa_handler; -#else /* !HAVE_SIGACTION */ - /* FIXME: need to handle sigvec and systems with broken signal() */ - return signal(signum, handler); -#endif -} - - - -/*************************************************************** - Make a TDB_DATA and keep the const warning in one place -****************************************************************/ - -static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) -{ - TDB_DATA ret; - ret.dptr = dptr; - ret.dsize = dsize; - return ret; -} - -/**************************************************************************** - Lock a chain with timeout (in seconds). -****************************************************************************/ - -static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) -{ - /* Allow tdb_chainlock to be interrupted by an alarm. */ - int ret; - gotalarm = 0; - tdb_set_lock_alarm(&gotalarm); - - if (timeout) { - TdbCatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(timeout); - } - - if (rw_type == F_RDLCK) - ret = tdb_chainlock_read(tdb, key); - else - ret = tdb_chainlock(tdb, key); - - if (timeout) { - alarm(0); - TdbCatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); - if (gotalarm) { - tdb_debug(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", - timeout, key.dptr, tdb->name ); - /* TODO: If we time out waiting for a lock, it might - * be nice to use F_GETLK to get the pid of the - * process currently holding the lock and print that - * as part of the debugging message. -- mbp */ - return -1; - } - } - - return ret; -} - -/**************************************************************************** - Write lock a chain. Return -1 if timeout or lock failed. -****************************************************************************/ - -int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) -{ - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); -} - -/**************************************************************************** - Lock a chain by string. Return -1 if timeout or lock failed. -****************************************************************************/ - -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); -} - -/**************************************************************************** - Unlock a chain by string. -****************************************************************************/ - -void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - tdb_chainunlock(tdb, key); -} - -/**************************************************************************** - Read lock a chain by string. Return -1 if timeout or lock failed. -****************************************************************************/ - -int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); -} - -/**************************************************************************** - Read unlock a chain by string. -****************************************************************************/ - -void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - tdb_chainunlock_read(tdb, key); -} - - -/**************************************************************************** - Fetch a int32 value by a arbitrary blob key, return -1 if not found. - Output is int32 in native byte order. -****************************************************************************/ - -int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) -{ - TDB_DATA key = make_tdb_data(keyval, len); - TDB_DATA data; - int32 ret; - - data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(int32)) { - SAFE_FREE(data.dptr); - return -1; - } - - ret = IVAL(data.dptr,0); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Fetch a int32 value by string key, return -1 if not found. - Output is int32 in native byte order. -****************************************************************************/ - -int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) -{ - return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); -} - -/**************************************************************************** - Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. - Input is int32 in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) -{ - TDB_DATA key = make_tdb_data(keystr, len); - TDB_DATA data; - int32 v_store; - - SIVAL(&v_store,0,v); - data.dptr = (void *)&v_store; - data.dsize = sizeof(int32); - - return tdb_store(tdb, key, data, TDB_REPLACE); -} - -/**************************************************************************** - Store a int32 value by string key, return 0 on success, -1 on failure. - Input is int32 in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) -{ - return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); -} - -/**************************************************************************** - Fetch a uint32 value by a arbitrary blob key, return -1 if not found. - Output is uint32 in native byte order. -****************************************************************************/ - -BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) -{ - TDB_DATA key = make_tdb_data(keyval, len); - TDB_DATA data; - - data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(uint32)) { - SAFE_FREE(data.dptr); - return False; - } - - *value = IVAL(data.dptr,0); - SAFE_FREE(data.dptr); - return True; -} - -/**************************************************************************** - Fetch a uint32 value by string key, return -1 if not found. - Output is uint32 in native byte order. -****************************************************************************/ - -BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) -{ - return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); -} - -/**************************************************************************** - Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. - Input is uint32 in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) -{ - TDB_DATA key = make_tdb_data(keystr, len); - TDB_DATA data; - uint32 v_store; - BOOL ret = True; - - SIVAL(&v_store, 0, value); - data.dptr = (void *)&v_store; - data.dsize = sizeof(uint32); - - if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) - ret = False; - - return ret; -} - -/**************************************************************************** - Store a uint32 value by string key, return 0 on success, -1 on failure. - Input is uint32 in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) -{ - return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); -} -/**************************************************************************** - Store a buffer by a null terminated string key. Return 0 on success, -1 - on failure. -****************************************************************************/ - -int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_store(tdb, key, data, flags); -} - -/**************************************************************************** - Fetch a buffer using a null terminated string key. Don't forget to call - free() on the result dptr. -****************************************************************************/ - -TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_fetch(tdb, key); -} - -/**************************************************************************** - Delete an entry using a null terminated string key. -****************************************************************************/ - -int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_delete(tdb, key); -} - -/**************************************************************************** - Atomic integer change. Returns old value. To create, set initial value in *oldval. -****************************************************************************/ - -int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) -{ - int32 val; - int32 ret = -1; - - if (tdb_lock_bystring(tdb, keystr,0) == -1) - return -1; - - if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { - /* The lookup failed */ - if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* but not because it didn't exist */ - goto err_out; - } - - /* Start with 'old' value */ - val = *oldval; - - } else { - /* It worked, set return value (oldval) to tdb data */ - *oldval = val; - } - - /* Increment value for storage and return next time */ - val += change_val; - - if (tdb_store_int32(tdb, keystr, val) == -1) - goto err_out; - - ret = 0; - - err_out: - - tdb_unlock_bystring(tdb, keystr); - return ret; -} - -/**************************************************************************** - Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. -****************************************************************************/ - -BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) -{ - uint32 val; - BOOL ret = False; - - if (tdb_lock_bystring(tdb, keystr,0) == -1) - return False; - - if (!tdb_fetch_uint32(tdb, keystr, &val)) { - /* It failed */ - if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* and not because it didn't exist */ - goto err_out; - } - - /* Start with 'old' value */ - val = *oldval; - - } else { - /* it worked, set return value (oldval) to tdb data */ - *oldval = val; - - } - - /* get a new value to store */ - val += change_val; - - if (!tdb_store_uint32(tdb, keystr, val)) - goto err_out; - - ret = True; - - err_out: - - tdb_unlock_bystring(tdb, keystr); - return ret; -} - -/**************************************************************************** - Useful pair of routines for packing/unpacking data consisting of - integers and strings. -****************************************************************************/ - -size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) -{ - va_list ap; - uint8 bt; - uint16 w; - uint32 d; - int i; - void *p; - int len; - char *s; - char c; - char *buf0 = buf; - const char *fmt0 = fmt; - int bufsize0 = bufsize; - - va_start(ap, fmt); - - while (*fmt) { - switch ((c = *fmt++)) { - case 'b': /* unsigned 8-bit integer */ - len = 1; - bt = (uint8)va_arg(ap, int); - if (bufsize && bufsize >= len) - SSVAL(buf, 0, bt); - break; - case 'w': /* unsigned 16-bit integer */ - len = 2; - w = (uint16)va_arg(ap, int); - if (bufsize && bufsize >= len) - SSVAL(buf, 0, w); - break; - case 'd': /* signed 32-bit integer (standard int in most systems) */ - len = 4; - d = va_arg(ap, uint32); - if (bufsize && bufsize >= len) - SIVAL(buf, 0, d); - break; - case 'p': /* pointer */ - len = 4; - p = va_arg(ap, void *); - d = p?1:0; - if (bufsize && bufsize >= len) - SIVAL(buf, 0, d); - break; - case 'P': /* null-terminated string */ - s = va_arg(ap,char *); - w = strlen(s); - len = w + 1; - if (bufsize && bufsize >= len) - memcpy(buf, s, len); - break; - case 'f': /* null-terminated string */ - s = va_arg(ap,char *); - w = strlen(s); - len = w + 1; - if (bufsize && bufsize >= len) - memcpy(buf, s, len); - break; - case 'B': /* fixed-length string */ - i = va_arg(ap, int); - s = va_arg(ap, char *); - len = 4+i; - if (bufsize && bufsize >= len) { - SIVAL(buf, 0, i); - memcpy(buf+4, s, i); - } - break; - default: - tdb_debug(tdb, 0,"Unknown tdb_pack format %c in %s\n", - c, fmt); - len = 0; - break; - } - - buf += len; - if (bufsize) - bufsize -= len; - if (bufsize < 0) - bufsize = 0; - } - - va_end(ap); - - tdb_debug(tdb, 18,"tdb_pack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); - - return PTR_DIFF(buf, buf0); -} - -/**************************************************************************** - Useful pair of routines for packing/unpacking data consisting of - integers and strings. -****************************************************************************/ - -int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) -{ - va_list ap; - uint8 *bt; - uint16 *w; - uint32 *d; - int len; - int *i; - void **p; - char *s, **b; - char c; - char *buf0 = buf; - const char *fmt0 = fmt; - int bufsize0 = bufsize; - - va_start(ap, fmt); - - while (*fmt) { - switch ((c=*fmt++)) { - case 'b': - len = 1; - bt = va_arg(ap, uint8 *); - if (bufsize < len) - goto no_space; - *bt = SVAL(buf, 0); - break; - case 'w': - len = 2; - w = va_arg(ap, uint16 *); - if (bufsize < len) - goto no_space; - *w = SVAL(buf, 0); - break; - case 'd': - len = 4; - d = va_arg(ap, uint32 *); - if (bufsize < len) - goto no_space; - *d = IVAL(buf, 0); - break; - case 'p': - len = 4; - p = va_arg(ap, void **); - if (bufsize < len) - goto no_space; - *p = (void *)IVAL(buf, 0); - break; - case 'P': - s = va_arg(ap,char *); - len = strlen(buf) + 1; - if (bufsize < len || len > sizeof(pstring)) - goto no_space; - memcpy(s, buf, len); - break; - case 'f': - s = va_arg(ap,char *); - len = strlen(buf) + 1; - if (bufsize < len || len > sizeof(fstring)) - goto no_space; - memcpy(s, buf, len); - break; - case 'B': - i = va_arg(ap, int *); - b = va_arg(ap, char **); - len = 4; - if (bufsize < len) - goto no_space; - *i = IVAL(buf, 0); - if (! *i) { - *b = NULL; - break; - } - len += *i; - if (bufsize < len) - goto no_space; - *b = (char *)malloc(*i); - if (! *b) - goto no_space; - memcpy(*b, buf+4, *i); - break; - default: - tdb_debug(tdb, 0, "Unknown tdb_unpack format %c in %s\n", - c, fmt); - - len = 0; - break; - } - - buf += len; - bufsize -= len; - } - - va_end(ap); - - tdb_debug(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); - - return PTR_DIFF(buf, buf0); - - no_space: - return -1; -} - -/**************************************************************************** - Print out debug messages. -****************************************************************************/ - -void tdb_debug(TDB_CONTEXT *tdb, int level, const char *fmt, ...) -{ - va_list ap; - if (tdb->log_fn == NULL) { - return; - } - va_start(ap, fmt); - tdb->log_fn(tdb, level, fmt, ap); - va_end(ap); -} - - -/**************************************************************************** - Allow tdb_delete to be used as a tdb_traversal_fn. -****************************************************************************/ - -int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) -{ - return tdb_delete(the_tdb, key); -} - - - -/** - * Search across the whole tdb for keys that match the given pattern - * return the result as a list of keys - * - * @param tdb pointer to opened tdb file context - * @param pattern searching pattern used by fnmatch(3) functions - * - * @return list of keys found by looking up with given pattern - **/ -TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) -{ - TDB_DATA key, next; - TDB_LIST_NODE *list = NULL; - TDB_LIST_NODE *rec = NULL; - - for (key = tdb_firstkey(tdb); key.dptr; key = next) { - /* duplicate key string to ensure null-termination */ - char *key_str = (char*) strndup(key.dptr, key.dsize); -#if 0 - if (!key_str) { - tdb_debug(tdb, 0, "tdb_search_keys: strndup() failed!\n"); - smb_panic("strndup failed!\n"); - } -#endif - tdb_debug(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); - - next = tdb_nextkey(tdb, key); - - /* do the pattern checking */ - if (fnmatch(pattern, key_str, 0) == 0) { - rec = (TDB_LIST_NODE*) malloc(sizeof(*rec)); - ZERO_STRUCTP(rec); - - rec->node_key = key; - - DLIST_ADD_END(list, rec, TDB_LIST_NODE *); - - tdb_debug(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); - } else { - free(key.dptr); - } - - /* free duplicated key string */ - free(key_str); - } - - return list; - -} - - -/** - * Free the list returned by tdb_search_keys - * - * @param node list of results found by tdb_search_keys - **/ -void tdb_search_list_free(TDB_LIST_NODE* node) -{ - TDB_LIST_NODE *next_node; - - while (node) { - next_node = node->next; - SAFE_FREE(node->node_key.dptr); - SAFE_FREE(node); - node = next_node; - } -} diff --git a/source4/lib/tdb/tdbutil.h b/source4/lib/tdb/tdbutil.h deleted file mode 100644 index 01473446a1..0000000000 --- a/source4/lib/tdb/tdbutil.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Unix SMB/CIFS implementation. - tdb utility functions - Copyright (C) Andrew Tridgell 1999 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef __TDBUTIL_H__ -#define __TDBUTIL_H__ - - -/* single node of a list returned by tdb_search_keys */ -typedef struct keys_node -{ - struct keys_node *prev, *next; - TDB_DATA node_key; -} TDB_LIST_NODE; - - -TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); -void tdb_search_list_free(TDB_LIST_NODE*); - - -#endif /* __TDBUTIL_H__ */ diff --git a/source4/lib/tdb/tools/Makefile b/source4/lib/tdb/tools/Makefile new file mode 100644 index 0000000000..59fbb079bd --- /dev/null +++ b/source4/lib/tdb/tools/Makefile @@ -0,0 +1,29 @@ +# +# Makefile for tdb directory +# + +CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1 +CC = gcc + +PROGS = tdbtest tdbtool tdbtorture +TDB_OBJ = tdb.o spinlock.o + +default: $(PROGS) + +tdbtest: tdbtest.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtest tdbtest.o $(TDB_OBJ) -lgdbm + +tdbtool: tdbtool.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtool tdbtool.o $(TDB_OBJ) + +tdbtorture: tdbtorture.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtorture tdbtorture.o $(TDB_OBJ) + +tdbdump: tdbdump.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbdump tdbdump.o $(TDB_OBJ) + +tdbbackup: tdbbackup.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbbackup tdbbackup.o $(TDB_OBJ) + +clean: + rm -f $(PROGS) *.o *~ *% core test.db test.tdb test.gdbm diff --git a/source4/lib/tdb/tools/tdbbackup.c b/source4/lib/tdb/tools/tdbbackup.c new file mode 100644 index 0000000000..1a0e1c1588 --- /dev/null +++ b/source4/lib/tdb/tools/tdbbackup.c @@ -0,0 +1,149 @@ +/* + Unix SMB/CIFS implementation. + low level tdb backup and restore utility + Copyright (C) Andrew Tridgell 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + + This program is meant for backup/restore of tdb databases. Typical usage would be: + tdbbackup *.tdb + when Samba shuts down cleanly, which will make a backup of all the local databases + to *.bak files. Then on Samba startup you would use: + tdbbackup -v *.tdb + and this will check the databases for corruption and if corruption is detected then + the backup will be restored. + + You may also like to do a backup on a regular basis while Samba is + running, perhaps using cron. + + The reason this program is needed is to cope with power failures + while Samba is running. A power failure could lead to database + corruption and Samba will then not start correctly. + + Note that many of the databases in Samba are transient and thus + don't need to be backed up, so you can optimise the above a little + by only running the backup on the critical databases. + + */ + +#ifdef STANDALONE +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include "includes.h" + +#endif + +#include "tdb.h" +#include "tdbback.h" + +/* + see if one file is newer than another +*/ +static int file_newer(const char *fname1, const char *fname2) +{ + struct stat st1, st2; + if (stat(fname1, &st1) != 0) { + return 0; + } + if (stat(fname2, &st2) != 0) { + return 1; + } + return (st1.st_mtime > st2.st_mtime); +} + +static void usage(void) +{ + printf("Usage: tdbbackup [options] \n\n"); + printf(" -h this help message\n"); + printf(" -s suffix set the backup suffix\n"); + printf(" -v verify mode (restore if corrupt)\n"); +} + + + int main(int argc, char *argv[]) +{ + int i; + int ret = 0; + int c; + int verify = 0; + const char *suffix = ".bak"; + extern int optind; + extern char *optarg; + + while ((c = getopt(argc, argv, "vhs:")) != -1) { + switch (c) { + case 'h': + usage(); + exit(0); + case 'v': + verify = 1; + break; + case 's': + suffix = optarg; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + usage(); + exit(1); + } + + for (i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" + +static void print_data(TDB_DATA d) +{ + unsigned char *p = d.dptr; + int len = d.dsize; + while (len--) { + if (isprint(*p) && !strchr("\"\\", *p)) { + fputc(*p, stdout); + } else { + printf("\\%02X", *p); + } + p++; + } +} + +static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + printf("{\n"); + printf("key = \""); + print_data(key); + printf("\"\n"); + printf("data = \""); + print_data(dbuf); + printf("\"\n"); + printf("}\n"); + return 0; +} + +static int dump_tdb(const char *fname) +{ + TDB_CONTEXT *tdb; + + tdb = tdb_open(fname, 0, 0, O_RDONLY, 0); + if (!tdb) { + printf("Failed to open %s\n", fname); + return 1; + } + + tdb_traverse(tdb, traverse_fn, NULL); + return 0; +} + + int main(int argc, char *argv[]) +{ + char *fname; + + if (argc < 2) { + printf("Usage: tdbdump \n"); + exit(1); + } + + fname = argv[1]; + + return dump_tdb(fname); +} diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c new file mode 100644 index 0000000000..89295a3291 --- /dev/null +++ b/source4/lib/tdb/tools/tdbtest.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" +#include + +/* a test program for tdb - the trivial database */ + + + +#define DELETE_PROB 7 +#define STORE_PROB 5 + +static TDB_CONTEXT *db; +static GDBM_FILE gdbm; + +struct timeval tp1,tp2; + +static void start_timer(void) +{ + gettimeofday(&tp1,NULL); +} + +static double end_timer(void) +{ + gettimeofday(&tp2,NULL); + return((tp2.tv_sec - tp1.tv_sec) + + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); +} + +static void fatal(char *why) +{ + perror(why); + exit(1); +} + +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +} + +static void compare_db(void) +{ + TDB_DATA d, key, nextkey; + datum gd, gkey, gnextkey; + + key = tdb_firstkey(db); + while (key.dptr) { + d = tdb_fetch(db, key); + gkey.dptr = key.dptr; + gkey.dsize = key.dsize; + + gd = gdbm_fetch(gdbm, gkey); + + if (!gd.dptr) fatal("key not in gdbm"); + if (gd.dsize != d.dsize) fatal("data sizes differ"); + if (memcmp(gd.dptr, d.dptr, d.dsize)) { + fatal("data differs"); + } + + nextkey = tdb_nextkey(db, key); + free(key.dptr); + free(d.dptr); + free(gd.dptr); + key = nextkey; + } + + gkey = gdbm_firstkey(gdbm); + while (gkey.dptr) { + gd = gdbm_fetch(gdbm, gkey); + key.dptr = gkey.dptr; + key.dsize = gkey.dsize; + + d = tdb_fetch(db, key); + + if (!d.dptr) fatal("key not in db"); + if (d.dsize != gd.dsize) fatal("data sizes differ"); + if (memcmp(d.dptr, gd.dptr, gd.dsize)) { + fatal("data differs"); + } + + gnextkey = gdbm_nextkey(gdbm, gkey); + free(gkey.dptr); + free(gd.dptr); + free(d.dptr); + gkey = gnextkey; + } +} + +static char *randbuf(int len) +{ + char *buf; + int i; + buf = (char *)malloc(len+1); + + for (i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" + +/* a tdb tool for manipulating a tdb database */ + +#define FSTRING_LEN 256 +typedef char fstring[FSTRING_LEN]; + +typedef struct connections_key { + pid_t pid; + int cnum; + fstring name; +} connections_key; + +typedef struct connections_data { + int magic; + pid_t pid; + int cnum; + uid_t uid; + gid_t gid; + char name[24]; + char addr[24]; + char machine[128]; + time_t start; +} connections_data; + +static TDB_CONTEXT *tdb; + +static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); + +static void print_asc(unsigned char *buf,int len) +{ + int i; + + /* We're probably printing ASCII strings so don't try to display + the trailing NULL character. */ + + if (buf[len - 1] == 0) + len--; + + for (i=0;i8) printf(" "); + while (n--) printf(" "); + + n = i%16; + if (n > 8) n = 8; + print_asc(&buf[i-(i%16)],n); printf(" "); + n = (i%16) - n; + if (n>0) print_asc(&buf[i-n],n); + printf("\n"); + } +} + +static void help(void) +{ + printf("\n" +"tdbtool: \n" +" create dbname : create a database\n" +" open dbname : open an existing database\n" +" erase : erase the database\n" +" dump : dump the database as strings\n" +" insert key data : insert a record\n" +" move key file : move a record to a destination tdb\n" +" store key data : store a record (replace)\n" +" show key : show a record by key\n" +" delete key : delete a record by key\n" +" list : print the database hash table and freelist\n" +" free : print the database freelist\n" +" 1 | first : print the first record\n" +" n | next : print the next record\n" +" q | quit : terminate\n" +" \\n : repeat 'next' command\n" +"\n"); +} + +static void terror(char *why) +{ + printf("%s\n", why); +} + +static char *get_token(int startover) +{ + static char tmp[1024]; + static char *cont = NULL; + char *insert, *start; + char *k = strtok(NULL, " "); + + if (!k) + return NULL; + + if (startover) + start = tmp; + else + start = cont; + + strcpy(start, k); + insert = start + strlen(start) - 1; + while (*insert == '\\') { + *insert++ = ' '; + k = strtok(NULL, " "); + if (!k) + break; + strcpy(insert, k); + insert = start + strlen(start) - 1; + } + + /* Get ready for next call */ + cont = start + strlen(start) + 1; + return start; +} + +static void create_tdb(void) +{ + char *tok = get_token(1); + if (!tok) { + help(); + return; + } + if (tdb) tdb_close(tdb); + tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT | O_TRUNC, 0600); + if (!tdb) { + printf("Could not create %s: %s\n", tok, strerror(errno)); + } +} + +static void open_tdb(void) +{ + char *tok = get_token(1); + if (!tok) { + help(); + return; + } + if (tdb) tdb_close(tdb); + tdb = tdb_open(tok, 0, 0, O_RDWR, 0600); + if (!tdb) { + printf("Could not open %s: %s\n", tok, strerror(errno)); + } +} + +static void insert_tdb(void) +{ + char *k = get_token(1); + char *d = get_token(0); + TDB_DATA key, dbuf; + + if (!k || !d) { + help(); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + dbuf.dptr = d; + dbuf.dsize = strlen(d)+1; + + if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) { + terror("insert failed"); + } +} + +static void store_tdb(void) +{ + char *k = get_token(1); + char *d = get_token(0); + TDB_DATA key, dbuf; + + if (!k || !d) { + help(); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + dbuf.dptr = d; + dbuf.dsize = strlen(d)+1; + + printf("Storing key:\n"); + print_rec(tdb, key, dbuf, NULL); + + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { + terror("store failed"); + } +} + +static void show_tdb(void) +{ + char *k = get_token(1); + TDB_DATA key, dbuf; + + if (!k) { + help(); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + /* maybe it is non-NULL terminated key? */ + key.dsize = strlen(k); + dbuf = tdb_fetch(tdb, key); + + if ( !dbuf.dptr ) { + terror("fetch failed"); + return; + } + } + + /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */ + print_rec(tdb, key, dbuf, NULL); + + free( dbuf.dptr ); + + return; +} + +static void delete_tdb(void) +{ + char *k = get_token(1); + TDB_DATA key; + + if (!k) { + help(); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + + if (tdb_delete(tdb, key) != 0) { + terror("delete failed"); + } +} + +static void move_rec(void) +{ + char *k = get_token(1); + char *file = get_token(0); + TDB_DATA key, dbuf; + TDB_CONTEXT *dst_tdb; + + if (!k) { + help(); + return; + } + + if ( !file ) { + terror("need destination tdb name"); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + /* maybe it is non-NULL terminated key? */ + key.dsize = strlen(k); + dbuf = tdb_fetch(tdb, key); + + if ( !dbuf.dptr ) { + terror("fetch failed"); + return; + } + } + + print_rec(tdb, key, dbuf, NULL); + + dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600); + if ( !dst_tdb ) { + terror("unable to open destination tdb"); + return; + } + + if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) { + terror("failed to move record"); + } + else + printf("record moved\n"); + + tdb_close( dst_tdb ); + + return; +} + +#if 0 +static int print_conn_key(TDB_DATA key) +{ + printf( "pid =%5d ", ((connections_key*)key.dptr)->pid); + printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum); + printf( "name =[%s]\n", ((connections_key*)key.dptr)->name); + return 0; +} + +static int print_conn_data(TDB_DATA dbuf) +{ + printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid); + printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum); + printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->name); + + printf( "uid =%5d ", ((connections_data*)dbuf.dptr)->uid); + printf( "addr =[%s]\n", ((connections_data*)dbuf.dptr)->addr); + printf( "gid =%5d ", ((connections_data*)dbuf.dptr)->gid); + printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine); + printf( "start = %s\n", ctime(&((connections_data*)dbuf.dptr)->start)); + return 0; +} +#endif + +static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ +#if 0 + print_conn_key(key); + print_conn_data(dbuf); + return 0; +#else + printf("\nkey %d bytes\n", key.dsize); + print_asc(key.dptr, key.dsize); + printf("\ndata %d bytes\n", dbuf.dsize); + print_data(dbuf.dptr, dbuf.dsize); + return 0; +#endif +} + +static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + print_asc(key.dptr, key.dsize); + printf("\n"); + return 0; +} + +static int total_bytes; + +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + total_bytes += dbuf.dsize; + return 0; +} + +static void info_tdb(void) +{ + int count; + total_bytes = 0; + if ((count = tdb_traverse(tdb, traverse_fn, NULL) == -1)) + printf("Error = %s\n", tdb_errorstr(tdb)); + else + printf("%d records totalling %d bytes\n", count, total_bytes); +} + +static char *tdb_getline(char *prompt) +{ + static char line[1024]; + char *p; + fputs(prompt, stdout); + line[0] = 0; + p = fgets(line, sizeof(line)-1, stdin); + if (p) p = strchr(p, '\n'); + if (p) *p = 0; + return p?line:NULL; +} + +static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + +static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +{ + TDB_DATA dbuf; + *pkey = tdb_firstkey(the_tdb); + + dbuf = tdb_fetch(the_tdb, *pkey); + if (!dbuf.dptr) terror("fetch failed"); + else { + /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */ + print_rec(the_tdb, *pkey, dbuf, NULL); + } +} + +static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +{ + TDB_DATA dbuf; + *pkey = tdb_nextkey(the_tdb, *pkey); + + dbuf = tdb_fetch(the_tdb, *pkey); + if (!dbuf.dptr) + terror("fetch failed"); + else + /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */ + print_rec(the_tdb, *pkey, dbuf, NULL); +} + +int main(int argc, char *argv[]) +{ + int bIterate = 0; + char *line; + char *tok; + TDB_DATA iterate_kbuf; + + if (argv[1]) { + static char tmp[1024]; + sprintf(tmp, "open %s", argv[1]); + tok=strtok(tmp," "); + open_tdb(); + } + + while ((line = tdb_getline("tdb> "))) { + + /* Shell command */ + + if (line[0] == '!') { + system(line + 1); + continue; + } + + if ((tok = strtok(line," "))==NULL) { + if (bIterate) + next_record(tdb, &iterate_kbuf); + continue; + } + if (strcmp(tok,"create") == 0) { + bIterate = 0; + create_tdb(); + continue; + } else if (strcmp(tok,"open") == 0) { + open_tdb(); + continue; + } else if ((strcmp(tok, "q") == 0) || + (strcmp(tok, "quit") == 0)) { + break; + } + + /* all the rest require a open database */ + if (!tdb) { + bIterate = 0; + terror("database not open"); + help(); + continue; + } + + if (strcmp(tok,"insert") == 0) { + bIterate = 0; + insert_tdb(); + } else if (strcmp(tok,"store") == 0) { + bIterate = 0; + store_tdb(); + } else if (strcmp(tok,"show") == 0) { + bIterate = 0; + show_tdb(); + } else if (strcmp(tok,"erase") == 0) { + bIterate = 0; + tdb_traverse(tdb, do_delete_fn, NULL); + } else if (strcmp(tok,"delete") == 0) { + bIterate = 0; + delete_tdb(); + } else if (strcmp(tok,"dump") == 0) { + bIterate = 0; + tdb_traverse(tdb, print_rec, NULL); + } else if (strcmp(tok,"move") == 0) { + bIterate = 0; + move_rec(); + } else if (strcmp(tok,"list") == 0) { + tdb_dump_all(tdb); + } else if (strcmp(tok, "free") == 0) { + tdb_printfreelist(tdb); + } else if (strcmp(tok,"info") == 0) { + info_tdb(); + } else if ( (strcmp(tok, "1") == 0) || + (strcmp(tok, "first") == 0)) { + bIterate = 1; + first_record(tdb, &iterate_kbuf); + } else if ((strcmp(tok, "n") == 0) || + (strcmp(tok, "next") == 0)) { + next_record(tdb, &iterate_kbuf); + } else if ((strcmp(tok, "keys") == 0)) { + bIterate = 0; + tdb_traverse(tdb, print_key, NULL); + } else { + help(); + } + } + + if (tdb) tdb_close(tdb); + + return 0; +} diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c new file mode 100644 index 0000000000..3f704e537e --- /dev/null +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -0,0 +1,227 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" + +/* this tests tdb by doing lots of ops from several simultaneous + writers - that stresses the locking code. Build with TDB_DEBUG=1 + for best effect */ + + + +#define REOPEN_PROB 30 +#define DELETE_PROB 8 +#define STORE_PROB 4 +#define APPEND_PROB 6 +#define LOCKSTORE_PROB 0 +#define TRAVERSE_PROB 20 +#define CULL_PROB 100 +#define KEYLEN 3 +#define DATALEN 100 +#define LOCKLEN 20 + +static TDB_CONTEXT *db; + +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +#if 0 + { + char *ptr; + asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid()); + system(ptr); + free(ptr); + } +#endif +} + +static void fatal(char *why) +{ + perror(why); + exit(1); +} + +static char *randbuf(int len) +{ + char *buf; + int i; + buf = (char *)malloc(len+1); + + for (i=0;i Date: Mon, 24 May 2004 16:39:19 +0000 Subject: r849: move tdb/tools/Makefile to tdb/Makefile.tdb like in ldb also fix the makefile to let it compile the tools fine metze (This used to be commit e3191b54ea583913a9fd21eeb4e57d82e996c847) --- source4/lib/tdb/Makefile.tdb | 29 +++++++++++++++++++++++++++++ source4/lib/tdb/tools/Makefile | 29 ----------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 source4/lib/tdb/Makefile.tdb delete mode 100644 source4/lib/tdb/tools/Makefile (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.tdb b/source4/lib/tdb/Makefile.tdb new file mode 100644 index 0000000000..db697e9379 --- /dev/null +++ b/source4/lib/tdb/Makefile.tdb @@ -0,0 +1,29 @@ +# +# Makefile for tdb directory +# + +CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1 -Iinclude +CC = gcc + +PROGS = bin/tdbtest bin/tdbtool bin/tdbtorture +TDB_OBJ = common/tdb.o common/spinlock.o + +default: $(PROGS) + +bin/tdbtest: tools/tdbtest.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm + +bin/tdbtool: tools/tdbtool.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtool tools/tdbtool.o $(TDB_OBJ) + +bin/tdbtorture: tools/tdbtorture.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbtorture tools/tdbtorture.o $(TDB_OBJ) + +bin/tdbdump: tools/tdbdump.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbdump tools/tdbdump.o $(TDB_OBJ) + +bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o tdbbackup tools/tdbbackup.o $(TDB_OBJ) + +clean: + rm -f $(PROGS) common/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm diff --git a/source4/lib/tdb/tools/Makefile b/source4/lib/tdb/tools/Makefile deleted file mode 100644 index 59fbb079bd..0000000000 --- a/source4/lib/tdb/tools/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# -# Makefile for tdb directory -# - -CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1 -CC = gcc - -PROGS = tdbtest tdbtool tdbtorture -TDB_OBJ = tdb.o spinlock.o - -default: $(PROGS) - -tdbtest: tdbtest.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtest tdbtest.o $(TDB_OBJ) -lgdbm - -tdbtool: tdbtool.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtool tdbtool.o $(TDB_OBJ) - -tdbtorture: tdbtorture.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtorture tdbtorture.o $(TDB_OBJ) - -tdbdump: tdbdump.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbdump tdbdump.o $(TDB_OBJ) - -tdbbackup: tdbbackup.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbbackup tdbbackup.o $(TDB_OBJ) - -clean: - rm -f $(PROGS) *.o *~ *% core test.db test.tdb test.gdbm -- cgit From d17ca56aed836b5cf0725e7c74f34ecbf5dcdab3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 17:18:00 +0000 Subject: r851: convert lib/registry/ to a config.mk file metze (This used to be commit b5567601464a649374e0ef280661292322b3334c) --- source4/lib/registry/config.m4 | 32 +++++----- source4/lib/registry/config.mk | 132 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 17 deletions(-) create mode 100644 source4/lib/registry/config.mk (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 77508063fc..331b9c2df1 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -22,25 +22,23 @@ if test t$SMB_EXT_LIB_ENABLE_gtk = tYES; then SMB_BINARY_ENABLE(gregedit, YES) fi -SMB_MODULE(registry_nt4, REGISTRY, STATIC, lib/registry/reg_backend_nt4/reg_backend_nt4.o) -SMB_MODULE(registry_w95, REGISTRY, STATIC, lib/registry/reg_backend_w95/reg_backend_w95.o) -SMB_MODULE(registry_dir, REGISTRY, STATIC, lib/registry/reg_backend_dir/reg_backend_dir.o) -SMB_MODULE(registry_rpc, REGISTRY, STATIC, lib/registry/reg_backend_rpc/reg_backend_rpc.o,[],[],[LIBSMB]) -SMB_MODULE(registry_gconf, REGISTRY, STATIC, lib/registry/reg_backend_gconf/reg_backend_gconf.o, [], [gconf]) -SMB_MODULE(registry_ldb, REGISTRY, NOT, lib/registry/reg_backend_ldb/reg_backend_ldb.o,[],[],[LIBLDB]) -SMB_SUBSYSTEM(REGISTRY,lib/registry/common/reg_interface.o, - [lib/registry/common/reg_objects.o lib/registry/common/reg_util.o], - [], - [LIBBASIC]) - -SMB_BINARY(regdiff, [REG], [BIN], lib/registry/tools/regdiff.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -SMB_BINARY(regpatch, [REG], [BIN], lib/registry/tools/regpatch.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -SMB_BINARY(regshell, [REG], [BIN], lib/registry/tools/regshell.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -SMB_BINARY(regtree, [REG], [BIN], lib/registry/tools/regtree.o,[],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) -SMB_BINARY(gregedit, [REG], [BIN], lib/registry/tools/gregedit.o,[gtk],[CONFIG LIBBASIC LIBCMDLINE REGISTRY]) +SMB_MODULE_MK(registry_nt4, REGISTRY, STATIC, lib/registry/config.mk) +SMB_MODULE_MK(registry_w95, REGISTRY, STATIC, lib/registry/config.mk) +SMB_MODULE_MK(registry_dir, REGISTRY, STATIC, lib/registry/config.mk) +SMB_MODULE_MK(registry_rpc, REGISTRY, STATIC, lib/registry/config.mk) +SMB_MODULE_MK(registry_gconf, REGISTRY, STATIC, lib/registry/config.mk) +SMB_MODULE_MK(registry_ldb, REGISTRY, NOT, lib/registry/config.mk) + +SMB_SUBSYSTEM_MK(REGISTRY,lib/registry/config.mk) + +SMB_BINARY_MK(regdiff, lib/registry/config.mk) +SMB_BINARY_MK(regpatch, lib/registry/config.mk) +SMB_BINARY_MK(regshell, lib/registry/config.mk) +SMB_BINARY_MK(regtree, lib/registry/config.mk) +SMB_BINARY_MK(gregedit, lib/registry/config.mk) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libwinregistry, YES) fi -SMB_LIBRARY(libwinregistry, 0, 0, 1, , , REGISTRY) +SMB_LIBRARY_MK(libwinregistry, lib/registry/config.mk) diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk new file mode 100644 index 0000000000..fff5381e87 --- /dev/null +++ b/source4/lib/registry/config.mk @@ -0,0 +1,132 @@ +# Registry backends + +################################################ +# Start MODULE registry_nt4 +[MODULE::registry_nt4] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_nt4/reg_backend_nt4.o +# End MODULE registry_nt4 +################################################ + +################################################ +# Start MODULE registry_w95 +[MODULE::registry_w95] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_w95/reg_backend_w95.o +# End MODULE registry_w95 +################################################ + +################################################ +# Start MODULE registry_dir +[MODULE::registry_dir] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_dir/reg_backend_dir.o +# End MODULE registry_dir +################################################ + +################################################ +# Start MODULE registry_rpc +[MODULE::registry_rpc] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_rpc/reg_backend_rpc.o +REQUIRED_SUBSYSTEMS = \ + LIBSMB +# End MODULE registry_rpc +################################################ + +################################################ +# Start MODULE registry_gconf +[MODULE::registry_gconf] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_gconf/reg_backend_gconf.o +REQUIRED_LIBRARIES = \ + gconf +# End MODULE registry_gconf +################################################ + +################################################ +# Start MODULE registry_ldb +[MODULE::registry_ldb] +INIT_OBJ_FILES = \ + lib/registry/reg_backend_ldb/reg_backend_ldb.o +REQUIRED_SUBSYSTEMS = \ + LIBLDB +# End MODULE registry_ldb +################################################ + +################################################ +# Start SUBSYSTEM REGISTRY +[SUBSYSTEM::REGISTRY] +INIT_OBJ_FILES = \ + lib/registry/common/reg_interface.o +ADD_OBJ_FILES = \ + lib/registry/common/reg_objects.o \ + lib/registry/common/reg_util.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC +# End MODULE registry_ldb +################################################ + +################################################ +# Start LIBRARY libwinregistry +[LIBRARY::libwinregistry] +MAJOR_VERSION = 0 +MINOR_VERSION = 0 +RELEASE_VERSION = 1 +REQUIRED_SUBSYSTEMS = \ + REGISTRY +# +# End LIBRARY libwinregistry +################################################ + +################################################ +# Start BINARY regdiff +[BINARY::regdiff] +OBJ_FILES= \ + lib/registry/tools/regdiff.o +REQUIRED_SUBSYSTEMS = \ + CONFIG LIBCMDLINE REGISTRY +# End BINARY regdiff +################################################ + +################################################ +# Start BINARY regpatch +[BINARY::regpatch] +OBJ_FILES= \ + lib/registry/tools/regpatch.o +REQUIRED_SUBSYSTEMS = \ + CONFIG LIBCMDLINE REGISTRY +# End BINARY regpatch +################################################ + +################################################ +# Start BINARY regshell +[BINARY::regshell] +OBJ_FILES= \ + lib/registry/tools/regshell.o +REQUIRED_SUBSYSTEMS = \ + CONFIG LIBCMDLINE REGISTRY +# End BINARY regshell +################################################ + +################################################ +# Start BINARY regtree +[BINARY::regtree] +OBJ_FILES= \ + lib/registry/tools/regtree.o +REQUIRED_SUBSYSTEMS = \ + CONFIG LIBCMDLINE REGISTRY +# End BINARY regtree +################################################ + +################################################ +# Start BINARY gregedit +[BINARY::grepedit] +OBJ_FILES= \ + lib/registry/tools/gregedit.o +REQUIRED_LIBRARIES = \ + gtk +REQUIRED_SUBSYSTEMS = \ + CONFIG LIBCMDLINE REGISTRY +# End BINARY gregedit +################################################ -- cgit From 7fb1be73734915e027f86aca9ba62b86c56ca787 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 17:41:47 +0000 Subject: r853: remove a real big bunch of unused code I really think that this is needed to get a better overview of what is currently used Also this stuff is really out of date so if we really ever need some of this stuff back, a 'svn copy' from the SAMBA_3_0 branch should be no big problem... metze (This used to be commit 972598d511c64f29bdc849fe58c9c82fbcf6a4a2) --- source4/lib/basic.mk | 2 -- source4/lib/username.c | 83 +------------------------------------------------- 2 files changed, 1 insertion(+), 84 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 78acb5bb1c..55254498d9 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -43,8 +43,6 @@ ADD_OBJ_FILES = \ lib/tallocmsg.o \ lib/dmallocmsg.o \ lib/smbpasswd.o \ - nsswitch/wb_client.o \ - nsswitch/wb_common.o \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/account_pol.o \ diff --git a/source4/lib/username.c b/source4/lib/username.c index 3af9dbd027..2d9d212858 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -168,82 +168,6 @@ struct passwd *Get_Pwnam(const char *user) return ret; } -/**************************************************************************** - Check if a user is in a winbind group. -****************************************************************************/ - -static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered) -{ - int num_groups; - int i; - gid_t *groups = NULL; - gid_t gid, gid_low, gid_high; - BOOL ret = False; - - *winbind_answered = False; - - if ((gid = nametogid(gname)) == (gid_t)-1) { - DEBUG(0,("user_in_winbind_group_list: nametogid for group %s failed.\n", - gname )); - goto err; - } - - if (!lp_winbind_gid(&gid_low, &gid_high)) { - DEBUG(4, ("winbind gid range not configured, therefore %s cannot be a winbind group\n", gname)); - goto err; - } - - if (gid < gid_low || gid > gid_high) { - DEBUG(4, ("group %s is not a winbind group\n", gname)); - goto err; - } - - /* - * Get the gid's that this user belongs to. - */ - - if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) - return False; - - if (num_groups == 0) { - *winbind_answered = True; - return False; - } - - if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { - DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); - goto err; - } - - if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { - DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ -failed with error %s\n", strerror(errno) )); - goto err; - } - - /* - * Now we have the gid list for this user - convert the gname - * to a gid_t via either winbind or the local UNIX lookup and do the comparison. - */ - - for (i = 0; i < num_groups; i++) { - if (gid == groups[i]) { - ret = True; - break; - } - } - - *winbind_answered = True; - SAFE_FREE(groups); - return ret; - - err: - - *winbind_answered = False; - SAFE_FREE(groups); - return False; -} - /**************************************************************************** Check if a user is in a UNIX group. ****************************************************************************/ @@ -298,7 +222,6 @@ exit: ****************************************************************************/ static BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, size_t n_groups) { - BOOL winbind_answered = False; BOOL ret; gid_t gid; unsigned i; @@ -317,11 +240,7 @@ static BOOL user_in_group_list(const char *user, const char *gname, gid_t *group } /* fallback if we don't yet have the group list */ - - ret = user_in_winbind_group_list(user, gname, &winbind_answered); - if (!winbind_answered) - ret = user_in_unix_group_list(user, gname); - + ret = user_in_unix_group_list(user, gname); if (ret) DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n", user, gname)); return ret; -- cgit From 69e40486f98e49cb9fbfd7d4816c8074ed3f786a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 18:13:24 +0000 Subject: r857: fix the build of gregedit (typo:-) metze (This used to be commit 44de741038ccdbca1e3c950670748e99483a7417) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index fff5381e87..1d2a1fec6d 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -121,7 +121,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY gregedit -[BINARY::grepedit] +[BINARY::gregedit] OBJ_FILES= \ lib/registry/tools/gregedit.o REQUIRED_LIBRARIES = \ -- cgit From 2fbe37362f6c5835dc11b1d95b27ced6bfa5a513 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 20:52:03 +0000 Subject: r858: - remove unused account policy stuff it's in our sam.ldb now:-) - don't link lib/ldap_escape.c it's currently unused metze (This used to be commit be472beea3a7ae60cbacada8047b13d4de30643e) --- source4/lib/basic.mk | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 55254498d9..698c09a563 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -45,11 +45,9 @@ ADD_OBJ_FILES = \ lib/smbpasswd.o \ lib/pam_errors.o \ intl/lang_tdb.o \ - lib/account_pol.o \ lib/gencache.o \ lib/module.o \ lib/mutex.o \ - lib/ldap_escape.o \ lib/events.o \ lib/crypto/crc32.o \ lib/crypto/md5.o \ -- cgit From 1f033febfe19d6bb0b45524a672eaf1d1373f15e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 22:05:06 +0000 Subject: r861: remove the next round of unused stuff metze (This used to be commit 8f59daba0d03a2c58f7f23655153de05cbe47e81) --- source4/lib/account_pol.c | 169 --- source4/lib/adt_tree.c | 464 ------- source4/lib/basic.mk | 2 - source4/lib/genrand.c | 17 - source4/lib/sysacls.c | 3198 --------------------------------------------- source4/lib/username.c | 318 ----- 6 files changed, 4168 deletions(-) delete mode 100644 source4/lib/account_pol.c delete mode 100644 source4/lib/adt_tree.c delete mode 100644 source4/lib/sysacls.c (limited to 'source4/lib') diff --git a/source4/lib/account_pol.c b/source4/lib/account_pol.c deleted file mode 100644 index df1479da3a..0000000000 --- a/source4/lib/account_pol.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * account policy storage - * Copyright (C) Jean Fran�ois Micouleau 1998-2001. - * Copyright (C) Andrew Bartlett 2002 - * - * 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 - * (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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -static TDB_CONTEXT *tdb; /* used for driver files */ - -#define DATABASE_VERSION 1 - -/**************************************************************************** - Open the account policy tdb. -****************************************************************************/ - -BOOL init_account_policy(void) -{ - static pid_t local_pid; - const char *vstring = "INFO/version"; - uint32 version; - TALLOC_CTX *mem_ctx; - - if (tdb && local_pid == getpid()) - return True; - mem_ctx = talloc_init("init_account_policy"); - if (!mem_ctx) { - DEBUG(0,("No memory to open account policy database\n")); - return False; - } - tdb = tdb_open_log(lock_path(mem_ctx, "account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - talloc_destroy(mem_ctx); - if (!tdb) { - DEBUG(0,("Failed to open account policy database\n")); - return False; - } - - local_pid = getpid(); - - /* handle a Samba upgrade */ - tdb_lock_bystring(tdb, vstring,0); - if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { - tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); - tdb_store_uint32(tdb, vstring, DATABASE_VERSION); - - account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */ - account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */ - account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, 0); /* don't force user to logon */ - account_policy_set(AP_MAX_PASSWORD_AGE, MAX_PASSWORD_AGE); /* 21 days */ - account_policy_set(AP_MIN_PASSWORD_AGE, 0); /* 0 days */ - account_policy_set(AP_LOCK_ACCOUNT_DURATION, 0); /* lockout for 0 minutes */ - account_policy_set(AP_RESET_COUNT_TIME, 0); /* reset immediatly */ - account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, 0); /* don't lockout */ - account_policy_set(AP_TIME_TO_LOGOUT, -1); /* don't force logout */ - } - tdb_unlock_bystring(tdb, vstring); - - return True; -} - -static const struct { - int field; - const char *string; -} account_policy_names[] = { - {AP_MIN_PASSWORD_LEN, "min password length"}, - {AP_PASSWORD_HISTORY, "password history"}, - {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"}, - {AP_MAX_PASSWORD_AGE, "maximum password age"}, - {AP_MIN_PASSWORD_AGE,"minimum password age"}, - {AP_LOCK_ACCOUNT_DURATION, "lockout duration"}, - {AP_RESET_COUNT_TIME, "reset count minutes"}, - {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"}, - {AP_TIME_TO_LOGOUT, "disconnect time"}, - {0, NULL} -}; - -/**************************************************************************** -Get the account policy name as a string from its #define'ed number -****************************************************************************/ - -static const char *decode_account_policy_name(int field) -{ - int i; - for (i=0; account_policy_names[i].string; i++) { - if (field == account_policy_names[i].field) - return account_policy_names[i].string; - } - return NULL; - -} - -/**************************************************************************** -Get the account policy name as a string from its #define'ed number -****************************************************************************/ - -int account_policy_name_to_fieldnum(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 0; - -} - - -/**************************************************************************** -****************************************************************************/ -BOOL account_policy_get(int field, uint32 *value) -{ - fstring name; - - init_account_policy(); - - *value = 0; - - fstrcpy(name, decode_account_policy_name(field)); - if (!*name) { - DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); - return False; - } - if (!tdb_fetch_uint32(tdb, name, value)) { - DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for efild %d (%s), returning 0", field, name)); - return False; - } - DEBUG(10,("account_policy_get: %s:%d\n", name, *value)); - return True; -} - - -/**************************************************************************** -****************************************************************************/ -BOOL account_policy_set(int field, uint32 value) -{ - fstring name; - - init_account_policy(); - - fstrcpy(name, decode_account_policy_name(field)); - if (!*name) { - DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field)); - return False; - } - - if (!tdb_store_uint32(tdb, name, value)) { - DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value)); - return False; - } - - DEBUG(10,("account_policy_set: %s:%d\n", name, value)); - - return True; -} - diff --git a/source4/lib/adt_tree.c b/source4/lib/adt_tree.c deleted file mode 100644 index 0bc224ec23..0000000000 --- a/source4/lib/adt_tree.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * Generic Abstract Data Types - * Copyright (C) Gerald Carter 2002. - * - * 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 - * (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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - - -/************************************************************************** - Initialize the tree's root. The cmp_fn is a callback function used - for comparision of two children - *************************************************************************/ - -static BOOL trim_tree_keypath( char *path, char **base, char **new_path ) -{ - char *p; - - *new_path = *base = NULL; - - if ( !path ) - return False; - - *base = path; - - p = strchr( path, '/' ); - - if ( p ) { - *p = '\0'; - *new_path = p+1; - } - - return True; -} - - -/************************************************************************** - Initialize the tree's root. The cmp_fn is a callback function used - for comparision of two children - *************************************************************************/ - -SORTED_TREE* sorted_tree_init( void *data_p, - int (cmp_fn)(void*, void*), - void (free_fn)(void*) ) -{ - SORTED_TREE *tree = NULL; - - if ( !(tree = (SORTED_TREE*)malloc( sizeof(SORTED_TREE) )) ) - return NULL; - - ZERO_STRUCTP( tree ); - - tree->compare = cmp_fn; - tree->free = free_fn; - - if ( !(tree->root = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) { - SAFE_FREE( tree ); - return NULL; - } - - ZERO_STRUCTP( tree->root ); - tree->root->data_p = data_p; - - return tree; -} - - -/************************************************************************** - Delete a tree and free all allocated memory - *************************************************************************/ - -static void sorted_tree_destroy_children( TREE_NODE *root ) -{ - int i; - - if ( !root ) - return; - - for ( i=0; inum_children; i++ ) - { - sorted_tree_destroy_children( root->children[i] ); - } - - SAFE_FREE( root->children ); - SAFE_FREE( root->key ); - - return; -} - -/************************************************************************** - Delete a tree and free all allocated memory - *************************************************************************/ - -void sorted_tree_destroy( SORTED_TREE *tree ) -{ - if ( tree->root ) - sorted_tree_destroy_children( tree->root ); - - if ( tree->free ) - tree->free( tree->root ); - - SAFE_FREE( tree ); -} - -/************************************************************************** - Find the next child given a key string - *************************************************************************/ - -static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key ) -{ - TREE_NODE *infant = NULL; - TREE_NODE **siblings; - int i; - - if ( !(infant = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) - return NULL; - - ZERO_STRUCTP( infant ); - - infant->key = strdup( key ); - infant->parent = node; - - siblings = Realloc( node->children, sizeof(TREE_NODE*)*(node->num_children+1) ); - - if ( siblings ) - node->children = siblings; - - node->num_children++; - - /* first child */ - - if ( node->num_children == 1 ) { - DEBUG(11,("sorted_tree_birth_child: First child of node [%s]! [%s]\n", - node->key ? node->key : "NULL", infant->key )); - node->children[0] = infant; - } - else - { - /* - * multiple siblings .... (at least 2 children) - * - * work from the end of the list forward - * The last child is not set at this point - * Insert the new infanct in ascending order - * from left to right - */ - - for ( i = node->num_children-1; i>=1; i-- ) - { - DEBUG(11,("sorted_tree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n", - infant->key, node->children[i-1]->key)); - - /* the strings should never match assuming that we - have called sorted_tree_find_child() first */ - - if ( StrCaseCmp( infant->key, node->children[i-1]->key ) > 0 ) { - DEBUG(11,("sorted_tree_birth_child: storing infant in i == [%d]\n", - i)); - node->children[i] = infant; - break; - } - - /* bump everything towards the end on slot */ - - node->children[i] = node->children[i-1]; - } - - DEBUG(11,("sorted_tree_birth_child: Exiting loop (i == [%d])\n", i )); - - /* if we haven't found the correct slot yet, the child - will be first in the list */ - - if ( i == 0 ) - node->children[0] = infant; - } - - return infant; -} - -/************************************************************************** - Find the next child given a key string - *************************************************************************/ - -static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key ) -{ - TREE_NODE *next = NULL; - int i, result; - - if ( !node ) { - DEBUG(0,("sorted_tree_find_child: NULL node passed into function!\n")); - return NULL; - } - - if ( !key ) { - DEBUG(0,("sorted_tree_find_child: NULL key string passed into function!\n")); - return NULL; - } - - for ( i=0; inum_children; i++ ) - { - DEBUG(11,("sorted_tree_find_child: child key => [%s]\n", - node->children[i]->key)); - - result = StrCaseCmp( node->children[i]->key, key ); - - if ( result == 0 ) - next = node->children[i]; - - /* if result > 0 then we've gone to far because - the list of children is sorted by key name - If result == 0, then we have a match */ - - if ( result > 0 ) - break; - } - - DEBUG(11,("sorted_tree_find_child: %s [%s]\n", - next ? "Found" : "Did not find", key )); - - return next; -} - -/************************************************************************** - Add a new node into the tree given a key path and a blob of data - *************************************************************************/ - -BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p ) -{ - char *str, *base, *path2; - TREE_NODE *current, *next; - BOOL ret = True; - - DEBUG(8,("sorted_tree_add: Enter\n")); - - if ( !path || *path != '/' ) { - DEBUG(0,("sorted_tree_add: Attempt to add a node with a bad path [%s]\n", - path ? path : "NULL" )); - return False; - } - - if ( !tree ) { - DEBUG(0,("sorted_tree_add: Attempt to add a node to an uninitialized tree!\n")); - return False; - } - - /* move past the first '/' */ - - path++; - path2 = strdup( path ); - if ( !path2 ) { - DEBUG(0,("sorted_tree_add: strdup() failed on string [%s]!?!?!\n", path)); - return False; - } - - - /* - * this works sort of like a 'mkdir -p' call, possibly - * creating an entire path to the new node at once - * The path should be of the form ///... - */ - - base = path2; - str = path2; - current = tree->root; - - do { - /* break off the remaining part of the path */ - - str = strchr( str, '/' ); - if ( str ) - *str = '\0'; - - /* iterate to the next child--birth it if necessary */ - - next = sorted_tree_find_child( current, base ); - if ( !next ) { - next = sorted_tree_birth_child( current, base ); - if ( !next ) { - DEBUG(0,("sorted_tree_add: Failed to create new child!\n")); - ret = False; - goto done; - } - } - current = next; - - /* setup the next part of the path */ - - base = str; - if ( base ) { - *base = '/'; - base++; - str = base; - } - - } while ( base != NULL ); - - current->data_p = data_p; - - DEBUG(10,("sorted_tree_add: Successfully added node [%s] to tree\n", - path )); - - DEBUG(8,("sorted_tree_add: Exit\n")); - -done: - SAFE_FREE( path2 ); - return ret; -} - - -/************************************************************************** - Recursive routine to print out all children of a TREE_NODE - *************************************************************************/ - -static void sorted_tree_print_children( TREE_NODE *node, int debug, const char *path ) -{ - int i; - int num_children; - pstring path2; - - if ( !node ) - return; - - - if ( node->key ) - DEBUG(debug,("%s: [%s] (%s)\n", path ? path : "NULL", node->key, - node->data_p ? "data" : "NULL" )); - - *path2 = '\0'; - if ( path ) - pstrcpy( path2, path ); - pstrcat( path2, node->key ? node->key : "NULL" ); - pstrcat( path2, "/" ); - - num_children = node->num_children; - for ( i=0; ichildren[i], debug, path2 ); - - -} - -/************************************************************************** - Dump the kys for a tree to the log file - *************************************************************************/ - -void sorted_tree_print_keys( SORTED_TREE *tree, int debug ) -{ - int i; - int num_children = tree->root->num_children; - - if ( tree->root->key ) - DEBUG(debug,("ROOT/: [%s] (%s)\n", tree->root->key, - tree->root->data_p ? "data" : "NULL" )); - - for ( i=0; iroot->children[i], debug, - tree->root->key ? tree->root->key : "ROOT/" ); - } - -} - -/************************************************************************** - return the data_p for for the node in tree matching the key string - The key string is the full path. We must break it apart and walk - the tree - *************************************************************************/ - -void* sorted_tree_find( SORTED_TREE *tree, char *key ) -{ - char *keystr, *base, *str, *p; - TREE_NODE *current; - void *result = NULL; - - DEBUG(10,("sorted_tree_find: Enter [%s]\n", key ? key : "NULL" )); - - /* sanity checks first */ - - if ( !key ) { - DEBUG(0,("sorted_tree_find: Attempt to search tree using NULL search string!\n")); - return NULL; - } - - if ( !tree ) { - DEBUG(0,("sorted_tree_find: Attempt to search an uninitialized tree using string [%s]!\n", - key ? key : "NULL" )); - return NULL; - } - - if ( !tree->root ) - return NULL; - - /* make a copy to play with */ - - if ( *key == '/' ) - keystr = strdup( key+1 ); - else - keystr = strdup( key ); - - if ( !keystr ) { - DEBUG(0,("sorted_tree_find: strdup() failed on string [%s]!?!?!\n", key)); - return NULL; - } - - /* start breaking the path apart */ - - p = keystr; - current = tree->root; - - if ( tree->root->data_p ) - result = tree->root->data_p; - - do - { - /* break off the remaining part of the path */ - - trim_tree_keypath( p, &base, &str ); - - DEBUG(11,("sorted_tree_find: [loop] base => [%s], new_path => [%s]\n", - base, str)); - - /* iterate to the next child */ - - current = sorted_tree_find_child( current, base ); - - /* - * the idea is that the data_p for a parent should - * be inherited by all children, but allow it to be - * overridden farther down - */ - - if ( current && current->data_p ) - result = current->data_p; - - /* reset the path pointer 'p' to the remaining part of the key string */ - - p = str; - - } while ( str && current ); - - /* result should be the data_p from the lowest match node in the tree */ - if ( result ) - DEBUG(11,("sorted_tree_find: Found data_p!\n")); - - SAFE_FREE( keystr ); - - DEBUG(10,("sorted_tree_find: Exit\n")); - - return result; -} - - diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 698c09a563..3a1f127853 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -18,8 +18,6 @@ ADD_OBJ_FILES = \ lib/time.o \ lib/genrand.o \ lib/username.o \ - lib/util_getent.o \ - lib/util_pw.o \ lib/smbrun.o \ lib/bitmap.o \ lib/snprintf.o \ diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index fdd4bb14fc..9645dd7999 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -135,7 +135,6 @@ static int do_reseed(BOOL use_fd, int fd) { unsigned char seed_inbuf[40]; uint32 v1, v2; struct timeval tval; pid_t mypid; - struct passwd *pw; if (use_fd) { if (fd != -1) @@ -151,22 +150,6 @@ static int do_reseed(BOOL use_fd, int fd) do_filehash("/etc/shadow", &seed_inbuf[0]); do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]); - /* - * Add in the root encrypted password. - * On any system where security is taken - * seriously this will be secret. - */ - - pw = getpwnam_alloc("root"); - if (pw && pw->pw_passwd) { - size_t i; - unsigned char md4_tmp[16]; - mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd)); - for (i=0;i<16;i++) - seed_inbuf[8+i] ^= md4_tmp[i]; - passwd_free(&pw); - } - /* * Add the counter, time of day, and pid. */ diff --git a/source4/lib/sysacls.c b/source4/lib/sysacls.c deleted file mode 100644 index fe85b9e72f..0000000000 --- a/source4/lib/sysacls.c +++ /dev/null @@ -1,3198 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba system utilities for ACL support. - Copyright (C) Jeremy Allison 2000. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* - This file wraps all differing system ACL interfaces into a consistent - one based on the POSIX interface. It also returns the correct errors - for older UNIX systems that don't support ACLs. - - The interfaces that each ACL implementation must support are as follows : - - int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) - int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) - int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p - void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) - SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) - SMB_ACL_T sys_acl_get_fd(int fd) - int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset); - int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) - SMB_ACL_T sys_acl_init( int count) - int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) - int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) - int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) - int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) - int sys_acl_valid( SMB_ACL_T theacl ) - int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) - int sys_acl_set_fd( int fd, SMB_ACL_T theacl) - int sys_acl_delete_def_file(const char *path) - - This next one is not POSIX complient - but we *have* to have it ! - More POSIX braindamage. - - int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) - - The generic POSIX free is the following call. We split this into - several different free functions as we may need to add tag info - to structures when emulating the POSIX interface. - - int sys_acl_free( void *obj_p) - - The calls we actually use are : - - int sys_acl_free_text(char *text) - free acl_to_text - int sys_acl_free_acl(SMB_ACL_T posix_acl) - int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype) - -*/ - -#if defined(HAVE_POSIX_ACLS) - -/* Identity mapping - easy. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return acl_get_entry( the_acl, entry_id, entry_p); -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file( path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - return acl_clear_perms(permset); -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return acl_add_perm(permset, perm); -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ -#if defined(HAVE_ACL_GET_PERM_NP) - /* - * Required for TrustedBSD-based ACL implementations where - * non-POSIX.1e functions are denoted by a _np (non-portable) - * suffix. - */ - return acl_get_perm_np(permset, perm); -#else - return acl_get_perm(permset, perm); -#endif -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return acl_create_entry(pacl, pentry); -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - return acl_valid(theacl); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file(name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file(name); -} - -int sys_acl_free_text(char *text) -{ - return acl_free(text); -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free(qual); -} - -#elif defined(HAVE_TRU64_ACLS) -/* - * The interface to DEC/Compaq Tru64 UNIX ACLs - * is based on Draft 13 of the POSIX spec which is - * slightly different from the Draft 16 interface. - * - * Also, some of the permset manipulation functions - * such as acl_clear_perm() and acl_add_perm() appear - * to be broken on Tru64 so we have to manipulate - * the permission bits in the permset directly. - */ -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_ENTRY_T entry; - - if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) { - return -1; - } - - errno = 0; - if ((entry = acl_get_entry(the_acl)) != NULL) { - *entry_p = entry; - return 1; - } - - return errno ? -1 : 0; -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return acl_get_tag_type( entry_d, tag_type_p); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return acl_get_permset( entry_d, permset_p); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return acl_get_qualifier( entry_d); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - return acl_get_file((char *)path_p, type); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - return acl_get_fd(fd, ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - *permset = 0; /* acl_clear_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) { - errno = EINVAL; - return -1; - } - - *permset |= perm; /* acl_add_perm() is broken on Tru64 */ - - return 0; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return *permset & perm; /* Tru64 doesn't have acl_get_perm() */ -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - return acl_to_text( the_acl, plen); -} - -SMB_ACL_T sys_acl_init( int count) -{ - return acl_init(count); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - SMB_ACL_ENTRY_T entry; - - if ((entry = acl_create_entry(pacl)) == NULL) { - return -1; - } - - *pentry = entry; - return 0; -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return acl_set_tag_type(entry, tagtype); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - return acl_set_qualifier(entry, qual); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return acl_set_permset(entry, permset); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - acl_entry_t entry; - - return acl_valid(theacl, &entry); -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return acl_set_file((char *)name, acltype, theacl); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file((char *)name); -} - -int sys_acl_free_text(char *text) -{ - /* - * (void) cast and explicit return 0 are for DEC UNIX - * which just #defines acl_free_text() to be free() - */ - (void) acl_free_text(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - return acl_free(the_acl); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return acl_free_qualifier(qual, tagtype); -} - -#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS) - -/* - * Donated by Michael Davidson for UnixWare / OpenUNIX. - * Modified by Toomas Soome for Solaris. - */ - -/* - * Note that while this code implements sufficient functionality - * to support the sys_acl_* interfaces it does not provide all - * of the semantics of the POSIX ACL interfaces. - * - * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned - * from a call to sys_acl_get_entry() should not be assumed to be - * valid after calling any of the following functions, which may - * reorder the entries in the ACL. - * - * sys_acl_valid() - * sys_acl_set_file() - * sys_acl_set_fd() - */ - -/* - * The only difference between Solaris and UnixWare / OpenUNIX is - * that the #defines for the ACL operations have different names - */ -#if defined(HAVE_UNIXWARE_ACLS) - -#define SETACL ACL_SET -#define GETACL ACL_GET -#define GETACLCNT ACL_CNT - -#endif - - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->count) { - return 0; - } - - *entry_p = &acl_d->acl[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->a_type; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = &entry_d->a_perm; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) -{ - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; -} - -/* - * There is no way of knowing what size the ACL returned by - * GETACL will be unless you first call GETACLCNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use GETACLCNT to find out the actual - * size, reallocate the ACL buffer, and then call GETACL again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * GETACLCNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * GETACLCNT and the call to GETACL. - */ - while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0 - && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - - acl_d->count = naccess; - - return acl_d; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - *permset_d = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - *permset_d |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return *permset_d & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - int i; - int len, maxlen; - char *text; - - /* - * use an initial estimate of 20 bytes per ACL entry - * when allocating memory for the text representation - * of the ACL - */ - len = 0; - maxlen = 20 * acl_d->count; - if ((text = malloc(maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - - for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; - struct group *gr; - char tagbuf[12]; - char idbuf[12]; - char *tag; - char *id = ""; - char perms[4]; - int nbytes; - - switch (ap->a_type) { - /* - * for debugging purposes it's probably more - * useful to dump unknown tag types rather - * than just returning an error - */ - default: - slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); - tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - break; - - case SMB_ACL_USER: - id = uidtoname(ap->a_id); - case SMB_ACL_USER_OBJ: - tag = "user"; - break; - - case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - } else { - id = gr->gr_name; - } - case SMB_ACL_GROUP_OBJ: - tag = "group"; - break; - - case SMB_ACL_OTHER: - tag = "other"; - break; - - case SMB_ACL_MASK: - tag = "mask"; - break; - - } - - perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; - perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; - perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; - perms[3] = '\0'; - - /* : : rwx \n \0 */ - nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; - - /* - * If this entry would overflow the buffer - * allocate enough additional memory for this - * entry and an estimate of another 20 bytes - * for each entry still to be processed - */ - if ((len + nbytes) > maxlen) { - char *oldtext = text; - - maxlen += nbytes + 20 * (acl_d->count - i); - - if ((text = Realloc(oldtext, maxlen)) == NULL) { - SAFE_FREE(oldtext); - errno = ENOMEM; - return NULL; - } - } - - slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); - len += nbytes - 1; - } - - if (len_p) - *len_p = len; - - return text; -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - /* - * note that since the definition of the structure pointed - * to by the SMB_ACL_T includes the first element of the - * acl[] array, this actually allocates an ACL with room - * for (count+1) entries - */ - if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->size = count + 1; - a->count = 0; - a->next = -1; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->count >= acl_d->size) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->acl[acl_d->count++]; - entry_d->a_type = 0; - entry_d->a_id = -1; - entry_d->a_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->a_type = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->a_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* - * sort the ACL and check it for validity - * - * if it's a minimal ACL with only 4 entries then we - * need to recalculate the mask permissions to make - * sure that they are the same as the GROUP_OBJ - * permissions as required by the UnixWare acl() system call. - * - * (note: since POSIX allows minimal ACLs which only contain - * 3 entries - ie there is no mask entry - we should, in theory, - * check for this and add a mask entry if necessary - however - * we "know" that the caller of this interface always specifies - * a mask so, in practice "this never happens" (tm) - if it *does* - * happen aclsort() will fail and return an error and someone will - * have to fix it ...) - */ - -static int acl_sort(SMB_ACL_T acl_d) -{ - int fixmask = (acl_d->count <= 4); - - if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) { - errno = EINVAL; - return -1; - } - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0])); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, SETACL, acl_count, acl_p); - - SAFE_FREE(acl_buf); - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - if (acl_sort(acl_d) != 0) { - return -1; - } - - return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]); -} - -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, SETACL, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; -} - -int sys_acl_free_text(char *text) -{ - SAFE_FREE(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T acl_d) -{ - SAFE_FREE(acl_d); - return 0; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return 0; -} - -#elif defined(HAVE_HPUX_ACLS) -#include - -/* - * Based on the Solaris/SCO code - with modifications. - */ - -/* - * Note that while this code implements sufficient functionality - * to support the sys_acl_* interfaces it does not provide all - * of the semantics of the POSIX ACL interfaces. - * - * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned - * from a call to sys_acl_get_entry() should not be assumed to be - * valid after calling any of the following functions, which may - * reorder the entries in the ACL. - * - * sys_acl_valid() - * sys_acl_set_file() - * sys_acl_set_fd() - */ - -/* This checks if the POSIX ACL system call is defined */ -/* which basically corresponds to whether JFS 3.3 or */ -/* higher is installed. If acl() was called when it */ -/* isn't defined, it causes the process to core dump */ -/* so it is important to check this and avoid acl() */ -/* calls if it isn't there. */ - -static BOOL hpux_acl_call_presence(void) -{ - - shl_t handle = NULL; - void *value; - int ret_val=0; - //static BOOL already_checked=0; - // REWRITE: add this back in?? - //if(already_checked) - // return True; - - - ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); - - if(ret_val != 0) { - DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n", - ret_val, errno, strerror(errno))); - DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); - return False; - } - - DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n")); - - already_checked = True; - return True; -} - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->count) { - return 0; - } - - *entry_p = &acl_d->acl[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->a_type; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = &entry_d->a_perm; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) -{ - if (entry_d->a_type != SMB_ACL_USER - && entry_d->a_type != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->a_id; -} - -/* - * There is no way of knowing what size the ACL returned by - * ACL_GET will be unless you first call ACL_CNT which means - * making an additional system call. - * - * In the hope of avoiding the cost of the additional system - * call in most cases, we initially allocate enough space for - * an ACL with INITIAL_ACL_SIZE entries. If this turns out to - * be too small then we use ACL_CNT to find out the actual - * size, reallocate the ACL buffer, and then call ACL_GET again. - */ - -#define INITIAL_ACL_SIZE 16 - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T acl_d; - int count; /* # of ACL entries allocated */ - int naccess; /* # of access ACL entries */ - int ndefault; /* # of default ACL entries */ - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - return NULL; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return NULL; - } - - count = INITIAL_ACL_SIZE; - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - - /* - * If there isn't enough space for the ACL entries we use - * ACL_CNT to determine the actual number of ACL entries - * reallocate and try again. This is in a loop because it - * is possible that someone else could modify the ACL and - * increase the number of entries between the call to - * ACL_CNT and the call to ACL_GET. - */ - while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) { - - sys_acl_free_acl(acl_d); - - if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) { - return NULL; - } - - if ((acl_d = sys_acl_init(count)) == NULL) { - return NULL; - } - } - - if (count < 0) { - sys_acl_free_acl(acl_d); - return NULL; - } - - /* - * calculate the number of access and default ACL entries - * - * Note: we assume that the acl() system call returned a - * well formed ACL which is sorted so that all of the - * access ACL entries preceed any default ACL entries - */ - for (naccess = 0; naccess < count; naccess++) { - if (acl_d->acl[naccess].a_type & ACL_DEFAULT) - break; - } - ndefault = count - naccess; - - /* - * if the caller wants the default ACL we have to copy - * the entries down to the start of the acl[] buffer - * and mask out the ACL_DEFAULT flag from the type field - */ - if (type == SMB_ACL_TYPE_DEFAULT) { - int i, j; - - for (i = 0, j = naccess; i < ndefault; i++, j++) { - acl_d->acl[i] = acl_d->acl[j]; - acl_d->acl[i].a_type &= ~ACL_DEFAULT; - } - - acl_d->count = ndefault; - } else { - acl_d->count = naccess; - } - - return acl_d; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - *permset_d = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - *permset_d |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return *permset_d & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - int i; - int len, maxlen; - char *text; - - /* - * use an initial estimate of 20 bytes per ACL entry - * when allocating memory for the text representation - * of the ACL - */ - len = 0; - maxlen = 20 * acl_d->count; - if ((text = malloc(maxlen)) == NULL) { - errno = ENOMEM; - return NULL; - } - - for (i = 0; i < acl_d->count; i++) { - struct acl *ap = &acl_d->acl[i]; - struct passwd *pw; - struct group *gr; - char tagbuf[12]; - char idbuf[12]; - char *tag; - char *id = ""; - char perms[4]; - int nbytes; - - switch (ap->a_type) { - /* - * for debugging purposes it's probably more - * useful to dump unknown tag types rather - * than just returning an error - */ - default: - slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", - ap->a_type); - tag = tagbuf; - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - break; - - case SMB_ACL_USER: - id = uidtoname(ap->a_id); - case SMB_ACL_USER_OBJ: - tag = "user"; - break; - - case SMB_ACL_GROUP: - if ((gr = getgrgid(ap->a_id)) == NULL) { - slprintf(idbuf, sizeof(idbuf)-1, "%ld", - (long)ap->a_id); - id = idbuf; - } else { - id = gr->gr_name; - } - case SMB_ACL_GROUP_OBJ: - tag = "group"; - break; - - case SMB_ACL_OTHER: - tag = "other"; - break; - - case SMB_ACL_MASK: - tag = "mask"; - break; - - } - - perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; - perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; - perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; - perms[3] = '\0'; - - /* : : rwx \n \0 */ - nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; - - /* - * If this entry would overflow the buffer - * allocate enough additional memory for this - * entry and an estimate of another 20 bytes - * for each entry still to be processed - */ - if ((len + nbytes) > maxlen) { - char *oldtext = text; - - maxlen += nbytes + 20 * (acl_d->count - i); - - if ((text = Realloc(oldtext, maxlen)) == NULL) { - free(oldtext); - errno = ENOMEM; - return NULL; - } - } - - slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); - len += nbytes - 1; - } - - if (len_p) - *len_p = len; - - return text; -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - /* - * note that since the definition of the structure pointed - * to by the SMB_ACL_T includes the first element of the - * acl[] array, this actually allocates an ACL with room - * for (count+1) entries - */ - if ((a = malloc(sizeof(*a) + count * sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->size = count + 1; - a->count = 0; - a->next = -1; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->count >= acl_d->size) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->acl[acl_d->count++]; - entry_d->a_type = 0; - entry_d->a_id = -1; - entry_d->a_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->a_type = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->a_type != SMB_ACL_GROUP - && entry_d->a_type != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->a_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->a_perm = *permset_d; - - return 0; -} - -/* Structure to capture the count for each type of ACE. */ - -struct hpux_acl_types { - int n_user; - int n_def_user; - int n_user_obj; - int n_def_user_obj; - - int n_group; - int n_def_group; - int n_group_obj; - int n_def_group_obj; - - int n_other; - int n_other_obj; - int n_def_other_obj; - - int n_class_obj; - int n_def_class_obj; - - int n_illegal_obj; -}; - -/* count_obj: - * Counts the different number of objects in a given array of ACL - * structures. - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL strucutres. - * aclp - Array of ACL structures. - * acl_type_count - Pointer to acl_types structure. Should already be - * allocated. - * Output: - * - * acl_type_count - This structure is filled up with counts of various - * acl types. - */ - -static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count) -{ - int i; - - memset(acl_type_count, 0, sizeof(struct hpux_acl_types)); - - for(i=0;in_user++; - break; - case USER_OBJ: - acl_type_count->n_user_obj++; - break; - case DEF_USER_OBJ: - acl_type_count->n_def_user_obj++; - break; - case GROUP: - acl_type_count->n_group++; - break; - case GROUP_OBJ: - acl_type_count->n_group_obj++; - break; - case DEF_GROUP_OBJ: - acl_type_count->n_def_group_obj++; - break; - case OTHER_OBJ: - acl_type_count->n_other_obj++; - break; - case DEF_OTHER_OBJ: - acl_type_count->n_def_other_obj++; - break; - case CLASS_OBJ: - acl_type_count->n_class_obj++; - break; - case DEF_CLASS_OBJ: - acl_type_count->n_def_class_obj++; - break; - case DEF_USER: - acl_type_count->n_def_user++; - break; - case DEF_GROUP: - acl_type_count->n_def_group++; - break; - default: - acl_type_count->n_illegal_obj++; - break; - } - } -} - -/* swap_acl_entries: Swaps two ACL entries. - * - * Inputs: aclp0, aclp1 - ACL entries to be swapped. - */ - -static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1) -{ - struct acl temp_acl; - - temp_acl.a_type = aclp0->a_type; - temp_acl.a_id = aclp0->a_id; - temp_acl.a_perm = aclp0->a_perm; - - aclp0->a_type = aclp1->a_type; - aclp0->a_id = aclp1->a_id; - aclp0->a_perm = aclp1->a_perm; - - aclp1->a_type = temp_acl.a_type; - aclp1->a_id = temp_acl.a_id; - aclp1->a_perm = temp_acl.a_perm; -} - -/* prohibited_duplicate_type - * Identifies if given ACL type can have duplicate entries or - * not. - * - * Inputs: acl_type - ACL Type. - * - * Outputs: - * - * Return.. - * - * True - If the ACL type matches any of the prohibited types. - * False - If the ACL type doesn't match any of the prohibited types. - */ - -static BOOL hpux_prohibited_duplicate_type(int acl_type) -{ - switch(acl_type) { - case USER: - case GROUP: - case DEF_USER: - case DEF_GROUP: - return True; - default: - return False; - } -} - -/* get_needed_class_perm - * Returns the permissions of a ACL structure only if the ACL - * type matches one of the pre-determined types for computing - * CLASS_OBJ permissions. - * - * Inputs: aclp - Pointer to ACL structure. - */ - -static int hpux_get_needed_class_perm(struct acl *aclp) -{ - switch(aclp->a_type) { - case USER: - case GROUP_OBJ: - case GROUP: - case DEF_USER_OBJ: - case DEF_USER: - case DEF_GROUP_OBJ: - case DEF_GROUP: - case DEF_CLASS_OBJ: - case DEF_OTHER_OBJ: - return aclp->a_perm; - default: - return 0; - } -} - -/* acl_sort for HPUX. - * Sorts the array of ACL structures as per the description in - * aclsort man page. Refer to aclsort man page for more details - * - * Inputs: - * - * acl_count - Count of ACLs in the array of ACL structures. - * calclass - If this is not zero, then we compute the CLASS_OBJ - * permissions. - * aclp - Array of ACL structures. - * - * Outputs: - * - * aclp - Sorted array of ACL structures. - * - * Outputs: - * - * Returns 0 for success -1 for failure. Prints a message to the Samba - * debug log in case of failure. - */ - -static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp) -{ -#if !defined(HAVE_HPUX_ACLSORT) - /* - * The aclsort() system call is availabe on the latest HPUX General - * Patch Bundles. So for HPUX, we developed our version of acl_sort - * function. Because, we don't want to update to a new - * HPUX GR bundle just for aclsort() call. - */ - - struct hpux_acl_types acl_obj_count; - int n_class_obj_perm = 0; - int i, j; - - if(!acl_count) { - DEBUG(10,("Zero acl count passed. Returning Success\n")); - return 0; - } - - if(aclp == NULL) { - DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n")); - return -1; - } - - /* Count different types of ACLs in the ACLs array */ - - hpux_count_obj(acl_count, aclp, &acl_obj_count); - - /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, - * CLASS_OBJ and OTHER_OBJ - */ - - if( (acl_obj_count.n_user_obj != 1) || - (acl_obj_count.n_group_obj != 1) || - (acl_obj_count.n_class_obj != 1) || - (acl_obj_count.n_other_obj != 1) - ) { - DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \ -USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n")); - return -1; - } - - /* If any of the default objects are present, there should be only - * one of them each. - */ - - if( (acl_obj_count.n_def_user_obj > 1) || (acl_obj_count.n_def_group_obj > 1) || - (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) { - DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \ -or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n")); - return -1; - } - - /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl - * structures. - * - * Sorting crieteria - First sort by ACL type. If there are multiple entries of - * same ACL type, sort by ACL id. - * - * I am using the trival kind of sorting method here because, performance isn't - * really effected by the ACLs feature. More over there aren't going to be more - * than 17 entries on HPUX. - */ - - for(i=0; i aclp[j].a_type ) { - /* ACL entries out of order, swap them */ - - hpux_swap_acl_entries((aclp+i), (aclp+j)); - - } else if ( aclp[i].a_type == aclp[j].a_type ) { - - /* ACL entries of same type, sort by id */ - - if(aclp[i].a_id > aclp[j].a_id) { - hpux_swap_acl_entries((aclp+i), (aclp+j)); - } else if (aclp[i].a_id == aclp[j].a_id) { - /* We have a duplicate entry. */ - if(hpux_prohibited_duplicate_type(aclp[i].a_type)) { - DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n", - aclp[i].a_type, aclp[i].a_id)); - return -1; - } - } - - } - } - } - - /* set the class obj permissions to the computed one. */ - if(calclass) { - int n_class_obj_index = -1; - - for(i=0;icount <= 4); - - if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) { - errno = EINVAL; - return -1; - } - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_sort(acl_d); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - struct stat s; - struct acl *acl_p; - int acl_count; - struct acl *acl_buf = NULL; - int ret; - - if(hpux_acl_call_presence() == False) { - /* Looks like we don't have the acl() system call on HPUX. - * May be the system doesn't have the latest version of JFS. - */ - errno=ENOSYS; - return -1; - } - - if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { - errno = EINVAL; - return -1; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - acl_p = &acl_d->acl[0]; - acl_count = acl_d->count; - - /* - * if it's a directory there is extra work to do - * since the acl() system call will replace both - * the access ACLs and the default ACLs (if any) - */ - if (stat(name, &s) != 0) { - return -1; - } - if (S_ISDIR(s.st_mode)) { - SMB_ACL_T acc_acl; - SMB_ACL_T def_acl; - SMB_ACL_T tmp_acl; - int i; - - if (type == SMB_ACL_TYPE_ACCESS) { - acc_acl = acl_d; - def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); - - } else { - def_acl = acl_d; - acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); - } - - if (tmp_acl == NULL) { - return -1; - } - - /* - * allocate a temporary buffer for the complete ACL - */ - acl_count = acc_acl->count + def_acl->count; - acl_p = acl_buf = malloc(acl_count * sizeof(acl_buf[0])); - - if (acl_buf == NULL) { - sys_acl_free_acl(tmp_acl); - errno = ENOMEM; - return -1; - } - - /* - * copy the access control and default entries into the buffer - */ - memcpy(&acl_buf[0], &acc_acl->acl[0], - acc_acl->count * sizeof(acl_buf[0])); - - memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], - def_acl->count * sizeof(acl_buf[0])); - - /* - * set the ACL_DEFAULT flag on the default entries - */ - for (i = acc_acl->count; i < acl_count; i++) { - acl_buf[i].a_type |= ACL_DEFAULT; - } - - sys_acl_free_acl(tmp_acl); - - } else if (type != SMB_ACL_TYPE_ACCESS) { - errno = EINVAL; - return -1; - } - - ret = acl(name, ACL_SET, acl_count, acl_p); - - if (acl_buf) { - free(acl_buf); - } - - return ret; -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - /* - * HPUX doesn't have the facl call. Fake it using the path.... JRA. - */ - - files_struct *fsp = file_find_fd(fd); - - if (fsp == NULL) { - errno = EBADF; - return NULL; - } - - if (acl_sort(acl_d) != 0) { - return -1; - } - - /* - * We know we're in the same conn context. So we - * can use the relative path. - */ - - return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d); -} - -int sys_acl_delete_def_file(const char *path) -{ - SMB_ACL_T acl_d; - int ret; - - /* - * fetching the access ACL and rewriting it has - * the effect of deleting the default ACL - */ - if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { - return -1; - } - - ret = acl(path, ACL_SET, acl_d->count, acl_d->acl); - - sys_acl_free_acl(acl_d); - - return ret; -} - -int sys_acl_free_text(char *text) -{ - free(text); - return 0; -} - -int sys_acl_free_acl(SMB_ACL_T acl_d) -{ - free(acl_d); - return 0; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return 0; -} - -#elif defined(HAVE_IRIX_ACLS) - -int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { - errno = EINVAL; - return -1; - } - - if (entry_p == NULL) { - errno = EINVAL; - return -1; - } - - if (entry_id == SMB_ACL_FIRST_ENTRY) { - acl_d->next = 0; - } - - if (acl_d->next < 0) { - errno = EINVAL; - return -1; - } - - if (acl_d->next >= acl_d->aclp->acl_cnt) { - return 0; - } - - *entry_p = &acl_d->aclp->acl_entry[acl_d->next++]; - - return 1; -} - -int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p) -{ - *type_p = entry_d->ae_tag; - - return 0; -} - -int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - *permset_p = entry_d; - - return 0; -} - -void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d) -{ - if (entry_d->ae_tag != SMB_ACL_USER - && entry_d->ae_tag != SMB_ACL_GROUP) { - errno = EINVAL; - return NULL; - } - - return &entry_d->ae_id; -} - -SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type) -{ - SMB_ACL_T a; - - if ((a = malloc(sizeof(*a))) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_file(path_p, type)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - SMB_ACL_T a; - - if ((a = malloc(sizeof(*a))) == NULL) { - errno = ENOMEM; - return NULL; - } - if ((a->aclp = acl_get_fd(fd)) == NULL) { - SAFE_FREE(a); - return NULL; - } - a->next = -1; - a->freeaclp = True; - return a; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d) -{ - permset_d->ae_perm = 0; - - return 0; -} - -int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE - && perm != SMB_ACL_EXECUTE) { - errno = EINVAL; - return -1; - } - - if (permset_d == NULL) { - errno = EINVAL; - return -1; - } - - permset_d->ae_perm |= perm; - - return 0; -} - -int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm) -{ - return permset_d->ae_perm & perm; -} - -char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p) -{ - return acl_to_text(acl_d->aclp, len_p); -} - -SMB_ACL_T sys_acl_init(int count) -{ - SMB_ACL_T a; - - if (count < 0) { - errno = EINVAL; - return NULL; - } - - if ((a = malloc(sizeof(*a) + sizeof(struct acl))) == NULL) { - errno = ENOMEM; - return NULL; - } - - a->next = -1; - a->freeaclp = False; - a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *)); - a->aclp->acl_cnt = 0; - - return a; -} - - -int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p) -{ - SMB_ACL_T acl_d; - SMB_ACL_ENTRY_T entry_d; - - if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { - errno = EINVAL; - return -1; - } - - if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) { - errno = ENOSPC; - return -1; - } - - entry_d = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++]; - entry_d->ae_tag = 0; - entry_d->ae_id = 0; - entry_d->ae_perm = 0; - *entry_p = entry_d; - - return 0; -} - -int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type) -{ - switch (tag_type) { - case SMB_ACL_USER: - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - case SMB_ACL_MASK: - entry_d->ae_tag = tag_type; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - -int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p) -{ - if (entry_d->ae_tag != SMB_ACL_GROUP - && entry_d->ae_tag != SMB_ACL_USER) { - errno = EINVAL; - return -1; - } - - entry_d->ae_id = *((id_t *)qual_p); - - return 0; -} - -int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d) -{ - if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { - return EINVAL; - } - - entry_d->ae_perm = permset_d->ae_perm; - - return 0; -} - -int sys_acl_valid(SMB_ACL_T acl_d) -{ - return acl_valid(acl_d->aclp); -} - -int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d) -{ - return acl_set_file(name, type, acl_d->aclp); -} - -int sys_acl_set_fd(int fd, SMB_ACL_T acl_d) -{ - return acl_set_fd(fd, acl_d->aclp); -} - -int sys_acl_delete_def_file(const char *name) -{ - return acl_delete_def_file(name); -} - -int sys_acl_free_text(char *text) -{ - return acl_free(text); -} - -int sys_acl_free_acl(SMB_ACL_T acl_d) -{ - if (acl_d->freeaclp) { - acl_free(acl_d->aclp); - } - acl_free(acl_d); - return 0; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return 0; -} - -#elif defined(HAVE_AIX_ACLS) - -/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */ - -int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - struct acl_entry_link *link; - struct new_acl_entry *entry; - int keep_going; - - DEBUG(10,("This is the count: %d\n",theacl->count)); - - /* Check if count was previously set to -1. * - * If it was, that means we reached the end * - * of the acl last time. */ - if(theacl->count == -1) - return(0); - - link = theacl; - /* To get to the next acl, traverse linked list until index * - * of acl matches the count we are keeping. This count is * - * incremented each time we return an acl entry. */ - - for(keep_going = 0; keep_going < theacl->count; keep_going++) - link = link->nextp; - - entry = *entry_p = link->entryp; - - DEBUG(10,("*entry_p is %d\n",entry_p)); - DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access)); - - /* Increment count */ - theacl->count++; - if(link->nextp == NULL) - theacl->count = -1; - - return(1); -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - /* Initialize tag type */ - - *tag_type_p = -1; - DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type)); - - /* Depending on what type of entry we have, * - * return tag type. */ - switch(entry_d->ace_id->id_type) { - case ACEID_USER: - *tag_type_p = SMB_ACL_USER; - break; - case ACEID_GROUP: - *tag_type_p = SMB_ACL_GROUP; - break; - - case SMB_ACL_USER_OBJ: - case SMB_ACL_GROUP_OBJ: - case SMB_ACL_OTHER: - *tag_type_p = entry_d->ace_id->id_type; - break; - - default: - return(-1); - } - - return(0); -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - DEBUG(10,("Starting AIX sys_acl_get_permset\n")); - *permset_p = &entry_d->ace_access; - DEBUG(10,("**permset_p is %d\n",**permset_p)); - if(!(**permset_p & S_IXUSR) && - !(**permset_p & S_IWUSR) && - !(**permset_p & S_IRUSR) && - (**permset_p != 0)) - return(-1); - - DEBUG(10,("Ending AIX sys_acl_get_permset\n")); - return(0); -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - return(entry_d->ace_id->id_data); -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* Get the acl using statacl */ - - DEBUG(10,("Entering sys_acl_get_file\n")); - DEBUG(10,("path_p is %s\n",path_p)); - - file_acl = (struct acl *)malloc(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = statacl((char *)path_p,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("statacl returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - acl_entry = file_acl->acl_ext; - - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL) - return(NULL); - - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = (struct acl_entry_link *) - malloc(sizeof(struct acl_entry_link)); - - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); - if(acl_entry_link->nextp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); - - return(acl_entry_link_head); -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - struct acl *file_acl = (struct acl *)NULL; - struct acl_entry *acl_entry; - struct new_acl_entry *new_acl_entry; - struct ace_id *idp; - struct acl_entry_link *acl_entry_link; - struct acl_entry_link *acl_entry_link_head; - int i; - int rc = 0; - uid_t user_id; - - /* Get the acl using fstatacl */ - - DEBUG(10,("Entering sys_acl_get_fd\n")); - DEBUG(10,("fd is %d\n",fd)); - file_acl = (struct acl *)malloc(BUFSIZ); - - if(file_acl == NULL) { - errno=ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - - memset(file_acl,0,BUFSIZ); - - rc = fstatacl(fd,0,file_acl,BUFSIZ); - if(rc == -1) { - DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("Got facl and returned it\n")); - - /* Point to the first acl entry in the acl */ - - acl_entry = file_acl->acl_ext; - /* Begin setting up the head of the linked list * - * that will be used for the storing the acl * - * in a way that is useful for the posix_acls.c * - * code. */ - - acl_entry_link_head = acl_entry_link = sys_acl_init(0); - if(acl_entry_link_head == NULL){ - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - DEBUG(10,("acl_entry is %d\n",acl_entry)); - DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); - - /* Check if the extended acl bit is on. * - * If it isn't, do not show the * - * contents of the acl since AIX intends * - * the extended info to remain unused */ - - if(file_acl->acl_mode & S_IXACL){ - /* while we are not pointing to the very end */ - while(acl_entry < acl_last(file_acl)) { - /* before we malloc anything, make sure this is */ - /* a valid acl entry and one that we want to map */ - - idp = id_nxt(acl_entry->ace_id); - if((acl_entry->ace_type == ACC_SPECIFY || - (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { - acl_entry = acl_nxt(acl_entry); - continue; - } - - idp = acl_entry->ace_id; - - /* Check if this is the first entry in the linked list. * - * The first entry needs to keep prevp pointing to NULL * - * and already has entryp allocated. */ - - if(acl_entry_link_head->count != 0) { - acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - if(acl_entry_link->entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp = NULL; - } - - acl_entry_link->entryp->ace_len = acl_entry->ace_len; - - /* Don't really need this since all types are going * - * to be specified but, it's better than leaving it 0 */ - - acl_entry_link->entryp->ace_type = acl_entry->ace_type; - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - - memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id)); - - /* The access in the acl entries must be left shifted by * - * three bites, because they will ultimately be compared * - * to S_IRUSR, S_IWUSR, and S_IXUSR. */ - - switch(acl_entry->ace_type){ - case ACC_PERMIT: - case ACC_SPECIFY: - acl_entry_link->entryp->ace_access = acl_entry->ace_access; - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - case ACC_DENY: - /* Since there is no way to return a DENY acl entry * - * change to PERMIT and then shift. */ - DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); - acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7; - DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access)); - acl_entry_link->entryp->ace_access <<= 6; - acl_entry_link_head->count++; - break; - default: - return(0); - } - - DEBUG(10,("acl_entry = %d\n",acl_entry)); - DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); - - acl_entry = acl_nxt(acl_entry); - } - } /* end of if enabled */ - - /* Since owner, group, other acl entries are not * - * part of the acl entries in an acl, they must * - * be dummied up to become part of the list. */ - - for( i = 1; i < 4; i++) { - DEBUG(10,("i is %d\n",i)); - if(acl_entry_link_head->count != 0){ - acl_entry_link->nextp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); - if(acl_entry_link->nextp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - SAFE_FREE(file_acl); - return(NULL); - } - - acl_entry_link->nextp->prevp = acl_entry_link; - acl_entry_link = acl_entry_link->nextp; - acl_entry_link->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - - if(acl_entry_link->entryp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno)); - return(NULL); - } - } - - acl_entry_link->nextp = NULL; - - new_acl_entry = acl_entry_link->entryp; - idp = new_acl_entry->ace_id; - - new_acl_entry->ace_len = sizeof(struct acl_entry); - new_acl_entry->ace_type = ACC_PERMIT; - idp->id_len = sizeof(struct ace_id); - DEBUG(10,("idp->id_len = %d\n",idp->id_len)); - memset(idp->id_data,0,sizeof(uid_t)); - - switch(i) { - case 2: - new_acl_entry->ace_access = file_acl->g_access << 6; - idp->id_type = SMB_ACL_GROUP_OBJ; - break; - - case 3: - new_acl_entry->ace_access = file_acl->o_access << 6; - idp->id_type = SMB_ACL_OTHER; - break; - - case 1: - new_acl_entry->ace_access = file_acl->u_access << 6; - idp->id_type = SMB_ACL_USER_OBJ; - break; - - default: - return(NULL); - } - - acl_entry_link_head->count++; - DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access)); - } - - acl_entry_link_head->count = 0; - SAFE_FREE(file_acl); - - return(acl_entry_link_head); -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - *permset = *permset & ~0777; - return(0); -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - if((perm != 0) && - (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0) - return(-1); - - *permset |= perm; - DEBUG(10,("This is the permset now: %d\n",*permset)); - return(0); -} - -char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen) -{ - return(NULL); -} - -SMB_ACL_T sys_acl_init( int count) -{ - struct acl_entry_link *theacl = NULL; - - DEBUG(10,("Entering sys_acl_init\n")); - - theacl = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); - if(theacl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_init is %d\n",errno)); - return(NULL); - } - - theacl->count = 0; - theacl->nextp = NULL; - theacl->prevp = NULL; - theacl->entryp = NULL; - DEBUG(10,("Exiting sys_acl_init\n")); - return(theacl); -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - struct acl_entry_link *theacl; - struct acl_entry_link *acl_entryp; - struct acl_entry_link *temp_entry; - int counting; - - DEBUG(10,("Entering the sys_acl_create_entry\n")); - - theacl = acl_entryp = *pacl; - - /* Get to the end of the acl before adding entry */ - - for(counting=0; counting < theacl->count; counting++){ - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - temp_entry = acl_entryp; - acl_entryp = acl_entryp->nextp; - } - - if(theacl->count != 0){ - temp_entry->nextp = acl_entryp = (struct acl_entry_link *)malloc(sizeof(struct acl_entry_link)); - if(acl_entryp == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - DEBUG(10,("The acl_entryp is %d\n",acl_entryp)); - acl_entryp->prevp = temp_entry; - DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp)); - } - - *pentry = acl_entryp->entryp = (struct new_acl_entry *)malloc(sizeof(struct new_acl_entry)); - if(*pentry == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno)); - return(-1); - } - - memset(*pentry,0,sizeof(struct new_acl_entry)); - acl_entryp->entryp->ace_len = sizeof(struct acl_entry); - acl_entryp->entryp->ace_type = ACC_PERMIT; - acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id); - acl_entryp->nextp = NULL; - theacl->count++; - DEBUG(10,("Exiting sys_acl_create_entry\n")); - return(0); -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - DEBUG(10,("Starting AIX sys_acl_set_tag_type\n")); - entry->ace_id->id_type = tagtype; - DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type)); - DEBUG(10,("Ending AIX sys_acl_set_tag_type\n")); -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - DEBUG(10,("Starting AIX sys_acl_set_qualifier\n")); - memcpy(entry->ace_id->id_data,qual,sizeof(uid_t)); - DEBUG(10,("Ending AIX sys_acl_set_qualifier\n")); - return(0); -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - DEBUG(10,("Starting AIX sys_acl_set_permset\n")); - if(!(*permset & S_IXUSR) && - !(*permset & S_IWUSR) && - !(*permset & S_IRUSR) && - (*permset != 0)) - return(-1); - - entry->ace_access = *permset; - DEBUG(10,("entry->ace_access = %d\n",entry->ace_access)); - DEBUG(10,("Ending AIX sys_acl_set_permset\n")); - return(0); -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - int user_obj = 0; - int group_obj = 0; - int other_obj = 0; - struct acl_entry_link *acl_entry; - - for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) { - user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ); - group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ); - other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER); - } - - DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj)); - - if(user_obj != 1 || group_obj != 1 || other_obj != 1) - return(-1); - - return(0); -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint ace_access; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_file\n")); - DEBUG(10,("File name is %s\n",name)); - - /* AIX has no default ACL */ - if(acltype == SMB_ACL_TYPE_DEFAULT) - return(0); - - acl_length = BUFSIZ; - file_acl = (struct acl *)malloc(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)malloc(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_file is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = chacl(name,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting the sys_acl_set_file\n")); - return(rc); -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - struct acl_entry_link *acl_entry_link = NULL; - struct acl *file_acl = NULL; - struct acl *file_acl_temp = NULL; - struct acl_entry *acl_entry = NULL; - struct ace_id *ace_id = NULL; - uint id_type; - uint user_id; - uint acl_length; - uint rc; - - DEBUG(10,("Entering sys_acl_set_fd\n")); - acl_length = BUFSIZ; - file_acl = (struct acl *)malloc(BUFSIZ); - - if(file_acl == NULL) { - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memset(file_acl,0,BUFSIZ); - - file_acl->acl_len = ACL_SIZ; - file_acl->acl_mode = S_IXACL; - - for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) { - acl_entry_link->entryp->ace_access >>= 6; - id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id_type is %d\n",id_type)); - - switch(id_type) { - case SMB_ACL_USER_OBJ: - file_acl->u_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_GROUP_OBJ: - file_acl->g_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_OTHER: - file_acl->o_access = acl_entry_link->entryp->ace_access; - continue; - case SMB_ACL_MASK: - continue; - } - - if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { - acl_length += sizeof(struct acl_entry); - file_acl_temp = (struct acl *)malloc(acl_length); - if(file_acl_temp == NULL) { - SAFE_FREE(file_acl); - errno = ENOMEM; - DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno)); - return(-1); - } - - memcpy(file_acl_temp,file_acl,file_acl->acl_len); - SAFE_FREE(file_acl); - file_acl = file_acl_temp; - } - - acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); - file_acl->acl_len += sizeof(struct acl_entry); - acl_entry->ace_len = acl_entry_link->entryp->ace_len; - acl_entry->ace_access = acl_entry_link->entryp->ace_access; - - /* In order to use this, we'll need to wait until we can get denies */ - /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) - acl_entry->ace_type = ACC_SPECIFY; */ - - acl_entry->ace_type = ACC_SPECIFY; - - ace_id = acl_entry->ace_id; - - ace_id->id_type = acl_entry_link->entryp->ace_id->id_type; - DEBUG(10,("The id type is %d\n",ace_id->id_type)); - ace_id->id_len = acl_entry_link->entryp->ace_id->id_len; - memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t)); - memcpy(ace_id->id_data, &user_id, sizeof(uid_t)); - } - - rc = fchacl(fd,file_acl,file_acl->acl_len); - DEBUG(10,("errno is %d\n",errno)); - DEBUG(10,("return code is %d\n",rc)); - SAFE_FREE(file_acl); - DEBUG(10,("Exiting sys_acl_set_fd\n")); - return(rc); -} - -int sys_acl_delete_def_file(const char *name) -{ - /* AIX has no default ACL */ - return 0; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return(*permset & perm); -} - -int sys_acl_free_text(char *text) -{ - return(0); -} - -int sys_acl_free_acl(SMB_ACL_T posix_acl) -{ - struct acl_entry_link *acl_entry_link; - - for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) { - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - } - - SAFE_FREE(acl_entry_link->prevp->entryp); - SAFE_FREE(acl_entry_link->prevp); - SAFE_FREE(acl_entry_link->entryp); - SAFE_FREE(acl_entry_link); - - return(0); -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - return(0); -} - -#else /* No ACLs. */ - -int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - errno = ENOSYS; - return -1; -} - -void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d) -{ - errno = ENOSYS; - return NULL; -} - -SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type) -{ - errno = ENOSYS; - return (SMB_ACL_T)NULL; -} - -SMB_ACL_T sys_acl_get_fd(int fd) -{ - errno = ENOSYS; - return (SMB_ACL_T)NULL; -} - -int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - errno = ENOSYS; - return (permset & perm) ? 1 : 0; -} - -char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen) -{ - errno = ENOSYS; - return NULL; -} - -int sys_acl_free_text(char *text) -{ - errno = ENOSYS; - return -1; -} - -SMB_ACL_T sys_acl_init( int count) -{ - errno = ENOSYS; - return NULL; -} - -int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_valid( SMB_ACL_T theacl ) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_set_fd( int fd, SMB_ACL_T theacl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_delete_def_file(const char *name) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_free_acl(SMB_ACL_T the_acl) -{ - errno = ENOSYS; - return -1; -} - -int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype) -{ - errno = ENOSYS; - return -1; -} - -#endif /* No ACLs. */ diff --git a/source4/lib/username.c b/source4/lib/username.c index 2d9d212858..1c8e5aa2bb 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -21,10 +21,6 @@ #include "includes.h" -/* internal functions */ -static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N); -static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N); - /***************************************************************** Splits passed user or group name to domain and user/group name parts Returns True if name was splitted and False otherwise. @@ -52,317 +48,3 @@ BOOL split_domain_and_name(const char *name, char *domain, char* username) DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and name is |%s|\n", domain, username)); return True; } - -/**************************************************************************** - Get a users home directory. -****************************************************************************/ - -char *get_user_home_dir(const char *user) -{ - struct passwd *pass; - - /* Ensure the user exists. */ - - pass = Get_Pwnam(user); - - if (!pass) - return(NULL); - /* Return home directory from struct passwd. */ - - return(pass->pw_dir); -} - - -/**************************************************************************** - * A wrapper for sys_getpwnam(). The following variations are tried: - * - as transmitted - * - in all lower case if this differs from transmitted - * - in all upper case if this differs from transmitted - * - using lp_usernamelevel() for permutations. -****************************************************************************/ - -static struct passwd *Get_Pwnam_ret = NULL; - -static struct passwd *Get_Pwnam_internals(const char *user, char *user2) -{ - struct passwd *ret = NULL; - - if (!user2 || !(*user2)) - return(NULL); - - if (!user || !(*user)) - return(NULL); - - /* Try in all lower case first as this is the most - common case on UNIX systems */ - strlower(user2); - DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); - ret = getpwnam_alloc(user2); - if(ret) - goto done; - - /* Try as given, if username wasn't originally lowercase */ - if(strcmp(user, user2) != 0) { - DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n", user)); - ret = getpwnam_alloc(user); - if(ret) - goto done; - } - - /* Try as uppercase, if username wasn't originally uppercase */ - strupper(user2); - if(strcmp(user, user2) != 0) { - DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", user2)); - ret = getpwnam_alloc(user2); - if(ret) - goto done; - } - - /* Try all combinations up to usernamelevel */ - strlower(user2); - DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", lp_usernamelevel(), user2)); - ret = uname_string_combinations(user2, getpwnam_alloc, lp_usernamelevel()); - -done: - DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ? "did":"didn't", user)); - - /* This call used to just return the 'passwd' static buffer. - This could then have accidental reuse implications, so - we now malloc a copy, and free it in the next use. - - This should cause the (ab)user to segfault if it - uses an old struct. - - This is better than useing the wrong data in security - critical operations. - - The real fix is to make the callers free the returned - malloc'ed data. - */ - - if (Get_Pwnam_ret) { - passwd_free(&Get_Pwnam_ret); - } - - Get_Pwnam_ret = ret; - - return ret; -} - -/**************************************************************************** - Get_Pwnam wrapper without modification. - NOTE: This with NOT modify 'user'! -****************************************************************************/ - -struct passwd *Get_Pwnam(const char *user) -{ - fstring user2; - struct passwd *ret; - - fstrcpy(user2, user); - - DEBUG(5,("Finding user %s\n", user)); - - ret = Get_Pwnam_internals(user, user2); - - return ret; -} - -/**************************************************************************** - Check if a user is in a UNIX group. -****************************************************************************/ -static BOOL user_in_unix_group_list(const char *user,const char *gname) -{ - struct passwd *pass = Get_Pwnam(user); - struct sys_userlist *user_list; - struct sys_userlist *member; - TALLOC_CTX *mem_ctx; - - DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n", user, gname)); - - /* - * We need to check the users primary group as this - * group is implicit and often not listed in the group database. - */ - - mem_ctx = talloc_init("smbgroupedit talloc"); - if (!mem_ctx) return -1; - if (pass) { - if (strequal(gname,gidtoname(mem_ctx, pass->pw_gid))) { - DEBUG(10,("user_in_unix_group_list: group %s is primary group.\n", gname )); - goto exit; - } - } - - user_list = get_users_in_group(gname); - if (user_list == NULL) { - DEBUG(10,("user_in_unix_group_list: no such group %s\n", gname )); - return False; - } - - for (member = user_list; member; member = member->next) { - DEBUG(10,("user_in_unix_group_list: checking user %s against member %s\n", - user, member->unix_name )); - if (strequal(member->unix_name,user)) { - free_userlist(user_list); - goto exit; - } - } - - free_userlist(user_list); - talloc_destroy(mem_ctx); - return False; -exit: - talloc_destroy(mem_ctx); - return True; -} - -/**************************************************************************** - Check if a user is in a group list. Ask winbind first, then use UNIX. -****************************************************************************/ -static BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, size_t n_groups) -{ - BOOL ret; - gid_t gid; - unsigned i; - - gid = nametogid(gname); - if (gid == (gid_t)-1) - return False; - - if (groups && n_groups > 0) { - for (i=0; i < n_groups; i++) { - if (groups[i] == gid) { - return True; - } - } - return False; - } - - /* fallback if we don't yet have the group list */ - ret = user_in_unix_group_list(user, gname); - if (ret) - DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n", user, gname)); - return ret; -} - -/**************************************************************************** - Check if a user is in a user list - can check combinations of UNIX - and netgroup lists. -****************************************************************************/ - -BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_groups) -{ - if (!list || !*list) - return False; - - DEBUG(10,("user_in_list: checking user %s in list\n", user)); - - while (*list) { - - DEBUG(10,("user_in_list: checking user |%s| against |%s|\n", user, *list)); - - /* - * Check raw username. - */ - if (strequal(user, *list)) - return(True); - - /* - * Now check to see if any combination - * of UNIX and netgroups has been specified. - */ - - if(**list == '@') { - /* - * Old behaviour. Check netgroup list - * followed by UNIX list. - */ - if(user_in_group_list(user, *list +1, groups, n_groups)) - return True; - } else if (**list == '+') { - - if((*(*list +1)) == '&') { - /* - * Search UNIX list followed by netgroup. - */ - if(user_in_group_list(user, *list +2, groups, n_groups)) - return True; - } else { - - /* - * Just search UNIX list. - */ - - if(user_in_group_list(user, *list +1, groups, n_groups)) - return True; - } - - } else if (**list == '&') { - - if(*(*list +1) == '+') { - /* - * Search netgroup list followed by UNIX list. - */ - if(user_in_group_list(user, *list +2, groups, n_groups)) - return True; - } - } - - list++; - } - return(False); -} - -/* The functions below have been taken from password.c and slightly modified */ -/**************************************************************************** - Apply a function to upper/lower case combinations - of a string and return true if one of them returns true. - Try all combinations with N uppercase letters. - offset is the first char to try and change (start with 0) - it assumes the string starts lowercased -****************************************************************************/ - -static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(const char *),int N) -{ - ssize_t len = (ssize_t)strlen(s); - int i; - struct passwd *ret; - - if (N <= 0 || offset >= len) - return(fn(s)); - - for (i=offset;i<(len-(N-1));i++) { - char c = s[i]; - if (!islower((int)c)) - continue; - s[i] = toupper(c); - ret = uname_string_combinations2(s,i+1,fn,N-1); - if(ret) - return(ret); - s[i] = c; - } - return(NULL); -} - -/**************************************************************************** - Apply a function to upper/lower case combinations - of a string and return true if one of them returns true. - Try all combinations with up to N uppercase letters. - offset is the first char to try and change (start with 0) - it assumes the string starts lowercased -****************************************************************************/ - -static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(const char *),int N) -{ - int n; - struct passwd *ret; - - for (n=1;n<=N;n++) { - ret = uname_string_combinations2(s,0,fn,n); - if(ret) - return(ret); - } - return(NULL); -} - -- cgit From b744493be566d1edcfcc9c4b0d1bfbc271918203 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 23:01:20 +0000 Subject: r862: remove acl and sendfile stuff it will be readded inside the ntvfs_posix module metze (This used to be commit ec624aefa86934da23105a5c014080b464efac28) --- source4/lib/basic.mk | 1 - source4/lib/sendfile.c | 382 ------------------------------------------------- 2 files changed, 383 deletions(-) delete mode 100644 source4/lib/sendfile.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 3a1f127853..865ba7342f 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -14,7 +14,6 @@ ADD_OBJ_FILES = \ lib/replace.o \ lib/signal.o \ lib/system.o \ - lib/sendfile.o \ lib/time.o \ lib/genrand.o \ lib/username.o \ diff --git a/source4/lib/sendfile.c b/source4/lib/sendfile.c deleted file mode 100644 index bcc8cb08ca..0000000000 --- a/source4/lib/sendfile.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.2.x / 3.0.x - sendfile implementations. - Copyright (C) Jeremy Allison 2002. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * This file handles the OS dependent sendfile implementations. - * The API is such that it returns -1 on error, else returns the - * number of bytes written. - */ - -#include "includes.h" - -#if defined(LINUX_SENDFILE_API) - -#include - -#ifndef MSG_MORE -#define MSG_MORE 0x8000 -#endif - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - size_t total=0; - ssize_t ret; - size_t hdr_len = 0; - - /* - * Send the header first. - * Use MSG_MORE to cork the TCP output until sendfile is called. - */ - - if (header) { - hdr_len = header->length; - while (total < hdr_len) { - ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); - if (ret == -1) - return -1; - total += ret; - } - } - - total = count; - while (total) { - ssize_t nwritten; - do { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) - nwritten = sendfile64(tofd, fromfd, &offset, total); -#else - nwritten = sendfile(tofd, fromfd, &offset, total); -#endif - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - total -= nwritten; - } - return count + hdr_len; -} - -#elif defined(LINUX_BROKEN_SENDFILE_API) - -/* - * We must use explicit 32 bit types here. This code path means Linux - * won't do proper 64-bit sendfile. JRA. - */ - -extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count); - - -#ifndef MSG_MORE -#define MSG_MORE 0x8000 -#endif - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - size_t total=0; - ssize_t ret; - ssize_t hdr_len = 0; - uint32 small_total = 0; - int32 small_offset; - - /* - * Fix for broken Linux 2.4 systems with no working sendfile64(). - * If the offset+count > 2 GB then pretend we don't have the - * system call sendfile at all. The upper layer catches this - * and uses a normal read. JRA. - */ - - if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) { - errno = ENOSYS; - return -1; - } - - /* - * Send the header first. - * Use MSG_MORE to cork the TCP output until sendfile is called. - */ - - if (header) { - hdr_len = header->length; - while (total < hdr_len) { - ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); - if (ret == -1) - return -1; - total += ret; - } - } - - small_total = (uint32)count; - small_offset = (int32)offset; - - while (small_total) { - int32 nwritten; - do { - nwritten = sendfile(tofd, fromfd, &small_offset, small_total); - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - small_total -= nwritten; - } - return count + hdr_len; -} - - -#elif defined(SOLARIS_SENDFILE_API) - -/* - * Solaris sendfile code written by Pierre Belanger . - */ - -#include - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - int sfvcnt; - size_t total, xferred; - struct sendfilevec vec[2]; - ssize_t hdr_len = 0; - - if (header) { - sfvcnt = 2; - - vec[0].sfv_fd = SFV_FD_SELF; - vec[0].sfv_flag = 0; - vec[0].sfv_off = header->data; - vec[0].sfv_len = hdr_len = header->length; - - vec[1].sfv_fd = fromfd; - vec[1].sfv_flag = 0; - vec[1].sfv_off = offset; - vec[1].sfv_len = count; - - } else { - sfvcnt = 1; - - vec[0].sfv_fd = fromfd; - vec[0].sfv_flag = 0; - vec[0].sfv_off = offset; - vec[0].sfv_len = count; - } - - total = count + hdr_len; - - while (total) { - ssize_t nwritten; - - /* - * Although not listed in the API error returns, this is almost certainly - * a slow system call and will be interrupted by a signal with EINTR. JRA. - */ - - xferred = 0; - -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64) - nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); -#else - nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); -#endif - if (nwritten == -1 && errno == EINTR) { - if (xferred == 0) - continue; /* Nothing written yet. */ - else - nwritten = xferred; - } - - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - - /* - * If this was a short (signal interrupted) write we may need - * to subtract it from the header data, or null out the header - * data altogether if we wrote more than vec[0].sfv_len bytes. - * We move vec[1].* to vec[0].* and set sfvcnt to 1 - */ - - if (sfvcnt == 2 && nwritten >= vec[0].sfv_len) { - vec[1].sfv_off += nwritten - vec[0].sfv_len; - vec[1].sfv_len -= nwritten - vec[0].sfv_len; - - /* Move vec[1].* to vec[0].* and set sfvcnt to 1 */ - vec[0] = vec[1]; - sfvcnt = 1; - } else { - vec[0].sfv_off += nwritten; - vec[0].sfv_len -= nwritten; - } - total -= nwritten; - } - return count + hdr_len; -} - -#elif defined(HPUX_SENDFILE_API) - -#include -#include - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - size_t total=0; - struct iovec hdtrl[2]; - size_t hdr_len = 0; - - if (header) { - /* Set up the header/trailer iovec. */ - hdtrl[0].iov_base = header->data; - hdtrl[0].iov_len = hdr_len = header->length; - } else { - hdtrl[0].iov_base = NULL; - hdtrl[0].iov_len = hdr_len = 0; - } - hdtrl[1].iov_base = NULL; - hdtrl[1].iov_base = 0; - - total = count; - while (total + hdtrl[0].iov_len) { - ssize_t nwritten; - - /* - * HPUX guarantees that if any data was written before - * a signal interrupt then sendfile returns the number of - * bytes written (which may be less than requested) not -1. - * nwritten includes the header data sent. - */ - - do { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) - nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0); -#else - nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0); -#endif - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - - /* - * If this was a short (signal interrupted) write we may need - * to subtract it from the header data, or null out the header - * data altogether if we wrote more than hdtrl[0].iov_len bytes. - * We change nwritten to be the number of file bytes written. - */ - - if (hdtrl[0].iov_base && hdtrl[0].iov_len) { - if (nwritten >= hdtrl[0].iov_len) { - nwritten -= hdtrl[0].iov_len; - hdtrl[0].iov_base = NULL; - hdtrl[0].iov_len = 0; - } else { - /* iov_base is defined as a void *... */ - hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten; - hdtrl[0].iov_len -= nwritten; - nwritten = 0; - } - } - total -= nwritten; - offset += nwritten; - } - return count + hdr_len; -} - -#elif defined(FREEBSD_SENDFILE_API) - -#include -#include -#include - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - size_t total=0; - struct sf_hdtr hdr; - struct iovec hdtrl; - size_t hdr_len = 0; - - hdr.headers = &hdtrl; - hdr.hdr_cnt = 1; - hdr.trailers = NULL; - hdr.trl_cnt = 0; - - /* Set up the header iovec. */ - if (header) { - hdtrl.iov_base = header->data; - hdtrl.iov_len = hdr_len = header->length; - } else { - hdtrl.iov_base = NULL; - hdtrl.iov_len = 0; - } - - total = count; - while (total + hdtrl.iov_len) { - SMB_OFF_T nwritten; - int ret; - - /* - * FreeBSD sendfile returns 0 on success, -1 on error. - * Remember, the tofd and fromfd are reversed..... :-). - * nwritten includes the header data sent. - */ - - do { - ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0); - } while (ret == -1 && errno == EINTR); - if (ret == -1) - return -1; - - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - - /* - * If this was a short (signal interrupted) write we may need - * to subtract it from the header data, or null out the header - * data altogether if we wrote more than hdtrl.iov_len bytes. - * We change nwritten to be the number of file bytes written. - */ - - if (hdtrl.iov_base && hdtrl.iov_len) { - if (nwritten >= hdtrl.iov_len) { - nwritten -= hdtrl.iov_len; - hdtrl.iov_base = NULL; - hdtrl.iov_len = 0; - } else { - hdtrl.iov_base += nwritten; - hdtrl.iov_len -= nwritten; - nwritten = 0; - } - } - total -= nwritten; - offset += nwritten; - } - return count + hdr_len; -} - -#else /* No sendfile implementation. Return error. */ - -ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -{ - /* No sendfile syscall. */ - errno = ENOSYS; - return -1; -} -#endif -- cgit From 579c13da43d5b40ac6d6c1436399fbc1d8dfd054 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 May 2004 13:57:39 +0000 Subject: r873: converted samba4 to use real 64 bit integers instead of structures. This was suggested by metze recently. I checked on the build farm and all the machines we have support 64 bit ints, and support the LL suffix for 64 bit constants. I suspect some won't support strtoll() and related functions, so we will probably need replacements for those. (This used to be commit 9a9244a1c66654c12abe4379661cba83a73c4c21) --- source4/lib/fsusage.c | 18 ++-- source4/lib/ldb/common/ldb_msg.c | 22 +++++ .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 3 +- source4/lib/system.c | 30 ------- source4/lib/time.c | 99 +++++----------------- 5 files changed, 55 insertions(+), 117 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/fsusage.c b/source4/lib/fsusage.c index bb7cff0645..bff6fdda03 100644 --- a/source4/lib/fsusage.c +++ b/source4/lib/fsusage.c @@ -24,7 +24,7 @@ /* Return the number of TOSIZE-byte blocks used by BLOCKS FROMSIZE-byte blocks, rounding away from zero. */ -static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SMB_BIG_UINT tosize) +static uint64_t adjust_blocks(uint64_t blocks, uint64_t fromsize, uint64_t tosize) { if (fromsize == tosize) /* e.g., from 512 to 512 */ return blocks; @@ -40,10 +40,10 @@ static SMB_BIG_UINT adjust_blocks(SMB_BIG_UINT blocks, SMB_BIG_UINT fromsize, SM results are returned in *dfree and *dsize, in 512 byte units */ -int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize) { #ifdef STAT_STATFS3_OSF1 -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) struct statfs fsd; if (statfs (path, &fsd, sizeof (struct statfs)) != 0) @@ -51,7 +51,7 @@ int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #endif /* STAT_STATFS3_OSF1 */ #ifdef STAT_STATFS2_FS_DATA /* Ultrix */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)1024, (SMB_BIG_UINT)512) +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512) struct fs_data fsd; if (statfs (path, &fsd) != 1) @@ -62,7 +62,7 @@ int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #endif /* STAT_STATFS2_FS_DATA */ #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) struct statfs fsd; if (statfs (path, &fsd) < 0) @@ -84,7 +84,7 @@ int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ -#define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_fsize, (SMB_BIG_UINT)512) +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) struct statfs fsd; @@ -94,12 +94,12 @@ int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ # if _AIX || defined(_CRAY) -# define CONVERT_BLOCKS(B) adjust_blocks ((SMB_BIG_UINT)(B), (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) +# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) # ifdef _CRAY # define f_bavail f_bfree # endif # else -# define CONVERT_BLOCKS(B) ((SMB_BIG_UINT)B) +# define CONVERT_BLOCKS(B) ((uint64_t)B) # ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ # ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ # define f_bavail f_bfree @@ -119,7 +119,7 @@ int sys_fsusage(const char *path, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) #if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ # define CONVERT_BLOCKS(B) \ - adjust_blocks ((SMB_BIG_UINT)(B), fsd.f_frsize ? (SMB_BIG_UINT)fsd.f_frsize : (SMB_BIG_UINT)fsd.f_bsize, (SMB_BIG_UINT)512) + adjust_blocks ((uint64_t)(B), fsd.f_frsize ? (uint64_t)fsd.f_frsize : (uint64_t)fsd.f_bsize, (uint64_t)512) #ifdef STAT_STATVFS64 struct statvfs64 fsd; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 59d480a33a..055569b0ee 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -235,6 +235,28 @@ unsigned int ldb_msg_find_uint(const struct ldb_message *msg, return strtoul(v->data, NULL, 0); } +int64_t ldb_msg_find_int64(const struct ldb_message *msg, + const char *attr_name, + int64_t default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { + return default_value; + } + return strtoll(v->data, NULL, 0); +} + +uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, + const char *attr_name, + uint64_t default_value) +{ + const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + if (!v || !v->data) { + return default_value; + } + return strtoull(v->data, NULL, 0); +} + double ldb_msg_find_double(const struct ldb_message *msg, const char *attr_name, double default_value) diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index e4f9447488..415f764f61 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -608,8 +608,7 @@ static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) #define REG_HANDLE_REGTYPE_NT 1 #define REG_HANDLE_REGTYPE_W9X 2 -#define TTTONTTIME(r, t1, t2) (r)->last_mod_time.low = (t1); \ - (r)->last_mod_time.high = (t2); +#define TTTONTTIME(r, t1, t2) (r)->last_mod_time = (t1) | (((uint64_t)(t2)) << 32) #define REGF_HDR_BLKSIZ 0x1000 diff --git a/source4/lib/system.c b/source4/lib/system.c index 98d975aa50..8c9627eb26 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -247,36 +247,6 @@ SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence) #endif } -/******************************************************************* - An fseek() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64) - return fseek64(fp, offset, whence); -#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64) - return fseeko64(fp, offset, whence); -#else - return fseek(fp, offset, whence); -#endif -} - -/******************************************************************* - An ftell() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -SMB_OFF_T sys_ftell(FILE *fp) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64) - return (SMB_OFF_T)ftell64(fp); -#elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64) - return (SMB_OFF_T)ftello64(fp); -#else - return (SMB_OFF_T)ftell(fp); -#endif -} - /******************************************************************* A creat() wrapper that will deal with 64 bit filesizes. ********************************************************************/ diff --git a/source4/lib/time.c b/source4/lib/time.c index ba650668c5..e3811c884e 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -23,11 +23,10 @@ #include "includes.h" #ifndef TIME_T_MIN -#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ - : ~ (time_t) 0 << (sizeof (time_t) * 8 - 1)) +#define TIME_T_MIN 0 #endif #ifndef TIME_T_MAX -#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) +#define TIME_T_MAX (~(time_t)0) #endif /******************************************************************* @@ -84,35 +83,23 @@ int get_time_zone(time_t t) return tm_diff(&tm_utc,tm); } -#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) +#define TIME_FIXUP_CONSTANT 11644473600LL /**************************************************************************** interpret an 8 byte "filetime" structure to a time_t It's originally in "100ns units since jan 1st 1601" ****************************************************************************/ -time_t nt_time_to_unix(const NTTIME *nt) +time_t nt_time_to_unix(NTTIME nt) { - double d; - time_t ret; + nt += 1000*1000*10/2; + nt /= 1000*1000*10; + nt -= TIME_FIXUP_CONSTANT; - if (nt->high == 0) { + if (TIME_T_MIN >= nt || nt >= TIME_T_MAX) { return 0; } - d = ((double)nt->high)*4.0*(double)(1<<30); - d += (nt->low&0xFFF00000); - d *= 1.0e-7; - - /* now adjust by 369 years to make the secs since 1970 */ - d -= TIME_FIXUP_CONSTANT; - - if (TIME_T_MIN >= d || d >= TIME_T_MAX) { - return 0; - } - - ret = (time_t)(d+0.5); - - return ret; + return (time_t)nt; } @@ -122,30 +109,22 @@ This takes GMT as input ****************************************************************************/ void unix_to_nt_time(NTTIME *nt, time_t t) { - double d; + uint64_t t2; - if (t==0) { - nt->low = 0; - nt->high = 0; - return; - } - if (t == TIME_T_MAX) { - nt->low = 0xffffffff; - nt->high = 0x7fffffff; + if (t == (time_t)-1) { + *nt = (NTTIME)-1LL; return; } - if (t == -1) { - nt->low = 0xffffffff; - nt->high = 0xffffffff; + if (t == 0) { + *nt = 0; return; } - d = (double)(t); - d += TIME_FIXUP_CONSTANT; - d *= 1.0e7; + t2 = t; + t2 += TIME_FIXUP_CONSTANT; + t2 *= 1000*1000*10; - nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); + *nt = t2; } @@ -390,18 +369,10 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) return TimeBuf; } -/**************************************************************************** -check if NTTIME is 0 -****************************************************************************/ -BOOL nt_time_is_zero(NTTIME *nt) -{ - return (nt->high==0); -} - /* return a talloced string representing a NTTIME for human consumption */ -const char *nt_time_string(TALLOC_CTX *mem_ctx, const NTTIME *nt) +const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) { time_t t = nt_time_to_unix(nt); return talloc_strdup(mem_ctx, timestring(mem_ctx, t)); @@ -411,10 +382,9 @@ const char *nt_time_string(TALLOC_CTX *mem_ctx, const NTTIME *nt) /* put a NTTIME into a packet */ -void push_nttime(void *base, uint16 offset, NTTIME *t) +void push_nttime(void *base, uint16 offset, NTTIME t) { - SIVAL(base, offset, t->low); - SIVAL(base, offset+4, t->high); + SBVAL(base, offset, t); } /* @@ -422,30 +392,7 @@ void push_nttime(void *base, uint16 offset, NTTIME *t) */ NTTIME pull_nttime(void *base, uint16 offset) { - NTTIME ret; - ret.low = IVAL(base, offset); - ret.high = IVAL(base, offset+4); - return ret; -} - -/* - convert a NTTIME to a double in 100-nano-seconds since 1601 -*/ -double nttime_to_double_nt(NTTIME t) -{ - const double t32 = 4294967296.0; - return t.high*t32 + t.low; -} - -/* - convert a double in 100-nano-seconds since 1601 to a NTTIME -*/ -NTTIME nttime_from_double_nt(double t) -{ - const double t32 = 4294967296.0; - NTTIME ret; - ret.high = t / t32; - ret.low = t - (ret.high*t32); + NTTIME ret = BVAL(base, offset); return ret; } @@ -454,5 +401,5 @@ NTTIME nttime_from_double_nt(double t) */ NTTIME nttime_from_string(const char *s) { - return nttime_from_double_nt(strtod(s, NULL)); + return strtoull(s, NULL, 0); } -- cgit From 5b0ab386cb0fb74d78e6c68abe1b047ab515b7b3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 25 May 2004 14:06:28 +0000 Subject: r874: This patch is a pile of work on NTLMSSP: Samba's NTLMSSP code is now fully talloc based, which should go a long way to cleaning up the memory leaks in this code. This also avoids a lot of extra copies of data, as we now allocate the 'return' blobs on a caller-supplied context. I have also been doing a lot of work towards NTLM2 signing and sealing. I have this working for sealing, but not for the verifier (MD5 integrity check on the stream) which is still incorrect. (I can aim a rpcecho sinkdata from a Win2k3 box to my server, and the data arrives intact, but the signature check fails. It does however match the test values I have...). The new torture test is cludged in - when we get a unit test suite back, I'll happliy put it in the 'right' place.... Andrew Bartlett (This used to be commit 399e2e2b1149b8d1c070aa7f0d5131c0b577d2b9) --- source4/lib/crypto/hmacmd5.c | 15 +----------- source4/lib/util_str.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index 8ca7dba841..7697ac8a69 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -77,20 +77,7 @@ void hmac_md5_init_limK_to_64(const uchar* key, int key_len, key_len = 64; } - /* start out by storing key in pads */ - ZERO_STRUCT(ctx->k_ipad); - ZERO_STRUCT(ctx->k_opad); - memcpy( ctx->k_ipad, key, key_len); - memcpy( ctx->k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - ctx->k_ipad[i] ^= 0x36; - ctx->k_opad[i] ^= 0x5c; - } - - MD5Init(&ctx->ctx); - MD5Update(&ctx->ctx, ctx->k_ipad, 64); + hmac_md5_init_rfc2104(key, key_len, ctx); } /*********************************************************************** diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 7bdec8c1e9..7d6505bab2 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1196,6 +1196,62 @@ void ipstr_list_free(char* ipstr_list) SAFE_FREE(ipstr_list); } +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + +**/ + +size_t strhex_to_str(char *p, size_t len, const char *strhex) +{ + size_t i; + size_t num_chars = 0; + unsigned char lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1 = NULL, *p2 = NULL; + + for (i = 0; i < len && strhex[i] != 0; i++) { + if (strnequal(hexchars, "0x", 2)) { + i++; /* skip two chars */ + continue; + } + + if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + i++; /* next hex digit */ + + if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + /* get the two nybbles */ + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + p[num_chars] = (hinybble << 4) | lonybble; + num_chars++; + + p1 = NULL; + p2 = NULL; + } + return num_chars; +} + +DATA_BLOB strhex_to_data_blob(const char *strhex) +{ + DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1); + + ret_blob.length = strhex_to_str(ret_blob.data, + strlen(strhex), + strhex); + + return ret_blob; +} + /** Unescape a URL encoded string, in place. -- cgit From f9d8f8843dc0ab8c9d59abde7222e0f118b86b5d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 25 May 2004 16:24:13 +0000 Subject: r884: convert samba4 to use [u]int32_t instead of [u]int32 metze (This used to be commit 0e5517d937a2eb7cf707991d1c7498c1ab456095) --- source4/lib/bitmap.c | 4 +- source4/lib/crypto/crc32.c | 4 +- source4/lib/crypto/md4.c | 28 ++++----- source4/lib/crypto/md5.c | 28 ++++----- source4/lib/debug.c | 2 +- source4/lib/genrand.c | 4 +- source4/lib/interface.c | 2 +- source4/lib/messages.c | 2 +- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/common/reg_objects.c | 2 +- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/registry/common/registry.h | 2 +- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 2 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 2 +- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 4 +- source4/lib/system.c | 4 +- source4/lib/tdb/common/tdbutil.c | 70 +++++++++++----------- source4/lib/time.c | 16 ++--- source4/lib/util.c | 12 ++-- source4/lib/util_sid.c | 8 +-- source4/lib/util_sock.c | 2 +- 21 files changed, 101 insertions(+), 101 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/bitmap.c b/source4/lib/bitmap.c index 1023dd6541..63b093617b 100644 --- a/source4/lib/bitmap.c +++ b/source4/lib/bitmap.c @@ -35,7 +35,7 @@ struct bitmap *bitmap_allocate(int n) if (!bm) return NULL; bm->n = n; - bm->b = (uint32 *)malloc(sizeof(bm->b[0])*(n+31)/32); + bm->b = (uint32_t *)malloc(sizeof(bm->b[0])*(n+31)/32); if (!bm->b) { SAFE_FREE(bm); return NULL; @@ -73,7 +73,7 @@ struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n) if (!bm) return NULL; bm->n = n; - bm->b = (uint32 *)talloc(mem_ctx, sizeof(bm->b[0])*(n+31)/32); + bm->b = (uint32_t *)talloc(mem_ctx, sizeof(bm->b[0])*(n+31)/32); if (!bm->b) { return NULL; } diff --git a/source4/lib/crypto/crc32.c b/source4/lib/crypto/crc32.c index da3aeaa901..f2d76332f9 100644 --- a/source4/lib/crypto/crc32.c +++ b/source4/lib/crypto/crc32.c @@ -55,9 +55,9 @@ static const unsigned long CRCTable[256] = 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; -uint32 crc32_calc_buffer( const char *buffer, uint32 count) +uint32_t crc32_calc_buffer( const char *buffer, uint32_t count) { - uint32 crc=0xffffffff, i; + uint32_t crc=0xffffffff, i; for(i=0;i>8) ^ CRCTable[(buffer[i] ^ crc) & 0xff]; crc^=0xffffffff; diff --git a/source4/lib/crypto/md4.c b/source4/lib/crypto/md4.c index 417e87bd8e..cc8b9b6841 100644 --- a/source4/lib/crypto/md4.c +++ b/source4/lib/crypto/md4.c @@ -26,40 +26,40 @@ */ struct mdfour_state { - uint32 A, B, C, D; + uint32_t A, B, C, D; }; -static uint32 F(uint32 X, uint32 Y, uint32 Z) +static uint32_t F(uint32_t X, uint32_t Y, uint32_t Z) { return (X&Y) | ((~X)&Z); } -static uint32 G(uint32 X, uint32 Y, uint32 Z) +static uint32_t G(uint32_t X, uint32_t Y, uint32_t Z) { return (X&Y) | (X&Z) | (Y&Z); } -static uint32 H(uint32 X, uint32 Y, uint32 Z) +static uint32_t H(uint32_t X, uint32_t Y, uint32_t Z) { return X^Y^Z; } -static uint32 lshift(uint32 x, int s) +static uint32_t lshift(uint32_t x, int s) { x &= 0xFFFFFFFF; return ((x<>(32-s)); } #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) -#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) -#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32_t)0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32_t)0x6ED9EBA1,s) /* this applies md4 to 64 byte chunks */ -static void mdfour64(struct mdfour_state *s, uint32 *M) +static void mdfour64(struct mdfour_state *s, uint32_t *M) { int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; + uint32_t AA, BB, CC, DD; + uint32_t X[16]; for (j=0;j<16;j++) X[j] = M[j]; @@ -107,7 +107,7 @@ static void mdfour64(struct mdfour_state *s, uint32 *M) X[j] = 0; } -static void copy64(uint32 *M, const unsigned char *in) +static void copy64(uint32_t *M, const unsigned char *in) { int i; @@ -116,7 +116,7 @@ static void copy64(uint32 *M, const unsigned char *in) (in[i*4+1]<<8) | (in[i*4+0]<<0); } -static void copy4(unsigned char *out, uint32 x) +static void copy4(unsigned char *out, uint32_t x) { out[0] = x&0xFF; out[1] = (x>>8)&0xFF; @@ -128,8 +128,8 @@ static void copy4(unsigned char *out, uint32 x) void mdfour(unsigned char *out, const unsigned char *in, int n) { unsigned char buf[128]; - uint32 M[16]; - uint32 b = n * 8; + uint32_t M[16]; + uint32_t b = n * 8; int i; struct mdfour_state state; diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index 2121b17047..dbb3462bd4 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -22,18 +22,18 @@ #include "md5.h" -static void MD5Transform(uint32 buf[4], uint32 const in[16]); +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { - uint32 t; + uint32_t t; do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; + *(uint32_t *) buf = t; buf += 4; } while (--longs); } @@ -59,12 +59,12 @@ void MD5Init(struct MD5Context *ctx) */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { - register uint32 t; + register uint32_t t; /* Update bitcount */ t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; @@ -82,7 +82,7 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) } memmove(p, buf, t); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += t; len -= t; } @@ -91,7 +91,7 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) while (len >= 64) { memmove(ctx->in, buf, 64); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += 64; len -= 64; } @@ -126,7 +126,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -137,10 +137,10 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) byteReverse(ctx->in, 14); /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; + ((uint32_t *) ctx->in)[14] = ctx->bits[0]; + ((uint32_t *) ctx->in)[15] = ctx->bits[1]; - MD5Transform(ctx->buf, (uint32 *) ctx->in); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memmove(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ @@ -163,9 +163,9 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ -static void MD5Transform(uint32 buf[4], uint32 const in[16]) +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { - register uint32 a, b, c, d; + register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; diff --git a/source4/lib/debug.c b/source4/lib/debug.c index dbd3946c81..c9247f380f 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -141,7 +141,7 @@ void print_suspicious_usage(const char* from, const char* info) } } -uint32 get_task_id(void) +uint32_t get_task_id(void) { if (debug_handlers.ops.get_task_id) { return debug_handlers.ops.get_task_id(); diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 9645dd7999..a5002969bd 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -23,7 +23,7 @@ #include "includes.h" static unsigned char hash[258]; -static uint32 counter; +static uint32_t counter; static unsigned char *reseed_data; static size_t reseed_data_size; @@ -134,7 +134,7 @@ static void do_filehash(const char *fname, unsigned char *the_hash) static int do_reseed(BOOL use_fd, int fd) { unsigned char seed_inbuf[40]; - uint32 v1, v2; struct timeval tval; pid_t mypid; + uint32_t v1, v2; struct timeval tval; pid_t mypid; if (use_fd) { if (fd != -1) diff --git a/source4/lib/interface.c b/source4/lib/interface.c index 2540c898ff..14abfbd09a 100644 --- a/source4/lib/interface.c +++ b/source4/lib/interface.c @@ -28,7 +28,7 @@ struct in_addr loopback_ip; static struct interface *local_interfaces; -#define ALLONES ((uint32)0xFFFFFFFF) +#define ALLONES ((uint32_t)0xFFFFFFFF) #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES)) #define MKNETADDR(_IP, _NM) (_IP & _NM) diff --git a/source4/lib/messages.c b/source4/lib/messages.c index cb26b356bd..9357b12f1f 100644 --- a/source4/lib/messages.c +++ b/source4/lib/messages.c @@ -474,7 +474,7 @@ void message_deregister(int msg_type) struct msg_all { int msg_type; - uint32 msg_flag; + uint32_t msg_flag; const void *buf; size_t len; BOOL duplicates; diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 6acedb3591..6d305e61bf 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -508,7 +508,7 @@ WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) return WERR_OK; } -WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **newkey) +WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **newkey) { WERROR error; diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index 168ee946e8..be15108f4d 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -85,7 +85,7 @@ char *reg_val_name( REG_VAL *val ) /********************************************************************** *********************************************************************/ -uint32 reg_val_type( REG_VAL *val ) +uint32_t reg_val_type( REG_VAL *val ) { return val->data_type; } diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 82b8d06679..353963f78d 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -105,7 +105,7 @@ WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *val return reg_key_get_value_by_name(k, valname, val); } -WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32 type, uint8 *data, int real_len) +WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8 *data, int real_len) { REG_KEY *k; REG_VAL *v; diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index 5325a89086..caa0e284bf 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -107,7 +107,7 @@ struct registry_ops { WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function); /* Key management */ - WERROR (*add_key)(REG_KEY *, const char *name, uint32 access_mask, SEC_DESC *, REG_KEY **); + WERROR (*add_key)(REG_KEY *, const char *name, uint32_t access_mask, SEC_DESC *, REG_KEY **); WERROR (*del_key)(REG_KEY *); /* Value management */ diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index c7ed95d80f..cac54f8437 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/registry/common/registry.h" -static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *desc, REG_KEY **result) +static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **result) { char *path; int ret; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 415f764f61..627b5a8f13 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -501,7 +501,7 @@ static DWORD str_to_dword(const char *a) { /* * Create an ACE */ -static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32 perms, const char *sid) +static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, const char *sid) { DOM_SID s; SEC_ACCESS access; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index d863568c17..28e2094bed 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -197,7 +197,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) struct winreg_EnumValueName vn; NTSTATUS status; struct rpc_key_data *mykeydata; - uint32 type = 0x0, requested_len = 0, returned_len = 0; + uint32_t type = 0x0, requested_len = 0, returned_len = 0; WERROR error; error = rpc_key_put_rpc_data(parent, &mykeydata); @@ -283,7 +283,7 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) return r.out.result; } -static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32 access_mask, SEC_DESC *sec, REG_KEY **key) +static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **key) { struct rpc_key_data *mykeydata; WERROR error; diff --git a/source4/lib/system.c b/source4/lib/system.c index 8c9627eb26..2641a180ef 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -410,7 +410,7 @@ struct hostent *sys_gethostbyname(const char *name) /************************************************************************** Try and abstract process capabilities (for systems that have them). ****************************************************************************/ -static BOOL set_process_capability( uint32 cap_flag, BOOL enable ) +static BOOL set_process_capability( uint32_t cap_flag, BOOL enable ) { if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { cap_t cap = cap_get_proc(); @@ -444,7 +444,7 @@ static BOOL set_process_capability( uint32 cap_flag, BOOL enable ) Try and abstract inherited process capabilities (for systems that have them). ****************************************************************************/ -static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable ) +static BOOL set_inherited_process_capability( uint32_t cap_flag, BOOL enable ) { if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { cap_t cap = cap_get_proc(); diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 62841ddfc2..b8babf48aa 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -180,15 +180,15 @@ void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) /**************************************************************************** - Fetch a int32 value by a arbitrary blob key, return -1 if not found. - Output is int32 in native byte order. + Fetch a int32_t value by a arbitrary blob key, return -1 if not found. + Output is int32_t in native byte order. ****************************************************************************/ -int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +int32_t tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) { TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; - int32 ret; + int32_t ret; data = tdb_fetch(tdb, key); if (!data.dptr || data.dsize != sizeof(int32)) { @@ -202,25 +202,25 @@ int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) } /**************************************************************************** - Fetch a int32 value by string key, return -1 if not found. - Output is int32 in native byte order. + Fetch a int32_t value by string key, return -1 if not found. + Output is int32_t in native byte order. ****************************************************************************/ -int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) { return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); } /**************************************************************************** - Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure. - Input is int32 in native byte order. Output in tdb is in little-endian. + Store a int32_t value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v) +int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32_t v) { TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; - int32 v_store; + int32_t v_store; SIVAL(&v_store,0,v); data.dptr = (void *)&v_store; @@ -230,21 +230,21 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int } /**************************************************************************** - Store a int32 value by string key, return 0 on success, -1 on failure. - Input is int32 in native byte order. Output in tdb is in little-endian. + Store a int32_t value by string key, return 0 on success, -1 on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v) +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v) { return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); } /**************************************************************************** - Fetch a uint32 value by a arbitrary blob key, return -1 if not found. - Output is uint32 in native byte order. + Fetch a uint32_t value by a arbitrary blob key, return -1 if not found. + Output is uint32_t in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value) +BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32_t *value) { TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; @@ -261,25 +261,25 @@ BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, u } /**************************************************************************** - Fetch a uint32 value by string key, return -1 if not found. - Output is uint32 in native byte order. + Fetch a uint32_t value by string key, return -1 if not found. + Output is uint32_t in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value) +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t *value) { return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); } /**************************************************************************** - Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure. - Input is uint32 in native byte order. Output in tdb is in little-endian. + Store a uint32_t value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value) +BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32_t value) { TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; - uint32 v_store; + uint32_t v_store; BOOL ret = True; SIVAL(&v_store, 0, value); @@ -293,11 +293,11 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, u } /**************************************************************************** - Store a uint32 value by string key, return 0 on success, -1 on failure. - Input is uint32 in native byte order. Output in tdb is in little-endian. + Store a uint32_t value by string key, return 0 on success, -1 on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t value) { return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); } @@ -340,10 +340,10 @@ int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) Atomic integer change. Returns old value. To create, set initial value in *oldval. ****************************************************************************/ -int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val) +int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *oldval, int32_t change_val) { - int32 val; - int32 ret = -1; + int32_t val; + int32_t ret = -1; if (tdb_lock_bystring(tdb, keystr,0) == -1) return -1; @@ -381,9 +381,9 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. ****************************************************************************/ -BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val) +BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) { - uint32 val; + uint32_t val; BOOL ret = False; if (tdb_lock_bystring(tdb, keystr,0) == -1) @@ -429,7 +429,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_list ap; uint8 bt; uint16 w; - uint32 d; + uint32_t d; int i; void *p; int len; @@ -523,7 +523,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_list ap; uint8 *bt; uint16 *w; - uint32 *d; + uint32_t *d; int len; int *i; void **p; @@ -553,7 +553,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) break; case 'd': len = 4; - d = va_arg(ap, uint32 *); + d = va_arg(ap, uint32_t *); if (bufsize < len) goto no_space; *d = IVAL(buf, 0); diff --git a/source4/lib/time.c b/source4/lib/time.c index e3811c884e..99738d5a4a 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -164,10 +164,10 @@ static uint16 make_dos_time1(struct tm *t) create a 32 bit dos packed date/time from some parameters This takes a GMT time and returns a packed localtime structure ********************************************************************/ -static uint32 make_dos_date(time_t unixdate, int zone_offset) +static uint32_t make_dos_date(time_t unixdate, int zone_offset) { struct tm *t; - uint32 ret=0; + uint32_t ret=0; if (unixdate == 0) { return 0; @@ -192,7 +192,7 @@ This takes GMT time and puts local time in the buffer ********************************************************************/ void push_dos_date(char *buf, int offset, time_t unixdate, int zone_offset) { - uint32 x = make_dos_date(unixdate, zone_offset); + uint32_t x = make_dos_date(unixdate, zone_offset); SIVAL(buf,offset,x); } @@ -202,7 +202,7 @@ This takes GMT time and puts local time in the buffer ********************************************************************/ void push_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) { - uint32 x; + uint32_t x; x = make_dos_date(unixdate, zone_offset); x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(buf,offset,x); @@ -224,9 +224,9 @@ void push_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) /******************************************************************* interpret a 32 bit dos packed date/time to some parameters ********************************************************************/ -static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) +static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second) { - uint32 p0,p1,p2,p3; + uint32_t p0,p1,p2,p3; p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; @@ -245,7 +245,7 @@ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *ho ********************************************************************/ time_t pull_dos_date(const uint8 *date_ptr, int zone_offset) { - uint32 dos_date=0; + uint32_t dos_date=0; struct tm t; time_t ret; @@ -269,7 +269,7 @@ like make_unix_date() but the words are reversed ********************************************************************/ time_t pull_dos_date2(const uint8 *date_ptr, int zone_offset) { - uint32 x,x2; + uint32_t x,x2; x = IVAL(date_ptr,0); x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); diff --git a/source4/lib/util.c b/source4/lib/util.c index 0cb5258a64..a4be8f8bf8 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -426,10 +426,10 @@ BOOL is_ipaddress(const char *str) Interpret an internet address or name into an IP address in 4 byte form. ****************************************************************************/ -uint32 interpret_addr(const char *str) +uint32_t interpret_addr(const char *str) { struct hostent *hp; - uint32 res; + uint32_t res; if (strcmp(str,"0.0.0.0") == 0) return(0); @@ -454,7 +454,7 @@ uint32 interpret_addr(const char *str) putip((char *)&res,(char *)hp->h_addr); } - if (res == (uint32)-1) + if (res == (uint32_t)-1) return(0); return(res); @@ -467,7 +467,7 @@ uint32 interpret_addr(const char *str) struct in_addr *interpret_addr2(TALLOC_CTX *mem_ctx, const char *str) { struct in_addr *ret; - uint32 a = interpret_addr(str); + uint32_t a = interpret_addr(str); ret = talloc(mem_ctx, sizeof(struct in_addr)); if (!ret) return NULL; @@ -481,7 +481,7 @@ struct in_addr *interpret_addr2(TALLOC_CTX *mem_ctx, const char *str) BOOL is_zero_ip(struct in_addr ip) { - uint32 a; + uint32_t a; putip((char *)&a,(char *)&ip); return(a == 0); } @@ -503,7 +503,7 @@ void zero_ip(struct in_addr *ip) BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) { - uint32 net1,net2,nmask; + uint32_t net1,net2,nmask; nmask = ntohl(mask.s_addr); net1 = ntohl(ip1.s_addr); diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 56f5abd611..2a70625317 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -78,7 +78,7 @@ static const struct { {SID_NAME_USE_NONE, NULL} }; -const char *sid_type_lookup(uint32 sid_type) +const char *sid_type_lookup(uint32_t sid_type) { int i = 0; @@ -147,7 +147,7 @@ void generate_wellknown_sids(void) Return the last rid from the end of a sid *****************************************************************/ -BOOL sid_peek_rid(const struct dom_sid *sid, uint32 *rid) +BOOL sid_peek_rid(const struct dom_sid *sid, uint32_t *rid) { if (!sid || !rid) return False; @@ -164,7 +164,7 @@ BOOL sid_peek_rid(const struct dom_sid *sid, uint32 *rid) and check the sid against the exp_dom_sid *****************************************************************/ -BOOL sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32 *rid) +BOOL sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32_t *rid) { if (!exp_dom_sid || !sid || !rid) return False; @@ -285,7 +285,7 @@ size_t sid_size(const struct dom_sid *sid) if (sid == NULL) return 0; - return sid->num_auths * sizeof(uint32) + 8; + return sid->num_auths * sizeof(uint32_t) + 8; } /***************************************************************** diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 57d3715cfc..999aeae744 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -250,7 +250,7 @@ BOOL send_nbt_keepalive(int sock_fd) /**************************************************************************** Open a socket of the specified type, port, and address for incoming data. ****************************************************************************/ -int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL rebind ) +int open_socket_in( int type, int port, int dlevel, uint32_t socket_addr, BOOL rebind ) { struct sockaddr_in sock; int res; -- cgit From f2ad98a165cdec6d344a96aeb21a38518a10720a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 25 May 2004 16:50:09 +0000 Subject: r888: more ..int32 -> ..int32_t stuff metze (This used to be commit f3b1d3bdc74f08ee2a1d22102d57bff94f71f5a5) --- source4/lib/tdb/common/tdbutil.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index b8babf48aa..bdb8621d16 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -191,7 +191,7 @@ int32_t tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) int32_t ret; data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(int32)) { + if (!data.dptr || data.dsize != sizeof(int32_t)) { SAFE_FREE(data.dptr); return -1; } @@ -224,7 +224,7 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int SIVAL(&v_store,0,v); data.dptr = (void *)&v_store; - data.dsize = sizeof(int32); + data.dsize = sizeof(int32_t); return tdb_store(tdb, key, data, TDB_REPLACE); } @@ -250,7 +250,7 @@ BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, u TDB_DATA data; data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(uint32)) { + if (!data.dptr || data.dsize != sizeof(uint32_t)) { SAFE_FREE(data.dptr); return False; } @@ -284,7 +284,7 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, u SIVAL(&v_store, 0, value); data.dptr = (void *)&v_store; - data.dsize = sizeof(uint32); + data.dsize = sizeof(uint32_t); if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) ret = False; @@ -457,7 +457,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) break; case 'd': /* signed 32-bit integer (standard int in most systems) */ len = 4; - d = va_arg(ap, uint32); + d = va_arg(ap, uint32_t); if (bufsize && bufsize >= len) SIVAL(buf, 0, d); break; -- cgit From f88bf54c7f6d1c2ef833047eb8327953c304b5ff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 25 May 2004 17:24:24 +0000 Subject: r889: convert samba4 to use [u]int16_t instead of [u]int16 metze (This used to be commit af6f1f8a01bebbecd99bc8c066519e89966e65e3) --- source4/lib/cmdline/popt_common.c | 2 +- source4/lib/events.c | 2 +- source4/lib/smbpasswd.c | 8 ++++---- source4/lib/tdb/common/tdbutil.c | 8 ++++---- source4/lib/time.c | 12 ++++++------ source4/lib/util_str.c | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 1b8e3bd93e..f659468561 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -191,7 +191,7 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) { XFILE *auth; fstring buf; - uint16 len = 0; + uint16_t len = 0; char *ptr, *val, *param; if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) diff --git a/source4/lib/events.c b/source4/lib/events.c index 85a2cee70f..50f3f53c94 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -357,7 +357,7 @@ int event_loop_wait(struct event_context *ev) which ones and call the handler, being careful to allow the handler to remove itself when called */ for (fe=ev->fd_events; fe; fe=fe->next) { - uint16 flags = 0; + uint16_t flags = 0; if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (fe->ref_count && flags) { diff --git a/source4/lib/smbpasswd.c b/source4/lib/smbpasswd.c index 92ae1ffea2..5cb8439878 100644 --- a/source4/lib/smbpasswd.c +++ b/source4/lib/smbpasswd.c @@ -88,7 +88,7 @@ BOOL smbpasswd_gethexpwd(char *p, unsigned char *pwd) /*! Convert a 16-byte array into 32 hex characters. */ -void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16 acb_info) +void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16_t acb_info) { if (pwd != NULL) { int i; @@ -104,9 +104,9 @@ void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16 acb_info) /*! Decode the account control bits (ACB) info from a string. */ -uint16 smbpasswd_decode_acb_info(const char *p) +uint16_t smbpasswd_decode_acb_info(const char *p) { - uint16 acb_info = 0; + uint16_t acb_info = 0; BOOL finished = False; /* @@ -170,7 +170,7 @@ uint16 smbpasswd_decode_acb_info(const char *p) /*! Encode account control bits (ACBs) into a string. */ -char *smbpasswd_encode_acb_info(uint16 acb_info) +char *smbpasswd_encode_acb_info(uint16_t acb_info) { static fstring acct_str; size_t i = 0; diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index bdb8621d16..3fe3ff4b11 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -428,7 +428,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; uint8 bt; - uint16 w; + uint16_t w; uint32_t d; int i; void *p; @@ -451,7 +451,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) break; case 'w': /* unsigned 16-bit integer */ len = 2; - w = (uint16)va_arg(ap, int); + w = (uint16_t)va_arg(ap, int); if (bufsize && bufsize >= len) SSVAL(buf, 0, w); break; @@ -522,7 +522,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; uint8 *bt; - uint16 *w; + uint16_t *w; uint32_t *d; int len; int *i; @@ -546,7 +546,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) break; case 'w': len = 2; - w = va_arg(ap, uint16 *); + w = va_arg(ap, uint16_t *); if (bufsize < len) goto no_space; *w = SVAL(buf, 0); diff --git a/source4/lib/time.c b/source4/lib/time.c index 99738d5a4a..1f95ef7daf 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -141,9 +141,9 @@ BOOL null_mtime(time_t mtime) /******************************************************************* create a 16 bit dos packed date ********************************************************************/ -static uint16 make_dos_date1(struct tm *t) +static uint16_t make_dos_date1(struct tm *t) { - uint16 ret=0; + uint16_t ret=0; ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); return ret; @@ -152,9 +152,9 @@ static uint16 make_dos_date1(struct tm *t) /******************************************************************* create a 16 bit dos packed time ********************************************************************/ -static uint16 make_dos_time1(struct tm *t) +static uint16_t make_dos_time1(struct tm *t) { - uint16 ret=0; + uint16_t ret=0; ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); return ret; @@ -382,7 +382,7 @@ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) /* put a NTTIME into a packet */ -void push_nttime(void *base, uint16 offset, NTTIME t) +void push_nttime(void *base, uint16_t offset, NTTIME t) { SBVAL(base, offset, t); } @@ -390,7 +390,7 @@ void push_nttime(void *base, uint16 offset, NTTIME t) /* pull a NTTIME from a packet */ -NTTIME pull_nttime(void *base, uint16 offset) +NTTIME pull_nttime(void *base, uint16_t offset) { NTTIME ret = BVAL(base, offset); return ret; diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 7d6505bab2..4002c21e9a 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -86,7 +86,7 @@ BOOL next_token_nr(const char **ptr, char *buff, const char *sep, size_t bufsize return ret; } -static uint16 tmpbuf[sizeof(pstring)]; +static uint16_t tmpbuf[sizeof(pstring)]; /** Convert list of tokens to array; dependent on above routine. @@ -269,7 +269,7 @@ void string_replace(char *s,char oldc,char newc) size_t str_charnum(const char *s) { - uint16 tmpbuf2[sizeof(pstring)]; + uint16_t tmpbuf2[sizeof(pstring)]; push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE); return strlen_w(tmpbuf2); } -- cgit From fcd718c7d8a6850ae8719f23ed044b06b57501cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 25 May 2004 17:50:17 +0000 Subject: r890: convert samba4 to use [u]int8_t instead of [u]int8 metze (This used to be commit 2986c5f08c8f0c26a2ea7b6ce20aae025183109f) --- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/tdb/common/tdbutil.c | 8 ++++---- source4/lib/time.c | 6 +++--- source4/lib/util_sid.c | 2 +- source4/lib/util_unistr.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 353963f78d..01d75f1b90 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -105,7 +105,7 @@ WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *val return reg_key_get_value_by_name(k, valname, val); } -WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8 *data, int real_len) +WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8_t *data, int real_len) { REG_KEY *k; REG_VAL *v; diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 3fe3ff4b11..05f4713c82 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -427,7 +427,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32_t *ol size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; - uint8 bt; + uint8_t bt; uint16_t w; uint32_t d; int i; @@ -445,7 +445,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) switch ((c = *fmt++)) { case 'b': /* unsigned 8-bit integer */ len = 1; - bt = (uint8)va_arg(ap, int); + bt = (uint8_t)va_arg(ap, int); if (bufsize && bufsize >= len) SSVAL(buf, 0, bt); break; @@ -521,7 +521,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) { va_list ap; - uint8 *bt; + uint8_t *bt; uint16_t *w; uint32_t *d; int len; @@ -539,7 +539,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) switch ((c=*fmt++)) { case 'b': len = 1; - bt = va_arg(ap, uint8 *); + bt = va_arg(ap, uint8_t *); if (bufsize < len) goto no_space; *bt = SVAL(buf, 0); diff --git a/source4/lib/time.c b/source4/lib/time.c index 1f95ef7daf..e95d3a8d17 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -243,7 +243,7 @@ static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int * create a unix date (int GMT) from a dos date (which is actually in localtime) ********************************************************************/ -time_t pull_dos_date(const uint8 *date_ptr, int zone_offset) +time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) { uint32_t dos_date=0; struct tm t; @@ -267,7 +267,7 @@ time_t pull_dos_date(const uint8 *date_ptr, int zone_offset) /******************************************************************* like make_unix_date() but the words are reversed ********************************************************************/ -time_t pull_dos_date2(const uint8 *date_ptr, int zone_offset) +time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) { uint32_t x,x2; @@ -282,7 +282,7 @@ time_t pull_dos_date2(const uint8 *date_ptr, int zone_offset) create a unix GMT date from a dos date in 32 bit "unix like" format these generally arrive as localtimes, with corresponding DST ******************************************************************/ -time_t pull_dos_date3(const uint8 *date_ptr, int zone_offset) +time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) { time_t t = (time_t)IVAL(date_ptr,0); if (!null_mtime(t)) { diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 2a70625317..c370beed5f 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -309,7 +309,7 @@ char *sid_binstring(const struct dom_sid *sid) /******************************************************************* Check if ACE has OBJECT type. ********************************************************************/ -BOOL sec_ace_object(uint8 type) +BOOL sec_ace_object(uint8_t type) { if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 76ebadc3ef..09a1c9a4df 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -25,7 +25,7 @@ at startup either via mmap() or read() from the lib directory */ static smb_ucs2_t *upcase_table; static smb_ucs2_t *lowcase_table; -static uint8 *valid_table; +static uint8_t *valid_table; /******************************************************************* @@ -116,7 +116,7 @@ void init_valid_table(void) static int mapped_file; int i; const char *allowed = ".!#$%&'()_-@^`~"; - uint8 *valid_file; + uint8_t *valid_file; TALLOC_CTX *mem_ctx; if (mapped_file) { -- cgit From 47864891ffd6309764fdc3a5227ec2e83c6f7107 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 26 May 2004 01:13:12 +0000 Subject: r893: a few more _t conversions (This used to be commit 66eb46dbb1486c5916194bf6b303cf16373a272a) --- source4/lib/registry/common/reg_objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index be15108f4d..d042c74e47 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -61,7 +61,7 @@ void reg_val_free( REG_VAL *val ) /********************************************************************** *********************************************************************/ -uint8* reg_val_data_blk( REG_VAL *val ) +uint8_t * reg_val_data_blk( REG_VAL *val ) { return val->data_blk; } -- cgit From 8b3f08cefcd41e6f8005de84a2cc865c1011194d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 26 May 2004 05:40:33 +0000 Subject: r898: - remove some unused macros - remove unused lib/smbpasswd.c - don't set the pkt size twice when doing SMB signing (This used to be commit 69a2942f7987647a32d43c71f41ac1a82a82ccda) --- source4/lib/basic.mk | 1 - source4/lib/smbpasswd.c | 200 ------------------------------------------------ 2 files changed, 201 deletions(-) delete mode 100644 source4/lib/smbpasswd.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 865ba7342f..ce82157894 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -39,7 +39,6 @@ ADD_OBJ_FILES = \ lib/messages.o \ lib/tallocmsg.o \ lib/dmallocmsg.o \ - lib/smbpasswd.o \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/gencache.o \ diff --git a/source4/lib/smbpasswd.c b/source4/lib/smbpasswd.c deleted file mode 100644 index 5cb8439878..0000000000 --- a/source4/lib/smbpasswd.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - smbpasswd file format routines - - Copyright (C) Andrew Tridgell 1992-1998 - Modified by Jeremy Allison 1995. - Modified by Gerald (Jerry) Carter 2000-2001 - Copyright (C) Tim Potter 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/*! \file lib/smbpasswd.c - - The smbpasswd file is used to store encrypted passwords in a similar - fashion to the /etc/passwd file. The format is colon separated fields - with one user per line like so: - - ::::: - - The username and uid must correspond to an entry in the /etc/passwd - file. The lanman and nt password hashes are 32 hex digits corresponding - to the 16-byte lanman and nt hashes respectively. - - The password last change time is stored as a string of the format - LCD- where the change time is expressed as an - - 'N' No password - 'D' Disabled - 'H' Homedir required - 'T' Temp account. - 'U' User account (normal) - 'M' MNS logon user account - what is this ? - 'W' Workstation account - 'S' Server account - 'L' Locked account - 'X' No Xpiry on password - 'I' Interdomain trust account - -*/ - -#include "includes.h" - -/*! Convert 32 hex characters into a 16 byte array. */ - -BOOL smbpasswd_gethexpwd(char *p, unsigned char *pwd) -{ - int i; - unsigned char lonybble, hinybble; - const char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; - - if (!p) return (False); - - for (i = 0; i < 32; i += 2) - { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); - - p1 = strchr_m(hexchars, hinybble); - p2 = strchr_m(hexchars, lonybble); - - if (!p1 || !p2) - { - return (False); - } - - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - pwd[i / 2] = (hinybble << 4) | lonybble; - } - return (True); -} - -/*! Convert a 16-byte array into 32 hex characters. */ - -void smbpasswd_sethexpwd(fstring p, unsigned char *pwd, uint16_t acb_info) -{ - if (pwd != NULL) { - int i; - for (i = 0; i < 16; i++) - slprintf(&p[i*2], 3, "%02X", pwd[i]); - } else { - if (acb_info & ACB_PWNOTREQ) - safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); - else - safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); - } -} - -/*! Decode the account control bits (ACB) info from a string. */ - -uint16_t smbpasswd_decode_acb_info(const char *p) -{ - uint16_t acb_info = 0; - BOOL finished = False; - - /* - * Check if the account type bits have been encoded after the - * NT password (in the form [NDHTUWSLXI]). - */ - - if (*p != '[') return 0; - - for (p++; *p && !finished; p++) - { - switch (*p) { - case 'N': /* 'N'o password. */ - acb_info |= ACB_PWNOTREQ; - break; - case 'D': /* 'D'isabled. */ - acb_info |= ACB_DISABLED; - break; - case 'H': /* 'H'omedir required. */ - acb_info |= ACB_HOMDIRREQ; - break; - case 'T': /* 'T'emp account. */ - acb_info |= ACB_TEMPDUP; - break; - case 'U': /* 'U'ser account (normal). */ - acb_info |= ACB_NORMAL; - break; - case 'M': /* 'M'NS logon user account. What is this ? */ - acb_info |= ACB_MNS; - break; - case 'W': /* 'W'orkstation account. */ - acb_info |= ACB_WSTRUST; - break; - case 'S': /* 'S'erver account. */ - acb_info |= ACB_SVRTRUST; - break; - case 'L': /* 'L'ocked account. */ - acb_info |= ACB_AUTOLOCK; - break; - case 'X': /* No 'X'piry on password */ - acb_info |= ACB_PWNOEXP; - break; - case 'I': /* 'I'nterdomain trust account. */ - acb_info |= ACB_DOMTRUST; - break; - - case ' ': - break; - case ':': - case '\n': - case '\0': - case ']': - default: - finished = True; - break; - } - } - - return acb_info; -} - -/*! Encode account control bits (ACBs) into a string. */ - -char *smbpasswd_encode_acb_info(uint16_t acb_info) -{ - static fstring acct_str; - size_t i = 0; - - acct_str[i++] = '['; - - if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N'; - if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D'; - if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H'; - if (acb_info & ACB_TEMPDUP ) acct_str[i++] = 'T'; - if (acb_info & ACB_NORMAL ) acct_str[i++] = 'U'; - if (acb_info & ACB_MNS ) acct_str[i++] = 'M'; - if (acb_info & ACB_WSTRUST ) acct_str[i++] = 'W'; - if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S'; - if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L'; - if (acb_info & ACB_PWNOEXP ) acct_str[i++] = 'X'; - if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I'; - - for ( ; i < NEW_PW_FORMAT_SPACE_PADDED_LEN - 2 ; i++ ) - acct_str[i] = ' '; - - i = NEW_PW_FORMAT_SPACE_PADDED_LEN - 2; - acct_str[i++] = ']'; - acct_str[i++] = '\0'; - - return acct_str; -} -- cgit From 39a236883ee4015980ff3d3cab8a8e5fec858502 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 26 May 2004 08:02:20 +0000 Subject: r904: - fixed account expiry testing in auth_sam - added printf style format attribute checking to samdb varargs fns - fix nt_time_to_unix() for zero and -1 times (This used to be commit 41f9b144f9fe77e92f960bd11b1df397a63fd2d5) --- source4/lib/time.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index e95d3a8d17..5fd8aa3081 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -91,6 +91,12 @@ It's originally in "100ns units since jan 1st 1601" ****************************************************************************/ time_t nt_time_to_unix(NTTIME nt) { + if (nt == 0) { + return 0; + } + if (nt == -1LL) { + return (time_t)-1; + } nt += 1000*1000*10/2; nt /= 1000*1000*10; nt -= TIME_FIXUP_CONSTANT; -- cgit From 56e74a7c3f30b8dcc84f5246b44fc7393fd7ccf3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 27 May 2004 13:21:35 +0000 Subject: r924: got rid of the global well-known SIDs, instead using const defines in misc.idl (This used to be commit ce7920a5fac0dbccb01402129c341b410a032e60) --- source4/lib/util_sid.c | 85 -------------------------------------------------- 1 file changed, 85 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index c370beed5f..6eb19b59e6 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -24,40 +24,6 @@ #include "includes.h" -/* - * Some useful sids - */ - -struct dom_sid *global_sid_World_Domain; /* Everyone domain */ -struct dom_sid *global_sid_World; /* Everyone */ -struct dom_sid *global_sid_Creator_Owner_Domain; /* Creator Owner domain */ -struct dom_sid *global_sid_NT_Authority; /* NT Authority */ -struct dom_sid *global_sid_System; /* System */ -struct dom_sid *global_sid_NULL; /* NULL sid */ -struct dom_sid *global_sid_Authenticated_Users; /* All authenticated rids */ -struct dom_sid *global_sid_Network; /* Network rids */ - -struct dom_sid *global_sid_Creator_Owner; /* Creator Owner */ -struct dom_sid *global_sid_Creator_Group; /* Creator Group */ -struct dom_sid *global_sid_Anonymous; /* Anonymous login */ - -struct dom_sid *global_sid_Builtin; /* Local well-known domain */ -struct dom_sid *global_sid_Builtin_Administrators; /* Builtin administrators */ -struct dom_sid *global_sid_Builtin_Users; /* Builtin users */ -struct dom_sid *global_sid_Builtin_Guests; /* Builtin guest users */ -struct dom_sid *global_sid_Builtin_Power_Users; /* Builtin power users */ -struct dom_sid *global_sid_Builtin_Account_Operators; /* Builtin account operators */ -struct dom_sid *global_sid_Builtin_Server_Operators; /* Builtin server operators */ -struct dom_sid *global_sid_Builtin_Print_Operators; /* Builtin print operators */ -struct dom_sid *global_sid_Builtin_Backup_Operators; /* Builtin backup operators */ -struct dom_sid *global_sid_Builtin_Replicator; /* Builtin replicator */ - -#define SECURITY_NULL_SID_AUTHORITY 0 -#define SECURITY_WORLD_SID_AUTHORITY 1 -#define SECURITY_LOCAL_SID_AUTHORITY 2 -#define SECURITY_CREATOR_SID_AUTHORITY 3 -#define SECURITY_NT_AUTHORITY 5 - /**************************************************************************** Lookup string names for SID types. ****************************************************************************/ @@ -93,60 +59,9 @@ const char *sid_type_lookup(uint32_t sid_type) return "SID *TYPE* is INVALID"; } -/**************************************************************************** - Creates some useful well known sids -****************************************************************************/ - -void generate_wellknown_sids(void) -{ - static BOOL initialised = False; - static TALLOC_CTX *mem_ctx; - - if (initialised) - return; - - mem_ctx = talloc_init("Well known groups, global static context"); - if (!mem_ctx) - return; - - /* SECURITY_NULL_SID_AUTHORITY */ - global_sid_NULL = dom_sid_parse_talloc(mem_ctx, "S-1-0-0"); - - /* SECURITY_WORLD_SID_AUTHORITY */ - global_sid_World_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-1"); - global_sid_World = dom_sid_parse_talloc(mem_ctx, "S-1-1-0"); - - /* SECURITY_CREATOR_SID_AUTHORITY */ - global_sid_Creator_Owner_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-3"); - global_sid_Creator_Owner = dom_sid_parse_talloc(mem_ctx, "S-1-3-0"); - global_sid_Creator_Group = dom_sid_parse_talloc(mem_ctx, "S-1-3-1"); - - /* SECURITY_NT_AUTHORITY */ - global_sid_NT_Authority = dom_sid_parse_talloc(mem_ctx, "S-1-5"); - global_sid_Network = dom_sid_parse_talloc(mem_ctx, "S-1-5-2"); - global_sid_Anonymous = dom_sid_parse_talloc(mem_ctx, "S-1-5-7"); - global_sid_Authenticated_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-11"); - global_sid_System = dom_sid_parse_talloc(mem_ctx, "S-1-5-18"); - - /* SECURITY_BUILTIN_DOMAIN_RID */ - global_sid_Builtin = dom_sid_parse_talloc(mem_ctx, "S-1-5-32"); - global_sid_Builtin_Administrators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-544"); - global_sid_Builtin_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545"); - global_sid_Builtin_Guests = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-546"); - global_sid_Builtin_Power_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-547"); - global_sid_Builtin_Account_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-548"); - global_sid_Builtin_Server_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-549"); - global_sid_Builtin_Print_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-550"); - global_sid_Builtin_Backup_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-551"); - global_sid_Builtin_Replicator = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-552"); - - initialised = True; -} - /***************************************************************** Return the last rid from the end of a sid *****************************************************************/ - BOOL sid_peek_rid(const struct dom_sid *sid, uint32_t *rid) { if (!sid || !rid) -- cgit From c5cd8680abe8efb8d32243f912284d925da73fa3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 27 May 2004 23:35:02 +0000 Subject: r929: Remove more unused code from util_sid.c (the old-style sid code is almost gone). (This used to be commit 82d68e8a4472906f2a2036c13a0301055740641a) --- source4/lib/util_sid.c | 153 +------------------------------------------------ 1 file changed, 1 insertion(+), 152 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 6eb19b59e6..cb2ec3eb75 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -24,75 +24,6 @@ #include "includes.h" -/**************************************************************************** - Lookup string names for SID types. -****************************************************************************/ - -static const struct { - enum SID_NAME_USE sid_type; - const char *string; -} sid_name_type[] = { - {SID_NAME_USER, "User"}, - {SID_NAME_DOM_GRP, "Domain Group"}, - {SID_NAME_DOMAIN, "Domain"}, - {SID_NAME_ALIAS, "Local Group"}, - {SID_NAME_WKN_GRP, "Well-known Group"}, - {SID_NAME_DELETED, "Deleted Account"}, - {SID_NAME_INVALID, "Invalid Account"}, - {SID_NAME_UNKNOWN, "UNKNOWN"}, - - {SID_NAME_USE_NONE, NULL} -}; - -const char *sid_type_lookup(uint32_t sid_type) -{ - int i = 0; - - /* Look through list */ - while(sid_name_type[i].sid_type != 0) { - if (sid_name_type[i].sid_type == sid_type) - return sid_name_type[i].string; - i++; - } - - /* Default return */ - return "SID *TYPE* is INVALID"; -} - -/***************************************************************** - Return the last rid from the end of a sid -*****************************************************************/ -BOOL sid_peek_rid(const struct dom_sid *sid, uint32_t *rid) -{ - if (!sid || !rid) - return False; - - if (sid->num_auths > 0) { - *rid = sid->sub_auths[sid->num_auths - 1]; - return True; - } - return False; -} - -/***************************************************************** - Return the last rid from the end of a sid - and check the sid against the exp_dom_sid -*****************************************************************/ - -BOOL sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32_t *rid) -{ - if (!exp_dom_sid || !sid || !rid) - return False; - - - if (sid_compare_domain(exp_dom_sid, sid)!=0){ - *rid=(-1); - return False; - } - - return sid_peek_rid(sid, rid); -} - /***************************************************************** Compare the auth portion of two sids. *****************************************************************/ @@ -122,7 +53,7 @@ static int sid_compare_auth(const struct dom_sid *sid1, const struct dom_sid *si Compare two sids. *****************************************************************/ -int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) +static int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) { int i; @@ -144,24 +75,6 @@ int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) return sid_compare_auth(sid1, sid2); } -/***************************************************************** - See if 2 SIDs are in the same domain - this just compares the leading sub-auths -*****************************************************************/ - -int sid_compare_domain(const struct dom_sid *sid1, const struct dom_sid *sid2) -{ - int n, i; - - n = MIN(sid1->num_auths, sid2->num_auths); - - for (i = n-1; i >= 0; --i) - if (sid1->sub_auths[i] != sid2->sub_auths[i]) - return sid1->sub_auths[i] - sid2->sub_auths[i]; - - return sid_compare_auth(sid1, sid2); -} - /***************************************************************** Compare two sids. *****************************************************************/ @@ -170,67 +83,3 @@ BOOL sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2) { return sid_compare(sid1, sid2) == 0; } -/***************************************************************** - Write a sid out into on-the-wire format. -*****************************************************************/ - -BOOL sid_linearize(char *outbuf, size_t len, const struct dom_sid *sid) -{ - size_t i; - - if (len < sid_size(sid)) - return False; - - SCVAL(outbuf,0,sid->sid_rev_num); - SCVAL(outbuf,1,sid->num_auths); - memcpy(&outbuf[2], sid->id_auth, 6); - for(i = 0; i < sid->num_auths; i++) - SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]); - - return True; -} - - -/***************************************************************** - Calculates size of a sid. -*****************************************************************/ - -size_t sid_size(const struct dom_sid *sid) -{ - if (sid == NULL) - return 0; - - return sid->num_auths * sizeof(uint32_t) + 8; -} - -/***************************************************************** - Return the binary string representation of a struct dom_sid. - Caller must free. -*****************************************************************/ - -char *sid_binstring(const struct dom_sid *sid) -{ - char *buf, *s; - int len = sid_size(sid); - buf = malloc(len); - if (!buf) - return NULL; - sid_linearize(buf, len, sid); - s = binary_string(buf, len); - free(buf); - return s; -} - -/******************************************************************* - Check if ACE has OBJECT type. -********************************************************************/ -BOOL sec_ace_object(uint8_t type) -{ - if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || - type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { - return True; - } - return False; -} -- cgit From 7cd74a596e74091bbcabe8d85d90747f855ba7ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 May 2004 03:11:14 +0000 Subject: r934: on ascii strings STR_TERMINATE_ASCII should trigger STR_TERMINATE behaviour (This used to be commit b7935c96742a3c09ee4bf69f708b19095f497be1) --- source4/lib/charcnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index ed56d9d0cc..c3ef45d038 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -405,7 +405,7 @@ ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, if (dest_len == (size_t)-1) dest_len = sizeof(pstring); - if (flags & STR_TERMINATE) { + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { if (src_len == (size_t)-1) { src_len = strlen(src) + 1; } else { -- cgit From 90341da78b10beb4fa0bdbc8de35d44373c27fbf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 May 2004 03:11:35 +0000 Subject: r935: remove unused variable (This used to be commit a8056e329484256ffb51e823296b87979ef9221f) --- source4/lib/crypto/hmacmd5.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index 7697ac8a69..0a7cbb3663 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -69,8 +69,6 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) void hmac_md5_init_limK_to_64(const uchar* key, int key_len, HMACMD5Context *ctx) { - int i; - /* if key is longer than 64 bytes truncate it */ if (key_len > 64) { -- cgit From d9538e7412c593a9dc10a600676939d2cf0205ea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 May 2004 13:23:30 +0000 Subject: r937: - added a simple QuerySecurity implementation in samr server - moved some sec desc defines into misc.idl - fixed pw_len field in UserInfo26 - made some pipes available on TCP - added netr_DsrEnumerateDomainTrusts() to netlogon - added templates for remaining netlogon IDL calls (from ethereal) - added a unistr_noterm vs unistr error detector in ndr basic decoder - added torture test for netr_DsrEnumerateDomainTrusts() (This used to be commit ae5a5113fb83640dcb9ae4642c1b9eaf28487956) --- source4/lib/basic.mk | 1 + source4/lib/util_secdesc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 source4/lib/util_secdesc.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index ce82157894..754458fec1 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -25,6 +25,7 @@ ADD_OBJ_FILES = \ lib/wins_srv.o \ lib/util_str.o \ lib/util_sid.o \ + lib/util_secdesc.o \ lib/util_uuid.o \ lib/util_unistr.o \ lib/util_file.o \ diff --git a/source4/lib/util_secdesc.c b/source4/lib/util_secdesc.c new file mode 100644 index 0000000000..92887b21d9 --- /dev/null +++ b/source4/lib/util_secdesc.c @@ -0,0 +1,51 @@ +/* + Unix SMB/CIFS implementation. + + security descriptror utility functions + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + return a blank security descriptor (no owners, dacl or sacl) +*/ +struct security_descriptor *sd_initialise(TALLOC_CTX *mem_ctx) +{ + struct security_descriptor *sd; + + sd = talloc_p(mem_ctx, struct security_descriptor); + if (!sd) { + return NULL; + } + + sd->revision = SD_REVISION; + /* we mark as self relative, even though it isn't while it remains + a pointer in memory because this simplifies the ndr code later. + All SDs that we store/emit are in fact SELF_RELATIVE + */ + sd->type = SEC_DESC_SELF_RELATIVE; + + sd->owner_sid = NULL; + sd->group_sid = NULL; + sd->sacl = NULL; + sd->dacl = NULL; + + return sd; +} + -- cgit From 45e93c19ef95978f908f5b14962770510634cd3b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 29 May 2004 08:11:46 +0000 Subject: r943: change samba4 to use 'uint8_t' instead of 'unsigned char' metze (This used to be commit b5378803fdcb3b3afe7c2932a38828e83470f61a) --- source4/lib/crypto/md4.c | 8 ++--- source4/lib/crypto/md5.c | 12 +++---- source4/lib/genrand.c | 42 +++++++++++----------- source4/lib/iconv.c | 8 ++--- source4/lib/ldb/common/ldb_ldif.c | 6 ++-- source4/lib/ldb/ldb_tdb/ldb_pack.c | 4 +-- source4/lib/registry/common/reg_util.c | 2 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 16 ++++----- source4/lib/registry/tools/regpatch.c | 4 +-- source4/lib/replace.c | 2 +- source4/lib/snprintf.c | 4 +-- source4/lib/tdb/common/tdb.c | 4 +-- source4/lib/tdb/tools/tdbdump.c | 2 +- source4/lib/tdb/tools/tdbtool.c | 4 +-- source4/lib/util.c | 4 +-- source4/lib/util_file.c | 6 ++-- source4/lib/util_sock.c | 2 +- source4/lib/util_str.c | 20 +++++------ source4/lib/xfile.c | 2 +- 19 files changed, 76 insertions(+), 76 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/md4.c b/source4/lib/crypto/md4.c index cc8b9b6841..98fcabf224 100644 --- a/source4/lib/crypto/md4.c +++ b/source4/lib/crypto/md4.c @@ -107,7 +107,7 @@ static void mdfour64(struct mdfour_state *s, uint32_t *M) X[j] = 0; } -static void copy64(uint32_t *M, const unsigned char *in) +static void copy64(uint32_t *M, const uint8_t *in) { int i; @@ -116,7 +116,7 @@ static void copy64(uint32_t *M, const unsigned char *in) (in[i*4+1]<<8) | (in[i*4+0]<<0); } -static void copy4(unsigned char *out, uint32_t x) +static void copy4(uint8_t *out, uint32_t x) { out[0] = x&0xFF; out[1] = (x>>8)&0xFF; @@ -125,9 +125,9 @@ static void copy4(unsigned char *out, uint32_t x) } /* produce a md4 message digest from data of length n bytes */ -void mdfour(unsigned char *out, const unsigned char *in, int n) +void mdfour(uint8_t *out, const uint8_t *in, int n) { - unsigned char buf[128]; + uint8_t buf[128]; uint32_t M[16]; uint32_t b = n * 8; int i; diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index dbb3462bd4..a393fc2532 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -27,7 +27,7 @@ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); /* * Note: this code is harmless on little-endian machines. */ -static void byteReverse(unsigned char *buf, unsigned longs) +static void byteReverse(uint8_t *buf, unsigned longs) { uint32_t t; do { @@ -57,7 +57,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +void MD5Update(struct MD5Context *ctx, uint8_t const *buf, unsigned len) { register uint32_t t; @@ -73,7 +73,7 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) /* Handle any leading odd-sized chunks */ if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; + uint8_t *p = (uint8_t *) ctx->in + t; t = 64 - t; if (len < t) { @@ -105,10 +105,10 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +void MD5Final(uint8_t digest[16], struct MD5Context *ctx) { unsigned int count; - unsigned char *p; + uint8_t *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; @@ -141,7 +141,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) ((uint32_t *) ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, (uint32_t *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); + byteReverse((uint8_t *) ctx->buf, 4); memmove(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index a5002969bd..b37078b284 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -22,21 +22,21 @@ #include "includes.h" -static unsigned char hash[258]; +static uint8_t hash[258]; static uint32_t counter; -static unsigned char *reseed_data; +static uint8_t *reseed_data; static size_t reseed_data_size; /**************************************************************** Copy any user given reseed data. *****************************************************************/ -void set_rand_reseed_data(unsigned char *data, size_t len) +void set_rand_reseed_data(uint8_t *data, size_t len) { SAFE_FREE(reseed_data); reseed_data_size = 0; - reseed_data = (unsigned char *)memdup(data, len); + reseed_data = (uint8_t *)memdup(data, len); if (reseed_data) reseed_data_size = len; } @@ -45,16 +45,16 @@ void set_rand_reseed_data(unsigned char *data, size_t len) Setup the seed. *****************************************************************/ -static void seed_random_stream(unsigned char *seedval, size_t seedlen) +static void seed_random_stream(uint8_t *seedval, size_t seedlen) { - unsigned char j = 0; + uint8_t j = 0; size_t ind; for (ind = 0; ind < 256; ind++) - hash[ind] = (unsigned char)ind; + hash[ind] = (uint8_t)ind; for( ind = 0; ind < 256; ind++) { - unsigned char tc; + uint8_t tc; j += (hash[ind] + seedval[ind%seedlen]); @@ -71,15 +71,15 @@ static void seed_random_stream(unsigned char *seedval, size_t seedlen) Get datasize bytes worth of random data. *****************************************************************/ -static void get_random_stream(unsigned char *data, size_t datasize) +static void get_random_stream(uint8_t *data, size_t datasize) { - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; + uint8_t index_i = hash[256]; + uint8_t index_j = hash[257]; size_t ind; for( ind = 0; ind < datasize; ind++) { - unsigned char tc; - unsigned char t; + uint8_t tc; + uint8_t t; index_i++; index_j += hash[index_i]; @@ -101,10 +101,10 @@ static void get_random_stream(unsigned char *data, size_t datasize) Note that the hash is not initialised. *****************************************************************/ -static void do_filehash(const char *fname, unsigned char *the_hash) +static void do_filehash(const char *fname, uint8_t *the_hash) { - unsigned char buf[1011]; /* deliberate weird size */ - unsigned char tmp_md4[16]; + uint8_t buf[1011]; /* deliberate weird size */ + uint8_t tmp_md4[16]; int fd, n; fd = sys_open(fname,O_RDONLY,0); @@ -133,7 +133,7 @@ static void do_filehash(const char *fname, unsigned char *the_hash) static int do_reseed(BOOL use_fd, int fd) { - unsigned char seed_inbuf[40]; + uint8_t seed_inbuf[40]; uint32_t v1, v2; struct timeval tval; pid_t mypid; if (use_fd) { @@ -181,13 +181,13 @@ static int do_reseed(BOOL use_fd, int fd) Interface to the (hopefully) good crypto random number generator. ********************************************************************/ -void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) +void generate_random_buffer( uint8_t *out, int len, BOOL do_reseed_now) { static BOOL done_reseed = False; static int urand_fd = -1; - unsigned char md4_buf[64]; - unsigned char tmp_buf[16]; - unsigned char *p; + uint8_t md4_buf[64]; + uint8_t tmp_buf[16]; + uint8_t *p; if(!done_reseed || do_reseed_now) { urand_fd = do_reseed(True, urand_fd); diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 3f37583e39..65fa45248f 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -458,8 +458,8 @@ static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { - const unsigned char *c = (const unsigned char *)*inbuf; - unsigned char *uc = (unsigned char *)*outbuf; + const uint8_t *c = (const uint8_t *)*inbuf; + uint8_t *uc = (uint8_t *)*outbuf; int len = 1; if ((c[0] & 0x80) == 0) { @@ -505,8 +505,8 @@ static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 2 && *outbytesleft >= 1) { - unsigned char *c = (unsigned char *)*outbuf; - const unsigned char *uc = (const unsigned char *)*inbuf; + uint8_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*inbuf; int len=1; if (uc[1] & 0xf8) { diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index c120ee5f4e..b08c616a05 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -47,7 +47,7 @@ static int base64_decode(char *s) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i, n; - unsigned char *d = (unsigned char *)s; + uint8_t *d = (uint8_t *)s; char *p; n=i=0; @@ -90,7 +90,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; - const unsigned char *d = (const unsigned char *)buf; + const uint8_t *d = (const uint8_t *)buf; int bytes = (len*8 + 5)/6; char *out; @@ -123,7 +123,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) int ldb_should_b64_encode(const struct ldb_val *val) { int i; - unsigned char *p = val->data; + uint8_t *p = val->data; if (val->length == 0 || p[0] == ' ' || p[0] == ':') { return 1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index e71679646e..fcbc9bd56d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -42,7 +42,7 @@ #define LTDB_PACKING_FORMAT_NODN 0x26011966 /* use a portable integer format */ -static void put_uint32(unsigned char *p, int ofs, unsigned int val) +static void put_uint32(uint8_t *p, int ofs, unsigned int val) { p += ofs; p[0] = val&0xFF; @@ -51,7 +51,7 @@ static void put_uint32(unsigned char *p, int ofs, unsigned int val) p[3] = (val>>24) & 0xFF; } -static unsigned int pull_uint32(unsigned char *p, int ofs) +static unsigned int pull_uint32(uint8_t *p, int ofs) { p += ofs; return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 01d75f1b90..db5e97bf7f 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -55,7 +55,7 @@ char *reg_val_data_string(REG_VAL *v) asciip = ret; for (i=0; i 0) *asciip = ' '; asciip++; } diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 627b5a8f13..fa4b3e4d18 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1268,10 +1268,10 @@ static void *nt_alloc_regf_space(REG_HANDLE *h, int size, unsigned int *off) /* * Store a SID at the location provided */ -static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, unsigned char *locn) +static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, uint8_t *locn) { int i; - unsigned char *p = locn; + uint8_t *p = locn; if (!regf || !sid || !locn) return 0; @@ -1290,11 +1290,11 @@ static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, unsigned char *locn) } -static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, unsigned char *locn) +static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, uint8_t *locn) { int size = 0; SEC_ACE *reg_ace = (SEC_ACE *)locn; - unsigned char *p; + uint8_t *p; if (!regf || !ace || !locn) return 0; @@ -1303,7 +1303,7 @@ static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, unsigned char *locn) /* Deal with the length when we have stored the SID */ - p = (unsigned char *)®_ace->info.mask; + p = (uint8_t *)®_ace->info.mask; SIVAL(p, 0, ace->info.mask); p += 4; @@ -1311,7 +1311,7 @@ static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, unsigned char *locn) size += 8; /* Size of the fixed header */ - p = (unsigned char *)®_ace->size; + p = (uint8_t *)®_ace->size; SSVAL(p, 0, size); @@ -1321,9 +1321,9 @@ static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, unsigned char *locn) /* * Store an ACL at the location provided */ -static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, unsigned char *locn) { +static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { int size = 0, i; - unsigned char *p = locn, *s; + uint8_t *p = locn, *s; if (!regf || !acl || !locn) return 0; diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 77c0f710c1..af869d1cfa 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -155,7 +155,7 @@ static struct cmd_line *get_cmd_line(int fd) { struct cmd_line *cl = (CMD_LINE *)smb_xmalloc(sizeof(CMD_LINE)); int i = 0, rc; - unsigned char ch; + uint8_t ch; cl->len = INIT_ALLOC; @@ -662,7 +662,7 @@ static CMD_FILE *cmd_file_create(const char *file) * Sec Desc print functions */ -char *str_type(unsigned char type); +char *str_type(uint8_t type); static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) { diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 189c5bc04d..c186d307e6 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -328,7 +328,7 @@ duplicate a string #ifdef REPLACE_INET_NTOA char *rep_inet_ntoa(struct in_addr ip) { - unsigned char *p = (unsigned char *)&ip.s_addr; + uint8_t *p = (uint8_t *)&ip.s_addr; static char buf[18]; slprintf(buf, 17, "%d.%d.%d.%d", (int)p[0], (int)p[1], (int)p[2], (int)p[3]); diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c index fd31870162..3b04228c42 100644 --- a/source4/lib/snprintf.c +++ b/source4/lib/snprintf.c @@ -219,7 +219,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args } break; case DP_S_MIN: - if (isdigit((unsigned char)ch)) { + if (isdigit((uint8_t)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { @@ -239,7 +239,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args } break; case DP_S_MAX: - if (isdigit((unsigned char)ch)) { + if (isdigit((uint8_t)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index c8ac7babad..b7b9631444 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1762,7 +1762,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, TDB_CONTEXT *tdb; struct stat st; int rev = 0, locked = 0; - unsigned char *vp; + uint8_t *vp; u32 vertest; if (!(tdb = calloc(1, sizeof *tdb))) { @@ -1841,7 +1841,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } rev = (tdb->flags & TDB_CONVERT); } - vp = (unsigned char *)&tdb->header.version; + vp = (uint8_t *)&tdb->header.version; vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | (((u32)vp[2]) << 8) | (u32)vp[3]; tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 9c1dc2761b..1a7128c473 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -35,7 +35,7 @@ static void print_data(TDB_DATA d) { - unsigned char *p = d.dptr; + uint8_t *p = d.dptr; int len = d.dsize; while (len--) { if (isprint(*p) && !strchr("\"\\", *p)) { diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 92009dcef4..65bbedf709 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -63,7 +63,7 @@ static TDB_CONTEXT *tdb; static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); -static void print_asc(unsigned char *buf,int len) +static void print_asc(uint8_t *buf,int len) { int i; @@ -77,7 +77,7 @@ static void print_asc(unsigned char *buf,int len) printf("%c",isprint(buf[i])?buf[i]:'.'); } -static void print_data(unsigned char *buf,int len) +static void print_data(uint8_t *buf,int len) { int i=0; if (len<=0) return; diff --git a/source4/lib/util.c b/source4/lib/util.c index a4be8f8bf8..dd53d2b174 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -677,7 +677,7 @@ void set_remote_arch(struct server_context *smb, enum remote_arch_types type) } -void print_asc(int level, const unsigned char *buf,int len) +void print_asc(int level, const uint8_t *buf,int len) { int i; for (i=0;i> 4]; - s[j+2] = hex[((unsigned char)buf[i]) & 0xF]; + s[j+1] = hex[((uint8_t)buf[i]) >> 4]; + s[j+2] = hex[((uint8_t)buf[i]) & 0xF]; j += 3; } s[j] = 0; @@ -1210,7 +1210,7 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex) { size_t i; size_t num_chars = 0; - unsigned char lonybble, hinybble; + uint8_t lonybble, hinybble; const char *hexchars = "0123456789ABCDEF"; char *p1 = NULL, *p2 = NULL; @@ -1302,7 +1302,7 @@ DATA_BLOB base64_decode_data_blob(const char *s) { int bit_offset, byte_offset, idx, i, n; DATA_BLOB decoded = data_blob(s, strlen(s)+1); - unsigned char *d = decoded.data; + uint8_t *d = decoded.data; char *p; n=i=0; @@ -1357,7 +1357,7 @@ char * base64_encode_data_blob(DATA_BLOB data) char *result = malloc(output_len); /* get us plenty of space */ while (len-- && out_cnt < (data.length * 2) - 5) { - int c = (unsigned char) *(data.data++); + int c = (uint8_t) *(data.data++); bits += c; char_count++; if (char_count == 3) { diff --git a/source4/lib/xfile.c b/source4/lib/xfile.c index 1534dd855e..de4cf4b12a 100644 --- a/source4/lib/xfile.c +++ b/source4/lib/xfile.c @@ -306,7 +306,7 @@ int x_fgetc(XFILE *f) return EOF; } - ret = *(unsigned char *)(f->next); + ret = *(uint8_t *)(f->next); f->next++; f->bufused--; return ret; -- cgit From 9fba08b621432861b52d5af0b7d994ba0e0100f0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 31 May 2004 17:14:27 +0000 Subject: r955: Update debian package rules... builds now (This used to be commit 3df8ff6cf111c6601554bffb411506bd43f726c7) --- source4/lib/module.c | 4 ++-- source4/lib/registry/TODO | 3 +++ source4/lib/registry/common/reg_interface.c | 8 ++++++-- source4/lib/registry/config.m4 | 2 +- source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 8 ++++++-- 5 files changed, 18 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index 15f92db59e..f03e19d924 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. module loading system - Copyright (C) Jelmer Vernooij 2002-2003 + Copyright (C) Jelmer Vernooij 2002-2004 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 @@ -133,7 +133,7 @@ NTSTATUS register_subsystem(const char *name, register_backend_function callback while(t) { if(!strcmp(name, t->name)) { /* its already registered! */ - DEBUG(0,("SUBSYSTEM '%s' for type already registered\n", name)); + DEBUG(0,("Subsystem '%s' already registered\n", name)); return NT_STATUS_OBJECT_NAME_COLLISION; } t = t->next; diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 9b0dbe4c71..695f786b69 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -24,6 +24,9 @@ reg_backend_wine.c: regshell: - support for security descriptors + + regdiff: + - fix gregedit.c: - support for editing values / adding values / deleting values diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 6d305e61bf..6ad7ee69cb 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -64,8 +64,12 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) if(reg_first_init) { status = register_subsystem("registry", registry_register); - if (!NT_STATUS_IS_OK(status)) + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status))); + /* Don't try the initialisation again */ + reg_first_init = False; return NULL; + } static_init_registry; reg_first_init = False; @@ -83,7 +87,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) BOOL reg_has_backend(const char *backend) { - return reg_find_backend_entry(backend)?True:False; + return reg_find_backend_entry(backend) != NULL?True:False; } /* Open a registry file/host/etc */ diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 331b9c2df1..a1dc9a45bc 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -27,7 +27,7 @@ SMB_MODULE_MK(registry_w95, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_dir, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_rpc, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_gconf, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_ldb, REGISTRY, NOT, lib/registry/config.mk) +SMB_MODULE_MK(registry_ldb, REGISTRY, STATIC, lib/registry/config.mk) SMB_SUBSYSTEM_MK(REGISTRY,lib/registry/config.mk) diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 498dc6991b..7b574069e9 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -39,6 +39,7 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) } ret[strlen(ret)-1] = ')'; + printf("Doing search for : %s\n", ret); return ret; } @@ -85,9 +86,12 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) return WERR_OK; } +static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) +{ + /* FIXME */ +} - -static WERROR ldb_open_key(REG_HANDLE *h, const char *name, REG_KEY **key) +static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) { struct ldb_context *c = h->backend_data; char *path; -- cgit From b88fc7a3911e0ff8b6d7d324028e351281e94c46 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Jun 2004 07:23:51 +0000 Subject: r959: - a static WERROR function should return a WERROR:-) - some minor format fixes metze (This used to be commit 72d9c70fdd21101744f6fad230c75b6a13105696) --- source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 7b574069e9..0633c94616 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Registry interface - Copyright (C) Jelmer Vernooij 2004. + Copyright (C) Jelmer Vernooij 2004. 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 @@ -88,7 +88,8 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) { - /* FIXME */ + /* FIXME */ + return WERR_FOOBAR; } static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) @@ -109,7 +110,7 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k ldb_search_free(c, msg); talloc_destroy(mem_ctx); - return WERR_OK;; + return WERR_OK; } static struct registry_ops reg_backend_ldb = { -- cgit From fa2e9ec311b99dee2fbff5ee5fa2c743298dacad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Jun 2004 08:12:45 +0000 Subject: r960: convert 'unsigned int' to uint_t in the most places metze (This used to be commit 18062d2ed9fc9224c43143c10efbf2f6f1f5bbe0) --- source4/lib/bitmap.c | 2 +- source4/lib/crypto/md5.c | 2 +- source4/lib/messages.c | 12 +++++----- source4/lib/pidfile.c | 2 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 28 +++++++++++----------- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 2 +- source4/lib/system.c | 2 +- source4/lib/tdb/common/spinlock.c | 22 ++++++++--------- source4/lib/tdb/common/tdbutil.c | 8 +++---- source4/lib/tdb/include/spinlock.h | 4 ++-- source4/lib/util.c | 2 +- source4/lib/util_str.c | 2 +- 12 files changed, 44 insertions(+), 44 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/bitmap.c b/source4/lib/bitmap.c index 63b093617b..2e67fb5439 100644 --- a/source4/lib/bitmap.c +++ b/source4/lib/bitmap.c @@ -129,7 +129,7 @@ wraparound ****************************************************************************/ int bitmap_find(struct bitmap *bm, unsigned ofs) { - unsigned int i, j; + uint_t i, j; if (ofs > bm->n) ofs = 0; diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index a393fc2532..1c53a0a152 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -107,7 +107,7 @@ void MD5Update(struct MD5Context *ctx, uint8_t const *buf, unsigned len) */ void MD5Final(uint8_t digest[16], struct MD5Context *ctx) { - unsigned int count; + uint_t count; uint8_t *p; /* Compute number of bytes mod 64 */ diff --git a/source4/lib/messages.c b/source4/lib/messages.c index 9357b12f1f..b4de7c0145 100644 --- a/source4/lib/messages.c +++ b/source4/lib/messages.c @@ -86,7 +86,7 @@ static void sig_usr1(void) static void ping_message(int msg_type, pid_t src, void *buf, size_t len) { const char *msg = buf ? buf : "none"; - DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(unsigned int)src, msg)); + DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(uint_t)src, msg)); message_send_pid(src, MSG_PONG, buf, len, True); } @@ -169,7 +169,7 @@ static BOOL message_notify(pid_t pid) ****************************************************************************/ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, unsigned int timeout) + BOOL duplicates_allowed, uint_t timeout) { TDB_DATA kbuf; TDB_DATA dbuf; @@ -301,7 +301,7 @@ BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL ****************************************************************************/ BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, unsigned int timeout) + BOOL duplicates_allowed, uint_t timeout) { return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout); } @@ -409,7 +409,7 @@ void message_dispatch(void) for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n", - msg_type, (unsigned int) src)); + msg_type, (uint_t) src)); n_handled = 0; for (dfn = dispatch_fns; dfn; dfn = dfn->next) { if (dfn->msg_type == msg_type) { @@ -421,7 +421,7 @@ void message_dispatch(void) if (!n_handled) { DEBUG(5,("message_dispatch: warning: no handlers registed for " "msg_type %d in pid %u\n", - msg_type, (unsigned int)getpid())); + msg_type, (uint_t)getpid())); } } SAFE_FREE(msgs_buf); @@ -514,7 +514,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void if (errno == ESRCH) { DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", - (unsigned int)crec.pid, crec.cnum, crec.name)); + (uint_t)crec.pid, crec.cnum, crec.name)); tdb_delete(the_tdb, kbuf); } } diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index 3471f27b8e..7126482256 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -99,7 +99,7 @@ void pidfile_create(const char *name) } memset(buf, 0, sizeof(buf)); - slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) getpid()); + slprintf(buf, sizeof(buf) - 1, "%u\n", (uint_t) getpid()); if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) { DEBUG(0,("ERROR: can't write to file %s: %s\n", pidFile, strerror(errno))); diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index fa4b3e4d18..36feaff907 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -338,7 +338,7 @@ const char *def_owner_sid_str = NULL; #define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) -typedef unsigned int DWORD; +typedef uint_t DWORD; typedef unsigned short WORD; typedef struct sk_struct SK_HDR; @@ -358,7 +358,7 @@ typedef struct regf_block { DWORD uk5; /* 0 */ DWORD uk6; /* 1 */ DWORD first_key; /* offset */ - unsigned int dblk_size; + uint_t dblk_size; DWORD uk7[116]; /* 1 */ DWORD chksum; } REGF_HDR; @@ -462,9 +462,9 @@ typedef struct hbin_blk_s { int type, size; struct hbin_blk_s *next; char *data; /* The data block */ - unsigned int file_offset; /* Offset in file */ - unsigned int free_space; /* Amount of free space in block */ - unsigned int fsp_off; /* Start of free space in block */ + uint_t file_offset; /* Offset in file */ + uint_t free_space; /* Amount of free space in block */ + uint_t fsp_off; /* Start of free space in block */ int complete, stored; } HBIN_BLK; @@ -1023,7 +1023,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent REGF *regf = h->backend_data; REG_KEY *tmp = NULL, *own; int namlen, clsname_len, sk_off, own_off; - unsigned int nk_id; + uint_t nk_id; SK_HDR *sk_hdr; int type; char key_name[1024], cls_name[1024]; @@ -1104,7 +1104,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent DEBUG(2, ("Owner Offset: %0X\n", own_off)); DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", - (unsigned int)own, (unsigned int)nk_hdr)); + (uint_t)own, (uint_t)nk_hdr)); /* * We should verify that the owner field is correct ... @@ -1185,7 +1185,7 @@ static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) * Allocate a unit of space ... and return a pointer as function param * and the block's offset as a side effect */ -static void *nt_alloc_regf_space(REG_HANDLE *h, int size, unsigned int *off) +static void *nt_alloc_regf_space(REG_HANDLE *h, int size, uint_t *off) { REGF *regf = h->backend_data; int tmp = 0; @@ -1357,10 +1357,10 @@ static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { * that first, then the owner, then the group SID. So, we do it that way * too. */ -static unsigned int nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) +static uint_t nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) { SEC_DESC *rsd = (SEC_DESC *)locn; - unsigned int size = 0, off = 0; + uint_t size = 0, off = 0; if (!regf || !sd || !locn) return 0; @@ -1424,10 +1424,10 @@ static unsigned int nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn * If it has already been stored, just get its offset from record * otherwise, store it and record its offset */ -static unsigned int nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) +static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) { int size = 0; - unsigned int sk_off; + uint_t sk_off; SK_HDR *sk_hdr; if (sec->offset) return sec->offset; @@ -1483,7 +1483,7 @@ static unsigned int nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) static int nt_store_reg_key(REG_HANDLE *regf, REG_KEY *key) { NK_HDR *nk_hdr; - unsigned int nk_off, sk_off, size; + uint_t nk_off, sk_off, size; if (!regf || !key) return 0; @@ -1581,7 +1581,7 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char { REGF *regf; REGF_HDR *regf_hdr; - unsigned int regf_id, hbin_id; + uint_t regf_id, hbin_id; HBIN_HDR *hbin_hdr; regf = (REGF *)talloc_p(h->mem_ctx, REGF); diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index b014f4da66..f392759b8d 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -40,7 +40,7 @@ * the keys and the RGDB contains the actual data. */ -typedef unsigned int DWORD; +typedef uint_t DWORD; typedef unsigned short WORD; typedef struct creg_block { diff --git a/source4/lib/system.c b/source4/lib/system.c index 2641a180ef..8d307caea3 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -507,7 +507,7 @@ long sys_random(void) Wrapper for srandom(). ****************************************************************************/ -void sys_srandom(unsigned int seed) +void sys_srandom(uint_t seed) { #if defined(HAVE_SRANDOM) srandom(seed); diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index 1b789d4daa..0c8991c1e0 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -55,7 +55,7 @@ static inline int __spin_trylock(spinlock_t *lock) { - unsigned int result; + uint_t result; asm volatile("ldstub [%1], %0" : "=r" (result) @@ -85,7 +85,7 @@ static inline int __spin_is_locked(spinlock_t *lock) static inline int __spin_trylock(spinlock_t *lock) { - unsigned int result; + uint_t result; __asm__ __volatile__( "1: lwarx %0,0,%1\n\ @@ -167,7 +167,7 @@ static inline int __spin_is_locked(spinlock_t *lock) /* Returns 0 if the lock is acquired, EBUSY otherwise. */ static inline int __spin_trylock(spinlock_t *lock) { - unsigned int val; + uint_t val; val = __lock_test_and_set(lock, 1); return val == 0 ? 0 : EBUSY; } @@ -185,16 +185,16 @@ static inline void __spin_lock_init(spinlock_t *lock) /* Returns 1 if the lock is held, 0 otherwise. */ static inline int __spin_is_locked(spinlock_t *lock) { - unsigned int val; + uint_t val; val = __add_and_fetch(lock, 0); return val; } #elif defined(MIPS_SPINLOCKS) -static inline unsigned int load_linked(unsigned long addr) +static inline uint_t load_linked(unsigned long addr) { - unsigned int res; + uint_t res; __asm__ __volatile__("ll\t%0,(%1)" : "=r" (res) @@ -203,9 +203,9 @@ static inline unsigned int load_linked(unsigned long addr) return res; } -static inline unsigned int store_conditional(unsigned long addr, unsigned int value) +static inline uint_t store_conditional(unsigned long addr, uint_t value) { - unsigned int res; + uint_t res; __asm__ __volatile__("sc\t%0,(%2)" : "=r" (res) @@ -215,7 +215,7 @@ static inline unsigned int store_conditional(unsigned long addr, unsigned int va static inline int __spin_trylock(spinlock_t *lock) { - unsigned int mw; + uint_t mw; do { mw = load_linked(lock); @@ -418,7 +418,7 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) return 0; } -int tdb_create_rwlocks(int fd, unsigned int hash_size) +int tdb_create_rwlocks(int fd, uint_t hash_size) { unsigned size, i; tdb_rwlock_t *rwlocks; @@ -460,7 +460,7 @@ int tdb_clear_spinlocks(TDB_CONTEXT *tdb) return 0; } #else -int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } +int tdb_create_rwlocks(int fd, uint_t hash_size) { return 0; } int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 05f4713c82..6b9ad414c5 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -91,7 +91,7 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) Lock a chain with timeout (in seconds). ****************************************************************************/ -static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type) +static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, uint_t timeout, int rw_type) { /* Allow tdb_chainlock to be interrupted by an alarm. */ int ret; @@ -129,7 +129,7 @@ static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, u Write lock a chain. Return -1 if timeout or lock failed. ****************************************************************************/ -int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout) +int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, uint_t timeout) { return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); } @@ -138,7 +138,7 @@ int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, unsigned int time Lock a chain by string. Return -1 if timeout or lock failed. ****************************************************************************/ -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -160,7 +160,7 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Read lock a chain by string. Return -1 if timeout or lock failed. ****************************************************************************/ -int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout) +int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); diff --git a/source4/lib/tdb/include/spinlock.h b/source4/lib/tdb/include/spinlock.h index 967fe37457..1255d455de 100644 --- a/source4/lib/tdb/include/spinlock.h +++ b/source4/lib/tdb/include/spinlock.h @@ -36,7 +36,7 @@ typedef struct { int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); +int tdb_create_rwlocks(int fd, uint_t hash_size); int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) @@ -49,7 +49,7 @@ int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #else int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); +int tdb_create_rwlocks(int fd, uint_t hash_size); #endif int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #define TDB_SPINLOCK_SIZE(hash_size) 0 diff --git a/source4/lib/util.c b/source4/lib/util.c index dd53d2b174..2fc87241de 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -189,7 +189,7 @@ int set_blocking(int fd, BOOL set) Sleep for a specified number of milliseconds. ********************************************************************/ -void msleep(unsigned int t) +void msleep(uint_t t) { struct timeval tval; diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 0113b1ae48..7b1a81bdfd 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -402,7 +402,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength) if (len > maxlength) { DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", - (unsigned int)(len-maxlength), len, maxlength, src)); + (uint_t)(len-maxlength), len, maxlength, src)); len = maxlength; } -- cgit From 98d291423ff581786a369ce373c861f94c654aa0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Jun 2004 08:30:34 +0000 Subject: r961: convert 'uchar' to 'uint8_t' metze (This used to be commit 9f914e4af99e18b469d4cf9d8b1514a2bd28ddec) --- source4/lib/crypto/hmacmd5.c | 14 ++++++-------- source4/lib/util.c | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index 0a7cbb3663..0d52e36858 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -28,14 +28,14 @@ /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. ***********************************************************************/ -void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) +void hmac_md5_init_rfc2104(uint8_t *key, int key_len, HMACMD5Context *ctx) { int i; /* if key is longer than 64 bytes reset it to key=MD5(key) */ if (key_len > 64) { - uchar tk[16]; + uint8_t tk[16]; struct MD5Context tctx; MD5Init(&tctx); @@ -66,7 +66,7 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx) /*********************************************************************** the microsoft version of hmac_md5 initialisation. ***********************************************************************/ -void hmac_md5_init_limK_to_64(const uchar* key, int key_len, +void hmac_md5_init_limK_to_64(const uint8_t *key, int key_len, HMACMD5Context *ctx) { /* if key is longer than 64 bytes truncate it */ @@ -81,7 +81,7 @@ void hmac_md5_init_limK_to_64(const uchar* key, int key_len, /*********************************************************************** update hmac_md5 "inner" buffer ***********************************************************************/ -void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) +void hmac_md5_update(const uint8_t *text, int text_len, HMACMD5Context *ctx) { MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ } @@ -89,8 +89,7 @@ void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx) /*********************************************************************** finish off hmac_md5 "inner" buffer and generate outer one. ***********************************************************************/ -void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) - +void hmac_md5_final(uint8_t *digest, HMACMD5Context *ctx) { struct MD5Context ctx_o; @@ -106,7 +105,7 @@ void hmac_md5_final(uchar *digest, HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ -void hmac_md5(const uchar key[16], const uchar *data, int data_len, uchar* digest) +void hmac_md5(const uint8_t key[16], const uint8_t *data, int data_len, uint8_t *digest) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(key, 16, &ctx); @@ -116,4 +115,3 @@ void hmac_md5(const uchar key[16], const uchar *data, int data_len, uchar* diges } hmac_md5_final(digest, &ctx); } - diff --git a/source4/lib/util.c b/source4/lib/util.c index 2fc87241de..e8ad79af0c 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -968,7 +968,7 @@ static BOOL unix_do_match(char *regexp, char *str) return False; } -void dump_data_pw(const char *msg, const uchar * data, size_t len) +void dump_data_pw(const char *msg, const uint8_t * data, size_t len) { #ifdef DEBUG_PASSWORD DEBUG(11, ("%s", msg)); -- cgit From 770e3307ce3da928762e15a136c562df86a9c799 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Jun 2004 10:12:52 +0000 Subject: r962: convert 'unsigned' and 'unsigned int' to uint_t metze (This used to be commit 57151e80eb1090281401930c8fe25b20a8cf3a38) --- source4/lib/bitmap.c | 8 ++++---- source4/lib/crypto/md5.c | 8 ++++---- source4/lib/iconv.c | 2 +- source4/lib/interfaces.c | 2 +- source4/lib/pidfile.c | 2 +- source4/lib/talloc.c | 12 ++++++------ source4/lib/tdb/common/spinlock.c | 4 ++-- source4/lib/tdb/common/tdb.c | 2 +- source4/lib/time.c | 4 ++-- source4/lib/util.c | 2 +- source4/lib/wins_srv.c | 4 ++-- 11 files changed, 25 insertions(+), 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/bitmap.c b/source4/lib/bitmap.c index 2e67fb5439..5a8325d4ba 100644 --- a/source4/lib/bitmap.c +++ b/source4/lib/bitmap.c @@ -86,7 +86,7 @@ struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n) /**************************************************************************** set a bit in a bitmap ****************************************************************************/ -BOOL bitmap_set(struct bitmap *bm, unsigned i) +BOOL bitmap_set(struct bitmap *bm, uint_t i) { if (i >= bm->n) { DEBUG(0,("Setting invalid bitmap entry %d (of %d)\n", @@ -100,7 +100,7 @@ BOOL bitmap_set(struct bitmap *bm, unsigned i) /**************************************************************************** clear a bit in a bitmap ****************************************************************************/ -BOOL bitmap_clear(struct bitmap *bm, unsigned i) +BOOL bitmap_clear(struct bitmap *bm, uint_t i) { if (i >= bm->n) { DEBUG(0,("clearing invalid bitmap entry %d (of %d)\n", @@ -114,7 +114,7 @@ BOOL bitmap_clear(struct bitmap *bm, unsigned i) /**************************************************************************** query a bit in a bitmap ****************************************************************************/ -BOOL bitmap_query(struct bitmap *bm, unsigned i) +BOOL bitmap_query(struct bitmap *bm, uint_t i) { if (i >= bm->n) return False; if (bm->b[i/32] & (1<<(i%32))) { @@ -127,7 +127,7 @@ BOOL bitmap_query(struct bitmap *bm, unsigned i) find a zero bit in a bitmap starting at the specified offset, with wraparound ****************************************************************************/ -int bitmap_find(struct bitmap *bm, unsigned ofs) +int bitmap_find(struct bitmap *bm, uint_t ofs) { uint_t i, j; diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index 1c53a0a152..07028e9043 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -27,12 +27,12 @@ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); /* * Note: this code is harmless on little-endian machines. */ -static void byteReverse(uint8_t *buf, unsigned longs) +static void byteReverse(uint8_t *buf, uint_t longs) { uint32_t t; do { - t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); + t = (uint32_t) ((uint_t) buf[3] << 8 | buf[2]) << 16 | + ((uint_t) buf[1] << 8 | buf[0]); *(uint32_t *) buf = t; buf += 4; } while (--longs); @@ -57,7 +57,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, uint8_t const *buf, unsigned len) +void MD5Update(struct MD5Context *ctx, uint8_t const *buf, uint_t len) { register uint32_t t; diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 65fa45248f..f75621af09 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -326,7 +326,7 @@ static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { - unsigned v; + uint_t v; if ((*inbuf)[0] != '@') { /* seven bit ascii case */ diff --git a/source4/lib/interfaces.c b/source4/lib/interfaces.c index 96f4b4cd94..89ed144eec 100644 --- a/source4/lib/interfaces.c +++ b/source4/lib/interfaces.c @@ -284,7 +284,7 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) i = ifc.ifc_len; while (i > 0 && total < max_interfaces) { - unsigned inc; + uint_t inc; inc = ifr->ifr_addr.sa_len; diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index 7126482256..989f19b323 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -32,7 +32,7 @@ pid_t pidfile_pid(const char *name) { int fd; char pidstr[20]; - unsigned ret; + uint_t ret; pstring pidFile; slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 92e0d52d2d..f3cdd75231 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -53,7 +53,7 @@ struct talloc_chunk { TALLOC_CTX *context; size_t size; void *ptr; - unsigned magic; + uint_t magic; }; @@ -492,7 +492,7 @@ char *talloc_describe_all(TALLOC_CTX *rt) if (!rt) return NULL; s = talloc_asprintf(rt, "global talloc allocations in pid: %u\n", - (unsigned) getpid()); + (uint_t) getpid()); s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", "name", "chunks", "bytes"); s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", @@ -517,8 +517,8 @@ char *talloc_describe_all(TALLOC_CTX *rt) s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", what, - (unsigned) n_chunks, - (unsigned) bytes); + (uint_t) n_chunks, + (uint_t) bytes); total_bytes += bytes; total_chunks += n_chunks; } @@ -532,7 +532,7 @@ char *talloc_describe_all(TALLOC_CTX *rt) s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", "TOTAL", - (unsigned) total_chunks, (unsigned) total_bytes); + (uint_t) total_chunks, (uint_t) total_bytes); return s; } @@ -563,7 +563,7 @@ void talloc_get_allocation(TALLOC_CTX *t, /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned count) +void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, uint_t count) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index 0c8991c1e0..ee3eff1b31 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -420,7 +420,7 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) int tdb_create_rwlocks(int fd, uint_t hash_size) { - unsigned size, i; + uint_t size, i; tdb_rwlock_t *rwlocks; size = TDB_SPINLOCK_SIZE(hash_size); @@ -446,7 +446,7 @@ int tdb_create_rwlocks(int fd, uint_t hash_size) int tdb_clear_spinlocks(TDB_CONTEXT *tdb) { tdb_rwlock_t *rwlocks; - unsigned i; + uint_t i; if (tdb->header.rwlocks == 0) return 0; if (!tdb->map_ptr) return -1; diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index b7b9631444..d4c0928217 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -541,7 +541,7 @@ static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) if (tailer != rec.rec_len + sizeof(rec)) { printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec))); + (uint_t)tailer, (uint_t)(rec.rec_len + sizeof(rec))); } return rec.next; } diff --git a/source4/lib/time.c b/source4/lib/time.c index 5fd8aa3081..dbbfab24b5 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -150,7 +150,7 @@ BOOL null_mtime(time_t mtime) static uint16_t make_dos_date1(struct tm *t) { uint16_t ret=0; - ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); + ret = (((uint_t)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); return ret; } @@ -161,7 +161,7 @@ static uint16_t make_dos_date1(struct tm *t) static uint16_t make_dos_time1(struct tm *t) { uint16_t ret=0; - ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); + ret = ((((uint_t)t->tm_min >> 3)&0x7) | (((uint_t)t->tm_hour) << 3)); ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); return ret; } diff --git a/source4/lib/util.c b/source4/lib/util.c index e8ad79af0c..16f5e7a888 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -982,7 +982,7 @@ void dump_data_pw(const char *msg, const uint8_t * data, size_t len) /* see if a range of memory is all zero. A NULL pointer is considered to be all zero */ -BOOL all_zero(const char *ptr, unsigned size) +BOOL all_zero(const char *ptr, uint_t size) { int i; if (!ptr) return True; diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index 30e81b08ab..71368658b0 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -139,7 +139,7 @@ void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip) /* return the total number of wins servers, dead or not */ -unsigned wins_srv_count(void) +uint_t wins_srv_count(void) { const char **list; int count = 0; @@ -327,7 +327,7 @@ exit: return a count of the number of IPs for a particular tag, including dead ones */ -unsigned wins_srv_count_tag(const char *tag) +uint_t wins_srv_count_tag(const char *tag) { const char **list; int i, count=0; -- cgit From 4309727424a0a27bbf5372789bc8644b96a28ba9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 3 Jun 2004 15:59:26 +0000 Subject: r990: fix tdb standalone build metze (This used to be commit 4c1c9f59ccea8b6cd7edf3bad8acb9cd8c772670) --- source4/lib/tdb/tools/tdbtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 65bbedf709..92009dcef4 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -63,7 +63,7 @@ static TDB_CONTEXT *tdb; static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); -static void print_asc(uint8_t *buf,int len) +static void print_asc(unsigned char *buf,int len) { int i; @@ -77,7 +77,7 @@ static void print_asc(uint8_t *buf,int len) printf("%c",isprint(buf[i])?buf[i]:'.'); } -static void print_data(uint8_t *buf,int len) +static void print_data(unsigned char *buf,int len) { int i=0; if (len<=0) return; -- cgit From 8087d844ef59a82617be51f7c887b9bafe362f80 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Jun 2004 23:15:16 +0000 Subject: r995: - renamed many of our crypto routines to use the industry standard names rather than our crazy naming scheme. So DES is now called des_crypt() rather than smbhash() - added the code from the solution of the ADS crypto challenge that allows Samba to correctly handle a 128 bit session key in all of the netr_ServerAuthenticateX() varients. A huge thanks to Luke Howard from PADL for solving this one! - restructured the server side rpc authentication to allow for other than NTLMSSP sign and seal. This commit just adds the structure, the next commit will add schannel server side support. - added 128 bit session key support to our client side code, and testing against w2k3 with smbtorture. Works well. (This used to be commit 729b2f41c924a0b435d44a14209e6dacc2304cee) --- source4/lib/crypto/hmacmd5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index 0d52e36858..9b24279f71 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -28,7 +28,7 @@ /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. ***********************************************************************/ -void hmac_md5_init_rfc2104(uint8_t *key, int key_len, HMACMD5Context *ctx) +void hmac_md5_init_rfc2104(const uint8_t *key, int key_len, HMACMD5Context *ctx) { int i; -- cgit From e06d8e94a9eeb87c0c2ee8f22375c1ab6d18a3de Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Jun 2004 01:29:49 +0000 Subject: r1017: - move to a centralised way of handling talloc/ldb interaction (This used to be commit 363cb3377a0eca5bfef71a02dcdc21c5fadbaf32) --- source4/lib/talloc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index f3cdd75231..f61ef6d906 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -582,4 +582,13 @@ void *talloc_strdup_w(TALLOC_CTX *mem_ctx, void *s) return talloc_memdup(mem_ctx, s, (len+1)*2); } +/* + a alloc function for ldb that uses talloc +*/ +void *talloc_ldb_alloc(void *context, void *ptr, size_t size) +{ + return talloc_realloc((TALLOC_CTX *)context, ptr, size); +} + + /** @} */ -- cgit From b553acce4b426e1a2e4fda3a9acbfbf41003154a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Jun 2004 01:30:27 +0000 Subject: r1018: fix a const and unsigned int problem in ldb (This used to be commit 3d52ca93731ad67c14ac42f627e3feb1a964b29a) --- source4/lib/ldb/common/ldb_msg.c | 4 ++-- source4/lib/ldb/include/ldb.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 055569b0ee..0d5b47f920 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -168,7 +168,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, add a string element to a message */ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, - char *attr_name, char *str) + const char *attr_name, char *str) { struct ldb_val val; @@ -226,7 +226,7 @@ int ldb_msg_find_int(const struct ldb_message *msg, unsigned int ldb_msg_find_uint(const struct ldb_message *msg, const char *attr_name, - int default_value) + unsigned int default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); if (!v || !v->data) { diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 448d5607a8..241f186991 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -300,7 +300,7 @@ int ldb_msg_find_int(const struct ldb_message *msg, int default_value); unsigned int ldb_msg_find_uint(const struct ldb_message *msg, const char *attr_name, - int default_value); + unsigned int default_value); double ldb_msg_find_double(const struct ldb_message *msg, const char *attr_name, double default_value); -- cgit From fe3bcd4588f75805a12ff6c11f4f0794f9963463 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 5 Jun 2004 18:45:27 +0000 Subject: r1032: Fix RPC backend segfault (This used to be commit db902bff3c5eb54d6b1035d009948ff316cffa94) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 28e2094bed..4e6944a1e3 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -88,7 +88,6 @@ static WERROR rpc_query_key(REG_KEY *k); static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) { - char *binding = strdup(location); NTSTATUS status; char *user, *pass; @@ -98,7 +97,7 @@ static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char pass = strchr(user, '%'); *pass = '\0'; pass++; - status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, binding, + status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, h->location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), -- cgit From 39e465a0965b7974c95f318db240d47cced37874 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 5 Jun 2004 19:30:13 +0000 Subject: r1035: Support shared modules again (This used to be commit 7949dc25ab05f7d5ad6217a6304e1f50b8b5dc41) --- source4/lib/registry/tools/regdiff.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 7520e653bb..b599a54c2e 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -91,7 +91,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } } - int main(int argc, char **argv) +int main(int argc, char **argv) { int opt; poptContext pc; @@ -115,7 +115,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) }; pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); - + while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { case 'c': @@ -123,9 +123,9 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) else if(!credentials2) credentials2 = poptGetOptArg(pc); break; case 'b': - if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); - else if(!backend2) backend2 = poptGetOptArg(pc); - break; + if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); + else if(!backend2) backend2 = poptGetOptArg(pc); + break; } } setup_logging(argv[0], True); @@ -154,13 +154,13 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } if(!backend2) backend2 = "dir"; - + error = reg_open(backend2, location2, credentials2, &h2); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); return 1; } - + poptFreeContext(pc); if(outputfile) { @@ -175,24 +175,24 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) fprintf(fd, "; Generated using regdiff\n"); error2 = error = WERR_OK; - + for(i = 0; ; i++) { if(backend1) error = reg_get_hive(h1, i, &root1); else root1 = NULL; if(!W_ERROR_IS_OK(error)) break; - + if(backend2) error2 = reg_get_hive(h2, i, &root2); else root2 = NULL; - + if(!W_ERROR_IS_OK(error2)) break; - + writediff(root1, root2, fd); if(!root1 && !root2) break; } fclose(fd); - + return 0; } -- cgit From 439a78014625cf93c0e787747aec08d0f45b9781 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 5 Jun 2004 20:53:18 +0000 Subject: r1038: Check whether a module actually exists before attempting to load it... (This used to be commit c8e3fd75e594c8fc841337234e99be288180822f) --- source4/lib/module.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index f03e19d924..1fcb57fac1 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -35,7 +35,10 @@ NTSTATUS smb_load_module(const char *module_name) DIR *dir; struct dirent *dirent; - stat(module_name, &st); + if(stat(module_name, &st) < 0) { + DEBUG(0, ("Can't stat module '%s'\n", module_name)); + return NT_STATUS_UNSUCCESSFUL; + } /* If the argument is a directory, recursively load all files / * directories in it */ -- cgit From 7ea6a0b1fc3e5f35e5096ad820053d54c4496a09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 6 Jun 2004 07:10:58 +0000 Subject: r1040: make sure main() doesn't get auto-prototyped (This used to be commit 7c2279e4bc631d88e402ac82c6c17fb811785394) --- source4/lib/registry/tools/regdiff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index b599a54c2e..c46411ae31 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -91,7 +91,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } } -int main(int argc, char **argv) + int main(int argc, char **argv) { int opt; poptContext pc; -- cgit From 42eadaf3d94afc7abf8ba2f1a67c55f317215483 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 6 Jun 2004 12:59:14 +0000 Subject: r1048: - moved the schannel definitions into a separate schannel.idl - added server side support for schannel type 23. This allows WinXP to establish a schannel connection to Samba4 as an ADS DC - added client side support for schannel type 23, but disabled it as currently the client code has now way of getting the fully qualified domain name (which is needed) - report dcerpc faults in the server code in the log (This used to be commit 55e0b014fe14ca8811b55887208a1c3147ddb0d2) --- source4/lib/util_str.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 7b1a81bdfd..bb94d3fce6 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1396,3 +1396,37 @@ size_t valgrind_strlen(const char *s) return count; } #endif + + +/* + format a string into length-prefixed dotted domain format, as used in NBT + and in some ADS structures +*/ +const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s) +{ + char *ret; + int i; + if (!s || !*s) { + return talloc_strdup(mem_ctx, ""); + } + ret = talloc(mem_ctx, strlen(s)+2); + if (!ret) { + return ret; + } + + memcpy(ret+1, s, strlen(s)+1); + ret[0] = '.'; + + for (i=0;ret[i];i++) { + if (ret[i] == '.') { + char *p = strchr(ret+i+1, '.'); + if (p) { + ret[i] = p-(ret+i+1); + } else { + ret[i] = strlen(ret+i+1); + } + } + } + + return ret; +} -- cgit From cfb25947f2fd45254b5fac0be6c15dd4e1c9cc84 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Jun 2004 01:40:30 +0000 Subject: r1052: Remove autogenerated file. (This used to be commit 108efcc002c2eccfd1da30fff5c11aa67af09f9e) --- source4/lib/ldb/man/man3/ldb.3 | 165 ----------------------------------------- 1 file changed, 165 deletions(-) delete mode 100644 source4/lib/ldb/man/man3/ldb.3 (limited to 'source4/lib') diff --git a/source4/lib/ldb/man/man3/ldb.3 b/source4/lib/ldb/man/man3/ldb.3 deleted file mode 100644 index d6e20035c6..0000000000 --- a/source4/lib/ldb/man/man3/ldb.3 +++ /dev/null @@ -1,165 +0,0 @@ -.TH "ldb" "3" "May 2004" "" "" -.SH "NAME" -ldb \- A light-weight database library -.PP -.SH "SYNOPSIS" -.PP -\fB#include \fP -.PP -.SH "DESCRIPTION" -.PP -ldb is a light weight embedded database library and API\&. With a -programming interface that is very similar to LDAP, ldb can store its -data either in a tdb(3) database or in a real LDAP database\&. -.PP -When used with the tdb backend ldb does not require any database -daemon\&. Instead, ldb function calls are processed immediately by the -ldb library, which does IO directly on the database, while allowing -multiple readers/writers using operating system byte range locks\&. This -leads to an API with very low overheads, often resulting in speeds of -more than 10x what can be achieved with a more traditional LDAP -architecture\&. -.PP -It a taxonomy of databases ldb would sit half way between key/value -pair databases (such as berkley db or tdb) and a full LDAP -database\&. With a structured attribute oriented API like LDAP and good -indexing capabilities, ldb can be used for quite sophisticated -applications that need a light weight database, without the -administrative overhead of a full LDAP installation\&. -.PP -Included with ldb are a number of useful command line tools for -manipulating a ldb database\&. These tools are similar in style to the -equivalent ldap command line tools\&. -.PP -In its default mode of operation with a tdb backend, ldb can also be -seen as a "schema-less LDAP"\&. By default ldb does not require a -schema, which greatly reduces the complexity of getting started with -ldb databases\&. As the complexity of you application grows you can take -advantage of some of the optional schema-like attributes that ldb -offers, or you can migrate to using the full LDAP api while keeping -your exiting ldb code\&. -.PP -If you are new to ldb, then I suggest starting with the manual pages -for ldbsearch(1) and ldbedit(1), and experimenting with a local -database\&. Then I suggest you look at the ldb_connect(3) and -ldb_search(3) manual pages\&. -.PP -.SH "INDEX" -.PP -.IP -.IP "\fBldbsearch(1)\fP" -command line ldb search utility -.IP -.IP "\fBldbedit(1)\fP" -edit all or part of a ldb databse using your -favourite editor -.IP -.IP "\fBldbedit(1)\fP" -edit all or part of a ldb databse using your -favourite editor -.IP -.IP "\fBldbadd(1)\fP" -add records to a ldb database using LDIF formatted input -.IP -.IP "\fBldbdel(1)\fP" -delete records from a ldb database -.IP -.IP "\fBldbmodify(1)\fP" -modify records in a ldb database using LDIF -formatted input -.IP -.IP "\fBldb_connect(3)\fP" -connect to a ldb backend -.IP -.IP "\fBldb_close(3)\fP" -close a connection to a ldb backend -.IP -.IP "\fBldb_search(3)\fP" -perform a database search -.IP -.IP "\fBldb_search_free(3)\fP" -free the results of a ldb_search -.IP -.IP "\fBldb_add(3)\fP" -add a record to the database -.IP -.IP "\fBldb_delete(3)\fP" -delete a record from the database -.IP -.IP "\fBldb_modify(3)\fP" -modify a record in the database -.IP -.IP "\fBldb_errstring(3)\fP" -retrieve extended error information from the -last operation -.IP -.IP "\fBldb_ldif_write(3)\fP" -write a LDIF formatted message -.IP -.IP "\fBldb_ldif_write_\fB3\fP\fP" -write a LDIF formatted message to a file -.IP -.IP "\fBldb_ldif_read(3)\fP" -read a LDIF formatted message -.IP -.IP "\fBldb_ldif_read_free(3)\fP" -free the result of a ldb_ldif_read() -.IP -.IP "\fBldb_ldif_read_\fB3\fP\fP" -read a LDIF message from a file -.IP -.IP "\fBldb_ldif_read_string(3)\fP" -read a LDIF message from a string -.IP -.IP "\fBldb_msg_find_element(3)\fP" -find an element in a ldb_message -.IP -.IP "\fBldb_val_equal_exact(3)\fP" -compare two ldb_val structures -.IP -.IP "\fBldb_msg_find_val(3)\fP" -find an element by value -.IP -.IP "\fBldb_msg_add_empty(3)\fP" -add an empty message element to a ldb_message -.IP -.IP "\fBldb_msg_add(3)\fP" -add a non-empty message element to a ldb_message -.IP -.IP "\fBldb_msg_element_compare(3)\fP" -compare two ldb_message_element structures -.IP -.IP "\fBldb_msg_find_int(3)\fP" -return an integer value from a ldb_message -.IP -.IP "\fBldb_msg_find_uint(3)\fP" -return an unsigned integer value from a ldb_message -.IP -.IP "\fBldb_msg_find_double(3)\fP" -return a double value from a ldb_message -.IP -.IP "\fBldb_msg_find_string(3)\fP" -return a string value from a ldb_message -.IP -.IP "\fBldb_set_alloc(3)\fP" -set the memory allocation function to be used by ldb -.IP -.IP "\fBldb_set_debug(3)\fP" -set a debug handler to be used by ldb -.IP -.IP "\fBldb_set_debug_stderr(3)\fP" -set a debug handler for stderr output -.IP -.PP -.SH "AUTHOR" -.PP -ldb was written by Andrew Tridgell -http://samba\&.org/~tridge/ -.PP -If you wish to report a problem or make a suggestion then please see -the http://ldb\&.samba\&.org/ web site for -current contact and maintainer information\&. -.PP -ldb is released under the GNU Lesser General Public License version 2 -or later\&. Please see the file COPYING for license details\&. -.PP -- cgit From b619abb98e0c9384f75586a56e63fd3a1fc6badb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Jun 2004 01:51:04 +0000 Subject: r1053: Make tdb build standalone: - #include - uint_t isn't a valid type, change back to unsigned int (This used to be commit f690325565d2393bba3cb9f6e7cdf3753cbd4423) --- source4/lib/tdb/Makefile.tdb | 2 +- source4/lib/tdb/common/spinlock.c | 26 +++++++++++++------------- source4/lib/tdb/common/tdb.c | 3 ++- source4/lib/tdb/include/spinlock.h | 4 ++-- 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.tdb b/source4/lib/tdb/Makefile.tdb index db697e9379..35e208256c 100644 --- a/source4/lib/tdb/Makefile.tdb +++ b/source4/lib/tdb/Makefile.tdb @@ -26,4 +26,4 @@ bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) $(CC) $(CFLAGS) -o tdbbackup tools/tdbbackup.o $(TDB_OBJ) clean: - rm -f $(PROGS) common/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm + rm -f $(PROGS) common/*.o tools/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index ee3eff1b31..27481e221c 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -55,7 +55,7 @@ static inline int __spin_trylock(spinlock_t *lock) { - uint_t result; + unsigned int result; asm volatile("ldstub [%1], %0" : "=r" (result) @@ -85,7 +85,7 @@ static inline int __spin_is_locked(spinlock_t *lock) static inline int __spin_trylock(spinlock_t *lock) { - uint_t result; + unsigned int result; __asm__ __volatile__( "1: lwarx %0,0,%1\n\ @@ -167,7 +167,7 @@ static inline int __spin_is_locked(spinlock_t *lock) /* Returns 0 if the lock is acquired, EBUSY otherwise. */ static inline int __spin_trylock(spinlock_t *lock) { - uint_t val; + unsigned int val; val = __lock_test_and_set(lock, 1); return val == 0 ? 0 : EBUSY; } @@ -185,16 +185,16 @@ static inline void __spin_lock_init(spinlock_t *lock) /* Returns 1 if the lock is held, 0 otherwise. */ static inline int __spin_is_locked(spinlock_t *lock) { - uint_t val; + unsigned int val; val = __add_and_fetch(lock, 0); return val; } #elif defined(MIPS_SPINLOCKS) -static inline uint_t load_linked(unsigned long addr) +static inline unsigned int load_linked(unsigned long addr) { - uint_t res; + unsigned int res; __asm__ __volatile__("ll\t%0,(%1)" : "=r" (res) @@ -203,9 +203,9 @@ static inline uint_t load_linked(unsigned long addr) return res; } -static inline uint_t store_conditional(unsigned long addr, uint_t value) +static inline unsigned int store_conditional(unsigned long addr, unsigned int value) { - uint_t res; + unsigned int res; __asm__ __volatile__("sc\t%0,(%2)" : "=r" (res) @@ -215,7 +215,7 @@ static inline uint_t store_conditional(unsigned long addr, uint_t value) static inline int __spin_trylock(spinlock_t *lock) { - uint_t mw; + unsigned int mw; do { mw = load_linked(lock); @@ -418,9 +418,9 @@ int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) return 0; } -int tdb_create_rwlocks(int fd, uint_t hash_size) +int tdb_create_rwlocks(int fd, unsigned int hash_size) { - uint_t size, i; + unsigned int size, i; tdb_rwlock_t *rwlocks; size = TDB_SPINLOCK_SIZE(hash_size); @@ -446,7 +446,7 @@ int tdb_create_rwlocks(int fd, uint_t hash_size) int tdb_clear_spinlocks(TDB_CONTEXT *tdb) { tdb_rwlock_t *rwlocks; - uint_t i; + unsigned int i; if (tdb->header.rwlocks == 0) return 0; if (!tdb->map_ptr) return -1; @@ -460,7 +460,7 @@ int tdb_clear_spinlocks(TDB_CONTEXT *tdb) return 0; } #else -int tdb_create_rwlocks(int fd, uint_t hash_size) { return 0; } +int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index d4c0928217..ef13955fab 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -541,7 +542,7 @@ static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) if (tailer != rec.rec_len + sizeof(rec)) { printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (uint_t)tailer, (uint_t)(rec.rec_len + sizeof(rec))); + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); } return rec.next; } diff --git a/source4/lib/tdb/include/spinlock.h b/source4/lib/tdb/include/spinlock.h index 1255d455de..967fe37457 100644 --- a/source4/lib/tdb/include/spinlock.h +++ b/source4/lib/tdb/include/spinlock.h @@ -36,7 +36,7 @@ typedef struct { int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, uint_t hash_size); +int tdb_create_rwlocks(int fd, unsigned int hash_size); int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) @@ -49,7 +49,7 @@ int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #else int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, uint_t hash_size); +int tdb_create_rwlocks(int fd, unsigned int hash_size); #endif int tdb_clear_spinlocks(TDB_CONTEXT *tdb); #define TDB_SPINLOCK_SIZE(hash_size) 0 -- cgit From f63cd117ae99fb4f8e65272ada0ded23318f337c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Jun 2004 01:53:55 +0000 Subject: r1054: Build extra binaries in bin directory like ldb does. (This used to be commit 6c15d5f31bdb2559656c96ae7f01f99d1ab9cb36) --- source4/lib/tdb/Makefile.tdb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.tdb b/source4/lib/tdb/Makefile.tdb index 35e208256c..a863b0de8b 100644 --- a/source4/lib/tdb/Makefile.tdb +++ b/source4/lib/tdb/Makefile.tdb @@ -11,19 +11,19 @@ TDB_OBJ = common/tdb.o common/spinlock.o default: $(PROGS) bin/tdbtest: tools/tdbtest.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm + $(CC) $(CFLAGS) -o bin/tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm bin/tdbtool: tools/tdbtool.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtool tools/tdbtool.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbtool tools/tdbtool.o $(TDB_OBJ) bin/tdbtorture: tools/tdbtorture.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbtorture tools/tdbtorture.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbtorture tools/tdbtorture.o $(TDB_OBJ) bin/tdbdump: tools/tdbdump.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbdump tools/tdbdump.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbdump tools/tdbdump.o $(TDB_OBJ) bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o tdbbackup tools/tdbbackup.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbbackup tools/tdbbackup.o $(TDB_OBJ) clean: rm -f $(PROGS) common/*.o tools/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm -- cgit From 8a01231a8bb03884c17c174f7d2cfea536da1130 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Jun 2004 01:59:23 +0000 Subject: r1055: Standalone build fixes for ldb: - Various Makefile fixes - #include ldb still needs a proper build system though. (-: (This used to be commit 52e4fe8ce9142c4002263686c8043d94b37d7a9c) --- source4/lib/ldb/Makefile.ldb | 6 +++--- source4/lib/ldb/include/includes.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 392407a46e..5573fba32f 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -11,10 +11,10 @@ endif TDBDIR=../tdb -CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -I$(TDBDIR)/include -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) -TDB_OBJ=$(TDBDIR)/tdb.o $(TDBDIR)/spinlock.o +TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ @@ -70,7 +70,7 @@ clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) man/man?/*.[13] proto: - mkproto.pl */*.c > include/proto.h + perl ../../script/mkproto.pl */*.c > include/proto.h etags: etags */*.[ch] diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index bf61a983e0..e55b494b98 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -6,6 +6,7 @@ #define _GNU_SOURCE #endif #include +#include #include #include #include @@ -18,5 +19,5 @@ #include #include #include "ldb.h" -#include "tdb/tdb.h" +#include "tdb.h" #include "proto.h" -- cgit From a125e49d6740c44a36e6d5a1af33700163a11e95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jun 2004 19:25:26 +0000 Subject: r1086: Add defer open test to check timeout on sharing violation open. This has found some signing errors in the Samba3.0 implementation of the deferred open code. Still working on these... Jeremy (This used to be commit 0068cb12ef91515a95f17a1be7dfbc83fbb89eba) --- source4/lib/time.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index dbbfab24b5..9d906af2fa 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -409,3 +409,10 @@ NTTIME nttime_from_string(const char *s) { return strtoull(s, NULL, 0); } + +long long usec_time_diff(struct timeval *larget, struct timeval *smallt) +{ + long long sec_diff = larget->tv_sec - smallt->tv_sec; + return (sec_diff * 1000000) + (long long)(larget->tv_usec - smallt->tv_usec); +} + -- cgit From 9503af8d648eb727b954dfe4c09d5764038a245e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 12 Jun 2004 15:12:23 +0000 Subject: r1118: Read-only enumeration of keys in the LDB backend works now :-) (This used to be commit 456f97eed05047b20acceb50708b47209c37ca20) --- source4/lib/registry/common/reg_interface.c | 25 +++-- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 106 +++++++++++++++------ 2 files changed, 95 insertions(+), 36 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 6ad7ee69cb..0a0cf05c2e 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -85,6 +85,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) return NULL; } +/* Check whether a certain backend is present */ BOOL reg_has_backend(const char *backend) { return reg_find_backend_entry(backend) != NULL?True:False; @@ -129,6 +130,7 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia return werr; } +/* Open a key by name (including the hive name!) */ WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result) { REG_KEY *hive; @@ -195,9 +197,13 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) mem_ctx = talloc_init("mem_ctx"); - fullname = talloc_asprintf(mem_ctx, "%s%s%s", reg_key_get_path(parent), strlen(reg_key_get_path(parent))?"\\":"", name); + fullname = talloc_asprintf(mem_ctx, "%s%s%s", + reg_key_get_path(parent), + strlen(reg_key_get_path(parent))?"\\":"", + name); - error = parent->handle->functions->open_key(parent->handle, parent->hive, fullname, result); + error = parent->handle->functions->open_key(parent->handle, + parent->hive, fullname, result); if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); @@ -205,7 +211,8 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) } (*result)->handle = parent->handle; - (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", reg_key_get_path_abs(parent), (*result)->name); + (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", + reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; talloc_steal(mem_ctx, (*result)->mem_ctx, fullname); @@ -225,7 +232,8 @@ WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) } else if(key->handle->functions->fetch_values) { if(!key->cache_values) - key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); + key->handle->functions->fetch_values(key, + &key->cache_values_count, &key->cache_values); if(idx < key->cache_values_count && idx >= 0) { *val = reg_val_dup(key->cache_values[idx]); @@ -251,7 +259,8 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) if(key->handle->functions->fetch_subkeys) { if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + key->handle->functions->fetch_subkeys(key, + &key->cache_subkeys_count, &key->cache_subkeys); *count = key->cache_subkeys_count; return WERR_OK; @@ -304,7 +313,8 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) if(!NT_STATUS_IS_OK(status)) return status; } else if(key->handle->functions->fetch_subkeys) { if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys); + key->handle->functions->fetch_subkeys(key, + &key->cache_subkeys_count, &key->cache_subkeys); if(idx < key->cache_subkeys_count) { *subkey = reg_key_dup(key->cache_subkeys[idx]); @@ -315,7 +325,8 @@ WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) return WERR_NOT_SUPPORTED; } - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); + (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", + reg_key_get_path_abs(key), (*subkey)->name); (*subkey)->handle = key->handle; (*subkey)->hive = key->hive; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 0633c94616..408ce52e44 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -21,24 +21,37 @@ #include "includes.h" #include "lib/registry/common/registry.h" -static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) +static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { - char *ret = talloc_strdup(mem_ctx, "(dn="); - char *begin = (char *)path; - char *end = NULL; - - while(begin) { - end = strchr(begin, '\\'); - if(end)end = '\0'; - if(end - begin != 0) ret = talloc_asprintf_append(mem_ctx, ret, "key=%s,", begin); + char *ret = talloc_strdup(mem_ctx, ""); + char *mypath = strdup(path); + char *end = mypath, *begin; + + if(add) + ret = talloc_asprintf_append(mem_ctx, ret, "%s", add); + + while(end) { + char *keyname; + begin = strrchr(end, '\\'); + + if(begin) keyname = begin + 1; + else keyname = mypath; + + if(strlen(keyname)) + ret = talloc_asprintf_append(mem_ctx, ret, "key=%s,", keyname); - if(end) { - *end = '\\'; - begin = end+1; - } else begin = NULL; + if(begin) { + begin[0] = '\0'; + end = begin-1; + } else { + end = NULL; + } } - ret[strlen(ret)-1] = ')'; + SAFE_FREE(mypath); + + ret[strlen(ret)-1] = '\0'; + printf("Doing search for : %s\n", ret); return ret; } @@ -50,8 +63,12 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path) static WERROR ldb_open_registry(REG_HANDLE *handle, const char *location, const char *credentials) { struct ldb_context *c; + + if (!location) return WERR_INVALID_PARAM; c = ldb_connect(location, 0, NULL); + ldb_set_debug_stderr(c); + if(!c) return WERR_FOOBAR; handle->backend_data = c; @@ -69,18 +86,36 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) { struct ldb_context *c = k->handle->backend_data; char *path; + int ret, i, j; struct ldb_message **msg; - char *ldap_path; TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); REG_KEY *key = NULL; - ldap_path = reg_path_to_ldb(mem_ctx, reg_key_get_path(k)); - - if(ldb_search(c, NULL, LDB_SCOPE_ONELEVEL, ldap_path, NULL,&msg) > 0) { - key = reg_key_new_abs(reg_key_get_path(k), k->handle, ldap_path); - talloc_steal(mem_ctx, key->mem_ctx, ldap_path); - /* FIXME */ + + ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); + + if(ret < 0) { + DEBUG(0, ("Error getting subkeys for '%s': %s\n", k->backend_data, ldb_errstring(c))); + return WERR_FOOBAR; } + *subkeys = talloc_array_p(k->mem_ctx, REG_KEY *, ret); + j = 0; + for(i = 0; i < ret; i++) { + struct ldb_message_element *el; + char *name; + el = ldb_msg_find_element(msg[i], "key"); + + name = el->values[0].data; + + /* Dirty hack to circumvent ldb_tdb bug */ + if(k->backend_data && !strcmp(msg[i]->dn, (char *)k->backend_data)) continue; + + (*subkeys)[j] = reg_key_new_rel(name, k, NULL); + (*subkeys)[j]->backend_data = talloc_strdup((*subkeys)[j]->mem_ctx, msg[i]->dn); + j++; + } + *count = j; + ldb_search_free(c, msg); talloc_destroy(mem_ctx); return WERR_OK; @@ -88,8 +123,10 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) { - /* FIXME */ - return WERR_FOOBAR; + if(num != 0) return WERR_NO_MORE_ITEMS; + *key = reg_key_new_abs("", h, NULL); +// (*key)->backend_data = talloc_strdup((*key)->mem_ctx, ""); + return WERR_OK; } static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) @@ -97,16 +134,26 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k struct ldb_context *c = h->backend_data; char *path; struct ldb_message **msg; - char *ldap_path; + char *ldap_path, *new_ldap_path; + int ret; TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); - ldap_path = reg_path_to_ldb(mem_ctx, name); + if(num != 0) return WERR_NO_MORE_ITEMS; + ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); - if(ldb_search(c, NULL, LDB_SCOPE_BASE, ldap_path, NULL,&msg) > 0) { - *key = reg_key_new_abs(name, h, ldap_path); - talloc_steal(mem_ctx, (*key)->mem_ctx, ldap_path); - /* FIXME */ + ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "*", NULL,&msg); + + if(ret == 0) { + return WERR_NO_MORE_ITEMS; + } else if(ret < 0) { + DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c))); + return WERR_FOOBAR; } + *key = reg_key_new_abs(name, h, ldap_path); + talloc_steal(mem_ctx, (*key)->mem_ctx, ldap_path); + printf("Got something!\n"); + /* FIXME */ + ldb_search_free(c, msg); talloc_destroy(mem_ctx); @@ -116,6 +163,7 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k static struct registry_ops reg_backend_ldb = { .name = "ldb", .open_registry = ldb_open_registry, + .get_hive = ldb_get_hive, .close_registry = ldb_close_registry, .open_key = ldb_open_key, .fetch_subkeys = ldb_fetch_subkeys, -- cgit From 8dcb4aa084457e6d7a68467dceebc11abe4464bd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 12 Jun 2004 17:51:22 +0000 Subject: r1119: Saner keyboard shortcuts (This used to be commit 971941acc7e75da89b1bdc612fd476a7f6124dcb) --- source4/lib/registry/tools/gregedit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c index d878461bff..f9e1786d71 100644 --- a/source4/lib/registry/tools/gregedit.c +++ b/source4/lib/registry/tools/gregedit.c @@ -451,7 +451,7 @@ static GtkWidget* create_mainwin (void) gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_file), menu_file_menu); if(reg_has_backend("nt4")) { - open_nt4 = gtk_image_menu_item_new_with_mnemonic("_Open NT4 file"); + open_nt4 = gtk_image_menu_item_new_with_mnemonic("Open _NT4 file"); gtk_widget_show (open_nt4); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); @@ -461,7 +461,7 @@ static GtkWidget* create_mainwin (void) } if(reg_has_backend("w95")) { - open_w95 = gtk_image_menu_item_new_with_mnemonic("_Open Win9x file"); + open_w95 = gtk_image_menu_item_new_with_mnemonic("Open Win_9x file"); gtk_widget_show (open_w95); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); @@ -471,7 +471,7 @@ static GtkWidget* create_mainwin (void) } if(reg_has_backend("gconf")) { - open_gconf = gtk_image_menu_item_new_with_mnemonic ("_Open GConf"); + open_gconf = gtk_image_menu_item_new_with_mnemonic ("Open _GConf"); gtk_widget_show (open_gconf); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); @@ -481,7 +481,7 @@ static GtkWidget* create_mainwin (void) } if(reg_has_backend("rpc")) { - open_remote = gtk_menu_item_new_with_mnemonic ("_Open Remote"); + open_remote = gtk_menu_item_new_with_mnemonic ("Open _Remote"); gtk_widget_show (open_remote); gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); -- cgit From b1268fc4455f61ee49412fc256106cd34e98ce7c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 13 Jun 2004 23:50:55 +0000 Subject: r1123: Make all lp_ string functions return 'const char *'. Fix other 'const' warnings in the torture code. Andrew Bartlett (This used to be commit 5d39d7497f189da15d659b3f83b7314026040a15) --- source4/lib/debug.c | 2 +- source4/lib/util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/debug.c b/source4/lib/debug.c index c9247f380f..4f6ba125d3 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -68,7 +68,7 @@ void do_debug(const char *format, ...) */ void reopen_logs(void) { - char *logfile = lp_logfile(); + const char *logfile = lp_logfile(); char *fname = NULL; int old_fd = state.fd; diff --git a/source4/lib/util.c b/source4/lib/util.c index 16f5e7a888..0dbc2a125d 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -568,7 +568,7 @@ gid_t nametogid(const char *name) void smb_panic(const char *why) { - char *cmd = lp_panic_action(); + const char *cmd = lp_panic_action(); int result; if (cmd && *cmd) { -- cgit From 7de7dafcc4472f7aaecd04320811a21b0e42d444 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 14 Jun 2004 07:24:13 +0000 Subject: r1130: remove some pointless debug messages (This used to be commit 260be3fbef5a198621274cfe0c0250f292d819ca) --- source4/lib/iconv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index f75621af09..cb861a7bb8 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -70,7 +70,6 @@ static NTSTATUS charset_register_backend(void *_funcs) struct charset_functions *funcs = (struct charset_functions *)_funcs; struct charset_functions *c = charsets; - DEBUG(5, ("Attempting to register new charset %s\n", funcs->name)); /* Check whether we already have this charset... */ while(c) { if(!strcasecmp(c->name, funcs->name)){ @@ -81,7 +80,6 @@ static NTSTATUS charset_register_backend(void *_funcs) } funcs->next = funcs->prev = NULL; - DEBUG(5, ("Registered charset %s\n", funcs->name)); DLIST_ADD(charsets, funcs); return NT_STATUS_OK; } -- cgit From 0b817ae8511983825ef63d2989e937f03beb39cf Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 14 Jun 2004 13:56:52 +0000 Subject: r1147: Support enumerating values (This used to be commit 3af8419fa4053a3b2887e91b4bda5c93327efad4) --- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 48 ++++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 408ce52e44..9dfd3329e0 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -52,7 +52,6 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * ret[strlen(ret)-1] = '\0'; - printf("Doing search for : %s\n", ret); return ret; } @@ -82,13 +81,17 @@ static WERROR ldb_close_registry(REG_HANDLE *h) return WERR_OK; } +static WERROR ldb_add_key(REG_KEY *p, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **new) +{ + return WERR_NOT_SUPPORTED; +} + static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) { struct ldb_context *c = k->handle->backend_data; char *path; int ret, i, j; struct ldb_message **msg; - TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); REG_KEY *key = NULL; ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); @@ -117,7 +120,43 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) *count = j; ldb_search_free(c, msg); - talloc_destroy(mem_ctx); + return WERR_OK; +} + +static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +{ + struct ldb_context *c = k->handle->backend_data; + char *path; + int ret, i, j; + struct ldb_message **msg; + REG_KEY *key = NULL; + + ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); + + if(ret < 0) { + DEBUG(0, ("Error getting values for '%s': %s\n", k->backend_data, ldb_errstring(c))); + return WERR_FOOBAR; + } + + *values = talloc_array_p(k->mem_ctx, REG_VAL *, ret); + j = 0; + for(i = 0; i < ret; i++) { + struct ldb_message_element *el; + char *name; + el = ldb_msg_find_element(msg[i], "key"); + + name = el->values[0].data; + + /* Dirty hack to circumvent ldb_tdb bug */ + if(k->backend_data && !strcmp(msg[i]->dn, (char *)k->backend_data)) continue; + + (*values)[j] = reg_val_new(k, NULL); + (*values)[j]->backend_data = talloc_strdup((*values)[j]->mem_ctx, msg[i]->dn); + j++; + } + *count = j; + + ldb_search_free(c, msg); return WERR_OK; } @@ -125,7 +164,6 @@ static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) { if(num != 0) return WERR_NO_MORE_ITEMS; *key = reg_key_new_abs("", h, NULL); -// (*key)->backend_data = talloc_strdup((*key)->mem_ctx, ""); return WERR_OK; } @@ -167,6 +205,8 @@ static struct registry_ops reg_backend_ldb = { .close_registry = ldb_close_registry, .open_key = ldb_open_key, .fetch_subkeys = ldb_fetch_subkeys, + .fetch_values = ldb_fetch_values, + .add_key = ldb_add_key, }; NTSTATUS registry_ldb_init(void) -- cgit From e8524d731a91d52f8cf426d96f71239babbd1dd7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Jun 2004 04:41:32 +0000 Subject: r1163: Add const. Andrew Bartlett (This used to be commit 4a445fce7fcc09049b97bcde61fa5ed1a945757d) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 0dbc2a125d..6834cd53fc 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -89,7 +89,7 @@ time_t file_modtime(const char *fname) Check if a directory exists. ********************************************************************/ -BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st) +BOOL directory_exist(const char *dname,SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st2; BOOL ret; -- cgit From aba5a2df325cf1963ab716f90b630600cd8ba5cf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Jun 2004 04:22:49 +0000 Subject: r1196: Remove unused pstring/fstring functions. Andrew Bartlett (This used to be commit 4f06bf4ab8cc61aec730f84766306119eb976c57) --- source4/lib/charcnv.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index c3ef45d038..b84814b41c 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -368,16 +368,6 @@ ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); } -ssize_t push_ascii_fstring(void *dest, const char *src) -{ - return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE); -} - -ssize_t push_ascii_pstring(void *dest, const char *src) -{ - return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); -} - ssize_t push_pstring(void *dest, const char *src) { return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); @@ -424,16 +414,6 @@ ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, return src_len; } -ssize_t pull_ascii_pstring(char *dest, const void *src) -{ - return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE); -} - -ssize_t pull_ascii_fstring(char *dest, const void *src) -{ - return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE); -} - /** * Copy a string from a char* src to a unicode destination. * @@ -550,16 +530,6 @@ ssize_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len); } -ssize_t push_utf8_fstring(void *dest, const char *src) -{ - return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE); -} - -ssize_t push_utf8_pstring(void *dest, const char *src) -{ - return push_utf8(dest, src, sizeof(pstring), STR_TERMINATE); -} - /** * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc * @@ -643,11 +613,6 @@ ssize_t pull_ucs2_pstring(char *dest, const void *src) return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE); } -ssize_t pull_ucs2_fstring(char *dest, const void *src) -{ - return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE); -} - /** * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc * @@ -713,16 +678,6 @@ ssize_t pull_utf8(char *dest, const void *src, size_t dest_len, size_t src_len, return src_len; } -ssize_t pull_utf8_pstring(char *dest, const void *src) -{ - return pull_utf8(dest, src, sizeof(pstring), -1, STR_TERMINATE); -} - -ssize_t pull_utf8_fstring(char *dest, const void *src) -{ - return pull_utf8(dest, src, sizeof(fstring), -1, STR_TERMINATE); -} - /** * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc * -- cgit From bf598954f75bfd924b9aa22649975b372c74a49e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Jun 2004 08:15:41 +0000 Subject: r1198: Merge the Samba 3.0 ntlm_auth, including the kerberos and SPENGO parts. I have moved the SPNEGO and Kerberos code into libcli/auth, and intend to refactor them into the same format as NTLMSSP. Andrew Bartlett (This used to be commit 58da78a7460d5d0a4abee7d7b84799c228e6bc0b) --- source4/lib/basic.mk | 3 ++- source4/lib/util_str.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 754458fec1..ccd0935407 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -50,7 +50,8 @@ ADD_OBJ_FILES = \ lib/crypto/md5.o \ lib/crypto/hmacmd5.o \ lib/crypto/md4.o \ - lib/tdb_helper.o + lib/tdb_helper.o \ + lib/server_mutex.o REQUIRED_SUBSYSTEMS = \ LIBTDB CHARSET # End SUBSYSTEM LIBBASIC diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index bb94d3fce6..70011cf80d 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1252,6 +1252,22 @@ DATA_BLOB strhex_to_data_blob(const char *strhex) return ret_blob; } +/** + * Routine to print a buffer as HEX digits, into an allocated string. + */ + +void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) +{ + int i; + char *hex_buffer; + + *out_hex_buffer = smb_xmalloc((len*2)+1); + hex_buffer = *out_hex_buffer; + + for (i = 0; i < len; i++) + slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); +} + /** Unescape a URL encoded string, in place. -- cgit From 8cb41badd4349b7d9d78ff8e25143929522e4749 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jun 2004 00:54:17 +0000 Subject: r1199: Make talloc_asprintf_append() work on a NULL source string as if it were just a alloc_asprintf(). (makes it easier to use in a loop) Andrew Bartlett (This used to be commit 5816d09c47252d2ee8732722b3cc44ea865b8fcc) --- source4/lib/talloc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index f61ef6d906..9f873a2d6b 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -464,7 +464,11 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) VA_COPY(ap2, ap); - s_len = strlen(s); + if (s) { + s_len = strlen(s); + } else { + s = 0; + } len = vsnprintf(NULL, 0, fmt, ap2); s = talloc_realloc(t, s, s_len + len+1); -- cgit From 121e074232439817bd2467d847c93885b40e13b7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jun 2004 15:22:41 +0000 Subject: r1228: use int64_t instead of long long (jra: please use: void, char int, uint_t, [u]int<8|16|32|64>_t types in new code) metze (This used to be commit 626bb153c45405f93a96bc5019241af506fac163) --- source4/lib/time.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 9d906af2fa..bd8d7ddb30 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -410,9 +410,9 @@ NTTIME nttime_from_string(const char *s) return strtoull(s, NULL, 0); } -long long usec_time_diff(struct timeval *larget, struct timeval *smallt) +int64_t usec_time_diff(struct timeval *larget, struct timeval *smallt) { - long long sec_diff = larget->tv_sec - smallt->tv_sec; - return (sec_diff * 1000000) + (long long)(larget->tv_usec - smallt->tv_usec); + int64_t sec_diff = larget->tv_sec - smallt->tv_sec; + return (sec_diff * 1000000) + (int64_t)(larget->tv_usec - smallt->tv_usec); } -- cgit From 37fcf2236433bc5e74f19d2afac3d1d0055dcd01 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 27 Jun 2004 11:06:10 +0000 Subject: r1268: varient -> variant (This used to be commit de5984c95602ca67e8ac3139c3aa4330b74266e0) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index d97444a6e8..7e8cd8b289 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -484,7 +484,7 @@ int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) /* search the database with a LDAP-like expression. - this is the "full search" non-indexed varient + this is the "full search" non-indexed variant */ static int ltdb_search_full(struct ldb_context *ldb, const char *base, -- cgit From d4ae6ae74d712b74800e360590052d318d2fd101 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Jun 2004 07:41:15 +0000 Subject: r1277: rename struct server_context to smbsrv_ontext because I need server_context fot the generic server infastructure metze (This used to be commit 0712f9f30797e65362c99423c0cf158a2f539000) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 6834cd53fc..7fb51710a0 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -640,7 +640,7 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) Set the remote_arch string based on an enum. This is used in places where we desperately need to distinguish client type. ********************************************************************/ -void set_remote_arch(struct server_context *smb, enum remote_arch_types type) +void set_remote_arch(struct smbsrv_context *smb, enum remote_arch_types type) { const char *arch; -- cgit From 4ddb2d347d86818a13d71d0eb2f0f8983c2cc41f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Jun 2004 08:27:36 +0000 Subject: r1279: rename struct tcon_context to smbsrv_tcon metze (This used to be commit 99473fab4b1ff87a795f3c08f4c521d9beb504c0) --- source4/lib/substitute.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c index 4e4f0bc040..7d3997ecd7 100644 --- a/source4/lib/substitute.c +++ b/source4/lib/substitute.c @@ -165,16 +165,16 @@ char *alloc_sub_advanced(int snum, const char *user, Do some standard substitutions in a string. ****************************************************************************/ -void standard_sub_conn(struct tcon_context *conn, char *str, size_t len) +void standard_sub_tcon(struct smbsrv_tcon *tcon, char *str, size_t len) { } -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, struct tcon_context *conn, char *str) +char *talloc_sub_tcon(TALLOC_CTX *mem_ctx, struct smbsrv_tcon *tcon, char *str) { return talloc_strdup(mem_ctx, str); } -char *alloc_sub_conn(struct tcon_context *conn, char *str) +char *alloc_sub_tcon(struct smbsrv_tcon *tcon, char *str) { return strdup(str); } -- cgit From 118f3edd27f5adacc1da636ed05b33f04999584f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Jun 2004 07:40:14 +0000 Subject: r1291: rename struct smbsrv_context to smbsrv_connection because this is the connection state per transport layer (tcp) connection I also moved the substructs directly into smbsrv_connection, because they don't need a struct name and we should allway pass the complete smbsrv_connection struct into functions metze (This used to be commit 60f823f201fcedf5473008e8453a6351e73a92c7) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 7fb51710a0..ee637aeaad 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -640,7 +640,7 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) Set the remote_arch string based on an enum. This is used in places where we desperately need to distinguish client type. ********************************************************************/ -void set_remote_arch(struct smbsrv_context *smb, enum remote_arch_types type) +void set_remote_arch(struct smbsrv_connection *smb, enum remote_arch_types type) { const char *arch; -- cgit From fe0706d5d5813edc29c909c4f74c593fb5717190 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 29 Jun 2004 09:20:18 +0000 Subject: r1292: Add const to the subsystem/module registration code. Add some 'multi init' code, until we get a better set of infrustructure. Andrew Bartlett (This used to be commit 982422b2d286335378531ae9523e74192340af3c) --- source4/lib/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index 1fcb57fac1..c724d872ee 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -153,7 +153,7 @@ NTSTATUS register_subsystem(const char *name, register_backend_function callback return NT_STATUS_OK; } -NTSTATUS register_backend(const char *subsystem, void *args) +NTSTATUS register_backend(const char *subsystem, const void *args) { /* Find the specified subsystem */ struct subsystem *s = subsystems; -- cgit From 1cec0de9273d10847ffb513679f6643a7a4cc648 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Jun 2004 19:46:28 +0000 Subject: r1308: move smb_panic() to lib/fault.c merge the backtrace stuff from 3.0 metze (This used to be commit 4daf1bafc71cc8f13188aeb85d81aa7513d57d95) --- source4/lib/fault.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/util.c | 24 ------------ 2 files changed, 105 insertions(+), 24 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/fault.c b/source4/lib/fault.c index 47a43bca84..0ce003a2b0 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -29,6 +29,105 @@ static struct { } fault_handlers; +#ifdef HAVE_BACKTRACE +#include +#define BACKTRACE_STACK_SIZE 64 +#elif HAVE_LIBEXC_H +#include +#endif + +static void call_backtrace(void) +{ +#ifdef HAVE_BACKTRACE +#define BACKTRACE_STACK_SIZE 64 + void *backtrace_stack[BACKTRACE_STACK_SIZE]; + size_t backtrace_size; + char **backtrace_strings; + + /* get the backtrace (stack frames) */ + backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); + backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); + + DEBUG(0, ("BACKTRACE: %lu stack frames:\n", + (unsigned long)backtrace_size)); + + if (backtrace_strings) { + int i; + + for (i = 0; i < backtrace_size; i++) + DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i])); + + /* Leak the backtrace_strings, rather than risk what free() might do */ + } + +#elif HAVE_LIBEXC + +#define NAMESIZE 32 /* Arbitrary */ + + /* The IRIX libexc library provides an API for unwinding the stack. See + * libexc(3) for details. Apparantly trace_back_stack leaks memory, but + * since we are about to abort anyway, it hardly matters. + * + * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this + * will fail with a nasty message upon failing to open the /proc entry. + */ + { + uint64_t addrs[BACKTRACE_STACK_SIZE]; + char * names[BACKTRACE_STACK_SIZE]; + char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE]; + + int i; + int levels; + + ZERO_ARRAY(addrs); + ZERO_ARRAY(names); + ZERO_ARRAY(namebuf); + + for (i = 0; i < BACKTRACE_STACK_SIZE; i++) { + names[i] = namebuf + (i * NAMESIZE); + } + + levels = trace_back_stack(0, addrs, names, + BACKTRACE_STACK_SIZE, NAMESIZE); + + DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels)); + for (i = 0; i < levels; i++) { + DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i])); + } + } +#undef NAMESIZE +#endif +} + +/******************************************************************* + Something really nasty happened - panic ! +********************************************************************/ +void smb_panic(const char *why) +{ + const char *cmd = lp_panic_action(); + int result; + + if (cmd && *cmd) { + DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd)); + result = system(cmd); + + if (result == -1) + DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", + strerror(errno))); + else + DEBUG(0, ("smb_panic(): action returned status %d\n", + WEXITSTATUS(result))); + } + DEBUG(0,("PANIC: %s\n", why)); + + call_backtrace(); + +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); +#endif + abort(); +} + /******************************************************************* report a fault ********************************************************************/ @@ -52,6 +151,9 @@ static void fault_report(int sig) #endif #ifdef SIGBUS CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); +#endif +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); #endif return; /* this should cause a core dump */ } @@ -84,6 +186,9 @@ void fault_setup(void (*fn)(void *)) #ifdef SIGBUS CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); #endif +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST sig_fault); +#endif } /* diff --git a/source4/lib/util.c b/source4/lib/util.c index ee637aeaad..3b23543bfc 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -562,30 +562,6 @@ gid_t nametogid(const char *name) return (gid_t)-1; } -/******************************************************************* - Something really nasty happened - panic ! -********************************************************************/ - -void smb_panic(const char *why) -{ - const char *cmd = lp_panic_action(); - int result; - - if (cmd && *cmd) { - DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd)); - result = system(cmd); - - if (result == -1) - DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", - strerror(errno))); - else - DEBUG(0, ("smb_panic(): action returned status %d\n", - WEXITSTATUS(result))); - } - DEBUG(0,("PANIC: %s\n", why)); - abort(); -} - /**************************************************************************** Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping is dealt with in posix.c -- cgit From 34ca729f733d9d22fc789a5fce6c448b03c96545 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 7 Jul 2004 01:02:54 +0000 Subject: r1374: Fix signed/unsigned warnings (actually found by g++) after unsigned int changes in r1018. (This used to be commit 45b4016530fc0bfa13146f73a503866b5dbed517) --- source4/lib/ldb/common/ldb_ldif.c | 8 ++++---- source4/lib/ldb/common/ldb_msg.c | 6 +++--- source4/lib/ldb/common/ldb_parse.c | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 5 +++-- source4/lib/ldb/ldb_tdb/ldb_index.c | 38 +++++++++++++++++++++--------------- source4/lib/ldb/ldb_tdb/ldb_match.c | 9 +++++---- source4/lib/ldb/ldb_tdb/ldb_pack.c | 6 +++--- source4/lib/ldb/ldb_tdb/ldb_search.c | 8 ++++---- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 18 +++++++++-------- source4/lib/ldb/tools/ldbedit.c | 2 +- 10 files changed, 56 insertions(+), 46 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index b08c616a05..8c912f76d4 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -122,7 +122,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) */ int ldb_should_b64_encode(const struct ldb_val *val) { - int i; + unsigned int i; uint8_t *p = val->data; if (val->length == 0 || p[0] == ' ' || p[0] == ':') { @@ -146,7 +146,7 @@ int ldb_should_b64_encode(const struct ldb_val *val) static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data, const char *buf, size_t length, int start_pos) { - int i; + unsigned int i; int total=0, ret; for (i=0;imsg; - int i; + unsigned int i; for (i=0;inum_elements;i++) { if (msg->elements[i].name) ldb_free(ldb, msg->elements[i].name); if (msg->elements[i].values) ldb_free(ldb, msg->elements[i].values); diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 0d5b47f920..170a7ae5e4 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -41,7 +41,7 @@ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, const char *attr_name) { - int i; + unsigned int i; for (i=0;inum_elements;i++) { if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { return &msg->elements[i]; @@ -74,7 +74,7 @@ int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2) struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, struct ldb_val *val) { - int i; + unsigned int i; for (i=0;inum_values;i++) { if (ldb_val_equal_exact(val, &el->values[i])) { return &el->values[i]; @@ -185,7 +185,7 @@ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, int ldb_msg_element_compare(struct ldb_message_element *el1, struct ldb_message_element *el2) { - int i; + unsigned int i; if (el1->num_values != el2->num_values) { return el1->num_values - el2->num_values; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index d61d65548c..b037284a24 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -344,7 +344,7 @@ struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s) */ void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree) { - int i; + unsigned int i; switch (tree->operation) { case LDB_OP_SIMPLE: diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index d96bfd62d3..06d3884c16 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -117,7 +117,7 @@ static int lldb_delete(struct ldb_context *ldb, const char *dn) */ static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) { - int i, j; + unsigned int i, j; ldb_free(ldb, msg->dn); for (i=0;inum_elements;i++) { ldb_free(ldb, msg->elements[i].name); @@ -333,7 +333,8 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, const struct ldb_message *msg, int use_flags) { LDAPMod **mods; - int i, j, num_mods = 0; + unsigned int i, j; + int num_mods = 0; /* allocate maximum number of elements needed */ mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1); diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index b4ca666287..8a26e2d197 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -46,7 +46,7 @@ struct dn_list { */ static void dn_list_free(struct ldb_context *ldb, struct dn_list *list) { - int i; + unsigned int i; for (i=0;icount;i++) { ldb_free(ldb, list->dn[i]); } @@ -80,7 +80,7 @@ static char *ldb_dn_key(struct ldb_context *ldb, static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, int *v_idx, const char *key) { - int i, j; + unsigned int i, j; for (i=0;inum_elements;i++) { if (ldb_attr_cmp(msg->elements[i].name, key) == 0) { const struct ldb_message_element *el = @@ -113,7 +113,8 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, struct dn_list *list) { char *dn = NULL; - int ret, i, j; + int ret; + unsigned int i, j; struct ldb_message msg; list->count = 0; @@ -186,7 +187,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, struct dn_list *list) { struct ltdb_private *ltdb = ldb->private_data; - int i; + unsigned int i; int ret; const char *target = tree->u.simple.value.data; static int list_union(struct ldb_context *, @@ -200,7 +201,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, for (i=0;icache.subclasses.num_elements;i++) { struct ldb_message_element *el = <db->cache.subclasses.elements[i]; if (ldb_attr_cmp(el->name, target) == 0) { - int j; + unsigned int j; for (j=0;jnum_values;j++) { struct ldb_parse_tree tree2; struct dn_list list2; @@ -252,7 +253,7 @@ static int list_intersect(struct ldb_context *ldb, struct dn_list *list, const struct dn_list *list2) { struct dn_list list3; - int i; + unsigned int i; if (list->count == 0 || list2->count == 0) { /* 0 & X == 0 */ @@ -293,7 +294,7 @@ static int list_intersect(struct ldb_context *ldb, static int list_union(struct ldb_context *ldb, struct dn_list *list, const struct dn_list *list2) { - int i; + unsigned int i; char **d; unsigned int count = list->count; @@ -343,7 +344,8 @@ static int ltdb_index_dn_or(struct ldb_context *ldb, const struct ldb_message *index_list, struct dn_list *list) { - int ret, i; + unsigned int i; + int ret; ret = -1; list->dn = NULL; @@ -416,7 +418,8 @@ static int ltdb_index_dn_and(struct ldb_context *ldb, const struct ldb_message *index_list, struct dn_list *list) { - int ret, i; + unsigned int i; + int ret; ret = -1; list->dn = NULL; @@ -499,8 +502,7 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree const struct dn_list *dn_list, const char * const attrs[], struct ldb_message ***res) { - int i; - unsigned int count = 0; + unsigned int count = 0, i; for (i=0;icount;i++) { struct ldb_message msg; @@ -608,7 +610,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, char *dn) { struct ldb_val *v2; - int i; + unsigned int i; /* for multi-valued attributes we can end up with repeats */ for (i=0;ielements[idx].num_values;i++) { @@ -640,7 +642,8 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, { struct ldb_message msg; char *dn_key; - int ret, i, added=0, added_dn=0; + int ret, added=0, added_dn=0; + unsigned int i; dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); if (!dn_key) { @@ -704,7 +707,8 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) { struct ltdb_private *ltdb = ldb->private_data; - int ret, i, j; + int ret; + unsigned int i, j; if (ltdb->cache.indexlist.num_elements == 0) { /* no indexed fields */ @@ -737,7 +741,8 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, { struct ldb_message msg; char *dn_key; - int ret, i, j; + int ret, i; + unsigned int j; dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); if (!dn_key) { @@ -794,7 +799,8 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) { struct ltdb_private *ltdb = ldb->private_data; - int ret, i, j; + int ret; + unsigned int i, j; /* find the list of indexed fields */ if (ltdb->cache.indexlist.num_elements == 0) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 05a2826d4d..963048915a 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -140,7 +140,7 @@ static int ldb_val_equal_objectclass(struct ldb_context *ldb, const struct ldb_val *v1, const struct ldb_val *v2) { struct ltdb_private *ltdb = ldb->private_data; - int i; + unsigned int i; if (ldb_val_equal_case_insensitive(v1, v2) == 1) { return 1; @@ -149,7 +149,7 @@ static int ldb_val_equal_objectclass(struct ldb_context *ldb, for (i=0;icache.subclasses.num_elements;i++) { struct ldb_message_element *el = <db->cache.subclasses.elements[i]; if (ldb_attr_cmp(el->name, v2->data) == 0) { - int j; + unsigned int j; for (j=0;jnum_values;j++) { if (ldb_val_equal_objectclass(ldb, v1, &el->values[j])) { return 1; @@ -259,7 +259,7 @@ static int match_leaf(struct ldb_context *ldb, const char *base, enum ldb_scope scope) { - int i, j; + unsigned int i, j; if (!scope_match(msg->dn, base, scope)) { return 0; @@ -304,7 +304,8 @@ int ldb_message_match(struct ldb_context *ldb, const char *base, enum ldb_scope scope) { - int v, i; + unsigned int i; + int v; switch (tree->operation) { case LDB_OP_SIMPLE: diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index fcbc9bd56d..ad856d2faf 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -69,7 +69,7 @@ int ltdb_pack_data(struct ldb_context *ldb, const struct ldb_message *message, struct TDB_DATA *data) { - int i, j, real_elements=0; + unsigned int i, j, real_elements=0; size_t size; char *p; size_t len; @@ -141,7 +141,7 @@ int ltdb_pack_data(struct ldb_context *ldb, void ltdb_unpack_data_free(struct ldb_context *ldb, struct ldb_message *message) { - int i; + unsigned int i; for (i=0;inum_elements;i++) { if (message->elements[i].values) ldb_free(ldb, message->elements[i].values); @@ -166,7 +166,7 @@ int ltdb_unpack_data(struct ldb_context *ldb, { char *p; unsigned int remaining; - int i, j; + unsigned int i, j; unsigned format; size_t len; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 7e8cd8b289..18d51d1aa4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -41,7 +41,7 @@ */ static void msg_free_all_parts(struct ldb_context *ldb, struct ldb_message *msg) { - int i, j; + unsigned int i, j; ldb_free(ldb, msg->dn); for (i=0;inum_elements;i++) { ldb_free(ldb, msg->elements[i].name); @@ -89,7 +89,7 @@ struct ldb_val ldb_val_dup(struct ldb_context *ldb, static int msg_add_element(struct ldb_context *ldb, struct ldb_message *ret, const struct ldb_message_element *el) { - int i; + unsigned int i; struct ldb_message_element *e2, *elnew; e2 = ldb_realloc_p(ldb, ret->elements, struct ldb_message_element, ret->num_elements+1); @@ -134,7 +134,7 @@ static int msg_add_element(struct ldb_context *ldb, static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret, const struct ldb_message *msg) { - int i; + unsigned int i; for (i=0;inum_elements;i++) { int flags = ltdb_attribute_flags(ldb, msg->elements[i].name); if ((msg->dn[0] != '@') && (flags & LTDB_FLAG_HIDDEN)) { @@ -265,7 +265,7 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, */ void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { - int i; + unsigned int i; ldb_free(ldb, msg->private_data); for (i=0;inum_elements;i++) { ldb_free(ldb, msg->elements[i].values); diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index d60504ff17..b36c53e100 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -324,7 +324,7 @@ failed: */ static int find_element(const struct ldb_message *msg, const char *name) { - int i; + unsigned int i; for (i=0;inum_elements;i++) { if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { return i; @@ -345,7 +345,7 @@ static int msg_add_element(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_message_element *el) { struct ldb_message_element *e2; - int i; + unsigned int i; e2 = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, msg->num_elements+1); @@ -385,7 +385,7 @@ static int msg_add_element(struct ldb_context *ldb, static int msg_delete_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name) { - int i, count=0; + unsigned int i, count=0; struct ldb_message_element *el2; el2 = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); @@ -419,15 +419,16 @@ static int msg_delete_element(struct ldb_context *ldb, const char *name, const struct ldb_val *val) { - int i; + unsigned int i; + int found; struct ldb_message_element *el; - i = find_element(msg, name); - if (i == -1) { + found = find_element(msg, name); + if (found == -1) { return -1; } - el = &msg->elements[i]; + el = &msg->elements[found]; for (i=0;inum_values;i++) { if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) { @@ -459,7 +460,8 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) struct ltdb_private *ltdb = ldb->private_data; TDB_DATA tdb_key, tdb_data; struct ldb_message msg2; - int ret, i, j; + unsigned i, j; + int ret; tdb_key = ltdb_key(ldb, msg->dn); if (!tdb_key.dptr) { diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index f8e0fbb68a..90a6f94750 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -44,7 +44,7 @@ static int modify_record(struct ldb_context *ldb, { struct ldb_message mod; struct ldb_message_element *el; - int i; + unsigned int i; int count = 0; mod.dn = msg1->dn; -- cgit From f929ee3e4eefe370c9cb4672ea4754fc17f5917d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 9 Jul 2004 13:08:00 +0000 Subject: r1422: StrnCaseCmp now needs to be non-static. Andrew Bartlett (This used to be commit 6709c7010df2912eec3dfc086343cb3cb7910459) --- source4/lib/util_str.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 70011cf80d..66acc0ca0e 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -150,7 +150,7 @@ int StrCaseCmp(const char *s, const char *t) Case insensitive string compararison, length limited. **/ -static int StrnCaseCmp(const char *s, const char *t, size_t n) +int StrnCaseCmp(const char *s, const char *t, size_t n) { pstring buf1, buf2; unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); -- cgit From e3fd2d049216f79ced472e2af790ca6ffefba442 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 11 Jul 2004 01:01:48 +0000 Subject: r1432: - Move the various Gtk-specific parts from the registry code into a directory gtk/ - Move common "Samba-Gtk" code into gtk/common/ ("Connect to RPC pipe"-dialog, etc) - Add a new utility 'gwcrontab' that can currently list, delete and add 'atsvc' jobs. It still displays times and dates as integers though, will fix that later. Some screenshots available at: http://samba.org/~jelmer/gwcrontab/ (This used to be commit d321cf20f1f0ff33603b013c26d370669f255868) --- source4/lib/registry/config.m4 | 6 - source4/lib/registry/config.mk | 12 - source4/lib/registry/tools/gregedit.c | 783 ---------------------------------- 3 files changed, 801 deletions(-) delete mode 100644 source4/lib/registry/tools/gregedit.c (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index a1dc9a45bc..4fdde67faf 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -7,7 +7,6 @@ LIBWINREG=libwinregistry AC_CONFIG_FILES(lib/registry/winregistry.pc) -SMB_BINARY_ENABLE(gregedit, NO) SMB_MODULE_DEFAULT(registry_gconf, NOT) SMB_EXT_LIB_FROM_PKGCONFIG(gconf, gconf-2.0) @@ -18,10 +17,6 @@ fi SMB_EXT_LIB_FROM_PKGCONFIG(gtk, [glib-2.0 gtk+-2.0]) -if test t$SMB_EXT_LIB_ENABLE_gtk = tYES; then - SMB_BINARY_ENABLE(gregedit, YES) -fi - SMB_MODULE_MK(registry_nt4, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_w95, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_dir, REGISTRY, STATIC, lib/registry/config.mk) @@ -35,7 +30,6 @@ SMB_BINARY_MK(regdiff, lib/registry/config.mk) SMB_BINARY_MK(regpatch, lib/registry/config.mk) SMB_BINARY_MK(regshell, lib/registry/config.mk) SMB_BINARY_MK(regtree, lib/registry/config.mk) -SMB_BINARY_MK(gregedit, lib/registry/config.mk) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libwinregistry, YES) diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 1d2a1fec6d..8100c798e6 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -118,15 +118,3 @@ REQUIRED_SUBSYSTEMS = \ CONFIG LIBCMDLINE REGISTRY # End BINARY regtree ################################################ - -################################################ -# Start BINARY gregedit -[BINARY::gregedit] -OBJ_FILES= \ - lib/registry/tools/gregedit.o -REQUIRED_LIBRARIES = \ - gtk -REQUIRED_SUBSYSTEMS = \ - CONFIG LIBCMDLINE REGISTRY -# End BINARY gregedit -################################################ diff --git a/source4/lib/registry/tools/gregedit.c b/source4/lib/registry/tools/gregedit.c deleted file mode 100644 index f9e1786d71..0000000000 --- a/source4/lib/registry/tools/gregedit.c +++ /dev/null @@ -1,783 +0,0 @@ -/* - Unix SMB/CIFS implementation. - GTK+ registry frontend - - Copyright (C) Jelmer Vernooij 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include "includes.h" - -GtkWidget *openfilewin; -GtkWidget *savefilewin; -GtkTreeStore *store_keys; -GtkListStore *store_vals; -GtkWidget *tree_keys; -GtkWidget *aboutwin; -GtkWidget *mainwin; - -GtkWidget *rpcwin; -GtkWidget *rpcwin_host; -GtkWidget *rpcwin_user; -GtkWidget *rpcwin_password; -GtkWidget *save; -GtkWidget *save_as; -static GtkWidget* create_openfilewin (void); -static GtkWidget* create_savefilewin (void); -static GtkWidget* create_aboutwin (void); -REG_HANDLE *registry = NULL; - -static void gtk_show_werror(WERROR err) -{ - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(mainwin), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Registry error: %s\n", win_errstr(err)); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} - -static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath *arg2) -{ - GtkTreeIter firstiter, iter, tmpiter; - REG_KEY *k, *sub; - char *name; - GValue value; - WERROR error; - int i; - - gtk_tree_model_iter_children(GTK_TREE_MODEL(store_keys), &firstiter, parent); - - /* See if this row has ever had a name gtk_tree_store_set()'ed to it. - If not, read the directory contents */ - gtk_tree_model_get(GTK_TREE_MODEL(store_keys), &firstiter, 0, &name, -1); - - if(name) return; - - gtk_tree_model_get(GTK_TREE_MODEL(store_keys), parent, 1, &k, -1); - - g_assert(k); - - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(k, i, &sub)); i++) { - int count; - /* Replace the blank child with the first directory entry - You may be tempted to remove the blank child node and then - append a new one. Don't. If you remove the blank child - node GTK gets confused and won't expand the parent row. */ - - if(i == 0) { - iter = firstiter; - } else { - gtk_tree_store_append(store_keys, &iter, parent); - } - gtk_tree_store_set (store_keys, - &iter, - 0, - reg_key_name(sub), - 1, - sub, - -1); - - if(W_ERROR_IS_OK(reg_key_num_subkeys(sub, &count)) && count > 0) - gtk_tree_store_append(store_keys, &tmpiter, &iter); - } - - if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); -} - -static void registry_load_root() -{ - REG_KEY *root; - GtkTreeIter iter, tmpiter; - WERROR error = WERR_OK; - int i = 0; - if(!registry) return; - - gtk_tree_store_clear(store_keys); - - while(1) { - error = reg_get_hive(registry, i, &root); - if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - return; - } - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - return; - } - - /* Add the root */ - gtk_tree_store_append(store_keys, &iter, NULL); - gtk_tree_store_set (store_keys, - &iter, - 0, - reg_key_name(root), - 1, - root, - -1); - - gtk_tree_store_append(store_keys, &tmpiter, &iter); - i++; - } - - gtk_widget_set_sensitive( save, True ); - gtk_widget_set_sensitive( save_as, True ); -} - -static GtkWidget* create_rpcwin (void) -{ - GtkWidget *dialog_vbox1; - GtkWidget *table1; - GtkWidget *label1; - GtkWidget *label2; - GtkWidget *label3; - GtkWidget *dialog_action_area1; - GtkWidget *cancelbutton1; - GtkWidget *okbutton1; - - rpcwin = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (rpcwin), "Connect to remote server"); - - dialog_vbox1 = GTK_DIALOG (rpcwin)->vbox; - gtk_widget_show (dialog_vbox1); - - table1 = gtk_table_new (3, 2, FALSE); - gtk_widget_show (table1); - gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0); - - label1 = gtk_label_new ("Host:"); - gtk_widget_show (label1); - gtk_table_attach (GTK_TABLE (table1), label1, 0, 1, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label1), 0, 0.5); - - label2 = gtk_label_new ("User:"); - gtk_widget_show (label2); - gtk_table_attach (GTK_TABLE (table1), label2, 0, 1, 1, 2, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5); - - label3 = gtk_label_new ("Password:"); - gtk_widget_show (label3); - gtk_table_attach (GTK_TABLE (table1), label3, 0, 1, 2, 3, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5); - - rpcwin_host = gtk_entry_new (); - gtk_widget_show (rpcwin_host); - gtk_table_attach (GTK_TABLE (table1), rpcwin_host, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - - rpcwin_user = gtk_entry_new (); - gtk_widget_show (rpcwin_user); - gtk_table_attach (GTK_TABLE (table1), rpcwin_user, 1, 2, 1, 2, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - - rpcwin_password = gtk_entry_new (); - gtk_widget_show (rpcwin_password); - gtk_table_attach (GTK_TABLE (table1), rpcwin_password, 1, 2, 2, 3, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_entry_set_visibility (GTK_ENTRY (rpcwin_password), FALSE); - - dialog_action_area1 = GTK_DIALOG (rpcwin)->action_area; - gtk_widget_show (dialog_action_area1); - gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END); - - cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel"); - gtk_widget_show (cancelbutton1); - gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), cancelbutton1, GTK_RESPONSE_CANCEL); - GTK_WIDGET_SET_FLAGS (cancelbutton1, GTK_CAN_DEFAULT); - - okbutton1 = gtk_button_new_from_stock ("gtk-ok"); - gtk_widget_show (okbutton1); - gtk_dialog_add_action_widget (GTK_DIALOG (rpcwin), okbutton1, GTK_RESPONSE_OK); - GTK_WIDGET_SET_FLAGS (okbutton1, GTK_CAN_DEFAULT); - - return rpcwin; -} - -static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) -{ - gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); - char *filename; - WERROR error; - switch(result) { - case GTK_RESPONSE_OK: - filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin))); - error = reg_open(user_data, filename, NULL, ®istry); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - break; - } - registry_load_root(); - break; - default: - break; - } - - gtk_widget_destroy(openfilewin); -} - -static void on_open_gconf_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - WERROR error = reg_open("gconf", NULL, NULL, ®istry); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - return; - } - - registry_load_root(); -} - -static void on_open_remote_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - char *location, *credentials; - gint result = gtk_dialog_run(GTK_DIALOG(create_rpcwin())); - WERROR error; - switch(result) { - case GTK_RESPONSE_OK: - asprintf(&location, "ncacn_np:%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_host))); - asprintf(&credentials, "%s%%%s", gtk_entry_get_text(GTK_ENTRY(rpcwin_user)), gtk_entry_get_text(GTK_ENTRY(rpcwin_password))); - error = reg_open("rpc", location, credentials, ®istry); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - break; - } - free(location); free(credentials); - registry_load_root(); - break; - default: - break; - } - - gtk_widget_destroy(rpcwin); -} - - -static void on_save_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - WERROR error = reg_save(registry, NULL); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - } -} - - -static void on_save_as_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - gint result; - WERROR error; - create_savefilewin(); - result = gtk_dialog_run(GTK_DIALOG(savefilewin)); - switch(result) { - case GTK_RESPONSE_OK: - error = reg_save(registry, gtk_file_selection_get_filename(GTK_FILE_SELECTION(savefilewin))); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - } - break; - - default: - break; - - } - gtk_widget_destroy(savefilewin); -} - - -static void on_quit_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - gtk_main_quit(); -} - - -static void on_cut_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - /* FIXME */ -} - - -static void on_copy_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - /* FIXME */ -} - - -static void on_paste_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - /* FIXME */ -} - - -static void on_delete_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - /* FIXME */ -} - - -static void on_about_activate (GtkMenuItem *menuitem, - gpointer user_data) -{ - gtk_dialog_run(GTK_DIALOG(create_aboutwin())); - gtk_widget_destroy(aboutwin); -} - -static void on_key_activate (GtkTreeView *treeview, - GtkTreePath *path, - gpointer user_data) -{ - int i; - REG_KEY *k; - REG_VAL *val; - WERROR error; - GtkTreeIter parent; - - gtk_tree_model_get_iter(GTK_TREE_MODEL(store_keys), &parent, path); - gtk_tree_model_get(GTK_TREE_MODEL(store_keys), &parent, 1, &k, -1); - - g_assert(k); - - gtk_list_store_clear(store_vals); - - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(k, i, &val)); i++) { - GtkTreeIter iter; - gtk_list_store_append(store_vals, &iter); - gtk_list_store_set (store_vals, - &iter, - 0, - reg_val_name(val), - 1, - str_regtype(reg_val_type(val)), - 2, - reg_val_data_string(val), - 3, - val, - -1); - } - - if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(error); -} - -static GtkWidget* create_mainwin (void) -{ - GtkWidget *vbox1; - GtkWidget *menubar; - GtkWidget *menu_file; - GtkWidget *menu_file_menu; - GtkWidget *open_nt4; - GtkWidget *open_w95; - GtkWidget *open_gconf; - GtkWidget *open_remote; - GtkWidget *separatormenuitem1; - GtkWidget *quit; - GtkWidget *men_edit; - GtkWidget *men_edit_menu; - GtkWidget *cut; - GtkWidget *copy; - GtkWidget *paste; - GtkWidget *delete; - GtkCellRenderer *renderer; - GtkTreeViewColumn *curcol; - GtkWidget *help; - GtkWidget *help_menu; - GtkWidget *about; - GtkWidget *hbox1; - GtkWidget *scrolledwindow1; - GtkWidget *scrolledwindow2; - GtkWidget *tree_vals; - GtkWidget *statusbar; - GtkAccelGroup *accel_group; - GtkTreeIter iter, child; - - accel_group = gtk_accel_group_new (); - - mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (mainwin), "Registry editor"); - gtk_window_set_default_size (GTK_WINDOW (mainwin), 642, 562); - - vbox1 = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vbox1); - gtk_container_add (GTK_CONTAINER (mainwin), vbox1); - - menubar = gtk_menu_bar_new (); - gtk_widget_show (menubar); - gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, FALSE, 0); - - menu_file = gtk_menu_item_new_with_mnemonic ("_File"); - gtk_widget_show (menu_file); - gtk_container_add (GTK_CONTAINER (menubar), menu_file); - - menu_file_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_file), menu_file_menu); - - if(reg_has_backend("nt4")) { - open_nt4 = gtk_image_menu_item_new_with_mnemonic("Open _NT4 file"); - gtk_widget_show (open_nt4); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_nt4); - - g_signal_connect ((gpointer) open_nt4, "activate", - G_CALLBACK (on_open_file_activate), - "nt4"); - } - - if(reg_has_backend("w95")) { - open_w95 = gtk_image_menu_item_new_with_mnemonic("Open Win_9x file"); - gtk_widget_show (open_w95); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_w95); - - g_signal_connect ((gpointer) open_w95, "activate", - G_CALLBACK (on_open_file_activate), - "w95"); - } - - if(reg_has_backend("gconf")) { - open_gconf = gtk_image_menu_item_new_with_mnemonic ("Open _GConf"); - gtk_widget_show (open_gconf); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_gconf); - - g_signal_connect ((gpointer) open_gconf, "activate", - G_CALLBACK (on_open_gconf_activate), - NULL); - } - - if(reg_has_backend("rpc")) { - open_remote = gtk_menu_item_new_with_mnemonic ("Open _Remote"); - gtk_widget_show (open_remote); - gtk_container_add (GTK_CONTAINER (menu_file_menu), open_remote); - - g_signal_connect ((gpointer) open_remote, "activate", - G_CALLBACK (on_open_remote_activate), - NULL); - } - - save = gtk_image_menu_item_new_from_stock ("gtk-save", accel_group); - gtk_widget_show (save); - gtk_widget_set_sensitive( save, False ); - gtk_container_add (GTK_CONTAINER (menu_file_menu), save); - - save_as = gtk_image_menu_item_new_from_stock ("gtk-save-as", accel_group); - gtk_widget_show (save_as); - gtk_widget_set_sensitive( save_as, False ); - gtk_container_add (GTK_CONTAINER (menu_file_menu), save_as); - - separatormenuitem1 = gtk_menu_item_new (); - gtk_widget_show (separatormenuitem1); - gtk_container_add (GTK_CONTAINER (menu_file_menu), separatormenuitem1); - gtk_widget_set_sensitive (separatormenuitem1, FALSE); - - quit = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group); - gtk_widget_show (quit); - gtk_container_add (GTK_CONTAINER (menu_file_menu), quit); - - men_edit = gtk_menu_item_new_with_mnemonic ("_Edit"); - gtk_widget_show (men_edit); - gtk_container_add (GTK_CONTAINER (menubar), men_edit); - - men_edit_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (men_edit), men_edit_menu); - - cut = gtk_image_menu_item_new_from_stock ("gtk-cut", accel_group); - gtk_widget_show (cut); - gtk_widget_set_sensitive(cut, False); - gtk_container_add (GTK_CONTAINER (men_edit_menu), cut); - - copy = gtk_image_menu_item_new_from_stock ("gtk-copy", accel_group); - gtk_widget_show (copy); - gtk_widget_set_sensitive(copy, False); - gtk_container_add (GTK_CONTAINER (men_edit_menu), copy); - - paste = gtk_image_menu_item_new_from_stock ("gtk-paste", accel_group); - gtk_widget_show (paste); - gtk_widget_set_sensitive(paste, False); - gtk_container_add (GTK_CONTAINER (men_edit_menu), paste); - - delete = gtk_image_menu_item_new_from_stock ("gtk-delete", accel_group); - gtk_widget_show (delete); - gtk_widget_set_sensitive(delete, False); - gtk_container_add (GTK_CONTAINER (men_edit_menu), delete); - - help = gtk_menu_item_new_with_mnemonic ("_Help"); - gtk_widget_show (help); - gtk_container_add (GTK_CONTAINER (menubar), help); - - help_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), help_menu); - - about = gtk_menu_item_new_with_mnemonic ("_About"); - gtk_widget_show (about); - gtk_container_add (GTK_CONTAINER (help_menu), about); - - hbox1 = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox1); - gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0); - - scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_show (scrolledwindow1); - gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow1, TRUE, TRUE, 0); - - tree_keys = gtk_tree_view_new (); - - /* Column names */ - curcol = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title(curcol, "Name"); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(curcol, renderer, True); - - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_keys), curcol); - - gtk_tree_view_column_add_attribute(curcol, renderer, "text", 0); - gtk_widget_show (tree_keys); - gtk_container_add (GTK_CONTAINER (scrolledwindow1), tree_keys); - store_keys = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - gtk_tree_view_set_model(GTK_TREE_VIEW(tree_keys), GTK_TREE_MODEL(store_keys)); - g_object_unref(store_keys); - - g_signal_connect ((gpointer) tree_keys, "row-activated", - G_CALLBACK (on_key_activate), - NULL); - - g_signal_connect ((gpointer) tree_keys, "row-expanded", - G_CALLBACK (expand_key), - NULL); - - scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_show (scrolledwindow2); - gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow2, TRUE, TRUE, 0); - - tree_vals = gtk_tree_view_new (); - /* Column names */ - - curcol = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title(curcol, "Name"); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(curcol, renderer, True); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); - gtk_tree_view_column_add_attribute(curcol, renderer, "text", 0); - - curcol = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title(curcol, "Type"); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(curcol, renderer, True); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); - gtk_tree_view_column_add_attribute(curcol, renderer, "text", 1); - - curcol = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title(curcol, "Value"); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(curcol, renderer, True); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_vals), curcol); - gtk_tree_view_column_add_attribute(curcol, renderer, "text", 2); - - - gtk_widget_show (tree_vals); - gtk_container_add (GTK_CONTAINER (scrolledwindow2), tree_vals); - - store_vals = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); - gtk_tree_view_set_model(GTK_TREE_VIEW(tree_vals), GTK_TREE_MODEL(store_vals)); - g_object_unref(store_vals); - - statusbar = gtk_statusbar_new (); - gtk_widget_show (statusbar); - gtk_box_pack_start (GTK_BOX (vbox1), statusbar, FALSE, FALSE, 0); - gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (statusbar), FALSE); - - g_signal_connect ((gpointer) save, "activate", - G_CALLBACK (on_save_activate), - NULL); - g_signal_connect ((gpointer) save_as, "activate", - G_CALLBACK (on_save_as_activate), - NULL); - g_signal_connect ((gpointer) quit, "activate", - G_CALLBACK (on_quit_activate), - NULL); - g_signal_connect ((gpointer) cut, "activate", - G_CALLBACK (on_cut_activate), - NULL); - g_signal_connect ((gpointer) copy, "activate", - G_CALLBACK (on_copy_activate), - NULL); - g_signal_connect ((gpointer) paste, "activate", - G_CALLBACK (on_paste_activate), - NULL); - g_signal_connect ((gpointer) delete, "activate", - G_CALLBACK (on_delete_activate), - NULL); - g_signal_connect ((gpointer) about, "activate", - G_CALLBACK (on_about_activate), - NULL); - - gtk_window_add_accel_group (GTK_WINDOW (mainwin), accel_group); - - return mainwin; -} - -static GtkWidget* create_aboutwin (void) -{ - GtkWidget *dialog_vbox1; - GtkWidget *image1; - GtkWidget *label1; - GtkWidget *label2; - GtkWidget *dialog_action_area1; - GtkWidget *closebutton1; - - aboutwin = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (aboutwin), "About GRegEdit"); - gtk_window_set_resizable (GTK_WINDOW (aboutwin), FALSE); - - dialog_vbox1 = GTK_DIALOG (aboutwin)->vbox; - gtk_widget_show (dialog_vbox1); - - /* FIXME: Samba logo ? - image1 = create_pixmap (aboutwin, "samba.png"); - gtk_widget_show (image1); - gtk_box_pack_start (GTK_BOX (dialog_vbox1), image1, FALSE, TRUE, 0); */ - - label1 = gtk_label_new ("GRegEdit 0.1"); - gtk_widget_show (label1); - gtk_box_pack_start (GTK_BOX (dialog_vbox1), label1, FALSE, FALSE, 0); - gtk_label_set_use_markup (GTK_LABEL (label1), TRUE); - - label2 = gtk_label_new_with_mnemonic ("(C) 2004 Jelmer Vernooij \nPart of Samba\nhttp://www.samba.org/\n"); - gtk_widget_show (label2); - gtk_box_pack_start (GTK_BOX (dialog_vbox1), label2, TRUE, FALSE, 0); - gtk_label_set_use_markup (GTK_LABEL (label2), TRUE); - - dialog_action_area1 = GTK_DIALOG (aboutwin)->action_area; - gtk_widget_show (dialog_action_area1); - gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END); - - closebutton1 = gtk_button_new_from_stock ("gtk-close"); - gtk_widget_show (closebutton1); - gtk_dialog_add_action_widget (GTK_DIALOG (aboutwin), closebutton1, GTK_RESPONSE_CLOSE); - GTK_WIDGET_SET_FLAGS (closebutton1, GTK_CAN_DEFAULT); - - return aboutwin; -} - - -static GtkWidget* create_openfilewin (void) -{ - GtkWidget *ok_button; - GtkWidget *cancel_button; - - openfilewin = gtk_file_selection_new ("Select File"); - gtk_container_set_border_width (GTK_CONTAINER (openfilewin), 10); - - ok_button = GTK_FILE_SELECTION (openfilewin)->ok_button; - gtk_widget_show (ok_button); - GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); - - cancel_button = GTK_FILE_SELECTION (openfilewin)->cancel_button; - gtk_widget_show (cancel_button); - GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); - - return openfilewin; -} - -static GtkWidget* create_savefilewin (void) -{ - GtkWidget *ok_button; - GtkWidget *cancel_button; - - savefilewin = gtk_file_selection_new ("Select File"); - gtk_container_set_border_width (GTK_CONTAINER (savefilewin), 10); - - ok_button = GTK_FILE_SELECTION (savefilewin)->ok_button; - gtk_widget_show (ok_button); - GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); - - cancel_button = GTK_FILE_SELECTION (savefilewin)->cancel_button; - gtk_widget_show (cancel_button); - GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); - - return savefilewin; -} - - int main(int argc, char *argv[]) -{ - poptContext pc; - const char *backend = NULL; - const char *credentials = NULL; - const char *location; - int opt; - struct poptOption long_options[] = { - POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%%password)", NULL}, - POPT_TABLEEND - }; - - gtk_init (&argc, &argv); - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); - - while((opt = poptGetNextOpt(pc)) != -1) { - } - - location = poptGetArg(pc); - - if(location) { - WERROR error; - - if(!backend) { - if(credentials)backend = "rpc"; - else backend = "nt4"; - } - - error = reg_open(backend, location, credentials, ®istry); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(error); - return -1; - } - mainwin = create_mainwin (); - registry_load_root(); - } else - mainwin = create_mainwin (); - - gtk_widget_show (mainwin); - - gtk_main (); - - if(registry)reg_free(registry); - return 0; -} -- cgit From 462d27d7e633e368928569f8fbe9e25ab3e72e1c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Jul 2004 06:50:31 +0000 Subject: r1434: Merge this function in from Samba 3.0, but use a mem_ctx rather than an fstring. Andrew Bartlett (This used to be commit e8de8905b2f328395d71afdd73c77301c9366a66) --- source4/lib/util.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 3b23543bfc..3666d6e4e7 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -797,6 +797,23 @@ char *myhostname(TALLOC_CTX *mem_ctx) } +/********************************************************************** + Converts a name to a fully qalified domain name. +***********************************************************************/ + +char *name_to_fqdn(TALLOC_CTX *mem_ctx, const char *name) +{ + struct hostent *hp = sys_gethostbyname(name); + if ( hp && hp->h_name && *hp->h_name ) { + DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, hp->h_name)); + return talloc_strdup(mem_ctx, hp->h_name); + } else { + DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name)); + return talloc_strdup(mem_ctx, name); + } +} + + /***************************************************************** A useful function for returning a path in the Samba lock directory. *****************************************************************/ -- cgit From 30c15f37cc73f0beebceed009109542ba738d011 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Jul 2004 06:51:58 +0000 Subject: r1435: talloc_steal is very useful - add a function to do it with a DATA_BLOB Andrew Bartlett (This used to be commit 66d6e2611084d579a20833a4c0daa5d72ef9393c) --- source4/lib/data_blob.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 3667d453b9..a6e6672b90 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -99,6 +99,21 @@ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) return blob; } +/** + * Steal a talloc'ed DATA_BLOB from one context to another + */ + +DATA_BLOB data_blob_talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, + DATA_BLOB *old) +{ + DATA_BLOB new; + new = *old; + new.data = talloc_steal(old_ctx, new_ctx, old->data); + if (new.data == NULL) { + smb_panic("data_blob_talloc_steal: talloc_steal failed.\n"); + } +} + /******************************************************************* free a data blob *******************************************************************/ -- cgit From 02262db2ed81fd99a58bce4b7a21c75184264483 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 11 Jul 2004 12:59:27 +0000 Subject: r1452: Thanks to Volker for spotting that this code was certainly not tested... (make sure to actually return the result). Andrew Bartlett (This used to be commit 8d449bbe2b9aa29315e894be1400a9475ef99468) --- source4/lib/data_blob.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index a6e6672b90..ee7bffdc1b 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -112,6 +112,7 @@ DATA_BLOB data_blob_talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, if (new.data == NULL) { smb_panic("data_blob_talloc_steal: talloc_steal failed.\n"); } + return new; } /******************************************************************* -- cgit From 39b12015846e06cbf89079e365e6c228ca3883c2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 13 Jul 2004 03:23:55 +0000 Subject: r1474: It is useful if talloc_strdup() behaves like strdup() - NULL in, NULL out Andrew Bartlett (This used to be commit 2cc0b3a2f1785c53268f018999a87c26539fd4a6) --- source4/lib/talloc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 9f873a2d6b..421a09e3c6 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -381,6 +381,9 @@ void *talloc_memdup(TALLOC_CTX *t, const void *p, size_t size) /** strdup with a talloc */ char *talloc_strdup(TALLOC_CTX *t, const char *p) { + if (!p) { + return NULL; + } return talloc_memdup(t, p, strlen(p) + 1); } -- cgit From f607197054436a8195e3d0a695fe31574b418059 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 14 Jul 2004 12:14:07 +0000 Subject: r1498: (merge from 3.0) Rework our random number generation system. On systems with /dev/urandom, this avoids a change to secrets.tdb for every fork(). For other systems, we now only re-seed after a fork, and on startup. No need to do it per-operation. This removes the 'need_reseed' parameter from generate_random_buffer(). This also requires that we start the secrets subsystem, as that is where the reseed value is stored, for systems without /dev/urandom. In order to aviod identical streams in forked children, the random state is re-initialised after the fork(), at the same point were we do that to the tdbs. Andrew Bartlett (This used to be commit b97d3cb2efd68310b1aea8a3ac40a64979c8cdae) --- source4/lib/genrand.c | 77 ++++++++++++++++++++++++++++--------------------- source4/lib/util_uuid.c | 2 +- 2 files changed, 45 insertions(+), 34 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index b37078b284..adc6d7344e 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -22,39 +22,50 @@ #include "includes.h" -static uint8_t hash[258]; -static uint32_t counter; -static uint8_t *reseed_data; -static size_t reseed_data_size; +static unsigned char hash[258]; +static uint32 counter; + +static BOOL done_reseed = False; +static void (*reseed_callback)(int *newseed); /**************************************************************** Copy any user given reseed data. *****************************************************************/ -void set_rand_reseed_data(uint8_t *data, size_t len) +void set_rand_reseed_callback(void (*fn)(int *)) +{ + reseed_callback = fn; + set_need_random_reseed(); +} + +void set_need_random_reseed(void) { - SAFE_FREE(reseed_data); - reseed_data_size = 0; + done_reseed = False; +} - reseed_data = (uint8_t *)memdup(data, len); - if (reseed_data) - reseed_data_size = len; +static void get_rand_reseed_data(int *reseed_data) +{ + if (reseed_callback) { + reseed_callback(reseed_data); + } else { + *reseed_data = 0; + } } /**************************************************************** Setup the seed. *****************************************************************/ -static void seed_random_stream(uint8_t *seedval, size_t seedlen) +static void seed_random_stream(unsigned char *seedval, size_t seedlen) { - uint8_t j = 0; + unsigned char j = 0; size_t ind; for (ind = 0; ind < 256; ind++) - hash[ind] = (uint8_t)ind; + hash[ind] = (unsigned char)ind; for( ind = 0; ind < 256; ind++) { - uint8_t tc; + unsigned char tc; j += (hash[ind] + seedval[ind%seedlen]); @@ -71,15 +82,15 @@ static void seed_random_stream(uint8_t *seedval, size_t seedlen) Get datasize bytes worth of random data. *****************************************************************/ -static void get_random_stream(uint8_t *data, size_t datasize) +static void get_random_stream(unsigned char *data, size_t datasize) { - uint8_t index_i = hash[256]; - uint8_t index_j = hash[257]; + unsigned char index_i = hash[256]; + unsigned char index_j = hash[257]; size_t ind; for( ind = 0; ind < datasize; ind++) { - uint8_t tc; - uint8_t t; + unsigned char tc; + unsigned char t; index_i++; index_j += hash[index_i]; @@ -101,10 +112,10 @@ static void get_random_stream(uint8_t *data, size_t datasize) Note that the hash is not initialised. *****************************************************************/ -static void do_filehash(const char *fname, uint8_t *the_hash) +static void do_filehash(const char *fname, unsigned char *the_hash) { - uint8_t buf[1011]; /* deliberate weird size */ - uint8_t tmp_md4[16]; + unsigned char buf[1011]; /* deliberate weird size */ + unsigned char tmp_md4[16]; int fd, n; fd = sys_open(fname,O_RDONLY,0); @@ -133,8 +144,9 @@ static void do_filehash(const char *fname, uint8_t *the_hash) static int do_reseed(BOOL use_fd, int fd) { - uint8_t seed_inbuf[40]; - uint32_t v1, v2; struct timeval tval; pid_t mypid; + unsigned char seed_inbuf[40]; + uint32 v1, v2; struct timeval tval; pid_t mypid; + int reseed_data = 0; if (use_fd) { if (fd != -1) @@ -166,10 +178,11 @@ static int do_reseed(BOOL use_fd, int fd) * Add any user-given reseed data. */ + get_rand_reseed_data(&reseed_data); if (reseed_data) { size_t i; for (i = 0; i < sizeof(seed_inbuf); i++) - seed_inbuf[i] ^= reseed_data[i % reseed_data_size]; + seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); @@ -181,15 +194,14 @@ static int do_reseed(BOOL use_fd, int fd) Interface to the (hopefully) good crypto random number generator. ********************************************************************/ -void generate_random_buffer( uint8_t *out, int len, BOOL do_reseed_now) +void generate_random_buffer( unsigned char *out, int len) { - static BOOL done_reseed = False; static int urand_fd = -1; - uint8_t md4_buf[64]; - uint8_t tmp_buf[16]; - uint8_t *p; + unsigned char md4_buf[64]; + unsigned char tmp_buf[16]; + unsigned char *p; - if(!done_reseed || do_reseed_now) { + if(!done_reseed) { urand_fd = do_reseed(True, urand_fd); done_reseed = True; } @@ -225,7 +237,6 @@ void generate_random_buffer( uint8_t *out, int len, BOOL do_reseed_now) } } - /* very basic password quality checker */ @@ -262,7 +273,7 @@ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) return NULL; again: - generate_random_buffer(retstr, len, False); + generate_random_buffer(retstr, len); for (i = 0; i < len; i++) retstr[i] = c_list[retstr[i] % (sizeof(c_list)-1) ]; diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 6a705a4f30..156f20e53e 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -24,7 +24,7 @@ void uuid_generate_random(struct GUID *out) { - generate_random_buffer(out, sizeof(struct GUID), False); + generate_random_buffer(out, sizeof(struct GUID)); out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; } -- cgit From 6f47dec36459dda22130ff36f7cdf8b675a28742 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jul 2004 07:16:15 +0000 Subject: r1511: fixed a free() that should be ldb_free() this might explain the tdb corruption that metze found - it caused heap corruption that affected tdb (This used to be commit 31d55dfb443612a341ff6ade77c6e4477c4fefca) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index b36c53e100..355de21250 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -470,7 +470,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) tdb_data = tdb_fetch(ltdb->tdb, tdb_key); if (!tdb_data.dptr) { - free(tdb_key.dptr); + ldb_free(ldb, tdb_key.dptr); return -1; } -- cgit From eeec6109833571f275a9adc220b5bbb05d1cb2bd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 Jul 2004 10:07:05 +0000 Subject: r1517: change event_remove_timed() to remove by structure not by handler. this fixes a crash bug in smbd with multiple RPC clients (This used to be commit 6e102f732e4404fc5f9b2851d12b00d2d083b43d) --- source4/lib/events.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 50f3f53c94..13a9a444e8 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -186,15 +186,13 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event /* remove a timed event - the event to remove is matched only on the handler function return False on failure (event not found) */ BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) { struct timed_event *e; for (e=ev->timed_events; e; e=e->next) { - if (e->ref_count && - e->handler == e1->handler) { + if (e->ref_count && e == e1) { e->ref_count--; return True; } -- cgit From 5ddf678e0113f81aa2b5f99134cda4fe8c01afb7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 Jul 2004 06:40:49 +0000 Subject: r1578: the first stage of the async client rewrite. Up to now the client code has had an async API, and operated asynchronously at the packet level, but was not truly async in that it assumed that it could always write to the socket and when a partial packet came in that it could block waiting for the rest of the packet. This change makes the SMB client library full async, by adding a separate outgoing packet queue, using non-blocking socket IO and having a input buffer that can fill asynchonously until the full packet has arrived. The main complexity was in dealing with the events structure when using the CIFS proxy backend. In that case the same events structure needs to be used in both the client library and the main smbd server, so that when the client library is waiting for a reply that the main server keeps processing packets. This required some changes in the events library code. Next step is to make the generated rpc client code use these new capabilities. (This used to be commit 96bf4da3edc4d64b0f58ef520269f3b385b8da02) --- source4/lib/events.c | 344 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 209 insertions(+), 135 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 13a9a444e8..a6099db5c5 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -81,25 +81,50 @@ struct event_context *event_context_init(void) /* start off with no events */ ZERO_STRUCTP(ev); + ev->ref_count = 1; + return ev; } - - /* - add a fd based event - return NULL on failure (memory allocation error) + destroy an events context, also destroying any remaining events */ -struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) +void event_context_destroy(struct event_context *ev) { - e = memdup(e, sizeof(*e)); - if (!e) return NULL; - DLIST_ADD(ev->fd_events, e); - e->ref_count = 1; - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; + struct fd_event *fde; + struct timed_event *te; + struct loop_event *le; + + ev->ref_count--; + if (ev->ref_count != 0) { + return; } - return e; + + for (fde=ev->fd_events; fde;) { + struct fd_event *next = fde->next; + event_remove_fd(ev, fde); + if (fde->ref_count == 0) { + free(fde); + } + fde=next; + } + for (te=ev->timed_events; te;) { + struct timed_event *next = te->next; + event_remove_timed(ev, te); + if (te->ref_count == 0) { + free(te); + } + te=next; + } + for (le=ev->loop_events; le;) { + struct loop_event *next = le->next; + event_remove_loop(ev, le); + if (le->ref_count == 0) { + free(le); + } + le=next; + } + free(ev); } @@ -118,6 +143,47 @@ static void calc_maxfd(struct event_context *ev) } } +/* + move the event structures from ev2 into ev, upping the reference + count on ev. The event context ev2 is then destroyed. + + this is used by modules that need to call on the events of a lower module +*/ +void event_context_merge(struct event_context *ev, struct event_context *ev2) +{ + DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *); + DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *); + DLIST_CONCATENATE(ev->loop_events, ev2->loop_events, struct loop_event *); + + ev->ref_count++; + + ev2->fd_events = NULL; + ev2->timed_events = NULL; + ev2->loop_events = NULL; + + event_context_destroy(ev2); + + calc_maxfd(ev); +} + + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) +{ + e = memdup(e, sizeof(*e)); + if (!e) return NULL; + DLIST_ADD(ev->fd_events, e); + e->ref_count = 1; + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + return e; +} + + /* to mark the ev->maxfd invalid * this means we need to recalculate it */ @@ -242,150 +308,158 @@ void event_loop_exit(struct event_context *ev, int code) } /* - go into an event loop using the events defined in ev this function - will return with the specified code if one of the handlers calls - event_loop_exit() - - also return (with code 0) if all fd events are removed + do a single event loop using the events defined in ev this function */ -int event_loop_wait(struct event_context *ev) +void event_loop_once(struct event_context *ev) { time_t t; - - ZERO_STRUCT(ev->exit); - ev->maxfd = EVENT_INVALID_MAXFD; + fd_set r_fds, w_fds; + struct fd_event *fe; + struct loop_event *le; + struct timed_event *te; + int selrtn; + struct timeval tval; t = time(NULL); - while (ev->fd_events && !ev->exit.exit_now) { - fd_set r_fds, w_fds; - struct fd_event *fe; - struct loop_event *le; - struct timed_event *te; - int selrtn; - struct timeval tval; - - /* the loop events are called on each loop. Be careful to allow the - event to remove itself */ - for (le=ev->loop_events;le;) { - struct loop_event *next = le->next; - if (le->ref_count == 0) { - DLIST_REMOVE(ev->loop_events, le); - free(le); - } else { - le->ref_count++; - le->handler(ev, le, t); - le->ref_count--; - } - le = next; + /* the loop events are called on each loop. Be careful to allow the + event to remove itself */ + for (le=ev->loop_events;le;) { + struct loop_event *next = le->next; + if (le->ref_count == 0) { + DLIST_REMOVE(ev->loop_events, le); + free(le); + } else { + le->ref_count++; + le->handler(ev, le, t); + le->ref_count--; } + le = next; + } - ZERO_STRUCT(tval); - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - - /* setup any fd events */ - for (fe=ev->fd_events; fe; ) { - struct fd_event *next = fe->next; - if (fe->ref_count == 0) { - DLIST_REMOVE(ev->fd_events, fe); - if (ev->maxfd == fe->fd) { - ev->maxfd = EVENT_INVALID_MAXFD; - } - free(fe); - } else { - if (fe->flags & EVENT_FD_READ) { - FD_SET(fe->fd, &r_fds); - } - if (fe->flags & EVENT_FD_WRITE) { - FD_SET(fe->fd, &w_fds); - } + ZERO_STRUCT(tval); + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); + + /* setup any fd events */ + for (fe=ev->fd_events; fe; ) { + struct fd_event *next = fe->next; + if (fe->ref_count == 0) { + DLIST_REMOVE(ev->fd_events, fe); + if (ev->maxfd == fe->fd) { + ev->maxfd = EVENT_INVALID_MAXFD; + } + free(fe); + } else { + if (fe->flags & EVENT_FD_READ) { + FD_SET(fe->fd, &r_fds); + } + if (fe->flags & EVENT_FD_WRITE) { + FD_SET(fe->fd, &w_fds); } - fe = next; } + fe = next; + } - /* start with a reasonable max timeout */ - tval.tv_sec = 600; + /* start with a reasonable max timeout */ + tval.tv_sec = 600; - /* work out the right timeout for all timed events */ - for (te=ev->timed_events;te;te=te->next) { - int timeout = te->next_event - t; - if (timeout < 0) { - timeout = 0; - } - if (te->ref_count && - timeout < tval.tv_sec) { - tval.tv_sec = timeout; - } + /* work out the right timeout for all timed events */ + for (te=ev->timed_events;te;te=te->next) { + int timeout = te->next_event - t; + if (timeout < 0) { + timeout = 0; } + if (te->ref_count && + timeout < tval.tv_sec) { + tval.tv_sec = timeout; + } + } - /* only do a select() if there're fd_events - * otherwise we would block for a the time in tval, - * and if there're no fd_events present anymore we want to - * leave the event loop directly + /* only do a select() if there're fd_events + * otherwise we would block for a the time in tval, + * and if there're no fd_events present anymore we want to + * leave the event loop directly + */ + if (ev->fd_events) { + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } + + /* TODO: + * we don't use sys_select() as it isn't thread + * safe. We need to replace the magic pipe handling in + * sys_select() with something in the events + * structure - for now just use select() */ - if (ev->fd_events) { - /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(ev); - } - - /* TODO: - * we don't use sys_select() as it isn't thread - * safe. We need to replace the magic pipe handling in - * sys_select() with something in the events - * structure - for now just use select() - */ - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); - - t = time(NULL); - - if (selrtn == -1 && errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - DEBUG(0,("EBADF on event_loop_wait - exiting\n")); - return -1; - } - - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { - uint16_t flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (fe->ref_count && flags) { - fe->ref_count++; - fe->handler(ev, fe, t, flags); - fe->ref_count--; - } + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + + t = time(NULL); + + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("EBADF on event_loop_wait - exiting\n")); + return; + } + + if (selrtn > 0) { + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16_t flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (fe->ref_count && flags) { + fe->ref_count++; + fe->handler(ev, fe, t, flags); + fe->ref_count--; } } } + } - /* call any timed events that are now due */ - for (te=ev->timed_events;te;) { - struct timed_event *next = te->next; - if (te->ref_count == 0) { - DLIST_REMOVE(ev->timed_events, te); - free(te); - } else if (te->next_event <= t) { - te->ref_count++; - te->handler(ev, te, t); - te->ref_count--; - if (te->next_event <= t) { - /* the handler didn't set a time for the - next event - remove the event */ - event_remove_timed(ev, te); - } + /* call any timed events that are now due */ + for (te=ev->timed_events;te;) { + struct timed_event *next = te->next; + if (te->ref_count == 0) { + DLIST_REMOVE(ev->timed_events, te); + free(te); + } else if (te->next_event <= t) { + te->ref_count++; + te->handler(ev, te, t); + te->ref_count--; + if (te->next_event <= t) { + /* the handler didn't set a time for the + next event - remove the event */ + event_remove_timed(ev, te); } - te = next; - } + } + te = next; + } +} + +/* + go into an event loop using the events defined in ev this function + will return with the specified code if one of the handlers calls + event_loop_exit() + + also return (with code 0) if all fd events are removed +*/ +int event_loop_wait(struct event_context *ev) +{ + ZERO_STRUCT(ev->exit); + ev->maxfd = EVENT_INVALID_MAXFD; + + ev->exit.exit_now = False; + while (ev->fd_events && !ev->exit.exit_now) { + event_loop_once(ev); } return ev->exit.code; -- cgit From 112c2c831b96ae8f454a93483ffdf924a8f91a88 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 28 Jul 2004 13:08:08 +0000 Subject: r1596: Fix up copyrights. (This used to be commit d2553aac0a75591026b9b1fcf46065e5b03ed19c) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 3666d6e4e7..e09796c4f3 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -4,7 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001-2002 Copyright (C) Simo Sorce 2001 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. Copyright (C) James J Myers 2003 This program is free software; you can redistribute it and/or modify -- cgit From 578a99db4d43827ac78ca6bf94e89c883a3dd310 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 29 Jul 2004 11:55:57 +0000 Subject: r1606: make the low level socket read/write routines cope properly with non-blocking sockets (This used to be commit bb6cbf29ccf8f2b556bf3e7b3ff487faa0f36773) --- source4/lib/util_sock.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 43da8a2f57..8c9a140746 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -195,10 +195,13 @@ ssize_t read_data(int fd, char *buffer, size_t N) while (total < N) { ret = sys_read(fd,buffer + total,N - total); if (ret == 0) { - return 0; + return total; } if (ret == -1) { - return -1; + if (total == 0) { + return -1; + } + return total; } total += ret; } @@ -222,10 +225,14 @@ ssize_t write_data(int fd, const char *buffer, size_t N) while (total < N) { ret = sys_write(fd, buffer + total, N - total); if (ret == -1) { - return -1; + if (total == 0) { + return -1; + } + return total; } - if (ret == 0) + if (ret == 0) { return total; + } total += ret; } -- cgit From 94fb514376e7cb1c3ba4f89e10289350052d1294 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 3 Aug 2004 05:47:24 +0000 Subject: r1630: - fixed the replacement timegm() function to work correctly for DST changes - got rid of global_myname(), using lp_netbios_name() instead (This used to be commit e8d4b390884e487163d81f66a5a7ac1de1305d9a) --- source4/lib/replace.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index c186d307e6..de32d377d5 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -437,7 +437,6 @@ char *rep_inet_ntoa(struct in_addr ip) { struct tm tm2, tm3; time_t t; - static int zone = -1; tm2 = *tm; @@ -446,10 +445,7 @@ char *rep_inet_ntoa(struct in_addr ip) tm2 = *tm; tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); - if (zone == -1) { - zone = get_time_zone(t); - } - t -= zone; + t -= get_time_zone(t); return t; } @@ -472,8 +468,3 @@ char *rep_inet_ntoa(struct in_addr ip) return ret; } #endif - -const char *global_myname(void) -{ - return lp_netbios_name(); -} -- cgit From 6292e5b95202b9cb17579cbcc5bf01483770e2d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Aug 2004 03:28:44 +0000 Subject: r1749: added some random stuff that captures some discussions volker and I just had on emulating % macros from smb.conf in a possible ldb based config system (This used to be commit d547479290e30d4fd86ab718528e879a28f71447) --- source4/lib/ldb/tests/test-config.ldif | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-config.ldif b/source4/lib/ldb/tests/test-config.ldif index 92592a2d66..7926a9e3c5 100644 --- a/source4/lib/ldb/tests/test-config.ldif +++ b/source4/lib/ldb/tests/test-config.ldif @@ -2,13 +2,35 @@ # global configuration options dn: cn=Global,cn=Config,cn=Samba objectclass: globalconfig +LocalConfigCn: cn=%U,cn=Config,cn=Samba +LocalConfigCn;1: cn=%U,cn=Config,cn=Samba +LocalConfigCn;2: cn=%I,cn=Config,cn=Samba +LocalConfigCn;3: cn=%M,cn=Config,cn=Samba + +############# +dn: cn=Protocol,cn=Global,cn=Config,cn=Samba +maxXmit: 7000 + +################################ +dn: cn=Volker,cn=Config,cn=Samba +Workgroup: VNET3 +UnixCharset: UTF8 +Security: user +Interfaces: vmnet* eth* +NetbiosName: blu +GuestAccount: tridge + +################################# +dn: cn=Volker,cn=Config,cn=Samba Workgroup: VNET3 UnixCharset: UTF8 Security: user Interfaces: vmnet* eth* NetbiosName: blu GuestAccount: tridge +Include: cn=%U,cn=MyConfig,cn=Config,cn=Samba +#### ((objectClass=fileshare)(cn=test)) ############################## # [test] share dn: cn=test,cn=Shares,cn=Config,cn=Samba -- cgit From d01bc8a91e90a818786b46625249fc38ead7be4d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 12 Aug 2004 06:30:03 +0000 Subject: r1758: Move and enhance the add_string_to_array function as per volker job on trunk (This used to be commit 606caddeb95382287fa41a5017ca473d0301be6b) --- source4/lib/util_str.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 66acc0ca0e..fd13f86501 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1446,3 +1446,21 @@ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s) return ret; } + +BOOL add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, const char ***strings, int *num) +{ + char *dup_str = talloc_strdup(mem_ctx, str); + + *strings = talloc_realloc(mem_ctx, *strings, + ((*num)+1) * sizeof(**strings)); + + if ((*strings == NULL) || (dup_str == NULL)) + return False; + + (*strings)[*num] = dup_str; + *num += 1; + + return True; +} + -- cgit From 13a579df8729aee6781af817c62a5f688f85328d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 12 Aug 2004 06:31:22 +0000 Subject: r1759: Add some helper functions to read and write data to a socket with timeout (again from volker in trunk) (This used to be commit 40d8262e7dbba76f88f1900744ed02f9f7fcdadd) --- source4/lib/util_sock.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 8c9a140746..54365116e8 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -239,6 +239,118 @@ ssize_t write_data(int fd, const char *buffer, size_t N) return (ssize_t)total; } +/**************************************************************************** + Check the timeout. +****************************************************************************/ + +static BOOL timeout_until(struct timeval *timeout, + const struct timeval *endtime) +{ + struct timeval now; + + GetTimeOfDay(&now); + + if ((now.tv_sec > endtime->tv_sec) || + ((now.tv_sec == endtime->tv_sec) && + (now.tv_usec > endtime->tv_usec))) + return False; + + timeout->tv_sec = endtime->tv_sec - now.tv_sec; + timeout->tv_usec = endtime->tv_usec - now.tv_usec; + return True; +} + + +/**************************************************************************** + Read data from the client, reading exactly N bytes, with timeout. +****************************************************************************/ + +ssize_t read_data_until(int fd,char *buffer,size_t N, + const struct timeval *endtime) +{ + ssize_t ret; + size_t total=0; + + smb_read_error = 0; + + while (total < N) { + + if (endtime != NULL) { + fd_set r_fds; + struct timeval timeout; + int res; + + FD_ZERO(&r_fds); + FD_SET(fd, &r_fds); + + if (!timeout_until(&timeout, endtime)) + return -1; + + res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout); + if (res <= 0) + return -1; + } + + ret = sys_read(fd,buffer + total,N - total); + + if (ret == 0) { + DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); + smb_read_error = READ_EOF; + return 0; + } + + if (ret == -1) { + DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); + smb_read_error = READ_ERROR; + return -1; + } + total += ret; + } + return (ssize_t)total; +} + +/**************************************************************************** + Write data to a fd with timeout. +****************************************************************************/ + +ssize_t write_data_until(int fd,char *buffer,size_t N, + const struct timeval *endtime) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + + if (endtime != NULL) { + fd_set w_fds; + struct timeval timeout; + int res; + + FD_ZERO(&w_fds); + FD_SET(fd, &w_fds); + + if (!timeout_until(&timeout, endtime)) + return -1; + + res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout); + if (res <= 0) + return -1; + } + + ret = sys_write(fd,buffer + total,N - total); + + if (ret == -1) { + DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (ret == 0) + return total; + + total += ret; + } + return (ssize_t)total; +} + /**************************************************************************** send a keepalive packet (rfc1002) -- cgit From 67f28b93ab01dc74bacf7e45b4030a83a2a7a3d9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 12 Aug 2004 07:13:44 +0000 Subject: r1766: we do not have smb_read_error in samba4 (This used to be commit 1c3d52cea4dff57b14ee9bc197001fadb1d18abf) --- source4/lib/util_sock.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 54365116e8..f24d010f22 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -271,8 +271,6 @@ ssize_t read_data_until(int fd,char *buffer,size_t N, ssize_t ret; size_t total=0; - smb_read_error = 0; - while (total < N) { if (endtime != NULL) { @@ -295,13 +293,11 @@ ssize_t read_data_until(int fd,char *buffer,size_t N, if (ret == 0) { DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); - smb_read_error = READ_EOF; return 0; } if (ret == -1) { DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); - smb_read_error = READ_ERROR; return -1; } total += ret; -- cgit From ada86316e54320a891d982c653e1070155bc8dbb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 14 Aug 2004 05:57:43 +0000 Subject: r1820: added a strcmp_safe() that handles NULL pointers. Needed for the search torture test, as some servers return really bad entries. (This used to be commit c900ebb3ac18d77ab334d3bf5259b3bba547b09c) --- source4/lib/util_str.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index fd13f86501..a6f54f9a8d 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1464,3 +1464,18 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx, return True; } + + +/* + varient of strcmp() that handles NULL ptrs +*/ +int strcmp_safe(const char *s1, const char *s2) +{ + if (s1 == s2) { + return 0; + } + if (s1 == NULL || s2 == NULL) { + return s1?-1:1; + } + return strcmp(s1, s2); +} -- cgit From d3e8a74551746f3326fceeb55565bd95b1990b4f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 16 Aug 2004 19:03:22 +0000 Subject: r1838: Updates from the airplane: - IDL fixes + adding comments - Start working on dcom infrastructure (This used to be commit ef0fc269f06c82594c34ad8673c76c5ea099250e) --- source4/lib/dcom/config.m4 | 1 + source4/lib/dcom/config.mk | 8 ++++++ source4/lib/dcom/main.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/dcom/procedure | 8 ++++++ 4 files changed, 82 insertions(+) create mode 100644 source4/lib/dcom/config.m4 create mode 100644 source4/lib/dcom/config.mk create mode 100644 source4/lib/dcom/main.c create mode 100644 source4/lib/dcom/procedure (limited to 'source4/lib') diff --git a/source4/lib/dcom/config.m4 b/source4/lib/dcom/config.m4 new file mode 100644 index 0000000000..206b916fa6 --- /dev/null +++ b/source4/lib/dcom/config.m4 @@ -0,0 +1 @@ +SMB_SUBSYSTEM_MK(LIBDCOM,lib/dcom/config.mk) diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk new file mode 100644 index 0000000000..ef7cbf40c8 --- /dev/null +++ b/source4/lib/dcom/config.mk @@ -0,0 +1,8 @@ +################################################ +# Start SUBSYSTEM LIBDCOM +[SUBSYSTEM::LIBDCOM] +INIT_OBJ_FILES = \ + lib/dcom/main.o +# +# End SUBSYSTEM LIBDCOM +################################################ diff --git a/source4/lib/dcom/main.c b/source4/lib/dcom/main.c new file mode 100644 index 0000000000..515322e27a --- /dev/null +++ b/source4/lib/dcom/main.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + Main DCOM functionality + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +void CoInitializeEx(void *reserved, uint32 thread_options) +{ + /* FIXME */ +} + +void CoInitialize(void *reserved) +{ + CoInitializeEx(reserved, 0); +} + +void CoUnitialize(void) +{ + /* FIXME */ +} + +void CoRegisterClassObject(void) +{ + /* FIXME */ +} + +void CoUnregisterClassObject(void) +{ + /* FIXME */ +} + +void CoCreateInstanceEx(struct GUID *clsid, void *iface, uint32 context, struct COSERVERINFO *pcsi, uint32 num, struct MULTI_QI *results) +{ + /* FIXME: Connect to remote server and :*/ + + /* FIXME: Call RemoteActivation() */ + /* FIXME: Call ServerAlive() on IOXIDResolver */ + +} + +void CoCreateInstance(void) +{ + CoCreateInstanceEx(/*FIXME*/); +} + +void CoRegisterClassObject(void) +{ + /* FIXME */ +} diff --git a/source4/lib/dcom/procedure b/source4/lib/dcom/procedure new file mode 100644 index 0000000000..dc89d00bb2 --- /dev/null +++ b/source4/lib/dcom/procedure @@ -0,0 +1,8 @@ +Required infrastructure: + - CoCreateInstance function + - Proxy and Stub (class ?) + + + - Bind to IOXIDResolver + - ServerAlive2() + - Bind to ISystemActivator -- cgit From c3a2584bb485e41d580e4098731984c194602fc8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 18 Aug 2004 18:25:02 +0000 Subject: r1892: this adds talloc_get_context(), which is something I discussed at the team meeting at CIFS04. It allows you to find the talloc context given any pointer allocated with talloc. (This used to be commit 01dc4ed9b4f9390930d3c235cf2ccf9a9028392d) --- source4/lib/talloc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 421a09e3c6..328a1ce1d1 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -1,7 +1,7 @@ /* Samba Unix SMB/CIFS implementation. Samba temporary memory allocation functions - Copyright (C) Andrew Tridgell 2000 + Copyright (C) Andrew Tridgell 2000-2004 Copyright (C) 2001, 2002 by Martin Pool This program is free software; you can redistribute it and/or modify @@ -152,6 +152,18 @@ static TALLOC_CTX *talloc_init_internal(void) } +/* + return the talloc context given a pointer that has been allocated using + talloc +*/ +TALLOC_CTX *talloc_get_context(void *ptr) +{ + struct talloc_chunk *tc; + tc = ((struct talloc_chunk *)ptr)-1; + + return tc->context; +} + /** Allocate a bit of memory from the specified pool **/ void *talloc(TALLOC_CTX *t, size_t size) { -- cgit From 664f50e81cc97eac7162cb3dd324eaefb11aa7d2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 18 Aug 2004 19:57:49 +0000 Subject: r1894: Convert // to /* */ (This used to be commit 5dc793b2b4b5c54df4aa3b0c98c248bdd671bbb1) --- source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 36feaff907..ee9f8bf24f 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1438,7 +1438,7 @@ static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) * means making one pass over each structure and figuring it out */ -//FIXME size = sec_desc_size(sec->sec_desc); +/* FIXME size = sec_desc_size(sec->sec_desc); */ /* Allocate that much space */ diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index af869d1cfa..7eddea2b93 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -648,7 +648,7 @@ static CMD_FILE *cmd_file_create(const char *file) * We pass a table of command callbacks for that */ -//FIXME +/* FIXME */ /* * Main code from here on ... -- cgit From debce401eb31ee5b6ffe08af6ccfc0a8bfd07a11 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 18 Aug 2004 21:22:07 +0000 Subject: r1898: Check the context we are going to return. (This used to be commit d721b122b5c443363b8f8ec2e1ef4b798378b658) --- source4/lib/talloc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 328a1ce1d1..21c3bdac6e 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -161,7 +161,11 @@ TALLOC_CTX *talloc_get_context(void *ptr) struct talloc_chunk *tc; tc = ((struct talloc_chunk *)ptr)-1; - return tc->context; + if (tc->magic == TALLOC_MAGIC) { + return tc->context; + } else { + return NULL; + } } /** Allocate a bit of memory from the specified pool **/ -- cgit From 838c208ab1531814579191472d7427c89b231296 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Aug 2004 07:51:51 +0000 Subject: r1901: add missing include of metze (This used to be commit 5e5681e2830bfd487d7e783249fe069b41be1f37) --- source4/lib/ldb/ldb_tdb/ldb_match.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 963048915a..cae5886547 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" -- cgit From bca24a19ebfc8943b46fdb900418e396aef96aa4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Aug 2004 12:16:48 +0000 Subject: r1911: merge a few popt parameters from 3.0 move some to better places and deal with users DOMAIN and lp_workgroup() of the local workstation metze (This used to be commit 1fc0100e44a8640cfc15effb99f5824cb7817da8) --- source4/lib/cmdline/popt_common.c | 94 ++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index f659468561..ef75d7be1f 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -33,10 +33,7 @@ * -i,--scope */ -extern pstring user_socket_options; -extern BOOL AllowDebugChange; - -struct user_auth_info cmdline_auth_info; +struct cmdline_auth_info cmdline_auth_info; static void popt_common_callback(poptContext con, enum poptCallbackReason reason, @@ -70,6 +67,12 @@ static void popt_common_callback(poptContext con, exit(0); break; + case 'O': + if (arg) { + lp_set_cmdline("socket options", arg); + } + break; + case 's': if (arg) { pstrcpy(dyn_CONFIGFILE, arg); @@ -98,13 +101,17 @@ static void popt_common_callback(poptContext con, case 'm': lp_set_cmdline("max protocol", arg); break; + + case 'R': + lp_set_cmdline("name resolve order", arg); + break; } } struct poptOption popt_common_connection[] = { { NULL, 0, POPT_ARG_CALLBACK, popt_common_callback }, - { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", - "SOCKETOPTIONS" }, + { "name-resolve", 'R', POPT_ARG_STRING, NULL, 'R', "Use these name resolution services only", "NAME-RESOLVE-ORDER" }, + { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use", "SOCKETOPTIONS" }, { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, @@ -117,7 +124,6 @@ struct poptOption popt_common_samba[] = { { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, - { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" }, POPT_TABLEEND }; @@ -133,7 +139,7 @@ struct poptOption popt_common_version[] = { * get a password from a a file or file descriptor * exit on failure * ****************************************************************************/ -static void get_password_file(struct user_auth_info *a) +static void get_password_file(struct cmdline_auth_info *a) { int fd = -1; char *p; @@ -187,7 +193,7 @@ static void get_password_file(struct user_auth_info *a) close(fd); } -static void get_credentials_file(const char *file, struct user_auth_info *info) +static void get_credentials_file(const char *file, struct cmdline_auth_info *info) { XFILE *auth; fstring buf; @@ -236,10 +242,8 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) } else if (strwicmp("username", param) == 0) pstrcpy(info->username, val); -#if 0 else if (strwicmp("domain", param) == 0) - set_global_myworkgroup(val); -#endif + pstrcpy(info->domain,val); memset(buf, 0, sizeof(buf)); } x_fclose(auth); @@ -250,13 +254,15 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) * -A,--authentication-file * -k,--use-kerberos * -N,--no-pass + * -S,--signing + * -P --machine-pass */ static void popt_common_credentials_callback(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, const void *data) + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) { char *p; @@ -268,8 +274,17 @@ static void popt_common_credentials_callback(poptContext con, if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); if (getenv("USER")) { + pstring tmp; + pstrcpy(cmdline_auth_info.username,getenv("USER")); + pstrcpy(tmp,cmdline_auth_info.username); + if ((p = strchr_m(tmp,'\\'))) { + *p = 0; + pstrcpy(cmdline_auth_info.domain,tmp); + pstrcpy(cmdline_auth_info.username,p+1); + } + if ((p = strchr_m(cmdline_auth_info.username,'%'))) { *p = 0; pstrcpy(cmdline_auth_info.password,p+1); @@ -278,6 +293,10 @@ static void popt_common_credentials_callback(poptContext con, } } + if (getenv("DOMAIN")) { + pstrcpy(cmdline_auth_info.domain,getenv("DOMAIN")); + } + if (getenv("PASSWD")) { pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); cmdline_auth_info.got_pass = True; @@ -295,8 +314,17 @@ static void popt_common_credentials_callback(poptContext con, case 'U': { char *lp; + pstring tmp; pstrcpy(cmdline_auth_info.username,arg); + + pstrcpy(tmp,cmdline_auth_info.username); + if ((p = strchr_m(tmp,'\\'))) { + *p = 0; + pstrcpy(cmdline_auth_info.domain,tmp); + pstrcpy(cmdline_auth_info.username,p+1); + } + if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { *lp = 0; pstrcpy(cmdline_auth_info.password,lp+1); @@ -319,6 +347,40 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.got_pass = True; #endif break; + + case 'S': + lp_set_cmdline("client signing", arg); + break; + + case 'P': + { + char *opt_password = NULL; + /* it is very useful to be able to make ads queries as the + machine account for testing purposes and for domain leave */ + + if (!secrets_init()) { + d_printf("ERROR: Unable to open secrets database\n"); + exit(1); + } + + opt_password = secrets_fetch_machine_password(lp_workgroup()); + + if (!opt_password) { + d_printf("ERROR: Unable to fetch machine password\n"); + exit(1); + } + pstr_sprintf(cmdline_auth_info.username, "%s$", + lp_netbios_name()); + pstrcpy(cmdline_auth_info.password,opt_password); + SAFE_FREE(opt_password); + + pstrcpy(cmdline_auth_info.password, lp_workgroup()); + + /* machine accounts only work with kerberos */ + cmdline_auth_info.use_kerberos = True; + cmdline_auth_info.got_pass = True; + } + break; } } @@ -330,5 +392,7 @@ struct poptOption popt_common_credentials[] = { { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, + { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, + { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, POPT_TABLEEND }; -- cgit From d139dc808abd7b3ee8c4721c6e4ce51894210598 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Aug 2004 12:18:07 +0000 Subject: r1912: move popt_common.h metze (This used to be commit ecf6be894fc47f9e00f46531e06ef20e11115c0f) --- source4/lib/cmdline/popt_common.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 source4/lib/cmdline/popt_common.h (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h new file mode 100644 index 0000000000..e41b1a2cf4 --- /dev/null +++ b/source4/lib/cmdline/popt_common.h @@ -0,0 +1,51 @@ +/* + Unix SMB/CIFS implementation. + Common popt arguments + Copyright (C) Jelmer Vernooij 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _POPT_COMMON_H +#define _POPT_COMMON_H + +#include "popt.h" + +/* Common popt structures */ +extern struct poptOption popt_common_samba[]; +extern struct poptOption popt_common_connection[]; +extern struct poptOption popt_common_version[]; +extern struct poptOption popt_common_credentials[]; + +#ifndef POPT_TABLEEND +#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL } +#endif + +#define POPT_COMMON_SAMBA { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_samba, 0, "Common samba options:", NULL }, +#define POPT_COMMON_CONNECTION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_connection, 0, "Connection options:", NULL }, +#define POPT_COMMON_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version, 0, "Common samba options:", NULL }, +#define POPT_COMMON_CREDENTIALS { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_credentials, 0, "Authentication options:", NULL }, + +struct cmdline_auth_info { + pstring username; + pstring password; + pstring domain; + BOOL got_pass; + BOOL use_kerberos; +}; + +extern struct cmdline_auth_info cmdline_auth_info; + +#endif /* _POPT_COMMON_H */ -- cgit From c2e2921bada17aae84e6c29f48401fa467e8ed9c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Aug 2004 09:48:25 +0000 Subject: r1949: provide functions to access the username, userdomain and userpassword now you're prompted when cmdline_get_userpassword() is called and the password is not yet known metze (This used to be commit d14a01533c5d465ff3709c48576b798b3be807e0) --- source4/lib/cmdline/popt_common.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index ef75d7be1f..20b9aac201 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -33,7 +33,7 @@ * -i,--scope */ -struct cmdline_auth_info cmdline_auth_info; +static struct cmdline_auth_info cmdline_auth_info; static void popt_common_callback(poptContext con, enum poptCallbackReason reason, @@ -396,3 +396,38 @@ struct poptOption popt_common_credentials[] = { { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, POPT_TABLEEND }; + +const char *cmdline_get_username(void) +{ + return cmdline_auth_info.username; +} + +const char *cmdline_get_userdomain(void) +{ + if (cmdline_auth_info.domain[0]) { + return cmdline_auth_info.domain; + } + + /* I think this should be lp_netbios_name() + * instead of lp_workgroup(), because if you're logged in + * as domain user the getenv("USER") contains the domain + * and this code path isn't used + * --metze + */ + return lp_netbios_name(); +} + +const char *cmdline_get_userpassword(void) +{ + pstring prompt; + + if (cmdline_auth_info.got_pass) { + return cmdline_auth_info.password; + } + + pstr_sprintf(prompt, "Password for [%s\\%s]:", + cmdline_get_userdomain(), + cmdline_get_username()); + + return getpass(prompt); +} -- cgit From 8115bf6e2ceba588b3d503380a530297b0f03f2c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Aug 2004 13:24:28 +0000 Subject: r1957: add cmdline_set_* functions and let smbclient use the cmdline _* functions metze (This used to be commit ffb87ebc33e728bf8506383f95b80605adec3c68) --- source4/lib/cmdline/popt_common.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 20b9aac201..7acdb34bba 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -397,11 +397,21 @@ struct poptOption popt_common_credentials[] = { POPT_TABLEEND }; +void cmdline_set_username(const char *name) +{ + pstrcpy(cmdline_auth_info.username, name); +} + const char *cmdline_get_username(void) { return cmdline_auth_info.username; } +void cmdline_set_userdomain(const char *domain) +{ + pstrcpy(cmdline_auth_info.domain, domain); +} + const char *cmdline_get_userdomain(void) { if (cmdline_auth_info.domain[0]) { @@ -431,3 +441,19 @@ const char *cmdline_get_userpassword(void) return getpass(prompt); } + +void cmdline_set_userpassword(const char *pass) +{ + cmdline_auth_info.got_pass = True; + pstrcpy(cmdline_auth_info.password, pass); +} + +void cmdline_set_use_kerberos(BOOL use_kerberos) +{ + cmdline_auth_info.use_kerberos = use_kerberos; +} + +BOOL cmdline_get_use_kerberos(void) +{ + return cmdline_auth_info.use_kerberos; +} -- cgit From e205ffd83c36c485bcd07de318e0a1bb506f8415 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 20 Aug 2004 22:49:45 +0000 Subject: r1972: cmdline_auth_info does not need to be declared global (This used to be commit d07dbdb22acc4c9cafb7141486fbf162d9f8164e) --- source4/lib/cmdline/popt_common.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index e41b1a2cf4..bedf8f7f5d 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -46,6 +46,4 @@ struct cmdline_auth_info { BOOL use_kerberos; }; -extern struct cmdline_auth_info cmdline_auth_info; - #endif /* _POPT_COMMON_H */ -- cgit From 43afd3fda8c0aba14b2f41778b050c0a93d64253 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 20 Aug 2004 22:50:33 +0000 Subject: r1973: for systems that don't have strtoull() try strtouq(). This should fix the build for some BSD varients. (This used to be commit 73e9ee791472bb212efe0eb4744daa91678263ad) --- source4/lib/replace.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index de32d377d5..64234f7042 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -468,3 +468,15 @@ char *rep_inet_ntoa(struct in_addr ip) return ret; } #endif + + +#ifndef HAVE_STRTOULL + unsigned long long int strtoull(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOUQ + return strtouq(str, endptr, base); +#else +#error "system must support 64 bit integer read from strings" +#endif +} +#endif -- cgit From b83ba93eaeb2dcb0bf11615591d886fda84e4162 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Aug 2004 01:54:46 +0000 Subject: r1983: a completely new implementation of talloc This version does the following: 1) talloc_free(), talloc_realloc() and talloc_steal() lose their (redundent) first arguments 2) you can use _any_ talloc pointer as a talloc context to allocate more memory. This allows you to create complex data structures where the top level structure is the logical parent of the next level down, and those are the parents of the level below that. Then destroy either the lot with a single talloc_free() or destroy any sub-part with a talloc_free() of that part 3) you can name any pointer. Use talloc_named() which is just like talloc() but takes the printf style name argument as well as the parent context and the size. The whole thing ends up being a very simple piece of code, although some of the pointer walking gets hairy. So far, I'm just using the new talloc() like the old one. The next step is to actually take advantage of the new interface properly. Expect some new commits soon that simplify some common coding styles in samba4 by using the new talloc(). (This used to be commit e35bb094c52e550b3105dd1638d8d90de71d854f) --- source4/lib/data_blob.c | 2 +- source4/lib/registry/common/reg_interface.c | 2 +- .../lib/registry/reg_backend_dir/reg_backend_dir.c | 2 +- .../registry/reg_backend_gconf/reg_backend_gconf.c | 4 +- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 2 +- source4/lib/talloc.c | 557 ++++++++------------- source4/lib/tallocmsg.c | 5 +- source4/lib/util_str.c | 2 +- source4/lib/util_unistr.c | 8 - source4/lib/util_uuid.c | 2 +- 10 files changed, 210 insertions(+), 376 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index ee7bffdc1b..bc5cf9abc8 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -108,7 +108,7 @@ DATA_BLOB data_blob_talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, { DATA_BLOB new; new = *old; - new.data = talloc_steal(old_ctx, new_ctx, old->data); + new.data = talloc_steal(new_ctx, old->data); if (new.data == NULL) { smb_panic("data_blob_talloc_steal: talloc_steal failed.\n"); } diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 0a0cf05c2e..e7024d23fe 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -214,7 +214,7 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; - talloc_steal(mem_ctx, (*result)->mem_ctx, fullname); + talloc_steal((*result)->mem_ctx, fullname); talloc_destroy(mem_ctx); diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index cac54f8437..b2bd34bf71 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -65,7 +65,7 @@ static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KE } closedir(d); ret = reg_key_new_abs(name, h, fullpath); - talloc_steal(mem_ctx, ret->mem_ctx, fullpath); + talloc_steal(ret->mem_ctx, fullpath); talloc_destroy(mem_ctx); *subkey = ret; return WERR_OK; diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index c705a2e3cb..15a8319711 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -126,7 +126,7 @@ static WERROR gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) } else newval->data_type = REG_NONE; ar[(*count)] = newval; - ar = talloc_realloc(p->mem_ctx, ar, sizeof(REG_VAL *) * ((*count)+2)); + ar = talloc_realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); (*count)++; g_free(cur->data); cur = cur->next; @@ -151,7 +151,7 @@ static WERROR gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) ar[(*count)] = reg_key_new_abs(winpath, p->handle,NULL); free(winpath); ar[(*count)]->backend_data = reg_path_win2unix(talloc_strdup(ar[*count]->mem_ctx, cur->data)); - ar = talloc_realloc_p(p->mem_ctx, ar, REG_KEY *, (*count)+2); + ar = talloc_realloc_p(ar, REG_KEY *, (*count)+2); (*count)++; g_free(cur->data); cur = cur->next; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 9dfd3329e0..fa7e22d010 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -188,7 +188,7 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k } *key = reg_key_new_abs(name, h, ldap_path); - talloc_steal(mem_ctx, (*key)->mem_ctx, ldap_path); + talloc_steal((*key)->mem_ctx, ldap_path); printf("Got something!\n"); /* FIXME */ diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 21c3bdac6e..8a67f83a7f 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -1,8 +1,9 @@ /* Samba Unix SMB/CIFS implementation. - Samba temporary memory allocation functions - Copyright (C) Andrew Tridgell 2000-2004 - Copyright (C) 2001, 2002 by Martin Pool + + Samba temporary memory allocation functions - new interface + + Copyright (C) Andrew Tridgell 2004 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 @@ -19,208 +20,175 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** - @defgroup talloc Simple memory allocator - @{ - - This is a very simple temporary memory allocator. To use it do the following: - - 1) when you first want to allocate a pool of meomry use - talloc_init() and save the resulting context pointer somewhere - - 2) to allocate memory use talloc() - - 3) when _all_ of the memory allocated using this context is no longer needed - use talloc_destroy() - - talloc does not zero the memory. - - @sa talloc.h -*/ - -/** - * If you want testing for memory corruption use valgrind - **/ - #include "includes.h" #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0x06052004 +#define TALLOC_MAGIC 0x14082004 #define TALLOC_MAGIC_FREE 0x3421abcd struct talloc_chunk { struct talloc_chunk *next, *prev; - TALLOC_CTX *context; + struct talloc_chunk *parent, *child; size_t size; - void *ptr; uint_t magic; + char *name; }; -struct talloc_ctx { - struct talloc_chunk *list; - off_t total_alloc_size; - - /** The name recorded for this pool, if any. Should describe - * the purpose for which it was allocated. The string is - * allocated within the pool. **/ - char *name; +/* + Allocate a bit of memory as a child of an existing pointer +*/ +void *talloc(void *context, size_t size) +{ + struct talloc_chunk *tc; - /** Pointer to the next allocate talloc pool, so that we can - * summarize all talloc memory usage. **/ - struct talloc_ctx *next, *prev; -}; + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + tc = malloc(sizeof(*tc)+size); + if (tc == NULL) { + return NULL; + } -/** - * Start of linked list of all talloc pools. - * - * @todo We should turn the global list off when using Insure++, - * otherwise all the memory will be seen as still reachable. - **/ -static TALLOC_CTX *list_head; + tc->size = size; + tc->magic = TALLOC_MAGIC; + tc->child = NULL; + tc->name = NULL; -/** - * Add to the global list - **/ -static void talloc_enroll(TALLOC_CTX *t) -{ -#if 0 - /* disabled enrole/disenrole until we have __thread support */ - MUTEX_LOCK_BY_ID(MUTEX_TALLOC); - DLIST_ADD(list_head, t); - MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); -#endif -} + if (context) { + struct talloc_chunk *parent = ((struct talloc_chunk *)context)-1; + if (parent->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad magic in context - 0x%08x\n", parent->magic)); + free(tc); + return NULL; + } -static void talloc_disenroll(TALLOC_CTX *t) -{ -#if 0 - /* disabled enrole/disenrole until we have __thread support */ - MUTEX_LOCK_BY_ID(MUTEX_TALLOC); - DLIST_REMOVE(list_head, t); - MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); -#endif -} + tc->parent = parent; + if (parent->child) { + parent->child->parent = NULL; + } -/** Create a new talloc context. **/ -static TALLOC_CTX *talloc_init_internal(void) -{ - TALLOC_CTX *t; - - t = (TALLOC_CTX *)malloc(sizeof(TALLOC_CTX)); - if (t) { - t->list = NULL; - t->total_alloc_size = 0; - t->name = NULL; - talloc_enroll(t); + DLIST_ADD(parent->child, tc); + } else { + tc->next = tc->prev = tc->parent = NULL; } - return t; + return (void *)(tc+1); } - -/** - * Create a new talloc context, with a name specifying its purpose. - **/ - - TALLOC_CTX *talloc_init(char const *fmt, ...) +/* + create a named talloc pointer +*/ +void *talloc_named(void *context, size_t size, + const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4) { - TALLOC_CTX *t; va_list ap; + void *ptr; + struct talloc_chunk *tc; - t = talloc_init_internal(); - if (t && fmt) { - /* - * t->name must not be talloced. - * as destroying the pool would destroy it. JRA. - */ - t->name = NULL; - va_start(ap, fmt); - vasprintf(&t->name, fmt, ap); - va_end(ap); - if (!t->name) { - talloc_destroy(t); - t = NULL; - } + ptr = talloc(context, size); + if (ptr == NULL) { + return NULL; } - - return t; -} + tc = ((struct talloc_chunk *)ptr)-1; + + va_start(ap, fmt); + vasprintf(&tc->name, fmt, ap); + va_end(ap); + + return ptr; +} /* - return the talloc context given a pointer that has been allocated using - talloc + this is for compatibility with older versions of talloc */ -TALLOC_CTX *talloc_get_context(void *ptr) +void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) { + va_list ap; + void *ptr; struct talloc_chunk *tc; - tc = ((struct talloc_chunk *)ptr)-1; - if (tc->magic == TALLOC_MAGIC) { - return tc->context; - } else { + ptr = talloc(NULL, 0); + if (ptr == NULL) { return NULL; } + + tc = ((struct talloc_chunk *)ptr)-1; + + va_start(ap, fmt); + vasprintf(&tc->name, fmt, ap); + va_end(ap); + + return ptr; } -/** Allocate a bit of memory from the specified pool **/ -void *talloc(TALLOC_CTX *t, size_t size) + + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively +*/ +void talloc_free(void *ptr) { struct talloc_chunk *tc; - if (!t || size == 0) { - return NULL; - } + if (ptr == NULL) return; - tc = malloc(sizeof(*tc)+size); - if (!tc) { - return NULL; + tc = ((struct talloc_chunk *)ptr)-1; + + if (tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad talloc magic 0x%08x in talloc_free\n", tc->magic)); + return; } - tc->context = t; - tc->size = size; - tc->magic = TALLOC_MAGIC; + while (tc->child) { + talloc_free(tc->child + 1); + } - DLIST_ADD(t->list, tc); + if (tc->parent) { + DLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } - t->total_alloc_size += size; + tc->magic = TALLOC_MAGIC_FREE; + if (tc->name) free(tc->name); - return (void *)(tc+1); + free(tc); } -/** A talloc version of realloc */ -void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size) + + +/* + A talloc version of realloc +*/ +void *talloc_realloc(void *ptr, size_t size) { struct talloc_chunk *tc; void *new_ptr; /* size zero is equivalent to free() */ - if (!t) { - return NULL; - } - if (size == 0) { - talloc_free(t, ptr); + talloc_free(ptr); return NULL; } /* realloc(NULL) is equavalent to malloc() */ if (ptr == NULL) { - return talloc(t, size); + return talloc(NULL, size); } tc = ((struct talloc_chunk *)ptr)-1; - if (tc->context != t) { - DEBUG(0,("Bad talloc context passed to talloc_realloc\n")); - return NULL; - } - if (tc->magic != TALLOC_MAGIC) { DEBUG(0,("Bad talloc magic 0x%08x in talloc_realloc\n", tc->magic)); return NULL; @@ -235,11 +203,11 @@ void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size) return NULL; } - if (tc == t->list) { - t->list = new_ptr; - } tc = new_ptr; tc->magic = TALLOC_MAGIC; + if (tc->parent) { + tc->parent->child = new_ptr; + } if (tc->prev) { tc->prev->next = tc; @@ -248,129 +216,74 @@ void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size) tc->next->prev = tc; } - t->total_alloc_size += (size - tc->size); tc->size = size; return (void *)(tc+1); } /* - free a lump from a pool. Use sparingly please. + move a lump of memory from one talloc context to another return the + ptr on success, or NUL if it could not be transferred */ -void talloc_free(TALLOC_CTX *ctx, void *ptr) +void *talloc_steal(void *new_ctx, void *ptr) { - struct talloc_chunk *tc; - - if (!ptr || !ctx->list) return; - - tc = ((struct talloc_chunk *)ptr)-1; - - if (tc->context != ctx) { - DEBUG(0,("Bad talloc context passed to talloc_free\n")); - } - - if (tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad talloc magic 0x%08x in talloc_free\n", tc->magic)); - } - - DLIST_REMOVE(ctx->list, tc); - - ctx->total_alloc_size -= tc->size; - tc->magic = TALLOC_MAGIC_FREE; - - free(tc); -} - - -/* - move a lump of memory from one talloc context to another - return the ptr on success, or NULL if it could not be found - in the old context or could not be transferred -*/ -void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, void *ptr) -{ - struct talloc_chunk *tc; + struct talloc_chunk *tc, *new_tc; if (!ptr) { return NULL; } tc = ((struct talloc_chunk *)ptr)-1; - - if (tc->context != old_ctx) { - DEBUG(0,("Bad talloc context passed to talloc_steal\n")); - return NULL; - } + new_tc = ((struct talloc_chunk *)new_ctx)-1; if (tc->magic != TALLOC_MAGIC) { DEBUG(0,("Bad talloc magic 0x%08x in talloc_steal\n", tc->magic)); return NULL; } - - DLIST_REMOVE(old_ctx->list, tc); - DLIST_ADD(new_ctx->list, tc); - - tc->context = new_ctx; - - old_ctx->total_alloc_size -= tc->size; - new_ctx->total_alloc_size += tc->size; - - return ptr; -} - - - -/** Destroy all the memory allocated inside @p t, but not @p t - * itself. */ -void talloc_destroy_pool(TALLOC_CTX *t) -{ - if (!t) { - return; + if (new_tc->magic != TALLOC_MAGIC) { + DEBUG(0,("Bad new talloc magic 0x%08x in talloc_steal\n", new_tc->magic)); + return NULL; } - while (t->list) { - struct talloc_chunk *tc = t->list; - if (tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad magic 0x%08x in talloc_destroy_pool\n", - tc->magic)); - return; + if (tc->parent) { + DLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; } - DLIST_REMOVE(t->list, tc); - tc->magic = TALLOC_MAGIC_FREE; - free(tc); + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; } - t->total_alloc_size = 0; -} - -/** Destroy a whole pool including the context */ -void talloc_destroy(TALLOC_CTX *t) -{ - if (!t) - return; + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + DLIST_ADD(new_tc->child, tc); - talloc_destroy_pool(t); - talloc_disenroll(t); - SAFE_FREE(t->name); - SAFE_FREE(t); + return ptr; } -/** Return the current total size of the pool. */ -size_t talloc_pool_size(TALLOC_CTX *t) +/* + return the total size of a talloc pool (subtree) +*/ +off_t talloc_total_size(void *p) { - return t->total_alloc_size; -} + off_t total = 0; + struct talloc_chunk *c, *tc; -const char *talloc_pool_name(TALLOC_CTX const *t) -{ - if (t) return t->name; + tc = ((struct talloc_chunk *)p)-1; - return NULL; + total = tc->size; + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(c+1); + } + return total; } -/** talloc and zero memory. */ -void *talloc_zero(TALLOC_CTX *t, size_t size) +/* + talloc and zero memory. +*/ +void *talloc_zero(void *t, size_t size) { void *p = talloc(t, size); @@ -382,8 +295,10 @@ void *talloc_zero(TALLOC_CTX *t, size_t size) } -/** memdup with a talloc. */ -void *talloc_memdup(TALLOC_CTX *t, const void *p, size_t size) +/* + memdup with a talloc. +*/ +void *talloc_memdup(void *t, const void *p, size_t size) { void *newp = talloc(t,size); @@ -394,8 +309,10 @@ void *talloc_memdup(TALLOC_CTX *t, const void *p, size_t size) return newp; } -/** strdup with a talloc */ -char *talloc_strdup(TALLOC_CTX *t, const char *p) +/* + strdup with a talloc +*/ +char *talloc_strdup(void *t, const char *p) { if (!p) { return NULL; @@ -403,8 +320,10 @@ char *talloc_strdup(TALLOC_CTX *t, const char *p) return talloc_memdup(t, p, strlen(p) + 1); } -/** strndup with a talloc */ -char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) +/* + strndup with a talloc +*/ +char *talloc_strndup(void *t, const char *p, size_t n) { size_t len = strnlen(p, n); char *ret; @@ -416,23 +335,7 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) return ret; } -/** - * Perform string formatting, and return a pointer to newly allocated - * memory holding the result, inside a memory pool. - **/ - char *talloc_asprintf(TALLOC_CTX *t, const char *fmt, ...) -{ - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = talloc_vasprintf(t, fmt, ap); - va_end(ap); - return ret; -} - - - char *talloc_vasprintf(TALLOC_CTX *t, const char *fmt, va_list ap) + char *talloc_vasprintf(void *t, const char *fmt, va_list ap) { int len; char *ret; @@ -452,31 +355,29 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) } -/** - * Realloc @p s to append the formatted result of @p fmt and return @p - * s, which may have moved. Good for gradually accumulating output - * into a string buffer. - **/ - char *talloc_asprintf_append(TALLOC_CTX *t, char *s, - const char *fmt, ...) +/* + Perform string formatting, and return a pointer to newly allocated + memory holding the result, inside a memory pool. + */ +char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) { va_list ap; + char *ret; va_start(ap, fmt); - s = talloc_vasprintf_append(t, s, fmt, ap); + ret = talloc_vasprintf(t, fmt, ap); va_end(ap); - return s; + return ret; } - /** * Realloc @p s to append the formatted result of @p fmt and @p ap, * and return @p s, which may have moved. Good for gradually * accumulating output into a string buffer. **/ - char *talloc_vasprintf_append(TALLOC_CTX *t, char *s, - const char *fmt, va_list ap) +char *talloc_vasprintf_append(char *s, + const char *fmt, va_list ap) { int len, s_len; va_list ap2; @@ -486,11 +387,11 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) if (s) { s_len = strlen(s); } else { - s = 0; + s_len = 0; } len = vsnprintf(NULL, 0, fmt, ap2); - s = talloc_realloc(t, s, s_len + len+1); + s = talloc_realloc(s, s_len + len+1); if (!s) return NULL; VA_COPY(ap2, ap); @@ -500,109 +401,45 @@ char *talloc_strndup(TALLOC_CTX *t, const char *p, size_t n) return s; } - -/** - * Return a human-readable description of all talloc memory usage. - * The result is allocated from @p t. - **/ -char *talloc_describe_all(TALLOC_CTX *rt) +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a string buffer. + */ +char *talloc_asprintf_append(char *s, + const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) { - int n_pools = 0, total_chunks = 0; - size_t total_bytes = 0; - TALLOC_CTX *it; - char *s; - - if (!rt) return NULL; - - s = talloc_asprintf(rt, "global talloc allocations in pid: %u\n", - (uint_t) getpid()); - s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", - "name", "chunks", "bytes"); - s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", - "----------------------------------------", - "--------", - "--------"); - MUTEX_LOCK_BY_ID(MUTEX_TALLOC); - - for (it = list_head; it; it = it->next) { - size_t bytes; - int n_chunks; - fstring what; - - n_pools++; - - talloc_get_allocation(it, &bytes, &n_chunks); - - if (it->name) - fstrcpy(what, it->name); - else - slprintf(what, sizeof(what), "@%p", it); - - s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", - what, - (uint_t) n_chunks, - (uint_t) bytes); - total_bytes += bytes; - total_chunks += n_chunks; - } - - MUTEX_UNLOCK_BY_ID(MUTEX_TALLOC); - - s = talloc_asprintf_append(rt, s, "%-40s %8s %8s\n", - "----------------------------------------", - "--------", - "--------"); - - s = talloc_asprintf_append(rt, s, "%-40s %8u %8u\n", - "TOTAL", - (uint_t) total_chunks, (uint_t) total_bytes); + va_list ap; + va_start(ap, fmt); + s = talloc_vasprintf_append(s, fmt, ap); + va_end(ap); return s; } - - -/** - * Return an estimated memory usage for the specified pool. This does - * not include memory used by the underlying malloc implementation. - **/ -void talloc_get_allocation(TALLOC_CTX *t, - size_t *total_bytes, - int *n_chunks) -{ - struct talloc_chunk *tc; - - if (t) { - *total_bytes = 0; - *n_chunks = 0; - - for (tc = t->list; tc; tc = tc->next) { - n_chunks[0]++; - *total_bytes += tc->size; - } - } -} - /* - realloc an array, checking for integer overflow in the array size + alloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, uint_t count) +void *talloc_array(void *ctx, size_t el_size, uint_t count) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - return talloc_realloc(ctx, ptr, el_size * count); + return talloc(ctx, el_size * count); } /* - we really should get rid of this + realloc an array, checking for integer overflow in the array size */ -void *talloc_strdup_w(TALLOC_CTX *mem_ctx, void *s) +void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count) { - size_t len = strlen_w(s); - return talloc_memdup(mem_ctx, s, (len+1)*2); + if (count == 0 || + count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return talloc_realloc(ptr, el_size * count); } /* @@ -610,8 +447,12 @@ void *talloc_strdup_w(TALLOC_CTX *mem_ctx, void *s) */ void *talloc_ldb_alloc(void *context, void *ptr, size_t size) { - return talloc_realloc((TALLOC_CTX *)context, ptr, size); + if (ptr == NULL) { + return talloc(context, size); + } + if (size == 0) { + talloc_free(ptr); + return NULL; + } + return talloc_realloc(ptr, size); } - - -/** @} */ diff --git a/source4/lib/tallocmsg.c b/source4/lib/tallocmsg.c index bbe1ee60a4..22870a934a 100644 --- a/source4/lib/tallocmsg.c +++ b/source4/lib/tallocmsg.c @@ -33,15 +33,16 @@ void msg_pool_usage(int msg_type, pid_t src_pid, void *UNUSED(buf), size_t UNUSED(len)) { - char *reply; + const char *reply="NOT IMPLEMENTED\n"; TALLOC_CTX *reply_pool = talloc_init("msg_pool_usage"); SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); DEBUG(2,("Got POOL_USAGE\n")); +#if 0 reply = talloc_describe_all(reply_pool); - +#endif message_send_pid(src_pid, MSG_POOL_USAGE, reply, strlen(reply)+1, True); diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index a6f54f9a8d..a66a363c17 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1452,7 +1452,7 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx, { char *dup_str = talloc_strdup(mem_ctx, str); - *strings = talloc_realloc(mem_ctx, *strings, + *strings = talloc_realloc(*strings, ((*num)+1) * sizeof(**strings)); if ((*strings == NULL) || (dup_str == NULL)) diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 09a1c9a4df..2bd990836e 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -249,14 +249,6 @@ const smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) return NULL; } -static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) -{ - size_t n = 0; - while ((n < len) && *b && *a == *b) { a++; b++; n++;} - return (len - n)?(*a - *b):0; -} - - /******************************************************************* Convert a string to lower case. return True if any char is converted diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 156f20e53e..a11b7bd3ed 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -24,7 +24,7 @@ void uuid_generate_random(struct GUID *out) { - generate_random_buffer(out, sizeof(struct GUID)); + generate_random_buffer((unsigned char *)out, sizeof(struct GUID)); out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; } -- cgit From b7e1ea20dc873a753ff64653987130f03897a4e9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Aug 2004 07:43:29 +0000 Subject: r1985: take advantage of the new talloc in a few more places (This used to be commit 6ffdfd779936ce8c5ca49c5f444e8da2bbeee0a8) --- source4/lib/talloc.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 8a67f83a7f..b01bcb27c8 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -20,6 +20,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + inspired by http://swapped.cc/halloc/ +*/ + #include "includes.h" #define MAX_TALLOC_SIZE 0x10000000 @@ -81,24 +85,49 @@ void *talloc(void *context, size_t size) /* - create a named talloc pointer + add a name to an existing pointer - va_list version +*/ +static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc; + + tc = ((struct talloc_chunk *)ptr)-1; + if (tc->magic != TALLOC_MAGIC) { + return; + } + + vasprintf(&tc->name, fmt, ap); +} + +/* + add a name to an existing pointer +*/ +void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) +{ + va_list ap; + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. */ void *talloc_named(void *context, size_t size, const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4) { va_list ap; void *ptr; - struct talloc_chunk *tc; ptr = talloc(context, size); if (ptr == NULL) { return NULL; } - tc = ((struct talloc_chunk *)ptr)-1; - va_start(ap, fmt); - vasprintf(&tc->name, fmt, ap); + talloc_set_name_v(ptr, fmt, ap); va_end(ap); return ptr; -- cgit From ca885cb2d1b0165a6e8c819b82ad9d13de9643ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 21 Aug 2004 18:15:07 +0000 Subject: r1989: fixed a couple of bugs in code that assumes sizeof(time_t) == sizeof(int) (This used to be commit cc3d420c33152c8e9026dc39a7322d11edb3c774) --- source4/lib/gencache.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index f3740e3e12..1a66d8dc3d 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -250,13 +250,15 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) char* entry_buf = strndup(databuf.dptr, databuf.dsize); char *v; time_t t; + unsigned i; v = (char*)malloc(sizeof(char) * (databuf.dsize - TIMEOUT_LEN)); SAFE_FREE(databuf.dptr); - sscanf(entry_buf, CACHE_DATA_FMT, (int*)&t, v); + sscanf(entry_buf, CACHE_DATA_FMT, (int*)&i, v); SAFE_FREE(entry_buf); + t = i; DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " "timeout = %s\n", t > time(NULL) ? "valid" : @@ -307,6 +309,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time TDB_DATA databuf; char *keystr = NULL, *valstr = NULL, *entry = NULL; time_t timeout = 0; + unsigned i; /* fail completely if get null pointers passed */ SMB_ASSERT(fn && keystr_pattern); @@ -335,7 +338,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time entry = strndup(databuf.dptr, databuf.dsize); SAFE_FREE(databuf.dptr); valstr = (char*)malloc(sizeof(char) * (databuf.dsize - TIMEOUT_LEN)); - sscanf(entry, CACHE_DATA_FMT, (int*)(&timeout), valstr); + sscanf(entry, CACHE_DATA_FMT, (int*)(&i), valstr); + timeout = i; DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n", keystr, valstr, ctime(&timeout))); -- cgit From dcd43a4cbef3bee948bdbd65212361b6043aa4bd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 22 Aug 2004 05:33:07 +0000 Subject: r1990: Fix breakage caused by the recent talloc changes. (Failure to process an SPNEGO login from WinXP at least). talloc_asprintf_append() lost an argument, but because TALLOC_CTX is now a void*, this was not picked up by the compiler. I've tested the login (asn1), but not the registry/gtk changes. Andrew Bartlett (This used to be commit 4294be44057124568fe1d176702056bb62ad3214) --- source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index fa7e22d010..6945ebdb55 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -28,7 +28,7 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * char *end = mypath, *begin; if(add) - ret = talloc_asprintf_append(mem_ctx, ret, "%s", add); + ret = talloc_asprintf_append(ret, "%s", add); while(end) { char *keyname; @@ -38,7 +38,7 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * else keyname = mypath; if(strlen(keyname)) - ret = talloc_asprintf_append(mem_ctx, ret, "key=%s,", keyname); + ret = talloc_asprintf_append(ret, "key=%s,", keyname); if(begin) { begin[0] = '\0'; -- cgit From 39a3d5eedc04a365cf2df215a39bec4fc8e170f0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 22 Aug 2004 05:35:43 +0000 Subject: r1991: After finding a talloc inconsistancy is a very good time to smb_panic(), it can only indicate programmer error, and doing a smb_panic() ensures an automatic backtrace (and eventually an abort()). Andrew Bartlett (This used to be commit b2d93d0010d80f158760f53273853de2439c3062) --- source4/lib/talloc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index b01bcb27c8..4a48347832 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -66,6 +66,7 @@ void *talloc(void *context, size_t size) if (parent->magic != TALLOC_MAGIC) { DEBUG(0,("Bad magic in context - 0x%08x\n", parent->magic)); free(tc); + smb_panic("Bad magic in talloc context"); return NULL; } @@ -172,6 +173,7 @@ void talloc_free(void *ptr) if (tc->magic != TALLOC_MAGIC) { DEBUG(0,("Bad talloc magic 0x%08x in talloc_free\n", tc->magic)); + smb_panic("Bad talloc magic in talloc_realloc"); return; } @@ -219,8 +221,14 @@ void *talloc_realloc(void *ptr, size_t size) tc = ((struct talloc_chunk *)ptr)-1; if (tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad talloc magic 0x%08x in talloc_realloc\n", tc->magic)); - return NULL; + if (tc->magic == TALLOC_MAGIC_FREE) { + + DEBUG(0,("Bad talloc magic - magic 0x%08x indicates double-free in talloc_realloc\n", tc->magic)); + smb_panic("Bad talloc magic - double-free - in talloc_realloc"); + } else { + DEBUG(0,("Bad talloc magic 0x%08x in talloc_realloc\n", tc->magic)); + smb_panic("Bad talloc magic in talloc_realloc"); + } } /* by resetting magic we catch users of the old memory */ @@ -267,10 +275,12 @@ void *talloc_steal(void *new_ctx, void *ptr) if (tc->magic != TALLOC_MAGIC) { DEBUG(0,("Bad talloc magic 0x%08x in talloc_steal\n", tc->magic)); + smb_panic("Bad talloc magic in talloc_steal"); return NULL; } if (new_tc->magic != TALLOC_MAGIC) { DEBUG(0,("Bad new talloc magic 0x%08x in talloc_steal\n", new_tc->magic)); + smb_panic("Bad new talloc magic in talloc_steal"); return NULL; } -- cgit From 694ac65faa13cc016f54330b656e64225aa40aab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 24 Aug 2004 01:32:12 +0000 Subject: r2003: got rid of next_token_nr(), which involved some horrible globals and nasy pointer tricks. this involved fixing some of the internals of smbclient (This used to be commit 126fec6169f9412932c82e7675840476132bce87) --- source4/lib/cmdline/readline.c | 2 +- source4/lib/util_str.c | 25 +++---------------------- 2 files changed, 4 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index c5da88b3e0..97201d00bb 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -140,7 +140,7 @@ void smb_readline_ca_char(char c) /**************************************************************************** history ****************************************************************************/ -int cmd_history(void) +int cmd_history(const char **cmd_ptr) { #if defined(HAVE_LIBREADLINE) HIST_ENTRY **hlist; diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index a66a363c17..fc76aed44a 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -67,25 +67,6 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) return(True); } -/** -This is like next_token but is not re-entrant and "remembers" the first -parameter so you can pass NULL. This is useful for user interface code -but beware the fact that it is not re-entrant! -**/ - -static char *last_ptr=NULL; - -BOOL next_token_nr(const char **ptr, char *buff, const char *sep, size_t bufsize) -{ - BOOL ret; - if (!ptr) - ptr = (const char **)&last_ptr; - - ret = next_token(ptr, buff, sep, bufsize); - last_ptr = *ptr; - return ret; -} - static uint16_t tmpbuf[sizeof(pstring)]; /** @@ -93,9 +74,9 @@ static uint16_t tmpbuf[sizeof(pstring)]; Uses last_ptr from above - bit of a hack. **/ -char **toktocliplist(int *ctok, const char *sep) +char **toktocliplist(const char *ptr, int *ctok, const char *sep) { - char *s=last_ptr; + char *s = ptr; int ictok=0; char **ret, **iret; @@ -118,7 +99,7 @@ char **toktocliplist(int *ctok, const char *sep) } while(*s); *ctok=ictok; - s=last_ptr; + s = ptr; if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL; -- cgit From 527bafcf73a1daea0a7a19f0181d811cabea451d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Aug 2004 15:38:57 +0000 Subject: r2017: fix compiler warnings metze (This used to be commit eb75d9323fb07fe9a19bbf77168aeb8a4b92c3b8) --- source4/lib/dprintf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/dprintf.c b/source4/lib/dprintf.c index 70387bbd61..fe939f0e8d 100644 --- a/source4/lib/dprintf.c +++ b/source4/lib/dprintf.c @@ -35,7 +35,7 @@ { char *p, *p2; int ret, maxlen, clen; - const char *msgstr; + char *msgstr; va_list ap2; /* do any message translations */ -- cgit From 85d8d24d3dd5e84c465050a2440d9a21c970c826 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Aug 2004 01:12:59 +0000 Subject: r2034: Allow user-selectable hash functions on open only. Jeremy. (This used to be commit b43320ee5c9ac14c330e61ae62e0786b088e04fa) --- source4/lib/tdb/common/tdb.c | 32 +++++++++++++++++--------------- source4/lib/tdb/include/tdb.h | 5 ++++- source4/lib/tdb_helper.c | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index ef13955fab..b9ca46c322 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -331,7 +331,7 @@ static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) } /* This is based on the hash algorithm from gdbm */ -static u32 tdb_hash(TDB_DATA *key) +static u32 default_tdb_hash(TDB_DATA *key) { u32 value; /* Used to compute the hash value. */ u32 i; /* Used to cycle through random values. */ @@ -1171,7 +1171,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) u32 hash; /* find which hash bucket it is in */ - hash = tdb_hash(&key); + hash = tdb->hash_fn(&key); if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; @@ -1203,7 +1203,7 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) { - u32 hash = tdb_hash(&key); + u32 hash = tdb->hash_fn(&key); return tdb_exists_hash(tdb, key, hash); } @@ -1463,7 +1463,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) if (!tdb->travlocks.off) { /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec); + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); if (!tdb->travlocks.off) return tdb_null; tdb->travlocks.hash = BUCKET(rec.full_hash); @@ -1507,7 +1507,7 @@ static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) { - u32 hash = tdb_hash(&key); + u32 hash = tdb->hash_fn(&key); return tdb_delete_hash(tdb, key, hash); } @@ -1525,7 +1525,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) int ret = 0; /* find which hash bucket it is in */ - hash = tdb_hash(&key); + hash = tdb->hash_fn(&key); if (!tdb_keylocked(tdb, hash)) return -1; if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) @@ -1643,7 +1643,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) size_t new_data_size = 0; /* find which hash bucket it is in */ - hash = tdb_hash(&key); + hash = tdb->hash_fn(&key); if (!tdb_keylocked(tdb, hash)) return -1; if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) @@ -1752,13 +1752,14 @@ static int tdb_already_open(dev_t device, TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) { - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL); + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); } TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - tdb_log_func log_fn) + tdb_log_func log_fn, + tdb_hash_func hash_fn) { TDB_CONTEXT *tdb; struct stat st; @@ -1778,7 +1779,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->flags = tdb_flags; tdb->open_flags = open_flags; tdb->log_fn = log_fn; - + tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + if ((open_flags & O_ACCMODE) == O_WRONLY) { TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", name)); @@ -2023,7 +2025,7 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) /* Insertion sort by bucket */ for (i = 0; i < number; i++) { - hash = tdb_hash(&keys[i]); + hash = tdb->hash_fn(&keys[i]); for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++); memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j)); tdb->lockedkeys[j+1] = hash; @@ -2058,22 +2060,22 @@ void tdb_unlockkeys(TDB_CONTEXT *tdb) contention - it cannot guarantee how many records will be locked */ int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) { - return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); } int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) { - return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); } int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) { - return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); } int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) { - return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); } diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 73a0ea8f83..02b89087a8 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -102,6 +102,7 @@ typedef struct tdb_context { dev_t device; /* uniquely identifies this tdb */ ino_t inode; /* uniquely identifies this tdb */ void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ + u32 (*hash_fn)(TDB_DATA *key); int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; @@ -109,12 +110,14 @@ void tdb_debug(TDB_CONTEXT *, int , const char *, ...); typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); +typedef u32 (*tdb_hash_func)(TDB_DATA *key); TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode); TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - tdb_log_func log_fn); + tdb_log_func log_fn, + tdb_hash_func hash_fn); int tdb_reopen(TDB_CONTEXT *tdb); int tdb_reopen_all(void); diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c index 121243bd0f..22c4d1bb45 100644 --- a/source4/lib/tdb_helper.c +++ b/source4/lib/tdb_helper.c @@ -59,7 +59,7 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, tdb_flags |= TDB_NOMMAP; tdb = tdb_open_ex(name, hash_size, tdb_flags, - open_flags, mode, tdb_log); + open_flags, mode, tdb_log, NULL); if (!tdb) return NULL; -- cgit From 600144050ce8e4515937c87be8d2c86c2c337364 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Aug 2004 02:07:20 +0000 Subject: r2039: got rid of the free() ptr in DATA_BLOB I plan on replacing the concept by adding a generic destructor in all talloc ptrs, so you can do: talloc_set_destructor(ptr, my_destructor); to setup a function that will be called on free. (This used to be commit 957b260621c091830c01e9e8c370c199350342ec) --- source4/lib/data_blob.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index bc5cf9abc8..92950298aa 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -21,16 +21,6 @@ #include "includes.h" -/******************************************************************* - free() a data blob -*******************************************************************/ -static void free_data_blob(DATA_BLOB *d) -{ - if ((d) && (d->free)) { - SAFE_FREE(d->data); - } -} - /******************************************************************* construct a data blob, must be freed with data_blob_free() you can pass NULL for p and get a blank data blob @@ -39,7 +29,7 @@ DATA_BLOB data_blob(const void *p, size_t length) { DATA_BLOB ret; - if (!length) { + if (length == 0) { ZERO_STRUCT(ret); return ret; } @@ -50,7 +40,6 @@ DATA_BLOB data_blob(const void *p, size_t length) ret.data = smb_xmalloc(length); } ret.length = length; - ret.free = free_data_blob; return ret; } @@ -73,7 +62,6 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) smb_panic("data_blob_talloc: talloc_memdup failed.\n"); } ret.length = length; - ret.free = NULL; return ret; } @@ -83,7 +71,6 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) } ret.length = length; - ret.free = NULL; return ret; } @@ -121,9 +108,7 @@ free a data blob void data_blob_free(DATA_BLOB *d) { if (d) { - if (d->free) { - (d->free)(d); - } + free(d->data); d->data = NULL; d->length = 0; } -- cgit From 716e6c1efb55f6fdc01f63cf703b46464da609b2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Aug 2004 03:23:39 +0000 Subject: r2043: data_blob() now returns a talloc'd pointer. If everyone has been following the data_blob() API properly then this will cause no problems. I'm expecting chaos. this is part of the general move towards using talloc for everything in samba4 (This used to be commit 3f6b3c21e4d538aeb30b7906a75995b8f4c11223) --- source4/lib/data_blob.c | 50 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 92950298aa..e10ebfe606 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -35,9 +35,13 @@ DATA_BLOB data_blob(const void *p, size_t length) } if (p) { - ret.data = smb_xmemdup(p, length); + ret.data = talloc_memdup(NULL, p, length); } else { - ret.data = smb_xmalloc(length); + ret.data = talloc(NULL, length); + } + if (ret.data == NULL) { + ret.length = 0; + return ret; } ret.length = length; return ret; @@ -48,29 +52,11 @@ DATA_BLOB data_blob(const void *p, size_t length) *******************************************************************/ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) { - DATA_BLOB ret; - - if (length == 0) { - ZERO_STRUCT(ret); - return ret; - } - - if (p == NULL) { - /* note that we do NOT zero memory in this case */ - ret.data = talloc(mem_ctx, length); - if (ret.data == NULL) { - smb_panic("data_blob_talloc: talloc_memdup failed.\n"); - } - ret.length = length; - return ret; - } + DATA_BLOB ret = data_blob(p, length); - ret.data = talloc_memdup(mem_ctx, p, length); - if (ret.data == NULL) { - smb_panic("data_blob_talloc: talloc_memdup failed.\n"); + if (ret.data) { + ret.data = talloc_steal(mem_ctx, ret.data); } - - ret.length = length; return ret; } @@ -86,29 +72,13 @@ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) return blob; } -/** - * Steal a talloc'ed DATA_BLOB from one context to another - */ - -DATA_BLOB data_blob_talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, - DATA_BLOB *old) -{ - DATA_BLOB new; - new = *old; - new.data = talloc_steal(new_ctx, old->data); - if (new.data == NULL) { - smb_panic("data_blob_talloc_steal: talloc_steal failed.\n"); - } - return new; -} - /******************************************************************* free a data blob *******************************************************************/ void data_blob_free(DATA_BLOB *d) { if (d) { - free(d->data); + talloc_free(d->data); d->data = NULL; d->length = 0; } -- cgit From 4f55a7af084137822c813cbe3822fca54e64df76 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Aug 2004 06:40:58 +0000 Subject: r2049: talloc now has destructors and reference counts this means you can do: talloc_set_destructor(ptr, my_destructor); and your destructor will be called with the pointer as an argument when the pointer is about to be freed. The destructor can refuse the free by returning -1. You can also increase the reference count on a pointer like this: talloc_increase_ref_count(ptr); and a talloc_free() will just reduce the reference count, only actually freeing the memory when the count reaches zero. (This used to be commit b5608d52d33a1d8be5a8a6751bc6cec162c7ed92) --- source4/lib/talloc.c | 131 +++++++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 56 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 4a48347832..31b6584845 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -27,17 +27,32 @@ #include "includes.h" #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0x14082004 -#define TALLOC_MAGIC_FREE 0x3421abcd +#define TALLOC_MAGIC 0xe814ec4f +#define TALLOC_MAGIC_FREE 0x7faebef3 struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; size_t size; uint_t magic; + uint_t ref_count; + int (*destructor)(void *); char *name; }; +/* panic if we get a bad magic value */ +static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr) +{ + struct talloc_chunk *tc = ((struct talloc_chunk *)ptr)-1; + if (tc->magic != TALLOC_MAGIC) { + if (tc->magic == TALLOC_MAGIC_FREE) { + smb_panic("Bad talloc magic value - double free\n"); + } else { + smb_panic("Bad talloc magic value\n"); + } + } + return tc; +} /* Allocate a bit of memory as a child of an existing pointer @@ -57,18 +72,13 @@ void *talloc(void *context, size_t size) tc->size = size; tc->magic = TALLOC_MAGIC; + tc->ref_count = 1; + tc->destructor = NULL; tc->child = NULL; tc->name = NULL; if (context) { - struct talloc_chunk *parent = ((struct talloc_chunk *)context)-1; - - if (parent->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad magic in context - 0x%08x\n", parent->magic)); - free(tc); - smb_panic("Bad magic in talloc context"); - return NULL; - } + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); tc->parent = parent; @@ -86,17 +96,35 @@ void *talloc(void *context, size_t size) /* - add a name to an existing pointer - va_list version + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used */ -static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) +void talloc_set_destructor(void *ptr, int (*destructor)(void *)) { - struct talloc_chunk *tc; + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. To decrease the + reference count call talloc_free(), which will free the memory if + the reference count reaches zero +*/ +void talloc_increase_ref_count(void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->ref_count++; +} - tc = ((struct talloc_chunk *)ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - return; - } +/* + add a name to an existing pointer - va_list version +*/ +static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); vasprintf(&tc->name, fmt, ap); } @@ -141,17 +169,14 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) { va_list ap; void *ptr; - struct talloc_chunk *tc; ptr = talloc(NULL, 0); if (ptr == NULL) { return NULL; } - tc = ((struct talloc_chunk *)ptr)-1; - va_start(ap, fmt); - vasprintf(&tc->name, fmt, ap); + talloc_set_name_v(ptr, fmt, ap); va_end(ap); return ptr; @@ -162,23 +187,36 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) /* free a talloc pointer. This also frees all child pointers of this pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero */ -void talloc_free(void *ptr) +int talloc_free(void *ptr) { struct talloc_chunk *tc; - if (ptr == NULL) return; + if (ptr == NULL) { + return -1; + } - tc = ((struct talloc_chunk *)ptr)-1; + tc = talloc_chunk_from_ptr(ptr); - if (tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad talloc magic 0x%08x in talloc_free\n", tc->magic)); - smb_panic("Bad talloc magic in talloc_realloc"); - return; + tc->ref_count--; + if (tc->ref_count != 0) { + return -1; + } + + if (tc->destructor && tc->destructor(ptr) == -1) { + tc->ref_count++; + return -1; } while (tc->child) { - talloc_free(tc->child + 1); + if (talloc_free(tc->child + 1) != 0) { + tc->child->parent = NULL; + break; + } } if (tc->parent) { @@ -195,6 +233,7 @@ void talloc_free(void *ptr) if (tc->name) free(tc->name); free(tc); + return 0; } @@ -218,18 +257,7 @@ void *talloc_realloc(void *ptr, size_t size) return talloc(NULL, size); } - tc = ((struct talloc_chunk *)ptr)-1; - - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { - - DEBUG(0,("Bad talloc magic - magic 0x%08x indicates double-free in talloc_realloc\n", tc->magic)); - smb_panic("Bad talloc magic - double-free - in talloc_realloc"); - } else { - DEBUG(0,("Bad talloc magic 0x%08x in talloc_realloc\n", tc->magic)); - smb_panic("Bad talloc magic in talloc_realloc"); - } - } + tc = talloc_chunk_from_ptr(ptr); /* by resetting magic we catch users of the old memory */ tc->magic = TALLOC_MAGIC_FREE; @@ -270,18 +298,11 @@ void *talloc_steal(void *new_ctx, void *ptr) return NULL; } - tc = ((struct talloc_chunk *)ptr)-1; - new_tc = ((struct talloc_chunk *)new_ctx)-1; + tc = talloc_chunk_from_ptr(ptr); + new_tc = talloc_chunk_from_ptr(new_ctx); - if (tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad talloc magic 0x%08x in talloc_steal\n", tc->magic)); - smb_panic("Bad talloc magic in talloc_steal"); - return NULL; - } - if (new_tc->magic != TALLOC_MAGIC) { - DEBUG(0,("Bad new talloc magic 0x%08x in talloc_steal\n", new_tc->magic)); - smb_panic("Bad new talloc magic in talloc_steal"); - return NULL; + if (tc == new_tc) { + return ptr; } if (tc->parent) { @@ -304,12 +325,10 @@ void *talloc_steal(void *new_ctx, void *ptr) /* return the total size of a talloc pool (subtree) */ -off_t talloc_total_size(void *p) +off_t talloc_total_size(void *ptr) { off_t total = 0; - struct talloc_chunk *c, *tc; - - tc = ((struct talloc_chunk *)p)-1; + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); total = tc->size; for (c=tc->child;c;c=c->next) { -- cgit From 5e869b4eabaf428b36b5bc158ab4047d25e3eb5b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 25 Aug 2004 07:15:21 +0000 Subject: r2055: Add PRINTF_ATTRIBUTE to many more parts of the code, and a new --enable-developer warning for when they are missing. Andrew Bartlett (This used to be commit 8115e44d47bcd65edba08d10117180ae508cdbc1) --- source4/lib/ldb/common/ldb_alloc.c | 2 +- source4/lib/ldb/common/ldb_debug.c | 2 ++ source4/lib/ldb/common/ldb_ldif.c | 2 ++ source4/lib/talloc.c | 9 +++++++-- source4/lib/tdb_helper.c | 2 ++ 5 files changed, 14 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_alloc.c b/source4/lib/ldb/common/ldb_alloc.c index 667759e832..6abd6fa8c3 100644 --- a/source4/lib/ldb/common/ldb_alloc.c +++ b/source4/lib/ldb/common/ldb_alloc.c @@ -122,7 +122,7 @@ void *ldb_strdup(struct ldb_context *ldb, const char *str) /* a ldb wrapper for asprintf(), using ldb_malloc() */ -int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) +int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) _PRINTF_ATTRIBUTE(3, 4) { int len, len2; va_list ap; diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c index d59f9284b0..0a187cd62d 100644 --- a/source4/lib/ldb/common/ldb_debug.c +++ b/source4/lib/ldb/common/ldb_debug.c @@ -51,6 +51,8 @@ int ldb_set_debug(struct ldb_context *ldb, /* debug function for ldb_set_debug_stderr */ +static void ldb_debug_stderr(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); static void ldb_debug_stderr(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) { diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 8c912f76d4..c693d211a9 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -640,6 +640,8 @@ struct ldif_write_file_state { FILE *f; }; +static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); + static int fprintf_file(void *private_data, const char *fmt, ...) { struct ldif_write_file_state *state = private_data; diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 31b6584845..036d06a2c2 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -122,6 +122,8 @@ void talloc_increase_ref_count(void *ptr) /* add a name to an existing pointer - va_list version */ +static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); @@ -393,7 +395,8 @@ char *talloc_strndup(void *t, const char *p, size_t n) return ret; } - char *talloc_vasprintf(void *t, const char *fmt, va_list ap) +static char *talloc_vasprintf(void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static char *talloc_vasprintf(void *t, const char *fmt, va_list ap) { int len; char *ret; @@ -434,8 +437,10 @@ char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) * and return @p s, which may have moved. Good for gradually * accumulating output into a string buffer. **/ + char *talloc_vasprintf_append(char *s, - const char *fmt, va_list ap) + const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0) + { int len, s_len; va_list ap2; diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c index 22c4d1bb45..2698e3cc71 100644 --- a/source4/lib/tdb_helper.c +++ b/source4/lib/tdb_helper.c @@ -29,6 +29,8 @@ Log tdb messages via DEBUG(). ****************************************************************************/ +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); + static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) { va_list ap; -- cgit From aca1e774f729f0662bf220b9468cd9e4dab8be73 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 25 Aug 2004 09:09:17 +0000 Subject: r2060: fix compiler warning metze (This used to be commit dde5442b75ba169856a52a45588e2702d198b31d) --- source4/lib/iconv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index cb861a7bb8..4cca6d56d2 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -54,7 +54,7 @@ static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); -static struct charset_functions builtin_functions[] = { +static const struct charset_functions const builtin_functions[] = { {"UCS-2LE", iconv_copy, iconv_copy}, {"UCS-2BE", iconv_swab, iconv_swab}, {"UTF8", utf8_pull, utf8_push}, @@ -65,9 +65,9 @@ static struct charset_functions builtin_functions[] = { static struct charset_functions *charsets = NULL; -static NTSTATUS charset_register_backend(void *_funcs) +static NTSTATUS charset_register_backend(const void *_funcs) { - struct charset_functions *funcs = (struct charset_functions *)_funcs; + struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); struct charset_functions *c = charsets; /* Check whether we already have this charset... */ -- cgit From 3cd74a363402a88a78cc900fda1c03134a8e9945 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Aug 2004 14:35:34 +0000 Subject: r2087: the ldb tools really don't need LIBSMB! that reduces the size of thet binaries with '-g' and gcc 3.4 from 5.3 MB to 745 KB:-) metze (This used to be commit 037a6d95b4a4640059a10dcbb0a266d15eaf42b3) --- source4/lib/ldb/config.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 677c31ac28..66e8481950 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -59,7 +59,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB + LIBBASIC CONFIG LIBCMDLINE LIBLDB # End BINARY ldbadd ################################################ @@ -69,7 +69,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB + LIBBASIC CONFIG LIBCMDLINE LIBLDB # End BINARY ldbdel ################################################ @@ -79,7 +79,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB + LIBBASIC CONFIG LIBCMDLINE LIBLDB # End BINARY ldbmodify ################################################ @@ -89,7 +89,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB + LIBBASIC CONFIG LIBCMDLINE LIBLDB # End BINARY ldbsearch ################################################ @@ -99,6 +99,6 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC LIBSMB CONFIG LIBCMDLINE LIBLDB + LIBBASIC CONFIG LIBCMDLINE LIBLDB # End BINARY ldbedit ################################################ -- cgit From 826a515ec063cf7b986ddfcfd47f2f7f09a12be5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Aug 2004 15:52:54 +0000 Subject: r2088: add tdbtorture tdbdump and tdbtest to the build NOTE: tdbbackup and tdbtool seems to be broken... NOTE: I also added SMB_EXT_LIB(GDBM,...) because that is needed by tdbtest metze (This used to be commit e66630662d4203ccecbb20962e83dbf50a2c056f) --- source4/lib/tdb/config.m4 | 25 +++++++++++++++++++ source4/lib/tdb/config.mk | 51 ++++++++++++++++++++++++++++++++++++++ source4/lib/tdb/tools/tdbdump.c | 9 ++++++- source4/lib/tdb/tools/tdbtest.c | 35 +++++++++++++++++--------- source4/lib/tdb/tools/tdbtorture.c | 16 +++++++++--- 5 files changed, 119 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 12d88ed6a8..d9b44b75a5 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -7,3 +7,28 @@ fi SMB_LIBRARY_MK(libtdb,lib/tdb/config.mk) +############################### +# start SMB_EXT_LIB_GDBM +# check for gdbm.h and -lgdbm +AC_CHECK_HEADERS(gdbm.h) +AC_CHECK_LIB_EXT(gdbm, GDBM_LIBS, gdbm_open) +if test x"$ac_cv_header_gdbm_h" = x"yes" -a x"$ac_cv_lib_ext_gdbm_gdbm_open" = x"yes";then + SMB_EXT_LIB_ENABLE(GDBM,YES) +fi +SMB_EXT_LIB(GDBM, $GDBM_LIBS) +# end SMB_EXT_LIB_GDBM +############################### + +SMB_BINARY_ENABLE(tdbtest, NO) +if test x"$SMB_EXT_LIB_ENABLE_GDBM" = x"YES"; then + SMB_BINARY_ENABLE(tdbtest, YES) +fi +SMB_BINARY_MK(tdbtest,lib/tdb/config.mk) + +SMB_BINARY_MK(tdbtorture,lib/tdb/config.mk) + +SMB_BINARY_MK(tdbdump,lib/tdb/config.mk) + +# these are broken +#SMB_BINARY_MK(tdbtool,lib/tdb/config.mk) +#SMB_BINARY_MK(tdbbackup,lib/tdb/config.mk) diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 96641f8da7..fdde6e7b4f 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -21,3 +21,54 @@ REQUIRED_SUBSYSTEMS = \ # # End LIBRARY LIBLDB ################################################ + +################################################ +# Start BINARY tdbtest +[BINARY::tdbtest] +OBJ_FILES= \ + lib/tdb/tools/tdbtest.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC CONFIG LIBCMDLINE LIBTDB +REQUIRED_LIBRARIES = GDBM +# End BINARY tdbtest +################################################ + +################################################ +# Start BINARY tdbtool +[BINARY::tdbtool] +OBJ_FILES= \ + lib/tdb/tools/tdbtool.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC CONFIG LIBCMDLINE LIBTDB +# End BINARY tdbtool +################################################ + +################################################ +# Start BINARY tdbtorture +[BINARY::tdbtorture] +OBJ_FILES= \ + lib/tdb/tools/tdbtorture.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC CONFIG LIBCMDLINE LIBTDB +# End BINARY tdbtorture +################################################ + +################################################ +# Start BINARY tdbdump +[BINARY::tdbdump] +OBJ_FILES= \ + lib/tdb/tools/tdbdump.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC CONFIG LIBCMDLINE LIBTDB +# End BINARY tdbdump +################################################ + +################################################ +# Start BINARY tdbbackup +[BINARY::tdbbackup] +OBJ_FILES= \ + lib/tdb/tools/tdbbackup.o +REQUIRED_SUBSYSTEMS = \ + LIBBASIC CONFIG LIBCMDLINE LIBTDB +# End BINARY tdbbackup +################################################ diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 1a7128c473..0e179f8c3e 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef STANDALONE #include #include #include @@ -33,9 +34,15 @@ #include #include "tdb.h" +#else + +#include "includes.h" + +#endif + static void print_data(TDB_DATA d) { - uint8_t *p = d.dptr; + unsigned char *p = d.dptr; int len = d.dsize; while (len--) { if (isprint(*p) && !strchr("\"\\", *p)) { diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index 89295a3291..9a210f8a61 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -1,3 +1,6 @@ +/* a test program for tdb - the trivial database */ + +#ifdef STANDALONE #include #include #include @@ -10,10 +13,13 @@ #include #include #include "tdb.h" -#include +#else -/* a test program for tdb - the trivial database */ +#include "includes.h" +#endif + +#include #define DELETE_PROB 7 @@ -24,24 +30,27 @@ static GDBM_FILE gdbm; struct timeval tp1,tp2; -static void start_timer(void) +static void _start_timer(void) { gettimeofday(&tp1,NULL); } -static double end_timer(void) +static double _end_timer(void) { gettimeofday(&tp2,NULL); return((tp2.tv_sec - tp1.tv_sec) + (tp2.tv_usec - tp1.tv_usec)*1.0e-6); } -static void fatal(char *why) +static void fatal(const char *why) { perror(why); exit(1); } +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) { va_list ap; @@ -192,14 +201,15 @@ static void merge_test(void) { int i; char keys[5][2]; + char tdata[] = "test"; TDB_DATA key, data; for (i = 0; i < 5; i++) { - sprintf(keys[i], "%d", i); + snprintf(keys[i],2, "%d", i); key.dptr = keys[i]; key.dsize = 2; - data.dptr = "test"; + data.dptr = tdata; data.dsize = 4; if (tdb_store(db, key, data, TDB_REPLACE) != 0) { @@ -223,12 +233,13 @@ int main(int argc, char *argv[]) { int i, seed=0; int loops = 10000; + char test_gdbm[] = "test.gdbm"; unlink("test.gdbm"); db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT | O_TRUNC, 0600); - gdbm = gdbm_open("test.gdbm", 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST, + gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST, 0600, NULL); if (!db || !gdbm) { @@ -239,17 +250,17 @@ int main(int argc, char *argv[]) #if 1 srand(seed); - start_timer(); + _start_timer(); for (i=0;i #include #include @@ -13,11 +18,11 @@ #include #include "tdb.h" -/* this tests tdb by doing lots of ops from several simultaneous - writers - that stresses the locking code. Build with TDB_DEBUG=1 - for best effect */ +#else +#include "includes.h" +#endif #define REOPEN_PROB 30 #define DELETE_PROB 8 @@ -32,6 +37,9 @@ static TDB_CONTEXT *db; +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) { va_list ap; @@ -50,7 +58,7 @@ static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) #endif } -static void fatal(char *why) +static void fatal(const char *why) { perror(why); exit(1); -- cgit From ef9351d84ba8bf5c4adc9881f3b2c388deac4ffe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Aug 2004 15:56:04 +0000 Subject: r2089: fix standalone build with LDAP, this needs -llber too metze (This used to be commit b9152c9ba2735f511663f34a910142eed67701b5) --- source4/lib/ldb/Makefile.ldb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 5573fba32f..6a87043114 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -4,7 +4,7 @@ WITH_LDAP=1 ifeq ($(WITH_LDAP),1) OPENLDAP_PREFIX=/usr -LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -lldap +LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -llber -lldap LDAP_FLAGS=-DHAVE_LDAP=1 LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o endif -- cgit From 2812998ae99ed96f5b9a7edff471eecf7359edac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Aug 2004 18:00:55 +0000 Subject: r2092: fix the build(don't catch main() by make proto) metze (This used to be commit ecdb0b442659e80ca91d5ec5b505224c68a97c5a) --- source4/lib/tdb/tools/tdbtest.c | 2 +- source4/lib/tdb/tools/tdbtorture.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index 9a210f8a61..6c20a5dc77 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -229,7 +229,7 @@ static void merge_test(void) tdb_delete(db, key); } -int main(int argc, char *argv[]) + int main(int argc, const char *argv[]) { int i, seed=0; int loops = 10000; diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index d7c0812800..005a2713af 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -185,7 +185,7 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, #define NLOOPS 200000 #endif -int main(int argc, char *argv[]) + int main(int argc, const char *argv[]) { int i, seed=0; int loops = NLOOPS; -- cgit From e7f36ff1a5ec909573ef398d215608e7c9aa71fe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 30 Aug 2004 03:10:43 +0000 Subject: r2100: rework the dcerpc client side library so that it is async. We now generate a separate *_send() async function for every RPC call, and there is a single dcerpc_ndr_request_recv() call that processes the receive side of any rpc call. The caller can use dcerpc_event_context() to get a pointer to the event context for the pipe so that events can be waited for asynchronously. The only part that remains synchronous is the initial bind calls. These could also be made async if necessary, although I suspect most applications won't need them to be. (This used to be commit f5d004d8eb8c76c03342cace1976b27266cfa1f0) --- source4/lib/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index a6099db5c5..9affaf1246 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -403,7 +403,7 @@ void event_loop_once(struct event_context *ev) made readable and that should have removed the event, so this must be a bug. This is a fatal error. */ - DEBUG(0,("EBADF on event_loop_wait - exiting\n")); + DEBUG(0,("EBADF on event_loop_once - exiting\n")); return; } -- cgit From 2de9ce9499803bac73ae9f49ce1fa7b57762c389 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 30 Aug 2004 12:03:01 +0000 Subject: r2106: try to cope with a wider range of UTF-16 characters when we are using an external libiconv library. (This used to be commit 168be7fbd7ae876ded39f73a7835e91b35e67244) --- source4/lib/charcnv.c | 8 +++++--- source4/lib/iconv.c | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index b84814b41c..8204a3bcdd 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -47,7 +47,7 @@ static const char *charset_name(charset_t ch) { const char *ret = NULL; - if (ch == CH_UCS2) ret = "UCS-2LE"; + if (ch == CH_UCS2) ret = "UTF-16LE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); @@ -82,10 +82,12 @@ void init_iconv(void) /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ if (!conv_handles[CH_UNIX][CH_UCS2]) - conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII"); + conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), + "ASCII"); if (!conv_handles[CH_UCS2][CH_UNIX]) - conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE"); + conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", + charset_name(CH_UCS2)); for (c1=0;c1 Date: Tue, 31 Aug 2004 08:21:29 +0000 Subject: r2125: the lp_use_mmap() in map_file() is inappropriate for 2 reasons, so I have removed it. - lp_use_mmap() is really meant to cope with systems that have broken mmap coherence, but map_file() doesn't need coherence, as its maps read only - map_file() is used to map the charset files before loadparm has loaded, so lp_use_mmap() is always returning false for the major use of map_file() (This used to be commit dbe786f61e3de0758f95f2abd1b15a4c320432ca) --- source4/lib/util_file.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index a5832adec5..51e6c7187e 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -366,19 +366,17 @@ void *map_file(char *fname, size_t size) size_t s2 = 0; void *p = NULL; #ifdef HAVE_MMAP - if (lp_use_mmap()) { - int fd; - fd = open(fname, O_RDONLY, 0); - if (fd == -1) { - DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno))); - return NULL; - } - p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); - close(fd); - if (p == MAP_FAILED) { - DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno))); - return NULL; - } + int fd; + fd = open(fname, O_RDONLY, 0); + if (fd == -1) { + DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno))); + return NULL; + } + p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + close(fd); + if (p == MAP_FAILED) { + DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno))); + return NULL; } #endif if (!p) { -- cgit From cfedadec2211676ed7f99685c695e1e2f0d41923 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 31 Aug 2004 23:57:14 +0000 Subject: r2154: Merge of Jim's format string fixup in r2130:2131 (This used to be commit 17a53eaac2d0d76413c8bb27a6f1c80536ccf3a7) --- source4/lib/tdb/common/tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index b9ca46c322..aefa08cdb8 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -490,7 +490,7 @@ static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) if (rec->magic == TDB_MAGIC) { /* this happens when a app is showdown while deleting a record - we should not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic at offset=%d - fixing\n", + TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", rec->magic, off)); rec->magic = TDB_FREE_MAGIC; if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) -- cgit From 31c1c7846f6b6e5848bc39a28a65118bfa98e35d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 1 Sep 2004 04:39:06 +0000 Subject: r2159: converted samba4 over to UTF-16. I had previously thought this was unnecessary, as windows doesn't use standards compliant UTF-16, and for filesystem operations treats bytes as UCS-2, but Bjoern Jacke has pointed out to me that this means we don't correctly store extended UTF-16 characters as UTF-8 on disk. This can be seen with (for example) the gothic characters with codepoints above 64k. This commit also adds a LOCAL-ICONV torture test that tests the first 1 million codepoints against the system iconv library, and tests 5 million random UTF-16LE buffers for identical error handling to the system iconv library. the lib/iconv.c changes need backporting to samba3 (This used to be commit 756f28ac95feaa84b42402723d5f7286865c78db) --- source4/lib/charcnv.c | 34 +++--- source4/lib/iconv.c | 262 ++++++++++++++++++++++++++++++++++------------ source4/lib/util_unistr.c | 4 +- 3 files changed, 216 insertions(+), 84 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 8204a3bcdd..2109e957d9 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -47,12 +47,12 @@ static const char *charset_name(charset_t ch) { const char *ret = NULL; - if (ch == CH_UCS2) ret = "UTF-16LE"; + if (ch == CH_UTF16) ret = "UTF-16LE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); else if (ch == CH_UTF8) ret = "UTF8"; - else if (ch == CH_UCS2BE) ret = "UCS-2BE"; + else if (ch == CH_UTF16BE) ret = "UTF-16BE"; if (!ret || !*ret) ret = "ASCII"; return ret; @@ -81,13 +81,13 @@ void init_iconv(void) /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ - if (!conv_handles[CH_UNIX][CH_UCS2]) - conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), + if (!conv_handles[CH_UNIX][CH_UTF16]) + conv_handles[CH_UNIX][CH_UTF16] = smb_iconv_open(charset_name(CH_UTF16), "ASCII"); - if (!conv_handles[CH_UCS2][CH_UNIX]) - conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", - charset_name(CH_UCS2)); + if (!conv_handles[CH_UTF16][CH_UNIX]) + conv_handles[CH_UTF16][CH_UNIX] = smb_iconv_open("ASCII", + charset_name(CH_UTF16)); for (c1=0;c1direct = to->push; return ret; } - if (strcasecmp(tocode, "UCS-2LE") == 0 && from) { + if (strcasecmp(tocode, "UTF-16LE") == 0 && from) { ret->direct = from->pull; return ret; } #ifdef HAVE_NATIVE_ICONV - if (strcasecmp(fromcode, "UCS-2LE") == 0) { + if (strcasecmp(fromcode, "UTF-16LE") == 0) { ret->direct = sys_iconv; ret->cd_direct = ret->cd_push; ret->cd_push = NULL; return ret; } - if (strcasecmp(tocode, "UCS-2LE") == 0) { + if (strcasecmp(tocode, "UTF-16LE") == 0) { ret->direct = sys_iconv; ret->cd_direct = ret->cd_pull; ret->cd_pull = NULL; @@ -460,100 +461,231 @@ static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - const uint8_t *c = (const uint8_t *)*inbuf; - uint8_t *uc = (uint8_t *)*outbuf; - int len = 1; + size_t in_left=*inbytesleft, out_left=*outbytesleft; + const uint8_t *c = (const uint8_t *)*inbuf; + uint8_t *uc = (uint8_t *)*outbuf; + while (in_left >= 1 && out_left >= 2) { if ((c[0] & 0x80) == 0) { uc[0] = c[0]; uc[1] = 0; - } else if ((c[0] & 0xf0) == 0xe0) { - if (*inbytesleft < 3) { - DEBUG(0,("short utf8 char\n")); - goto badseq; + c += 1; + in_left -= 1; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xe0) == 0xc0) { + if (in_left < 2 || + (c[1] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + uc[1] = (c[0]>>2) & 0x7; + uc[0] = (c[0]<<6) | (c[1]&0x3f); + c += 2; + in_left -= 2; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf0) == 0xe0) { + if (in_left < 3 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; } uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); uc[0] = (c[1]<<6) | (c[2]&0x3f); - len = 3; - } else if ((c[0] & 0xe0) == 0xc0) { - if (*inbytesleft < 2) { - DEBUG(0,("short utf8 char\n")); - goto badseq; + c += 3; + in_left -= 3; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf8) == 0xf0) { + unsigned int codepoint; + if (in_left < 4 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80 || + (c[3] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; } - uc[1] = (c[0]>>2) & 0x7; - uc[0] = (c[0]<<6) | (c[1]&0x3f); - len = 2; + codepoint = + (c[3]&0x3f) | + ((c[2]&0x3f)<<6) | + ((c[1]&0x3f)<<12) | + ((c[0]&0x7)<<18); + if (codepoint < 0x10000) { + /* accept UTF-8 characters that are not + minimally packed, but pack the result */ + uc[0] = (codepoint & 0xFF); + uc[1] = (codepoint >> 8); + c += 4; + in_left -= 4; + out_left -= 2; + uc += 2; + continue; + } + + codepoint -= 0x10000; + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + + uc[0] = (codepoint>>10) & 0xFF; + uc[1] = (codepoint>>18) | 0xd8; + uc[2] = codepoint & 0xFF; + uc[3] = ((codepoint>>8) & 0x3) | 0xdc; + c += 4; + in_left -= 4; + out_left -= 4; + uc += 4; + continue; } - (*inbuf) += len; - (*inbytesleft) -= len; - (*outbytesleft) -= 2; - (*outbuf) += 2; + /* we don't handle 5 byte sequences */ + errno = EINVAL; + goto error; } - if (*inbytesleft > 0) { + if (in_left > 0) { errno = E2BIG; - return -1; + goto error; } - + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = c; + *outbuf = uc; return 0; -badseq: - errno = EINVAL; +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = c; + *outbuf = uc; return -1; } static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) + char **outbuf, size_t *outbytesleft) { - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - uint8_t *c = (uint8_t *)*outbuf; - const uint8_t *uc = (const uint8_t *)*inbuf; - int len=1; - - if (uc[1] & 0xf8) { - if (*outbytesleft < 3) { - DEBUG(0,("short utf8 write\n")); - goto toobig; + size_t in_left=*inbytesleft, out_left=*outbytesleft; + uint8_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*inbuf; + + while (in_left >= 2 && out_left >= 1) { + unsigned int codepoint; + + if (uc[1] == 0 && !(uc[0] & 0x80)) { + /* simplest case */ + c[0] = uc[0]; + in_left -= 2; + out_left -= 1; + uc += 2; + c += 1; + continue; + } + + if ((uc[1]&0xf8) == 0) { + /* next simplest case */ + if (out_left < 2) { + errno = E2BIG; + goto error; } - c[0] = 0xe0 | (uc[1]>>4); - c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6); - c[2] = 0x80 | (uc[0]&0x3f); - len = 3; - } else if (uc[1] | (uc[0] & 0x80)) { - if (*outbytesleft < 2) { - DEBUG(0,("short utf8 write\n")); - goto toobig; + c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2); + c[1] = 0x80 | (uc[0] & 0x3f); + in_left -= 2; + out_left -= 2; + uc += 2; + c += 2; + continue; + } + + if ((uc[1] & 0xfc) == 0xdc) { + /* its the second part of a 4 byte sequence. Illegal */ + if (in_left < 4) { + errno = EINVAL; + } else { + errno = EILSEQ; } - c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6); - c[1] = 0x80 | (uc[0]&0x3f); - len = 2; - } else { - c[0] = uc[0]; + goto error; } + if ((uc[1] & 0xfc) != 0xd8) { + codepoint = uc[0] | (uc[1]<<8); + if (out_left < 3) { + errno = E2BIG; + goto error; + } + c[0] = 0xe0 | (codepoint >> 12); + c[1] = 0x80 | ((codepoint >> 6) & 0x3f); + c[2] = 0x80 | (codepoint & 0x3f); + + in_left -= 2; + out_left -= 3; + uc += 2; + c += 3; + continue; + } - (*inbytesleft) -= 2; - (*outbytesleft) -= len; - (*inbuf) += 2; - (*outbuf) += len; + /* its the first part of a 4 byte sequence */ + if (in_left < 4) { + errno = EINVAL; + goto error; + } + if ((uc[3] & 0xfc) != 0xdc) { + errno = EILSEQ; + goto error; + } + codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) | + (uc[0]<<10) | ((uc[1] & 0x3)<<18)); + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + c[0] = 0xf0 | (codepoint >> 18); + c[1] = 0x80 | ((codepoint >> 12) & 0x3f); + c[2] = 0x80 | ((codepoint >> 6) & 0x3f); + c[3] = 0x80 | (codepoint & 0x3f); + + in_left -= 4; + out_left -= 4; + uc += 4; + c += 4; } - if (*inbytesleft == 1) { + if (in_left == 1) { errno = EINVAL; - return -1; + goto error; } - if (*inbytesleft > 1) { + if (in_left > 1) { errno = E2BIG; - return -1; + goto error; } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = uc; + *outbuf = c; return 0; -toobig: - errno = E2BIG; +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = uc; + *outbuf = c; return -1; } diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 2bd990836e..63d68fa12e 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -96,9 +96,9 @@ static int check_dos_char(smb_ucs2_t c) char buf[10]; smb_ucs2_t c2 = 0; int len1, len2; - len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf)); + len1 = convert_string(CH_UTF16, CH_DOS, &c, 2, buf, sizeof(buf)); if (len1 == 0) return 0; - len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2); + len2 = convert_string(CH_DOS, CH_UTF16, buf, len1, &c2, 2); if (len2 != 2) return 0; return (c == c2); } -- cgit From a08808d62b455addad00d6c7ab42d12bc967cea5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 1 Sep 2004 05:19:00 +0000 Subject: r2164: put the latest "accept either form" utf-16 iconv code in samba4 (This used to be commit 62a0cfd865d6ad4c05e2461dbf0b81988683a219) --- source4/lib/iconv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 9f6526faa5..039dac2424 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -161,6 +161,12 @@ size_t smb_iconv(smb_iconv_t cd, return 0; } +static BOOL is_utf16(const char *name) +{ + return strcasecmp(name, "UCS-2LE") == 0 || + strcasecmp(name, "UTF-16LE") == 0; +} + /* simple iconv_open() wrapper */ @@ -202,13 +208,17 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) #ifdef HAVE_NATIVE_ICONV if (!from) { ret->pull = sys_iconv; - ret->cd_pull = iconv_open("UCS-2LE", fromcode); + ret->cd_pull = iconv_open("UTF-16LE", fromcode); + if (ret->cd_pull == (iconv_t)-1) + ret->cd_pull = iconv_open("UCS-2LE", fromcode); if (ret->cd_pull == (iconv_t)-1) goto failed; } if (!to) { ret->push = sys_iconv; - ret->cd_push = iconv_open(tocode, "UCS-2LE"); + ret->cd_push = iconv_open(tocode, "UTF-16LE"); + if (ret->cd_push == (iconv_t)-1) + ret->cd_push = iconv_open(tocode, "UCS-2LE"); if (ret->cd_push == (iconv_t)-1) goto failed; } #else @@ -218,23 +228,23 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) #endif /* check for conversion to/from ucs2 */ - if (strcasecmp(fromcode, "UTF-16LE") == 0 && to) { + if (is_utf16(fromcode) && to) { ret->direct = to->push; return ret; } - if (strcasecmp(tocode, "UTF-16LE") == 0 && from) { + if (is_utf16(tocode) && from) { ret->direct = from->pull; return ret; } #ifdef HAVE_NATIVE_ICONV - if (strcasecmp(fromcode, "UTF-16LE") == 0) { + if (is_utf16(fromcode)) { ret->direct = sys_iconv; ret->cd_direct = ret->cd_push; ret->cd_push = NULL; return ret; } - if (strcasecmp(tocode, "UTF-16LE") == 0) { + if (is_utf16(tocode)) { ret->direct = sys_iconv; ret->cd_direct = ret->cd_pull; ret->cd_pull = NULL; -- cgit From f4dbe1865e714cb2fc87acbe6ab5f331ac9dbb1e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 1 Sep 2004 09:45:00 +0000 Subject: r2169: switch core iconv code to use talloc (This used to be commit 117796c19ba9615113ae549068fd0b5ad5d3aa97) --- source4/lib/iconv.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 039dac2424..fb997cf8f1 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -179,15 +179,16 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) from = charsets; to = charsets; - ret = (smb_iconv_t)malloc(sizeof(*ret)); + ret = (smb_iconv_t)talloc_named(NULL, sizeof(*ret), + "iconv(%s,%s)", tocode, fromcode); if (!ret) { errno = ENOMEM; return (smb_iconv_t)-1; } memset(ret, 0, sizeof(*ret)); - ret->from_name = strdup(fromcode); - ret->to_name = strdup(tocode); + ret->from_name = talloc_strdup(ret, fromcode); + ret->to_name = talloc_strdup(ret, tocode); /* check for the simplest null conversion */ if (strcmp(fromcode, tocode) == 0) { @@ -258,7 +259,7 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) return ret; failed: - SAFE_FREE(ret); + talloc_free(ret); errno = EINVAL; return (smb_iconv_t)-1; } @@ -266,7 +267,7 @@ failed: /* simple iconv_close() wrapper */ -int smb_iconv_close (smb_iconv_t cd) +int smb_iconv_close(smb_iconv_t cd) { #ifdef HAVE_NATIVE_ICONV if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); @@ -274,11 +275,7 @@ int smb_iconv_close (smb_iconv_t cd) if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); #endif - SAFE_FREE(cd->from_name); - SAFE_FREE(cd->to_name); - - memset(cd, 0, sizeof(*cd)); - SAFE_FREE(cd); + talloc_free(cd); return 0; } @@ -699,3 +696,5 @@ error: return -1; } + + -- cgit From 37dc4e9bf757710c30d05ff9cba3c960ce76989a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Sep 2004 21:55:24 +0000 Subject: r2192: removed an erroneous free() call on an error path (This used to be commit c80d686f59a8b6c53305af1233137c22a26f6750) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 355de21250..e36770f88b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -364,7 +364,6 @@ static int msg_add_element(struct ldb_context *ldb, if (el->num_values != 0) { e2->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values); if (!e2->values) { - free(e2->name); errno = ENOMEM; return -1; } -- cgit From cecc2b38f1d3ed2c29487bd4fcfd38487095661d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 3 Sep 2004 17:44:07 +0000 Subject: r2212: Optimisation. Passes masktest against W2K3. Jeremy. (This used to be commit fb7a529c4c65788c307c1043cf2b664059ed8c2a) --- source4/lib/ms_fnmatch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index dd015a0ac8..1c4b3d1806 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -173,6 +173,9 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, break; case UCS2_CHAR('*'): + while (*p == UCS2_CHAR('*')) { + p++; + } for (; *n; n++) { if (ms_fnmatch_w(p, n, protocol) == 0) return 0; } -- cgit From 8fa455d815ff4ad3bda57d1c7b683adfe04efd85 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 7 Sep 2004 13:44:49 +0000 Subject: r2238: the tdb_debug() function was totally bogus - remove it (you can't convert a ... varargs function to a va_list by just a cast!!) also mark the tdb log function with PRINTF_ATTRIBUTE() and fixed some bad format errors in tdb.c that jim found. (This used to be commit c26c92eb8f538748fcbb2ae5a0a8a02bffbbbf86) --- source4/lib/tdb/common/tdb.c | 15 ++++++++++----- source4/lib/tdb/common/tdbutil.c | 40 ++++++++++++---------------------------- source4/lib/tdb/include/tdb.h | 4 +--- 3 files changed, 23 insertions(+), 36 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index aefa08cdb8..4ae23bead7 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -89,7 +89,7 @@ /* NB assumes there is a local variable called "tdb" that is the * current context, also takes doubly-parenthesized print-style * argument. */ -#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0) +#define TDB_LOG(x) tdb->log_fn x /* lock offsets */ #define GLOBAL_LOCK 0 @@ -277,7 +277,7 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) if (tdb->locked[list+1].count == 0) { if (!tdb->read_only && tdb->header.rwlocks) { if (tdb_spinlock(tdb, list, ltype)) { - TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n", + TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", list, ltype)); return -1; } @@ -1755,6 +1755,11 @@ TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); } +/* a default logging function */ +static void null_log_fn(TDB_CONTEXT *tdb, int level, const char *fmt, ...) +{ +} + TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, @@ -1778,7 +1783,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->lockedkeys = NULL; tdb->flags = tdb_flags; tdb->open_flags = open_flags; - tdb->log_fn = log_fn; + tdb->log_fn = log_fn?log_fn:null_log_fn; tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; if ((open_flags & O_ACCMODE) == O_WRONLY) { @@ -1861,7 +1866,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, if (tdb_already_open(st.st_dev, st.st_ino)) { TDB_LOG((tdb, 2, "tdb_open_ex: " "%s (%d,%d) is already open in this process\n", - name, st.st_dev, st.st_ino)); + name, (int)st.st_dev, (int)st.st_ino)); errno = EBUSY; goto fail; } @@ -2082,7 +2087,7 @@ int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) /* register a loging function */ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) { - tdb->log_fn = fn; + tdb->log_fn = fn?fn:null_log_fn; } diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 6b9ad414c5..596a79f52e 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -112,8 +112,8 @@ static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, u alarm(0); TdbCatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); if (gotalarm) { - tdb_debug(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", - timeout, key.dptr, tdb->name ); + tdb->log_fn(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", + timeout, key.dptr, tdb->name); /* TODO: If we time out waiting for a lock, it might * be nice to use F_GETLK to get the pid of the * process currently holding the lock and print that @@ -492,8 +492,8 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) } break; default: - tdb_debug(tdb, 0,"Unknown tdb_pack format %c in %s\n", - c, fmt); + tdb->log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n", + c, fmt); len = 0; break; } @@ -507,8 +507,8 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_end(ap); - tdb_debug(tdb, 18,"tdb_pack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + tdb->log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); } @@ -599,7 +599,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) memcpy(*b, buf+4, *i); break; default: - tdb_debug(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + tdb->log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", c, fmt); len = 0; @@ -612,8 +612,8 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_end(ap); - tdb_debug(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + tdb->log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); @@ -621,22 +621,6 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) return -1; } -/**************************************************************************** - Print out debug messages. -****************************************************************************/ - -void tdb_debug(TDB_CONTEXT *tdb, int level, const char *fmt, ...) -{ - va_list ap; - if (tdb->log_fn == NULL) { - return; - } - va_start(ap, fmt); - tdb->log_fn(tdb, level, fmt, ap); - va_end(ap); -} - - /**************************************************************************** Allow tdb_delete to be used as a tdb_traversal_fn. ****************************************************************************/ @@ -669,11 +653,11 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) char *key_str = (char*) strndup(key.dptr, key.dsize); #if 0 if (!key_str) { - tdb_debug(tdb, 0, "tdb_search_keys: strndup() failed!\n"); + tdb->log_fn(tdb, 0, "tdb_search_keys: strndup() failed!\n"); smb_panic("strndup failed!\n"); } #endif - tdb_debug(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); + tdb->log_fn(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); next = tdb_nextkey(tdb, key); @@ -686,7 +670,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) DLIST_ADD_END(list, rec, TDB_LIST_NODE *); - tdb_debug(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); + tdb->log_fn(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); } else { free(key.dptr); } diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 02b89087a8..ed8c247b08 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -101,13 +101,11 @@ typedef struct tdb_context { struct tdb_context *next; /* all tdbs to avoid multiple opens */ dev_t device; /* uniquely identifies this tdb */ ino_t inode; /* uniquely identifies this tdb */ - void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ + void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ u32 (*hash_fn)(TDB_DATA *key); int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; -void tdb_debug(TDB_CONTEXT *, int , const char *, ...); - typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); typedef u32 (*tdb_hash_func)(TDB_DATA *key); -- cgit From 9c69fe6522289c154505beea554426b0bf308e06 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 8 Sep 2004 12:41:12 +0000 Subject: r2254: Fix a couple of compiler warnings... (This used to be commit 8056f4a9a7f5065eeb3a3bec81977c5e4163bf8e) --- source4/lib/registry/common/reg_interface.c | 5 ++--- source4/lib/registry/common/registry.h | 4 ++-- source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 11 +++-------- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 3 --- 4 files changed, 7 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index e7024d23fe..f0a6807558 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -30,9 +30,9 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); /* Register new backend */ -NTSTATUS registry_register(void *_function) +NTSTATUS registry_register(const void *_function) { - struct registry_ops *functions = _function; + const struct registry_ops *functions = _function; struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { @@ -97,7 +97,6 @@ WERROR reg_open(const char *backend, const char *location, const char *credentia struct reg_init_function_entry *entry; TALLOC_CTX *mem_ctx; REG_HANDLE *ret; - NTSTATUS status; WERROR werr; entry = reg_find_backend_entry(backend); diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h index caa0e284bf..89d0ac6b14 100644 --- a/source4/lib/registry/common/registry.h +++ b/source4/lib/registry/common/registry.h @@ -123,7 +123,7 @@ struct registry_ops { }; struct reg_handle_s { - struct registry_ops *functions; + const struct registry_ops *functions; char *location; char *credentials; void *backend_data; @@ -132,7 +132,7 @@ struct reg_handle_s { struct reg_init_function_entry { /* Function to create a member of the pdb_methods list */ - struct registry_ops *functions; + const struct registry_ops *functions; struct reg_init_function_entry *prev, *next; }; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 6945ebdb55..47cb60d711 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -89,15 +89,13 @@ static WERROR ldb_add_key(REG_KEY *p, const char *name, uint32_t access_mask, SE static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) { struct ldb_context *c = k->handle->backend_data; - char *path; int ret, i, j; struct ldb_message **msg; - REG_KEY *key = NULL; ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); if(ret < 0) { - DEBUG(0, ("Error getting subkeys for '%s': %s\n", k->backend_data, ldb_errstring(c))); + DEBUG(0, ("Error getting subkeys for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); return WERR_FOOBAR; } @@ -126,15 +124,13 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) { struct ldb_context *c = k->handle->backend_data; - char *path; int ret, i, j; struct ldb_message **msg; - REG_KEY *key = NULL; ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); if(ret < 0) { - DEBUG(0, ("Error getting values for '%s': %s\n", k->backend_data, ldb_errstring(c))); + DEBUG(0, ("Error getting values for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); return WERR_FOOBAR; } @@ -170,9 +166,8 @@ static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) { struct ldb_context *c = h->backend_data; - char *path; struct ldb_message **msg; - char *ldap_path, *new_ldap_path; + char *ldap_path; int ret; TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); if(num != 0) return WERR_NO_MORE_ITEMS; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 4e6944a1e3..0d8d935a4a 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -128,8 +128,6 @@ static WERROR rpc_close_registry(REG_HANDLE *h) static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) { struct winreg_OpenKey r; - int i; - struct rpc_data *mydata = k->handle->backend_data; WERROR error; REG_KEY *hivekey; struct rpc_key_data *mykeydata; @@ -254,7 +252,6 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) struct winreg_EnumKeyNameRequest keyname; struct winreg_String classname; struct winreg_Time tm; - struct rpc_data *mydata = parent->handle->backend_data; struct rpc_key_data *mykeydata = parent->backend_data; WERROR error; NTSTATUS status; -- cgit From 93454ff3d8177fb71443808f01740dbbe7e46dd8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 8 Sep 2004 13:44:45 +0000 Subject: r2257: Tab completion support in regshell (complete command names and key names in the current key) (This used to be commit 83f9f8eaa4825bb49e2b160a1a810080ecae4d39) --- source4/lib/registry/common/reg_objects.c | 10 +++ source4/lib/registry/tools/regshell.c | 116 +++++++++++++++++++++++++++++- 2 files changed, 125 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c index d042c74e47..d911b4650b 100644 --- a/source4/lib/registry/common/reg_objects.c +++ b/source4/lib/registry/common/reg_objects.c @@ -103,6 +103,16 @@ char *reg_key_name( REG_KEY *key ) return key->name; } +char *reg_key_class( REG_KEY *key ) +{ + return key->class_name; +} + +NTTIME reg_key_last_modified( REG_KEY *key ) +{ + return key->last_mod; +} + REG_KEY *reg_key_dup(REG_KEY *key) { key->ref++; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index b843e91120..638ed70d5e 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -28,10 +28,23 @@ * rmkey/rmdir - remove key * mkkey/mkdir - make key * ch - change hive + * info - show key info * help * exit */ +static REG_KEY *cmd_info(REG_KEY *cur, int argc, char **argv) +{ + time_t last_mod; + printf("Name: %s\n", reg_key_name(cur)); + printf("Full path: %s\n", reg_key_get_path(cur)); + printf("Key Class: %s\n", reg_key_class(cur)); + last_mod = nt_time_to_unix(reg_key_last_modified(cur)); + printf("Time Last Modified: %s\n", ctime(&last_mod)); + /* FIXME: Security info */ + return cur; +} + static REG_KEY *cmd_pwd(REG_KEY *cur, int argc, char **argv) { printf("%s\n", reg_key_get_path_abs(cur)); @@ -180,6 +193,7 @@ struct { } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, {"ch", "hive", "Change current hive", cmd_hive }, + {"info", "i", "Show detailed information of a key", cmd_info }, {"list", "ls", "List values/keys in current key", cmd_ls }, {"mkkey", "mkdir", "Make new key", cmd_mkkey }, {"rmval", "rm", "Remove value", cmd_rmval }, @@ -224,6 +238,104 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) return k; } +#define MAX_COMPLETIONS 100 + +static REG_KEY *current_key = NULL; + +static char **reg_complete_command(const char *text, int end) +{ + /* Complete command */ + char **matches; + int i, len, samelen, count=1; + + matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); + if (!matches) return NULL; + matches[0] = NULL; + + len = strlen(text); + for (i=0;regshell_cmds[i].handle && count < MAX_COMPLETIONS-1;i++) { + if (strncmp(text, regshell_cmds[i].name, len) == 0) { + matches[count] = strdup(regshell_cmds[i].name); + if (!matches[count]) + goto cleanup; + if (count == 1) + samelen = strlen(matches[count]); + else + while (strncmp(matches[count], matches[count-1], samelen) != 0) + samelen--; + count++; + } + } + + switch (count) { + case 0: /* should never happen */ + case 1: + goto cleanup; + case 2: + matches[0] = strdup(matches[1]); + break; + default: + matches[0] = malloc(samelen+1); + if (!matches[0]) + goto cleanup; + strncpy(matches[0], matches[1], samelen); + matches[0][samelen] = 0; + } + matches[count] = NULL; + return matches; + +cleanup: + while (i >= 0) { + free(matches[i]); + i--; + } + free(matches); + return NULL; +} + +static char **reg_complete_key(const char *text, int end) +{ + REG_KEY *subkey; + int i, j = 0; + int len; + char **matches; + /* Complete argument */ + + matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); + if (!matches) return NULL; + matches[0] = NULL; + + len = strlen(text); + for(i = 0; j < MAX_COMPLETIONS-1; i++) { + WERROR status = reg_key_get_subkey_by_index(current_key, i, &subkey); + if(W_ERROR_IS_OK(status)) { + if(!strncmp(text, reg_key_name(subkey), len)) { + matches[j] = strdup(reg_key_name(subkey)); + j++; + } + reg_key_free(subkey); + } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) { + break; + } else { + printf("Error creating completion list: %s\n", win_errstr(status)); + return NULL; + } + } + matches[j] = NULL; + return matches; +} + +static char **reg_completion(const char *text, int start, int end) +{ + smb_readline_ca_char(' '); + + if (start == 0) { + return reg_complete_command(text, end); + } else { + return reg_complete_key(text, end); + } +} + int main(int argc, char **argv) { int opt; @@ -264,7 +376,9 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey)); - line = smb_readline(prompt, NULL, NULL); + current_key = curkey; /* No way to pass a void * pointer + via readline :-( */ + line = smb_readline(prompt, NULL, reg_completion); if(!line) break; -- cgit From b49dc085afe744c17c064ea8086c523aca663933 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Sep 2004 03:37:29 +0000 Subject: r2272: fixed another couple of errors in the popt option arrays (This used to be commit 89acbf4f02ae03f0546e1633c030765a563ce958) --- source4/lib/cmdline/popt_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 7acdb34bba..51018facb8 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -389,8 +389,8 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, + { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, -- cgit From 4490c816a90871cd93b1a709bae91e5176e4f599 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 11 Sep 2004 15:05:49 +0000 Subject: r2283: Change from tridge (in his ntlm2 patch). I think the idea here is to bail out correctly when we get signing broken on TCP, rather than keeping on hammering the socket. Andrew Bartlett (This used to be commit 553b529a0991ccf2f1be14cc6a27695223f02e65) --- source4/lib/events.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 9affaf1246..06d956a014 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -310,7 +310,7 @@ void event_loop_exit(struct event_context *ev, int code) /* do a single event loop using the events defined in ev this function */ -void event_loop_once(struct event_context *ev) +int event_loop_once(struct event_context *ev) { time_t t; fd_set r_fds, w_fds; @@ -404,7 +404,7 @@ void event_loop_once(struct event_context *ev) the event, so this must be a bug. This is a fatal error. */ DEBUG(0,("EBADF on event_loop_once - exiting\n")); - return; + return -1; } if (selrtn > 0) { @@ -442,6 +442,8 @@ void event_loop_once(struct event_context *ev) } te = next; } + + return 0; } /* @@ -459,7 +461,9 @@ int event_loop_wait(struct event_context *ev) ev->exit.exit_now = False; while (ev->fd_events && !ev->exit.exit_now) { - event_loop_once(ev); + if (event_loop_once(ev) != 0) { + break; + } } return ev->exit.code; -- cgit From 871604e3101edfd4c17eec5b05077eeb5674b26b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Sep 2004 01:27:37 +0000 Subject: r2302: added a '--option' option, allowing any global or default option in smb.conf to be set on the command line. For example, you can use: smbtorture --option 'unicode=false' or smbtorture --option 'netbios name=myname' (This used to be commit 360a6b530e2295976ddefc138d1333411a94484d) --- source4/lib/cmdline/popt_common.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 51018facb8..e2deb5db96 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -33,6 +33,9 @@ * -i,--scope */ + +enum {OPT_OPTION=1}; + static struct cmdline_auth_info cmdline_auth_info; static void popt_common_callback(poptContext con, @@ -40,7 +43,6 @@ static void popt_common_callback(poptContext con, const struct poptOption *opt, const char *arg, const void *data) { - pstring logfile; const char *pname; /* Find out basename of current program */ @@ -52,8 +54,9 @@ static void popt_common_callback(poptContext con, pname++; if (reason == POPT_CALLBACK_REASON_PRE) { - pstr_sprintf(logfile, "%s/log.%s", dyn_LOGFILEBASE, pname); + char *logfile = talloc_asprintf(NULL, "%s/log.%s", dyn_LOGFILEBASE, pname); lp_set_cmdline("log file", logfile); + talloc_free(logfile); return; } @@ -81,8 +84,9 @@ static void popt_common_callback(poptContext con, case 'l': if (arg) { - pstr_sprintf(logfile, "%s/log.%s", arg, pname); + char *logfile = talloc_asprintf(NULL, "%s/log.%s", arg, pname); lp_set_cmdline("log file", logfile); + talloc_free(logfile); } break; @@ -105,6 +109,13 @@ static void popt_common_callback(poptContext con, case 'R': lp_set_cmdline("name resolve order", arg); break; + + case OPT_OPTION: + if (!lp_set_option(arg)) { + fprintf(stderr, "Error setting option '%s'\n", arg); + exit(1); + } + break; } } @@ -123,6 +134,7 @@ struct poptOption popt_common_samba[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, + { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, POPT_TABLEEND }; -- cgit From 9922a795d44e624387c74e1097bf2507fe2b2d16 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Sep 2004 05:01:15 +0000 Subject: r2308: make talloc_vasprintf() available outside talloc.c (This used to be commit a3a15f9d1a3b51cb7099b5f3adb8401dfc37793d) --- source4/lib/talloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 036d06a2c2..e9fd7e8baf 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -395,8 +395,7 @@ char *talloc_strndup(void *t, const char *p, size_t n) return ret; } -static char *talloc_vasprintf(void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -static char *talloc_vasprintf(void *t, const char *fmt, va_list ap) +char *talloc_vasprintf(void *t, const char *fmt, va_list ap) { int len; char *ret; -- cgit From 59b0902d0864101b9861d8ab59402b3088db7ff7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Sep 2004 10:15:55 +0000 Subject: r2319: let event_merge_contexts() return a pointer to the final context metze (This used to be commit 71aa5eeea73ea42e04ae224914b6815d72c1690a) --- source4/lib/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 06d956a014..298aa6a7b8 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -149,7 +149,7 @@ static void calc_maxfd(struct event_context *ev) this is used by modules that need to call on the events of a lower module */ -void event_context_merge(struct event_context *ev, struct event_context *ev2) +struct event_context * event_context_merge(struct event_context *ev, struct event_context *ev2) { DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *); DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *); @@ -164,6 +164,8 @@ void event_context_merge(struct event_context *ev, struct event_context *ev2) event_context_destroy(ev2); calc_maxfd(ev); + + return ev; } -- cgit From ce694e7051dca90cdb5700e3865315d16931c3c1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Sep 2004 14:17:41 +0000 Subject: r2328: add the start of a new system and protocol independent socket library. this is not used, but compiled currently there're maybe some api changes later... metze (This used to be commit de4447d7a57c614b80d0ac00dca900ea7e1c21ea) --- source4/lib/socket/config.m4 | 4 + source4/lib/socket/config.mk | 16 +++ source4/lib/socket/socket.c | 215 ++++++++++++++++++++++++++++ source4/lib/socket/socket.h | 93 +++++++++++++ source4/lib/socket/socket_ipv4.c | 293 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 621 insertions(+) create mode 100644 source4/lib/socket/config.m4 create mode 100644 source4/lib/socket/config.mk create mode 100644 source4/lib/socket/socket.c create mode 100644 source4/lib/socket/socket.h create mode 100644 source4/lib/socket/socket_ipv4.c (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 new file mode 100644 index 0000000000..a5d3d0916e --- /dev/null +++ b/source4/lib/socket/config.m4 @@ -0,0 +1,4 @@ + +SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) + +SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk new file mode 100644 index 0000000000..854702a6f8 --- /dev/null +++ b/source4/lib/socket/config.mk @@ -0,0 +1,16 @@ + +################################################ +# Start MODULE socket_ipv4 +[MODULE::socket_ipv4] +INIT_OBJ_FILES = \ + lib/socket/socket_ipv4.o +# End MODULE socket_ipv4 +################################################ + +################################################ +# Start SUBSYSTEM SOCKET +[SUBSYSTEM::SOCKET] +INIT_OBJ_FILES = \ + lib/socket/socket.o +# End SUBSYSTEM SOCKET +################################################ diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c new file mode 100644 index 0000000000..fefd7a14b2 --- /dev/null +++ b/source4/lib/socket/socket.c @@ -0,0 +1,215 @@ +/* + Unix SMB/CIFS implementation. + Socket functions + Copyright (C) Stefan Metzmacher 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags) +{ + NTSTATUS status; + + (*new_sock) = talloc_p(NULL, struct socket_context); + if (!(*new_sock)) { + return NT_STATUS_NO_MEMORY; + } + + (*new_sock)->type = type; + (*new_sock)->state = SOCKET_STATE_UNDEFINED; + (*new_sock)->flags = flags; + + (*new_sock)->fd = -1; + + (*new_sock)->private_data = NULL; + (*new_sock)->ops = socket_getops_byname(name, type); + if (!(*new_sock)->ops) { + talloc_free((*new_sock)); + return status; + } + + status = (*new_sock)->ops->init((*new_sock)); + if (!NT_STATUS_IS_OK(status)) { + talloc_free((*new_sock)); + return status; + } + + return NT_STATUS_OK; +} + +void socket_destroy(struct socket_context *sock) +{ + if (sock->ops->close) { + sock->ops->close(sock); + } + talloc_free(sock); +} + +NTSTATUS socket_connect(struct socket_context *sock, + const char *my_address, int my_port, + const char *server_address, int server_port, + uint32_t flags) +{ + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state != SOCKET_STATE_UNDEFINED) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->connect) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->connect(sock, my_address, my_port, server_address, server_port, flags); +} + +NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) +{ + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state != SOCKET_STATE_UNDEFINED) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->listen) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->listen(sock, my_address, port, queue_size, flags); +} + +NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +{ + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state != SOCKET_STATE_SERVER_LISTEN) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->accept) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->accept(sock, new_sock, flags); +} + +NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, size_t wantlen, uint32_t flags) +{ + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state != SOCKET_STATE_CLIENT_CONNECTED || + sock->state != SOCKET_STATE_SERVER_CONNECTED) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->recv) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->recv(sock, mem_ctx, blob, wantlen, flags); +} + +NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +{ + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state != SOCKET_STATE_CLIENT_CONNECTED || + sock->state != SOCKET_STATE_SERVER_CONNECTED) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->send) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->send(sock, mem_ctx, blob, sendlen, flags); +} + +NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) +{ + if (!sock->ops->set_option) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->set_option(sock, option, val); +} + +const char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_peer_addr) { + return NULL; + } + + return sock->ops->get_peer_addr(sock, mem_ctx); +} + +int socket_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_peer_port) { + return -1; + } + + return sock->ops->get_peer_port(sock, mem_ctx); +} + +const char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_my_addr) { + return NULL; + } + + return sock->ops->get_my_addr(sock, mem_ctx); +} + +int socket_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_my_port) { + return -1; + } + + return sock->ops->get_my_port(sock, mem_ctx); +} + +int socket_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_fd) { + return -1; + } + + return sock->ops->get_fd(sock, mem_ctx); +} + +const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) +{ + if (strequal("ip", name) || strequal("ipv4", name)) { + return socket_ipv4_ops(); + } + + return NULL; +} diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h new file mode 100644 index 0000000000..dfc964b741 --- /dev/null +++ b/source4/lib/socket/socket.h @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + Socket functions + Copyright (C) Stefan Metzmacher 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SAMBA_SOCKET_H +#define _SAMBA_SOCKET_H + +struct socket_context; + +enum socket_type { + SOCKET_TYPE_STREAM +}; + +struct socket_ops { + const char *name; + enum socket_type type; + + NTSTATUS (*init)(struct socket_context *sock); + + /* client ops */ + NTSTATUS (*connect)(struct socket_context *sock, + const char *my_address, int my_port, + const char *server_address, int server_port, + uint32_t flags); + + /* server ops */ + NTSTATUS (*listen)(struct socket_context *sock, + const char *my_address, int port, int queue_size, uint32_t flags); + NTSTATUS (*accept)(struct socket_context *sock, + struct socket_context **new_sock, uint32_t flags); + + /* general ops */ + NTSTATUS (*recv)(struct socket_context *sock, TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, size_t wantlen, uint32_t flags); + NTSTATUS (*send)(struct socket_context *sock, TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); + + void (*close)(struct socket_context *sock); + + NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val); + + const char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*get_peer_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + const char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*get_my_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + + int (*get_fd)(struct socket_context *sock, TALLOC_CTX *mem_ctx); +}; + +enum socket_state { + SOCKET_STATE_UNDEFINED, + + SOCKET_STATE_CLIENT_START, + SOCKET_STATE_CLIENT_CONNECTED, + SOCKET_STATE_CLIENT_STARTTLS, + SOCKET_STATE_CLIENT_ERROR, + + SOCKET_STATE_SERVER_LISTEN, + SOCKET_STATE_SERVER_CONNECTED, + SOCKET_STATE_SERVER_STARTTLS, + SOCKET_STATE_SERVER_ERROR +}; + +#define SOCKET_OPTION_BLOCK 0x00000001 + +struct socket_context { + enum socket_type type; + enum socket_state state; + uint32_t flags; + + int fd; + + void *private_data; + const struct socket_ops *ops; +}; + +#endif /* _SAMBA_SOCKET_H */ diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c new file mode 100644 index 0000000000..90f289a1e0 --- /dev/null +++ b/source4/lib/socket/socket_ipv4.c @@ -0,0 +1,293 @@ +/* + Unix SMB/CIFS implementation. + Socket IPv4 functions + Copyright (C) Stefan Metzmacher 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static NTSTATUS ipv4_tcp_init(struct socket_context *sock) +{ + sock->fd = socket(PF_INET, SOCK_STREAM, 0); + if (sock->fd == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + return NT_STATUS_OK; +} + +static void ipv4_tcp_close(struct socket_context *sock) +{ + close(sock->fd); +} + +static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, + const char *my_address, int my_port, + const char *srv_address, int srv_port, + uint32_t flags) +{ + struct sockaddr_in my_addr; + struct sockaddr_in srv_addr; + struct in_addr my_ip; + struct in_addr srv_ip; + int ret; + + ret = inet_aton(my_address, &my_ip); + if (ret == 0) { + /* not a valid ipv4 address */ + return NT_STATUS_FOOBAR; + } + + ZERO_STRUCT(my_addr); +#ifdef HAVE_SOCK_SIN_LEN + my_addr.sin_len = sizeof(my_addr); +#endif + my_addr.sin_addr = my_ip; + my_addr.sin_port = htons(my_port); + my_addr.sin_family = PF_INET; + + ret = inet_aton(srv_address, &srv_ip); + if (ret == 0) { + /* not a valid ipv4 address */ + return NT_STATUS_FOOBAR; + } + + ret = bind(sock->fd, &my_addr, sizeof(my_addr)); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + ZERO_STRUCT(srv_addr); +#ifdef HAVE_SOCK_SIN_LEN + srv_addr.sin_len = sizeof(srv_addr); +#endif + srv_addr.sin_addr = srv_ip; + srv_addr.sin_port = htons(srv_port); + srv_addr.sin_family = PF_INET; + + if (!(flags & SOCKET_OPTION_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + } + + + ret = connect(sock->fd, &srv_addr, sizeof(srv_addr)); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, + const char *my_address, int port, + int queue_size, uint32_t flags) +{ + struct sockaddr_in my_addr; + struct in_addr ip_addr; + int ret; + + ZERO_STRUCT(my_addr); + + ret = inet_aton(my_address, &ip_addr); + if (ret == 0) { + /* not a valid ipv4 address */ + return NT_STATUS_FOOBAR; + } + +#ifdef HAVE_SOCK_SIN_LEN + my_addr.sin_len = sizeof(my_addr); +#endif + my_addr.sin_addr = ip_addr; + my_addr.sin_port = htons(port); + my_addr.sin_family = PF_INET; + + ret = bind(sock->fd, &my_addr, sizeof(my_addr)); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + ret = listen(sock->fd, queue_size); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +{ + struct sockaddr_in cli_addr; + socklen_t cli_addr_len = 0; + int new_fd; + int ret; + + new_fd = accept(sock->fd, &cli_addr, &cli_addr_len); + if (new_fd == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + if (!(flags & SOCKET_OPTION_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + } + + /* TODO: we could add a 'accept_check' hook here + * which get the black/white lists via socket_set_accept_filter() + * or something like that + * --metze + */ + + (*new_sock) = talloc_p(NULL, struct socket_context); + if (!(*new_sock)) { + return NT_STATUS_NO_MEMORY; + } + + /* copy the socket_context */ + (*new_sock)->type = sock->type; + (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; + (*new_sock)->flags = flags; + + (*new_sock)->fd = new_fd; + + (*new_sock)->private_data = NULL; + (*new_sock)->ops = sock->ops; + + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, size_t wantlen, uint32_t flags) +{ + ssize_t gotlen; + void *buf; + int flgs = 0; + + buf = talloc(mem_ctx, wantlen); + if (!buf) { + return NT_STATUS_NO_MEMORY; + } + + /* TODO: we need to map the flags here */ + + gotlen = recv(sock->fd, buf, wantlen, flgs); + if (gotlen == -1) { + talloc_free(buf); + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + blob->length = gotlen; + blob->data = buf; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +{ + ssize_t len; + int flgs = 0; + + /* TODO: we need to map the flags here */ + + len = send(sock->fd, blob->data, blob->length, flgs); + if (len == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + + *sendlen = len; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *option, const char *val) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static const char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return NULL; +} + +static int ipv4_tcp_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return -1; +} + +static const char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return NULL; +} + +static int ipv4_tcp_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return -1; +} + +static int ipv4_tcp_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return sock->fd; +} + +static const struct socket_ops ipv4_tcp_ops = { + .name = "ipv4", + .type = SOCKET_TYPE_STREAM, + + .init = ipv4_tcp_init, + .connect = ipv4_tcp_connect, + .listen = ipv4_tcp_listen, + .accept = ipv4_tcp_accept, + .recv = ipv4_tcp_recv, + .send = ipv4_tcp_send, + .close = ipv4_tcp_close, + + .set_option = ipv4_tcp_set_option, + + .get_peer_addr = ipv4_tcp_get_peer_addr, + .get_peer_port = ipv4_tcp_get_peer_port, + .get_my_addr = ipv4_tcp_get_my_addr, + .get_my_port = ipv4_tcp_get_my_port, + + .get_fd = ipv4_tcp_get_fd +}; + +const struct socket_ops *socket_ipv4_ops(void) +{ + return &ipv4_tcp_ops; +} + +NTSTATUS socket_ipv4_init(void) +{ + return NT_STATUS_OK; +} -- cgit From 498ea8485f8763a1c4e39bf49cd0b68004b2f8c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Sep 2004 12:14:47 +0000 Subject: r2343: - make socket_get_*_addr() return char * not const char * - add some error mappings - use some flags SOCKET_FLAG_PEEK ans SOCKET_FLAG_BLOCK metze (This used to be commit a375c6b0b1ec4d63251f63993f7798c1f2e7c717) --- source4/lib/socket/socket.c | 4 +- source4/lib/socket/socket.h | 7 +-- source4/lib/socket/socket_ipv4.c | 104 ++++++++++++++++++++++++++++++--------- 3 files changed, 87 insertions(+), 28 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index fefd7a14b2..5fd587a635 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -160,7 +160,7 @@ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, cons return sock->ops->set_option(sock, option, val); } -const char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { if (!sock->ops->get_peer_addr) { return NULL; @@ -178,7 +178,7 @@ int socket_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) return sock->ops->get_peer_port(sock, mem_ctx); } -const char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { if (!sock->ops->get_my_addr) { return NULL; diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index dfc964b741..10e937c4e2 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -55,9 +55,9 @@ struct socket_ops { NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val); - const char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); int (*get_peer_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - const char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); int (*get_my_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); int (*get_fd)(struct socket_context *sock, TALLOC_CTX *mem_ctx); @@ -77,7 +77,8 @@ enum socket_state { SOCKET_STATE_SERVER_ERROR }; -#define SOCKET_OPTION_BLOCK 0x00000001 +#define SOCKET_FLAG_BLOCK 0x00000001 +#define SOCKET_FLAG_PEEK 0x00000002 struct socket_context { enum socket_type type; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 90f289a1e0..136fc877d2 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -81,7 +81,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, srv_addr.sin_port = htons(srv_port); srv_addr.sin_family = PF_INET; - if (!(flags & SOCKET_OPTION_BLOCK)) { + if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, False); if (ret == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ @@ -136,6 +136,14 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, return NT_STATUS_FOOBAR; } + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + /* TODO: we need to map from errno to NTSTATUS here! */ + return NT_STATUS_FOOBAR; + } + } + return NT_STATUS_NOT_IMPLEMENTED; } @@ -144,7 +152,6 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte struct sockaddr_in cli_addr; socklen_t cli_addr_len = 0; int new_fd; - int ret; new_fd = accept(sock->fd, &cli_addr, &cli_addr_len); if (new_fd == -1) { @@ -152,14 +159,6 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return NT_STATUS_FOOBAR; } - if (!(flags & SOCKET_OPTION_BLOCK)) { - ret = set_blocking(sock->fd, False); - if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; - } - } - /* TODO: we could add a 'accept_check' hook here * which get the black/white lists via socket_set_accept_filter() * or something like that @@ -181,7 +180,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte (*new_sock)->private_data = NULL; (*new_sock)->ops = sock->ops; - return NT_STATUS_NOT_IMPLEMENTED; + return NT_STATUS_OK; } static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, @@ -196,17 +195,46 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - /* TODO: we need to map the flags here */ + /* TODO: we need to map all flags here */ + if (flags & SOCKET_FLAG_PEEK) { + flgs |= MSG_PEEK; + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + flgs |= MSG_DONTWAIT; + } gotlen = recv(sock->fd, buf, wantlen, flgs); - if (gotlen == -1) { + if (gotlen == 0) { talloc_free(buf); - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return NT_STATUS_END_OF_FILE; + } else if (gotlen == -1) { + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + switch (errno) { + case EBADF: + case ENOTCONN: + case ENOTSOCK: + case EFAULT: + case EINVAL: + status = NT_STATUS_INVALID_PARAMETER; + break; + case EAGAIN: + case EINTR: + status = STATUS_MORE_ENTRIES; + break; + case ECONNREFUSED: + status = NT_STATUS_CONNECTION_REFUSED; + break; + } + talloc_free(buf); + return status; } blob->length = gotlen; - blob->data = buf; + blob->data = talloc_realloc(buf, gotlen); + if (!blob->data) { + return NT_STATUS_NO_MEMORY; + } return NT_STATUS_OK; } @@ -215,14 +243,43 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; - int flgs = 0; + int flgs = MSG_NOSIGNAL; - /* TODO: we need to map the flags here */ + /* TODO: we need to map all flags here */ + if (!(flags & SOCKET_FLAG_BLOCK)) { + flgs |= MSG_DONTWAIT; + } len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + switch (errno) { + case EBADF: + case ENOTSOCK: + case EFAULT: + case EINVAL: + status = NT_STATUS_INVALID_PARAMETER; + break; + case EMSGSIZE: + status = NT_STATUS_INVALID_BUFFER_SIZE; + break; + case EAGAIN: + /*case EWOULDBLOCK: this is an alis of EAGAIN --metze */ + case EINTR: + *sendlen = 0; + status = STATUS_MORE_ENTRIES; + break; + case ENOBUFS: + status = NT_STATUS_FOOBAR; + break; + case ENOMEM: + status = NT_STATUS_NO_MEMORY; + break; + case EPIPE: + status = NT_STATUS_CONNECTION_DISCONNECTED; + break; + } + return status; } *sendlen = len; @@ -232,10 +289,11 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *option, const char *val) { - return NT_STATUS_NOT_SUPPORTED; + set_socket_options(sock->fd, option); + return NT_STATUS_OK; } -static const char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { return NULL; } @@ -245,7 +303,7 @@ static int ipv4_tcp_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_c return -1; } -static const char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { return NULL; } -- cgit From bc6d0b0f0f6bc83f921ec7b935f8d0e0decfec5d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Sep 2004 05:30:19 +0000 Subject: r2365: remove MSG_NOSIGNAL metze (This used to be commit 8ade8ab65fffea9172a768a60fe2bd32493c068f) --- source4/lib/socket/socket_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 136fc877d2..9246ac4070 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -243,7 +243,7 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; - int flgs = MSG_NOSIGNAL; + int flgs = 0; /* TODO: we need to map all flags here */ if (!(flags & SOCKET_FLAG_BLOCK)) { -- cgit From 66f1e8d020709aa66b3b64c9b583fd326aa6d3b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Sep 2004 10:41:53 +0000 Subject: r2380: nicer error reporting in convert_string() (This used to be commit 6807d336c2365e4e7f45605d75667dbf05715b34) --- source4/lib/charcnv.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 2109e957d9..f30f5b9239 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -161,12 +161,15 @@ ssize_t convert_string(charset_t from, charset_t to, break; case E2BIG: reason="No more room"; - DEBUG(0, ("convert_string: Required %d, available %d\n", - srclen, destlen)); - /* we are not sure we need srclen bytes, - may be more, may be less. - We only know we need more than destlen - bytes ---simo */ + if (from == CH_UNIX) { + DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n", + charset_name(from), charset_name(to), + srclen, destlen, (const char *)src)); + } else { + DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n", + charset_name(from), charset_name(to), + srclen, destlen)); + } break; case EILSEQ: reason="Illegal multibyte sequence"; -- cgit From be480ac55c1f3ebe29781ad718f28e5b95441d13 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Sep 2004 10:42:33 +0000 Subject: r2381: added a -v debugging option to ldbedit (This used to be commit 03d4a7832cd3670a8166820a1b9b4aaf2307bd1a) --- source4/lib/ldb/tools/ldbedit.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 90a6f94750..b97c40ff1a 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -34,6 +34,22 @@ #include "includes.h" +static int verbose; + +/* + debug routine +*/ +static void ldif_write_msg(struct ldb_context *ldb, + FILE *f, + enum ldb_changetype changetype, + struct ldb_message *msg) +{ + struct ldb_ldif ldif; + ldif.changetype = changetype; + ldif.msg = *msg; + ldb_ldif_write_file(ldb, f, &ldif); +} + /* modify a database record so msg1 becomes msg2 returns the number of modified elements @@ -91,6 +107,10 @@ static int modify_record(struct ldb_context *ldb, return -1; } + if (verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, &mod); + } + return count; } @@ -130,6 +150,9 @@ static int merge_edits(struct ldb_context *ldb, msgs2[i]->dn, ldb_errstring(ldb)); return -1; } + if (verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); + } adds++; } else { if (modify_record(ldb, msg, msgs2[i]) > 0) { @@ -147,6 +170,9 @@ static int merge_edits(struct ldb_context *ldb, msgs1[i]->dn, ldb_errstring(ldb)); return -1; } + if (verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); + } deletes++; } } @@ -295,7 +321,7 @@ static void usage(void) editor = "vi"; } - while ((opt = getopt(argc, argv, "hab:e:H:s:")) != EOF) { + while ((opt = getopt(argc, argv, "hab:e:H:s:v")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -323,6 +349,10 @@ static void usage(void) expression = "(|(objectclass=*)(dn=*))"; break; + case 'v': + verbose++; + break; + case 'h': default: usage(); -- cgit From b3da2c10e268b9d4fe621ec21ab39e4aa45795e9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Sep 2004 08:12:55 +0000 Subject: r2400: make ms_fnmatch() case insensitive. This is much more efficient than uppercasing the two whole strings before the call is made, is less error-prone, and also copes with strings where the upper case version is longer than the lower case version due to different multi-byte lengths. (This used to be commit e227ac1edfd48596a9d5096b6965ddd0beb969a5) --- source4/lib/ms_fnmatch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index 1c4b3d1806..5a9edc2c87 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -94,7 +94,8 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, break; default: - if (c != *n) goto nomatch; + if (c != *n && + toupper_w(c) != toupper_w(*n)) goto nomatch; n++; } } @@ -198,7 +199,8 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, break; default: - if (c != *n) return -1; + if (c != *n && + toupper_w(c) != toupper_w(*n)) return -1; n++; } } -- cgit From f25681b120555bfee99b4a3079479cb3b64e2ca6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Sep 2004 08:13:28 +0000 Subject: r2402: to make ms_fnmatch() case-insensitive we need toupper_w() exposed (This used to be commit 69413bdcfcf40e9ae2e5bcb00863cc7ef0ee8da1) --- source4/lib/util_unistr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 63d68fa12e..4b303a894d 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -162,7 +162,7 @@ void init_valid_table(void) Convert a wchar to upper case. ********************************************************************/ -static smb_ucs2_t toupper_w(smb_ucs2_t val) +smb_ucs2_t toupper_w(smb_ucs2_t val) { return upcase_table[SVAL(&val,0)]; } -- cgit From 9c69372fb2e7ab9b4100e0e3ea10142a38a4df97 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Sep 2004 07:21:26 +0000 Subject: r2430: got rid of StrnCaseCmp and added an accelerated version of StrCaseCmp() for places where known ascii strings are being compared we should just use strncasecmp() and other standard library functions (with replacements via lib/replace.c if needed) (This used to be commit 869b757bba729c9ecd720e3956958efc7541f353) --- source4/lib/util_str.c | 107 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 29 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index fc76aed44a..961bdb8084 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -118,25 +118,44 @@ char **toktocliplist(const char *ptr, int *ctok, const char *sep) /** Case insensitive string compararison. **/ - -int StrCaseCmp(const char *s, const char *t) +static int StrCaseCmp_slow(const char *s1, const char *s2) { - pstring buf1, buf2; - unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); - unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2)); - return strcmp(buf1,buf2); + smb_ucs2_t *u1, *u2; + int ret; + + convert_string_allocate(CH_UNIX, CH_UTF16, s1, strlen(s1)+1, &u1); + convert_string_allocate(CH_UNIX, CH_UTF16, s2, strlen(s2)+1, &u2); + + ret = strcasecmp_w(u1, u2); + + free(u1); + free(u2); + + return ret; } /** - Case insensitive string compararison, length limited. + Case insensitive string compararison, accelerated version **/ - -int StrnCaseCmp(const char *s, const char *t, size_t n) +int StrCaseCmp(const char *s1, const char *s2) { - pstring buf1, buf2; - unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1)); - unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2)); - return strncmp(buf1,buf2,n); + while (*s1 && *s2 && + (*s1 & 0x80) == 0 && + (*s2 & 0x80) == 0) { + char u1 = toupper(*s1); + char u2 = toupper(*s2); + if (u1 != u2) { + return u2 - u1; + } + s1++; + s2++; + } + + if (*s1 == 0 || *s2 == 0) { + return *s2 - *s1; + } + + return StrCaseCmp_slow(s1, s2); } /** @@ -154,21 +173,6 @@ BOOL strequal(const char *s1, const char *s2) return(StrCaseCmp(s1,s2)==0); } -/** - * Compare 2 strings up to and including the nth char. - * - * @note The comparison is case-insensitive. - **/ -BOOL strnequal(const char *s1,const char *s2,size_t n) -{ - if (s1 == s2) - return(True); - if (!s1 || !s2 || !n) - return(False); - - return(StrnCaseCmp(s1,s2,n)==0); -} - /** Compare 2 strings (case sensitive). **/ @@ -1196,7 +1200,7 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex) char *p1 = NULL, *p2 = NULL; for (i = 0; i < len && strhex[i] != 0; i++) { - if (strnequal(hexchars, "0x", 2)) { + if (strncasecmp(hexchars, "0x", 2) == 0) { i++; /* skip two chars */ continue; } @@ -1460,3 +1464,48 @@ int strcmp_safe(const char *s1, const char *s2) } return strcmp(s1, s2); } + + +/******************************************************************* + Return a string representing a CIFS attribute for a file. +********************************************************************/ +char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) +{ + int i, len; + const struct { + char c; + uint16_t attr; + } attr_strs[] = { + {'V', FILE_ATTRIBUTE_VOLUME}, + {'D', FILE_ATTRIBUTE_DIRECTORY}, + {'A', FILE_ATTRIBUTE_ARCHIVE}, + {'H', FILE_ATTRIBUTE_HIDDEN}, + {'S', FILE_ATTRIBUTE_SYSTEM}, + {'R', FILE_ATTRIBUTE_READONLY}, + {'d', FILE_ATTRIBUTE_DEVICE}, + {'t', FILE_ATTRIBUTE_TEMPORARY}, + {'s', FILE_ATTRIBUTE_SPARSE}, + {'r', FILE_ATTRIBUTE_REPARSE_POINT}, + {'c', FILE_ATTRIBUTE_COMPRESSED}, + {'o', FILE_ATTRIBUTE_OFFLINE}, + {'n', FILE_ATTRIBUTE_NONINDEXED}, + {'e', FILE_ATTRIBUTE_ENCRYPTED} + }; + char *ret; + + ret = talloc(mem_ctx, ARRAY_SIZE(attr_strs)+1); + if (!ret) { + return NULL; + } + + for (len=i=0; i Date: Mon, 20 Sep 2004 07:31:54 +0000 Subject: r2437: implemented a suggestion from abartlet that if we cannot convert strings to UTF16 in StrCaseCmp() that we fall back to a simpler comparison. (This used to be commit 2fa6ab9fe30aeacd7b1421fd83c409acf31c98aa) --- source4/lib/util_str.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 961bdb8084..3fe6fd1cc0 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -123,8 +123,11 @@ static int StrCaseCmp_slow(const char *s1, const char *s2) smb_ucs2_t *u1, *u2; int ret; - convert_string_allocate(CH_UNIX, CH_UTF16, s1, strlen(s1)+1, &u1); - convert_string_allocate(CH_UNIX, CH_UTF16, s2, strlen(s2)+1, &u2); + if (convert_string_allocate(CH_UNIX, CH_UTF16, s1, strlen(s1)+1, &u1) == -1 || + convert_string_allocate(CH_UNIX, CH_UTF16, s2, strlen(s2)+1, &u2) == -1) { + /* fallback to a simple comparison */ + return strcasecmp(s1, s2); + } ret = strcasecmp_w(u1, u2); -- cgit From be61c9d8773eb3d0dd97bcd5e9ccd3f1aabcd1d6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 20 Sep 2004 09:13:17 +0000 Subject: r2439: - function that return just an int don't need a TALLOC_CTX - fix some return and state bugs metze (This used to be commit 2757c593ab746b9dd7090f2cf5fcc31686adf67f) --- source4/lib/socket/socket.c | 18 +++++++++--------- source4/lib/socket/socket.h | 6 +++--- source4/lib/socket/socket_ipv4.c | 19 ++++++++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 5fd587a635..6869114587 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -39,7 +39,7 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co (*new_sock)->ops = socket_getops_byname(name, type); if (!(*new_sock)->ops) { talloc_free((*new_sock)); - return status; + return NT_STATUS_INVALID_PARAMETER; } status = (*new_sock)->ops->init((*new_sock)); @@ -120,7 +120,7 @@ NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_PARAMETER; } - if (sock->state != SOCKET_STATE_CLIENT_CONNECTED || + if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED) { return NT_STATUS_INVALID_PARAMETER; } @@ -139,7 +139,7 @@ NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_PARAMETER; } - if (sock->state != SOCKET_STATE_CLIENT_CONNECTED || + if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED) { return NT_STATUS_INVALID_PARAMETER; } @@ -169,13 +169,13 @@ char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) return sock->ops->get_peer_addr(sock, mem_ctx); } -int socket_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +int socket_get_peer_port(struct socket_context *sock) { if (!sock->ops->get_peer_port) { return -1; } - return sock->ops->get_peer_port(sock, mem_ctx); + return sock->ops->get_peer_port(sock); } char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) @@ -187,22 +187,22 @@ char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) return sock->ops->get_my_addr(sock, mem_ctx); } -int socket_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +int socket_get_my_port(struct socket_context *sock) { if (!sock->ops->get_my_port) { return -1; } - return sock->ops->get_my_port(sock, mem_ctx); + return sock->ops->get_my_port(sock); } -int socket_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx) +int socket_get_fd(struct socket_context *sock) { if (!sock->ops->get_fd) { return -1; } - return sock->ops->get_fd(sock, mem_ctx); + return sock->ops->get_fd(sock); } const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 10e937c4e2..ea4de1d291 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -56,11 +56,11 @@ struct socket_ops { NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val); char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - int (*get_peer_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*get_peer_port)(struct socket_context *sock); char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - int (*get_my_port)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*get_my_port)(struct socket_context *sock); - int (*get_fd)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*get_fd)(struct socket_context *sock); }; enum socket_state { diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 9246ac4070..f423ded302 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -67,7 +67,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, return NT_STATUS_FOOBAR; } - ret = bind(sock->fd, &my_addr, sizeof(my_addr)); + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ return NT_STATUS_FOOBAR; @@ -90,7 +90,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, } - ret = connect(sock->fd, &srv_addr, sizeof(srv_addr)); + ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (ret == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ return NT_STATUS_FOOBAR; @@ -109,14 +109,13 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, struct in_addr ip_addr; int ret; - ZERO_STRUCT(my_addr); - ret = inet_aton(my_address, &ip_addr); if (ret == 0) { /* not a valid ipv4 address */ return NT_STATUS_FOOBAR; } + ZERO_STRUCT(my_addr); #ifdef HAVE_SOCK_SIN_LEN my_addr.sin_len = sizeof(my_addr); #endif @@ -124,7 +123,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, my_addr.sin_port = htons(port); my_addr.sin_family = PF_INET; - ret = bind(sock->fd, &my_addr, sizeof(my_addr)); + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ return NT_STATUS_FOOBAR; @@ -144,7 +143,9 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, } } - return NT_STATUS_NOT_IMPLEMENTED; + sock->state= SOCKET_STATE_SERVER_LISTEN; + + return NT_STATUS_OK; } static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) @@ -298,7 +299,7 @@ static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem return NULL; } -static int ipv4_tcp_get_peer_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static int ipv4_tcp_get_peer_port(struct socket_context *sock) { return -1; } @@ -308,12 +309,12 @@ static char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_c return NULL; } -static int ipv4_tcp_get_my_port(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static int ipv4_tcp_get_my_port(struct socket_context *sock) { return -1; } -static int ipv4_tcp_get_fd(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static int ipv4_tcp_get_fd(struct socket_context *sock) { return sock->fd; } -- cgit From 61ef24537253ae155b2785a27f9549a6538f8224 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 20 Sep 2004 10:20:26 +0000 Subject: r2441: set exit code correct when we got EBADF from select() metze (This used to be commit 36bf2f3eaf2e7568563cd98dc941d20f4574d271) --- source4/lib/events.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 298aa6a7b8..4ae7cad8af 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -406,6 +406,7 @@ int event_loop_once(struct event_context *ev) the event, so this must be a bug. This is a fatal error. */ DEBUG(0,("EBADF on event_loop_once - exiting\n")); + ev->exit.code = EBADF; return -1; } -- cgit From e8d244251732cd744c2c69e3e7bd7a875e704a60 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 20 Sep 2004 12:03:49 +0000 Subject: r2446: implement socket_get__() for ipv4 metze (This used to be commit a8ebb5c5bc6a8651867b46e87cf223cddf444e89) --- source4/lib/socket/socket_ipv4.c | 45 +++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index f423ded302..9a1e7e43f6 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -89,7 +89,6 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, } } - ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (ret == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ @@ -296,22 +295,58 @@ static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *opt static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { - return NULL; + struct sockaddr_in peer_addr; + socklen_t len = sizeof(peer_addr); + int ret; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return NULL; + } + + return talloc_strdup(mem_ctx, inet_ntoa(peer_addr.sin_addr)); } static int ipv4_tcp_get_peer_port(struct socket_context *sock) { - return -1; + struct sockaddr_in peer_addr; + socklen_t len = sizeof(peer_addr); + int ret; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return -1; + } + + return ntohs(peer_addr.sin_port); } static char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { - return NULL; + struct sockaddr_in my_addr; + socklen_t len = sizeof(my_addr); + int ret; + + ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len); + if (ret == -1) { + return NULL; + } + + return talloc_strdup(mem_ctx, inet_ntoa(my_addr.sin_addr)); } static int ipv4_tcp_get_my_port(struct socket_context *sock) { - return -1; + struct sockaddr_in my_addr; + socklen_t len = sizeof(my_addr); + int ret; + + ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len); + if (ret == -1) { + return -1; + } + + return ntohs(my_addr.sin_port); } static int ipv4_tcp_get_fd(struct socket_context *sock) -- cgit From 1ec841d33e035f11ec12edbce52eab1c559d32e6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Sep 2004 01:42:04 +0000 Subject: r2454: fixed the accelerated StrCaseCmp() so it compares in the right order (This used to be commit 4b795cbf12108e56e5e84e3073c24ce6b625e3c3) --- source4/lib/util_str.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 3fe6fd1cc0..faa8690849 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -148,14 +148,14 @@ int StrCaseCmp(const char *s1, const char *s2) char u1 = toupper(*s1); char u2 = toupper(*s2); if (u1 != u2) { - return u2 - u1; + return u1 - u2; } s1++; s2++; } if (*s1 == 0 || *s2 == 0) { - return *s2 - *s1; + return *s1 - *s2; } return StrCaseCmp_slow(s1, s2); -- cgit From a2a97238f5ade51d7908803dee11d913531b7821 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Sep 2004 02:03:34 +0000 Subject: r2484: allow ldb to build standalone again (This used to be commit 05601a4c6f7c7a019fcac8743e2e4775a498b26a) --- source4/lib/ldb/include/includes.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index e55b494b98..1d3ac2a50e 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -18,6 +18,13 @@ #include #include #include + + +#ifndef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a,b) +#endif + #include "ldb.h" #include "tdb.h" #include "proto.h" + -- cgit From 4b09c0e5d9619fea420da80022829682e028ea57 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Sep 2004 02:05:02 +0000 Subject: r2485: - add a test case in ldbtest for a bug pointed out by Jon Haswell. - fixed the bug shown with the above test, by initialising the sequence number to something different from the value used in ltdb_cache_free() (This used to be commit 856cdf82f24aada074ee5c605cccb2e8ceeea487) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 8 +++- source4/lib/ldb/tools/ldbtest.c | 83 ++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 2a879f384c..55dea406b5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -45,8 +45,12 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) struct ldb_message_element el; struct ldb_val val; int ret; + /* the initial sequence number must be different from the one + set in ltdb_cache_free(). Thanks to Jon for pointing this + out. */ + const char *initial_sequence_number = "1"; - ltdb->sequence_number = 0; + ltdb->sequence_number = atof(initial_sequence_number); msg.num_elements = 1; msg.elements = ⪙ @@ -64,7 +68,7 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) el.values = &val; el.num_values = 1; el.flags = 0; - val.data = ldb_strdup(ldb, "0"); + val.data = ldb_strdup(ldb, initial_sequence_number); if (!val.data) { ldb_free(ldb, el.name); ldb_free(ldb, msg.dn); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index d7b4023895..96d228c177 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -34,6 +34,8 @@ #include "includes.h" +static const char *ldb_url; + static struct timeval tp1,tp2; static void start_timer(void) @@ -270,6 +272,84 @@ static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) } +/* + 2) Store an @indexlist record + + 3) Store a record that contains fields that should be index according +to @index + + 4) disconnection from database + + 5) connect to same database + + 6) search for record added in step 3 using a search key that should +be indexed +*/ +static void start_test_index(struct ldb_context **ldb) +{ + struct ldb_message msg; + struct ldb_message_element el[1]; + struct ldb_val val[1]; + struct ldb_message **res; + int ret; + + printf("Starting index test\n"); + + msg.dn = strdup("@INDEXLIST"); + msg.num_elements = 1; + msg.elements = el; + + el[0].flags = 0; + el[0].name = strdup("@IDXATTR"); + el[0].num_values = 1; + el[0].values = val; + + val[0].data = strdup("test"); + val[0].length = strlen(val[0].data); + + if (ldb_add(*ldb, &msg) != 0) { + printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); + exit(1); + } + + msg.dn = strdup("test1"); + el[0].name = strdup("test"); + val[0].data = strdup("foo"); + val[0].length = strlen(val[0].data); + + if (ldb_add(*ldb, &msg) != 0) { + printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); + exit(1); + } + + if (ldb_close(*ldb) != 0) { + printf("ldb_close failed - %s\n", ldb_errstring(*ldb)); + exit(1); + } + + *ldb = ldb_connect(ldb_url, 0, NULL); + + if (!*ldb) { + perror("ldb_connect"); + exit(1); + } + + ret = ldb_search(*ldb, NULL, LDB_SCOPE_SUBTREE, "test=foo", NULL, &res); + if (ret != 1) { + printf("Should have found 1 record - found %d\n", ret); + exit(1); + } + + if (ldb_delete(*ldb, "test1") != 0 || + ldb_delete(*ldb, "@INDEXLIST") != 0) { + printf("cleanup failed - %s\n", ldb_errstring(*ldb)); + exit(1); + } + + printf("Finished index test\n"); +} + + static void usage(void) { printf("Usage: ldbtest \n"); @@ -285,7 +365,6 @@ static void usage(void) int main(int argc, char * const argv[]) { struct ldb_context *ldb; - const char *ldb_url; int opt; int nrecords = 5000; int nsearches = 2000; @@ -332,6 +411,8 @@ static void usage(void) srandom(1); + start_test_index(&ldb); + start_test(ldb, nrecords, nsearches); ldb_close(ldb); -- cgit From 787b65b048f2079c51a8f3e8ad36fcd5cde39f12 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Sep 2004 05:12:21 +0000 Subject: r2493: allow tdb to build standalone (This used to be commit 0d5af5b70bd010e7107b18f73a4b899e05c4f025) --- source4/lib/tdb/include/tdb.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index ed8c247b08..6f4f3235a7 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -85,6 +85,10 @@ struct tdb_traverse_lock { u32 hash; }; +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a,b) +#endif + /* this is the context structure that is returned from a db open */ typedef struct tdb_context { char *name; /* the name of the database */ -- cgit From 988d65c5d1d24b91d0ab5de316f892e09546984a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Sep 2004 10:36:55 +0000 Subject: r2506: Add more printf attributes for format checking. Andrew Bartlett (This used to be commit 1640272dc36a0cb5bc8e647d06c7cee46022f077) --- source4/lib/talloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index e9fd7e8baf..c236834d91 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -395,7 +395,7 @@ char *talloc_strndup(void *t, const char *p, size_t n) return ret; } -char *talloc_vasprintf(void *t, const char *fmt, va_list ap) +char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0) { int len; char *ret; @@ -437,9 +437,11 @@ char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) * accumulating output into a string buffer. **/ -char *talloc_vasprintf_append(char *s, - const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0) +static char *talloc_vasprintf_append(char *s, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static char *talloc_vasprintf_append(char *s, + const char *fmt, va_list ap) { int len, s_len; va_list ap2; -- cgit From db9ea34fd13405ecfa5644a7d27333d0e96ecef7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Sep 2004 12:15:27 +0000 Subject: r2514: Remove unused funcions, and add static. Andrew Bartlett (This used to be commit fd10c9dd536bde497829aaed9e0ba2d51ffe2315) --- source4/lib/util.c | 56 +----------------------------------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index e09796c4f3..c09e1a2997 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -525,43 +525,6 @@ BOOL process_exists(pid_t pid) return(kill(pid,0) == 0 || errno != ESRCH); } -/******************************************************************* - Convert a gid into a group name. -********************************************************************/ - -char *gidtoname(TALLOC_CTX *mem_ctx, gid_t gid) -{ - char *name; - struct group *grp; - - grp = getgrgid(gid); - if (grp) - return(grp->gr_name); - name = talloc_asprintf(mem_ctx, "%d",(int)gid); - return(name); -} - - -/******************************************************************* - Convert a name to a gid_t if possible. Return -1 if not a group. -********************************************************************/ - -gid_t nametogid(const char *name) -{ - struct group *grp; - char *p; - gid_t g; - - g = (gid_t)strtol(name, &p, 0); - if ((p != name) && (*p == '\0')) - return g; - - grp = sys_getgrnam(name); - if (grp) - return(grp->gr_gid); - return (gid_t)-1; -} - /**************************************************************************** Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping is dealt with in posix.c @@ -653,7 +616,7 @@ void set_remote_arch(struct smbsrv_connection *smb, enum remote_arch_types type) } -void print_asc(int level, const uint8_t *buf,int len) +static void print_asc(int level, const uint8_t *buf,int len) { int i; for (i=0;i Date: Wed, 22 Sep 2004 12:32:31 +0000 Subject: r2518: Some long overdue changes: - Samba4-style code in lib/registry (struct registry_key instead of REG_KEY, etc) - Use hives (like Windows has drives) instead of one root key (like a Unix FS) - usability fixes in the GTK utilities (autodetect the username, enable/disable options, etc) - fix gwsam compile - several bugfixes in the registry rpc code - do charset conversion in nt4 registry backend (This used to be commit 2762ed3b9bf1d67dd54d63e02cddbfd71ea89892) --- source4/lib/registry/TODO | 1 - source4/lib/registry/common/reg_interface.c | 493 ++++++++++----------- source4/lib/registry/common/reg_objects.c | 213 --------- source4/lib/registry/common/reg_util.c | 64 +-- source4/lib/registry/common/registry.h | 142 ------ source4/lib/registry/config.mk | 1 - .../lib/registry/reg_backend_dir/reg_backend_dir.c | 77 ++-- .../registry/reg_backend_gconf/reg_backend_gconf.c | 201 ++++----- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 65 ++- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 143 +++--- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 198 ++++----- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 166 ++++--- source4/lib/registry/tools/regdiff.c | 76 ++-- source4/lib/registry/tools/regpatch.c | 31 +- source4/lib/registry/tools/regshell.c | 128 +++--- source4/lib/registry/tools/regtree.c | 50 ++- 16 files changed, 795 insertions(+), 1254 deletions(-) delete mode 100644 source4/lib/registry/common/reg_objects.c delete mode 100644 source4/lib/registry/common/registry.h (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 695f786b69..1dea9d2650 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -1,4 +1,3 @@ -- support subtrees - ..\..\, \bla\blie support in regshell - finish rpc_server diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f0a6807558..ec6188be71 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY @@ -29,10 +28,12 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); +#define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)) + /* Register new backend */ NTSTATUS registry_register(const void *_function) { - const struct registry_ops *functions = _function; + const struct registry_operations *functions = _function; struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { @@ -91,90 +92,157 @@ BOOL reg_has_backend(const char *backend) return reg_find_backend_entry(backend) != NULL?True:False; } -/* Open a registry file/host/etc */ -WERROR reg_open(const char *backend, const char *location, const char *credentials, REG_HANDLE **h) +WERROR reg_create(struct registry_context **_ret) +{ + TALLOC_CTX *mem_ctx; + struct registry_context *ret; + mem_ctx = talloc_init("registry handle"); + ret = talloc(mem_ctx, sizeof(struct registry_context)); + ret->mem_ctx = mem_ctx; + ZERO_STRUCTP(ret); + *_ret = ret; + return WERR_OK; +} + +WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives) { struct reg_init_function_entry *entry; + + entry = reg_find_backend_entry(backend); + + if (!entry) { + DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); + return WERR_GENERAL_FAILURE; + } + + if(!entry->functions->list_available_hives) { + return WERR_NOT_SUPPORTED; + } + + return entry->functions->list_available_hives(mem_ctx, location, credentials, hives); +} + +WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) +{ + WERROR error = reg_create(ret); + char **hives; + int i; + TALLOC_CTX *mem_ctx = talloc_init("reg_open"); + + if(!W_ERROR_IS_OK(error)) return error; + + error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives); + + if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) { + return reg_import_hive(*ret, backend, location, credentials, NULL); + } + + if(!W_ERROR_IS_OK(error)) return error; + + for(i = 0; hives[i]; i++) + { + error = reg_import_hive(*ret, backend, location, credentials, hives[i]); + if(!W_ERROR_IS_OK(error)) return error; + (*ret)->hives[i]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); + } + + return WERR_OK; +} + +/* Open a registry file/host/etc */ +WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) +{ + struct registry_hive *ret; TALLOC_CTX *mem_ctx; - REG_HANDLE *ret; + struct reg_init_function_entry *entry; WERROR werr; - + entry = reg_find_backend_entry(backend); if (!entry) { DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); return WERR_GENERAL_FAILURE; } + + if(!entry->functions->open_hive) { + return WERR_NOT_SUPPORTED; + } - mem_ctx = talloc_init(backend); - ret = talloc(mem_ctx, sizeof(REG_HANDLE)); - ZERO_STRUCTP(ret); + + mem_ctx = h->mem_ctx; + ret = talloc_p(mem_ctx, struct registry_hive); ret->location = location?talloc_strdup(mem_ctx, location):NULL; + ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL; ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; ret->functions = entry->functions; ret->backend_data = NULL; - ret->mem_ctx = mem_ctx; - *h = ret; + ret->reg_ctx = h; - if(!entry->functions->open_registry) { - return WERR_OK; - } + werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); + + if(!W_ERROR_IS_OK(werr)) return werr; - werr = entry->functions->open_registry(ret, location, credentials); + if(!ret->root) return WERR_GENERAL_FAILURE; - if(W_ERROR_IS_OK(werr)) - return WERR_OK; + ret->root->hive = ret; + ret->root->name = NULL; + ret->root->path = ""; - talloc_destroy(mem_ctx); - return werr; + /* Add hive to context */ + h->num_hives++; + h->hives = talloc_realloc_p(h->hives, struct registry_hive *, h->num_hives); + h->hives[h->num_hives-1] = ret; + + return WERR_OK; } /* Open a key by name (including the hive name!) */ -WERROR reg_open_key_abs(REG_HANDLE *handle, const char *name, REG_KEY **result) +WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; else hivelength = strlen(name); - for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_get_hive(handle, i, &hive); - if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { - return reg_open_key(hive, name, result); - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); + + if(!W_ERROR_IS_OK(error)) { + return error; } - return error; + return reg_open_key(mem_ctx, hive, name, result); } /* Open a key * First tries to use the open_key function from the backend * then falls back to get_subkey_by_name and later get_subkey_by_index */ -WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) +WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result) { char *fullname; WERROR error; - TALLOC_CTX *mem_ctx; if(!parent) { DEBUG(0, ("Invalid parent key specified")); return WERR_INVALID_PARAM; } - if(!parent->handle->functions->open_key && - (parent->handle->functions->get_subkey_by_name || - parent->handle->functions->get_subkey_by_index)) { + if(!parent->hive->functions->open_key && + (parent->hive->functions->get_subkey_by_name || + parent->hive->functions->get_subkey_by_index)) { char *orig = strdup(name), *curbegin = orig, *curend = strchr(orig, '\\'); - REG_KEY *curkey = parent; + struct registry_key *curkey = parent; while(curbegin && *curbegin) { if(curend)*curend = '\0'; - error = reg_key_get_subkey_by_name(curkey, curbegin, result); + error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey); if(!W_ERROR_IS_OK(error)) { SAFE_FREE(orig); return error; @@ -184,94 +252,63 @@ WERROR reg_open_key(REG_KEY *parent, const char *name, REG_KEY **result) curend = strchr(curbegin, '\\'); } SAFE_FREE(orig); - + *result = curkey; + return WERR_OK; } - if(!parent->handle->functions->open_key) { + if(!parent->hive->functions->open_key) { DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n")); return WERR_NOT_SUPPORTED; } - mem_ctx = talloc_init("mem_ctx"); + fullname = reg_make_path(mem_ctx, parent, name); - fullname = talloc_asprintf(mem_ctx, "%s%s%s", - reg_key_get_path(parent), - strlen(reg_key_get_path(parent))?"\\":"", - name); + error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); - error = parent->handle->functions->open_key(parent->handle, - parent->hive, fullname, result); - - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } + if(!W_ERROR_IS_OK(error)) return error; - (*result)->handle = parent->handle; - (*result)->path = talloc_asprintf((*result)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(parent), (*result)->name); (*result)->hive = parent->hive; - talloc_steal((*result)->mem_ctx, fullname); - - talloc_destroy(mem_ctx); + (*result)->path = fullname; + (*result)->hive = parent->hive; return WERR_OK; } -WERROR reg_key_get_value_by_index(REG_KEY *key, int idx, REG_VAL **val) +WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_index) { - WERROR status = key->handle->functions->get_value_by_index(key, idx, val); + if(key->hive->functions->get_value_by_index) { + WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val); if(!W_ERROR_IS_OK(status)) return status; - - } else if(key->handle->functions->fetch_values) { - if(!key->cache_values) - key->handle->functions->fetch_values(key, - &key->cache_values_count, &key->cache_values); - - if(idx < key->cache_values_count && idx >= 0) { - *val = reg_val_dup(key->cache_values[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_num_subkeys(REG_KEY *key, int *count) +WERROR reg_key_num_subkeys(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->num_subkeys) { - return key->handle->functions->num_subkeys(key, count); + if(key->hive->functions->num_subkeys) { + return key->hive->functions->num_subkeys(key, count); } - if(key->handle->functions->fetch_subkeys) { - if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, - &key->cache_subkeys_count, &key->cache_subkeys); - - *count = key->cache_subkeys_count; - return WERR_OK; - } - - if(key->handle->functions->get_subkey_by_index) { + if(key->hive->functions->get_subkey_by_index) { int i; WERROR error; - REG_KEY *dest; - for(i = 0; W_ERROR_IS_OK(error = key->handle->functions->get_subkey_by_index(key, i, &dest)); i++) { - reg_key_free(dest); - } + struct registry_key *dest; + TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); + + for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++); + talloc_destroy(mem_ctx); *count = i; if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK; @@ -281,74 +318,49 @@ WERROR reg_key_num_subkeys(REG_KEY *key, int *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_num_values(REG_KEY *key, int *count) +WERROR reg_key_num_values(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->num_values) { - if(!key->handle->functions->fetch_values) { - DEBUG(1, ("Backend '%s' doesn't support enumerating values\n", key->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - if(!key->cache_values) - key->handle->functions->fetch_values(key, &key->cache_values_count, &key->cache_values); - - *count = key->cache_values_count; - return WERR_OK; - } - - - return key->handle->functions->num_values(key, count); + return key->hive->functions->num_values(key, count); } -WERROR reg_key_get_subkey_by_index(REG_KEY *key, int idx, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey) { if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_index) { - WERROR status = key->handle->functions->get_subkey_by_index(key, idx, subkey); + if(key->hive->functions->get_subkey_by_index) { + WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey); if(!NT_STATUS_IS_OK(status)) return status; - } else if(key->handle->functions->fetch_subkeys) { - if(!key->cache_subkeys) - key->handle->functions->fetch_subkeys(key, - &key->cache_subkeys_count, &key->cache_subkeys); - - if(idx < key->cache_subkeys_count) { - *subkey = reg_key_dup(key->cache_subkeys[idx]); - } else { - return WERR_NO_MORE_ITEMS; - } } else { return WERR_NOT_SUPPORTED; } - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", - reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; - (*subkey)->hive = key->hive; - + if(key->hive->root == key) + (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name); + else + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); + (*subkey)->hive = key->hive; return WERR_OK;; } -WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subkey) +WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_subkey_by_name) { - error = key->handle->functions->get_subkey_by_name(key,name,subkey); - } else if(key->handle->functions->get_subkey_by_index || key->handle->functions->fetch_subkeys) { + if(key->hive->functions->get_subkey_by_name) { + error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); + } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_subkey_by_index(key, i, subkey); + error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { return error; } - reg_key_free(*subkey); } } else { return WERR_NOT_SUPPORTED; @@ -356,29 +368,27 @@ WERROR reg_key_get_subkey_by_name(REG_KEY *key, const char *name, REG_KEY **subk if(!W_ERROR_IS_OK(error)) return error; - (*subkey)->path = talloc_asprintf((*subkey)->mem_ctx, "%s\\%s", reg_key_get_path_abs(key), (*subkey)->name); - (*subkey)->handle = key->handle; + (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name); (*subkey)->hive = key->hive; return WERR_OK; } -WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) +WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val) { int i; WERROR error = WERR_OK; if(!key) return WERR_INVALID_PARAM; - if(key->handle->functions->get_value_by_name) { - error = key->handle->functions->get_value_by_name(key,name, val); + if(key->hive->functions->get_value_by_name) { + error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val); } else { for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_key_get_value_by_index(key, i, val); + error = reg_key_get_value_by_index(mem_ctx, key, i, val); if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) { break; } - reg_val_free(*val); } } @@ -386,52 +396,49 @@ WERROR reg_key_get_value_by_name(REG_KEY *key, const char *name, REG_VAL **val) return error; (*val)->parent = key; - (*val)->handle = key->handle; + (*val)->hive = key->hive; return WERR_OK; } -WERROR reg_key_del(REG_KEY *key) +WERROR reg_key_del(struct registry_key *key) { WERROR error; if(!key) return WERR_INVALID_PARAM; - if(!key->handle->functions->del_key) + if(!key->hive->functions->del_key) return WERR_NOT_SUPPORTED; - error = key->handle->functions->del_key(key); + error = key->hive->functions->del_key(key); if(!W_ERROR_IS_OK(error)) return error; - /* Invalidate cache */ - key->cache_subkeys = NULL; - key->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_sync(REG_KEY *h, const char *location) -{ - if(!h->handle->functions->sync_key) - return WERR_OK; - - return h->handle->functions->sync_key(h, location); -} - -WERROR reg_key_del_recursive(REG_KEY *key) +WERROR reg_key_del_recursive(struct registry_key *key) { WERROR error = WERR_OK; int i; + + TALLOC_CTX *mem_ctx = talloc_init("del_recursive"); /* Delete all values for specified key */ for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_VAL *val; - error = reg_key_get_value_by_index(key, i, &val); + struct registry_value *val; + error = reg_key_get_value_by_index(mem_ctx, key, i, &val); if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + { + talloc_destroy(mem_ctx); return error; + } if(W_ERROR_IS_OK(error)) { - error = reg_val_del(val); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_del_value(val); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } } } @@ -439,204 +446,150 @@ WERROR reg_key_del_recursive(REG_KEY *key) /* Delete all keys below this one */ for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_KEY *subkey; + struct registry_key *subkey; - error = reg_key_get_subkey_by_index(key, i, &subkey); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey); + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } error = reg_key_del_recursive(subkey); - if(!W_ERROR_IS_OK(error)) return error; + if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } } + talloc_destroy(mem_ctx); return reg_key_del(key); } -WERROR reg_val_del(REG_VAL *val) -{ - WERROR error; - if (!val) return WERR_INVALID_PARAM; - - if (!val->handle->functions->del_value) { - DEBUG(1, ("Backend '%s' doesn't support method del_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; - } - - error = val->handle->functions->del_value(val); - - if(!W_ERROR_IS_OK(error)) return error; - - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - - return WERR_OK; -} - -WERROR reg_key_add_name_recursive_abs(REG_HANDLE *handle, const char *name) +WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name) { - REG_KEY *hive; + struct registry_key *hive; WERROR error; - int i, hivelength; + int hivelength; + char *hivename; if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; else hivelength = strlen(name); - for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_get_hive(handle, i, &hive); - if(W_ERROR_IS_OK(error) && !strncmp(reg_key_name(hive), name, hivelength)) { - return reg_key_add_name_recursive(hive, name); - } - } + hivename = strndup(name, hivelength); + error = reg_get_hive(handle, hivename, &hive); + SAFE_FREE(hivename); - return error; + if(!W_ERROR_IS_OK(error)) return error; + + return reg_key_add_name_recursive(hive, name); } -WERROR reg_key_add_name_recursive(REG_KEY *parent, const char *path) +WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) { - REG_KEY *cur, *prevcur = parent; - WERROR error; - /* FIXME: we should never write to a 'const char *' !!! --metze */ - char *begin = (char *)path, *end; + struct registry_key *cur, *prevcur = parent; + WERROR error = WERR_OK; + char *dup, *begin, *end; + TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); + + begin = dup = strdup(path); while(1) { end = strchr(begin, '\\'); if(end) *end = '\0'; - error = reg_key_get_subkey_by_name(prevcur, begin, &cur); + error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur); /* Key is not there, add it */ if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - error = reg_key_add_name(prevcur, begin, 0, NULL, &cur); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur); + if(!W_ERROR_IS_OK(error)) break; } if(!W_ERROR_IS_OK(error)) { if(end) *end = '\\'; - return error; + break; } - if(!end) break; + if(!end) { + error = WERR_OK; + break; + } + *end = '\\'; begin = end+1; prevcur = cur; } - return WERR_OK; + SAFE_FREE(dup); + talloc_destroy(mem_ctx); + return error; } -WERROR reg_key_add_name(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **newkey) +WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey) { WERROR error; if (!parent) return WERR_INVALID_PARAM; - if (!parent->handle->functions->add_key) { - DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name)); + if (!parent->hive->functions->add_key) { + DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name)); return WERR_NOT_SUPPORTED; } - error = parent->handle->functions->add_key(parent, name, access_mask, desc, newkey); + error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey); if(!W_ERROR_IS_OK(error)) return error; - (*newkey)->handle = parent->handle; - (*newkey)->backend_data = talloc_asprintf((*newkey)->mem_ctx, "%s\\%s", reg_key_get_path(parent), name); + (*newkey)->hive = parent->hive; + (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name); - parent->cache_subkeys = NULL; - parent->cache_subkeys_count = 0; return WERR_OK; } -WERROR reg_val_update(REG_VAL *val, int type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len) { - WERROR error; - - /* A 'real' update function has preference */ - if (val->handle->functions->update_value) - return val->handle->functions->update_value(val, type, data, len); - - /* Otherwise, just remove and add again */ - if (val->handle->functions->add_value && - val->handle->functions->del_value) { - REG_VAL *new; - if(!W_ERROR_IS_OK(error = val->handle->functions->del_value(val))) - return error; - - error = val->handle->functions->add_value(val->parent, val->name, type, data, len); - if(!W_ERROR_IS_OK(error)) return error; - memcpy(val, new, sizeof(REG_VAL)); - val->parent->cache_values = NULL; - val->parent->cache_values_count = 0; - return WERR_OK; - } - - DEBUG(1, ("Backend '%s' doesn't support method update_value\n", val->handle->functions->name)); - return WERR_NOT_SUPPORTED; -} - -void reg_free(REG_HANDLE *h) -{ - if(!h->functions->close_registry) return; + /* A 'real' set function has preference */ + if (key->hive->functions->set_value) + return key->hive->functions->set_value(key, value, type, data, len); - h->functions->close_registry(h); + DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name)); + return WERR_NOT_SUPPORTED; } -WERROR reg_get_hive(REG_HANDLE *h, int hivenum, REG_KEY **key) +WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) { - WERROR ret; - - if(h->functions->get_hive) { - ret = h->functions->get_hive(h, hivenum, key); - } else if(h->functions->open_key) { - if(hivenum == 0) ret = h->functions->open_key(h, hivenum, "", key); - else ret = WERR_NO_MORE_ITEMS; - } else { - DEBUG(0, ("Backend '%s' has neither open_root_key nor open_key or get_hive method implemented\n", h->functions->name)); - ret = WERR_NOT_SUPPORTED; - } - - if(W_ERROR_IS_OK(ret)) { - (*key)->handle = h; - if(!(*key)->path) { - (*key)->path = talloc_strdup((*key)->mem_ctx, (*key)->name); + int i; + for(i = 0; i < h->num_hives; i++) + { + if(!strcmp(h->hives[i]->name, name)) { + *key = h->hives[i]->root; + return WERR_OK; } - (*key)->hive = hivenum; } - return ret; + return WERR_NO_MORE_ITEMS; } -WERROR reg_key_add_value(REG_KEY *key, const char *name, int type, void *value, size_t vallen) +WERROR reg_del_value(struct registry_value *val) { WERROR ret = WERR_OK; - if(!key->handle->functions->add_value) + if(!val->hive->functions->del_value) return WERR_NOT_SUPPORTED; - ret = key->handle->functions->add_value(key, name, type, value, vallen); + ret = val->hive->functions->del_value(val); if(!W_ERROR_IS_OK(ret)) return ret; - /* Invalidate the cache */ - key->cache_values = NULL; - key->cache_values_count = 0; return ret; } -WERROR reg_save(REG_HANDLE *h, const char *location) +WERROR reg_save(struct registry_context *h, const char *location) { /* FIXME */ return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) +WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent) { char *parent_name; char *last; - REG_KEY *root; + struct registry_key *root; WERROR error; - error = reg_get_hive(key->handle, key->hive, &root); - if(!W_ERROR_IS_OK(error)) return error; - - parent_name = strdup(reg_key_get_path(key)); + parent_name = strdup(key->path); last = strrchr(parent_name, '\\'); if(!last) { @@ -645,7 +598,7 @@ WERROR reg_key_get_parent(REG_KEY *key, REG_KEY **parent) } *last = '\0'; - error = reg_open_key(root, parent_name, parent); + error = reg_open_key(mem_ctx, root, parent_name, parent); SAFE_FREE(parent_name); return error; } diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c deleted file mode 100644 index d911b4650b..0000000000 --- a/source4/lib/registry/common/reg_objects.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Gerald Carter 2002. - * Copyright (C) Jelmer Vernooij 2003-2004. - * - * 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 - * (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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Implementation of registry frontend view functions. */ - -#include "includes.h" -#include "lib/registry/common/registry.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -/*********************************************************************** - allocate memory for and duplicate a REG_VAL. - This is malloc'd memory so the caller should free it when done - **********************************************************************/ - -REG_VAL* reg_val_dup( REG_VAL *val ) -{ - val->ref++; - return val; -} - -/********************************************************************** - free the memory allocated to a REG_VAL - *********************************************************************/ - -void reg_val_free( REG_VAL *val ) -{ - if ( !val ) - return; - - val->ref--; - if(val->ref) return; - - if(val->handle->functions->free_val_backend_data) - val->handle->functions->free_val_backend_data(val); - - talloc_destroy( val->mem_ctx ); - - return; -} - -/********************************************************************** - *********************************************************************/ - -uint8_t * reg_val_data_blk( REG_VAL *val ) -{ - return val->data_blk; -} - -/********************************************************************** - *********************************************************************/ - -int reg_val_size( REG_VAL *val ) -{ - return val->data_len; -} - -/********************************************************************** - *********************************************************************/ - -char *reg_val_name( REG_VAL *val ) -{ - return val->name; -} - -/********************************************************************** - *********************************************************************/ - -uint32_t reg_val_type( REG_VAL *val ) -{ - return val->data_type; -} - -/********************************************************************** - *********************************************************************/ - -REG_HANDLE *reg_key_handle (REG_KEY *key) -{ - return key->handle; -} - -char *reg_key_name( REG_KEY *key ) -{ - return key->name; -} - -char *reg_key_class( REG_KEY *key ) -{ - return key->class_name; -} - -NTTIME reg_key_last_modified( REG_KEY *key ) -{ - return key->last_mod; -} - -REG_KEY *reg_key_dup(REG_KEY *key) -{ - key->ref++; - return key; -} - -void reg_key_free(REG_KEY *key) -{ - if(!key) - return; - - key->ref--; - if(key->ref) return; - - if(key->handle->functions->free_key_backend_data) - key->handle->functions->free_key_backend_data(key); - - if(key->cache_values) { - int i; - for(i = 0; i < key->cache_values_count; i++) { - reg_val_free(key->cache_values[i]); - } - } - - if(key->cache_subkeys) { - int i; - for(i = 0; i < key->cache_subkeys_count; i++) { - reg_key_free(key->cache_subkeys[i]); - } - } - - talloc_destroy(key->mem_ctx); -} - -char *reg_val_get_path(REG_VAL *v) -{ - /* FIXME */ - return NULL; -} - -const char *reg_key_get_path(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return strchr(k->path, '\\')?strchr(k->path, '\\')+1:""; -} - -const char *reg_key_get_path_abs(REG_KEY *k) -{ - SMB_REG_ASSERT(k); - return k->path; -} - -/* For use by the backends _ONLY_ */ -REG_KEY *reg_key_new_abs(const char *path, REG_HANDLE *h, void *data) -{ - REG_KEY *r; - TALLOC_CTX *mem_ctx = talloc_init(path); - r = talloc(mem_ctx, sizeof(REG_KEY)); - ZERO_STRUCTP(r); - r->handle = h; - r->mem_ctx = mem_ctx; - r->path = talloc_strdup(mem_ctx, path); - r->name = talloc_strdup(mem_ctx, strrchr(path, '\\')?strrchr(path,'\\')+1:path); - r->backend_data = data; - r->ref = 1; - return r; -} - -REG_KEY *reg_key_new_rel(const char *name, REG_KEY *k, void *data) -{ - REG_KEY *r; - const char *parent_path = k?reg_key_get_path(k):""; - TALLOC_CTX *mem_ctx = talloc_init(name); - r = talloc(mem_ctx, sizeof(REG_KEY)); - ZERO_STRUCTP(r); - r->handle = k->handle; - r->hive = k->hive; - r->name = talloc_strdup(mem_ctx, name); - - r->path = talloc_asprintf(mem_ctx, "%s%s%s", parent_path, *parent_path && parent_path[strlen(parent_path)-1] != '\\'?"\\":"", name); - r->backend_data = data; - r->mem_ctx = mem_ctx; - r->ref = 1; - return r; -} - -REG_VAL *reg_val_new(REG_KEY *parent, void *data) -{ - REG_VAL *r; - TALLOC_CTX *mem_ctx = talloc_init("value"); - r = talloc(mem_ctx, sizeof(REG_VAL)); - ZERO_STRUCTP(r); - r->mem_ctx = mem_ctx; - r->handle = parent->handle; - r->backend_data = data; - r->ref = 1; - return r; -} diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index db5e97bf7f..21c925deab 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -34,90 +34,68 @@ const char *str_regtype(int type) return "Unknown"; } -char *reg_val_data_string(REG_VAL *v) +char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) { char *asciip; char *ret = NULL; int i; - if(reg_val_size(v) == 0) return strdup(""); + if(v->data_len == 0) return talloc_strdup(mem_ctx, ""); - switch (reg_val_type(v)) { + switch (v->data_type) { case REG_SZ: - /* FIXME: Convert to ascii */ - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_EXPAND_SZ: - return strndup(reg_val_data_blk(v), reg_val_size(v)); + return talloc_strndup(mem_ctx, v->data_blk, v->data_len); case REG_BINARY: - ret = malloc(reg_val_size(v) * 3 + 2); + ret = talloc(mem_ctx, v->data_len * 3 + 2); asciip = ret; - for (i=0; i 0) + for (i=0; idata_len; i++) { + int str_rem = v->data_len * 3 - (asciip - ret); + asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(v->data_blk+i)); + if (i < v->data_len && str_rem > 0) *asciip = ' '; asciip++; } *asciip = '\0'; return ret; - break; case REG_DWORD: - if (*(int *)reg_val_data_blk(v) == 0) - ret = strdup("0"); - else - asprintf(&ret, "0x%x", *(int *)reg_val_data_blk(v)); - break; + if (*(int *)v->data_blk == 0) + return talloc_strdup(mem_ctx, "0"); + + return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data_blk); case REG_MULTI_SZ: /* FIXME */ break; default: - return 0; break; } return ret; } -char *reg_val_description(REG_VAL *val) +char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) { - char *ret, *ds = reg_val_data_string(val); - asprintf(&ret, "%s = %s : %s", reg_val_name(val)?reg_val_name(val):"", str_regtype(reg_val_type(val)), ds); - free(ds); - return ret; + return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); } -BOOL reg_val_set_string(REG_VAL *val, char *str) +BOOL reg_val_set_string(struct registry_value *val, char *str) { /* FIXME */ return False; } -WERROR reg_key_get_subkey_val(REG_KEY *key, const char *subname, const char *valname, REG_VAL **val) +WERROR reg_key_get_subkey_val(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *subname, const char *valname, struct registry_value **val) { - REG_KEY *k; - WERROR error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_get_value_by_name(k, valname, val); -} - -WERROR reg_key_set_subkey_val(REG_KEY *key, const char *subname, const char *valname, uint32_t type, uint8_t *data, int real_len) -{ - REG_KEY *k; - REG_VAL *v; - WERROR error; - - error = reg_key_get_subkey_by_name(key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - error = reg_key_get_value_by_name(k, valname, &v); + struct registry_key *k; + WERROR error = reg_key_get_subkey_by_name(mem_ctx, key, subname, &k); if(!W_ERROR_IS_OK(error)) return error; - return reg_val_update(v, type, data, real_len); + return reg_key_get_value_by_name(mem_ctx, k, valname, val); } /*********************************************************************** diff --git a/source4/lib/registry/common/registry.h b/source4/lib/registry/common/registry.h deleted file mode 100644 index 89d0ac6b14..0000000000 --- a/source4/lib/registry/common/registry.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - This file contains the _internal_ structs for the registry - subsystem. Backends and the subsystem itself are the only - files that need to include this file. - Copyright (C) Gerald Carter 2002. - Copyright (C) Jelmer Vernooij 2003-2004. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _REGISTRY_REGISTRY_H /* _REGISTRY_REGISTRY_H */ -#define _REGISTRY_REGISTRY_H - -#define REGISTRY_INTERFACE_VERSION 1 - -/* structure to store the registry handles */ -struct reg_key_s { - char *name; /* Name of the key */ - char *path; /* Full path to the key */ - char *class_name; /* Name of key class */ - NTTIME last_mod; /* Time last modified */ - SEC_DESC *security; - REG_HANDLE *handle; - void *backend_data; - REG_VAL **cache_values; - int cache_values_count; - REG_KEY **cache_subkeys; - int cache_subkeys_count; - int hive; - TALLOC_CTX *mem_ctx; - int ref; -}; - -struct reg_val_s { - char *name; - int has_name; - int data_type; - int data_len; - void *data_blk; /* Might want a separate block */ - REG_HANDLE *handle; - REG_KEY *parent; - void *backend_data; - TALLOC_CTX *mem_ctx; - int ref; -}; - -/* FIXME */ -typedef void (*key_notification_function) (void); -typedef void (*value_notification_function) (void); - -/* - * Container for function pointers to enumeration routines - * for virtual registry view - * - * Backends can provide : - * - just one hive (example: nt4, w95) - * - several hives (example: rpc) - * - */ - -struct registry_ops { - const char *name; - WERROR (*open_registry) (REG_HANDLE *, const char *location, const char *credentials); - WERROR (*sync_key)(REG_KEY *, const char *location); - WERROR (*close_registry) (REG_HANDLE *); - - /* Implement this one */ - WERROR (*get_hive) (REG_HANDLE *, int , REG_KEY **); - - /* Or this one */ - WERROR (*open_key) (REG_HANDLE *, int hive, const char *name, REG_KEY **); - - /* Either implement these */ - WERROR (*num_subkeys) (REG_KEY *, int *count); - WERROR (*num_values) (REG_KEY *, int *count); - WERROR (*get_subkey_by_index) (REG_KEY *, int idx, REG_KEY **); - /* Can not contain more then one level */ - WERROR (*get_subkey_by_name) (REG_KEY *, const char *name, REG_KEY **); - WERROR (*get_value_by_index) (REG_KEY *, int idx, REG_VAL **); - /* Can not contain more then one level */ - WERROR (*get_value_by_name) (REG_KEY *, const char *name, REG_VAL **); - - /* Or these */ - WERROR (*fetch_subkeys) (REG_KEY *, int *count, REG_KEY ***); - WERROR (*fetch_values) (REG_KEY *, int *count, REG_VAL ***); - - /* Security control */ - WERROR (*key_get_sec_desc) (REG_KEY *, SEC_DESC **); - WERROR (*key_set_sec_desc) (REG_KEY *, SEC_DESC *); - - /* Notification */ - WERROR (*request_key_change_notify) (REG_KEY *, key_notification_function); - WERROR (*request_value_change_notify) (REG_VAL *, value_notification_function); - - /* Key management */ - WERROR (*add_key)(REG_KEY *, const char *name, uint32_t access_mask, SEC_DESC *, REG_KEY **); - WERROR (*del_key)(REG_KEY *); - - /* Value management */ - WERROR (*add_value)(REG_KEY *, const char *name, int type, void *data, int len); - WERROR (*del_value)(REG_VAL *); - - /* If update is not available, value will first be deleted and then added - * again */ - WERROR (*update_value)(REG_VAL *, int type, void *data, int len); - - void (*free_key_backend_data) (REG_KEY *); - void (*free_val_backend_data) (REG_VAL *); -}; - -struct reg_handle_s { - const struct registry_ops *functions; - char *location; - char *credentials; - void *backend_data; - TALLOC_CTX *mem_ctx; -}; - -struct reg_init_function_entry { - /* Function to create a member of the pdb_methods list */ - const struct registry_ops *functions; - struct reg_init_function_entry *prev, *next; -}; - -/* Used internally */ -#define SMB_REG_ASSERT(a) { if(!(a)) { DEBUG(0,("%s failed! (%s:%d)", #a, __FILE__, __LINE__)); }} - -#endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 8100c798e6..659e705d5d 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -60,7 +60,6 @@ REQUIRED_SUBSYSTEMS = \ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ - lib/registry/common/reg_objects.o \ lib/registry/common/reg_util.o REQUIRED_SUBSYSTEMS = \ LIBBASIC diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index b2bd34bf71..95d4c47af0 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -19,13 +19,12 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" -static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, REG_KEY **result) +static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) { char *path; int ret; - asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name); + asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name); path = reg_path_win2unix(path); ret = mkdir(path, 0700); SAFE_FREE(path); @@ -33,19 +32,16 @@ static WERROR reg_dir_add_key(REG_KEY *parent, const char *name, uint32_t access return WERR_INVALID_PARAM; } -static WERROR reg_dir_del_key(REG_KEY *k) +static WERROR reg_dir_del_key(struct registry_key *k) { return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; } -static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **subkey) +static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **subkey) { DIR *d; char *fullpath; - REG_KEY *ret; - TALLOC_CTX *mem_ctx; - - if(hive != 0) return WERR_NO_MORE_ITEMS; + struct registry_key *ret; if(!name) { DEBUG(0, ("NULL pointer passed as directory name!")); @@ -53,33 +49,28 @@ static WERROR reg_dir_open_key(REG_HANDLE *h, int hive, const char *name, REG_KE } - mem_ctx = talloc_init("tmp"); fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); fullpath = reg_path_win2unix(fullpath); d = opendir(fullpath); if(!d) { DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); - talloc_destroy(mem_ctx); return WERR_BADFILE; } closedir(d); - ret = reg_key_new_abs(name, h, fullpath); - talloc_steal(ret->mem_ctx, fullpath); - talloc_destroy(mem_ctx); + ret = talloc_p(mem_ctx, struct registry_key); + ret->hive = h; + ret->path = fullpath; *subkey = ret; return WERR_OK; } -static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) +static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **key) { struct dirent *e; - int max = 200; char *fullpath = k->backend_data; - REG_KEY **ar; + int i = 0; DIR *d; - (*count) = 0; - ar = talloc(k->mem_ctx, sizeof(REG_KEY *) * max); d = opendir(fullpath); @@ -96,13 +87,15 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) stat(thispath, &stbuf); if(S_ISDIR(stbuf.st_mode)) { - ar[(*count)] = reg_key_new_rel(e->d_name, k, NULL); - ar[(*count)]->backend_data = talloc_strdup(ar[*count]->mem_ctx, thispath); - if(ar[(*count)])(*count)++; - - if((*count) == max) { - max+=200; - ar = realloc(ar, sizeof(REG_KEY *) * max); + i++; + if(i == idx) { + (*key) = talloc_p(mem_ctx, struct registry_key); + (*key)->name = e->d_name; + (*key)->path = NULL; + (*key)->backend_data = talloc_strdup(mem_ctx, thispath); + SAFE_FREE(thispath); + closedir(d); + return WERR_OK; } } @@ -112,44 +105,38 @@ static WERROR reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r) closedir(d); - *r = ar; - return WERR_OK; + return WERR_NO_MORE_ITEMS; } -static WERROR reg_dir_open(REG_HANDLE *h, const char *loc, const char *credentials) { - if(!loc) return WERR_INVALID_PARAM; +static WERROR reg_dir_open(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) +{ + if(!h->location) return WERR_INVALID_PARAM; + + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->backend_data = talloc_strdup(mem_ctx, h->location); return WERR_OK; } -static WERROR reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len) +static WERROR reg_dir_set_value(struct registry_key *p, const char *name, int type, void *data, int len) { /* FIXME */ return WERR_NOT_SUPPORTED; } -static WERROR reg_dir_get_hive(REG_HANDLE *h, int hive, REG_KEY **key) -{ - if(hive != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - (*key)->backend_data = talloc_strdup((*key)->mem_ctx, h->location); - return WERR_OK; -} - -static WERROR reg_dir_del_value(REG_VAL *v) +static WERROR reg_dir_del_value(struct registry_value *v) { /* FIXME*/ return WERR_NOT_SUPPORTED; } -static struct registry_ops reg_backend_dir = { +static struct registry_operations reg_backend_dir = { .name = "dir", - .open_registry = reg_dir_open, + .open_hive = reg_dir_open, .open_key = reg_dir_open_key, - .get_hive = reg_dir_get_hive, - .fetch_subkeys = reg_dir_fetch_subkeys, .add_key = reg_dir_add_key, .del_key = reg_dir_del_key, - .add_value = reg_dir_add_value, + .get_subkey_by_index = reg_dir_key_by_index, + .set_value = reg_dir_set_value, .del_value = reg_dir_del_value, }; diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 15a8319711..d8c8d951c1 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" #include static WERROR gerror_to_werror(GError *error) @@ -29,33 +28,24 @@ static WERROR gerror_to_werror(GError *error) return WERR_FOOBAR; } -static WERROR reg_open_gconf(REG_HANDLE *h, const char *location, const char *credentials) +static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { + g_type_init(); h->backend_data = (void *)gconf_client_get_default(); if(!h->backend_data) return WERR_FOOBAR; + + *k = talloc_p(mem_ctx, struct registry_key); + (*k)->name = ""; + (*k)->path = ""; + (*k)->backend_data = talloc_strdup(mem_ctx, "/"); return WERR_OK; } -static WERROR reg_close_gconf(REG_HANDLE *h) -{ - return WERR_OK; -} - -static WERROR gconf_get_hive (REG_HANDLE *h, int hivenum, REG_KEY **key) -{ - if(hivenum != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - (*key)->backend_data = talloc_strdup((*key)->mem_ctx, "/"); - return WERR_OK; -} - -static WERROR gconf_open_key (REG_HANDLE *h, int hivenum, const char *name, REG_KEY **key) +static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { - REG_KEY *ret; + struct registry_key *ret; char *fullpath; - if(hivenum != 0) return WERR_NO_MORE_ITEMS; - fullpath = reg_path_win2unix(strdup(name)); /* Check if key exists */ @@ -63,143 +53,134 @@ static WERROR gconf_open_key (REG_HANDLE *h, int hivenum, const char *name, REG_ SAFE_FREE(fullpath); return WERR_DEST_NOT_FOUND; } - ret = reg_key_new_abs(name, h, NULL); - ret->backend_data = talloc_strdup(ret->mem_ctx, fullpath); + + ret = talloc_p(mem_ctx, struct registry_key); + ret->backend_data = talloc_strdup(mem_ctx, fullpath); SAFE_FREE(fullpath); *key = ret; return WERR_OK; } -static WERROR gconf_fetch_values(REG_KEY *p, int *count, REG_VAL ***vals) +static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_value **val) { GSList *entries; GSList *cur; - REG_VAL **ar = talloc(p->mem_ctx, sizeof(REG_VAL *)); + GConfEntry *entry; + GConfValue *value; + struct registry_value *newval; char *fullpath = p->backend_data; - cur = entries = gconf_client_all_entries((GConfClient*)p->handle->backend_data, fullpath, NULL); - - (*count) = 0; - while(cur) { - GConfEntry *entry = cur->data; - GConfValue *value = gconf_entry_get_value(entry); - REG_VAL *newval = reg_val_new(p, NULL); - newval->name = talloc_strdup(newval->mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); - if(value) { - switch(value->type) { - case GCONF_VALUE_INVALID: - newval->data_type = REG_NONE; - break; - - case GCONF_VALUE_STRING: - newval->data_type = REG_SZ; - newval->data_blk = talloc_strdup(newval->mem_ctx, gconf_value_get_string(value)); - newval->data_len = strlen(newval->data_blk); - break; - - case GCONF_VALUE_INT: - newval->data_type = REG_DWORD; - newval->data_blk = talloc(newval->mem_ctx, sizeof(long)); - *((long *)newval->data_blk) = gconf_value_get_int(value); - newval->data_len = sizeof(long); - break; - - case GCONF_VALUE_FLOAT: - newval->data_blk = talloc(newval->mem_ctx, sizeof(double)); - newval->data_type = REG_BINARY; - *((double *)newval->data_blk) = gconf_value_get_float(value); - newval->data_len = sizeof(double); - break; - - case GCONF_VALUE_BOOL: - newval->data_blk = talloc(newval->mem_ctx, sizeof(BOOL)); - newval->data_type = REG_BINARY; - *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); - newval->data_len = sizeof(BOOL); - break; - - default: - newval->data_type = REG_NONE; - DEBUG(0, ("Not implemented..\n")); - break; - } - } else newval->data_type = REG_NONE; - - ar[(*count)] = newval; - ar = talloc_realloc(ar, sizeof(REG_VAL *) * ((*count)+2)); - (*count)++; - g_free(cur->data); - cur = cur->next; - } + int i; + cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + entry = cur->data; + value = gconf_entry_get_value(entry); + + newval = talloc_p(mem_ctx, struct registry_value); + newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); + if(value) { + switch(value->type) { + case GCONF_VALUE_INVALID: + newval->data_type = REG_NONE; + break; + + case GCONF_VALUE_STRING: + newval->data_type = REG_SZ; + newval->data_blk = talloc_strdup(mem_ctx, gconf_value_get_string(value)); + newval->data_len = strlen(newval->data_blk); + break; + + case GCONF_VALUE_INT: + newval->data_type = REG_DWORD; + newval->data_blk = talloc_p(mem_ctx, long); + *((long *)newval->data_blk) = gconf_value_get_int(value); + newval->data_len = sizeof(long); + break; + + case GCONF_VALUE_FLOAT: + newval->data_blk = talloc_p(mem_ctx, double); + newval->data_type = REG_BINARY; + *((double *)newval->data_blk) = gconf_value_get_float(value); + newval->data_len = sizeof(double); + break; + + case GCONF_VALUE_BOOL: + newval->data_blk = talloc_p(mem_ctx, BOOL); + newval->data_type = REG_BINARY; + *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); + newval->data_len = sizeof(BOOL); + break; + + default: + newval->data_type = REG_NONE; + DEBUG(0, ("Not implemented..\n")); + break; + } + } else newval->data_type = REG_NONE; g_slist_free(entries); - *vals = ar; + *val = newval; return WERR_OK; } -static WERROR gconf_fetch_subkeys(REG_KEY *p, int *count, REG_KEY ***subs) +static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_key **sub) { GSList *dirs; GSList *cur; - REG_KEY **ar = talloc_array_p(p->mem_ctx, REG_KEY *, 1); + int i; char *fullpath = p->backend_data; - cur = dirs = gconf_client_all_dirs((GConfClient*)p->handle->backend_data, fullpath,NULL); - - (*count) = 0; - while(cur) { - char *winpath = reg_path_unix2win(strdup((char *)cur->data)); - ar[(*count)] = reg_key_new_abs(winpath, p->handle,NULL); - free(winpath); - ar[(*count)]->backend_data = reg_path_win2unix(talloc_strdup(ar[*count]->mem_ctx, cur->data)); - ar = talloc_realloc_p(ar, REG_KEY *, (*count)+2); - (*count)++; - g_free(cur->data); - cur = cur->next; - } + cur = dirs = gconf_client_all_dirs((GConfClient*)p->hive->backend_data, fullpath,NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + *sub = talloc_p(mem_ctx, struct registry_key); + (*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1); + (*sub)->backend_data = talloc_strdup(mem_ctx, cur->data); g_slist_free(dirs); - *subs = ar; return WERR_OK; } -static WERROR gconf_update_value(REG_VAL *val, int type, void *data, int len) +static WERROR gconf_set_value(struct registry_key *key, const char *valname, int type, void *data, int len) { GError *error = NULL; - char *keypath = val->backend_data; char *valpath; - if(val->name)asprintf(&valpath, "%s/%s", keypath, val->name); - else valpath = strdup(keypath); + asprintf(&valpath, "%s/%s", key->path, valname); switch(type) { case REG_SZ: case REG_EXPAND_SZ: - gconf_client_set_string((GConfClient *)val->handle->backend_data, valpath, data, &error); - free(valpath); + gconf_client_set_string((GConfClient *)key->hive->backend_data, valpath, data, &error); + SAFE_FREE(valpath); return gerror_to_werror(error); case REG_DWORD: - gconf_client_set_int((GConfClient *)val->handle->backend_data, valpath, + gconf_client_set_int((GConfClient *)key->hive->backend_data, valpath, *((int *)data), &error); - free(valpath); + SAFE_FREE(valpath); return gerror_to_werror(error); default: DEBUG(0, ("Unsupported type: %d\n", type)); - free(valpath); + SAFE_FREE(valpath); return WERR_NOT_SUPPORTED; } return WERR_NOT_SUPPORTED; } -static struct registry_ops reg_backend_gconf = { +static struct registry_operations reg_backend_gconf = { .name = "gconf", - .open_registry = reg_open_gconf, - .close_registry = reg_close_gconf, - .get_hive = gconf_get_hive, + .open_hive = reg_open_gconf_hive, .open_key = gconf_open_key, - .fetch_subkeys = gconf_fetch_subkeys, - .fetch_values = gconf_fetch_values, - .update_value = gconf_update_value, + .get_subkey_by_index = gconf_get_subkey_by_id, + .get_value_by_index = gconf_get_value_by_id, + .set_value = gconf_set_value, /* Note: * since GConf uses schemas for what keys and values are allowed, there diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 47cb60d711..e0f65f2c37 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -19,7 +19,6 @@ */ #include "includes.h" -#include "lib/registry/common/registry.h" static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { @@ -55,40 +54,46 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * return ret; } + +static int ldb_close_registry(void *data) +{ + ldb_close((struct ldb_context *)data); + return 0; +} + + /* * Saves the dn as private_data for every key/val */ -static WERROR ldb_open_registry(REG_HANDLE *handle, const char *location, const char *credentials) +static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) { struct ldb_context *c; - if (!location) return WERR_INVALID_PARAM; - c = ldb_connect(location, 0, NULL); + if (!hive->location) return WERR_INVALID_PARAM; + c = ldb_connect(hive->location, 0, NULL); ldb_set_debug_stderr(c); + if(!c) return WERR_FOOBAR; - handle->backend_data = c; + hive->backend_data = c; + talloc_set_destructor(c, ldb_close_registry); return WERR_OK; } -static WERROR ldb_close_registry(REG_HANDLE *h) -{ - ldb_close((struct ldb_context *)h->backend_data); - return WERR_OK; -} - -static WERROR ldb_add_key(REG_KEY *p, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **new) +static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **new) { return WERR_NOT_SUPPORTED; } -static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) +#if 0 +FIXME +static WERROR ldb_fetch_subkeys(struct registry_key *k, int *count, struct registry_key ***subkeys) { - struct ldb_context *c = k->handle->backend_data; + struct ldb_context *c = k->hive->backend_data; int ret, i, j; struct ldb_message **msg; @@ -99,7 +104,7 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) return WERR_FOOBAR; } - *subkeys = talloc_array_p(k->mem_ctx, REG_KEY *, ret); + *subkeys = talloc_array_p(k->mem_ctx, struct registry_key *, ret); j = 0; for(i = 0; i < ret; i++) { struct ldb_message_element *el; @@ -121,9 +126,9 @@ static WERROR ldb_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***subkeys) return WERR_OK; } -static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +static WERROR ldb_fetch_values(struct registry_key *k, int *count, REG_VAL ***values) { - struct ldb_context *c = k->handle->backend_data; + struct ldb_context *c = k->hive->backend_data; int ret, i, j; struct ldb_message **msg; @@ -156,21 +161,14 @@ static WERROR ldb_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) return WERR_OK; } -static WERROR ldb_get_hive(REG_HANDLE *h, int num, REG_KEY **key) -{ - if(num != 0) return WERR_NO_MORE_ITEMS; - *key = reg_key_new_abs("", h, NULL); - return WERR_OK; -} +#endif -static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **key) +static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { struct ldb_context *c = h->backend_data; struct ldb_message **msg; char *ldap_path; int ret; - TALLOC_CTX *mem_ctx = talloc_init("ldb_path"); - if(num != 0) return WERR_NO_MORE_ITEMS; ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "*", NULL,&msg); @@ -182,25 +180,20 @@ static WERROR ldb_open_key(REG_HANDLE *h, int num, const char *name, REG_KEY **k return WERR_FOOBAR; } - *key = reg_key_new_abs(name, h, ldap_path); - talloc_steal((*key)->mem_ctx, ldap_path); - printf("Got something!\n"); + *key = talloc_p(mem_ctx, struct registry_key); /* FIXME */ ldb_search_free(c, msg); - talloc_destroy(mem_ctx); return WERR_OK; } -static struct registry_ops reg_backend_ldb = { +static struct registry_operations reg_backend_ldb = { .name = "ldb", - .open_registry = ldb_open_registry, - .get_hive = ldb_get_hive, - .close_registry = ldb_close_registry, + .open_hive = ldb_open_hive, .open_key = ldb_open_key, - .fetch_subkeys = ldb_fetch_subkeys, - .fetch_values = ldb_fetch_values, +/* .fetch_subkeys = ldb_fetch_subkeys, + .fetch_values = ldb_fetch_values,*/ .add_key = ldb_add_key, }; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index ee9f8bf24f..c271c55991 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -304,9 +304,9 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, *************************************************************************/ #include "includes.h" -#include "lib/registry/common/registry.h" #define REG_KEY_LIST_SIZE 10 +#define FLAG_HAS_NAME 0x01 /*FIXME*/ /* @@ -514,7 +514,7 @@ static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, con /* * Create a default ACL */ -static SEC_ACL *nt_create_default_acl(REG_HANDLE *regf) +static SEC_ACL *nt_create_default_acl(struct registry_hive *regf) { SEC_ACE aces[8]; @@ -534,7 +534,7 @@ static SEC_ACL *nt_create_default_acl(REG_HANDLE *regf) * Create a default security descriptor. We pull in things from env * if need be */ -static SEC_DESC *nt_create_def_sec_desc(REG_HANDLE *regf) +static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) { SEC_DESC *tmp; @@ -559,7 +559,7 @@ static SEC_DESC *nt_create_def_sec_desc(REG_HANDLE *regf) * says, but the Owner and Group SIDs can be overwridden from the command line * and additional ACEs can be applied from the command line etc. */ -static KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) +static KEY_SEC_DESC *nt_inherit_security(struct registry_key *key) { if (!key) return NULL; @@ -570,7 +570,7 @@ static KEY_SEC_DESC *nt_inherit_security(REG_KEY *key) * Create an initial security descriptor and init other structures, if needed * We assume that the initial security stuff is empty ... */ -static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) +static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) { REGF *regf = h->backend_data; KEY_SEC_DESC *tsec = NULL; @@ -618,7 +618,7 @@ static KEY_SEC_DESC *nt_create_init_sec(REG_HANDLE *h) /* Get the header of the registry. Return a pointer to the structure * If the mmap'd area has not been allocated, then mmap the input file */ -static REGF_HDR *nt_get_regf_hdr(REG_HANDLE *h) +static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) { REGF *regf = h->backend_data; SMB_REG_ASSERT(regf); @@ -676,7 +676,7 @@ static int valid_regf_hdr(REGF_HDR *regf_hdr) /* * Create a new entry in the map, and increase the size of the map if needed */ -static SK_MAP *alloc_sk_map_entry(REG_HANDLE *h, KEY_SEC_DESC *tmp, int sk_off) +static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, int sk_off) { REGF *regf = h->backend_data; if (!regf->sk_map) { /* Allocate a block of 10 */ @@ -731,7 +731,7 @@ KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) /* * Allocate a KEY_SEC_DESC if we can't find one in the map */ -static KEY_SEC_DESC *lookup_create_sec_key(REG_HANDLE *h, SK_MAP *sk_map, int sk_off) +static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_map, int sk_off) { REGF *regf = h->backend_data; KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); @@ -750,7 +750,7 @@ static KEY_SEC_DESC *lookup_create_sec_key(REG_HANDLE *h, SK_MAP *sk_map, int sk } } -static SEC_DESC *process_sec_desc(REG_HANDLE *regf, SEC_DESC *sec_desc) +static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc) { SEC_DESC *tmp = NULL; @@ -790,7 +790,7 @@ static SEC_DESC *process_sec_desc(REG_HANDLE *regf, SEC_DESC *sec_desc) return tmp; } -static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, int size) +static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_off, int size) { KEY_SEC_DESC *tmp = NULL; int sk_next_off, sk_prev_off, sk_size; @@ -879,38 +879,34 @@ static KEY_SEC_DESC *process_sk(REG_HANDLE *regf, SK_HDR *sk_hdr, int sk_off, in /* * Process a VK header and return a value */ -static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **value) +static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR *vk_hdr, int size, struct registry_value **value) { - char val_name[1024]; - REGF *regf = parent->handle->backend_data; + REGF *regf = parent->hive->backend_data; int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - REG_VAL *tmp = NULL; + struct registry_value *tmp = NULL; if (!vk_hdr) return WERR_INVALID_PARAM; if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", - vk_id, (int)vk_hdr, parent->handle->location)); + vk_id, (int)vk_hdr, parent->hive->location)); return WERR_GENERAL_FAILURE; } nam_len = SVAL(&vk_hdr->nam_len,0); - val_name[nam_len] = '\0'; flag = SVAL(&vk_hdr->flag,0); dat_type = IVAL(&vk_hdr->dat_type,0); dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ dat_off = IVAL(&vk_hdr->dat_off,0); - tmp = reg_val_new(parent, NULL); - tmp->has_name = flag; + tmp = talloc_p(mem_ctx, struct registry_value); tmp->data_type = dat_type; - if (flag & 0x01) { - strncpy(val_name, vk_hdr->dat_name, nam_len); - tmp->name = strdup(val_name); + if (flag & FLAG_HAS_NAME) { + tmp->name = talloc_strndup(mem_ctx, vk_hdr->dat_name, nam_len); + } else { + tmp->name = NULL; } - else - strncpy(val_name, "", 10); /* * Allocate space and copy the data as a BLOB @@ -918,9 +914,7 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val if (dat_len&0x7FFFFFFF) { - char *dtmp = (char *)talloc(tmp->mem_ctx, dat_len&0x7FFFFFFF); - - tmp->data_blk = dtmp; + char *dtmp = (char *)talloc(mem_ctx, dat_len&0x7FFFFFFF); if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ char *dat_ptr = LOCN(regf->base, dat_off); @@ -937,6 +931,15 @@ static WERROR vk_to_val(REG_KEY *parent, VK_HDR *vk_hdr, int size, REG_VAL **val memcpy(dtmp, &dat_off, dat_len); } + + if(tmp->data_type == REG_SZ) { + char *ret; + dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (const void **)&ret); + dtmp = ret; + } + + + tmp->data_blk = dtmp; tmp->data_len = dat_len; } @@ -958,7 +961,7 @@ static BOOL vl_verify(VL_TYPE vl, int count, int size) #endif -static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) +static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) { int lf_id; if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { @@ -969,7 +972,7 @@ static WERROR lf_verify(REG_HANDLE *h, LF_HDR *lf_hdr, int size) return WERR_OK; } -static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count) +static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, int *count) { WERROR error; @@ -986,23 +989,23 @@ static WERROR lf_num_entries(REG_HANDLE *h, LF_HDR *lf_hdr, int size, int *count } -static WERROR nk_to_key(REG_HANDLE *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **); +static WERROR nk_to_key(TALLOC_CTX *, struct registry_hive *regf, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **); /* * Process an LF Header and return a list of sub-keys */ -static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG_KEY **key) +static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_HDR *lf_hdr, int size, int n, struct registry_key **key) { - REGF *regf = parent->handle->backend_data; + REGF *regf = parent->hive->backend_data; int count, nk_off; NK_HDR *nk_hdr; WERROR error; if (!lf_hdr) return WERR_INVALID_PARAM; - error = lf_verify(parent->handle, lf_hdr, size); + error = lf_verify(parent->hive, lf_hdr, size); if(!W_ERROR_IS_OK(error)) return error; SMB_REG_ASSERT(size < 0); @@ -1015,13 +1018,13 @@ static WERROR lf_get_entry(REG_KEY *parent, LF_HDR *lf_hdr, int size, int n, REG nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); DEBUG(2, ("NK Offset: %0X\n", nk_off)); nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - return nk_to_key(parent->handle, nk_hdr, BLK_SIZE(nk_hdr), parent, key); + return nk_to_key(mem_ctx, parent->hive, nk_hdr, BLK_SIZE(nk_hdr), parent, key); } -static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent, REG_KEY **key) +static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **key) { REGF *regf = h->backend_data; - REG_KEY *tmp = NULL, *own; + struct registry_key *tmp = NULL, *own; int namlen, clsname_len, sk_off, own_off; uint_t nk_id; SK_HDR *sk_hdr; @@ -1032,7 +1035,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", - nk_id, (int)nk_hdr, parent->handle->location)); + nk_id, (int)nk_hdr, parent->hive->location)); return WERR_INVALID_PARAM; } @@ -1071,8 +1074,9 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent return WERR_GENERAL_FAILURE; } - if(type == REG_ROOT_KEY) tmp = reg_key_new_abs(key_name, h, nk_hdr); - else tmp = reg_key_new_rel(key_name, parent, nk_hdr); + tmp = talloc_p(mem_ctx, struct registry_key); + tmp->name = talloc_strdup(mem_ctx, key_name); + tmp->backend_data = nk_hdr; DEBUG(2, ("Key name: %s\n", key_name)); @@ -1089,7 +1093,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - pull_ucs2_talloc(tmp->mem_ctx, &tmp->class_name, clsnamep); + pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); DEBUGADD(2,(" Class Name: %s\n", cls_name)); @@ -1100,7 +1104,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent */ own_off = IVAL(&nk_hdr->own_off,0); - own = (REG_KEY *)LOCN(regf->base, own_off); + own = (struct registry_key *)LOCN(regf->base, own_off); DEBUG(2, ("Owner Offset: %0X\n", own_off)); DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", @@ -1136,7 +1140,7 @@ static WERROR nk_to_key(REG_HANDLE *h, NK_HDR *nk_hdr, int size, REG_KEY *parent /* * Allocate a new hbin block, set up the header for the block etc */ -static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) +static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) { REGF *regf = h->backend_data; HBIN_BLK *tmp; @@ -1185,7 +1189,7 @@ static HBIN_BLK *nt_create_hbin_blk(REG_HANDLE *h, int size) * Allocate a unit of space ... and return a pointer as function param * and the block's offset as a side effect */ -static void *nt_alloc_regf_space(REG_HANDLE *h, int size, uint_t *off) +static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) { REGF *regf = h->backend_data; int tmp = 0; @@ -1268,7 +1272,7 @@ static void *nt_alloc_regf_space(REG_HANDLE *h, int size, uint_t *off) /* * Store a SID at the location provided */ -static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, uint8_t *locn) +static int nt_store_SID(struct registry_hive *regf, DOM_SID *sid, uint8_t *locn) { int i; uint8_t *p = locn; @@ -1290,7 +1294,7 @@ static int nt_store_SID(REG_HANDLE *regf, DOM_SID *sid, uint8_t *locn) } -static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, uint8_t *locn) +static int nt_store_ace(struct registry_hive *regf, SEC_ACE *ace, uint8_t *locn) { int size = 0; SEC_ACE *reg_ace = (SEC_ACE *)locn; @@ -1321,7 +1325,7 @@ static int nt_store_ace(REG_HANDLE *regf, SEC_ACE *ace, uint8_t *locn) /* * Store an ACL at the location provided */ -static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { +static int nt_store_acl(struct registry_hive *regf, SEC_ACL *acl, uint8_t *locn) { int size = 0, i; uint8_t *p = locn, *s; @@ -1357,7 +1361,7 @@ static int nt_store_acl(REG_HANDLE *regf, SEC_ACL *acl, uint8_t *locn) { * that first, then the owner, then the group SID. So, we do it that way * too. */ -static uint_t nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) +static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char *locn) { SEC_DESC *rsd = (SEC_DESC *)locn; uint_t size = 0, off = 0; @@ -1424,7 +1428,7 @@ static uint_t nt_store_sec_desc(REG_HANDLE *regf, SEC_DESC *sd, char *locn) * If it has already been stored, just get its offset from record * otherwise, store it and record its offset */ -static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) +static uint_t nt_store_security(struct registry_hive *regf, KEY_SEC_DESC *sec) { int size = 0; uint_t sk_off; @@ -1480,7 +1484,7 @@ static uint_t nt_store_security(REG_HANDLE *regf, KEY_SEC_DESC *sec) * We return the offset of the NK struct * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... */ -static int nt_store_reg_key(REG_HANDLE *regf, REG_KEY *key) +static int nt_store_reg_key(struct registry_hive *regf, struct registry_key *key) { NK_HDR *nk_hdr; uint_t nk_off, sk_off, size; @@ -1543,7 +1547,7 @@ error: * We actually create the registry header block and link it to the chain * of output blocks. */ -static REGF_HDR *nt_get_reg_header(REG_HANDLE *h) { +static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { REGF *regf = h->backend_data; HBIN_BLK *tmp = NULL; @@ -1567,7 +1571,7 @@ error: #endif -static WERROR nt_close_registry (REG_HANDLE *h) +static WERROR nt_close_registry (struct registry_hive *h) { REGF *regf = h->backend_data; if (regf->base) munmap(regf->base, regf->sbuf.st_size); @@ -1577,16 +1581,16 @@ static WERROR nt_close_registry (REG_HANDLE *h) return WERR_OK; } -static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char *credentials) +static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) { REGF *regf; REGF_HDR *regf_hdr; uint_t regf_id, hbin_id; HBIN_HDR *hbin_hdr; - regf = (REGF *)talloc_p(h->mem_ctx, REGF); + regf = (REGF *)talloc_p(mem_ctx, REGF); memset(regf, 0, sizeof(REGF)); - regf->owner_sid_str = credentials; + regf->owner_sid_str = h->credentials; h->backend_data = regf; DEBUG(5, ("Attempting to load registry file\n")); @@ -1659,18 +1663,13 @@ static WERROR nt_open_registry (REG_HANDLE *h, const char *location, const char h->backend_data = regf; - return WERR_OK; + return nk_to_key(mem_ctx, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); } -static WERROR nt_get_root_key(REG_HANDLE *h, int hive, REG_KEY **key) -{ - if(hive != 0) return WERR_NO_MORE_ITEMS; - return nk_to_key(h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); -} -static WERROR nt_num_subkeys(REG_KEY *k, int *num) +static WERROR nt_num_subkeys(struct registry_key *k, int *num) { - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; LF_HDR *lf_hdr; int lf_off; NK_HDR *nk_hdr = k->backend_data; @@ -1682,23 +1681,23 @@ static WERROR nt_num_subkeys(REG_KEY *k, int *num) } lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_num_entries(k->handle, lf_hdr, BLK_SIZE(lf_hdr), num); + return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); } -static WERROR nt_num_values(REG_KEY *k, int *count) +static WERROR nt_num_values(struct registry_key *k, int *count) { NK_HDR *nk_hdr = k->backend_data; *count = IVAL(&nk_hdr->val_cnt,0); return WERR_OK; } -static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) +static WERROR nt_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_value **value) { VL_TYPE *vl; int val_off, vk_off; int val_count; VK_HDR *vk_hdr; - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; NK_HDR *nk_hdr = k->backend_data; val_count = IVAL(&nk_hdr->val_cnt,0); val_off = IVAL(&nk_hdr->val_off,0); @@ -1709,12 +1708,12 @@ static WERROR nt_value_by_index(REG_KEY *k, int n, REG_VAL **value) vk_off = IVAL(&vl[n],0); vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - return vk_to_val(k, vk_hdr, BLK_SIZE(vk_hdr), value); + return vk_to_val(mem_ctx, k, vk_hdr, BLK_SIZE(vk_hdr), value); } -static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey) +static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_key **subkey) { - REGF *regf = k->handle->backend_data; + REGF *regf = k->hive->backend_data; int lf_off; NK_HDR *nk_hdr = k->backend_data; LF_HDR *lf_hdr; @@ -1727,17 +1726,15 @@ static WERROR nt_key_by_index(REG_KEY *k, int n, REG_KEY **subkey) if (lf_off != -1) { lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_get_entry(k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); + return lf_get_entry(mem_ctx, k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); } return WERR_NO_MORE_ITEMS; } -static struct registry_ops reg_backend_nt4 = { +static struct registry_operations reg_backend_nt4 = { .name = "nt4", - .open_registry = nt_open_registry, - .close_registry = nt_close_registry, - .get_hive = nt_get_root_key, + .open_hive = nt_open_hive, .num_subkeys = nt_num_subkeys, .num_values = nt_num_values, .get_subkey_by_index = nt_key_by_index, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 0d8d935a4a..1c887fc411 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" -#include "lib/registry/common/registry.h" /** * This is the RPC backend for the registry library. @@ -37,7 +36,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) } -#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, REG_KEY *h, struct policy_handle *hnd) \ +#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ { \ struct winreg_Open ## u r; \ struct winreg_OpenUnknown unknown; \ @@ -49,7 +48,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ - status = dcerpc_winreg_Open ## u(p, h->mem_ctx, &r); \ + status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ if (NT_STATUS_IS_ERR(status)) {\ DEBUG(0,("Error executing open\n"));\ return ntstatus_to_werror(status);\ @@ -74,7 +73,7 @@ struct rpc_key_data { struct { const char *name; - WERROR (*open) (struct dcerpc_pipe *p, REG_KEY *k, struct policy_handle *h); + WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); } known_hives[] = { { "HKEY_LOCAL_MACHINE", open_HKLM }, { "HKEY_CURRENT_USER", open_HKCU }, @@ -84,122 +83,124 @@ struct { { NULL, NULL } }; -static WERROR rpc_query_key(REG_KEY *k); +static WERROR rpc_query_key(struct registry_key *k); -static WERROR rpc_open_registry(REG_HANDLE *h, const char *location, const char *credentials) +WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) +{ + int i = 0; + *hives = talloc_p(mem_ctx, char *); + for(i = 0; known_hives[i].name; i++) { + *hives = talloc_realloc_p(*hives, char *, i+2); + (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name); + } + (*hives)[i] = NULL; + return WERR_OK; +} + +static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { NTSTATUS status; char *user, *pass; + struct rpc_key_data *mykeydata; + struct dcerpc_pipe *p; + int n; - if(!credentials || !location) return WERR_INVALID_PARAM; + if(!h->credentials || !h->location) return WERR_INVALID_PARAM; - user = talloc_strdup(h->mem_ctx, credentials); + user = talloc_strdup(mem_ctx, h->credentials); pass = strchr(user, '%'); - *pass = '\0'; pass++; + if(pass) + { + *pass = '\0'; pass++; + } else { + pass = ""; + } - status = dcerpc_pipe_connect((struct dcerpc_pipe **)&h->backend_data, h->location, + status = dcerpc_pipe_connect(&p, h->location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, lp_workgroup(), user, pass); - - return ntstatus_to_werror(status); -} -static WERROR rpc_get_hive(REG_HANDLE *h, int n, REG_KEY **k) -{ - struct rpc_key_data *mykeydata; - WERROR error; + h->backend_data = p; + + if(NT_STATUS_IS_ERR(status)) return ntstatus_to_werror(status); + + for(n = 0; known_hives[n].name; n++) + { + if(!strcmp(known_hives[n].name, h->backend_hivename)) break; + } + if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; - *k = reg_key_new_abs(known_hives[n].name, h, NULL); - (*k)->backend_data = mykeydata = talloc_p((*k)->mem_ctx, struct rpc_key_data); + + *k = talloc_p(mem_ctx, struct registry_key); + (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; - error = known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &mykeydata->pol); - return error; + return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol)); } -static WERROR rpc_close_registry(REG_HANDLE *h) +static WERROR rpc_close_registry(struct registry_hive *h) { dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data); return WERR_OK; } -static WERROR rpc_key_put_rpc_data(REG_KEY *k, struct rpc_key_data **data) +static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) { struct winreg_OpenKey r; - WERROR error; - REG_KEY *hivekey; struct rpc_key_data *mykeydata; - if(k->backend_data) { - *data = k->backend_data; - return WERR_OK; - } - - k->backend_data = mykeydata = talloc_p(k->mem_ctx, struct rpc_key_data); - *data = mykeydata; + k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); - error = rpc_get_hive(k->handle, k->hive, &hivekey); - if(!W_ERROR_IS_OK(error))return error; - r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol); - init_winreg_String(&r.in.keyname, reg_key_get_path(k)); + r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); + init_winreg_String(&r.in.keyname, k->path); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); return r.out.result; } -static WERROR rpc_open_key(REG_HANDLE *h, int hive, const char *name, REG_KEY **key) +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { struct rpc_key_data *mykeydata; struct winreg_OpenKey r; - REG_KEY *hivekey; - WERROR error; - - *key = reg_key_new_abs(name, h, NULL); - (*key)->backend_data = mykeydata = talloc_p((*key)->mem_ctx, struct rpc_key_data); + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->name = talloc_strdup(mem_ctx, name); + + (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); - error = rpc_get_hive(h, hive, &hivekey); - if(!W_ERROR_IS_OK(error))return error; - r.in.handle = &(((struct rpc_key_data *)hivekey->backend_data)->pol); + r.in.handle = &(((struct rpc_key_data *)h->root->backend_data)->pol); init_winreg_String(&r.in.keyname, name); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(*key)->handle->backend_data, (*key)->mem_ctx, &r); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->backend_data), mem_ctx, &r); return r.out.result; } -static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) +static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) { - struct winreg_EnumValue r; - struct winreg_Uint8buf vb; - struct winreg_EnumValueName vn; - NTSTATUS status; - struct rpc_key_data *mykeydata; - uint32_t type = 0x0, requested_len = 0, returned_len = 0; + struct rpc_key_data *mykeydata = parent->backend_data; + uint32_t requested_len = 0; WERROR error; - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - if(mykeydata->num_values == -1) { error = rpc_query_key(parent); if(!W_ERROR_IS_OK(error)) return error; @@ -207,6 +208,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) requested_len = mykeydata->max_valdatalen; +#if 0 /* EnumValue is not working yet ... */ r.in.handle = &mykeydata->pol; r.in.enum_index = n; r.in.type = r.out.type = &type; @@ -225,7 +227,7 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) vb.max_len = mykeydata->max_valdatalen; vb.offset = 0x0; vb.len = 0x0; - vb.buffer = talloc_array_p(parent->mem_ctx, uint8, mykeydata->max_valdatalen); + vb.buffer = talloc_array_p(mem_ctx, uint8, mykeydata->max_valdatalen); r.in.value = r.out.value = &vb; status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); @@ -242,23 +244,20 @@ static WERROR rpc_get_value_by_index(REG_KEY *parent, int n, REG_VAL **value) exit(1); return WERR_OK; } +#endif - return r.out.result; + return WERR_NOT_SUPPORTED; } -static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) +static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) { struct winreg_EnumKey r; struct winreg_EnumKeyNameRequest keyname; struct winreg_String classname; struct winreg_Time tm; struct rpc_key_data *mykeydata = parent->backend_data; - WERROR error; NTSTATUS status; - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - r.in.handle = &mykeydata->pol; keyname.unknown = 0x0000020a; init_winreg_String(&keyname.key_name, NULL); @@ -271,40 +270,33 @@ static WERROR rpc_get_subkey_by_index(REG_KEY *parent, int n, REG_KEY **subkey) r.in.enum_index = n; r.in.unknown = r.out.unknown = 0x0414; r.in.key_name_len = r.out.key_name_len = 0; - status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); + status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - *subkey = reg_key_new_rel(r.out.out_name->name, parent, NULL); + if(parent->hive->root == parent) + return rpc_open_key(mem_ctx, parent->hive, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); + return rpc_open_key(mem_ctx, parent->hive, talloc_asprintf(mem_ctx, "%s\\%s", parent->path, r.out.out_name->name), subkey); } return r.out.result; } -static WERROR rpc_add_key(REG_KEY *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, REG_KEY **key) +static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) { - struct rpc_key_data *mykeydata; - WERROR error; - - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - - /* FIXME */ return WERR_NOT_SUPPORTED; } -static WERROR rpc_query_key(REG_KEY *k) +static WERROR rpc_query_key(struct registry_key *k) { NTSTATUS status; - WERROR error; struct winreg_QueryInfoKey r; - struct rpc_key_data *mykeydata; - - error = rpc_key_put_rpc_data(k, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; + struct rpc_key_data *mykeydata = k->backend_data; + TALLOC_CTX *mem_ctx = talloc_init("query_key"); init_winreg_String(&r.in.class, NULL); r.in.handle = &mykeydata->pol; - status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r); + talloc_destroy(mem_ctx); if (!NT_STATUS_IS_OK(status)) { printf("QueryInfoKey failed - %s\n", nt_errstr(status)); @@ -321,40 +313,37 @@ static WERROR rpc_query_key(REG_KEY *k) return r.out.result; } -static WERROR rpc_del_key(REG_KEY *k) +static WERROR rpc_del_key(struct registry_key *k) { NTSTATUS status; struct rpc_key_data *mykeydata = k->backend_data; struct winreg_DeleteKey r; - REG_KEY *parent; + struct registry_key *parent; WERROR error; + TALLOC_CTX *mem_ctx = talloc_init("del_key"); - error = reg_key_get_parent(k, &parent); - if(!W_ERROR_IS_OK(error)) return error; + error = reg_key_get_parent(mem_ctx, k, &parent); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } + + mykeydata = parent->backend_data; - error = rpc_key_put_rpc_data(parent, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - r.in.handle = &mykeydata->pol; init_winreg_String(&r.in.key, k->name); - status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->handle->backend_data, k->mem_ctx, &r); + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); - return r.out.result; -} + talloc_destroy(mem_ctx); -static void rpc_close_key(REG_KEY *k) -{ - reg_key_free(k); + return r.out.result; } -static WERROR rpc_num_values(REG_KEY *key, int *count) { +static WERROR rpc_num_values(struct registry_key *key, int *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - error = rpc_key_put_rpc_data(key, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - if(mykeydata->num_values == -1) { error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; @@ -364,13 +353,10 @@ static WERROR rpc_num_values(REG_KEY *key, int *count) { return WERR_OK; } -static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { +static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; - error = rpc_key_put_rpc_data(key, &mykeydata); - if(!W_ERROR_IS_OK(error)) return error; - if(mykeydata->num_subkeys == -1) { error = rpc_query_key(key); if(!W_ERROR_IS_OK(error)) return error; @@ -380,19 +366,17 @@ static WERROR rpc_num_subkeys(REG_KEY *key, int *count) { return WERR_OK; } -static struct registry_ops reg_backend_rpc = { +static struct registry_operations reg_backend_rpc = { .name = "rpc", - .open_registry = rpc_open_registry, - .close_registry = rpc_close_registry, - .get_hive = rpc_get_hive, + .open_hive = rpc_open_hive, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, .get_value_by_index = rpc_get_value_by_index, .add_key = rpc_add_key, .del_key = rpc_del_key, - .free_key_backend_data = rpc_close_key, .num_subkeys = rpc_num_subkeys, .num_values = rpc_num_values, + .list_available_hives = rpc_list_hives, }; NTSTATUS registry_rpc_init(void) diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index f392759b8d..2184a8855d 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -20,7 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" -#include "lib/registry/common/registry.h" /** * The registry starts with a header that contains pointers to @@ -179,67 +178,18 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) } } -static WERROR w95_open_root (REG_HANDLE *h, int hive, REG_KEY **key) -{ - CREG *creg = h->backend_data; - - if(hive != 0) return WERR_NO_MORE_ITEMS; - - /* First element in rgkn should be root key */ - *key = reg_key_new_abs("", h, LOCN_RGKN(creg, sizeof(RGKN_HDR))); - - return WERR_OK; -} - -static WERROR w95_get_subkey_by_index (REG_KEY *parent, int n, REG_KEY **key) -{ - CREG *creg = parent->handle->backend_data; - RGKN_KEY *rgkn_key = parent->backend_data; - RGKN_KEY *child; - DWORD child_offset; - DWORD cur = 0; - - /* Get id of first child */ - child_offset = rgkn_key->first_child_offset; - - while(child_offset != 0xFFFFFFFF) { - child = LOCN_RGKN(creg, child_offset); - - /* n == cur ? return! */ - if(cur == n) { - RGDB_KEY *rgdb_key; - char *name; - rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); - if(!rgdb_key) { - DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); - return WERR_FOOBAR; - } - name = strndup((char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); - *key = reg_key_new_rel(name, parent, child); - SAFE_FREE(name); - return WERR_OK; - } - - cur++; - - child_offset = child->next_offset; - } - - return WERR_NO_MORE_ITEMS; -} - -static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *credentials) +static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **root) { CREG *creg; DWORD creg_id, rgkn_id; DWORD i; DWORD offset; - creg = talloc_p(h->mem_ctx, CREG); + creg = talloc_p(mem_ctx, CREG); memset(creg, 0, sizeof(CREG)); h->backend_data = creg; - if((creg->fd = open(location, O_RDONLY, 0000)) < 0) { + if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) { return WERR_FOOBAR; } @@ -250,7 +200,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0); if ((int)creg->base == 1) { - DEBUG(0,("Could not mmap file: %s, %s\n", location, strerror(errno))); + DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno))); return WERR_FOOBAR; } @@ -258,7 +208,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) { DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n", - creg_id, location)); + creg_id, h->location)); return WERR_FOOBAR; } @@ -266,7 +216,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", - rgkn_id, location)); + rgkn_id, h->location)); return WERR_FOOBAR; } @@ -282,7 +232,7 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre } #endif - creg->rgdb_keys = talloc_array_p(h->mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); + creg->rgdb_keys = talloc_array_p(mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); offset = 0; DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); @@ -291,14 +241,14 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n", - rgdb_hdr->RGDB_ID, location)); + rgdb_hdr->RGDB_ID, h->location)); return WERR_FOOBAR; } else { DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); } - creg->rgdb_keys[i] = talloc_array_p(h->mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); + creg->rgdb_keys[i] = talloc_array_p(mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); parse_rgdb_block(creg, rgdb_hdr); @@ -306,11 +256,51 @@ static WERROR w95_open_reg (REG_HANDLE *h, const char *location, const char *cre offset+=rgdb_hdr->size; } - + /* First element in rgkn should be root key */ + *root = talloc_p(mem_ctx, struct registry_key); + (*root)->name = NULL; + (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); + return WERR_OK; } -static WERROR w95_close_reg(REG_HANDLE *h) +static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **key) +{ + CREG *creg = parent->hive->backend_data; + RGKN_KEY *rgkn_key = parent->backend_data; + RGKN_KEY *child; + DWORD child_offset; + DWORD cur = 0; + + /* Get id of first child */ + child_offset = rgkn_key->first_child_offset; + + while(child_offset != 0xFFFFFFFF) { + child = LOCN_RGKN(creg, child_offset); + + /* n == cur ? return! */ + if(cur == n) { + RGDB_KEY *rgdb_key; + rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); + if(!rgdb_key) { + DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); + return WERR_FOOBAR; + } + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->backend_data = child; + (*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); + return WERR_OK; + } + + cur++; + + child_offset = child->next_offset; + } + + return WERR_NO_MORE_ITEMS; +} + +static WERROR w95_close_reg(struct registry_hive *h) { CREG *creg = h->backend_data; if (creg->base) munmap(creg->base, creg->sbuf.st_size); @@ -319,47 +309,51 @@ static WERROR w95_close_reg(REG_HANDLE *h) return WERR_OK; } +static WERROR w95_num_values(struct registry_key *k, int *count) +{ + RGKN_KEY *rgkn_key = k->backend_data; + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + + if(!rgdb_key) return WERR_FOOBAR; + + *count = rgdb_key->num_values; + + return WERR_OK; +} -static WERROR w95_fetch_values(REG_KEY *k, int *count, REG_VAL ***values) +static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) { RGKN_KEY *rgkn_key = k->backend_data; DWORD i; DWORD offset = 0; - RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->handle->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + RGDB_VALUE *curval; if(!rgdb_key) return WERR_FOOBAR; - *count = rgdb_key->num_values; + if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS; - if((*count) == 0) return WERR_OK; + for(i = 0; i < idx; i++) { + curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); + offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len; + } - (*values) = talloc_array_p(k->mem_ctx, REG_VAL *, (*count)+1); - for(i = 0; i < rgdb_key->num_values; i++) { - RGDB_VALUE *val = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); - (*values)[i] = reg_val_new(k, val); - - /* Name */ - (*values)[i]->name = talloc_strndup(k->mem_ctx, (char *)val+sizeof(RGDB_VALUE), val->name_len); + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->backend_data = curval; + (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); - /* Value */ - (*values)[i]->data_len = val->data_len; - (*values)[i]->data_blk = talloc_memdup((*values)[i]->mem_ctx, (char *)val+sizeof(RGDB_VALUE)+val->name_len, val->data_len); - - /* Type */ - (*values)[i]->data_type = val->type; - - offset+=sizeof(RGDB_VALUE) + val->name_len + val->data_len; - } + (*value)->data_len = curval->data_len; + (*value)->data_blk = talloc_memdup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); + (*value)->data_type = curval->type; return WERR_OK; } -static struct registry_ops reg_backend_w95 = { +static struct registry_operations reg_backend_w95 = { .name = "w95", - .open_registry = w95_open_reg, - .close_registry = w95_close_reg, - .get_hive = w95_open_root, - .fetch_values = w95_fetch_values, + .open_hive = w95_open_reg, + .get_value_by_index = w95_get_value_by_id, + .num_values = w95_num_values, .get_subkey_by_index = w95_get_subkey_by_index, }; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index c46411ae31..524e538591 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -21,47 +21,57 @@ #include "includes.h" -static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) +static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) { int i; - REG_KEY *t1, *t2; - REG_VAL *v1, *v2; + struct registry_key *t1, *t2; + struct registry_value *v1, *v2; WERROR error1, error2; + TALLOC_CTX *mem_ctx = talloc_init("writediff"); - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(oldkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(newkey, reg_key_name(t1), &t2); + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2); if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "-%s\n", reg_key_get_path(t1)+1); + fprintf(out, "-%s\n", t1->path+1); } else if(!W_ERROR_IS_OK(error2)) { DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(newkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1), &t2); + mem_ctx = talloc_init("writediff"); + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2); if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1); + fprintf(out, "\n[%s]\n", t1->path+1); } else if(!W_ERROR_IS_OK(error2)) { DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); } writediff(t2, t1, out); } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); return; } - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(newkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(oldkey, reg_val_name(v1), &v2); - if ((W_ERROR_IS_OK(error2) && (reg_val_size(v2) != reg_val_size(v1) || memcmp(reg_val_data_blk(v1), reg_val_data_blk(v2), reg_val_size(v1)))) + + mem_ctx = talloc_init("writediff"); + + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); + if ((W_ERROR_IS_OK(error2) && (v2->data_len != v1->data_len || memcmp(v1->data_blk, v2->data_blk, v1->data_len))) || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(v1), str_regtype(reg_val_type(v1)), reg_val_data_string(v1)); + fprintf(out, "\"%s\"=%s:%s\n", v1->name, str_regtype(v1->data_type), reg_val_data_string(mem_ctx, v1)); } if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { @@ -69,22 +79,27 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; } + mem_ctx = talloc_init("writediff"); - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(oldkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(newkey, reg_val_name(v1), &v2); + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) { + error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2); if(W_ERROR_IS_OK(error2)) { } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=-\n", reg_val_name(v1)); + fprintf(out, "\"%s\"=-\n", v1->name); } else { DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); } } + talloc_destroy(mem_ctx); + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); return; @@ -100,8 +115,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; - REG_HANDLE *h1, *h2; - REG_KEY *root1 = NULL, *root2; + struct registry_context *h1, *h2; int from_null = 0; int i; WERROR error, error2; @@ -114,6 +128,12 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -140,7 +160,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(!backend1) backend1 = "dir"; - error = reg_open(backend1, location1, credentials1, &h1); + error = reg_open(&h1, backend1, location1, credentials1); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); return 1; @@ -155,7 +175,7 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) if(!backend2) backend2 = "dir"; - error = reg_open(backend2, location2, credentials2, &h2); + error = reg_open(&h2, backend2, location2, credentials2); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); return 1; @@ -176,20 +196,8 @@ static void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) error2 = error = WERR_OK; - for(i = 0; ; i++) { - if(backend1) error = reg_get_hive(h1, i, &root1); - else root1 = NULL; - - if(!W_ERROR_IS_OK(error)) break; - - if(backend2) error2 = reg_get_hive(h2, i, &root2); - else root2 = NULL; - - if(!W_ERROR_IS_OK(error2)) break; - - writediff(root1, root2, fd); - - if(!root1 && !root2) break; + for(i = 0; i < h1->num_hives && i < h2->num_hives; i++) { + writediff(h1->hives[i]->root, h2->hives[i]->root, fd); } fclose(fd); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 7eddea2b93..1b33628a71 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -664,12 +664,13 @@ static CMD_FILE *cmd_file_create(const char *file) char *str_type(uint8_t type); -static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) +static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd_file_name) { CMD *cmd; BOOL modified = False; CMD_FILE *cmd_file = NULL; - REG_KEY *tmp = NULL; + TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file"); + struct registry_key *tmp = NULL; WERROR error; cmd_file = cmd_file_create(cmd_file_name); @@ -680,12 +681,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) */ switch (cmd->cmd) { case CMD_ADD_KEY: - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); /* If we found it, apply the other bits, else create such a key */ if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) { - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key)); continue; @@ -699,12 +700,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) while (cmd->val_count) { VAL_SPEC_LIST *val = cmd->val_spec_list; - REG_VAL *reg_val = NULL; + struct registry_value *reg_val = NULL; if (val->type == REG_DELETE) { - error = reg_key_get_value_by_name( tmp, val->name, ®_val); + error = reg_key_get_value_by_name( mem_ctx, tmp, val->name, ®_val); if(W_ERROR_IS_OK(error)) { - error = reg_val_del(reg_val); + error = reg_del_value(reg_val); } if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error removing value '%s'\n", val->name)); @@ -712,7 +713,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) modified = True; } else { - if(!W_ERROR_IS_OK(reg_key_add_value(tmp, val->name, val->type, val->val, strlen(val->val)))) { + if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, val->val, strlen(val->val)))) { DEBUG(0, ("Error adding new value '%s'\n", val->name)); continue; } @@ -732,7 +733,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) * Find the key if it exists, and delete it ... */ - error = reg_open_key_abs(r, cmd->key, &tmp); + error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); continue; @@ -760,7 +761,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) const char *credentials = NULL; const char *patch; const char *backend = "dir"; - REG_HANDLE *h; + struct registry_context *h; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP @@ -769,6 +770,12 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -782,7 +789,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) return 1; } - error = reg_open(backend, location, credentials, &h); + error = reg_open(&h, backend, location, credentials); if(!h) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); return 1; @@ -794,7 +801,7 @@ static int nt_apply_reg_command_file(REG_HANDLE *r, const char *cmd_file_name) nt_apply_reg_command_file(h, patch); - reg_free(h); + talloc_destroy(h->mem_ctx); return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 638ed70d5e..78fe36f1a0 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -33,96 +33,96 @@ * exit */ -static REG_KEY *cmd_info(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { time_t last_mod; - printf("Name: %s\n", reg_key_name(cur)); - printf("Full path: %s\n", reg_key_get_path(cur)); - printf("Key Class: %s\n", reg_key_class(cur)); - last_mod = nt_time_to_unix(reg_key_last_modified(cur)); + printf("Name: %s\n", cur->name); + printf("Full path: %s\n", cur->path); + printf("Key Class: %s\n", cur->class_name); + last_mod = nt_time_to_unix(cur->last_mod); printf("Time Last Modified: %s\n", ctime(&last_mod)); /* FIXME: Security info */ return cur; } -static REG_KEY *cmd_pwd(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - printf("%s\n", reg_key_get_path_abs(cur)); + printf("%s\n", cur->path); return cur; } -static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { /* FIXME */ return NULL; } -static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *new = NULL; + struct registry_key *new = NULL; WERROR error; if(argc < 2) { new = cur; } else { - error = reg_open_key(cur, argv[1], &new); + error = reg_open_key(mem_ctx, cur, argv[1], &new); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error))); return NULL; } } - printf("Current path is: %s\n", reg_key_get_path_abs(new)); + printf("Current path is: %s\n", new->path); return new; } -static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; WERROR error; - REG_VAL *value; - REG_KEY *sub; - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(cur, i, &sub)); i++) { - printf("K %s\n", reg_key_name(sub)); + struct registry_value *value; + struct registry_key *sub; + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, cur, i, &sub)); i++) { + printf("K %s\n", sub->name); } if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error))); } - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(cur, i, &value)); i++) { - printf("V \"%s\" %s %s\n", reg_val_name(value), str_regtype(reg_val_type(value)), reg_val_data_string(value)); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) { + printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); } return NULL; } -static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *tmp; + struct registry_key *tmp; if(argc < 2) { fprintf(stderr, "Usage: mkkey \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_key_add_name(cur, argv[1], 0, NULL, &tmp))) { + if(!W_ERROR_IS_OK(reg_key_add_name(mem_ctx, cur, argv[1], 0, NULL, &tmp))) { fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]); return NULL; } - fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path_abs(cur)); + fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], cur->path); return NULL; } -static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_KEY *key; + struct registry_key *key; if(argc < 2) { fprintf(stderr, "Usage: rmkey \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_open_key(cur, argv[1], &key))) { + if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) { fprintf(stderr, "No such subkey '%s'\n", argv[1]); return NULL; } @@ -136,20 +136,20 @@ static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - REG_VAL *val; + struct registry_value *val; if(argc < 2) { fprintf(stderr, "Usage: rmval \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_key_get_value_by_name(cur, argv[1], &val))) { + if(!W_ERROR_IS_OK(reg_key_get_value_by_name(mem_ctx, cur, argv[1], &val))) { fprintf(stderr, "No such value '%s'\n", argv[1]); return NULL; } - if(!W_ERROR_IS_OK(reg_val_del(val))) { + if(!W_ERROR_IS_OK(reg_del_value(val))) { fprintf(stderr, "Error deleting value '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); @@ -158,38 +158,33 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *cmd_hive(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; - WERROR error = WERR_OK; - for(i = 0; W_ERROR_IS_OK(error); i++) { - REG_KEY *hive; - error = reg_get_hive(reg_key_handle(cur), i, &hive); - if(!W_ERROR_IS_OK(error)) break; + for(i = 0; i < cur->hive->reg_ctx->num_hives; i++) { if(argc == 1) { - printf("%s\n", reg_key_name(hive)); - } else if(!strcmp(reg_key_name(hive), argv[1])) { - return hive; + printf("%s\n", cur->hive->reg_ctx->hives[i]->name); + } else if(!strcmp(cur->hive->reg_ctx->hives[i]->name, argv[1])) { + return cur->hive->reg_ctx->hives[i]->root; } - reg_key_free(hive); } return NULL; } -static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { exit(0); return NULL; } -static REG_KEY *cmd_help(REG_KEY *, int, char **); +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *, int, char **); struct { const char *name; const char *alias; const char *help; - REG_KEY *(*handle)(REG_KEY *, int argc, char **argv); + struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_key *, int argc, char **argv); } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, {"ch", "hive", "Change current hive", cmd_hive }, @@ -205,7 +200,7 @@ struct { {NULL } }; -static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { int i; printf("Available commands:\n"); @@ -215,7 +210,7 @@ static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) return NULL; } -static REG_KEY *process_cmd(REG_KEY *k, char *line) +static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key *k, char *line) { int argc; char **argv = NULL; @@ -229,7 +224,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) for(i = 0; regshell_cmds[i].name; i++) { if(!strcmp(regshell_cmds[i].name, argv[0]) || (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) { - return regshell_cmds[i].handle(k, argc, argv); + return regshell_cmds[i].handle(mem_ctx, k, argc, argv); } } @@ -240,7 +235,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line) #define MAX_COMPLETIONS 100 -static REG_KEY *current_key = NULL; +static struct registry_key *current_key = NULL; static char **reg_complete_command(const char *text, int end) { @@ -295,10 +290,11 @@ cleanup: static char **reg_complete_key(const char *text, int end) { - REG_KEY *subkey; + struct registry_key *subkey; int i, j = 0; int len; char **matches; + TALLOC_CTX *mem_ctx; /* Complete argument */ matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); @@ -306,22 +302,24 @@ static char **reg_complete_key(const char *text, int end) matches[0] = NULL; len = strlen(text); + mem_ctx = talloc_init("completion"); for(i = 0; j < MAX_COMPLETIONS-1; i++) { - WERROR status = reg_key_get_subkey_by_index(current_key, i, &subkey); + WERROR status = reg_key_get_subkey_by_index(mem_ctx, current_key, i, &subkey); if(W_ERROR_IS_OK(status)) { - if(!strncmp(text, reg_key_name(subkey), len)) { - matches[j] = strdup(reg_key_name(subkey)); + if(!strncmp(text, subkey->name, len)) { + matches[j] = strdup(subkey->name); j++; } - reg_key_free(subkey); } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) { break; } else { printf("Error creating completion list: %s\n", win_errstr(status)); + talloc_destroy(mem_ctx); return NULL; } } matches[j] = NULL; + talloc_destroy(mem_ctx); return matches; } @@ -341,10 +339,11 @@ static char **reg_completion(const char *text, int start, int end) int opt; const char *backend = "dir"; const char *credentials = NULL; - REG_KEY *curkey = NULL; + struct registry_key *curkey = NULL; poptContext pc; WERROR error; - REG_HANDLE *h; + TALLOC_CTX *mem_ctx = talloc_init("cmd"); + struct registry_context *h; struct poptOption long_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA @@ -352,13 +351,19 @@ static char **reg_completion(const char *text, int start, int end) {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL}, POPT_TABLEEND }; + + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { } - error = reg_open(backend, poptPeekArg(pc), credentials, &h); + error = reg_open(&h, backend, poptPeekArg(pc), credentials); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); return 1; @@ -367,14 +372,16 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); - error = reg_get_hive(h, 0, &curkey); - - if(!W_ERROR_IS_OK(error)) return 1; + curkey = h->hives[0]->root; while(True) { char *line, *prompt; - asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey)); + if(curkey->hive->name) { + asprintf(&prompt, "%s:%s> ", curkey->hive->name, curkey->path); + } else { + asprintf(&prompt, "%s> ", curkey->path); + } current_key = curkey; /* No way to pass a void * pointer via readline :-( */ @@ -384,10 +391,11 @@ static char **reg_completion(const char *text, int start, int end) break; if(line[0] != '\n') { - REG_KEY *new = process_cmd(curkey, line); + struct registry_key *new = process_cmd(mem_ctx, curkey, line); if(new)curkey = new; } } + talloc_destroy(mem_ctx); return 0; } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index b1ca9b3fb2..9748ca3438 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -21,39 +21,45 @@ #include "includes.h" -static void print_tree(int l, REG_KEY *p, int fullpath, int novals) +static void print_tree(int l, struct registry_key *p, int fullpath, int novals) { - REG_KEY *subkey; - REG_VAL *value; + struct registry_key *subkey; + struct registry_value *value; WERROR error; int i; + TALLOC_CTX *mem_ctx; for(i = 0; i < l; i++) putchar(' '); - if(fullpath) printf("%s\n", reg_key_get_path_abs(p)); - else printf("%s\n", reg_key_name(p)); + + /* Hive name */ + if(p->hive->root == p) printf("%s\n", p->hive->name); + else if(!p->name) printf("\n"); + else if(fullpath) printf("%s\n", p->path); + else printf("%s\n", p->name); - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(p, i, &subkey)); i++) { + mem_ctx = talloc_init("print_tree"); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) { print_tree(l+1, subkey, fullpath, novals); - reg_key_free(subkey); } + talloc_destroy(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", p->path, win_errstr(error))); } if(!novals) { - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(p, i, &value)); i++) { + mem_ctx = talloc_init("print_tree"); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, p, i, &value)); i++) { int j; char *desc; for(j = 0; j < l+1; j++) putchar(' '); - desc = reg_val_description(value); + desc = reg_val_description(mem_ctx, value); printf("%s\n", desc); - free(desc); - reg_val_free(value); } + talloc_destroy(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while fetching values for '%s': %s\n", reg_key_get_path_abs(p), win_errstr(error))); + DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error))); } } } @@ -64,8 +70,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) const char *backend = "dir"; const char *credentials = NULL; poptContext pc; - REG_KEY *root; - REG_HANDLE *h; + struct registry_context *h; WERROR error; int fullpath = 0, no_values = 0; struct poptOption long_options[] = { @@ -77,6 +82,12 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) POPT_TABLEEND }; + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); + } + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -84,7 +95,7 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) setup_logging("regtree", True); - error = reg_open(backend, poptPeekArg(pc), credentials, &h); + error = reg_open(&h, backend, poptPeekArg(pc), credentials); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error)); return 1; @@ -93,11 +104,8 @@ static void print_tree(int l, REG_KEY *p, int fullpath, int novals) error = WERR_OK; - for(i = 0; W_ERROR_IS_OK(error); i++) { - error = reg_get_hive(h, i, &root); - if(!W_ERROR_IS_OK(error)) return 1; - - print_tree(0, root, fullpath, no_values); + for(i = 0; i < h->num_hives; i++) { + print_tree(0, h->hives[i]->root, fullpath, no_values); } return 0; -- cgit From 79ae828819193dd9ed5e060f78a88752e30bd1c3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Sep 2004 23:50:28 +0000 Subject: r2542: I really don't like the 'substitute' code, and I particularly don't like it in the mainline code (outside the smb.conf magic). We will need to have a more useful 'helper' routine for this, but for now we at least get a reliable IP address. Also remove the unused 'socket' structure in the smb server - it seems to have been replaced by the socket library. Andrew Bartlett (This used to be commit d8fd19a2020da6cce691c0db2b00f42e31d672cc) --- source4/lib/substitute.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c index 7d3997ecd7..3de2966f56 100644 --- a/source4/lib/substitute.c +++ b/source4/lib/substitute.c @@ -52,18 +52,6 @@ static void setup_string(char **dest, const char *str) (*dest) = s; } -void sub_set_local_machine(const char *local_machine) -{ - if (!sub) return; - setup_string(&sub->local_machine, local_machine); -} - -void sub_set_remote_machine(const char *remote_machine) -{ - if (!sub) return; - setup_string(&sub->remote_machine, remote_machine); -} - void sub_set_remote_proto(const char *str) { if (!sub) return; @@ -76,19 +64,6 @@ void sub_set_remote_arch(const char *str) setup_string(&sub->remote_arch, str); } -const char *sub_get_remote_machine(void) -{ - if (!sub) return "UNKNOWN"; - return sub->remote_machine; -} - -const char *sub_get_local_machine(void) -{ - if (!sub) return "UNKNOWN"; - return sub->local_machine; -} - - /* setup the string used by %U substitution */ -- cgit From 9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 23 Sep 2004 00:51:45 +0000 Subject: r2552: Character set conversion and string handling updates. The intial motivation for this commit was to merge in some of the bugfixes present in Samba3's chrcnv and string handling code into Samba4. However, along the way I found a lot of unused functions, and decided to do a bit more... The strlen_m code now does not use a fixed buffer, but more work is needed to finish off other functions in str_util.c. These fixed length buffers hav caused very nasty, hard to chase down bugs at some sites. The strupper_m() function has a strupper_talloc() to replace it (we need to go around and fix more uses, but it's a start). Use of these new functions will avoid bugs where the upper or lowercase version of a string is a different length. I have removed the push_*_allocate functions, which are replaced by calls to push_*_talloc. Likewise, pstring and other 'fixed length' wrappers are removed, where possible. I have removed the first ('base pointer') argument, used by push_ucs2, as the Samba4 way of doing things ensures that this is always on an even boundary anyway. (It was used in only one place, in any case). (This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392) --- source4/lib/charcnv.c | 379 +++++++++++----------------------------------- source4/lib/util_str.c | 325 ++++++++++++++++++++------------------- source4/lib/util_unistr.c | 7 + 3 files changed, 267 insertions(+), 444 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index f30f5b9239..fd550895d0 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -181,7 +181,7 @@ ssize_t convert_string(charset_t from, charset_t to, } /** - * Convert between character sets, allocating a new buffer for the result. + * Convert between character sets, allocating a new buffer using talloc for the result. * * @param srclen length of source buffer. * @param dest always set at least to NULL @@ -190,7 +190,7 @@ ssize_t convert_string(charset_t from, charset_t to, * @returns Size in bytes of the converted string; or -1 in case of error. **/ -ssize_t convert_string_allocate(charset_t from, charset_t to, +ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest) { size_t i_len, o_len, destlen; @@ -210,7 +210,7 @@ ssize_t convert_string_allocate(charset_t from, charset_t to, if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, return -1*/ - DEBUG(3, ("convert_string_allocate: conversion not supported!\n")); + DEBUG(3, ("convert_string_talloc: conversion not supported!\n")); return -1; } @@ -218,10 +218,14 @@ ssize_t convert_string_allocate(charset_t from, charset_t to, outbuf = NULL; convert: destlen = destlen * 2; - ob = (char *)realloc(outbuf, destlen); + if (outbuf == NULL) { + ob = talloc_array_p(ctx, char, destlen); + } else { + ob = (char *)talloc_realloc(outbuf, destlen); + } if (!ob) { - DEBUG(0, ("convert_string_allocate: realloc failed!\n")); - SAFE_FREE(outbuf); + DEBUG(0, ("convert_string_talloc: realloc failed!\n")); + talloc_free(outbuf); return (size_t)-1; } else @@ -244,100 +248,25 @@ convert: break; } DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); + talloc_free(outbuf); /* smb_panic(reason); */ return (size_t)-1; } destlen = destlen - o_len; - *dest = (char *)Realloc(ob,destlen); + /* +2 for mandetory null termination, UTF8 or UTF16 */ + *dest = (char *)talloc_realloc(ob,destlen+2); if (!*dest) { - DEBUG(0, ("convert_string_allocate: out of memory!\n")); - SAFE_FREE(ob); + DEBUG(0, ("convert_string_talloc: out of memory!\n")); + talloc_free(ob); return (size_t)-1; } + ((char *)*dest)[destlen] = '\0'; + ((char *)*dest)[destlen+1] = '\0'; return destlen; } - -/** - * Convert between character sets, allocating a new buffer using talloc for the result. - * - * @param srclen length of source buffer. - * @param dest always set at least to NULL - * @note -1 is not accepted for srclen. - * - * @returns Size in bytes of the converted string; or -1 in case of error. - **/ -ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, const void **dest) -{ - void *alloced_string; - size_t dest_len; - void *dst; - - *dest = NULL; - dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string); - if (dest_len == (size_t)-1) - return (size_t)-1; - dst = talloc(ctx, dest_len + 2); - /* we want to be absolutely sure that the result is terminated */ - memcpy(dst, alloced_string, dest_len); - SSVAL(dst, dest_len, 0); - SAFE_FREE(alloced_string); - if (dst == NULL) - return -1; - *dest = dst; - return dest_len; -} - -size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) -{ - size_t size; - smb_ucs2_t *buffer; - - size = convert_string_allocate(CH_UNIX, CH_UTF16, src, srclen, - (void **) &buffer); - if (size == -1) { - smb_panic("failed to create UCS2 buffer"); - } - if (!strupper_w(buffer) && (dest == src)) { - free(buffer); - return srclen; - } - - size = convert_string(CH_UTF16, CH_UNIX, buffer, size, dest, destlen); - free(buffer); - return size; -} - -size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) -{ - size_t size; - smb_ucs2_t *buffer; - - size = convert_string_allocate(CH_UNIX, CH_UTF16, src, srclen, - (void **) &buffer); - if (size == -1) { - smb_panic("failed to create UCS2 buffer"); - } - if (!strlower_w(buffer) && (dest == src)) { - free(buffer); - return srclen; - } - size = convert_string(CH_UTF16, CH_UNIX, buffer, size, dest, destlen); - free(buffer); - return size; -} - -size_t ucs2_align(const void *base_ptr, const void *p, int flags) -{ - if (flags & (STR_NOALIGN|STR_ASCII)) - return 0; - return PTR_DIFF(p, base_ptr) & 1; -} - - /** * Copy a string from a char* unix src to a dos codepage string destination. * @@ -354,30 +283,49 @@ size_t ucs2_align(const void *base_ptr, const void *p, int flags) **/ ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) { - size_t src_len = strlen(src); - pstring tmpbuf; + size_t src_len; + ssize_t ret; + char *tmpbuf = NULL; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper(tmpbuf); + tmpbuf = strupper_talloc(NULL, src); + if (!tmpbuf) { + return -1; + } src = tmpbuf; } + src_len = strlen(src); if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; - return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); + ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); + talloc_free(tmpbuf); + return ret; } -ssize_t push_pstring(void *dest, const char *src) +/** + * Copy a string from a unix char* src to an ASCII destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) { - return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); } + /** * Copy a string from a dos codepage source to a unix char* destination. * @@ -435,26 +383,20 @@ ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, * @param dest_len is the maximum length allowed in the * destination. If dest_len is -1 then no maxiumum is used. **/ -ssize_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) +ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) { size_t len=0; size_t src_len = strlen(src); - pstring tmpbuf; + size_t ret; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); - if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper(tmpbuf); - src = tmpbuf; - } - if (flags & STR_TERMINATE) src_len++; - if (ucs2_align(base_ptr, dest, flags)) { + if (ucs2_align(NULL, dest, flags)) { *(char *)dest = 0; dest = (void *)((char *)dest + 1); if (dest_len) dest_len--; @@ -464,7 +406,24 @@ ssize_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest /* ucs2 is always a multiple of 2 bytes */ dest_len &= ~1; - len += convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); + ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); + if (ret == (size_t)-1) { + return 0; + } + + len += ret; + + if (flags & STR_UPPER) { + smb_ucs2_t *dest_ucs2 = dest; + size_t i; + for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { + smb_ucs2_t v = toupper_w(dest_ucs2[i]); + if (v != dest_ucs2[i]) { + dest_ucs2[i] = v; + } + } + } + return len; } @@ -483,58 +442,10 @@ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (const void **)dest); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest); } -/** - * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - * or -1 in case of error. - **/ - -ssize_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UTF16, src, src_len, (void **)dest); -} - -/** - Copy a string from a char* src to a UTF-8 destination. - Return the number of bytes occupied by the string in the destination - Flags can have: - STR_TERMINATE means include the null termination - STR_UPPER means uppercase in the destination - dest_len is the maximum length allowed in the destination. If dest_len - is -1 then no maxiumum is used. -**/ - -ssize_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) -{ - size_t src_len = strlen(src); - pstring tmpbuf; - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper(tmpbuf); - src = tmpbuf; - } - - if (flags & STR_TERMINATE) - src_len++; - - return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len); -} - /** * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc * @@ -548,23 +459,7 @@ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (const void **)dest); -} - -/** - * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t push_utf8_allocate(char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); } /** @@ -578,14 +473,14 @@ ssize_t push_utf8_allocate(char **dest, const char *src) The resulting string in "dest" is always null terminated. **/ -size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) { size_t ret; if (dest_len == (size_t)-1) dest_len = sizeof(pstring); - if (ucs2_align(base_ptr, src, flags)) { + if (ucs2_align(NULL, src, flags)) { src = (const void *)((const char *)src + 1); if (src_len > 0) src_len--; @@ -615,7 +510,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ ssize_t pull_ucs2_pstring(char *dest, const void *src) { - return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE); + return pull_ucs2(dest, src, sizeof(pstring), -1, STR_TERMINATE); } /** @@ -630,57 +525,7 @@ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src) { size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); *dest = NULL; - return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (const void **)dest); -} - -/** - * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_ucs2_allocate(void **dest, const smb_ucs2_t *src) -{ - size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); - *dest = NULL; - return convert_string_allocate(CH_UTF16, CH_UNIX, src, src_len, dest); -} - -/** - Copy a string from a utf-8 source to a unix char* destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - if STR_TERMINATE is set then src_len is ignored. - src_len is the length of the source area in bytes - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -ssize_t pull_utf8(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - size_t ret; - - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & STR_TERMINATE) { - if (src_len == (size_t)-1) { - src_len = strlen(src) + 1; - } else { - size_t len = strnlen(src, src_len); - if (len < src_len) - len++; - src_len = len; - } - } - - ret = convert_string(CH_UTF8, CH_UNIX, src, src_len, dest, dest_len); - if (dest_len) - dest[MIN(ret, dest_len-1)] = 0; - - return src_len; + return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); } /** @@ -695,24 +540,9 @@ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (const void **)dest); + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); } -/** - * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_utf8_allocate(void **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest); -} - /** Copy a string from a char* src to a unicode or ascii dos codepage destination choosing unicode or ascii based on the @@ -727,14 +557,16 @@ ssize_t pull_utf8_allocate(void **dest, const char *src) is -1 then no maxiumum is used. **/ -ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) +ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) { - if (!(flags & STR_ASCII) && \ - (((flags & STR_UNICODE) || \ - (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { - return push_ucs2(base_ptr, dest, src, dest_len, flags); + if (flags & STR_ASCII) { + return push_ascii(dest, src, dest_len, flags); + } else if (flags & STR_UNICODE) { + return push_ucs2(dest, src, dest_len, flags); + } else { + smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; } - return push_ascii(dest, src, dest_len, flags); } @@ -752,52 +584,15 @@ ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t de The resulting string in "dest" is always null terminated. **/ -ssize_t pull_string(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) { - if (!(flags & STR_ASCII) && \ - (((flags & STR_UNICODE) || \ - (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { - return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags); - } - return pull_ascii(dest, src, dest_len, src_len, flags); -} - -ssize_t align_string(const void *base_ptr, const char *p, int flags) -{ - if (!(flags & STR_ASCII) && \ - ((flags & STR_UNICODE || \ - (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) { - return ucs2_align(base_ptr, p, flags); - } - return 0; -} - -/** - Copy a string from a unicode or ascii source (depending on - the packet flags) to a TALLOC'ed destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - STR_UNICODE means to force as unicode. - STR_ASCII use ascii even with unicode packet. - STR_NOALIGN means don't do alignment. - if STR_TERMINATE is set then src_len is ignored is it is -1 - src_len is the length of the source area in bytes. - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -ssize_t pull_string_talloc(TALLOC_CTX *ctx, char **dest, const void *src, size_t src_len, int flags) -{ - if (!(flags & STR_ASCII) && \ - (flags & STR_UNICODE)) { - return pull_ucs2_talloc(ctx, dest, src); - } - *dest = NULL; - if (flags & STR_TERMINATE) { - *dest = talloc_strdup(ctx, src); - return strlen(*dest); + if (flags & STR_ASCII) { + return pull_ascii(dest, src, dest_len, src_len, flags); + } else if (flags & STR_UNICODE) { + return pull_ucs2(dest, src, dest_len, src_len, flags); + } else { + smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; } - *dest = talloc_strndup(ctx, src, src_len); - return src_len; } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index faa8690849..a71a9ee703 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 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 @@ -21,6 +23,11 @@ #include "includes.h" +/** + * @file + * @brief String utilities. + **/ + /** * Get the next token from a string, return False if none found. * Handles double-quotes. @@ -120,19 +127,20 @@ char **toktocliplist(const char *ptr, int *ctok, const char *sep) **/ static int StrCaseCmp_slow(const char *s1, const char *s2) { - smb_ucs2_t *u1, *u2; + smb_ucs2_t *u1 = NULL; + smb_ucs2_t *u2; int ret; - if (convert_string_allocate(CH_UNIX, CH_UTF16, s1, strlen(s1)+1, &u1) == -1 || - convert_string_allocate(CH_UNIX, CH_UTF16, s2, strlen(s2)+1, &u2) == -1) { + if (convert_string_talloc(NULL, CH_UNIX, CH_UTF16, s1, strlen(s1)+1, (void **)&u1) == -1 || + convert_string_talloc(u1, CH_UNIX, CH_UTF16, s2, strlen(s2)+1, (void **)&u2) == -1) { + talloc_free(u1); /* fallback to a simple comparison */ return strcasecmp(s1, s2); } ret = strcasecmp_w(u1, u2); - free(u1); - free(u2); + talloc_free(u1); return ret; } @@ -220,21 +228,6 @@ int strwicmp(const char *psz1, const char *psz2) return (*psz1 - *psz2); } -/** - Convert a string to upper case, but don't modify it. -**/ - -char *strupper_talloc(TALLOC_CTX *mem_ctx, const char *s) -{ - char *str; - - str = talloc_strdup(mem_ctx, s); - strupper(str); - - return str; -} - - /** String replace. NOTE: oldc and newc must be 7 bit characters @@ -243,38 +236,12 @@ char *strupper_talloc(TALLOC_CTX *mem_ctx, const char *s) void string_replace(char *s,char oldc,char newc) { if (strchr(s, oldc)) { - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(NULL, s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE); + pull_ucs2(s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE); } } -/** - Count the number of characters in a string. Normally this will - be the same as the number of bytes in a string for single byte strings, - but will be different for multibyte. -**/ - -size_t str_charnum(const char *s) -{ - uint16_t tmpbuf2[sizeof(pstring)]; - push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE); - return strlen_w(tmpbuf2); -} - -/** - Count the number of characters in a string. Normally this will - be the same as the number of bytes in a string for single byte strings, - but will be different for multibyte. -**/ - -size_t str_ascii_charnum(const char *s) -{ - pstring tmpbuf2; - push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE); - return strlen(tmpbuf2); -} - /** Trim the specified elements off the front and back of a string. **/ @@ -297,7 +264,9 @@ BOOL trim_string(char *s,const char *front,const char *back) if (front_len) { while (len && strncmp(s, front, front_len)==0) { - memcpy(s, s+front_len, (len-front_len)+1); + /* Must use memmove here as src & dest can + * easily overlap. Found by valgrind. JRA. */ + memmove(s, s+front_len, (len-front_len)+1); len -= front_len; ret=True; } @@ -320,7 +289,7 @@ BOOL trim_string(char *s,const char *front,const char *back) BOOL strhasupper(const char *s) { smb_ucs2_t *ptr; - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); for(ptr=tmpbuf;*ptr;ptr++) if(isupper_w(*ptr)) return True; @@ -334,7 +303,7 @@ BOOL strhasupper(const char *s) BOOL strhaslower(const char *s) { smb_ucs2_t *ptr; - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); for(ptr=tmpbuf;*ptr;ptr++) if(islower_w(*ptr)) return True; @@ -349,10 +318,17 @@ size_t count_chars(const char *s,char c) { smb_ucs2_t *ptr; int count; - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - for(count=0,ptr=tmpbuf;*ptr;ptr++) + smb_ucs2_t *alloc_tmpbuf = NULL; + + if (push_ucs2_talloc(NULL, &alloc_tmpbuf, s) == (size_t)-1) { + return 0; + } + + for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++) if(*ptr==UCS2_CHAR(c)) count++; + + talloc_free(alloc_tmpbuf); return(count); } @@ -506,6 +482,78 @@ char *StrnCpy(char *dest,const char *src,size_t n) } +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + +**/ + +size_t strhex_to_str(char *p, size_t len, const char *strhex) +{ + size_t i; + size_t num_chars = 0; + uint8_t lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1 = NULL, *p2 = NULL; + + for (i = 0; i < len && strhex[i] != 0; i++) { + if (strncasecmp(hexchars, "0x", 2) == 0) { + i++; /* skip two chars */ + continue; + } + + if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + i++; /* next hex digit */ + + if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) + break; + + /* get the two nybbles */ + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + p[num_chars] = (hinybble << 4) | lonybble; + num_chars++; + + p1 = NULL; + p2 = NULL; + } + return num_chars; +} + +DATA_BLOB strhex_to_data_blob(const char *strhex) +{ + DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1); + + ret_blob.length = strhex_to_str(ret_blob.data, + strlen(strhex), + strhex); + + return ret_blob; +} + +/** + * Routine to print a buffer as HEX digits, into an allocated string. + */ + +void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) +{ + int i; + char *hex_buffer; + + *out_hex_buffer = smb_xmalloc((len*2)+1); + hex_buffer = *out_hex_buffer; + + for (i = 0; i < len; i++) + slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); +} + /** Check if a string is part of a list. **/ @@ -688,7 +736,7 @@ char *strchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; - push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) return NULL; @@ -703,7 +751,7 @@ char *strrchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; - push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); p = strrchr_w(ws, UCS2_CHAR(c)); if (!p) return NULL; @@ -712,12 +760,55 @@ char *strrchr_m(const char *s, char c) return (char *)(s+strlen(s2)); } +/** + Convert a string to lower case, allocated with talloc +**/ + +char *strlower_talloc(TALLOC_CTX *ctx, const char *src) +{ + size_t size; + smb_ucs2_t *buffer; + char *dest; + + size = push_ucs2_talloc(ctx, &buffer, src); + if (size == -1) { + return NULL; + } + strlower_w(buffer); + + size = pull_ucs2_talloc(ctx, &dest, buffer); + talloc_free(buffer); + return dest; +} + +/** + Convert a string to UPPER case, allocated with talloc +**/ + +char *strupper_talloc(TALLOC_CTX *ctx, const char *src) +{ + size_t size; + smb_ucs2_t *buffer; + char *dest; + + size = push_ucs2_talloc(ctx, &buffer, src); + if (size == -1) { + return NULL; + } + strupper_w(buffer); + + size = pull_ucs2_talloc(ctx, &dest, buffer); + talloc_free(buffer); + return dest; +} + /** Convert a string to lower case. **/ void strlower_m(char *s) { + char *lower; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible @@ -733,15 +824,20 @@ void strlower_m(char *s) /* I assume that lowercased string takes the same number of bytes * as source string even in UTF-8 encoding. (VIV) */ - unix_strlower(s,strlen(s)+1,s,strlen(s)+1); + lower = strlower_talloc(NULL, s); + if (lower) { + safe_strcpy(s, lower, strlen(s)); + } + talloc_free(lower); } /** - Convert a string to upper case. + Convert a string to UPPER case. **/ void strupper_m(char *s) { + char *upper; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible @@ -755,18 +851,27 @@ void strupper_m(char *s) if (!*s) return; - /* I assume that lowercased string takes the same number of bytes - * as source string even in multibyte encoding. (VIV) */ - unix_strupper(s,strlen(s)+1,s,strlen(s)+1); + /* I assume that uppercased string takes the same number of bytes + * as source string even in UTF-8 encoding. (VIV) */ + upper = strupper_talloc(NULL, s); + if (upper) { + safe_strcpy(s, upper, strlen(s)); + } + talloc_free(upper); } - /** - work out the number of multibyte chars in a string + Count the number of UCS2 characters in a string. Normally this will + be the same as the number of bytes in a string for single byte strings, + but will be different for multibyte. **/ + size_t strlen_m(const char *s) { size_t count = 0; + smb_ucs2_t *tmp; + + size_t len; if (!s) { return 0; @@ -781,8 +886,12 @@ size_t strlen_m(const char *s) return count; } - push_ucs2(NULL,tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - return count + strlen_w(tmpbuf); + SMB_ASSERT(push_ucs2_talloc(NULL, &tmp, s) != -1); + + len = count + strlen_w(tmp); + talloc_free(tmp); + + return len; } /** @@ -798,21 +907,6 @@ size_t strlen_m_term(const char *s) return strlen_m(s) + 1; } -/** - Convert a string to upper case. -**/ - -char *strdup_upper(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_upper: Out of memory!\n")); - return NULL; - } - strupper_m(t); - return t; -} - /** Return a RFC2254 binary string representation of a buffer. Used in LDAP filters. @@ -1184,79 +1278,6 @@ void ipstr_list_free(char* ipstr_list) SAFE_FREE(ipstr_list); } -/** - Routine to get hex characters and turn them into a 16 byte array. - the array can be variable length, and any non-hex-numeric - characters are skipped. "0xnn" or "0Xnn" is specially catered - for. - - valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" - -**/ - -size_t strhex_to_str(char *p, size_t len, const char *strhex) -{ - size_t i; - size_t num_chars = 0; - uint8_t lonybble, hinybble; - const char *hexchars = "0123456789ABCDEF"; - char *p1 = NULL, *p2 = NULL; - - for (i = 0; i < len && strhex[i] != 0; i++) { - if (strncasecmp(hexchars, "0x", 2) == 0) { - i++; /* skip two chars */ - continue; - } - - if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) - break; - - i++; /* next hex digit */ - - if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) - break; - - /* get the two nybbles */ - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - p[num_chars] = (hinybble << 4) | lonybble; - num_chars++; - - p1 = NULL; - p2 = NULL; - } - return num_chars; -} - -DATA_BLOB strhex_to_data_blob(const char *strhex) -{ - DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1); - - ret_blob.length = strhex_to_str(ret_blob.data, - strlen(strhex), - strhex); - - return ret_blob; -} - -/** - * Routine to print a buffer as HEX digits, into an allocated string. - */ - -void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) -{ - int i; - char *hex_buffer; - - *out_hex_buffer = smb_xmalloc((len*2)+1); - hex_buffer = *out_hex_buffer; - - for (i = 0; i < len; i++) - slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); -} - - /** Unescape a URL encoded string, in place. **/ diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 4b303a894d..a05df0983b 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -342,3 +342,10 @@ const smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) return NULL; } +size_t ucs2_align(const void *base_ptr, const void *p, int flags) +{ + if (flags & (STR_NOALIGN|STR_ASCII)) + return 0; + return PTR_DIFF(p, base_ptr) & 1; +} + -- cgit From e4cd51e17ef5db8e78ed2d8481b7e4321c975fe5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 23 Sep 2004 02:14:43 +0000 Subject: r2553: fixed ldbtest so it passes the ldap schema restrictions and thus can be used on the ldap backend (This used to be commit 9f230425a0c926209887006ab1e3fec0998e7961) --- source4/lib/ldb/tools/ldbtest.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 96d228c177..7c240a01d2 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -287,35 +287,28 @@ be indexed */ static void start_test_index(struct ldb_context **ldb) { + const char *base = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; struct ldb_message msg; - struct ldb_message_element el[1]; - struct ldb_val val[1]; struct ldb_message **res; int ret; printf("Starting index test\n"); + memset(&msg, 0, sizeof(msg)); msg.dn = strdup("@INDEXLIST"); - msg.num_elements = 1; - msg.elements = el; - - el[0].flags = 0; - el[0].name = strdup("@IDXATTR"); - el[0].num_values = 1; - el[0].values = val; - - val[0].data = strdup("test"); - val[0].length = strlen(val[0].data); + ldb_msg_add_string(*ldb, &msg, "@IDXATTR", strdup("uid")); if (ldb_add(*ldb, &msg) != 0) { printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); exit(1); } - msg.dn = strdup("test1"); - el[0].name = strdup("test"); - val[0].data = strdup("foo"); - val[0].length = strlen(val[0].data); + memset(&msg, 0, sizeof(msg)); + asprintf(&msg.dn, "cn=%s,%s", "test", base); + ldb_msg_add_string(*ldb, &msg, "cn", strdup("test")); + ldb_msg_add_string(*ldb, &msg, "sn", strdup("test")); + ldb_msg_add_string(*ldb, &msg, "uid", strdup("test")); + ldb_msg_add_string(*ldb, &msg, "objectClass", strdup("OpenLDAPperson")); if (ldb_add(*ldb, &msg) != 0) { printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); @@ -334,13 +327,13 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - ret = ldb_search(*ldb, NULL, LDB_SCOPE_SUBTREE, "test=foo", NULL, &res); + ret = ldb_search(*ldb, NULL, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); if (ret != 1) { printf("Should have found 1 record - found %d\n", ret); exit(1); } - if (ldb_delete(*ldb, "test1") != 0 || + if (ldb_delete(*ldb, msg.dn) != 0 || ldb_delete(*ldb, "@INDEXLIST") != 0) { printf("cleanup failed - %s\n", ldb_errstring(*ldb)); exit(1); -- cgit From 9fbd16921a0ebcb633a8c1188d04439352db2d3c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 23 Sep 2004 02:15:10 +0000 Subject: r2554: added a test for a bug that jelmer pointed out (handling of -s one) (This used to be commit 74d7bc1948961a24837d966416db12be192382ff) --- source4/lib/ldb/tests/test-generic.sh | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 6db57967df..4cfae7affb 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -15,3 +15,10 @@ $VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 echo "Starting ldbtest indexed" time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 + +echo "Testing one level search" +count=`$VALGRIND bin/ldbsearch -b 'ou=Groups,o=University of Michigan,c=US' -s one 'objectclass=*' none |grep ^dn | wc -l` +if [ "$count" != 3 ]; then + echo returned $count records - expected 3 + exit 1 +fi -- cgit From 54d33d5674720aaa93dff20b66e7ab27d9027677 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 23 Sep 2004 02:21:51 +0000 Subject: r2556: fixed the -s one bug that jelmer pointed out (This used to be commit 03c38477add0c5f78072700615b2c1513cbc7663) --- source4/lib/ldb/ldb_tdb/ldb_match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index cae5886547..6f55496042 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -218,7 +218,7 @@ static int scope_match(const char *dn, const char *base, enum ldb_scope scope) base_len = strlen(base); dn_len = strlen(dn); - if (ldb_dn_cmp(dn, base) == 0) { + if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) { return 1; } -- cgit From 5c94fcab923b85c2dd75664deb8fa2819ca5ea23 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Sep 2004 01:21:21 +0000 Subject: r2577: - I recently found out that charaters below 0x3F are guaranteed not to occur as secondary bytes in any multi-byte character set. This allows for a very simple optimisation in strchr_m() and strrchr_m(). It might be a good idea to pick this up for Samba3. - the horrible toktocliplist() is only used in clitar.c, so move it there, to prevent anyone else from being tempted to use it. (This used to be commit 663b7b75ddd838ce547425b07d7ce4d4606fb479) --- source4/lib/util_str.c | 57 +++++++++++--------------------------------------- 1 file changed, 12 insertions(+), 45 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index a71a9ee703..cbe5988238 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -76,51 +76,6 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) static uint16_t tmpbuf[sizeof(pstring)]; -/** - Convert list of tokens to array; dependent on above routine. - Uses last_ptr from above - bit of a hack. -**/ - -char **toktocliplist(const char *ptr, int *ctok, const char *sep) -{ - char *s = ptr; - int ictok=0; - char **ret, **iret; - - if (!sep) - sep = " \t\n\r"; - - while(*s && strchr_m(sep,*s)) - s++; - - /* nothing left? */ - if (!*s) - return(NULL); - - do { - ictok++; - while(*s && (!strchr_m(sep,*s))) - s++; - while(*s && strchr_m(sep,*s)) - *s++=0; - } while(*s); - - *ctok=ictok; - s = ptr; - - if (!(ret=iret=malloc(ictok*sizeof(char *)))) - return NULL; - - while(ictok--) { - *iret++=s; - while(*s++) - ; - while(!*s) - s++; - } - - return ret; -} /** Case insensitive string compararison. @@ -736,6 +691,12 @@ char *strchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; + /* characters below 0x3F are guaranteed to not appear in + non-initial position in multi-byte charsets */ + if ((c & 0xC0) == 0) { + return strchr(s, c); + } + push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) @@ -751,6 +712,12 @@ char *strrchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; + /* characters below 0x3F are guaranteed to not appear in + non-initial position in multi-byte charsets */ + if ((c & 0xC0) == 0) { + return strrchr(s, c); + } + push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); p = strrchr_w(ws, UCS2_CHAR(c)); if (!p) -- cgit From fe45888e228d1452b8301b3b074794bd443a7fa5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Sep 2004 03:34:55 +0000 Subject: r2581: added "hosts allow" and "hosts deny" checking in smbd. I needed this as my box keeps getting hit by viruses spreading on my companies internal network, which screws up my debug log badly (sigh). metze, I'm not sure if you think access.c should go in the socket library or not. It is closely tied to the socket functions, but you may prefer it separate. The access.c code is a port from Samba3, but with some cleanups to make it (slighly) less ugly. (This used to be commit 058b2fd99e3957d7d2a9544fd27071f1122eab68) --- source4/lib/socket/access.c | 353 +++++++++++++++++++++++++++++++++++++++ source4/lib/socket/config.mk | 2 + source4/lib/socket/socket.c | 9 + source4/lib/socket/socket.h | 1 + source4/lib/socket/socket_ipv4.c | 21 +++ 5 files changed, 386 insertions(+) create mode 100644 source4/lib/socket/access.c (limited to 'source4/lib') diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c new file mode 100644 index 0000000000..f33f8d56b1 --- /dev/null +++ b/source4/lib/socket/access.c @@ -0,0 +1,353 @@ +/* + Unix SMB/CIFS implementation. + + check access rules for socket connections + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* + This module is an adaption of code from the tcpd-1.4 package written + by Wietse Venema, Eindhoven University of Technology, The Netherlands. + + The code is used here with permission. + + The code has been considerably changed from the original. Bug reports + should be sent to samba@samba.org +*/ + +#include "includes.h" + +#define FAIL (-1) +#define ALLONES ((uint32_t)0xFFFFFFFF) + +/* masked_match - match address against netnumber/netmask */ +static BOOL masked_match(TALLOC_CTX *mem_ctx, const char *tok, const char *slash, const char *s) +{ + uint32_t net; + uint32_t mask; + uint32_t addr; + char *tok_cpy; + + if ((addr = interpret_addr(s)) == INADDR_NONE) + return False; + + tok_cpy = talloc_strdup(mem_ctx, tok); + tok_cpy[PTR_DIFF(slash,tok)] = '\0'; + net = interpret_addr(tok_cpy); + talloc_free(tok_cpy); + + if (strlen(slash + 1) > 2) { + mask = interpret_addr(slash + 1); + } else { + mask = (uint32_t)((ALLONES >> atoi(slash + 1)) ^ ALLONES); + /* convert to network byte order */ + mask = htonl(mask); + } + + if (net == INADDR_NONE || mask == INADDR_NONE) { + DEBUG(0,("access: bad net/mask access control: %s\n", tok)); + return False; + } + + return (addr & mask) == (net & mask); +} + +/* string_match - match string against token */ +static BOOL string_match(TALLOC_CTX *mem_ctx, const char *tok,const char *s, char *invalid_char) +{ + size_t tok_len; + size_t str_len; + const char *cut; + + *invalid_char = '\0'; + + /* Return True if a token has the magic value "ALL". Return + * FAIL if the token is "FAIL". If the token starts with a "." + * (domain name), return True if it matches the last fields of + * the string. If the token has the magic value "LOCAL", + * return True if the string does not contain a "." + * character. If the token ends on a "." (network number), + * return True if it matches the first fields of the + * string. If the token begins with a "@" (netgroup name), + * return True if the string is a (host) member of the + * netgroup. Return True if the token fully matches the + * string. If the token is a netnumber/netmask pair, return + * True if the address is a member of the specified subnet. + */ + + if (tok[0] == '.') { /* domain: match last fields */ + if ((str_len = strlen(s)) > (tok_len = strlen(tok)) + && strcasecmp(tok, s + str_len - tok_len)==0) { + return True; + } + } else if (tok[0] == '@') { /* netgroup: look it up */ + DEBUG(0,("access: netgroup support is not available\n")); + return False; + } else if (strcmp(tok, "ALL")==0) { /* all: match any */ + return True; + } else if (strcmp(tok, "FAIL")==0) { /* fail: match any */ + return FAIL; + } else if (strcmp(tok, "LOCAL")==0) { /* local: no dots */ + if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0) { + return True; + } + } else if (strcasecmp(tok, s)==0) { /* match host name or address */ + return True; + } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ + if (strncmp(tok, s, tok_len) == 0) + return True; + } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */ + if (isdigit((int)s[0]) && masked_match(mem_ctx, tok, cut, s)) + return True; + } else if (strchr(tok, '*') != 0) { + *invalid_char = '*'; + } else if (strchr(tok, '?') != 0) { + *invalid_char = '?'; + } + return False; +} + +struct client_addr { + const char *cname; + const char *caddr; +}; + +/* client_match - match host name and address against token */ +static BOOL client_match(TALLOC_CTX *mem_ctx, const char *tok, struct client_addr *client) +{ + BOOL match; + char invalid_char = '\0'; + + /* + * Try to match the address first. If that fails, try to match the host + * name if available. + */ + + if ((match = string_match(mem_ctx, tok, client->caddr, &invalid_char)) == 0) { + if(invalid_char) + DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \ +token '%s' in an allow/deny hosts line.\n", invalid_char, tok )); + + if (client->cname[0] != 0) + match = string_match(mem_ctx, tok, client->cname, &invalid_char); + + if(invalid_char) + DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \ +token '%s' in an allow/deny hosts line.\n", invalid_char, tok )); + } + + return (match); +} + +/* list_match - match an item against a list of tokens with exceptions */ +static BOOL list_match(TALLOC_CTX *mem_ctx, const char **list, struct client_addr *client) +{ + BOOL match = False; + + if (!list) + return False; + + /* + * Process tokens one at a time. We have exhausted all possible matches + * when we reach an "EXCEPT" token or the end of the list. If we do find + * a match, look for an "EXCEPT" list and recurse to determine whether + * the match is affected by any exceptions. + */ + + for (; *list ; list++) { + if (strcmp(*list, "EXCEPT")==0) /* EXCEPT: give up */ + break; + if ((match = client_match(mem_ctx, *list, client))) /* True or FAIL */ + break; + } + + /* Process exceptions to True or FAIL matches. */ + if (match != False) { + while (*list && strcmp(*list, "EXCEPT")!=0) + list++; + + for (; *list; list++) { + if (client_match(mem_ctx, *list, client)) /* Exception Found */ + return False; + } + } + + return match; +} + +/* return true if access should be allowed */ +static BOOL allow_access_internal(TALLOC_CTX *mem_ctx, + const char **deny_list,const char **allow_list, + const char *cname, const char *caddr) +{ + struct client_addr client; + + client.cname = cname; + client.caddr = caddr; + + /* if it is loopback then always allow unless specifically denied */ + if (strcmp(caddr, "127.0.0.1") == 0) { + /* + * If 127.0.0.1 matches both allow and deny then allow. + * Patch from Steve Langasek vorlon@netexpress.net. + */ + if (deny_list && + list_match(mem_ctx, deny_list, &client) && + (!allow_list || + !list_match(mem_ctx, allow_list, &client))) { + return False; + } + return True; + } + + /* if theres no deny list and no allow list then allow access */ + if ((!deny_list || *deny_list == 0) && + (!allow_list || *allow_list == 0)) { + return True; + } + + /* if there is an allow list but no deny list then allow only hosts + on the allow list */ + if (!deny_list || *deny_list == 0) + return list_match(mem_ctx, allow_list, &client); + + /* if theres a deny list but no allow list then allow + all hosts not on the deny list */ + if (!allow_list || *allow_list == 0) + return !list_match(mem_ctx, deny_list, &client); + + /* if there are both types of list then allow all hosts on the + allow list */ + if (list_match(mem_ctx, allow_list, &client)) + return True; + + /* if there are both types of list and it's not on the allow then + allow it if its not on the deny */ + if (list_match(mem_ctx, deny_list, &client)) + return False; + + return True; +} + +/* return true if access should be allowed */ +static BOOL allow_access(TALLOC_CTX *mem_ctx, + const char **deny_list, const char **allow_list, + const char *cname, const char *caddr) +{ + BOOL ret; + char *nc_cname = talloc_strdup(mem_ctx, cname); + char *nc_caddr = talloc_strdup(mem_ctx, caddr); + + if (!nc_cname || !nc_caddr) { + return False; + } + + ret = allow_access_internal(mem_ctx, deny_list, allow_list, nc_cname, nc_caddr); + + talloc_free(nc_cname); + talloc_free(nc_caddr); + + return ret; +} + +/* return true if the char* contains ip addrs only. Used to avoid +gethostbyaddr() calls */ + +static BOOL only_ipaddrs_in_list(const char** list) +{ + BOOL only_ip = True; + + if (!list) + return True; + + for (; *list ; list++) { + /* factor out the special strings */ + if (strcmp(*list, "ALL")==0 || + strcmp(*list, "FAIL")==0 || + strcmp(*list, "EXCEPT")==0) { + continue; + } + + if (!is_ipaddress(*list)) { + /* + * if we failed, make sure that it was not because the token + * was a network/netmask pair. Only network/netmask pairs + * have a '/' in them + */ + if ((strchr(*list, '/')) == NULL) { + only_ip = False; + DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list)); + break; + } + } + } + + return only_ip; +} + +/* return true if access should be allowed to a service for a socket */ +BOOL socket_check_access(struct socket_context *sock, + const char *service_name, + const char **allow_list, const char **deny_list) +{ + BOOL ret; + const char *name="", *addr; + TALLOC_CTX *mem_ctx; + + if ((!deny_list || *deny_list==0) && + (!allow_list || *allow_list==0)) { + return True; + } + + mem_ctx = talloc_init("socket_check_access"); + if (!mem_ctx) { + return False; + } + + addr = socket_get_peer_addr(sock, mem_ctx); + + /* bypass gethostbyaddr() calls if the lists only contain IP addrs */ + if (!only_ipaddrs_in_list(allow_list) || + !only_ipaddrs_in_list(deny_list)) { + name = socket_get_peer_name(sock, mem_ctx); + if (!name) { + name = addr; + } + } + + if (!addr) { + DEBUG(0,("socket_check_access: Denied connection from unknown host\n")); + talloc_free(mem_ctx); + return False; + } + + ret = allow_access(mem_ctx, deny_list, allow_list, name, addr); + + if (ret) { + DEBUG(2,("socket_check_access: Allowed connection to '%s' from %s (%s)\n", + service_name, name, addr)); + } else { + DEBUG(0,("socket_check_access: Denied connection to '%s' from %s (%s)\n", + service_name, name, addr)); + } + + talloc_free(mem_ctx); + + return ret; +} diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 854702a6f8..320fc7f3ee 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -12,5 +12,7 @@ INIT_OBJ_FILES = \ [SUBSYSTEM::SOCKET] INIT_OBJ_FILES = \ lib/socket/socket.o +ADD_OBJ_FILES = \ + lib/socket/access.o # End SUBSYSTEM SOCKET ################################################ diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 6869114587..4814cc6a5a 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -160,6 +160,15 @@ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, cons return sock->ops->set_option(sock, option, val); } +char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + if (!sock->ops->get_peer_name) { + return NULL; + } + + return sock->ops->get_peer_name(sock, mem_ctx); +} + char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { if (!sock->ops->get_peer_addr) { diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index ea4de1d291..a089a1b78a 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -55,6 +55,7 @@ struct socket_ops { NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val); + char *(*get_peer_name)(struct socket_context *sock, TALLOC_CTX *mem_ctx); char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); int (*get_peer_port)(struct socket_context *sock); char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 9a1e7e43f6..151c49518f 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -293,6 +293,26 @@ static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *opt return NT_STATUS_OK; } +static char *ipv4_tcp_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + struct sockaddr_in peer_addr; + socklen_t len = sizeof(peer_addr); + struct hostent *he; + int ret; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return NULL; + } + + he = gethostbyaddr((char *)&peer_addr.sin_addr, sizeof(peer_addr.sin_addr), AF_INET); + if (he == NULL) { + return NULL; + } + + return talloc_strdup(mem_ctx, he->h_name); +} + static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct sockaddr_in peer_addr; @@ -368,6 +388,7 @@ static const struct socket_ops ipv4_tcp_ops = { .set_option = ipv4_tcp_set_option, + .get_peer_name = ipv4_tcp_get_peer_name, .get_peer_addr = ipv4_tcp_get_peer_addr, .get_peer_port = ipv4_tcp_get_peer_port, .get_my_addr = ipv4_tcp_get_my_addr, -- cgit From 567ed4e71824e374293e8a05effc1a898af494d8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 24 Sep 2004 17:42:46 +0000 Subject: r2601: avoid free()ing unallocated memory by mistake (This used to be commit e502b276ae5e4e22e31a522c4d9e346996d6e29f) --- source4/lib/xfile.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/xfile.c b/source4/lib/xfile.c index de4cf4b12a..e01723904f 100644 --- a/source4/lib/xfile.c +++ b/source4/lib/xfile.c @@ -135,7 +135,12 @@ int x_fclose(XFILE *f) memset(f->buf, 0, f->bufsize); SAFE_FREE(f->buf); } - SAFE_FREE(f); + /* check the file descriptor given to the function is NOT one of the static + * descriptor of this libreary or we will free unallocated memory + * --sss */ + if (f != x_stdin && f != x_stdout && f != x_stderr) { + SAFE_FREE(f); + } return ret; } -- cgit From 30381686c4874e4f9602a977a31399e49350e597 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 11:15:18 +0000 Subject: r2621: - now that the client code is non-blocking, we no longer need write_data and read_data, which are inherently blocking operations - got rid of some old NBT keepalive routines that are not needed (This used to be commit e73b4ae4e500d3b7ee57e160e0f8b63c99b2542a) --- source4/lib/util_sock.c | 73 ------------------------------------------------- 1 file changed, 73 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index f24d010f22..387c72599a 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -179,65 +179,6 @@ ssize_t read_udp_socket(int fd, char *buf, size_t len, } -/**************************************************************************** - read data from the client, reading exactly N bytes. -****************************************************************************/ -ssize_t read_data(int fd, char *buffer, size_t N) -{ - ssize_t ret; - size_t total=0; - - if (fd == -1) { - errno = EIO; - return -1; - } - - while (total < N) { - ret = sys_read(fd,buffer + total,N - total); - if (ret == 0) { - return total; - } - if (ret == -1) { - if (total == 0) { - return -1; - } - return total; - } - total += ret; - } - return (ssize_t)total; -} - - -/**************************************************************************** - Write data to a fd. -****************************************************************************/ -ssize_t write_data(int fd, const char *buffer, size_t N) -{ - size_t total=0; - ssize_t ret; - - if (fd == -1) { - errno = EIO; - return -1; - } - - while (total < N) { - ret = sys_write(fd, buffer + total, N - total); - if (ret == -1) { - if (total == 0) { - return -1; - } - return total; - } - if (ret == 0) { - return total; - } - - total += ret; - } - return (ssize_t)total; -} /**************************************************************************** Check the timeout. @@ -348,20 +289,6 @@ ssize_t write_data_until(int fd,char *buffer,size_t N, } -/**************************************************************************** -send a keepalive packet (rfc1002) -****************************************************************************/ -BOOL send_nbt_keepalive(int sock_fd) -{ - uint8_t buf[4]; - - buf[0] = SMBkeepalive; - buf[1] = buf[2] = buf[3] = 0; - - return write_data(sock_fd,(char *)buf,4) == 4; -} - - /**************************************************************************** Open a socket of the specified type, port, and address for incoming data. ****************************************************************************/ -- cgit From 5abd7f8f5f04b2c2a66e97974049fc65b11df9e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 11:16:30 +0000 Subject: r2622: to implement the SOCKET_FLAG_BLOCK option in the socket library we need to add MSG_WAITALL to the recv() flags. This is needed by the current server code or sometimes it will fail with a receive error. (This used to be commit 4cb11fb77acf74ab53bf5782a114151965c558f0) --- source4/lib/socket/socket_ipv4.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 151c49518f..67f1e99d17 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -204,6 +204,10 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, flgs |= MSG_DONTWAIT; } + if (flags & SOCKET_FLAG_BLOCK) { + flgs |= MSG_WAITALL; + } + gotlen = recv(sock->fd, buf, wantlen, flgs); if (gotlen == 0) { talloc_free(buf); -- cgit From 368802bc867f544355b5a8c4bc5e4b6ab47dd408 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 11:17:09 +0000 Subject: r2623: don't do pointer arithmetic on void*, as it doesn't work with non-GNU compilers (This used to be commit c2be7b696ccb338df06a5212ed1f7b78e4c116c2) --- source4/lib/registry/common/reg_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 21c925deab..c7354fe909 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -54,7 +54,7 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) asciip = ret; for (i=0; idata_len; i++) { int str_rem = v->data_len * 3 - (asciip - ret); - asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(v->data_blk+i)); + asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(((char *)v->data_blk)+i)); if (i < v->data_len && str_rem > 0) *asciip = ' '; asciip++; } -- cgit From 223e78990a16f134a01d1223a0dad8b2accd5fed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 11:48:30 +0000 Subject: r2628: got rid of some warnings and converted a few more places to use hierarchical memory allocation (This used to be commit 26da45a8019a2d6c9ff2ac2a6739c7d0b42b00de) --- source4/lib/socket/socket_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 67f1e99d17..c98e5534ca 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -153,7 +153,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte socklen_t cli_addr_len = 0; int new_fd; - new_fd = accept(sock->fd, &cli_addr, &cli_addr_len); + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { /* TODO: we need to map from errno to NTSTATUS here! */ return NT_STATUS_FOOBAR; -- cgit From 48c97988ca6703264721c6be435e6f616cdbdcb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 12:31:49 +0000 Subject: r2631: the strchr family of functions should not return const strings. (This used to be commit 2a7e5f07086ef4aebbb2be35acbf9c7c39b13c75) --- source4/lib/util_unistr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index a05df0983b..1d7d0de19a 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -221,7 +221,7 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max) /******************************************************************* wide strchr() ********************************************************************/ -const smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { while (*s != 0) { if (c == *s) return s; @@ -232,12 +232,12 @@ const smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) return NULL; } -const smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) +smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) { return strchr_w(s, UCS2_CHAR(c)); } -const smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { const smb_ucs2_t *p = s; int len = strlen_w(s); -- cgit From 797d80879c89cedce5992ec4a67b61d2711421a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 12:36:36 +0000 Subject: r2632: a new approach to handling const errors. We have had huge numbers of const warnings for a long time, and no real way to approach a solution. Some of them are unavoidable due to the way the C standard works (for example, any function that provides strchr() like functionality _must_ produce a const warning) I will be converting a bunch of places that currently produce const warnings to use the discard_const_p(). Some of these will be unavoidable const problems, some of them will be ones we will fix up over time. At least this change means we will no longer be swamped with const warnings, and we will easily be able to see when new problems emerge. (This used to be commit fec3288ad6ce58e8273e3f16e88037db49ecf046) --- source4/lib/util.c | 20 ++++++++++++++++++++ source4/lib/util_str.c | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index c09e1a2997..910a35217c 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -931,3 +931,23 @@ BOOL all_zero(const char *ptr, uint_t size) return True; } + +/* + this is a warning hack. The idea is to use this everywhere that we + get the "discarding const" warning from gcc, effectively moving all + the warnings to this one place. That doesn't actually fix the + problem of course, but it means that when we do get to cleaning them + up we can do it by searching the code for discard_const. + + It also means that other error types aren't as swamped by the noise + of hundreds of const warnings, so we are more likely to notice when + we get new errors. + + Please only add more calls to this function when you find it + _really_ hard to fix const warnings. Our aim is to eventually not + need this function at all, +*/ +void *discard_const(const void *ptr) +{ + return (void *)ptr; +} diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index cbe5988238..f8aadf8f59 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -703,7 +703,7 @@ char *strchr_m(const char *s, char c) return NULL; *p = 0; pull_ucs2_pstring(s2, ws); - return (char *)(s+strlen(s2)); + return discard_const_p(char, s+strlen(s2)); } char *strrchr_m(const char *s, char c) @@ -724,7 +724,7 @@ char *strrchr_m(const char *s, char c) return NULL; *p = 0; pull_ucs2_pstring(s2, ws); - return (char *)(s+strlen(s2)); + return discard_const_p(char, s+strlen(s2)); } /** -- cgit From 6310f40448f9f9e856874cbefcc25b753963a41e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 12:48:56 +0000 Subject: r2634: use discard_const_p() in a few places (This used to be commit 56ecda2178e33508c55c6195ccec41c06e099d6f) --- source4/lib/tdb/common/tdbutil.c | 2 +- source4/lib/util.c | 7 +++++-- source4/lib/util_unistr.c | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 596a79f52e..0e0a6eca28 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -82,7 +82,7 @@ static void (*TdbCatchSignal(int signum,void (*handler)(int )))(int) static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) { TDB_DATA ret; - ret.dptr = dptr; + ret.dptr = discard_const_p(char, dptr); ret.dsize = dsize; return ret; } diff --git a/source4/lib/util.c b/source4/lib/util.c index 910a35217c..2862a40bd7 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -944,8 +944,11 @@ BOOL all_zero(const char *ptr, uint_t size) we get new errors. Please only add more calls to this function when you find it - _really_ hard to fix const warnings. Our aim is to eventually not - need this function at all, + _really_ hard to fix const warnings. Our aim is to eventually use + this function in only a very few places. + + Also, please call this via the discard_const_p() macro interface, as that + makes the return type safe. */ void *discard_const(const void *ptr) { diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 1d7d0de19a..2d4b2e8fa8 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -224,10 +224,10 @@ wide strchr() smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { while (*s != 0) { - if (c == *s) return s; + if (c == *s) return discard_const_p(smb_ucs2_t, s); s++; } - if (c == *s) return s; + if (c == *s) return discard_const_p(smb_ucs2_t, s); return NULL; } @@ -244,7 +244,7 @@ smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) if (len == 0) return NULL; p += (len - 1); do { - if (c == *p) return p; + if (c == *p) return discard_const_p(smb_ucs2_t, p); } while (p-- != s); return NULL; } -- cgit From 4a1d53a07a5bb1b5a5c73eceb173225924a71ef5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 01:08:29 +0000 Subject: r2638: do lazy initialisation of iconv handles, so we don't initialise a handle unless we use it. This saves quite a bit of memory (libc chews a lot loading a handle). Typically smbd now loads 3 handles, instead of 36. (This used to be commit 60e8d154fda548862cd6f8e8c1dadd64b3c4bd9c) --- source4/lib/charcnv.c | 68 ++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index fd550895d0..3a3d470f99 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -37,9 +37,6 @@ * @sa lib/iconv.c */ -static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - - /** * Return the name of a charset to give to iconv(). **/ @@ -66,55 +63,48 @@ static void lazy_initialize_conv(void) initialized = True; load_case_tables(); init_iconv(); - init_valid_table(); } } -/** - Initialize iconv conversion descriptors. -**/ -void init_iconv(void) +static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; + +/* + on-demand initialisation of conversion handles +*/ +static smb_iconv_t get_conv_handle(charset_t from, charset_t to) { - int c1, c2; - BOOL did_reload = False; + const char *n1, *n2; - /* so that charset_name() works we need to get the UNIX<->UCS2 going - first */ - if (!conv_handles[CH_UNIX][CH_UTF16]) - conv_handles[CH_UNIX][CH_UTF16] = smb_iconv_open(charset_name(CH_UTF16), - "ASCII"); + if (conv_handles[from][to]) { + return conv_handles[from][to]; + } - if (!conv_handles[CH_UTF16][CH_UNIX]) - conv_handles[CH_UTF16][CH_UNIX] = smb_iconv_open("ASCII", - charset_name(CH_UTF16)); + n1 = charset_name(from); + n2 = charset_name(to); + conv_handles[from][to] = smb_iconv_open(n2,n1); + + return conv_handles[from][to]; +} + +/** + re-initialize iconv conversion descriptors +**/ +void init_iconv(void) +{ + charset_t c1, c2; for (c1=0;c1from_name) == 0 && - strcmp(n2, conv_handles[c1][c2]->to_name) == 0) - continue; - - did_reload = True; - - if (conv_handles[c1][c2]) - smb_iconv_close(conv_handles[c1][c2]); - - conv_handles[c1][c2] = smb_iconv_open(n2,n1); - if (conv_handles[c1][c2] == (smb_iconv_t)-1) { - DEBUG(0,("Conversion from %s to %s not supported\n", - charset_name((charset_t)c1), charset_name((charset_t)c2))); + if (conv_handles[c1][c2] != NULL) { + if (conv_handles[c1][c2] != -1) { + smb_iconv_close(conv_handles[c1][c2]); + } conv_handles[c1][c2] = NULL; } } } - if (did_reload) { - init_valid_table(); - } } /** @@ -141,7 +131,7 @@ ssize_t convert_string(charset_t from, charset_t to, lazy_initialize_conv(); - descriptor = conv_handles[from][to]; + descriptor = get_conv_handle(from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, use as is */ @@ -206,7 +196,7 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, lazy_initialize_conv(); - descriptor = conv_handles[from][to]; + descriptor = get_conv_handle(from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, return -1*/ -- cgit From 17cb5517f8c9d17ad00ce9008e82dcbda45308f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 01:09:04 +0000 Subject: r2639: we doon't need the valid_table code, so get rid of it (This used to be commit 480636ebbca102172621609496bdab682d4bda8a) --- source4/lib/util_unistr.c | 56 ----------------------------------------------- 1 file changed, 56 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 2d4b2e8fa8..59386ec31d 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -25,7 +25,6 @@ at startup either via mmap() or read() from the lib directory */ static smb_ucs2_t *upcase_table; static smb_ucs2_t *lowcase_table; -static uint8_t *valid_table; /******************************************************************* @@ -103,61 +102,6 @@ static int check_dos_char(smb_ucs2_t c) return (c == c2); } -/** - * Load the valid character map table from valid.dat or - * create from the configured codepage. - * - * This function is called whenever the configuration is reloaded. - * However, the valid character table is not changed if it's loaded - * from a file, because we can't unmap files. - **/ -void init_valid_table(void) -{ - static int mapped_file; - int i; - const char *allowed = ".!#$%&'()_-@^`~"; - uint8_t *valid_file; - TALLOC_CTX *mem_ctx; - - if (mapped_file) { - /* Can't unmap files, so stick with what we have */ - return; - } - - mem_ctx = talloc_init("init_valid_table"); - if (!mem_ctx) { - smb_panic("No memory for valid_table"); - } - valid_file = map_file(lib_path(mem_ctx, "valid.dat"), 0x10000); - talloc_destroy(mem_ctx); - if (valid_file) { - valid_table = valid_file; - mapped_file = 1; - return; - } - - /* Otherwise, we're using a dynamically created valid_table. - * It might need to be regenerated if the code page changed. - * We know that we're not using a mapped file, so we can - * free() the old one. */ - if (valid_table) free(valid_table); - - DEBUG(2,("creating default valid table\n")); - valid_table = malloc(0x10000); - if (!valid_table) { - smb_panic("No memory for valid_table"); - } - for (i=0;i<128;i++) - valid_table[i] = isalnum(i) || strchr(allowed,i); - - for (;i<0x10000;i++) { - smb_ucs2_t c; - SSVAL(&c, 0, i); - valid_table[i] = check_dos_char(c); - } -} - - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ -- cgit From b295256ea2f71a4fe3b16e0348b907f6ef73167b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 01:14:26 +0000 Subject: r2640: valgrind does a great job on some types of memory leaks, but is slow and can't properly handle leaks of doubly linked lists which we use a lot (as the memory is always reachable). Even with --show-reachable its hard to track leaks down sometimes. I realised that talloc does have the necessary information to track these, and by using the cascading property of the new talloc it can report on leaks in a much more succinct fashion than valgrind can. I have added a new samba option --leak-check that applies to all Samba tools. When enabled it prints a leak report summarising all top level contexts that are present when the program exits. A typical report looks like this: talloc report on 'null_context' (total 1071 bytes in 52 blocks) iconv(CP850,UTF8) contains 43 bytes in 3 blocks UNNAMED contains 24 bytes in 1 blocks UNNAMED contains 24 bytes in 1 blocks dcesrv_init contains 604 bytes in 26 blocks server_service contains 120 bytes in 6 blocks UNNAMED contains 24 bytes in 1 blocks UNNAMED contains 24 bytes in 1 blocks server_service contains 104 bytes in 4 blocks server_context contains 12 bytes in 2 blocks iconv(UTF8,UTF-16LE) contains 46 bytes in 3 blocks iconv(UTF-16LE,UTF8) contains 46 bytes in 3 blocks the numbers are recursive summaries for all the memory hanging off each context. this option is not thread safe when used, but the code is thread safe if the option is not given, so I don't think thats a problem. (This used to be commit 96d33d36a5639e7fc46b14a470ccac674d87c62a) --- source4/lib/cmdline/popt_common.c | 13 ++++--- source4/lib/talloc.c | 72 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index e2deb5db96..f98c460642 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -34,7 +34,7 @@ */ -enum {OPT_OPTION=1}; +enum {OPT_OPTION=1,OPT_LEAK_CHECK=2}; static struct cmdline_auth_info cmdline_auth_info; @@ -116,6 +116,10 @@ static void popt_common_callback(poptContext con, exit(1); } break; + + case OPT_LEAK_CHECK: + talloc_enable_leak_check(); + break; } } @@ -132,10 +136,11 @@ struct poptOption popt_common_connection[] = { struct poptOption popt_common_samba[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, - { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, - { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, - { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, + { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, + { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, + { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, + { "leak-check", 0, POPT_ARG_NONE, NULL, OPT_LEAK_CHECK, "enable talloc leak checking", NULL }, POPT_TABLEEND }; diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index c236834d91..114d0de43b 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -30,6 +30,8 @@ #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 +static void *null_context; + struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; @@ -61,6 +63,10 @@ void *talloc(void *context, size_t size) { struct talloc_chunk *tc; + if (context == NULL) { + context = null_context; + } + if (size >= MAX_TALLOC_SIZE) { return NULL; } @@ -164,6 +170,18 @@ void *talloc_named(void *context, size_t size, return ptr; } +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +const char *talloc_get_name(void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (tc->name) { + return tc->name; + } + return "UNNAMED"; +} + /* this is for compatibility with older versions of talloc */ @@ -327,7 +345,7 @@ void *talloc_steal(void *new_ctx, void *ptr) /* return the total size of a talloc pool (subtree) */ -off_t talloc_total_size(void *ptr) +static off_t talloc_total_size(void *ptr) { off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); @@ -339,6 +357,58 @@ off_t talloc_total_size(void *ptr) return total; } +/* + return the total number of blocks in a talloc pool (subtree) +*/ +static off_t talloc_total_blocks(void *ptr) +{ + off_t total = 0; + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(c+1); + } + return total; +} + +/* + report on memory usage by all children of a pointer +*/ +void talloc_report(void *ptr, FILE *f) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + for (c=tc->child;c;c=c->next) { + fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", + talloc_get_name(c+1), + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1)); + } + +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_all(void) +{ + talloc_report(null_context, stderr); +} + +/* + enable leak reporting on exit +*/ +void talloc_enable_leak_check(void) +{ + null_context = talloc_named(NULL, 0, "null_context"); + atexit(talloc_report_all); +} /* talloc and zero memory. -- cgit From 38aa97445769c6f1c54d59731b5a0edef91e41b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 01:41:04 +0000 Subject: r2641: talloc_p() now produces a named talloc pointer, with the name auto-derived from the type you are allocating. This is done with basically zero overhead by relying on the stringify operator in cpp producing string constants. the result is that --leak-check nicely names all pointers that come from talloc_p() (This used to be commit bd86ebe2972af4d424df20db1e422919aa6203d0) --- source4/lib/talloc.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 114d0de43b..3e42fc68f8 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -39,7 +39,7 @@ struct talloc_chunk { uint_t magic; uint_t ref_count; int (*destructor)(void *); - char *name; + const char *name; }; /* panic if we get a bad magic value */ @@ -133,7 +133,7 @@ static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) PRINTF_ATT static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - vasprintf(&tc->name, fmt, ap); + tc->name = talloc_vasprintf(ptr, fmt, ap); } /* @@ -147,6 +147,16 @@ void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) va_end(ap); } +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +void talloc_set_name_const(void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + /* create a named talloc pointer. Any talloc pointer can be named, and talloc_named() operates just like talloc() except that it allows you @@ -170,6 +180,25 @@ void *talloc_named(void *context, size_t size, return ptr; } +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = talloc(context, size); + if (ptr == NULL) { + return NULL; + } + + talloc_set_name_const(ptr, name); + + return ptr; +} + /* return the name of a talloc ptr, or "UNNAMED" */ @@ -250,7 +279,6 @@ int talloc_free(void *ptr) } tc->magic = TALLOC_MAGIC_FREE; - if (tc->name) free(tc->name); free(tc); return 0; -- cgit From 9cafc0d07ed339b511abf0f6fd41c289d2815974 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 01:41:55 +0000 Subject: r2642: smb_iconv_t is a pointer, so checks against -1 errors should use a cast (This used to be commit 28dcd2202948b003f8d13951395baa4a722593f4) --- source4/lib/charcnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 3a3d470f99..2ee2bd9bae 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -97,7 +97,7 @@ void init_iconv(void) for (c1=0;c1 Date: Sun, 26 Sep 2004 02:14:25 +0000 Subject: r2644: removed an unused function (This used to be commit bc779cb2ce6bc13157f9d046400ce99d107ccd52) --- source4/lib/util_unistr.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 59386ec31d..713f50708b 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -86,26 +86,9 @@ void load_case_tables(void) } } -/* - see if a ucs2 character can be mapped correctly to a dos character - and mapped back to the same character in ucs2 -*/ -static int check_dos_char(smb_ucs2_t c) -{ - char buf[10]; - smb_ucs2_t c2 = 0; - int len1, len2; - len1 = convert_string(CH_UTF16, CH_DOS, &c, 2, buf, sizeof(buf)); - if (len1 == 0) return 0; - len2 = convert_string(CH_DOS, CH_UTF16, buf, len1, &c2, 2); - if (len2 != 2) return 0; - return (c == c2); -} - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ - smb_ucs2_t toupper_w(smb_ucs2_t val) { return upcase_table[SVAL(&val,0)]; @@ -114,7 +97,6 @@ smb_ucs2_t toupper_w(smb_ucs2_t val) /******************************************************************* Convert a wchar to lower case. ********************************************************************/ - static smb_ucs2_t tolower_w( smb_ucs2_t val ) { return lowcase_table[SVAL(&val,0)]; -- cgit From 764eddb69647681f784f343a122251ca1ecf62df Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 03:05:04 +0000 Subject: r2646: - use a talloc destructor to ensure that sockets from the new socket library are closed on abnormal termination - convert the service.h structures to the new talloc methods (This used to be commit 2dc334a3284858eb1c7190f9687c9b6c879ecc9d) --- source4/lib/socket/socket.c | 32 ++++++++++++++++++++++++++------ source4/lib/time.c | 2 +- 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 4814cc6a5a..4fde41a3c0 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -20,6 +20,18 @@ #include "includes.h" +/* + auto-close sockets on free +*/ +static int socket_destructor(void *ptr) +{ + struct socket_context *sock = ptr; + if (sock->ops->close) { + sock->ops->close(sock); + } + return 0; +} + NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags) { NTSTATUS status; @@ -38,24 +50,24 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co (*new_sock)->private_data = NULL; (*new_sock)->ops = socket_getops_byname(name, type); if (!(*new_sock)->ops) { - talloc_free((*new_sock)); + talloc_free(*new_sock); return NT_STATUS_INVALID_PARAMETER; } status = (*new_sock)->ops->init((*new_sock)); if (!NT_STATUS_IS_OK(status)) { - talloc_free((*new_sock)); + talloc_free(*new_sock); return status; } + talloc_set_destructor(*new_sock, socket_destructor); + return NT_STATUS_OK; } void socket_destroy(struct socket_context *sock) { - if (sock->ops->close) { - sock->ops->close(sock); - } + /* the close is handled by the destructor */ talloc_free(sock); } @@ -98,6 +110,8 @@ NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) { + NTSTATUS status; + if (sock->type != SOCKET_TYPE_STREAM) { return NT_STATUS_INVALID_PARAMETER; } @@ -110,7 +124,13 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->accept(sock, new_sock, flags); + status = sock->ops->accept(sock, new_sock, flags); + + if (NT_STATUS_IS_OK(status)) { + talloc_set_destructor(*new_sock, socket_destructor); + } + + return status; } NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, diff --git a/source4/lib/time.c b/source4/lib/time.c index bd8d7ddb30..fec4dd62a2 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -137,7 +137,7 @@ void unix_to_nt_time(NTTIME *nt, time_t t) /**************************************************************************** check if it's a null mtime ****************************************************************************/ -BOOL null_mtime(time_t mtime) +static BOOL null_mtime(time_t mtime) { return mtime == 0 || mtime == (time_t)0xFFFFFFFF || -- cgit From ec0128ef012f4280b2fb607cb9c88c7673894fe6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 04:59:03 +0000 Subject: r2649: - used some cpp tricks to make users of talloc() and talloc_realloc() to get auto-naming of pointers very cheaply. - fixed a couple of memory leaks found with the new tricks A typical exit report for smbd is now: talloc report on 'null_context' (total 811 bytes in 54 blocks) auth/auth_sam.c:334 contains 20 bytes in 1 blocks struct auth_serversupplied_info contains 498 bytes in 33 blocks UNNAMED contains 8 bytes in 1 blocks lib/data_blob.c:40 contains 16 bytes in 1 blocks iconv(CP850,UTF8) contains 61 bytes in 4 blocks iconv(UTF8,CP850) contains 61 bytes in 4 blocks iconv(UTF8,UTF-16LE) contains 67 bytes in 4 blocks iconv(UTF-16LE,UTF8) contains 67 bytes in 4 blocks UNNAMED contains 13 bytes in 1 blocks which is much better than before (This used to be commit 6e721393d03afd3c2f8ced8422533547a9e33342) --- source4/lib/data_blob.c | 5 +++++ source4/lib/talloc.c | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index e10ebfe606..c8c57849d2 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -56,6 +56,11 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) if (ret.data) { ret.data = talloc_steal(mem_ctx, ret.data); + } else { + /* this ensures the blob has the context attached, so a zero length call + to data_blob_talloc followed by a realloc doesn't cause the memory to come + from the NULL context */ + ret.data = talloc(mem_ctx, 0); } return ret; } diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 3e42fc68f8..c08495aae4 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -26,6 +26,9 @@ #include "includes.h" +#undef talloc +#define talloc(ctx, size) _talloc(ctx, size) + #define MAX_TALLOC_SIZE 0x10000000 #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 @@ -59,7 +62,7 @@ static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr) /* Allocate a bit of memory as a child of an existing pointer */ -void *talloc(void *context, size_t size) +void *_talloc(void *context, size_t size) { struct talloc_chunk *tc; @@ -289,7 +292,7 @@ int talloc_free(void *ptr) /* A talloc version of realloc */ -void *talloc_realloc(void *ptr, size_t size) +void *_talloc_realloc(void *ptr, size_t size, const char *name) { struct talloc_chunk *tc; void *new_ptr; @@ -302,7 +305,7 @@ void *talloc_realloc(void *ptr, size_t size) /* realloc(NULL) is equavalent to malloc() */ if (ptr == NULL) { - return talloc(NULL, size); + return talloc_named_const(NULL, size, name); } tc = talloc_chunk_from_ptr(ptr); @@ -330,6 +333,7 @@ void *talloc_realloc(void *ptr, size_t size) } tc->size = size; + talloc_set_name_const(tc+1, name); return (void *)(tc+1); } @@ -582,26 +586,30 @@ char *talloc_asprintf_append(char *s, /* alloc an array, checking for integer overflow in the array size */ -void *talloc_array(void *ctx, size_t el_size, uint_t count) +void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - return talloc(ctx, el_size * count); + return talloc_named_const(ctx, el_size * count, name); } /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count) +void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - return talloc_realloc(ptr, el_size * count); + ptr = talloc_realloc(ptr, el_size * count); + if (ptr) { + talloc_set_name_const(ptr, name); + } + return ptr; } /* -- cgit From dbc2346de8b2f213d8bb7e647c4f187c6103e474 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 06:41:59 +0000 Subject: r2653: - data_blob() and data_blob_talloc() now get automatic names - talloc_strdup() and related functions get automatic names (This used to be commit 0cf427d14fe0a19cb3e85b6191be220f3d81080a) --- source4/lib/data_blob.c | 3 ++- source4/lib/talloc.c | 25 +++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index c8c57849d2..b09148b63e 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -25,7 +25,7 @@ construct a data blob, must be freed with data_blob_free() you can pass NULL for p and get a blank data blob *******************************************************************/ -DATA_BLOB data_blob(const void *p, size_t length) +DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) { DATA_BLOB ret; @@ -43,6 +43,7 @@ DATA_BLOB data_blob(const void *p, size_t length) ret.length = 0; return ret; } + talloc_set_name_const(ret.data, name); ret.length = length; return ret; } diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index c08495aae4..1d781e4101 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -26,9 +26,6 @@ #include "includes.h" -#undef talloc -#define talloc(ctx, size) _talloc(ctx, size) - #define MAX_TALLOC_SIZE 0x10000000 #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 @@ -171,7 +168,7 @@ void *talloc_named(void *context, size_t size, va_list ap; void *ptr; - ptr = talloc(context, size); + ptr = _talloc(context, size); if (ptr == NULL) { return NULL; } @@ -192,7 +189,7 @@ void *talloc_named_const(void *context, size_t size, const char *name) { void *ptr; - ptr = talloc(context, size); + ptr = _talloc(context, size); if (ptr == NULL) { return NULL; } @@ -222,7 +219,7 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) va_list ap; void *ptr; - ptr = talloc(NULL, 0); + ptr = _talloc(NULL, 0); if (ptr == NULL) { return NULL; } @@ -438,7 +435,7 @@ static void talloc_report_all(void) */ void talloc_enable_leak_check(void) { - null_context = talloc_named(NULL, 0, "null_context"); + null_context = talloc_named_const(NULL, 0, "null_context"); atexit(talloc_report_all); } @@ -460,12 +457,13 @@ void *talloc_zero(void *t, size_t size) /* memdup with a talloc. */ -void *talloc_memdup(void *t, const void *p, size_t size) +void *_talloc_memdup(void *t, const void *p, size_t size, const char *name) { - void *newp = talloc(t,size); + void *newp = _talloc(t,size); if (newp) { memcpy(newp, p, size); + talloc_set_name_const(newp, name); } return newp; @@ -476,10 +474,15 @@ void *talloc_memdup(void *t, const void *p, size_t size) */ char *talloc_strdup(void *t, const char *p) { + char *ret; if (!p) { return NULL; } - return talloc_memdup(t, p, strlen(p) + 1); + ret = talloc_memdup(t, p, strlen(p) + 1); + if (ret) { + talloc_set_name_const(ret, ret); + } + return ret; } /* @@ -511,6 +514,7 @@ char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2 if (ret) { VA_COPY(ap2, ap); vsnprintf(ret, len+1, fmt, ap2); + talloc_set_name_const(ret, ret); } return ret; @@ -563,6 +567,7 @@ static char *talloc_vasprintf_append(char *s, VA_COPY(ap2, ap); vsnprintf(s+s_len, len+1, fmt, ap2); + talloc_set_name_const(s, s); return s; } -- cgit From b9a779fa83029778bbd2bf059892d0226fc3a035 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 12:48:06 +0000 Subject: r2662: make --leak-check completely silent if not blocks are allocated (This used to be commit 00518201754dc2de583267071ebd2adecbadcb59) --- source4/lib/talloc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 1d781e4101..8193f9c384 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -427,6 +427,9 @@ void talloc_report(void *ptr, FILE *f) */ static void talloc_report_all(void) { + if (talloc_total_size(null_context) == 0) { + return; + } talloc_report(null_context, stderr); } -- cgit From 8d811df12b7e535e6e44bac088a4724a8478c4b1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Sep 2004 22:19:48 +0000 Subject: r2667: Remove forward declaration of static function from function. GCC 3.5 and 4.0 don't accept declarations of static functions inside other functions, see http://gcc.gnu.org/ml/gcc-patches/2004-08/msg02514.html (This used to be commit 8768168aadf51b9559831954e349d9aa94101c41) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 8a26e2d197..e23ae1e7dd 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -177,6 +177,9 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, return 1; } + +static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *); + /* return a list of dn's that might match a simple indexed search on the special objectclass attribute @@ -190,8 +193,6 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, unsigned int i; int ret; const char *target = tree->u.simple.value.data; - static int list_union(struct ldb_context *, - struct dn_list *, const struct dn_list *); list->count = 0; list->dn = NULL; -- cgit From 5b44130afad1bb1764d986de3ef0e8e04b0e7357 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 01:36:19 +0000 Subject: r2671: we're getting too many errors caused by the talloc_realloc() API not taking a context (so when you pass a NULL pointer you end up with memory in a top level context). Fixed it by changing the API to take a context. The context is only used if the pointer you are reallocing is NULL. (This used to be commit 8dc23821c9f54b2f13049b5e608a0cafb81aa540) --- source4/lib/charcnv.c | 8 ++------ source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- source4/lib/socket/socket_ipv4.c | 4 ++-- source4/lib/talloc.c | 17 +++++++++-------- source4/lib/util_str.c | 5 +++-- 6 files changed, 18 insertions(+), 20 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 2ee2bd9bae..33c49504d8 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -208,11 +208,7 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, outbuf = NULL; convert: destlen = destlen * 2; - if (outbuf == NULL) { - ob = talloc_array_p(ctx, char, destlen); - } else { - ob = (char *)talloc_realloc(outbuf, destlen); - } + ob = (char *)talloc_realloc(ctx, outbuf, destlen); if (!ob) { DEBUG(0, ("convert_string_talloc: realloc failed!\n")); talloc_free(outbuf); @@ -245,7 +241,7 @@ convert: destlen = destlen - o_len; /* +2 for mandetory null termination, UTF8 or UTF16 */ - *dest = (char *)talloc_realloc(ob,destlen+2); + *dest = (char *)talloc_realloc(ctx, ob, destlen+2); if (!*dest) { DEBUG(0, ("convert_string_talloc: out of memory!\n")); talloc_free(ob); diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index ec6188be71..ba92369194 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -190,7 +190,7 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch /* Add hive to context */ h->num_hives++; - h->hives = talloc_realloc_p(h->hives, struct registry_hive *, h->num_hives); + h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives); h->hives[h->num_hives-1] = ret; return WERR_OK; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 1c887fc411..3dd73162be 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -90,7 +90,7 @@ WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *cr int i = 0; *hives = talloc_p(mem_ctx, char *); for(i = 0; known_hives[i].name; i++) { - *hives = talloc_realloc_p(*hives, char *, i+2); + *hives = talloc_realloc_p(mem_ctx, *hives, char *, i+2); (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name); } (*hives)[i] = NULL; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index c98e5534ca..88bf611b67 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -184,7 +184,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte } static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags) + DATA_BLOB *blob, size_t wantlen, uint32_t flags) { ssize_t gotlen; void *buf; @@ -235,7 +235,7 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, } blob->length = gotlen; - blob->data = talloc_realloc(buf, gotlen); + blob->data = talloc_realloc(mem_ctx, buf, gotlen); if (!blob->data) { return NT_STATUS_NO_MEMORY; } diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 8193f9c384..7266ff8a45 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -287,9 +287,10 @@ int talloc_free(void *ptr) /* - A talloc version of realloc + A talloc version of realloc. The context argument is only used if + ptr is NULL */ -void *_talloc_realloc(void *ptr, size_t size, const char *name) +void *_talloc_realloc(void *context, void *ptr, size_t size, const char *name) { struct talloc_chunk *tc; void *new_ptr; @@ -302,7 +303,7 @@ void *_talloc_realloc(void *ptr, size_t size, const char *name) /* realloc(NULL) is equavalent to malloc() */ if (ptr == NULL) { - return talloc_named_const(NULL, size, name); + return talloc_named_const(context, size, name); } tc = talloc_chunk_from_ptr(ptr); @@ -550,7 +551,7 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); static char *talloc_vasprintf_append(char *s, - const char *fmt, va_list ap) + const char *fmt, va_list ap) { int len, s_len; va_list ap2; @@ -564,7 +565,7 @@ static char *talloc_vasprintf_append(char *s, } len = vsnprintf(NULL, 0, fmt, ap2); - s = talloc_realloc(s, s_len + len+1); + s = talloc_realloc(NULL, s, s_len + len+1); if (!s) return NULL; VA_COPY(ap2, ap); @@ -607,13 +608,13 @@ void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name) /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(void *ptr, size_t el_size, uint_t count, const char *name) +void *talloc_realloc_array(void *ctx, void *ptr, size_t el_size, uint_t count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - ptr = talloc_realloc(ptr, el_size * count); + ptr = talloc_realloc(ctx, ptr, el_size * count); if (ptr) { talloc_set_name_const(ptr, name); } @@ -632,5 +633,5 @@ void *talloc_ldb_alloc(void *context, void *ptr, size_t size) talloc_free(ptr); return NULL; } - return talloc_realloc(ptr, size); + return talloc_realloc(context, ptr, size); } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index f8aadf8f59..0e58face16 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1428,8 +1428,9 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx, { char *dup_str = talloc_strdup(mem_ctx, str); - *strings = talloc_realloc(*strings, - ((*num)+1) * sizeof(**strings)); + *strings = talloc_realloc_p(mem_ctx, + *strings, + const char *, ((*num)+1)); if ((*strings == NULL) || (dup_str == NULL)) return False; -- cgit From d13bbcf9e35deed8a7ad2b4e37bea56832ba3563 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 04:00:23 +0000 Subject: r2672: don't call a variable "dup" as that conflicts with a standard system call name (This used to be commit 015db2ed8cdde6d6eb79857cb9b6d72185382acc) --- source4/lib/registry/common/reg_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index ba92369194..c55ecd5a41 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -482,10 +482,10 @@ WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) { struct registry_key *cur, *prevcur = parent; WERROR error = WERR_OK; - char *dup, *begin, *end; + char *dups, *begin, *end; TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); - begin = dup = strdup(path); + begin = dups = strdup(path); while(1) { end = strchr(begin, '\\'); @@ -513,7 +513,7 @@ WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) begin = end+1; prevcur = cur; } - SAFE_FREE(dup); + SAFE_FREE(dups); talloc_destroy(mem_ctx); return error; } -- cgit From 351ca44e8b3ea8336abba8215dfc1ccb42458384 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 04:20:18 +0000 Subject: r2674: I have realised that talloc() should have its context marked const, as a const pointer really means that "the data pointed to by this pointer won't change", and that is certainly true of talloc(). The fact that some behind-the-scenes meta-data can change doesn't matter from the point of view of const. this fixes a number of const warnings caused by const data structures being passed as talloc contexts. That will no longer generate a warning. also changed the talloc leak reporting option from --leak-check to --leak-report, as all it does is generate a report on exit. A new --leak-report-full option has been added that shows the complete tree of memory allocations, which is is quite useful in tracking things down. NOTE: I find it quite useful to insert talloc_report_full(ptr, stderr) calls at strategic points in the code while debugging memory allocation problems, particularly before freeing a major context (such as the connection context). This allows you to see if that context has been accumulating too much data, such as per-request data, which should have been freed when the request finished. (This used to be commit c60ff99c3129c26a9204bac1c6e5fb386114a923) --- source4/lib/cmdline/popt_common.c | 13 +++-- source4/lib/data_blob.c | 11 +--- source4/lib/talloc.c | 118 +++++++++++++++++++++++++++----------- 3 files changed, 96 insertions(+), 46 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index f98c460642..725a5060c0 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -34,7 +34,7 @@ */ -enum {OPT_OPTION=1,OPT_LEAK_CHECK=2}; +enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL}; static struct cmdline_auth_info cmdline_auth_info; @@ -117,8 +117,12 @@ static void popt_common_callback(poptContext con, } break; - case OPT_LEAK_CHECK: - talloc_enable_leak_check(); + case OPT_LEAK_REPORT: + talloc_enable_leak_report(); + break; + + case OPT_LEAK_REPORT_FULL: + talloc_enable_leak_report_full(); break; } } @@ -140,7 +144,8 @@ struct poptOption popt_common_samba[] = { { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, - { "leak-check", 0, POPT_ARG_NONE, NULL, OPT_LEAK_CHECK, "enable talloc leak checking", NULL }, + { "leak-report", 0, POPT_ARG_NONE, NULL, OPT_LEAK_REPORT, "enable talloc leak reporting on exit", NULL }, + { "leak-report-full",0, POPT_ARG_NONE, NULL, OPT_LEAK_REPORT_FULL, "enable full talloc leak reporting on exit", NULL }, POPT_TABLEEND }; diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index b09148b63e..7803179d39 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -51,17 +51,12 @@ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) /******************************************************************* construct a data blob, using supplied TALLOC_CTX *******************************************************************/ -DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) +DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name) { - DATA_BLOB ret = data_blob(p, length); + DATA_BLOB ret = data_blob_named(p, length, name); if (ret.data) { - ret.data = talloc_steal(mem_ctx, ret.data); - } else { - /* this ensures the blob has the context attached, so a zero length call - to data_blob_talloc followed by a realloc doesn't cause the memory to come - from the NULL context */ - ret.data = talloc(mem_ctx, 0); + talloc_steal(mem_ctx, ret.data); } return ret; } diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 7266ff8a45..ce8f1c5272 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -30,7 +30,7 @@ #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 -static void *null_context; +static const void *null_context; struct talloc_chunk { struct talloc_chunk *next, *prev; @@ -43,9 +43,9 @@ struct talloc_chunk { }; /* panic if we get a bad magic value */ -static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr) +static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = ((struct talloc_chunk *)ptr)-1; + struct talloc_chunk *tc = ((struct talloc_chunk *)discard_const(ptr))-1; if (tc->magic != TALLOC_MAGIC) { if (tc->magic == TALLOC_MAGIC_FREE) { smb_panic("Bad talloc magic value - double free\n"); @@ -59,7 +59,7 @@ static struct talloc_chunk *talloc_chunk_from_ptr(void *ptr) /* Allocate a bit of memory as a child of an existing pointer */ -void *_talloc(void *context, size_t size) +void *_talloc(const void *context, size_t size) { struct talloc_chunk *tc; @@ -107,7 +107,7 @@ void *_talloc(void *context, size_t size) if the destructor fails then the free is failed, and the memory can be continued to be used */ -void talloc_set_destructor(void *ptr, int (*destructor)(void *)) +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->destructor = destructor; @@ -118,7 +118,7 @@ void talloc_set_destructor(void *ptr, int (*destructor)(void *)) reference count call talloc_free(), which will free the memory if the reference count reaches zero */ -void talloc_increase_ref_count(void *ptr) +void talloc_increase_ref_count(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->ref_count++; @@ -128,9 +128,9 @@ void talloc_increase_ref_count(void *ptr) /* add a name to an existing pointer - va_list version */ -static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = talloc_vasprintf(ptr, fmt, ap); @@ -139,7 +139,7 @@ static void talloc_set_name_v(void *ptr, const char *fmt, va_list ap) /* add a name to an existing pointer */ -void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) +void talloc_set_name(const void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) { va_list ap; va_start(ap, fmt); @@ -151,7 +151,7 @@ void talloc_set_name(void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) more efficient way to add a name to a pointer - the name must point to a true string constant */ -void talloc_set_name_const(void *ptr, const char *name) +void talloc_set_name_const(const void *ptr, const char *name) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = name; @@ -162,7 +162,7 @@ void talloc_set_name_const(void *ptr, const char *name) talloc_named() operates just like talloc() except that it allows you to name the pointer. */ -void *talloc_named(void *context, size_t size, +void *talloc_named(const void *context, size_t size, const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4) { va_list ap; @@ -185,7 +185,7 @@ void *talloc_named(void *context, size_t size, talloc_named() operates just like talloc() except that it allows you to name the pointer. */ -void *talloc_named_const(void *context, size_t size, const char *name) +void *talloc_named_const(const void *context, size_t size, const char *name) { void *ptr; @@ -202,7 +202,7 @@ void *talloc_named_const(void *context, size_t size, const char *name) /* return the name of a talloc ptr, or "UNNAMED" */ -const char *talloc_get_name(void *ptr) +const char *talloc_get_name(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); if (tc->name) { @@ -290,7 +290,7 @@ int talloc_free(void *ptr) A talloc version of realloc. The context argument is only used if ptr is NULL */ -void *_talloc_realloc(void *context, void *ptr, size_t size, const char *name) +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) { struct talloc_chunk *tc; void *new_ptr; @@ -340,7 +340,7 @@ void *_talloc_realloc(void *context, void *ptr, size_t size, const char *name) move a lump of memory from one talloc context to another return the ptr on success, or NUL if it could not be transferred */ -void *talloc_steal(void *new_ctx, void *ptr) +void *talloc_steal(const void *new_ctx, const void *ptr) { struct talloc_chunk *tc, *new_tc; @@ -352,7 +352,7 @@ void *talloc_steal(void *new_ctx, void *ptr) new_tc = talloc_chunk_from_ptr(new_ctx); if (tc == new_tc) { - return ptr; + discard_const(ptr); } if (tc->parent) { @@ -369,13 +369,13 @@ void *talloc_steal(void *new_ctx, void *ptr) if (new_tc->child) new_tc->child->parent = NULL; DLIST_ADD(new_tc->child, tc); - return ptr; + return discard_const(ptr); } /* return the total size of a talloc pool (subtree) */ -static off_t talloc_total_size(void *ptr) +static off_t talloc_total_size(const void *ptr) { off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); @@ -390,7 +390,7 @@ static off_t talloc_total_size(void *ptr) /* return the total number of blocks in a talloc pool (subtree) */ -static off_t talloc_total_blocks(void *ptr) +static off_t talloc_total_blocks(const void *ptr) { off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); @@ -402,10 +402,41 @@ static off_t talloc_total_blocks(void *ptr) return total; } +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth(const void *ptr, FILE *f, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + for (c=tc->child;c;c=c->next) { + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks\n", + depth*2, "", + talloc_get_name(c+1), + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1)); + talloc_report_depth(c+1, f, depth+1); + } + +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + talloc_report_depth(ptr, f, 1); +} + /* report on memory usage by all children of a pointer */ -void talloc_report(void *ptr, FILE *f) +void talloc_report(const void *ptr, FILE *f) { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); @@ -426,7 +457,7 @@ void talloc_report(void *ptr, FILE *f) /* report on any memory hanging off the null context */ -static void talloc_report_all(void) +static void talloc_report_null(void) { if (talloc_total_size(null_context) == 0) { return; @@ -434,21 +465,41 @@ static void talloc_report_all(void) talloc_report(null_context, stderr); } +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) == 0) { + return; + } + talloc_report_full(null_context, stderr); +} + /* enable leak reporting on exit */ -void talloc_enable_leak_check(void) +void talloc_enable_leak_report(void) +{ + null_context = talloc_named_const(NULL, 0, "null_context"); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +void talloc_enable_leak_report_full(void) { null_context = talloc_named_const(NULL, 0, "null_context"); - atexit(talloc_report_all); + atexit(talloc_report_null_full); } /* talloc and zero memory. */ -void *talloc_zero(void *t, size_t size) +void *talloc_zero(const void *ctx, size_t size) { - void *p = talloc(t, size); + void *p = talloc(ctx, size); if (p) { memset(p, '\0', size); @@ -461,13 +512,12 @@ void *talloc_zero(void *t, size_t size) /* memdup with a talloc. */ -void *_talloc_memdup(void *t, const void *p, size_t size, const char *name) +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) { - void *newp = _talloc(t,size); + void *newp = talloc_named_const(t, size, name); if (newp) { memcpy(newp, p, size); - talloc_set_name_const(newp, name); } return newp; @@ -476,7 +526,7 @@ void *_talloc_memdup(void *t, const void *p, size_t size, const char *name) /* strdup with a talloc */ -char *talloc_strdup(void *t, const char *p) +char *talloc_strdup(const void *t, const char *p) { char *ret; if (!p) { @@ -492,7 +542,7 @@ char *talloc_strdup(void *t, const char *p) /* strndup with a talloc */ -char *talloc_strndup(void *t, const char *p, size_t n) +char *talloc_strndup(const void *t, const char *p, size_t n) { size_t len = strnlen(p, n); char *ret; @@ -504,7 +554,7 @@ char *talloc_strndup(void *t, const char *p, size_t n) return ret; } -char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0) +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2,0) { int len; char *ret; @@ -529,7 +579,7 @@ char *talloc_vasprintf(void *t, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(2 Perform string formatting, and return a pointer to newly allocated memory holding the result, inside a memory pool. */ -char *talloc_asprintf(void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) +char *talloc_asprintf(const void *t, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) { va_list ap; char *ret; @@ -595,7 +645,7 @@ char *talloc_asprintf_append(char *s, /* alloc an array, checking for integer overflow in the array size */ -void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name) +void *talloc_array(const void *ctx, size_t el_size, uint_t count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { @@ -608,7 +658,7 @@ void *talloc_array(void *ctx, size_t el_size, uint_t count, const char *name) /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(void *ctx, void *ptr, size_t el_size, uint_t count, const char *name) +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, uint_t count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { -- cgit From 61a7dfc2371c65bce0bf15ef868b40921cd81756 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 05:13:00 +0000 Subject: r2675: added a convenience function void *talloc_reference(const void *context, const void *ptr); this function makes a secondary reference to ptr, and hangs it off the given context. This greatly simplifies some of the current reference counting code in the samr server and I suspect it will be widely used in other places too. the way you use it is like this: domain_state->connect_state = talloc_reference(domain_state, connect_state); that makes the element connect_state of domain_state a secondary reference to connect_state. The connect_state structure will then only be freed when both domain_state and the original connect_state go away, allowing you to free them independently and in any order. you could do this alrady using a talloc destructor, and that is what the samr server did previously, but that meant this construct was being reinvented in several places. So this convenience function sets up the destructor for you, giving a much more convenient and less error prone API. (This used to be commit dc5315086156644fad093cbe6b02d999adba8540) --- source4/lib/talloc.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index ce8f1c5272..55b97717c7 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -124,6 +124,41 @@ void talloc_increase_ref_count(const void *ptr) tc->ref_count++; } +/* + helper for talloc_reference() +*/ +static int talloc_reference_destructor(void *ptr) +{ + void **handle = ptr; + talloc_free(*handle); + return 0; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *talloc_reference(const void *context, const void *ptr) +{ + void **handle; + handle = _talloc(context, sizeof(void *)); + if (handle == NULL) { + return NULL; + } + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + talloc_increase_ref_count(ptr); + *handle = discard_const(ptr); + return *handle; +} + /* add a name to an existing pointer - va_list version -- cgit From 2f5cf5d7946e730f9e42b7914d5b1f2cbc5a2cc2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 08:38:13 +0000 Subject: r2677: - fixed a bug in the recursive logic talloc_free() when there are circular references (circular references are allowed, they just need to be handled carefully inside talloc) - mark talloc_reference() pointers nicely in the --leak-report-full code, so you see what has a reference to what in a useful manner (This used to be commit a87d3d11344069284604a7294a54cadcc6e1a096) --- source4/lib/talloc.c | 71 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 55b97717c7..5d22754f5b 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -146,7 +146,7 @@ static int talloc_reference_destructor(void *ptr) void *talloc_reference(const void *context, const void *ptr) { void **handle; - handle = _talloc(context, sizeof(void *)); + handle = talloc_named_const(context, sizeof(void *), ".reference"); if (handle == NULL) { return NULL; } @@ -169,6 +169,9 @@ static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = talloc_vasprintf(ptr, fmt, ap); + if (tc->name) { + talloc_set_name_const(tc->name, ".name"); + } } /* @@ -267,7 +270,6 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) } - /* free a talloc pointer. This also frees all child pointers of this pointer recursively @@ -278,7 +280,7 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) */ int talloc_free(void *ptr) { - struct talloc_chunk *tc; + struct talloc_chunk *tc, *tc2, *next; if (ptr == NULL) { return -1; @@ -286,23 +288,26 @@ int talloc_free(void *ptr) tc = talloc_chunk_from_ptr(ptr); - tc->ref_count--; - if (tc->ref_count != 0) { - return -1; - } - - if (tc->destructor && tc->destructor(ptr) == -1) { - tc->ref_count++; + if (tc->ref_count > 1) { + tc->ref_count--; return -1; } - while (tc->child) { - if (talloc_free(tc->child + 1) != 0) { - tc->child->parent = NULL; - break; + /* while processing the free, increase the reference count + so we don't recurse into this function */ + tc->ref_count++; + if (tc->destructor) { + if (tc->destructor(ptr) == -1) { + tc->ref_count--; + return -1; } } + for (tc2=tc->child;tc2;tc2=next) { + next = tc2->next; + talloc_free(tc2 + 1); + } + if (tc->parent) { DLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { @@ -313,6 +318,10 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } + if (tc->child) { + tc->child->parent = tc->parent; + } + tc->magic = TALLOC_MAGIC_FREE; free(tc); @@ -445,12 +454,20 @@ static void talloc_report_depth(const void *ptr, FILE *f, int depth) struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); for (c=tc->child;c;c=c->next) { - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks\n", - depth*2, "", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); - talloc_report_depth(c+1, f, depth+1); + const char *name = talloc_get_name(c+1); + if (strcmp(name, ".reference") == 0) { + void **handle = (void *)(c+1); + const char *name2 = talloc_get_name(*handle); + fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); + } else { + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1), + c->ref_count); + talloc_report_depth(c+1, f, depth+1); + } } } @@ -460,6 +477,11 @@ static void talloc_report_depth(const void *ptr, FILE *f, int depth) */ void talloc_report_full(const void *ptr, FILE *f) { + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", talloc_get_name(ptr), (unsigned long)talloc_total_size(ptr), @@ -473,13 +495,20 @@ void talloc_report_full(const void *ptr, FILE *f) */ void talloc_report(const void *ptr, FILE *f) { - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *c, *tc; + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", talloc_get_name(ptr), (unsigned long)talloc_total_size(ptr), (unsigned long)talloc_total_blocks(ptr)); + tc = talloc_chunk_from_ptr(ptr); + for (c=tc->child;c;c=c->next) { fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", talloc_get_name(c+1), -- cgit From 6f068e207ab6b6c0206df35e51c56119c2a82fef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Sep 2004 08:39:06 +0000 Subject: r2678: from_name and to_name aren't needed in smb_iconv_t (This used to be commit f3844cc0a5ad6b03f166435d44db02763df345d7) --- source4/lib/iconv.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index fb997cf8f1..567f5b5902 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -187,9 +187,6 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) } memset(ret, 0, sizeof(*ret)); - ret->from_name = talloc_strdup(ret, fromcode); - ret->to_name = talloc_strdup(ret, tocode); - /* check for the simplest null conversion */ if (strcmp(fromcode, tocode) == 0) { ret->direct = iconv_copy; -- cgit From 073e9af19bb1d913aa0704c142ee6b56e05030e3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 27 Sep 2004 10:13:41 +0000 Subject: r2684: Free the right talloc context (don't panic when encountering illegal multibyte sequences) (This used to be commit b90da2337b83eb261a8072f9d0b13ec28caf3c4d) --- source4/lib/charcnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 33c49504d8..7d00c7e78f 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -234,7 +234,7 @@ convert: break; } DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); - talloc_free(outbuf); + talloc_free(ob); /* smb_panic(reason); */ return (size_t)-1; } -- cgit From f63e3ae1f74966ba2e6eeb4a3830b81d3df5c67f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 27 Sep 2004 11:38:36 +0000 Subject: r2686: remove unused gtk+ check metze (This used to be commit d1e8b340a9942553ec7f281affd11ea4315ac448) --- source4/lib/registry/config.m4 | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index 4fdde67faf..f3681e7828 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -15,8 +15,6 @@ if test t$SMB_EXT_LIB_ENABLE_gconf = tYES; then SMB_MODULE_DEFAULT(registry_gconf, STATIC) fi -SMB_EXT_LIB_FROM_PKGCONFIG(gtk, [glib-2.0 gtk+-2.0]) - SMB_MODULE_MK(registry_nt4, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_w95, REGISTRY, STATIC, lib/registry/config.mk) SMB_MODULE_MK(registry_dir, REGISTRY, STATIC, lib/registry/config.mk) -- cgit From a675b09e8d45b9298df8f8c82bbaa7b91a793eb5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 05:42:02 +0000 Subject: r2709: finally solved the talloc reference problem. The problem was that the simple "uint_t ref_count;" in a talloc chunk did not give enough information. It told us that a pointer was referenced more than once, but it didn't say who it was referenced by. This means that when the pointer was freed we had no sane way to clean up the reference. I have now replaced ref_count with a "refs" list, which means that references point to the pointer, and the pointer has a linked list of references. So now we can cleanup from either direction without losing track of anything. I've also added a LOCAL-TALLOC smbtorture test that tests talloc behaviour for some common uses. (This used to be commit 911a8d590cb184bcb892810729955c2c4cf02550) --- source4/lib/talloc.c | 133 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 39 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 5d22754f5b..d0056d7b2a 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -32,13 +32,20 @@ static const void *null_context; +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; +}; + +typedef int (*talloc_destructor_t)(void *); + struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; size_t size; uint_t magic; - uint_t ref_count; - int (*destructor)(void *); + talloc_destructor_t destructor; const char *name; }; @@ -78,10 +85,10 @@ void *_talloc(const void *context, size_t size) tc->size = size; tc->magic = TALLOC_MAGIC; - tc->ref_count = 1; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; + tc->refs = NULL; if (context) { struct talloc_chunk *parent = talloc_chunk_from_ptr(context); @@ -114,14 +121,11 @@ void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) } /* - increase the reference count on a piece of memory. To decrease the - reference count call talloc_free(), which will free the memory if - the reference count reaches zero + increase the reference count on a piece of memory. */ void talloc_increase_ref_count(const void *ptr) { - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->ref_count++; + talloc_reference(null_context, ptr); } /* @@ -129,8 +133,14 @@ void talloc_increase_ref_count(const void *ptr) */ static int talloc_reference_destructor(void *ptr) { - void **handle = ptr; - talloc_free(*handle); + struct talloc_reference_handle *handle = ptr; + struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); + if (tc1->destructor != (talloc_destructor_t)-1) { + tc1->destructor = NULL; + } + DLIST_REMOVE(tc2->refs, handle); + talloc_free(handle); return 0; } @@ -145,8 +155,9 @@ static int talloc_reference_destructor(void *ptr) */ void *talloc_reference(const void *context, const void *ptr) { - void **handle; - handle = talloc_named_const(context, sizeof(void *), ".reference"); + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *handle; + handle = talloc_named_const(context, sizeof(*handle), ".reference"); if (handle == NULL) { return NULL; } @@ -154,9 +165,9 @@ void *talloc_reference(const void *context, const void *ptr) main context as that allows the caller to still setup their own destructor on the context if they want to */ talloc_set_destructor(handle, talloc_reference_destructor); - talloc_increase_ref_count(ptr); - *handle = discard_const(ptr); - return *handle; + handle->ptr = discard_const(ptr); + DLIST_ADD(tc->refs, handle); + return handle->ptr; } @@ -280,7 +291,7 @@ void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) */ int talloc_free(void *ptr) { - struct talloc_chunk *tc, *tc2, *next; + struct talloc_chunk *tc; if (ptr == NULL) { return -1; @@ -288,26 +299,29 @@ int talloc_free(void *ptr) tc = talloc_chunk_from_ptr(ptr); - if (tc->ref_count > 1) { - tc->ref_count--; - return -1; + if (tc->refs) { + talloc_reference_destructor(tc->refs); + return 0; } - /* while processing the free, increase the reference count - so we don't recurse into this function */ - tc->ref_count++; if (tc->destructor) { - if (tc->destructor(ptr) == -1) { - tc->ref_count--; + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; return -1; } + tc->destructor = NULL; } - for (tc2=tc->child;tc2;tc2=next) { - next = tc2->next; - talloc_free(tc2 + 1); + while (tc->child) { + talloc_free(talloc_steal(tc->parent?tc->parent+1:null_context, + tc->child+1)); } - + if (tc->parent) { DLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { @@ -318,10 +332,6 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - if (tc->child) { - tc->child->parent = tc->parent; - } - tc->magic = TALLOC_MAGIC_FREE; free(tc); @@ -352,6 +362,11 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n tc = talloc_chunk_from_ptr(ptr); + /* don't allow realloc on referenced pointers */ + if (tc->refs) { + return NULL; + } + /* by resetting magic we catch users of the old memory */ tc->magic = TALLOC_MAGIC_FREE; @@ -382,7 +397,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n /* move a lump of memory from one talloc context to another return the - ptr on success, or NUL if it could not be transferred + ptr on success, or NULL if it could not be transferred */ void *talloc_steal(const void *new_ctx, const void *ptr) { @@ -393,10 +408,26 @@ void *talloc_steal(const void *new_ctx, const void *ptr) } tc = talloc_chunk_from_ptr(ptr); + + if (new_ctx == NULL) { + if (tc->parent) { + DLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const(ptr); + } + new_tc = talloc_chunk_from_ptr(new_ctx); if (tc == new_tc) { - discard_const(ptr); + return discard_const(ptr); } if (tc->parent) { @@ -419,10 +450,19 @@ void *talloc_steal(const void *new_ctx, const void *ptr) /* return the total size of a talloc pool (subtree) */ -static off_t talloc_total_size(const void *ptr) +off_t talloc_total_size(const void *ptr) { off_t total = 0; - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); total = tc->size; for (c=tc->child;c;c=c->next) { @@ -446,6 +486,21 @@ static off_t talloc_total_blocks(const void *ptr) return total; } +/* + return the number of external references to a pointer +*/ +static int talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + int ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + /* report on memory usage by all children of a pointer, giving a full tree view */ @@ -456,8 +511,8 @@ static void talloc_report_depth(const void *ptr, FILE *f, int depth) for (c=tc->child;c;c=c->next) { const char *name = talloc_get_name(c+1); if (strcmp(name, ".reference") == 0) { - void **handle = (void *)(c+1); - const char *name2 = talloc_get_name(*handle); + struct talloc_reference_handle *handle = (void *)(c+1); + const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", @@ -465,7 +520,7 @@ static void talloc_report_depth(const void *ptr, FILE *f, int depth) name, (unsigned long)talloc_total_size(c+1), (unsigned long)talloc_total_blocks(c+1), - c->ref_count); + talloc_reference_count(c+1)); talloc_report_depth(c+1, f, depth+1); } } -- cgit From 0244414a58691c3e0081777fb1372d3ed068ac8b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 08:17:20 +0000 Subject: r2712: fixed a bug in ldbtest to make it cope with an existing index (This used to be commit 3f776a9b5c240312f161b651201458e43a9dd6a9) --- source4/lib/ldb/tools/ldbtest.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 7c240a01d2..63ce738f8c 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -294,6 +294,8 @@ static void start_test_index(struct ldb_context **ldb) printf("Starting index test\n"); + ldb_delete(*ldb, "@INDEXLIST"); + memset(&msg, 0, sizeof(msg)); msg.dn = strdup("@INDEXLIST"); ldb_msg_add_string(*ldb, &msg, "@IDXATTR", strdup("uid")); @@ -404,10 +406,10 @@ static void usage(void) srandom(1); - start_test_index(&ldb); - start_test(ldb, nrecords, nsearches); + start_test_index(&ldb); + ldb_close(ldb); return 0; -- cgit From 14a0e37582c9aea69d92cf2ad449dda0bdf3bce0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 09:34:49 +0000 Subject: r2713: better handling of binary values in index key creation (This used to be commit b0c92616fb69d8139f66dc8144cfcc88ea6825dc) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index e23ae1e7dd..cfd097e361 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -70,7 +70,7 @@ static char *ldb_dn_key(struct ldb_context *ldb, return ret; } - ldb_asprintf(ldb, &ret, "%s:%s:%s", LTDB_INDEX, attr, (char *)value->data); + ldb_asprintf(ldb, &ret, "%s:%s:%.*s", LTDB_INDEX, attr, value->length, (char *)value->data); return ret; } -- cgit From 8ae2cd82caaf8762e73499a1744c63c42a5b9fe6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 11:54:17 +0000 Subject: r2718: - added a talloc_unreference() function as requested by metze. - added documentation for talloc_unreference() - made the abandoned child logic in talloc_free() clearer and more consistent (This used to be commit a87584c8e3fb06cd3ff29a918f681b5c6c32b9ff) --- source4/lib/talloc.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index d0056d7b2a..bb2ed9449c 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -170,6 +170,34 @@ void *talloc_reference(const void *context, const void *ptr) return handle->ptr; } +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +void *talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (context == NULL) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *tc2 = talloc_chunk_from_ptr(h); + const void *parent = tc2->parent?tc2->parent+1:null_context; + if (parent == context) break; + } + if (h == NULL) { + return NULL; + } + + talloc_set_destructor(h, NULL); + DLIST_REMOVE(tc->refs, h); + talloc_free(h); + return discard_const(ptr); +} /* add a name to an existing pointer - va_list version @@ -318,8 +346,21 @@ int talloc_free(void *ptr) } while (tc->child) { - talloc_free(talloc_steal(tc->parent?tc->parent+1:null_context, - tc->child+1)); + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = tc->child+1; + const void *new_parent = null_context; + if (tc->child->refs) { + struct talloc_chunk *ref = talloc_chunk_from_ptr(tc->child->refs); + if (ref->parent) new_parent = ref->parent+1; + } + if (new_parent == null_context && tc->parent) { + new_parent = tc->parent+1; + } + talloc_free(talloc_steal(new_parent, child)); } if (tc->parent) { -- cgit From b2f9612e5dda513568633d3b11872e0f0395b128 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 12:06:22 +0000 Subject: r2721: added a -b option to ldbtest so it can be used with the new smbd ldap server without changing realms (This used to be commit fd2725f5c0a2ea89bbfcb0403d1bc03fa7b7ec25) --- source4/lib/ldb/tools/ldbtest.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 63ce738f8c..25b86a8a43 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -35,6 +35,7 @@ #include "includes.h" static const char *ldb_url; +static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; static struct timeval tp1,tp2; @@ -254,10 +255,8 @@ static void search_uid(struct ldb_context *ldb, int nrecords, int nsearches) static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) { - const char *base = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; - printf("Adding %d records\n", nrecords); - add_records(ldb, base, nrecords); + add_records(ldb, base_dn, nrecords); printf("Starting search on uid\n"); start_timer(); @@ -265,10 +264,10 @@ static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) printf("uid search took %.2f seconds\n", end_timer()); printf("Modifying records\n"); - modify_records(ldb, base, nrecords); + modify_records(ldb, base_dn, nrecords); printf("Deleting records\n"); - delete_records(ldb, base, nrecords); + delete_records(ldb, base_dn, nrecords); } @@ -287,7 +286,6 @@ be indexed */ static void start_test_index(struct ldb_context **ldb) { - const char *base = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; struct ldb_message msg; struct ldb_message **res; int ret; @@ -306,7 +304,7 @@ static void start_test_index(struct ldb_context **ldb) } memset(&msg, 0, sizeof(msg)); - asprintf(&msg.dn, "cn=%s,%s", "test", base); + asprintf(&msg.dn, "cn=%s,%s", "test", base_dn); ldb_msg_add_string(*ldb, &msg, "cn", strdup("test")); ldb_msg_add_string(*ldb, &msg, "sn", strdup("test")); ldb_msg_add_string(*ldb, &msg, "uid", strdup("test")); @@ -366,7 +364,7 @@ static void usage(void) ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:r:s:")) != EOF) { + while ((opt = getopt(argc, argv, "hH:r:s:b:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; @@ -376,6 +374,10 @@ static void usage(void) nrecords = atoi(optarg); break; + case 'b': + base_dn = optarg; + break; + case 's': nsearches = atoi(optarg); break; -- cgit From ca3765ca7834e4184745b861d3a9e3e7db19bd14 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 12:38:59 +0000 Subject: r2725: fixed ldbtest to give the basedn to ldb_search() (This used to be commit 19925f5bd8dd24742e5d216b0c491975ceb7d3a6) --- source4/lib/ldb/tools/ldbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 25b86a8a43..a5a8ea7a3a 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -228,7 +228,7 @@ static void search_uid(struct ldb_context *ldb, int nrecords, int nsearches) int ret; asprintf(&expr, "(uid=TEST%d)", uid); - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res); + ret = ldb_search(ldb, base_dn, LDB_SCOPE_SUBTREE, expr, NULL, &res); if (uid < nrecords && ret != 1) { printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb)); @@ -327,7 +327,7 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - ret = ldb_search(*ldb, NULL, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); + ret = ldb_search(*ldb, base_dn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); if (ret != 1) { printf("Should have found 1 record - found %d\n", ret); exit(1); -- cgit From 443d8fd05e6aa558c218d843f98c3ce3ae6d4963 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 12:39:41 +0000 Subject: r2726: added a -r option to ldbdel to allow easy delete of a whole subtree. Useful when cleaning up a mess after testing. (This used to be commit 476674af5519960300c0a07349c7cdf307af3822) --- source4/lib/ldb/tools/ldbdel.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 2977357ced..d36db5429a 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -34,10 +34,35 @@ #include "includes.h" +static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) +{ + int ret, i, total=0; + const char *attrs[] = { "dn", NULL }; + struct ldb_message **res; + + ret = ldb_search(ldb, dn, LDB_SCOPE_SUBTREE, "dn=*", attrs, &res); + if (ret <= 0) return -1; + + for (i=0;idn) == 0) { + total++; + } + } + + ldb_search_free(ldb, res); + + if (total == 0) { + return -1; + } + printf("Deleted %d records\n", total); + return 0; +} + static void usage(void) { printf("Usage: ldbdel \n"); printf("Options:\n"); + printf(" -r recursively delete the given subtree\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); printf("\n"); printf("Deletes records from a ldb\n\n"); @@ -49,16 +74,20 @@ static void usage(void) struct ldb_context *ldb; int ret, i; const char *ldb_url; - int opt; + int opt, recursive=0; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:")) != EOF) { + while ((opt = getopt(argc, argv, "hH:r")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; break; + case 'r': + recursive=1; + break; + case 'h': default: usage(); @@ -88,7 +117,14 @@ static void usage(void) ldb_set_debug_stderr(ldb); for (i=0;i Date: Tue, 28 Sep 2004 21:41:33 +0000 Subject: r2737: fixed up a corner case where talloc_unreference() and talloc_free() might not place the pointer in the context specified in the docs. The code was assuming that pointer was at the head of the child list, which it may not be, depending on what other operations have happened in between. (This used to be commit e62bd7ef7ec80365ab00ce5b2051b7dc1726304b) --- source4/lib/talloc.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index bb2ed9449c..4b796fbbd0 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -63,6 +63,17 @@ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) return tc; } + +/* + return the parent chunk of a pointer +*/ +static struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + return tc->parent; +} + /* Allocate a bit of memory as a child of an existing pointer */ @@ -185,8 +196,7 @@ void *talloc_unreference(const void *context, const void *ptr) } for (h=tc->refs;h;h=h->next) { - struct talloc_chunk *tc2 = talloc_chunk_from_ptr(h); - const void *parent = tc2->parent?tc2->parent+1:null_context; + const void *parent = talloc_parent_chunk(h); if (parent == context) break; } if (h == NULL) { @@ -354,11 +364,12 @@ int talloc_free(void *ptr) void *child = tc->child+1; const void *new_parent = null_context; if (tc->child->refs) { - struct talloc_chunk *ref = talloc_chunk_from_ptr(tc->child->refs); - if (ref->parent) new_parent = ref->parent+1; + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = p+1; } - if (new_parent == null_context && tc->parent) { - new_parent = tc->parent+1; + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = p+1; } talloc_free(talloc_steal(new_parent, child)); } -- cgit From facfe8867d0f69f194d375a81f54dcb4eb91334e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2004 23:30:14 +0000 Subject: r2742: - fixed a bug in talloc_unreference() - made the LOCAL-TALLOC smbtorture test much stricter, checking that block counts for every pointer are correct after every operation (This used to be commit 18d3e2647f0bedbba699d1ba2649c0cfe4526ef6) --- source4/lib/talloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 4b796fbbd0..b81cf7221b 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -196,8 +196,8 @@ void *talloc_unreference(const void *context, const void *ptr) } for (h=tc->refs;h;h=h->next) { - const void *parent = talloc_parent_chunk(h); - if (parent == context) break; + struct talloc_chunk *p = talloc_parent_chunk(h); + if ((p==NULL && context==NULL) || p+1 == context) break; } if (h == NULL) { return NULL; @@ -526,7 +526,7 @@ off_t talloc_total_size(const void *ptr) /* return the total number of blocks in a talloc pool (subtree) */ -static off_t talloc_total_blocks(const void *ptr) +off_t talloc_total_blocks(const void *ptr) { off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); -- cgit From 4f13ebef5d6711ac121b9c41e2fbbe2cd3b6da0e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Sep 2004 06:31:14 +0000 Subject: r2744: ben elliston taught me about gcov today, which allows you to measure the % coverage in terms of lines of code of a test suite. I thought a good first place to start with gcov was the talloc test suite. When I started the test suite covered about 60% of all lines of code in talloc.c, and now it covers about 99%. The only lines not covered are talloc corruption errors, as that would cause smb_panic() to fire. It will be interesting to try gcov on the main Samba test suite for smbd. We won't achieve 100% coverage, but it would be nice to get to 90% or more. I also modified the talloc.c sources to be able to be build standalone, using: gcc -c -D_STANDALONE_ -Iinlcude lib/talloc.c that should make it much easier to re-use talloc in other projects (This used to be commit 8d4dc99b82efdf24b6811851c7bdd4af5a4c52c9) --- source4/lib/talloc.c | 178 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 120 insertions(+), 58 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index b81cf7221b..9d8caeb0e7 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -1,7 +1,9 @@ /* Samba Unix SMB/CIFS implementation. - Samba temporary memory allocation functions - new interface + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 @@ -24,14 +26,42 @@ inspired by http://swapped.cc/halloc/ */ + +/* + if you need to build this outside of the Samba source tree then please define _STANDALONE_ +*/ +#ifdef _STANDALONE_ +#include +#include +#include +#include +#include "talloc.h" +#else #include "includes.h" +#endif #define MAX_TALLOC_SIZE 0x10000000 #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC_REFERENCE ((const char *)1) +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)(ptr)) +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ static const void *null_context; + struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; void *ptr; @@ -44,7 +74,7 @@ struct talloc_chunk { struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; size_t size; - uint_t magic; + unsigned magic; talloc_destructor_t destructor; const char *name; }; @@ -52,17 +82,45 @@ struct talloc_chunk { /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = ((struct talloc_chunk *)discard_const(ptr))-1; - if (tc->magic != TALLOC_MAGIC) { + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; + if (tc->magic != TALLOC_MAGIC) { if (tc->magic == TALLOC_MAGIC_FREE) { - smb_panic("Bad talloc magic value - double free\n"); + TALLOC_ABORT("Bad talloc magic value - double free"); } else { - smb_panic("Bad talloc magic value\n"); + TALLOC_ABORT("Bad talloc magic value - unknown value"); } } + return tc; } +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + /* return the parent chunk of a pointer @@ -90,9 +148,7 @@ void *_talloc(const void *context, size_t size) } tc = malloc(sizeof(*tc)+size); - if (tc == NULL) { - return NULL; - } + if (tc == NULL) return NULL; tc->size = size; tc->magic = TALLOC_MAGIC; @@ -110,7 +166,7 @@ void *_talloc(const void *context, size_t size) parent->child->parent = NULL; } - DLIST_ADD(parent->child, tc); + _TLIST_ADD(parent->child, tc); } else { tc->next = tc->prev = tc->parent = NULL; } @@ -150,7 +206,7 @@ static int talloc_reference_destructor(void *ptr) if (tc1->destructor != (talloc_destructor_t)-1) { tc1->destructor = NULL; } - DLIST_REMOVE(tc2->refs, handle); + _TLIST_REMOVE(tc2->refs, handle); talloc_free(handle); return 0; } @@ -168,16 +224,15 @@ void *talloc_reference(const void *context, const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *handle; - handle = talloc_named_const(context, sizeof(*handle), ".reference"); - if (handle == NULL) { - return NULL; - } + handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); + if (handle == NULL) return NULL; + /* note that we hang the destructor off the handle, not the main context as that allows the caller to still setup their own destructor on the context if they want to */ talloc_set_destructor(handle, talloc_reference_destructor); - handle->ptr = discard_const(ptr); - DLIST_ADD(tc->refs, handle); + handle->ptr = discard_const_p(void, ptr); + _TLIST_ADD(tc->refs, handle); return handle->ptr; } @@ -204,9 +259,9 @@ void *talloc_unreference(const void *context, const void *ptr) } talloc_set_destructor(h, NULL); - DLIST_REMOVE(tc->refs, h); + _TLIST_REMOVE(tc->refs, h); talloc_free(h); - return discard_const(ptr); + return discard_const_p(void, ptr); } /* @@ -226,7 +281,7 @@ static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) /* add a name to an existing pointer */ -void talloc_set_name(const void *ptr, const char *fmt, ...) _PRINTF_ATTRIBUTE(2,3) +void talloc_set_name(const void *ptr, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -249,16 +304,13 @@ void talloc_set_name_const(const void *ptr, const char *name) talloc_named() operates just like talloc() except that it allows you to name the pointer. */ -void *talloc_named(const void *context, size_t size, - const char *fmt, ...) _PRINTF_ATTRIBUTE(3,4) +void *talloc_named(const void *context, size_t size, const char *fmt, ...) { va_list ap; void *ptr; ptr = _talloc(context, size); - if (ptr == NULL) { - return NULL; - } + if (ptr == NULL) return NULL; va_start(ap, fmt); talloc_set_name_v(ptr, fmt, ap); @@ -292,6 +344,9 @@ void *talloc_named_const(const void *context, size_t size, const char *name) const char *talloc_get_name(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (tc->name == TALLOC_MAGIC_REFERENCE) { + return ".reference"; + } if (tc->name) { return tc->name; } @@ -301,15 +356,13 @@ const char *talloc_get_name(const void *ptr) /* this is for compatibility with older versions of talloc */ -void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2) +void *talloc_init(const char *fmt, ...) { va_list ap; void *ptr; ptr = _talloc(NULL, 0); - if (ptr == NULL) { - return NULL; - } + if (ptr == NULL) return NULL; va_start(ap, fmt); talloc_set_name_v(ptr, fmt, ap); @@ -375,7 +428,7 @@ int talloc_free(void *ptr) } if (tc->parent) { - DLIST_REMOVE(tc->parent->child, tc); + _TLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { tc->parent->child->parent = tc->parent; } @@ -407,6 +460,10 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n return NULL; } + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + /* realloc(NULL) is equavalent to malloc() */ if (ptr == NULL) { return talloc_named_const(context, size, name); @@ -423,9 +480,9 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n tc->magic = TALLOC_MAGIC_FREE; new_ptr = realloc(tc, size + sizeof(*tc)); - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - return NULL; + if (!new_ptr) { + tc->magic = TALLOC_MAGIC; + return NULL; } tc = new_ptr; @@ -463,7 +520,7 @@ void *talloc_steal(const void *new_ctx, const void *ptr) if (new_ctx == NULL) { if (tc->parent) { - DLIST_REMOVE(tc->parent->child, tc); + _TLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { tc->parent->child->parent = tc->parent; } @@ -473,17 +530,17 @@ void *talloc_steal(const void *new_ctx, const void *ptr) } tc->parent = tc->next = tc->prev = NULL; - return discard_const(ptr); + return discard_const_p(void, ptr); } new_tc = talloc_chunk_from_ptr(new_ctx); if (tc == new_tc) { - return discard_const(ptr); + return discard_const_p(void, ptr); } if (tc->parent) { - DLIST_REMOVE(tc->parent->child, tc); + _TLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { tc->parent->child->parent = tc->parent; } @@ -494,9 +551,9 @@ void *talloc_steal(const void *new_ctx, const void *ptr) tc->parent = new_tc; if (new_tc->child) new_tc->child->parent = NULL; - DLIST_ADD(new_tc->child, tc); + _TLIST_ADD(new_tc->child, tc); - return discard_const(ptr); + return discard_const_p(void, ptr); } /* @@ -561,12 +618,12 @@ static void talloc_report_depth(const void *ptr, FILE *f, int depth) struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); for (c=tc->child;c;c=c->next) { - const char *name = talloc_get_name(c+1); - if (strcmp(name, ".reference") == 0) { + if (c->name == TALLOC_MAGIC_REFERENCE) { struct talloc_reference_handle *handle = (void *)(c+1); const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { + const char *name = talloc_get_name(c+1); fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", depth*4, "", name, @@ -630,10 +687,9 @@ void talloc_report(const void *ptr, FILE *f) */ static void talloc_report_null(void) { - if (talloc_total_size(null_context) == 0) { - return; + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); } - talloc_report(null_context, stderr); } /* @@ -641,10 +697,9 @@ static void talloc_report_null(void) */ static void talloc_report_null_full(void) { - if (talloc_total_size(null_context) == 0) { - return; + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); } - talloc_report_full(null_context, stderr); } /* @@ -715,9 +770,11 @@ char *talloc_strdup(const void *t, const char *p) */ char *talloc_strndup(const void *t, const char *p, size_t n) { - size_t len = strnlen(p, n); + size_t len; char *ret; + for (len=0; p[len] && len= MAX_TALLOC_SIZE/el_size) { @@ -829,7 +891,7 @@ void *talloc_array(const void *ctx, size_t el_size, uint_t count, const char *na /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, uint_t count, const char *name) +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) { if (count == 0 || count >= MAX_TALLOC_SIZE/el_size) { -- cgit From 3c7251ee7889a9eb7d71d4fcb48dc5474a19fc05 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 01:42:06 +0000 Subject: r2773: allow zero sized array talloc (This used to be commit 06c58ad221ec40e46310e847ebf640bd53e8e468) --- source4/lib/talloc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 9d8caeb0e7..4032039142 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -880,8 +880,7 @@ char *talloc_asprintf_append(char *s, const char *fmt, ...) */ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) { - if (count == 0 || - count >= MAX_TALLOC_SIZE/el_size) { + if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; } return talloc_named_const(ctx, el_size * count, name); @@ -893,8 +892,7 @@ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char * */ void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) { - if (count == 0 || - count >= MAX_TALLOC_SIZE/el_size) { + if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; } ptr = talloc_realloc(ctx, ptr, el_size * count); -- cgit From 45717794c3d63ddf30fc1cfd040029b1ffd58063 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 01:43:43 +0000 Subject: r2775: rewrote our ms_fnmatch code to be much more efficient, and to exactly match w2k behaviour for older negotiated protocols. (This used to be commit bae2baeb0247ae8f840b3d3b5488c98d081789c5) --- source4/lib/ms_fnmatch.c | 275 +++++++++++++++++++++-------------------------- 1 file changed, 121 insertions(+), 154 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index 5a9edc2c87..d072eb6a50 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. filename matching routine - Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Tridgell 1992-2004 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 @@ -15,215 +15,182 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ /* This module was originally based on fnmatch.c copyright by the Free - Software Foundation. It bears little resemblence to that code now + Software Foundation. It bears little (if any) resemblence to that + code now */ -#if FNMATCH_TEST -#include -#include -#else #include "includes.h" -#endif -/* - bugger. we need a separate wildcard routine for older versions - of the protocol. This is not yet perfect, but its a lot - better than what we had */ -static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, - const smb_ucs2_t *string) +static int null_match(const smb_ucs2_t *p) { - const smb_ucs2_t *p = pattern, *n = string; - smb_ucs2_t c; - - if (strcmp_wa(p, "?")==0 && strcmp_wa(n, ".")) goto match; - - while ((c = *p++)) { - switch (c) { - case UCS2_CHAR('.'): - if (! *n) goto next; - if (*n != UCS2_CHAR('.')) goto nomatch; - n++; - break; - - case UCS2_CHAR('?'): - if (! *n) goto next; - if ((*n == UCS2_CHAR('.') && - n[1] != UCS2_CHAR('.')) || ! *n) - goto next; - n++; - break; - - case UCS2_CHAR('>'): - if (! *n) goto next; - if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; - goto nomatch; - } - n++; - break; - - case UCS2_CHAR('*'): - if (! *n) goto next; - if (! *p) goto match; - for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; - } - break; - - case UCS2_CHAR('<'): - for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; - if (*n == UCS2_CHAR('.') && - !strchr_w(n+1,UCS2_CHAR('.'))) { - n++; - break; - } - } - break; - - case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; - if (*n != UCS2_CHAR('.')) goto nomatch; - n++; - break; - - default: - if (c != *n && - toupper_w(c) != toupper_w(*n)) goto nomatch; - n++; - } + for (;*p;p++) { + if (*p != UCS2_CHAR('*') && + *p != UCS2_CHAR('<') && + *p != UCS2_CHAR('"') && + *p != UCS2_CHAR('>')) return -1; } - - if (! *n) goto match; - - nomatch: - /* - if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string); - */ - return -1; - -next: - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; - goto nomatch; - - match: - /* - if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string); - */ return 0; } -static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) -{ - if (!strpbrk_wa(pattern, "?*<>\"")) { - smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; - if (strcmp_wa(string,"..") == 0) string = s; - return strcasecmp_w(pattern, string); - } - - if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { - smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; - smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; - return ms_fnmatch_lanman_core(pattern, dotdot) && - ms_fnmatch_lanman_core(pattern, dot); - } - - return ms_fnmatch_lanman_core(pattern, string); -} - - -/* the following function was derived using the masktest utility - - after years of effort we finally have a perfect MS wildcard - matching routine! +/* + the max_n structure is purely for efficiency, it doesn't contribute + to the matching algorithm except by ensuring that the algorithm does + not grow exponentially +*/ +struct max_n { + const smb_ucs2_t *predot; + const smb_ucs2_t *postdot; +}; - NOTE: this matches only filenames with no directory component - Returns 0 on match, -1 on fail. +/* + p and n are the pattern and string being matched. The max_n array is + an optimisation only. The ldot pointer is NULL if the string does + not contain a '.', otherwise it points at the last dot in 'n'. */ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, - enum protocol_types protocol) +static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, + struct max_n *max_n, const smb_ucs2_t *ldot) { - const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; - - if (protocol <= PROTOCOL_LANMAN2) { - return ms_fnmatch_lanman1(pattern, string); - } + int i; while ((c = *p++)) { switch (c) { - case UCS2_CHAR('?'): - if (! *n) return -1; - n++; - break; + /* a '*' matches zero or more characters of any type */ + case UCS2_CHAR('*'): + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + for (i=0; n[i]; i++) { + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { + return 0; + } + } + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); - case UCS2_CHAR('>'): - if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + /* a '<' matches zero or more characters of + any type, but stops matching at the last + '.' in the string. */ + case UCS2_CHAR('<'): + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + if (max_n->postdot && max_n->postdot <= n && n <= ldot) { return -1; } - if (! *n) return ms_fnmatch_w(p, n, protocol); - n++; - break; - - case UCS2_CHAR('*'): - while (*p == UCS2_CHAR('*')) { - p++; + for (i=0; n[i]; i++) { + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; + if (n+i == ldot) { + if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot) == 0) return 0; + if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; + return -1; + } } - for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); + + /* a '?' matches any single character */ + case UCS2_CHAR('?'): + if (! *n) { + return -1; } + n++; break; - case UCS2_CHAR('<'): - for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; - if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { - n++; - break; + /* a '?' matches any single character */ + case UCS2_CHAR('>'): + if (n[0] == UCS2_CHAR('.')) { + if (! n[1] && null_match(p) == 0) { + return 0; } + break; } + if (! *n) return null_match(p); + n++; break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n == 0 && null_match(p) == 0) { + return 0; + } if (*n != UCS2_CHAR('.')) return -1; n++; break; default: - if (c != *n && - toupper_w(c) != toupper_w(*n)) return -1; + if (c != *n && toupper_w(c) != toupper_w(*n)) { + return -1; + } n++; + break; } } - if (! *n) return 0; + if (! *n) { + return 0; + } return -1; } - int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) { wpstring p, s; - int ret; + int ret, count, i; + struct max_n *max_n = NULL; + + if (strcmp(string, "..") == 0) { + string = "."; + } pstrcpy_wa(p, pattern); pstrcpy_wa(s, string); - ret = ms_fnmatch_w(p, s, protocol); -/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ + if (protocol <= PROTOCOL_LANMAN2) { + /* + for older negotiated protocols it is possible to + translate the pattern to produce a "new style" + pattern that exactly matches w2k behaviour + */ + for (i=0;p[i];i++) { + if (p[i] == UCS2_CHAR('?')) { + p[i] = UCS2_CHAR('>'); + } else if (p[i] == UCS2_CHAR('.') && + (p[i+1] == UCS2_CHAR('?') || + p[i+1] == UCS2_CHAR('*') || + p[i+1] == 0)) { + p[i] = UCS2_CHAR('"'); + } else if (p[i] == UCS2_CHAR('*') && p[i+1] == UCS2_CHAR('.')) { + p[i] = UCS2_CHAR('<'); + } + } + } + + for (count=i=0;p[i];i++) { + if (p[i] == UCS2_CHAR('*') || p[i] == UCS2_CHAR('<')) count++; + } + + max_n = talloc_array_p(NULL, struct max_n, count); + if (!max_n) { + return -1; + } + memset(max_n, 0, sizeof(struct max_n) * count); + + ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.'))); + + talloc_free(max_n); + return ret; } + /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { -- cgit From 6185fbad47e63f64599582ec9246f2df7c416942 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 05:09:16 +0000 Subject: r2776: if there are no wildcard characters then use StrCaseCmp() note that this is not just an optimisation, it fixes a rare edge case when LANMAN1 is negotiated (This used to be commit 8d879cf54c2fe09d62a5c28b02a070cb80984744) --- source4/lib/ms_fnmatch.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index d072eb6a50..507d2aea4a 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -150,6 +150,12 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot string = "."; } + if (strpbrk(pattern, "<>*?\"") == NULL) { + /* this is not just an optmisation - it is essential + for LANMAN1 correctness */ + return StrCaseCmp(pattern, string); + } + pstrcpy_wa(p, pattern); pstrcpy_wa(s, string); -- cgit From 20c550d87fae703dd8b84cb8f97c3bd32054d35a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 12:14:23 +0000 Subject: r2783: got rid of the unused remote architecture detection code (This used to be commit 9a04664531601b8251dbf6a0922ab48e675adb90) --- source4/lib/util.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 2862a40bd7..94b01f7501 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -575,46 +575,6 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) return(True); } -/******************************************************************* - Set the remote_arch string based on an enum. This is used in places -where we desperately need to distinguish client type. -********************************************************************/ -void set_remote_arch(struct smbsrv_connection *smb, enum remote_arch_types type) -{ - const char *arch; - - smb->negotiate.ra_type = type; - switch (type) { - case RA_WFWG: - arch = "WfWg"; - return; - case RA_OS2: - arch = "OS2"; - return; - case RA_WIN95: - arch = "Win95"; - return; - case RA_WINNT: - arch = "WinNT"; - return; - case RA_WIN2K: - arch = "Win2K"; - return; - case RA_WINXP: - arch = "WinXP"; - return; - case RA_SAMBA: - arch = "Samba"; - return; - default: - smb->negotiate.ra_type = RA_UNKNOWN; - arch = "UNKNOWN"; - break; - } - - sub_set_remote_arch(arch); -} - static void print_asc(int level, const uint8_t *buf,int len) { -- cgit From 15b9736ed30d8e947dbe2513dd9cf27d5b3761af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 3 Oct 2004 00:04:30 +0000 Subject: r2791: got rid of talloc_unreference() and instead created talloc_unlink(), which is much clearer and simpler to use. It removes a specific parent from a pointer, no matter whether that parent is a "reference" or a direct parent. This gives complete control over the free process. (This used to be commit 6c563887f1b9b8c842309a523e88b6f2a32db10f) --- source4/lib/talloc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 4032039142..fc65546063 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -241,7 +241,7 @@ void *talloc_reference(const void *context, const void *ptr) talloc_reference() has done. The context and pointer arguments must match those given to a talloc_reference() */ -void *talloc_unreference(const void *context, const void *ptr) +static int talloc_unreference(const void *context, const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *h; @@ -255,13 +255,58 @@ void *talloc_unreference(const void *context, const void *ptr) if ((p==NULL && context==NULL) || p+1 == context) break; } if (h == NULL) { - return NULL; + return -1; } talloc_set_destructor(h, NULL); _TLIST_REMOVE(tc->refs, h); talloc_free(h); - return discard_const_p(void, ptr); + return 0; +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return talloc_free(ptr); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = new_p+1; + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + talloc_steal(new_parent, ptr); + + return 0; } /* -- cgit From 1429ed54f14055a1a9399452cb6cfc94f9451cf5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 3 Oct 2004 06:39:19 +0000 Subject: r2792: got rid of talloc_ldb_alloc() and instead created talloc_realloc_fn(), so talloc now doesn't contain any ldb specific functions. allow NULL to be passed to a couple more talloc() functions (This used to be commit 1246f80d806fb5f63cfbf3879de6d546384552a8) --- source4/lib/ldb/common/ldb_alloc.c | 4 ++-- source4/lib/ldb/include/ldb.h | 4 ++-- source4/lib/talloc.c | 23 +++++++++++++---------- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_alloc.c b/source4/lib/ldb/common/ldb_alloc.c index 6abd6fa8c3..0053c5e73f 100644 --- a/source4/lib/ldb/common/ldb_alloc.c +++ b/source4/lib/ldb/common/ldb_alloc.c @@ -39,7 +39,7 @@ this allows the user to choose their own allocation function */ int ldb_set_alloc(struct ldb_context *ldb, - void *(*alloc)(void *context, void *ptr, size_t size), + void *(*alloc)(const void *context, void *ptr, size_t size), void *context) { ldb->alloc_ops.alloc = alloc; @@ -50,7 +50,7 @@ int ldb_set_alloc(struct ldb_context *ldb, /* this is the default memory allocation function */ -static void *ldb_default_alloc(void *context, void *ptr, size_t size) +static void *ldb_default_alloc(const void *context, void *ptr, size_t size) { /* by setting LDB_ALLOC_OFS to non-zero the test suite can catch any places where we incorrectly use the libc alloc diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 241f186991..4b1401f673 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -145,7 +145,7 @@ struct ldb_backend_ops { for pool allocators */ struct ldb_alloc_ops { - void *(*alloc)(void *context, void *ptr, size_t size); + void *(*alloc)(const void *context, void *ptr, size_t size); void *context; }; @@ -320,7 +320,7 @@ const char *ldb_msg_find_string(const struct ldb_message *msg, which often take a context argument */ int ldb_set_alloc(struct ldb_context *ldb, - void *(*alloc)(void *context, void *ptr, size_t size), + void *(*alloc)(const void *context, void *ptr, size_t size), void *context); /* diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index fc65546063..5c1f3e7dcd 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -273,6 +273,10 @@ int talloc_unlink(const void *context, void *ptr) struct talloc_chunk *tc_p, *new_p; void *new_parent; + if (context == NULL) { + context = null_context; + } + if (talloc_unreference(context, ptr) == 0) { return 0; } @@ -561,6 +565,10 @@ void *talloc_steal(const void *new_ctx, const void *ptr) return NULL; } + if (new_ctx == NULL) { + new_ctx = null_context; + } + tc = talloc_chunk_from_ptr(ptr); if (new_ctx == NULL) { @@ -948,16 +956,11 @@ void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned } /* - a alloc function for ldb that uses talloc + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) */ -void *talloc_ldb_alloc(void *context, void *ptr, size_t size) +void *talloc_realloc_fn(const void *context, void *ptr, size_t size) { - if (ptr == NULL) { - return talloc(context, size); - } - if (size == 0) { - talloc_free(ptr); - return NULL; - } - return talloc_realloc(context, ptr, size); + return _talloc_realloc(context, ptr, size, NULL); } -- cgit From 7d32679e9683c81aca538f0267684332a28a286f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Oct 2004 08:13:00 +0000 Subject: r2857: this commit gets rid of smb_ucs2_t, wpstring and fpstring, plus lots of associated functions. The motivation for this change was to avoid having to convert to/from ucs2 strings for so many operations. Doing that was slow, used many static buffers, and was also incorrect as it didn't cope properly with unicode codepoints above 65536 (which could not be represented correctly as smb_ucs2_t chars) The two core functions that allowed this change are next_codepoint() and push_codepoint(). These functions allow you to correctly walk a arbitrary multi-byte string a character at a time without converting the whole string to ucs2. While doing this cleanup I also fixed several ucs2 string handling bugs. See the commit for details. The following code (which counts the number of occuraces of 'c' in a string) shows how to use the new interface: size_t count_chars(const char *s, char c) { size_t count = 0; while (*s) { size_t size; codepoint_t c2 = next_codepoint(s, &size); if (c2 == c) count++; s += size; } return count; } (This used to be commit 814881f0e50019196b3aa9fbe4aeadbb98172040) --- source4/lib/basic.mk | 1 + source4/lib/charcnv.c | 204 +++++-- source4/lib/cmdline/popt_common.c | 18 +- source4/lib/iconv.c | 2 +- source4/lib/ms_fnmatch.c | 99 ++-- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 8 +- source4/lib/util_str.c | 631 +++++---------------- source4/lib/util_strlist.c | 323 +++++++++++ source4/lib/util_unistr.c | 225 ++------ 9 files changed, 759 insertions(+), 752 deletions(-) create mode 100644 source4/lib/util_strlist.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index ccd0935407..f8bb46a95d 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -24,6 +24,7 @@ ADD_OBJ_FILES = \ lib/xfile.o \ lib/wins_srv.o \ lib/util_str.o \ + lib/util_strlist.o \ lib/util_sid.o \ lib/util_secdesc.o \ lib/util_uuid.o \ diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 7d00c7e78f..392ad3cc72 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -55,18 +55,6 @@ static const char *charset_name(charset_t ch) return ret; } -static void lazy_initialize_conv(void) -{ - static int initialized = False; - - if (!initialized) { - initialized = True; - load_case_tables(); - init_iconv(); - } -} - - static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; /* @@ -107,6 +95,7 @@ void init_iconv(void) } + /** * Convert string from one encoding to another, making error checking etc * @@ -129,8 +118,6 @@ ssize_t convert_string(charset_t from, charset_t to, if (srclen == (size_t)-1) srclen = strlen(src)+1; - lazy_initialize_conv(); - descriptor = get_conv_handle(from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { @@ -194,8 +181,6 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, if (src == NULL || srclen == (size_t)-1 || srclen == 0) return (size_t)-1; - lazy_initialize_conv(); - descriptor = get_conv_handle(from, to); if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { @@ -271,27 +256,27 @@ ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) { size_t src_len; ssize_t ret; - char *tmpbuf = NULL; - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); if (flags & STR_UPPER) { - tmpbuf = strupper_talloc(NULL, src); - if (!tmpbuf) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { return -1; } - src = tmpbuf; + ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; } + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + src_len = strlen(src); if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; - ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); - talloc_free(tmpbuf); - return ret; + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); } /** @@ -375,6 +360,16 @@ ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) size_t src_len = strlen(src); size_t ret; + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return -1; + } + ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; + } + /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); @@ -399,17 +394,6 @@ ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) len += ret; - if (flags & STR_UPPER) { - smb_ucs2_t *dest_ucs2 = dest; - size_t i; - for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { - smb_ucs2_t v = toupper_w(dest_ucs2[i]); - if (v != dest_ucs2[i]) { - dest_ucs2[i] = v; - } - } - } - return len; } @@ -423,12 +407,11 @@ ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) * @returns The number of bytes occupied by the string in the destination * or -1 in case of error. **/ -ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src) +ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) { size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest); + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); } @@ -474,12 +457,9 @@ size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, i if (flags & STR_TERMINATE) { if (src_len == (size_t)-1) { - src_len = strlen_w(src)*2 + 2; + src_len = utf16_len(src); } else { - size_t len = strnlen_w(src, src_len/2); - if (len < src_len/2) - len++; - src_len = len*2; + src_len = utf16_len_n(src, src_len); } } @@ -507,9 +487,9 @@ ssize_t pull_ucs2_pstring(char *dest, const void *src) * @returns The number of bytes occupied by the string in the destination **/ -ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src) +ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) { - size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); + size_t src_len = utf16_len(src); *dest = NULL; return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); } @@ -582,3 +562,131 @@ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len } } + +/* + return the unicode codepoint for the next multi-byte CH_UNIX character + in the string + + also return the number of bytes consumed (which tells the caller + how many bytes to skip to get to the next CH_UNIX character) + + return INVALID_CODEPOINT if the next character cannot be converted +*/ +codepoint_t next_codepoint(const char *str, size_t *size) +{ + /* it cannot occupy more than 4 bytes in UTF16 format */ + uint8_t buf[4]; + smb_iconv_t descriptor; + size_t ilen_orig; + size_t ilen; + size_t olen; + char *outbuf; + + if ((str[0] & 0x80) == 0) { + *size = 1; + return (codepoint_t)str[0]; + } + + /* we assume that no multi-byte character can take + more than 5 bytes. This is OK as we only + support codepoints up to 1M */ + ilen_orig = strnlen(str, 5); + ilen = ilen_orig; + + descriptor = get_conv_handle(CH_UNIX, CH_UTF16); + if (descriptor == (smb_iconv_t)-1) { + *size = 1; + return INVALID_CODEPOINT; + } + + /* this looks a little strange, but it is needed to cope + with codepoints above 64k */ + olen = 2; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 2) { + olen = 4; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 4) { + /* we didn't convert any bytes */ + *size = 1; + return INVALID_CODEPOINT; + } + olen = 4 - olen; + } else { + olen = 2 - olen; + } + + *size = ilen_orig - ilen; + + if (olen == 2) { + return (codepoint_t)SVAL(buf, 0); + } + if (olen == 4) { + /* decode a 4 byte UTF16 character manually */ + return (codepoint_t)0x10000 + + (buf[2] | ((buf[3] & 0x3)<<8) | + (buf[0]<<10) | ((buf[1] & 0x3)<<18)); + } + + /* no other length is valid */ + return INVALID_CODEPOINT; +} + +/* + push a single codepoint into a CH_UNIX string the target string must + be able to hold the full character, which is guaranteed if it is at + least 5 bytes in size. The caller may pass less than 5 bytes if they + are sure the character will fit (for example, you can assume that + uppercase/lowercase of a character will not add more than 1 byte) + + return the number of bytes occupied by the CH_UNIX character, or + -1 on failure +*/ +ssize_t push_codepoint(char *str, codepoint_t c) +{ + smb_iconv_t descriptor; + uint8_t buf[4]; + size_t ilen, olen; + const char *inbuf; + + if (c < 128) { + *str = c; + return 1; + } + + descriptor = get_conv_handle(CH_UTF16, CH_UNIX); + if (descriptor == (smb_iconv_t)-1) { + return -1; + } + + if (c < 0x10000) { + ilen = 2; + olen = 5; + inbuf = buf; + SSVAL(buf, 0, c); + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; + } + + c -= 0x10000; + + buf[0] = (c>>10) & 0xFF; + buf[1] = (c>>18) | 0xd8; + buf[2] = c & 0xFF; + buf[3] = ((c>>8) & 0x3) | 0xdc; + + ilen = 4; + olen = 5; + inbuf = buf; + + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; +} diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 725a5060c0..554b46a940 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -391,8 +391,8 @@ static void popt_common_credentials_callback(poptContext con, d_printf("ERROR: Unable to fetch machine password\n"); exit(1); } - pstr_sprintf(cmdline_auth_info.username, "%s$", - lp_netbios_name()); + snprintf(cmdline_auth_info.username, sizeof(cmdline_auth_info.username), + "%s$", lp_netbios_name()); pstrcpy(cmdline_auth_info.password,opt_password); SAFE_FREE(opt_password); @@ -451,17 +451,21 @@ const char *cmdline_get_userdomain(void) const char *cmdline_get_userpassword(void) { - pstring prompt; + char *prompt; + char *ret; if (cmdline_auth_info.got_pass) { return cmdline_auth_info.password; } - pstr_sprintf(prompt, "Password for [%s\\%s]:", - cmdline_get_userdomain(), - cmdline_get_username()); + prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", + cmdline_get_userdomain(), + cmdline_get_username()); - return getpass(prompt); + ret = getpass(prompt); + + talloc_free(prompt); + return ret; } void cmdline_set_userpassword(const char *pass) diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 567f5b5902..f4f7660bcd 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -113,7 +113,7 @@ static size_t sys_iconv(void *cd, char **outbuf, size_t *outbytesleft) { size_t ret = iconv((iconv_t)cd, - inbuf, inbytesleft, + discard_const_p(char *, inbuf), inbytesleft, outbuf, outbytesleft); if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); return ret; diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index 507d2aea4a..386dac4ea3 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -27,13 +27,13 @@ #include "includes.h" -static int null_match(const smb_ucs2_t *p) +static int null_match(const char *p) { for (;*p;p++) { - if (*p != UCS2_CHAR('*') && - *p != UCS2_CHAR('<') && - *p != UCS2_CHAR('"') && - *p != UCS2_CHAR('>')) return -1; + if (*p != '*' && + *p != '<' && + *p != '"' && + *p != '>') return -1; } return 0; } @@ -44,8 +44,8 @@ static int null_match(const smb_ucs2_t *p) not grow exponentially */ struct max_n { - const smb_ucs2_t *predot; - const smb_ucs2_t *postdot; + const char *predot; + const char *postdot; }; @@ -54,20 +54,24 @@ struct max_n { an optimisation only. The ldot pointer is NULL if the string does not contain a '.', otherwise it points at the last dot in 'n'. */ -static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, - struct max_n *max_n, const smb_ucs2_t *ldot) +static int ms_fnmatch_core(const char *p, const char *n, + struct max_n *max_n, const char *ldot) { - smb_ucs2_t c; + codepoint_t c, c2; int i; + size_t size, size_n; + + while ((c = next_codepoint(p, &size))) { + p += size; - while ((c = *p++)) { switch (c) { + case '*': /* a '*' matches zero or more characters of any type */ - case UCS2_CHAR('*'): if (max_n->predot && max_n->predot <= n) { return null_match(p); } - for (i=0; n[i]; i++) { + for (i=0; n[i]; i += size_n) { + next_codepoint(n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { return 0; } @@ -75,20 +79,21 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, if (!max_n->predot || max_n->predot > n) max_n->predot = n; return null_match(p); + case '<': /* a '<' matches zero or more characters of any type, but stops matching at the last '.' in the string. */ - case UCS2_CHAR('<'): if (max_n->predot && max_n->predot <= n) { return null_match(p); } if (max_n->postdot && max_n->postdot <= n && n <= ldot) { return -1; } - for (i=0; n[i]; i++) { + for (i=0; n[i]; i += size_n) { + next_codepoint(n+i, &size_n); if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; if (n+i == ldot) { - if (ms_fnmatch_core(p, n+i+1, max_n+1, ldot) == 0) return 0; + if (ms_fnmatch_core(p, n+i+size_n, max_n+1, ldot) == 0) return 0; if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; return -1; } @@ -96,39 +101,45 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, if (!max_n->predot || max_n->predot > n) max_n->predot = n; return null_match(p); + case '?': /* a '?' matches any single character */ - case UCS2_CHAR('?'): if (! *n) { return -1; } - n++; + next_codepoint(n, &size_n); + n += size_n; break; - /* a '?' matches any single character */ - case UCS2_CHAR('>'): - if (n[0] == UCS2_CHAR('.')) { + case '>': + /* a '?' matches any single character, but + treats '.' specially */ + if (n[0] == '.') { if (! n[1] && null_match(p) == 0) { return 0; } break; } if (! *n) return null_match(p); - n++; + next_codepoint(n, &size_n); + n += size_n; break; - case UCS2_CHAR('"'): + case '"': + /* a bit like a soft '.' */ if (*n == 0 && null_match(p) == 0) { return 0; } - if (*n != UCS2_CHAR('.')) return -1; - n++; + if (*n != '.') return -1; + next_codepoint(n, &size_n); + n += size_n; break; default: - if (c != *n && toupper_w(c) != toupper_w(*n)) { + c2 = next_codepoint(n, &size_n); + if (c != c2 && codepoint_cmpi(c, c2) != 0) { return -1; } - n++; + n += size_n; break; } } @@ -142,7 +153,6 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) { - wpstring p, s; int ret, count, i; struct max_n *max_n = NULL; @@ -156,31 +166,36 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot return StrCaseCmp(pattern, string); } - pstrcpy_wa(p, pattern); - pstrcpy_wa(s, string); - if (protocol <= PROTOCOL_LANMAN2) { + char *p = talloc_strdup(NULL, pattern); + if (p == NULL) { + return -1; + } /* for older negotiated protocols it is possible to translate the pattern to produce a "new style" pattern that exactly matches w2k behaviour */ for (i=0;p[i];i++) { - if (p[i] == UCS2_CHAR('?')) { - p[i] = UCS2_CHAR('>'); - } else if (p[i] == UCS2_CHAR('.') && - (p[i+1] == UCS2_CHAR('?') || - p[i+1] == UCS2_CHAR('*') || + if (p[i] == '?') { + p[i] = '>'; + } else if (p[i] == '.' && + (p[i+1] == '?' || + p[i+1] == '*' || p[i+1] == 0)) { - p[i] = UCS2_CHAR('"'); - } else if (p[i] == UCS2_CHAR('*') && p[i+1] == UCS2_CHAR('.')) { - p[i] = UCS2_CHAR('<'); + p[i] = '"'; + } else if (p[i] == '*' && + p[i+1] == '.') { + p[i] = '<'; } } + ret = ms_fnmatch(p, string, PROTOCOL_NT1); + talloc_free(p); + return ret; } - for (count=i=0;p[i];i++) { - if (p[i] == UCS2_CHAR('*') || p[i] == UCS2_CHAR('<')) count++; + for (count=i=0;pattern[i];i++) { + if (pattern[i] == '*' || pattern[i] == '<') count++; } max_n = talloc_array_p(NULL, struct max_n, count); @@ -189,7 +204,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot } memset(max_n, 0, sizeof(struct max_n) * count); - ret = ms_fnmatch_core(p, s, max_n, strrchr_w(s, UCS2_CHAR('.'))); + ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.')); talloc_free(max_n); diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index c271c55991..14fff5b60d 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1029,7 +1029,7 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk uint_t nk_id; SK_HDR *sk_hdr; int type; - char key_name[1024], cls_name[1024]; + char key_name[1024]; if (!nk_hdr) return WERR_INVALID_PARAM; @@ -1086,16 +1086,16 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk */ if (clsname_len) { /* Just print in Ascii for now */ - smb_ucs2_t *clsnamep; + void *clsnamep; int clsnam_off; clsnam_off = IVAL(&nk_hdr->clsnam_off,0); - clsnamep = (smb_ucs2_t *)LOCN(regf->base, clsnam_off); + clsnamep = LOCN(regf->base, clsnam_off); DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); - DEBUGADD(2,(" Class Name: %s\n", cls_name)); + DEBUGADD(2,(" Class Name: %s\n", tmp->class_name)); } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 0e58face16..c4c68a3dcd 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -74,54 +74,37 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) return(True); } -static uint16_t tmpbuf[sizeof(pstring)]; - - /** - Case insensitive string compararison. + Case insensitive string compararison **/ -static int StrCaseCmp_slow(const char *s1, const char *s2) +int StrCaseCmp(const char *s1, const char *s2) { - smb_ucs2_t *u1 = NULL; - smb_ucs2_t *u2; - int ret; - - if (convert_string_talloc(NULL, CH_UNIX, CH_UTF16, s1, strlen(s1)+1, (void **)&u1) == -1 || - convert_string_talloc(u1, CH_UNIX, CH_UTF16, s2, strlen(s2)+1, (void **)&u2) == -1) { - talloc_free(u1); - /* fallback to a simple comparison */ - return strcasecmp(s1, s2); - } + codepoint_t c1=0, c2=0; + size_t size1, size2; - ret = strcasecmp_w(u1, u2); + while (*s1 && *s2) { + c1 = next_codepoint(s1, &size1); + c2 = next_codepoint(s2, &size2); - talloc_free(u1); + s1 += size1; + s2 += size2; - return ret; -} + if (c1 == c2) { + continue; + } -/** - Case insensitive string compararison, accelerated version -**/ -int StrCaseCmp(const char *s1, const char *s2) -{ - while (*s1 && *s2 && - (*s1 & 0x80) == 0 && - (*s2 & 0x80) == 0) { - char u1 = toupper(*s1); - char u2 = toupper(*s2); - if (u1 != u2) { - return u1 - u2; + if (c1 == INVALID_CODEPOINT || + c2 == INVALID_CODEPOINT) { + /* what else can we do?? */ + return c1 - c2; } - s1++; - s2++; - } - if (*s1 == 0 || *s2 == 0) { - return *s1 - *s2; + if (toupper_w(c1) != toupper_w(c2)) { + return c1 - c2; + } } - return StrCaseCmp_slow(s1, s2); + return *s1 - *s2; } /** @@ -136,27 +119,26 @@ BOOL strequal(const char *s1, const char *s2) if (!s1 || !s2) return(False); - return(StrCaseCmp(s1,s2)==0); + return StrCaseCmp(s1,s2) == 0; } /** Compare 2 strings (case sensitive). **/ - BOOL strcsequal(const char *s1,const char *s2) { - if (s1 == s2) - return(True); - if (!s1 || !s2) - return(False); - - return(strcmp(s1,s2)==0); + if (s1 == s2) + return(True); + if (!s1 || !s2) + return(False); + + return strcmp(s1,s2) == 0; } + /** Do a case-insensitive, whitespace-ignoring string compare. **/ - int strwicmp(const char *psz1, const char *psz2) { /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */ @@ -187,20 +169,21 @@ int strwicmp(const char *psz1, const char *psz2) String replace. NOTE: oldc and newc must be 7 bit characters **/ - -void string_replace(char *s,char oldc,char newc) +void string_replace(char *s, char oldc, char newc) { - if (strchr(s, oldc)) { - push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE); + while (*s) { + size_t size; + codepoint_t c = next_codepoint(s, &size); + if (c == oldc) { + *s = newc; + } + s += size; } } /** Trim the specified elements off the front and back of a string. **/ - BOOL trim_string(char *s,const char *front,const char *back) { BOOL ret = False; @@ -237,61 +220,27 @@ BOOL trim_string(char *s,const char *front,const char *back) return ret; } -/** - Does a string have any uppercase chars in it? -**/ - -BOOL strhasupper(const char *s) -{ - smb_ucs2_t *ptr; - push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - for(ptr=tmpbuf;*ptr;ptr++) - if(isupper_w(*ptr)) - return True; - return(False); -} - -/** - Does a string have any lowercase chars in it? -**/ - -BOOL strhaslower(const char *s) -{ - smb_ucs2_t *ptr; - push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); - for(ptr=tmpbuf;*ptr;ptr++) - if(islower_w(*ptr)) - return True; - return(False); -} - /** Find the number of 'c' chars in a string **/ - -size_t count_chars(const char *s,char c) +size_t count_chars(const char *s, char c) { - smb_ucs2_t *ptr; - int count; - smb_ucs2_t *alloc_tmpbuf = NULL; + size_t count = 0; - if (push_ucs2_talloc(NULL, &alloc_tmpbuf, s) == (size_t)-1) { - return 0; + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint(s, &size); + if (c2 == c) count++; + s += size; } - for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++) - if(*ptr==UCS2_CHAR(c)) - count++; - - talloc_free(alloc_tmpbuf); - return(count); + return count; } /** Safe string copy into a known length string. maxlength does not include the terminating zero. **/ - char *safe_strcpy(char *dest,const char *src, size_t maxlength) { size_t len; @@ -334,7 +283,6 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength) Safe string cat into a string. maxlength does not include the terminating zero. **/ - char *safe_strcat(char *dest, const char *src, size_t maxlength) { size_t src_len, dest_len; @@ -446,7 +394,6 @@ char *StrnCpy(char *dest,const char *src,size_t n) valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" **/ - size_t strhex_to_str(char *p, size_t len, const char *strhex) { size_t i; @@ -493,10 +440,10 @@ DATA_BLOB strhex_to_data_blob(const char *strhex) return ret_blob; } + /** * Routine to print a buffer as HEX digits, into an allocated string. */ - void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) { int i; @@ -512,7 +459,6 @@ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) /** Check if a string is part of a list. **/ - BOOL in_list(const char *s, const char *list, BOOL casesensitive) { pstring tok; @@ -681,36 +627,31 @@ const char *octal_string(int i) /** - Strchr and strrchr_m are very hard to do on general multi-byte strings. - We convert via ucs2 for now. + Strchr and strrchr_m are a bit complex on general multi-byte strings. **/ - char *strchr_m(const char *s, char c) { - wpstring ws; - pstring s2; - smb_ucs2_t *p; - /* characters below 0x3F are guaranteed to not appear in non-initial position in multi-byte charsets */ if ((c & 0xC0) == 0) { return strchr(s, c); } - push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); - p = strchr_w(ws, UCS2_CHAR(c)); - if (!p) - return NULL; - *p = 0; - pull_ucs2_pstring(s2, ws); - return discard_const_p(char, s+strlen(s2)); + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint(s, &size); + if (c2 == c) { + return discard_const(s); + } + s += size; + } + + return NULL; } char *strrchr_m(const char *s, char c) { - wpstring ws; - pstring s2; - smb_ucs2_t *p; + char *ret = NULL; /* characters below 0x3F are guaranteed to not appear in non-initial position in multi-byte charsets */ @@ -718,69 +659,99 @@ char *strrchr_m(const char *s, char c) return strrchr(s, c); } - push_ucs2(ws, s, sizeof(ws), STR_TERMINATE); - p = strrchr_w(ws, UCS2_CHAR(c)); - if (!p) - return NULL; - *p = 0; - pull_ucs2_pstring(s2, ws); - return discard_const_p(char, s+strlen(s2)); + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint(s, &size); + if (c2 == c) { + ret = discard_const(s); + } + s += size; + } + + return ret; } /** Convert a string to lower case, allocated with talloc **/ - char *strlower_talloc(TALLOC_CTX *ctx, const char *src) { - size_t size; - smb_ucs2_t *buffer; + size_t size=0; char *dest; - size = push_ucs2_talloc(ctx, &buffer, src); - if (size == -1) { + /* this takes advantage of the fact that upper/lower can't + change the length of a character by more than 1 byte */ + dest = talloc(ctx, 2*(strlen(src))+1); + if (dest == NULL) { return NULL; } - strlower_w(buffer); - size = pull_ucs2_talloc(ctx, &dest, buffer); - talloc_free(buffer); + while (*src) { + size_t c_size; + codepoint_t c = next_codepoint(src, &c_size); + src += c_size; + + c = tolower_w(c); + + c_size = push_codepoint(dest+size, c); + if (c_size == -1) { + talloc_free(dest); + return NULL; + } + size += c_size; + } + + dest[size] = 0; + return dest; } /** Convert a string to UPPER case, allocated with talloc **/ - char *strupper_talloc(TALLOC_CTX *ctx, const char *src) { - size_t size; - smb_ucs2_t *buffer; + size_t size=0; char *dest; - size = push_ucs2_talloc(ctx, &buffer, src); - if (size == -1) { + /* this takes advantage of the fact that upper/lower can't + change the length of a character by more than 1 byte */ + dest = talloc(ctx, 2*(strlen(src))+1); + if (dest == NULL) { return NULL; } - strupper_w(buffer); - size = pull_ucs2_talloc(ctx, &dest, buffer); - talloc_free(buffer); + while (*src) { + size_t c_size; + codepoint_t c = next_codepoint(src, &c_size); + src += c_size; + + c = toupper_w(c); + + c_size = push_codepoint(dest+size, c); + if (c_size == -1) { + talloc_free(dest); + return NULL; + } + size += c_size; + } + + dest[size] = 0; + return dest; } /** Convert a string to lower case. **/ - void strlower_m(char *s) { - char *lower; + char *d; + /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ - while (*s && !(((uint8_t)s[0]) & 0x7F)) { *s = tolower((uint8_t)*s); s++; @@ -789,27 +760,32 @@ void strlower_m(char *s) if (!*s) return; - /* I assume that lowercased string takes the same number of bytes - * as source string even in UTF-8 encoding. (VIV) */ - lower = strlower_talloc(NULL, s); - if (lower) { - safe_strcpy(s, lower, strlen(s)); + d = s; + + while (*s) { + size_t c_size, c_size2; + codepoint_t c = next_codepoint(s, &c_size); + c_size2 = push_codepoint(d, tolower_w(c)); + if (c_size2 > c_size) { + smb_panic("codepoint expansion in strlower_m\n"); + } + s += c_size; + d += c_size2; } - talloc_free(lower); + *d = 0; } /** Convert a string to UPPER case. **/ - void strupper_m(char *s) { - char *upper; + char *d; + /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ - while (*s && !(((uint8_t)s[0]) & 0x7F)) { *s = toupper((uint8_t)*s); s++; @@ -818,13 +794,19 @@ void strupper_m(char *s) if (!*s) return; - /* I assume that uppercased string takes the same number of bytes - * as source string even in UTF-8 encoding. (VIV) */ - upper = strupper_talloc(NULL, s); - if (upper) { - safe_strcpy(s, upper, strlen(s)); + d = s; + + while (*s) { + size_t c_size, c_size2; + codepoint_t c = next_codepoint(s, &c_size); + c_size2 = push_codepoint(d, toupper_w(c)); + if (c_size2 > c_size) { + smb_panic("codepoint expansion in strupper_m\n"); + } + s += c_size; + d += c_size2; } - talloc_free(upper); + *d = 0; } /** @@ -832,13 +814,9 @@ void strupper_m(char *s) be the same as the number of bytes in a string for single byte strings, but will be different for multibyte. **/ - size_t strlen_m(const char *s) { size_t count = 0; - smb_ucs2_t *tmp; - - size_t len; if (!s) { return 0; @@ -853,12 +831,18 @@ size_t strlen_m(const char *s) return count; } - SMB_ASSERT(push_ucs2_talloc(NULL, &tmp, s) != -1); - - len = count + strlen_w(tmp); - talloc_free(tmp); + while (*s) { + size_t c_size; + codepoint_t c = next_codepoint(s, &c_size); + if (c < 0x10000) { + count += 1; + } else { + count += 2; + } + s += c_size; + } - return len; + return count; } /** @@ -879,7 +863,6 @@ size_t strlen_m_term(const char *s) Used in LDAP filters. Caller must free. **/ - char *binary_string(char *buf, int len) { char *s; @@ -898,21 +881,6 @@ char *binary_string(char *buf, int len) return s; } -/** - Just a typesafety wrapper for snprintf into a pstring. -**/ - - int pstr_sprintf(pstring s, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vsnprintf(s, PSTRING_LEN, fmt, ap); - va_end(ap); - return ret; -} - #ifndef HAVE_STRNDUP /** Some platforms don't have strndup. @@ -945,305 +913,6 @@ char *binary_string(char *buf, int len) } #endif -/** - List of Strings manipulation functions -**/ - -#define S_LIST_ABS 16 /* List Allocation Block Size */ - -char **str_list_make(const char *string, const char *sep) -{ - char **list, **rlist; - const char *str; - char *s; - int num, lsize; - pstring tok; - - if (!string || !*string) - return NULL; - s = strdup(string); - if (!s) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - return NULL; - } - if (!sep) sep = LIST_SEP; - - num = lsize = 0; - list = NULL; - - str = s; - while (next_token(&str, tok, sep, sizeof(tok))) { - if (num == lsize) { - lsize += S_LIST_ABS; - rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); - if (!rlist) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - str_list_free(&list); - SAFE_FREE(s); - return NULL; - } else - list = rlist; - memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1))); - } - - list[num] = strdup(tok); - if (!list[num]) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - str_list_free(&list); - SAFE_FREE(s); - return NULL; - } - - num++; - } - - SAFE_FREE(s); - return list; -} - -BOOL str_list_copy(char ***dest, const char **src) -{ - char **list, **rlist; - int num, lsize; - - *dest = NULL; - if (!src) - return False; - - num = lsize = 0; - list = NULL; - - while (src[num]) { - if (num == lsize) { - lsize += S_LIST_ABS; - rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); - if (!rlist) { - DEBUG(0,("str_list_copy: Unable to re-allocate memory")); - str_list_free(&list); - return False; - } else - list = rlist; - memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1))); - } - - list[num] = strdup(src[num]); - if (!list[num]) { - DEBUG(0,("str_list_copy: Unable to allocate memory")); - str_list_free(&list); - return False; - } - - num++; - } - - *dest = list; - return True; -} - -/** - * Return true if all the elements of the list match exactly. - **/ -BOOL str_list_compare(char **list1, char **list2) -{ - int num; - - if (!list1 || !list2) - return (list1 == list2); - - for (num = 0; list1[num]; num++) { - if (!list2[num]) - return False; - if (!strcsequal(list1[num], list2[num])) - return False; - } - if (list2[num]) - return False; /* if list2 has more elements than list1 fail */ - - return True; -} - -void str_list_free(char ***list) -{ - char **tlist; - - if (!list || !*list) - return; - tlist = *list; - for(; *tlist; tlist++) - SAFE_FREE(*tlist); - SAFE_FREE(*list); -} - -BOOL str_list_substitute(char **list, const char *pattern, const char *insert) -{ - char *p, *s, *t; - ssize_t ls, lp, li, ld, i, d; - - if (!list) - return False; - if (!pattern) - return False; - if (!insert) - return False; - - lp = (ssize_t)strlen(pattern); - li = (ssize_t)strlen(insert); - ld = li -lp; - - while (*list) { - s = *list; - ls = (ssize_t)strlen(s); - - while ((p = strstr(s, pattern))) { - t = *list; - d = p -t; - if (ld) { - t = (char *) malloc(ls +ld +1); - if (!t) { - DEBUG(0,("str_list_substitute: Unable to allocate memory")); - return False; - } - memcpy(t, *list, d); - memcpy(t +d +li, p +lp, ls -d -lp +1); - SAFE_FREE(*list); - *list = t; - ls += ld; - s = t +d +li; - } - - for (i = 0; i < li; i++) { - switch (insert[i]) { - case '`': - case '"': - case '\'': - case ';': - case '$': - case '%': - case '\r': - case '\n': - t[d +i] = '_'; - break; - default: - t[d +i] = insert[i]; - } - } - } - - list++; - } - - return True; -} - - -#define IPSTR_LIST_SEP "," - -/** - * Add ip string representation to ipstr list. Used also - * as part of @function ipstr_list_make - * - * @param ipstr_list pointer to string containing ip list; - * MUST BE already allocated and IS reallocated if necessary - * @param ipstr_size pointer to current size of ipstr_list (might be changed - * as a result of reallocation) - * @param ip IP address which is to be added to list - * @return pointer to string appended with new ip and possibly - * reallocated to new length - **/ - -char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) -{ - char* new_ipstr = NULL; - - /* arguments checking */ - if (!ipstr_list || !ip) return NULL; - - /* attempt to convert ip to a string and append colon separator to it */ - if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip)); - SAFE_FREE(*ipstr_list); - } else { - asprintf(&new_ipstr, "%s", inet_ntoa(*ip)); - } - *ipstr_list = new_ipstr; - return *ipstr_list; -} - -/** - * Allocate and initialise an ipstr list using ip adresses - * passed as arguments. - * - * @param ipstr_list pointer to string meant to be allocated and set - * @param ip_list array of ip addresses to place in the list - * @param ip_count number of addresses stored in ip_list - * @return pointer to allocated ip string - **/ - -char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count) -{ - int i; - - /* arguments checking */ - if (!ip_list && !ipstr_list) return 0; - - *ipstr_list = NULL; - - /* process ip addresses given as arguments */ - for (i = 0; i < ip_count; i++) - *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]); - - return (*ipstr_list); -} - - -/** - * Parse given ip string list into array of ip addresses - * (as in_addr structures) - * - * @param ipstr ip string list to be parsed - * @param ip_list pointer to array of ip addresses which is - * allocated by this function and must be freed by caller - * @return number of succesfully parsed addresses - **/ - -int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) -{ - fstring token_str; - int count; - - if (!ipstr_list || !ip_list) return 0; - - for (*ip_list = NULL, count = 0; - next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); - count++) { - - struct in_addr addr; - - /* convert single token to ip address */ - if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE ) - break; - - /* prepare place for another in_addr structure */ - *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr)); - if (!*ip_list) return -1; - - (*ip_list)[count] = addr; - } - - return count; -} - - -/** - * Safely free ip string list - * - * @param ipstr_list ip string list to be freed - **/ - -void ipstr_list_free(char* ipstr_list) -{ - SAFE_FREE(ipstr_list); -} /** Unescape a URL encoded string, in place. diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c new file mode 100644 index 0000000000..12fb0946e2 --- /dev/null +++ b/source4/lib/util_strlist.c @@ -0,0 +1,323 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1992-2004 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + List of Strings manipulation functions +**/ + +#define S_LIST_ABS 16 /* List Allocation Block Size */ + +char **str_list_make(const char *string, const char *sep) +{ + char **list, **rlist; + const char *str; + char *s; + int num, lsize; + pstring tok; + + if (!string || !*string) + return NULL; + s = strdup(string); + if (!s) { + DEBUG(0,("str_list_make: Unable to allocate memory")); + return NULL; + } + if (!sep) sep = LIST_SEP; + + num = lsize = 0; + list = NULL; + + str = s; + while (next_token(&str, tok, sep, sizeof(tok))) { + if (num == lsize) { + lsize += S_LIST_ABS; + rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); + if (!rlist) { + DEBUG(0,("str_list_make: Unable to allocate memory")); + str_list_free(&list); + SAFE_FREE(s); + return NULL; + } else + list = rlist; + memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1))); + } + + list[num] = strdup(tok); + if (!list[num]) { + DEBUG(0,("str_list_make: Unable to allocate memory")); + str_list_free(&list); + SAFE_FREE(s); + return NULL; + } + + num++; + } + + SAFE_FREE(s); + return list; +} + +BOOL str_list_copy(char ***dest, const char **src) +{ + char **list, **rlist; + int num, lsize; + + *dest = NULL; + if (!src) + return False; + + num = lsize = 0; + list = NULL; + + while (src[num]) { + if (num == lsize) { + lsize += S_LIST_ABS; + rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); + if (!rlist) { + DEBUG(0,("str_list_copy: Unable to re-allocate memory")); + str_list_free(&list); + return False; + } else + list = rlist; + memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1))); + } + + list[num] = strdup(src[num]); + if (!list[num]) { + DEBUG(0,("str_list_copy: Unable to allocate memory")); + str_list_free(&list); + return False; + } + + num++; + } + + *dest = list; + return True; +} + +/** + Return true if all the elements of the list match exactly. + **/ +BOOL str_list_compare(char **list1, char **list2) +{ + int num; + + if (!list1 || !list2) + return (list1 == list2); + + for (num = 0; list1[num]; num++) { + if (!list2[num]) + return False; + if (!strcsequal(list1[num], list2[num])) + return False; + } + if (list2[num]) + return False; /* if list2 has more elements than list1 fail */ + + return True; +} + +void str_list_free(char ***list) +{ + char **tlist; + + if (!list || !*list) + return; + tlist = *list; + for(; *tlist; tlist++) + SAFE_FREE(*tlist); + SAFE_FREE(*list); +} + +BOOL str_list_substitute(char **list, const char *pattern, const char *insert) +{ + char *p, *s, *t; + ssize_t ls, lp, li, ld, i, d; + + if (!list) + return False; + if (!pattern) + return False; + if (!insert) + return False; + + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); + ld = li -lp; + + while (*list) { + s = *list; + ls = (ssize_t)strlen(s); + + while ((p = strstr(s, pattern))) { + t = *list; + d = p -t; + if (ld) { + t = (char *) malloc(ls +ld +1); + if (!t) { + DEBUG(0,("str_list_substitute: Unable to allocate memory")); + return False; + } + memcpy(t, *list, d); + memcpy(t +d +li, p +lp, ls -d -lp +1); + SAFE_FREE(*list); + *list = t; + ls += ld; + s = t +d +li; + } + + for (i = 0; i < li; i++) { + switch (insert[i]) { + case '`': + case '"': + case '\'': + case ';': + case '$': + case '%': + case '\r': + case '\n': + t[d +i] = '_'; + break; + default: + t[d +i] = insert[i]; + } + } + } + + list++; + } + + return True; +} + + +#define IPSTR_LIST_SEP "," + +/** + * Add ip string representation to ipstr list. Used also + * as part of @function ipstr_list_make + * + * @param ipstr_list pointer to string containing ip list; + * MUST BE already allocated and IS reallocated if necessary + * @param ipstr_size pointer to current size of ipstr_list (might be changed + * as a result of reallocation) + * @param ip IP address which is to be added to list + * @return pointer to string appended with new ip and possibly + * reallocated to new length + **/ + +char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) +{ + char* new_ipstr = NULL; + + /* arguments checking */ + if (!ipstr_list || !ip) return NULL; + + /* attempt to convert ip to a string and append colon separator to it */ + if (*ipstr_list) { + asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip)); + SAFE_FREE(*ipstr_list); + } else { + asprintf(&new_ipstr, "%s", inet_ntoa(*ip)); + } + *ipstr_list = new_ipstr; + return *ipstr_list; +} + +/** + * Allocate and initialise an ipstr list using ip adresses + * passed as arguments. + * + * @param ipstr_list pointer to string meant to be allocated and set + * @param ip_list array of ip addresses to place in the list + * @param ip_count number of addresses stored in ip_list + * @return pointer to allocated ip string + **/ + +char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count) +{ + int i; + + /* arguments checking */ + if (!ip_list && !ipstr_list) return 0; + + *ipstr_list = NULL; + + /* process ip addresses given as arguments */ + for (i = 0; i < ip_count; i++) + *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]); + + return (*ipstr_list); +} + + +/** + * Parse given ip string list into array of ip addresses + * (as in_addr structures) + * + * @param ipstr ip string list to be parsed + * @param ip_list pointer to array of ip addresses which is + * allocated by this function and must be freed by caller + * @return number of succesfully parsed addresses + **/ + +int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) +{ + fstring token_str; + int count; + + if (!ipstr_list || !ip_list) return 0; + + for (*ip_list = NULL, count = 0; + next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); + count++) { + + struct in_addr addr; + + /* convert single token to ip address */ + if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE ) + break; + + /* prepare place for another in_addr structure */ + *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr)); + if (!*ip_list) return -1; + + (*ip_list)[count] = addr; + } + + return count; +} + + +/** + * Safely free ip string list + * + * @param ipstr_list ip string list to be freed + **/ + +void ipstr_list_free(char* ipstr_list) +{ + SAFE_FREE(ipstr_list); +} diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 713f50708b..8b7504986f 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -21,16 +21,16 @@ #include "includes.h" -/* these 3 tables define the unicode case handling. They are loaded +/* these 2 tables define the unicode case handling. They are loaded at startup either via mmap() or read() from the lib directory */ -static smb_ucs2_t *upcase_table; -static smb_ucs2_t *lowcase_table; +static void *upcase_table; +static void *lowcase_table; /******************************************************************* load the case handling tables ********************************************************************/ -void load_case_tables(void) +static void load_case_tables(void) { static int initialised; int i; @@ -56,14 +56,10 @@ void load_case_tables(void) smb_panic("No memory for upcase tables"); } for (i=0;i<0x10000;i++) { - smb_ucs2_t v; - SSVAL(&v, 0, i); - upcase_table[v] = i; + SSVAL(upcase_table, i*2, i); } for (i=0;i<256;i++) { - smb_ucs2_t v; - SSVAL(&v, 0, UCS2_CHAR(i)); - upcase_table[v] = UCS2_CHAR(islower(i)?toupper(i):i); + SSVAL(upcase_table, i*2, islower(i)?toupper(i):i); } } @@ -74,199 +70,79 @@ void load_case_tables(void) smb_panic("No memory for lowcase tables"); } for (i=0;i<0x10000;i++) { - smb_ucs2_t v; - SSVAL(&v, 0, i); - lowcase_table[v] = i; + SSVAL(lowcase_table, i*2, i); } for (i=0;i<256;i++) { - smb_ucs2_t v; - SSVAL(&v, 0, UCS2_CHAR(i)); - lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i); + SSVAL(lowcase_table, i*2, isupper(i)?tolower(i):i); } } } /******************************************************************* - Convert a wchar to upper case. + Convert a codepoint_t to upper case. ********************************************************************/ -smb_ucs2_t toupper_w(smb_ucs2_t val) +codepoint_t toupper_w(codepoint_t val) { - return upcase_table[SVAL(&val,0)]; -} - -/******************************************************************* - Convert a wchar to lower case. -********************************************************************/ -static smb_ucs2_t tolower_w( smb_ucs2_t val ) -{ - return lowcase_table[SVAL(&val,0)]; - -} - -/******************************************************************* -determine if a character is lowercase -********************************************************************/ -BOOL islower_w(smb_ucs2_t c) -{ - return upcase_table[SVAL(&c,0)] != c; + if (val & 0xFFFF0000) { + return val; + } + if (val < 128) { + return toupper(val); + } + if (upcase_table == NULL) { + load_case_tables(); + } + return SVAL(upcase_table, val*2); } /******************************************************************* -determine if a character is uppercase + Convert a codepoint_t to lower case. ********************************************************************/ -BOOL isupper_w(smb_ucs2_t c) +codepoint_t tolower_w(codepoint_t val) { - return lowcase_table[SVAL(&c,0)] != c; + if (val & 0xFFFF0000) { + return val; + } + if (val < 128) { + return tolower(val); + } + if (lowcase_table == NULL) { + load_case_tables(); + } + return SVAL(lowcase_table, val*2); } - /******************************************************************* - Count the number of characters in a smb_ucs2_t string. +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination ********************************************************************/ -size_t strlen_w(const smb_ucs2_t *src) +size_t utf16_len(const void *buf) { size_t len; - for (len = 0; SVAL(src,0); len++, src++) ; + for (len = 0; SVAL(buf,len); len += 2) ; - return len; + return len + 2; } /******************************************************************* - Count up to max number of characters in a smb_ucs2_t string. +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes ********************************************************************/ -size_t strnlen_w(const smb_ucs2_t *src, size_t max) +size_t utf16_len_n(const void *src, size_t n) { size_t len; - for (len = 0; (len < max) && SVAL(src, 0); len++, src++) ; - - return len; -} - -/******************************************************************* -wide strchr() -********************************************************************/ -smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) -{ - while (*s != 0) { - if (c == *s) return discard_const_p(smb_ucs2_t, s); - s++; - } - if (c == *s) return discard_const_p(smb_ucs2_t, s); - - return NULL; -} - -smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) -{ - return strchr_w(s, UCS2_CHAR(c)); -} - -smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) -{ - const smb_ucs2_t *p = s; - int len = strlen_w(s); - if (len == 0) return NULL; - p += (len - 1); - do { - if (c == *p) return discard_const_p(smb_ucs2_t, p); - } while (p-- != s); - return NULL; -} - -/******************************************************************* - Convert a string to lower case. - return True if any char is converted -********************************************************************/ -BOOL strlower_w(smb_ucs2_t *s) -{ - BOOL ret = False; - while (*s) { - smb_ucs2_t v = tolower_w(*s); - if (v != *s) { - *s = v; - ret = True; - } - s++; - } - return ret; -} - -/******************************************************************* - Convert a string to upper case. - return True if any char is converted -********************************************************************/ -BOOL strupper_w(smb_ucs2_t *s) -{ - BOOL ret = False; - while (*s) { - smb_ucs2_t v = toupper_w(*s); - if (v != *s) { - *s = v; - ret = True; - } - s++; - } - return ret; -} - -/******************************************************************* -case insensitive string comparison -********************************************************************/ -int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b) -{ - while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; } - return (tolower_w(*a) - tolower_w(*b)); -} - -/******************************************************************* -replace any occurence of oldc with newc in unicode string -********************************************************************/ - -void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc) -{ - for(;*s;s++) { - if(*s==oldc) *s=newc; - } -} - - -/* - The *_wa() functions take a combination of 7 bit ascii - and wide characters They are used so that you can use string - functions combining C string constants with ucs2 strings - - The char* arguments must NOT be multibyte - to be completely sure - of this only pass string constants */ + for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ; - -void pstrcpy_wa(smb_ucs2_t *dest, const char *src) -{ - int i; - for (i=0;i Date: Fri, 8 Oct 2004 14:38:22 +0000 Subject: r2867: make call_backtrace() public this is very usefull we you don't want to use smb_panic() metze (This used to be commit 343b575baa528885f76be12b2cd707f092f85189) --- source4/lib/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/fault.c b/source4/lib/fault.c index 0ce003a2b0..ed1e7c4366 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -36,7 +36,7 @@ static struct { #include #endif -static void call_backtrace(void) +void call_backtrace(void) { #ifdef HAVE_BACKTRACE #define BACKTRACE_STACK_SIZE 64 -- cgit From 7b7619e0ba489329ced5f5159f97ba7da5aa3fa5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 9 Oct 2004 07:11:21 +0000 Subject: r2871: - got rid of the last bits of non-threadsafe data in util_str.o - switch the fallback case tables to use talloc - moved the used-once octal_string() inline in loadparm.c (This used to be commit b04202eaacc87d264d463f75673ee0e68cd54f94) --- source4/lib/util_str.c | 18 +++--------------- source4/lib/util_unistr.c | 12 ++++-------- 2 files changed, 7 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index c4c68a3dcd..89c26e6d22 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -612,19 +612,6 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) } } -/** - Write an octal as a string. -**/ - -const char *octal_string(int i) -{ - static char ret[64]; - if (i == -1) - return "-1"; - slprintf(ret, sizeof(ret)-1, "0%o", i); - return ret; -} - /** Strchr and strrchr_m are a bit complex on general multi-byte strings. @@ -954,13 +941,13 @@ void rfc1738_unescape(char *buf) } } -static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - /** * Decode a base64 string into a DATA_BLOB - simple and slow algorithm **/ DATA_BLOB base64_decode_data_blob(const char *s) { + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int bit_offset, byte_offset, idx, i, n; DATA_BLOB decoded = data_blob(s, strlen(s)+1); uint8_t *d = decoded.data; @@ -1010,6 +997,7 @@ void base64_decode_inplace(char *s) **/ char * base64_encode_data_blob(DATA_BLOB data) { + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bits = 0; int char_count = 0; size_t out_cnt = 0; diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 8b7504986f..480fb6c72e 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -32,13 +32,9 @@ load the case handling tables ********************************************************************/ static void load_case_tables(void) { - static int initialised; int i; TALLOC_CTX *mem_ctx; - if (initialised) return; - initialised = 1; - mem_ctx = talloc_init("load_case_tables"); if (!mem_ctx) { smb_panic("No memory for case_tables"); @@ -49,9 +45,9 @@ static void load_case_tables(void) /* we would like Samba to limp along even if these tables are not available */ - if (!upcase_table) { + if (upcase_table == NULL) { DEBUG(1,("creating lame upcase table\n")); - upcase_table = malloc(0x20000); + upcase_table = talloc_named_const(NULL, 0x20000, "upcase_table"); if (!upcase_table) { smb_panic("No memory for upcase tables"); } @@ -63,9 +59,9 @@ static void load_case_tables(void) } } - if (!lowcase_table) { + if (lowcase_table == NULL) { DEBUG(1,("creating lame lowcase table\n")); - lowcase_table = malloc(0x20000); + lowcase_table = talloc_named_const(NULL, 0x20000, "lowcase_table"); if (!lowcase_table) { smb_panic("No memory for lowcase tables"); } -- cgit From f9bac1dec23d2312d23d9605a39ce2819a10c1f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 9 Oct 2004 07:16:49 +0000 Subject: r2872: got rid of a couple of unused (and horrible) functions (This used to be commit 4bb410756df13c8c23d21b43c1186f3f9cb9f758) --- source4/lib/system.c | 191 ------------------------------------------------ source4/lib/util_file.c | 53 -------------- 2 files changed, 244 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/system.c b/source4/lib/system.c index 8d307caea3..e8a944d8f8 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -670,197 +670,6 @@ struct group *sys_getgrgid(gid_t gid) } -/************************************************************************** - Extract a command into an arg list. Uses a static pstring for storage. - Caller frees returned arg list (which contains pointers into the static pstring). -****************************************************************************/ - -static char **extract_args(const char *command) -{ - static pstring trunc_cmd; - char *ptr; - int argcl; - char **argl = NULL; - int i; - - pstrcpy(trunc_cmd, command); - - if(!(ptr = strtok(trunc_cmd, " \t"))) { - errno = EINVAL; - return NULL; - } - - /* - * Count the args. - */ - - for( argcl = 1; ptr; ptr = strtok(NULL, " \t")) - argcl++; - - if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL) - return NULL; - - /* - * Now do the extraction. - */ - - pstrcpy(trunc_cmd, command); - - ptr = strtok(trunc_cmd, " \t"); - i = 0; - argl[i++] = ptr; - - while((ptr = strtok(NULL, " \t")) != NULL) - argl[i++] = ptr; - - argl[i++] = NULL; - return argl; -} - -/************************************************************************** - Wrapper for popen. Safer as it doesn't search a path. - Modified from the glibc sources. - modified by tridge to return a file descriptor. We must kick our FILE* habit -****************************************************************************/ - -typedef struct _popen_list -{ - int fd; - pid_t child_pid; - struct _popen_list *next; -} popen_list; - -static popen_list *popen_chain; - -int sys_popen(const char *command) -{ - int parent_end, child_end; - int pipe_fds[2]; - popen_list *entry = NULL; - char **argl = NULL; - - if (pipe(pipe_fds) < 0) - return -1; - - parent_end = pipe_fds[0]; - child_end = pipe_fds[1]; - - if (!*command) { - errno = EINVAL; - goto err_exit; - } - - if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL) - goto err_exit; - - ZERO_STRUCTP(entry); - - /* - * Extract the command and args into a NULL terminated array. - */ - - if(!(argl = extract_args(command))) - goto err_exit; - - entry->child_pid = fork(); - - if (entry->child_pid == -1) { - goto err_exit; - } - - if (entry->child_pid == 0) { - - /* - * Child ! - */ - - int child_std_end = STDOUT_FILENO; - popen_list *p; - - close(parent_end); - if (child_end != child_std_end) { - dup2 (child_end, child_std_end); - close (child_end); - } - - /* - * POSIX.2: "popen() shall ensure that any streams from previous - * popen() calls that remain open in the parent process are closed - * in the new child process." - */ - - for (p = popen_chain; p; p = p->next) - close(p->fd); - - execv(argl[0], argl); - _exit (127); - } - - /* - * Parent. - */ - - close (child_end); - SAFE_FREE(argl); - - /* Link into popen_chain. */ - entry->next = popen_chain; - popen_chain = entry; - entry->fd = parent_end; - - return entry->fd; - -err_exit: - - SAFE_FREE(entry); - SAFE_FREE(argl); - close(pipe_fds[0]); - close(pipe_fds[1]); - return -1; -} - -/************************************************************************** - Wrapper for pclose. Modified from the glibc sources. -****************************************************************************/ - -int sys_pclose(int fd) -{ - int wstatus; - popen_list **ptr = &popen_chain; - popen_list *entry = NULL; - pid_t wait_pid; - int status = -1; - - /* Unlink from popen_chain. */ - for ( ; *ptr != NULL; ptr = &(*ptr)->next) { - if ((*ptr)->fd == fd) { - entry = *ptr; - *ptr = (*ptr)->next; - status = 0; - break; - } - } - - if (status < 0 || close(entry->fd) < 0) - return -1; - - /* - * As Samba is catching and eating child process - * exits we don't really care about the child exit - * code, a -1 with errno = ECHILD will do fine for us. - */ - - do { - wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0); - } while (wait_pid == -1 && errno == EINTR); - - SAFE_FREE(entry); - - if (wait_pid == -1) - return -1; - return wstatus; -} - /************************************************************************** Wrappers for dlopen, dlsym, dlclose. ****************************************************************************/ diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 51e6c7187e..c4f794db0e 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -273,44 +273,6 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f) } -/**************************************************************************** -load from a pipe into memory -****************************************************************************/ -char *file_pload(char *syscmd, size_t *size) -{ - int fd, n; - char *p, *tp; - pstring buf; - size_t total; - - fd = sys_popen(syscmd); - if (fd == -1) return NULL; - - p = NULL; - total = 0; - - while ((n = read(fd, buf, sizeof(buf))) > 0) { - tp = Realloc(p, total + n + 1); - if (!tp) { - DEBUG(0,("file_pload: failed to expand buffer!\n")); - close(fd); - SAFE_FREE(p); - return NULL; - } else p = tp; - memcpy(p+total, buf, n); - total += n; - } - if (p) p[total] = 0; - - /* FIXME: Perhaps ought to check that the command completed - * successfully (returned 0); if not the data may be - * truncated. */ - sys_pclose(fd); - - if (size) *size = total; - - return p; -} /**************************************************************************** load a file into memory from a fd. @@ -462,21 +424,6 @@ char **fd_lines_load(int fd, int *numlines) } -/**************************************************************************** -load a pipe into memory and return an array of pointers to lines in the data -must be freed with file_lines_free(). -****************************************************************************/ -char **file_lines_pload(char *syscmd, int *numlines) -{ - char *p; - size_t size; - - p = file_pload(syscmd, &size); - if (!p) return NULL; - - return file_lines_parse(p, size, numlines); -} - /**************************************************************************** free lines loaded with file_lines_load ****************************************************************************/ -- cgit From ffa0cf3af05c82df558bb2484e04a8f2220f6ea0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 10 Oct 2004 23:52:06 +0000 Subject: r2897: Fix double registration (of the registry subsystem) bug (This used to be commit f4860afc486da9fcd43798c81181d01eb0120a59) --- source4/lib/registry/common/reg_interface.c | 40 +++++++++++++++++------------ 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index c55ecd5a41..28025e4d84 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -37,6 +37,7 @@ NTSTATUS registry_register(const void *_function) struct reg_init_function_entry *entry = backends; if (!functions || !functions->name) { + DEBUG(0, ("Invalid arguments while registering registry backend\n")); return NT_STATUS_INVALID_PARAMETER; } @@ -56,30 +57,37 @@ NTSTATUS registry_register(const void *_function) return NT_STATUS_OK; } +static BOOL registry_init(void) +{ + static BOOL initialised; + NTSTATUS status; + + if(initialised) { + return True; + } + + status = register_subsystem("registry", registry_register); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status))); + return False; + } + + initialised = True; + static_init_registry; + return True; +} + /* Find a backend in the list of available backends */ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { struct reg_init_function_entry *entry; - static BOOL reg_first_init = True; - NTSTATUS status; - if(reg_first_init) { - status = register_subsystem("registry", registry_register); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status))); - /* Don't try the initialisation again */ - reg_first_init = False; - return NULL; - } - - static_init_registry; - reg_first_init = False; - } + if(registry_init() == False) return NULL; entry = backends; while(entry) { - if (strcmp(entry->functions->name, name)==0) return entry; + if (strcmp(entry->functions->name, name) == 0) return entry; entry = entry->next; } @@ -186,7 +194,7 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch ret->root->hive = ret; ret->root->name = NULL; - ret->root->path = ""; + ret->root->path = talloc_strdup(mem_ctx, ""); /* Add hive to context */ h->num_hives++; -- cgit From e2a47719097291dac9e2ff33fbb1d1b26f26517c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 11 Oct 2004 00:29:55 +0000 Subject: r2898: - Support enumerating remote registry values - Some LDB updates (This used to be commit 4b5bf739f5a8f39ff3633d738f6de42681a6b30f) --- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 80 ++++++++++------------ .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 63 +++++++++-------- 2 files changed, 67 insertions(+), 76 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index e0f65f2c37..cc0432d9ea 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -40,7 +40,7 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * ret = talloc_asprintf_append(ret, "key=%s,", keyname); if(begin) { - begin[0] = '\0'; + *begin = '\0'; end = begin-1; } else { end = NULL; @@ -50,6 +50,10 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * SAFE_FREE(mypath); ret[strlen(ret)-1] = '\0'; + + printf("RETURNING: %s\n", ret); + + if(strlen(ret) == 0) return NULL; return ret; } @@ -62,40 +66,19 @@ static int ldb_close_registry(void *data) } -/* - * Saves the dn as private_data for every key/val - */ - -static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) -{ - struct ldb_context *c; - - if (!hive->location) return WERR_INVALID_PARAM; - c = ldb_connect(hive->location, 0, NULL); - - ldb_set_debug_stderr(c); - - - if(!c) return WERR_FOOBAR; - hive->backend_data = c; - talloc_set_destructor(c, ldb_close_registry); - - return WERR_OK; -} static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **new) { return WERR_NOT_SUPPORTED; } -#if 0 -FIXME -static WERROR ldb_fetch_subkeys(struct registry_key *k, int *count, struct registry_key ***subkeys) +static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) { struct ldb_context *c = k->hive->backend_data; - int ret, i, j; + int ret; struct ldb_message **msg; + struct ldb_message_element *el; ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); @@ -104,27 +87,19 @@ static WERROR ldb_fetch_subkeys(struct registry_key *k, int *count, struct regis return WERR_FOOBAR; } - *subkeys = talloc_array_p(k->mem_ctx, struct registry_key *, ret); - j = 0; - for(i = 0; i < ret; i++) { - struct ldb_message_element *el; - char *name; - el = ldb_msg_find_element(msg[i], "key"); - - name = el->values[0].data; - - /* Dirty hack to circumvent ldb_tdb bug */ - if(k->backend_data && !strcmp(msg[i]->dn, (char *)k->backend_data)) continue; - - (*subkeys)[j] = reg_key_new_rel(name, k, NULL); - (*subkeys)[j]->backend_data = talloc_strdup((*subkeys)[j]->mem_ctx, msg[i]->dn); - j++; - } - *count = j; + if(idx >= ret) return WERR_NO_MORE_ITEMS; + + el = ldb_msg_find_element(msg[idx], "key"); + + *subkey = talloc_p(mem_ctx, struct registry_key); + (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); + (*subkey)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); + printf("Retrieved: %s\n", (*subkey)->backend_data); ldb_search_free(c, msg); return WERR_OK; } +#if 0 static WERROR ldb_fetch_values(struct registry_key *k, int *count, REG_VAL ***values) { @@ -171,7 +146,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c int ret; ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); - ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "*", NULL,&msg); + ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); if(ret == 0) { return WERR_NO_MORE_ITEMS; @@ -181,19 +156,36 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c } *key = talloc_p(mem_ctx, struct registry_key); - /* FIXME */ + (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); + (*key)->backend_data = talloc_strdup(mem_ctx, msg[0]->dn); + printf("Retrieved: %s\n", (*key)->backend_data); ldb_search_free(c, msg); return WERR_OK; } +static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) +{ + struct ldb_context *c; + + if (!hive->location) return WERR_INVALID_PARAM; + c = ldb_connect(hive->location, 0, NULL); + + if(!c) return WERR_FOOBAR; + ldb_set_debug_stderr(c); + hive->backend_data = c; + + return ldb_open_key(mem_ctx, hive, "", k); +} + static struct registry_operations reg_backend_ldb = { .name = "ldb", .open_hive = ldb_open_hive, .open_key = ldb_open_key, /* .fetch_subkeys = ldb_fetch_subkeys, .fetch_values = ldb_fetch_values,*/ + .get_subkey_by_index = ldb_get_subkey_by_id, .add_key = ldb_add_key, }; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 3dd73162be..db1ab9364e 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -198,55 +198,54 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) { struct rpc_key_data *mykeydata = parent->backend_data; - uint32_t requested_len = 0; WERROR error; - + struct winreg_EnumValue r; + uint32 type, len1, len2 = 0; + struct EnumValueIn buf_name, buf_val; + NTSTATUS status; + if(mykeydata->num_values == -1) { error = rpc_query_key(parent); if(!W_ERROR_IS_OK(error)) return error; } - requested_len = mykeydata->max_valdatalen; - -#if 0 /* EnumValue is not working yet ... */ + len1 = mykeydata->max_valdatalen; + r.in.handle = &mykeydata->pol; r.in.enum_index = n; - r.in.type = r.out.type = &type; - r.in.requested_len = r.out.requested_len = &requested_len; - r.in.returned_len = r.out.returned_len = &returned_len; - vn.max_len = mykeydata->max_valnamelen * 2; - vn.len = 0; - vn.buf = NULL; - if(vn.max_len > 0) { - vn.len = 0; - vn.max_len = mykeydata->max_valnamelen*2; - /* FIXME: we should not point a 'char *' to a const buffer!!! --metze*/ - vn.buf = ""; - } - r.in.name = r.out.name = &vn; - vb.max_len = mykeydata->max_valdatalen; - vb.offset = 0x0; - vb.len = 0x0; - vb.buffer = talloc_array_p(mem_ctx, uint8, mykeydata->max_valdatalen); - r.in.value = r.out.value = &vb; - - status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->handle->backend_data, parent->mem_ctx, &r); + r.in.name_in.len = 0; + r.in.name_in.max_len = mykeydata->max_valnamelen * 2; + buf_name.max_len = mykeydata->max_valnamelen; + buf_name.offset = 0; + buf_name.len = 0; + r.in.name_in.buffer = &buf_name; + r.in.type = &type; + buf_val.max_len = mykeydata->max_valdatalen; + buf_val.offset = 0; + buf_val.len = 0; + r.in.value_in = &buf_val; + r.in.value_len1 = &len1; + r.in.value_len2 = &len2; + + + status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); + return WERR_GENERAL_FAILURE; } if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - *value = reg_val_new(parent, NULL); - (*value)->name = r.out.name->buf; + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->parent = parent; + (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); + printf("Type: %d\n", type); (*value)->data_type = type; - (*value)->data_len = r.out.value->len; - (*value)->data_blk = r.out.value->buffer; - exit(1); + (*value)->data_len = r.out.value_out->buffer.length; + (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value_out->buffer.data, r.out.value_out->buffer.length); return WERR_OK; } -#endif - return WERR_NOT_SUPPORTED; + return r.out.result; } static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) -- cgit From 598e82e7ad9377138b5a899724083fc5d808a249 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 01:03:27 +0000 Subject: r2900: rusty pointed out to me that discard_const() can be done via a macro on systems that have the intptr_t type, and for systems that don't have it, they also almost certainly won't have -Wcast-qual, so we can use a void* cast. (This used to be commit 2132d38f9c5ba59825558d5ba084a514ebc2626b) --- source4/lib/util.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 94b01f7501..fde5390127 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -892,25 +892,3 @@ BOOL all_zero(const char *ptr, uint_t size) } -/* - this is a warning hack. The idea is to use this everywhere that we - get the "discarding const" warning from gcc, effectively moving all - the warnings to this one place. That doesn't actually fix the - problem of course, but it means that when we do get to cleaning them - up we can do it by searching the code for discard_const. - - It also means that other error types aren't as swamped by the noise - of hundreds of const warnings, so we are more likely to notice when - we get new errors. - - Please only add more calls to this function when you find it - _really_ hard to fix const warnings. Our aim is to eventually use - this function in only a very few places. - - Also, please call this via the discard_const_p() macro interface, as that - makes the return type safe. -*/ -void *discard_const(const void *ptr) -{ - return (void *)ptr; -} -- cgit From 51009f7052fd6c61d70a35ec311358f962c365c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 02:07:30 +0000 Subject: r2901: if we can't load upcase.dat or lowcase.dat then don't waste 256k making fake tables, instead just do the approximate upper/lower inline with toupper() and tolower(). (This used to be commit 994392d085e87046212191b8f41eba628467c778) --- source4/lib/util_unistr.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 480fb6c72e..672c7cd2c8 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -32,7 +32,6 @@ load the case handling tables ********************************************************************/ static void load_case_tables(void) { - int i; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("load_case_tables"); @@ -42,35 +41,11 @@ static void load_case_tables(void) upcase_table = map_file(lib_path(mem_ctx, "upcase.dat"), 0x20000); lowcase_table = map_file(lib_path(mem_ctx, "lowcase.dat"), 0x20000); talloc_destroy(mem_ctx); - - /* we would like Samba to limp along even if these tables are - not available */ if (upcase_table == NULL) { - DEBUG(1,("creating lame upcase table\n")); - upcase_table = talloc_named_const(NULL, 0x20000, "upcase_table"); - if (!upcase_table) { - smb_panic("No memory for upcase tables"); - } - for (i=0;i<0x10000;i++) { - SSVAL(upcase_table, i*2, i); - } - for (i=0;i<256;i++) { - SSVAL(upcase_table, i*2, islower(i)?toupper(i):i); - } + upcase_table = (void *)-1; } - if (lowcase_table == NULL) { - DEBUG(1,("creating lame lowcase table\n")); - lowcase_table = talloc_named_const(NULL, 0x20000, "lowcase_table"); - if (!lowcase_table) { - smb_panic("No memory for lowcase tables"); - } - for (i=0;i<0x10000;i++) { - SSVAL(lowcase_table, i*2, i); - } - for (i=0;i<256;i++) { - SSVAL(lowcase_table, i*2, isupper(i)?tolower(i):i); - } + lowcase_table = (void *)-1; } } @@ -88,6 +63,9 @@ codepoint_t toupper_w(codepoint_t val) if (upcase_table == NULL) { load_case_tables(); } + if (upcase_table == (void *)-1) { + return val; + } return SVAL(upcase_table, val*2); } @@ -105,6 +83,9 @@ codepoint_t tolower_w(codepoint_t val) if (lowcase_table == NULL) { load_case_tables(); } + if (lowcase_table == (void *)-1) { + return val; + } return SVAL(lowcase_table, val*2); } -- cgit From 173ec86fc05666690909a2ffe4721217fb3ceb51 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 02:10:45 +0000 Subject: r2902: make toupper_w() and tolower_w() slightly faster by putting the most common conditions first (This used to be commit 878f6b565f4e80eefbb08f44551b3b4f647d7aa7) --- source4/lib/util_unistr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 672c7cd2c8..7d10b92c43 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -54,16 +54,16 @@ static void load_case_tables(void) ********************************************************************/ codepoint_t toupper_w(codepoint_t val) { - if (val & 0xFFFF0000) { - return val; - } if (val < 128) { return toupper(val); } + if (upcase_table == (void *)-1) { + return val; + } if (upcase_table == NULL) { load_case_tables(); } - if (upcase_table == (void *)-1) { + if (val & 0xFFFF0000) { return val; } return SVAL(upcase_table, val*2); @@ -74,16 +74,16 @@ codepoint_t toupper_w(codepoint_t val) ********************************************************************/ codepoint_t tolower_w(codepoint_t val) { - if (val & 0xFFFF0000) { - return val; - } if (val < 128) { return tolower(val); } + if (lowcase_table == (void *)-1) { + return val; + } if (lowcase_table == NULL) { load_case_tables(); } - if (lowcase_table == (void *)-1) { + if (val & 0xFFFF0000) { return val; } return SVAL(lowcase_table, val*2); -- cgit From 4aebdb779a406bba6aa8d5665c608083e19fcf52 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 03:26:17 +0000 Subject: r2903: a considerably more efficient (both in terms of CPU and memory) convert_string_talloc() implementation. the previous version used a minimum of 512 bytes, which is way above the average of what is needed. (This used to be commit abcd841a8530ba3273d56c9001ea277611507be3) --- source4/lib/charcnv.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 392ad3cc72..e5331b973e 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -168,7 +168,7 @@ ssize_t convert_string(charset_t from, charset_t to, **/ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, - void const *src, size_t srclen, void **dest) + void const *src, size_t srclen, void **dest) { size_t i_len, o_len, destlen; size_t retval; @@ -189,20 +189,25 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, return -1; } - destlen = MAX(srclen, 512); + /* it is _very_ rare that a conversion increases the size by + more than 3x */ + destlen = srclen; outbuf = NULL; convert: - destlen = destlen * 2; + destlen = 2 + (destlen*3); ob = (char *)talloc_realloc(ctx, outbuf, destlen); if (!ob) { DEBUG(0, ("convert_string_talloc: realloc failed!\n")); talloc_free(outbuf); return (size_t)-1; - } - else + } else { outbuf = ob; + } + + /* we give iconv 2 less bytes to allow us to terminate at the + end */ i_len = srclen; - o_len = destlen; + o_len = destlen-2; retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); @@ -220,20 +225,15 @@ convert: } DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); talloc_free(ob); - /* smb_panic(reason); */ return (size_t)-1; } - destlen = destlen - o_len; - /* +2 for mandetory null termination, UTF8 or UTF16 */ - *dest = (char *)talloc_realloc(ctx, ob, destlen+2); - if (!*dest) { - DEBUG(0, ("convert_string_talloc: out of memory!\n")); - talloc_free(ob); - return (size_t)-1; - } - ((char *)*dest)[destlen] = '\0'; - ((char *)*dest)[destlen+1] = '\0'; + destlen = (destlen-2) - o_len; + + /* guarantee null termination in all charsets */ + SSVAL(ob, destlen, 0); + + *dest = ob; return destlen; } -- cgit From 925251ea592bf7f341d2b4471cd5311fcabad109 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 05:23:46 +0000 Subject: r2907: auto destroy iconv memory handles on exit, to make valgrind leak reports easier to read (less noisy) (This used to be commit e3009492b85ac90836aa9341687df5869f4ea291) --- source4/lib/charcnv.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index e5331b973e..10063c9f3c 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -57,25 +57,6 @@ static const char *charset_name(charset_t ch) static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; -/* - on-demand initialisation of conversion handles -*/ -static smb_iconv_t get_conv_handle(charset_t from, charset_t to) -{ - const char *n1, *n2; - - if (conv_handles[from][to]) { - return conv_handles[from][to]; - } - - n1 = charset_name(from); - n2 = charset_name(to); - - conv_handles[from][to] = smb_iconv_open(n2,n1); - - return conv_handles[from][to]; -} - /** re-initialize iconv conversion descriptors **/ @@ -95,6 +76,32 @@ void init_iconv(void) } +/* + on-demand initialisation of conversion handles +*/ +static smb_iconv_t get_conv_handle(charset_t from, charset_t to) +{ + const char *n1, *n2; + static int initialised; + /* auto-free iconv memory on exit so valgrind reports are easier + to look at */ + if (initialised == 0) { + initialised = 1; + atexit(init_iconv); + } + + if (conv_handles[from][to]) { + return conv_handles[from][to]; + } + + n1 = charset_name(from); + n2 = charset_name(to); + + conv_handles[from][to] = smb_iconv_open(n2,n1); + + return conv_handles[from][to]; +} + /** * Convert string from one encoding to another, making error checking etc -- cgit From 6df5d77c893a844c74af8c879986150742b1bc58 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 11 Oct 2004 11:52:44 +0000 Subject: r2911: Fix bug in opening relative keys (This used to be commit e7c256a92cc6cbe1cd6cc11a8fb37feba272d01c) --- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index db1ab9364e..fd81983227 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -169,7 +169,8 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) return r.out.result; } -static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) + +static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) { struct rpc_key_data *mykeydata; struct winreg_OpenKey r; @@ -184,17 +185,22 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c /* Then, open the handle using the hive */ memset(&r, 0, sizeof(struct winreg_OpenKey)); - r.in.handle = &(((struct rpc_key_data *)h->root->backend_data)->pol); + r.in.handle = &(((struct rpc_key_data *)h->backend_data)->pol); init_winreg_String(&r.in.keyname, name); r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->backend_data), mem_ctx, &r); + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r); return r.out.result; } +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +{ + return rpc_open_rel_key(mem_ctx, h->root, name, key); +} + static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) { struct rpc_key_data *mykeydata = parent->backend_data; @@ -226,6 +232,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p r.in.value_in = &buf_val; r.in.value_len1 = &len1; r.in.value_len2 = &len2; + r.out.type = &type; status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); @@ -238,7 +245,6 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p *value = talloc_p(mem_ctx, struct registry_value); (*value)->parent = parent; (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); - printf("Type: %d\n", type); (*value)->data_type = type; (*value)->data_len = r.out.value_out->buffer.length; (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value_out->buffer.data, r.out.value_out->buffer.length); @@ -271,9 +277,7 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key * r.in.key_name_len = r.out.key_name_len = 0; status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - if(parent->hive->root == parent) - return rpc_open_key(mem_ctx, parent->hive, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); - return rpc_open_key(mem_ctx, parent->hive, talloc_asprintf(mem_ctx, "%s\\%s", parent->path, r.out.out_name->name), subkey); + return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); } return r.out.result; @@ -298,7 +302,7 @@ static WERROR rpc_query_key(struct registry_key *k) talloc_destroy(mem_ctx); if (!NT_STATUS_IS_OK(status)) { - printf("QueryInfoKey failed - %s\n", nt_errstr(status)); + DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } -- cgit From aed95ba66f29b9536e99027fab5327548b984b70 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 11 Oct 2004 13:57:30 +0000 Subject: r2913: - Don't print hive name if it is NULL (regtree) - Initialise hive name (reg_interface) - Fix LDB backend (enumerating keys works now!) (This used to be commit 5086d6b2494f236ef67096b2dd4da4f7402a65c5) --- source4/lib/registry/common/reg_interface.c | 1 + source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 9 +-------- source4/lib/registry/tools/regtree.c | 11 +++++++---- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 28025e4d84..16edadfcbb 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -185,6 +185,7 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch ret->functions = entry->functions; ret->backend_data = NULL; ret->reg_ctx = h; + ret->name = NULL; werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index cc0432d9ea..7e228412d5 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -51,8 +51,6 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * ret[strlen(ret)-1] = '\0'; - printf("RETURNING: %s\n", ret); - if(strlen(ret) == 0) return NULL; return ret; @@ -65,9 +63,6 @@ static int ldb_close_registry(void *data) return 0; } - - - static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **new) { return WERR_NOT_SUPPORTED; @@ -94,7 +89,6 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, *subkey = talloc_p(mem_ctx, struct registry_key); (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); (*subkey)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); - printf("Retrieved: %s\n", (*subkey)->backend_data); ldb_search_free(c, msg); return WERR_OK; @@ -158,7 +152,6 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c *key = talloc_p(mem_ctx, struct registry_key); (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); (*key)->backend_data = talloc_strdup(mem_ctx, msg[0]->dn); - printf("Retrieved: %s\n", (*key)->backend_data); ldb_search_free(c, msg); @@ -183,7 +176,7 @@ static struct registry_operations reg_backend_ldb = { .name = "ldb", .open_hive = ldb_open_hive, .open_key = ldb_open_key, -/* .fetch_subkeys = ldb_fetch_subkeys, +/* .fetch_values = ldb_fetch_values,*/ .get_subkey_by_index = ldb_get_subkey_by_id, .add_key = ldb_add_key, diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 9748ca3438..bc0055a891 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -32,10 +32,13 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) for(i = 0; i < l; i++) putchar(' '); /* Hive name */ - if(p->hive->root == p) printf("%s\n", p->hive->name); - else if(!p->name) printf("\n"); - else if(fullpath) printf("%s\n", p->path); - else printf("%s\n", p->name); + if(p->hive->root == p) { + if(p->hive->name) printf("%s\n", p->hive->name); else printf("\n"); + } else { + if(!p->name) printf("\n"); + if(fullpath) printf("%s\n", p->path); + else printf("%s\n", p->name); + } mem_ctx = talloc_init("print_tree"); for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) { -- cgit From fe8aaa5d07eaeb54954a9a36207dbc02a6f39504 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 11 Oct 2004 14:07:20 +0000 Subject: r2914: ... and support enumerating values (data is not handled yet, only the names) (This used to be commit b3bc055ac73ff239c2b267717ee91669ecdd4c9b) --- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 41 ++++++---------------- 1 file changed, 11 insertions(+), 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 7e228412d5..d76b7715da 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -63,11 +63,6 @@ static int ldb_close_registry(void *data) return 0; } -static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **new) -{ - return WERR_NOT_SUPPORTED; -} - static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) { struct ldb_context *c = k->hive->backend_data; @@ -93,13 +88,13 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, ldb_search_free(c, msg); return WERR_OK; } -#if 0 -static WERROR ldb_fetch_values(struct registry_key *k, int *count, REG_VAL ***values) +static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) { struct ldb_context *c = k->hive->backend_data; - int ret, i, j; + int ret; struct ldb_message **msg; + struct ldb_message_element *el; ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); @@ -108,30 +103,18 @@ static WERROR ldb_fetch_values(struct registry_key *k, int *count, REG_VAL ***va return WERR_FOOBAR; } - *values = talloc_array_p(k->mem_ctx, REG_VAL *, ret); - j = 0; - for(i = 0; i < ret; i++) { - struct ldb_message_element *el; - char *name; - el = ldb_msg_find_element(msg[i], "key"); - - name = el->values[0].data; - - /* Dirty hack to circumvent ldb_tdb bug */ - if(k->backend_data && !strcmp(msg[i]->dn, (char *)k->backend_data)) continue; - - (*values)[j] = reg_val_new(k, NULL); - (*values)[j]->backend_data = talloc_strdup((*values)[j]->mem_ctx, msg[i]->dn); - j++; - } - *count = j; + if(idx >= ret) return WERR_NO_MORE_ITEMS; + + el = ldb_msg_find_element(msg[idx], "value"); + + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); + (*value)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); ldb_search_free(c, msg); return WERR_OK; } -#endif - static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) { struct ldb_context *c = h->backend_data; @@ -176,10 +159,8 @@ static struct registry_operations reg_backend_ldb = { .name = "ldb", .open_hive = ldb_open_hive, .open_key = ldb_open_key, -/* - .fetch_values = ldb_fetch_values,*/ + .get_value_by_index = ldb_get_value_by_id, .get_subkey_by_index = ldb_get_subkey_by_id, - .add_key = ldb_add_key, }; NTSTATUS registry_ldb_init(void) -- cgit From 94c18cd1a3399a621f6191e16e925e18bf641707 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Oct 2004 06:12:24 +0000 Subject: r2932: character expansion in strlower_m or strupper_m is considered fatal (as it could cause a overflow). Print a message giving the character values involved in the expansion so it can be debugged if it happens. (This used to be commit 2a6f59f376a132fcbce8c8e9d1b38d8aae3e8561) --- source4/lib/util_str.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 89c26e6d22..03ba1399ef 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -754,6 +754,8 @@ void strlower_m(char *s) codepoint_t c = next_codepoint(s, &c_size); c_size2 = push_codepoint(d, tolower_w(c)); if (c_size2 > c_size) { + DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n", + c, tolower_w(c), c_size, c_size2)); smb_panic("codepoint expansion in strlower_m\n"); } s += c_size; @@ -788,6 +790,8 @@ void strupper_m(char *s) codepoint_t c = next_codepoint(s, &c_size); c_size2 = push_codepoint(d, toupper_w(c)); if (c_size2 > c_size) { + DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n", + c, toupper_w(c), c_size, c_size2)); smb_panic("codepoint expansion in strupper_m\n"); } s += c_size; -- cgit From 7c31786a0d972029937b2f120704f425262f98c4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 12 Oct 2004 15:57:20 +0000 Subject: r2940: Complain when there is an attempt to register a backend for a subsystem that does not (yet) exist (This used to be commit 0130713fbe3d838964542a700839c4e276b18547) --- source4/lib/module.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/module.c b/source4/lib/module.c index c724d872ee..67fb830e6f 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -162,6 +162,8 @@ NTSTATUS register_backend(const char *subsystem, const void *args) if(!strcmp(subsystem, s->name)) return s->callback(args); s = s->next; } + + DEBUG(0, ("Unable to register backend for subsystem '%s'\n", subsystem)); return NT_STATUS_NOT_IMPLEMENTED; } -- cgit From ddd5f1163d5dee1df34f606ac8d2aba35150337c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Oct 2004 00:03:26 +0000 Subject: r2981: Fix incorrect locks/unlocks in tdb_lockkeys()/tdb_unlockkeys(). Spotted by Taj Khattra . Jeremy. (This used to be commit a7d92301bbf45cb9e475e4876fdbb37644ad5871) --- source4/lib/tdb/common/tdb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 4ae23bead7..c1deef80cd 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -2037,13 +2037,13 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) } /* Finally, lock in order */ for (i = 0; i < number; i++) - if (tdb_lock(tdb, i, F_WRLCK)) + if (tdb_lock(tdb, BUCKET(tdb->lockedkeys[i+1]), F_WRLCK)) break; /* If error, release locks we have... */ if (i < number) { for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); + tdb_unlock(tdb, BUCKET(tdb->lockedkeys[j+1]), F_WRLCK); SAFE_FREE(tdb->lockedkeys); return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); } @@ -2057,7 +2057,7 @@ void tdb_unlockkeys(TDB_CONTEXT *tdb) if (!tdb->lockedkeys) return; for (i = 0; i < tdb->lockedkeys[0]; i++) - tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK); + tdb_unlock(tdb, BUCKET(tdb->lockedkeys[i+1]), F_WRLCK); SAFE_FREE(tdb->lockedkeys); } -- cgit From 83928ac670bb17d4a1a8204d52468e5cca7c03d6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Oct 2004 06:41:35 +0000 Subject: r2985: got rid of the unused tdb_lockkeys() and tdb_unlockkeys() functions they have been broken for 4 years (ever since they were added) and have been never used, which makes them prime candidates for destruction. (This used to be commit 0b53ab85aae4569c04495f07c18a65fd6b47bf4c) --- source4/lib/tdb/common/tdb.c | 71 ------------------------------------------- source4/lib/tdb/include/tdb.h | 3 -- 2 files changed, 74 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index c1deef80cd..67d9f9903d 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1070,26 +1070,12 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); } -/* If they do lockkeys, check that this hash is one they locked */ -static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) -{ - u32 i; - if (!tdb->lockedkeys) - return 1; - for (i = 0; i < tdb->lockedkeys[0]; i++) - if (tdb->lockedkeys[i+1] == hash) - return 1; - return TDB_ERRCODE(TDB_ERR_NOLOCK, 0); -} - /* As tdb_find, but if you succeed, keep the lock */ static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, struct list_struct *rec) { u32 rec_ptr; - if (!tdb_keylocked(tdb, hash)) - return 0; if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) return 0; if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) @@ -1291,10 +1277,6 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, { int want_next = (tlock->off != 0); - /* No traversal allows if you've called tdb_lockkeys() */ - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - /* Lock each chain from the start one. */ for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) @@ -1526,8 +1508,6 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); - if (!tdb_keylocked(tdb, hash)) - return -1; if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) return -1; @@ -1644,8 +1624,6 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); - if (!tdb_keylocked(tdb, hash)) - return -1; if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) return -1; @@ -1780,7 +1758,6 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->fd = -1; tdb->name = NULL; tdb->map_ptr = NULL; - tdb->lockedkeys = NULL; tdb->flags = tdb_flags; tdb->open_flags = open_flags; tdb->log_fn = log_fn?log_fn:null_log_fn; @@ -1968,7 +1945,6 @@ int tdb_close(TDB_CONTEXT *tdb) if (tdb->fd != -1) ret = close(tdb->fd); SAFE_FREE(tdb->locked); - SAFE_FREE(tdb->lockedkeys); /* Remove from contexts list */ for (i = &tdbs; *i; i = &(*i)->next) { @@ -1992,8 +1968,6 @@ int tdb_lockall(TDB_CONTEXT *tdb) /* There are no locks on read-only dbs */ if (tdb->read_only) return TDB_ERRCODE(TDB_ERR_LOCK, -1); - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); for (i = 0; i < tdb->header.hash_size; i++) if (tdb_lock(tdb, i, F_WRLCK)) break; @@ -2016,51 +1990,6 @@ void tdb_unlockall(TDB_CONTEXT *tdb) tdb_unlock(tdb, i, F_WRLCK); } -int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]) -{ - u32 i, j, hash; - - /* Can't lock more keys if already locked */ - if (tdb->lockedkeys) - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - if (!(tdb->lockedkeys = malloc(sizeof(u32) * (number+1)))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - /* First number in array is # keys */ - tdb->lockedkeys[0] = number; - - /* Insertion sort by bucket */ - for (i = 0; i < number; i++) { - hash = tdb->hash_fn(&keys[i]); - for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++); - memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j)); - tdb->lockedkeys[j+1] = hash; - } - /* Finally, lock in order */ - for (i = 0; i < number; i++) - if (tdb_lock(tdb, BUCKET(tdb->lockedkeys[i+1]), F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < number) { - for ( j = 0; j < i; j++) - tdb_unlock(tdb, BUCKET(tdb->lockedkeys[j+1]), F_WRLCK); - SAFE_FREE(tdb->lockedkeys); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - return 0; -} - -/* Unlock the keys previously locked by tdb_lockkeys() */ -void tdb_unlockkeys(TDB_CONTEXT *tdb) -{ - u32 i; - if (!tdb->lockedkeys) - return; - for (i = 0; i < tdb->lockedkeys[0]; i++) - tdb_unlock(tdb, BUCKET(tdb->lockedkeys[i+1]), F_WRLCK); - SAFE_FREE(tdb->lockedkeys); -} - /* lock/unlock one hash chain. This is meant to be used to reduce contention - it cannot guarantee how many records will be locked */ int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 6f4f3235a7..416333f0b0 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -100,7 +100,6 @@ typedef struct tdb_context { enum TDB_ERROR ecode; /* error code for last tdb error */ struct tdb_header header; /* a cached copy of the header */ u32 flags; /* the flags passed to tdb_open */ - u32 *lockedkeys; /* array of locked keys: first is #keys */ struct tdb_traverse_lock travlocks; /* current traversal locks */ struct tdb_context *next; /* all tdbs to avoid multiple opens */ dev_t device; /* uniquely identifies this tdb */ @@ -135,8 +134,6 @@ TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]); -void tdb_unlockkeys(TDB_CONTEXT *tdb); int tdb_lockall(TDB_CONTEXT *tdb); void tdb_unlockall(TDB_CONTEXT *tdb); -- cgit From 645067efc69ff510612f7b63cf262cc9d60df700 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 16 Oct 2004 11:20:57 +0000 Subject: r3004: removed some unused functions (This used to be commit 247421ee648d1935b68a47195fe1709bb861a7d5) --- source4/lib/basic.mk | 1 - source4/lib/smbrun.c | 176 --------------------------------------------------- source4/lib/util.c | 120 ----------------------------------- 3 files changed, 297 deletions(-) delete mode 100644 source4/lib/smbrun.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index f8bb46a95d..addef77a20 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -17,7 +17,6 @@ ADD_OBJ_FILES = \ lib/time.o \ lib/genrand.o \ lib/username.o \ - lib/smbrun.o \ lib/bitmap.o \ lib/snprintf.o \ lib/dprintf.o \ diff --git a/source4/lib/smbrun.c b/source4/lib/smbrun.c deleted file mode 100644 index ab36ec6e40..0000000000 --- a/source4/lib/smbrun.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - Unix SMB/CIFS implementation. - run a command as a specified user - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - -#if 1 -int smbrun(char *cmd, int *outfd) -{ - DEBUG(0,("smbrun() needs a rewrite: struct current_user is gone!\n")); - return -1; -} -#else -/**************************************************************************** -This is a utility function of smbrun(). -****************************************************************************/ -static int setup_out_fd(void) -{ - int fd; - pstring path; - - slprintf(path, sizeof(path)-1, "%s/smb.XXXXXX", tmpdir()); - - /* now create the file */ - fd = smb_mkstemp(path); - - if (fd == -1) { - DEBUG(0,("setup_out_fd: Failed to create file %s. (%s)\n", - path, strerror(errno) )); - return -1; - } - - DEBUG(10,("setup_out_fd: Created tmp file %s\n", path )); - - /* Ensure file only kept around by open fd. */ - unlink(path); - return fd; -} - -/**************************************************************************** -run a command being careful about uid/gid handling and putting the output in -outfd (or discard it if outfd is NULL). -****************************************************************************/ - -int smbrun(char *cmd, int *outfd) -{ - pid_t pid; - uid_t uid = current_user.uid; - gid_t gid = current_user.gid; - - /* - * Lose any kernel oplock capabilities we may have. - */ - oplock_set_capability(False, False); - - /* point our stdout at the file we want output to go into */ - - if (outfd && ((*outfd = setup_out_fd()) == -1)) { - return -1; - } - - /* in this method we will exec /bin/sh with the correct - arguments, after first setting stdout to point at the file */ - - /* - * We need to temporarily stop CatchChild from eating - * SIGCLD signals as it also eats the exit status code. JRA. - */ - - CatchChildLeaveStatus(); - - if ((pid=fork()) < 0) { - DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) )); - CatchChild(); - if (outfd) { - close(*outfd); - *outfd = -1; - } - return errno; - } - - if (pid) { - /* - * Parent. - */ - int status=0; - pid_t wpid; - - - /* the parent just waits for the child to exit */ - while((wpid = sys_waitpid(pid,&status,0)) < 0) { - if(errno == EINTR) { - errno = 0; - continue; - } - break; - } - - CatchChild(); - - if (wpid != pid) { - DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno))); - if (outfd) { - close(*outfd); - *outfd = -1; - } - return -1; - } - - /* Reset the seek pointer. */ - if (outfd) { - sys_lseek(*outfd, 0, SEEK_SET); - } - -#if defined(WIFEXITED) && defined(WEXITSTATUS) - if (WIFEXITED(status)) { - return WEXITSTATUS(status); - } -#endif - - return status; - } - - CatchChild(); - - /* we are in the child. we exec /bin/sh to do the work for us. we - don't directly exec the command we want because it may be a - pipeline or anything else the config file specifies */ - - /* point our stdout at the file we want output to go into */ - if (outfd) { - close(1); - if (sys_dup2(*outfd,1) != 1) { - DEBUG(2,("Failed to create stdout file descriptor\n")); - close(*outfd); - exit(80); - } - } - - /* now completely lose our privileges. This is a fairly paranoid - way of doing it, but it does work on all systems that I know of */ - - become_user_permanently(uid, gid); - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* we failed to lose our privileges - do not execute - the command */ - exit(81); /* we can't print stuff at this stage, - instead use exit codes for debugging */ - } - - execl("/bin/sh","sh","-c",cmd,NULL); - - /* not reached */ - exit(82); - return 1; -} -#endif diff --git a/source4/lib/util.c b/source4/lib/util.c index fde5390127..0982694823 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -28,7 +28,6 @@ Find a suitable temporary directory. The result should be copied immediately as it may be overwritten by a subsequent call. ****************************************************************************/ - const char *tmpdir(void) { char *p; @@ -37,28 +36,10 @@ const char *tmpdir(void) return "/tmp"; } -/**************************************************************************** - Determine whether we are in the specified group. -****************************************************************************/ - -BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) -{ - int i; - - if (group == current_gid) - return(True); - - for (i=0;i Date: Sat, 16 Oct 2004 13:47:00 +0000 Subject: r3005: added talloc wrappers around tdb_open() and ldb_connect(), so that the caller doesn't have to worry about the constraint of only opening a database a single time in a process. These wrappers will ensure that only a single open is done, and will auto-close when the last instance is gone. When you are finished with a database pointer, use talloc_free() to close it. note that this code does not take account of the threads process model, and does not yet take account of symlinks or hard links to tdb files. (This used to be commit 04e1171996612ddb15f84134cadded68f0d173b2) --- source4/lib/basic.mk | 2 +- source4/lib/db_wrap.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/gencache.c | 27 ++++---- source4/lib/messages.c | 42 ++++++------ source4/lib/tdb/config.mk | 6 +- source4/lib/tdb_helper.c | 42 ------------ 6 files changed, 208 insertions(+), 81 deletions(-) create mode 100644 source4/lib/db_wrap.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index addef77a20..93309ce68b 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -50,7 +50,7 @@ ADD_OBJ_FILES = \ lib/crypto/md5.o \ lib/crypto/hmacmd5.o \ lib/crypto/md4.o \ - lib/tdb_helper.o \ + lib/db_wrap.o \ lib/server_mutex.o REQUIRED_SUBSYSTEMS = \ LIBTDB CHARSET diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c new file mode 100644 index 0000000000..251741c5b0 --- /dev/null +++ b/source4/lib/db_wrap.c @@ -0,0 +1,170 @@ +/* + Unix SMB/CIFS implementation. + + database wrap functions + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + the stupidity of the unix fcntl locking design forces us to never + allow a database file to be opened twice in the same process. These + wrappers provide convenient access to a tdb or ldb, taking advantage + of talloc destructors to ensure that only a single open is done +*/ + +#include "includes.h" + +static struct ldb_wrap *ldb_list; +static struct tdb_wrap *tdb_list; + +/* + this is used to catch debug messages from ldb +*/ +static void ldb_wrap_debug(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void ldb_wrap_debug(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + char *s = NULL; + if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) { + return; + } + vasprintf(&s, fmt, ap); + if (!s) return; + DEBUG(level, ("ldb: %s\n", s)); + free(s); +} + + +/* destroy the last connection to a ldb */ +static int ldb_wrap_destructor(void *ctx) +{ + struct ldb_wrap *w = ctx; + ldb_close(w->ldb); + DLIST_REMOVE(ldb_list, w); + return 0; +} + +/* + wrapped connection to a ldb database + to close just talloc_free() the ldb_wrap pointer + */ +struct ldb_wrap *ldb_wrap_connect(TALLOC_CTX *mem_ctx, + const char *url, + unsigned int flags, + const char *options[]) +{ + struct ldb_wrap *w; + + for (w=ldb_list;w;w=w->next) { + if (strcmp(url, w->url) == 0) { + return talloc_reference(mem_ctx, w); + } + } + + w = talloc_p(mem_ctx, struct ldb_wrap); + if (w == NULL) { + return NULL; + } + + w->url = talloc_strdup(w, url); + + w->ldb = ldb_connect(url, flags, options); + if (w->ldb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, ldb_wrap_destructor); + ldb_set_debug(w->ldb, ldb_wrap_debug, NULL); + + DLIST_ADD(ldb_list, w); + + return w; +} + + +/* + Log tdb messages via DEBUG(). +*/ +static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); + +static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, + const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (ptr != NULL) { + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + free(ptr); + } +} + + +/* destroy the last connection to a tdb */ +static int tdb_wrap_destructor(void *ctx) +{ + struct tdb_wrap *w = ctx; + tdb_close(w->tdb); + DLIST_REMOVE(tdb_list, w); + return 0; +} + +/* + wrapped connection to a tdb database + to close just talloc_free() the tdb_wrap pointer + */ +struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + struct tdb_wrap *w; + + for (w=tdb_list;w;w=w->next) { + if (strcmp(name, w->name) == 0) { + return talloc_reference(mem_ctx, w); + } + } + + w = talloc_p(mem_ctx, struct tdb_wrap); + if (w == NULL) { + return NULL; + } + + w->name = talloc_strdup(w, name); + + w->tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, tdb_wrap_log, NULL); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, tdb_wrap_destructor); + + DLIST_ADD(tdb_list, w); + + return w; +} diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 1a66d8dc3d..a176dc5ae8 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -29,7 +29,7 @@ #define TIMEOUT_LEN 12 #define CACHE_DATA_FMT "%12u/%s" -static TDB_CONTEXT *cache; +static struct tdb_wrap *cache; /** * @file gencache.c @@ -62,8 +62,8 @@ BOOL gencache_init(void) return False; } - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0644); + cache = tdb_wrap_open(NULL, cache_fname, 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0644); SAFE_FREE(cache_fname); if (!cache) { @@ -83,10 +83,10 @@ BOOL gencache_init(void) BOOL gencache_shutdown(void) { - /* tdb_close routine returns -1 on error */ if (!cache) return False; DEBUG(5, ("Closing cache file\n")); - return tdb_close(cache) != -1; + talloc_free(cache); + return True; } @@ -125,7 +125,7 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout), (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store(cache, keybuf, databuf, 0); + ret = tdb_store(cache->tdb, keybuf, databuf, 0); SAFE_FREE(valstr); SAFE_FREE(keybuf.dptr); SAFE_FREE(databuf.dptr); @@ -178,7 +178,7 @@ BOOL gencache_set_only(const char *keystr, const char *valstr, time_t timeout) timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store(cache, keybuf, databuf, TDB_REPLACE); + ret = tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE); SAFE_FREE(datastr); SAFE_FREE(old_valstr); @@ -211,7 +211,7 @@ BOOL gencache_del(const char *keystr) keybuf.dptr = strdup(keystr); keybuf.dsize = strlen(keystr)+1; DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); - ret = tdb_delete(cache, keybuf); + ret = tdb_delete(cache->tdb, keybuf); SAFE_FREE(keybuf.dptr); return ret == 0; @@ -243,7 +243,7 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) keybuf.dptr = strdup(keystr); keybuf.dsize = strlen(keystr)+1; - databuf = tdb_fetch(cache, keybuf); + databuf = tdb_fetch(cache->tdb, keybuf); SAFE_FREE(keybuf.dptr); if (databuf.dptr && databuf.dsize > TIMEOUT_LEN) { @@ -317,7 +317,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time if (!gencache_init()) return; DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern)); - node = tdb_search_keys(cache, keystr_pattern); + node = tdb_search_keys(cache->tdb, keystr_pattern); first_node = node; while (node) { @@ -328,7 +328,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time * We don't use gencache_get function, because we need to iterate through * all of the entries. Validity verification is up to fn routine. */ - databuf = tdb_fetch(cache, node->node_key); + databuf = tdb_fetch(cache->tdb, node->node_key); if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) { SAFE_FREE(databuf.dptr); SAFE_FREE(keystr); @@ -360,7 +360,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time int gencache_lock_entry( const char *key ) { - return tdb_lock_bystring(cache, key, 0); + return tdb_lock_bystring(cache->tdb, key, 0); } /******************************************************************** @@ -369,8 +369,7 @@ int gencache_lock_entry( const char *key ) void gencache_unlock_entry( const char *key ) { - tdb_unlock_bystring(cache, key); - return; + tdb_unlock_bystring(cache->tdb, key); } diff --git a/source4/lib/messages.c b/source4/lib/messages.c index b4de7c0145..64dc2f510a 100644 --- a/source4/lib/messages.c +++ b/source4/lib/messages.c @@ -48,7 +48,7 @@ #include "includes.h" /* the locking database handle */ -static TDB_CONTEXT *tdb; +static struct tdb_wrap *tdb; static int received_signal; /* change the message version with any incompatible changes in the protocol */ @@ -105,9 +105,9 @@ BOOL message_init(void) DEBUG(0,("ERROR: No memory to initialise messages database\n")); return False; } - tdb = tdb_open_log(lock_path(mem_ctx, "messages.tdb"), - 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR|O_CREAT,0600); + tdb = tdb_wrap_open(NULL, lock_path(mem_ctx, "messages.tdb"), + 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR|O_CREAT,0600); talloc_destroy(mem_ctx); if (!tdb) { @@ -155,7 +155,7 @@ static BOOL message_notify(pid_t pid) if (kill(pid, SIGUSR1) == -1) { if (errno == ESRCH) { DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); - tdb_delete(tdb, message_key_pid(pid)); + tdb_delete(tdb->tdb, message_key_pid(pid)); } else { DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); } @@ -209,18 +209,18 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* lock the record for the destination */ if (timeout) { - if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { - if (tdb_chainlock(tdb, kbuf) == -1) { + if (tdb_chainlock(tdb->tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } - tdb_append(tdb, kbuf, dbuf); - tdb_chainunlock(tdb, kbuf); + tdb_append(tdb->tdb, kbuf, dbuf); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ @@ -229,24 +229,24 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* lock the record for the destination */ if (timeout) { - if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { - if (tdb_chainlock(tdb, kbuf) == -1) { + if (tdb_chainlock(tdb->tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } - old_dbuf = tdb_fetch(tdb, kbuf); + old_dbuf = tdb_fetch(tdb->tdb, kbuf); if (!old_dbuf.dptr) { /* its a new record */ - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); - tdb_chainunlock(tdb, kbuf); + tdb_store(tdb->tdb, kbuf, dbuf, TDB_REPLACE); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ @@ -264,7 +264,7 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, if (!memcmp(ptr, &rec, sizeof(rec))) { if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { - tdb_chainunlock(tdb, kbuf); + tdb_chainunlock(tdb->tdb, kbuf); DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); SAFE_FREE(dbuf.dptr); SAFE_FREE(old_dbuf.dptr); @@ -277,8 +277,8 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* we're adding to an existing entry */ - tdb_append(tdb, kbuf, dbuf); - tdb_chainunlock(tdb, kbuf); + tdb_append(tdb->tdb, kbuf, dbuf); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(old_dbuf.dptr); SAFE_FREE(dbuf.dptr); @@ -323,14 +323,14 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) kbuf = message_key_pid(getpid()); - tdb_chainlock(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); + tdb_chainlock(tdb->tdb, kbuf); + dbuf = tdb_fetch(tdb->tdb, kbuf); /* * Replace with an empty record to keep the allocated * space in the tdb. */ - tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE); - tdb_chainunlock(tdb, kbuf); + tdb_store(tdb->tdb, kbuf, null_dbuf, TDB_REPLACE); + tdb_chainunlock(tdb->tdb, kbuf); if (dbuf.dptr == NULL || dbuf.dsize == 0) { SAFE_FREE(dbuf.dptr); diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index fdde6e7b4f..dba0d3e1d4 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -28,7 +28,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbtest.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB REQUIRED_LIBRARIES = GDBM # End BINARY tdbtest ################################################ @@ -49,7 +49,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbtorture.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbtorture ################################################ @@ -59,7 +59,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbdump.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbdump ################################################ diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c index 2698e3cc71..e29a8a7211 100644 --- a/source4/lib/tdb_helper.c +++ b/source4/lib/tdb_helper.c @@ -25,45 +25,3 @@ dealing with a tdb database a little less cumbersome in Samba */ -/**************************************************************************** - Log tdb messages via DEBUG(). -****************************************************************************/ - -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); - -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) -{ - va_list ap; - char *ptr = NULL; - - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - - if (!ptr || !*ptr) - return; - - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); - SAFE_FREE(ptr); -} - -/**************************************************************************** - Like tdb_open() but also setup a logging function that redirects to - the samba DEBUG() system. -****************************************************************************/ - -TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - TDB_CONTEXT *tdb; - - if (!lp_use_mmap()) - tdb_flags |= TDB_NOMMAP; - - tdb = tdb_open_ex(name, hash_size, tdb_flags, - open_flags, mode, tdb_log, NULL); - if (!tdb) - return NULL; - - return tdb; -} -- cgit From f42402da83afa97f821d36b7974de98ddd5a2880 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 05:07:07 +0000 Subject: r3013: added support for unix domain sockets in the generic socket library. I will shortly be using this for a rewrite of the intra-smbd messaging library, which is needed to get lock timeouts working properly (and share modes, oplocks etc) (This used to be commit 6f4926d846965a901e40d24546eab356c4a537c7) --- source4/lib/socket/config.m4 | 1 + source4/lib/socket/config.mk | 8 + source4/lib/socket/socket.c | 4 + source4/lib/socket/socket_ipv4.c | 3 +- source4/lib/socket/socket_unix.c | 319 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 334 insertions(+), 1 deletion(-) create mode 100644 source4/lib/socket/socket_unix.c (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index a5d3d0916e..c91f21368f 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,4 +1,5 @@ SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) +SMB_MODULE_MK(socket_unix,SOCKET,STATIC,lib/socket/config.mk) SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 320fc7f3ee..6072f743ce 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -7,6 +7,14 @@ INIT_OBJ_FILES = \ # End MODULE socket_ipv4 ################################################ +################################################ +# Start MODULE socket_unix +[MODULE::socket_unix] +INIT_OBJ_FILES = \ + lib/socket/socket_unix.o +# End MODULE socket_unix +################################################ + ################################################ # Start SUBSYSTEM SOCKET [SUBSYSTEM::SOCKET] diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 4fde41a3c0..f364ca7c9f 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -240,5 +240,9 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type return socket_ipv4_ops(); } + if (strequal("unix", name)) { + return socket_ipv4_ops(); + } + return NULL; } diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 88bf611b67..23e34dd39b 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -150,7 +150,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) { struct sockaddr_in cli_addr; - socklen_t cli_addr_len = 0; + socklen_t cli_addr_len = sizeof(cli_addr); int new_fd; new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); @@ -167,6 +167,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte (*new_sock) = talloc_p(NULL, struct socket_context); if (!(*new_sock)) { + close(new_fd); return NT_STATUS_NO_MEMORY; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c new file mode 100644 index 0000000000..d87eaf49c4 --- /dev/null +++ b/source4/lib/socket/socket_unix.c @@ -0,0 +1,319 @@ +/* + Unix SMB/CIFS implementation. + + unix domain socket functions + + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static NTSTATUS unixdom_init(struct socket_context *sock) +{ + sock->fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock->fd == -1) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + return NT_STATUS_OK; +} + +static void unixdom_close(struct socket_context *sock) +{ + close(sock->fd); +} + +static NTSTATUS unixdom_connect(struct socket_context *sock, + const char *my_address, int my_port, + const char *srv_address, int srv_port, + uint32_t flags) +{ + struct sockaddr_un srv_addr; + int ret; + + if (strlen(srv_address)+1 > sizeof(srv_addr.sun_path)) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(srv_addr); + srv_addr.sun_family = AF_UNIX; + strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path)); + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + } + + ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); + if (ret == -1) { + return NT_STATUS_CONNECTION_REFUSED; + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + +static NTSTATUS unixdom_listen(struct socket_context *sock, + const char *my_address, int port, + int queue_size, uint32_t flags) +{ + struct sockaddr_un my_addr; + int ret; + + if (strlen(my_address)+1 > sizeof(my_addr.sun_path)) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(my_addr); + my_addr.sun_family = AF_UNIX; + strncpy(my_addr.sun_path, my_address, sizeof(my_addr.sun_path)); + + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + if (ret == -1) { + return NT_STATUS_UNSUCCESSFUL; + } + + ret = listen(sock->fd, queue_size); + if (ret == -1) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + } + + sock->state = SOCKET_STATE_SERVER_LISTEN; + + return NT_STATUS_OK; +} + +static NTSTATUS unixdom_accept(struct socket_context *sock, + struct socket_context **new_sock, + uint32_t flags) +{ + struct sockaddr_un cli_addr; + socklen_t cli_addr_len = sizeof(cli_addr); + int new_fd; + + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); + if (new_fd == -1) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + (*new_sock) = talloc_p(NULL, struct socket_context); + if (!(*new_sock)) { + close(new_fd); + return NT_STATUS_NO_MEMORY; + } + + /* copy the socket_context */ + (*new_sock)->type = sock->type; + (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; + (*new_sock)->flags = flags; + + (*new_sock)->fd = new_fd; + + (*new_sock)->private_data = NULL; + (*new_sock)->ops = sock->ops; + + return NT_STATUS_OK; +} + +static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, + DATA_BLOB *blob, size_t wantlen, uint32_t flags) +{ + ssize_t gotlen; + void *buf; + int flgs = 0; + + buf = talloc(mem_ctx, wantlen); + if (!buf) { + return NT_STATUS_NO_MEMORY; + } + + /* TODO: we need to map all flags here */ + if (flags & SOCKET_FLAG_PEEK) { + flgs |= MSG_PEEK; + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + flgs |= MSG_DONTWAIT; + } + + if (flags & SOCKET_FLAG_BLOCK) { + flgs |= MSG_WAITALL; + } + + gotlen = recv(sock->fd, buf, wantlen, flgs); + if (gotlen == 0) { + talloc_free(buf); + return NT_STATUS_END_OF_FILE; + } else if (gotlen == -1) { + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + switch (errno) { + case EBADF: + case ENOTCONN: + case ENOTSOCK: + case EFAULT: + case EINVAL: + status = NT_STATUS_INVALID_PARAMETER; + break; + case EAGAIN: + case EINTR: + status = STATUS_MORE_ENTRIES; + break; + case ECONNREFUSED: + status = NT_STATUS_CONNECTION_REFUSED; + break; + } + talloc_free(buf); + return status; + } + + blob->length = gotlen; + blob->data = talloc_realloc(mem_ctx, buf, gotlen); + if (!blob->data) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +{ + ssize_t len; + int flgs = 0; + + /* TODO: we need to map all flags here */ + if (!(flags & SOCKET_FLAG_BLOCK)) { + flgs |= MSG_DONTWAIT; + } + + len = send(sock->fd, blob->data, blob->length, flgs); + if (len == -1) { + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + switch (errno) { + case EBADF: + case ENOTSOCK: + case EFAULT: + case EINVAL: + status = NT_STATUS_INVALID_PARAMETER; + break; + case EMSGSIZE: + status = NT_STATUS_INVALID_BUFFER_SIZE; + break; + case EAGAIN: + /*case EWOULDBLOCK: this is an alis of EAGAIN --metze */ + case EINTR: + *sendlen = 0; + status = STATUS_MORE_ENTRIES; + break; + case ENOBUFS: + status = NT_STATUS_FOOBAR; + break; + case ENOMEM: + status = NT_STATUS_NO_MEMORY; + break; + case EPIPE: + status = NT_STATUS_CONNECTION_DISCONNECTED; + break; + } + return status; + } + + *sendlen = len; + + return NT_STATUS_OK; +} + +static NTSTATUS unixdom_set_option(struct socket_context *sock, + const char *option, const char *val) +{ + set_socket_options(sock->fd, option); + return NT_STATUS_OK; +} + +static char *unixdom_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return talloc_strdup(mem_ctx, "LOCAL/unixdom"); +} + +static char *unixdom_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return talloc_strdup(mem_ctx, "LOCAL/unixdom"); +} + +static int unixdom_get_peer_port(struct socket_context *sock) +{ + return 0; +} + +static char *unixdom_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + return talloc_strdup(mem_ctx, "LOCAL/unixdom"); +} + +static int unixdom_get_my_port(struct socket_context *sock) +{ + return 0; +} + +static int unixdom_get_fd(struct socket_context *sock) +{ + return sock->fd; +} + +static const struct socket_ops unixdom_ops = { + .name = "unix", + .type = SOCKET_TYPE_STREAM, + + .init = unixdom_init, + .connect = unixdom_connect, + .listen = unixdom_listen, + .accept = unixdom_accept, + .recv = unixdom_recv, + .send = unixdom_send, + .close = unixdom_close, + + .set_option = unixdom_set_option, + + .get_peer_name = unixdom_get_peer_name, + .get_peer_addr = unixdom_get_peer_addr, + .get_peer_port = unixdom_get_peer_port, + .get_my_addr = unixdom_get_my_addr, + .get_my_port = unixdom_get_my_port, + + .get_fd = unixdom_get_fd +}; + +const struct socket_ops *socket_unixdom_ops(void) +{ + return &unixdom_ops; +} + +NTSTATUS socket_unixdom_init(void) +{ + return NT_STATUS_OK; +} -- cgit From 8d1e35e2435fc0d30534393c003a1a3388704679 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 05:12:59 +0000 Subject: r3014: got rid of the old intra-smbd messaging system in preparation for the new one (This used to be commit 283e38aeb210e048302dc2759a75879cfc81eeb5) --- source4/lib/basic.mk | 3 - source4/lib/dmallocmsg.c | 72 ------ source4/lib/messages.c | 566 ----------------------------------------------- source4/lib/tallocmsg.c | 59 ----- 4 files changed, 700 deletions(-) delete mode 100644 source4/lib/dmallocmsg.c delete mode 100644 source4/lib/messages.c delete mode 100644 source4/lib/tallocmsg.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 93309ce68b..b6f30b6feb 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -37,9 +37,6 @@ ADD_OBJ_FILES = \ lib/fsusage.o \ lib/ms_fnmatch.o \ lib/select.o \ - lib/messages.o \ - lib/tallocmsg.o \ - lib/dmallocmsg.o \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/gencache.o \ diff --git a/source4/lib/dmallocmsg.c b/source4/lib/dmallocmsg.c deleted file mode 100644 index a83ed518d7..0000000000 --- a/source4/lib/dmallocmsg.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - samba -- Unix SMB/CIFS implementation. - Copyright (C) 2002 by Martin Pool - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/** - * @file dmallocmsg.c - * - * Glue code to cause dmalloc info to come out when we receive a prod - * over samba messaging. - **/ - -#ifdef ENABLE_DMALLOC -static unsigned long our_dm_mark = 0; -#endif /* ENABLE_DMALLOC */ - - -/** - * Respond to a POOL_USAGE message by sending back string form of memory - * usage stats. - **/ -static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid), - void *UNUSED(buf), size_t UNUSED(len)) -{ -#ifdef ENABLE_DMALLOC - our_dm_mark = dmalloc_mark(); - DEBUG(2,("Got MSG_REQ_DMALLOC_MARK: mark set\n")); -#else - DEBUG(2,("Got MSG_REQ_DMALLOC_MARK but dmalloc not in this process\n")); -#endif -} - - - -static void msg_req_dmalloc_log_changed(int UNUSED(msg_type), - pid_t UNUSED(src_pid), - void *UNUSED(buf), size_t UNUSED(len)) -{ -#ifdef ENABLE_DMALLOC - dmalloc_log_changed(our_dm_mark, True, True, True); - DEBUG(2,("Got MSG_REQ_DMALLOC_LOG_CHANGED: done\n")); -#else - DEBUG(2,("Got MSG_REQ_DMALLOC_LOG_CHANGED but dmalloc not in this process\n")); -#endif -} - - -/** - * Register handler for MSG_REQ_POOL_USAGE - **/ -void register_dmalloc_msgs(void) -{ - message_register(MSG_REQ_DMALLOC_MARK, msg_req_dmalloc_mark); - message_register(MSG_REQ_DMALLOC_LOG_CHANGED, msg_req_dmalloc_log_changed); - DEBUG(2, ("Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED\n")); -} diff --git a/source4/lib/messages.c b/source4/lib/messages.c deleted file mode 100644 index 64dc2f510a..0000000000 --- a/source4/lib/messages.c +++ /dev/null @@ -1,566 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba internal messaging functions - Copyright (C) Andrew Tridgell 2000 - Copyright (C) 2001 by Martin Pool - Copyright (C) 2002 by Jeremy Allison - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/** - @defgroup messages Internal messaging framework - @{ - @file messages.c - - @brief Module for internal messaging between Samba daemons. - - The idea is that if a part of Samba wants to do communication with - another Samba process then it will do a message_register() of a - dispatch function, and use message_send_pid() to send messages to - that process. - - The dispatch function is given the pid of the sender, and it can - use that to reply by message_send_pid(). See ping_message() for a - simple example. - - @caution Dispatch functions must be able to cope with incoming - messages on an *odd* byte boundary. - - This system doesn't have any inherent size limitations but is not - very efficient for large messages or when messages are sent in very - quick succession. - -*/ - -#include "includes.h" - -/* the locking database handle */ -static struct tdb_wrap *tdb; -static int received_signal; - -/* change the message version with any incompatible changes in the protocol */ -#define MESSAGE_VERSION 1 - -struct message_rec { - int msg_version; - int msg_type; - pid_t dest; - pid_t src; - size_t len; -}; - -/* we have a linked list of dispatch handlers */ -static struct dispatch_fns { - struct dispatch_fns *next, *prev; - int msg_type; - void (*fn)(int msg_type, pid_t pid, void *buf, size_t len); -} *dispatch_fns; - -/**************************************************************************** - Notifications come in as signals. -****************************************************************************/ - -static void sig_usr1(void) -{ - received_signal = 1; - sys_select_signal(); -} - -/**************************************************************************** - A useful function for testing the message system. -****************************************************************************/ - -static void ping_message(int msg_type, pid_t src, void *buf, size_t len) -{ - const char *msg = buf ? buf : "none"; - DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(uint_t)src, msg)); - message_send_pid(src, MSG_PONG, buf, len, True); -} - -/**************************************************************************** - Initialise the messaging functions. -****************************************************************************/ - -BOOL message_init(void) -{ - TALLOC_CTX *mem_ctx; - - if (tdb) return True; - - mem_ctx = talloc_init("message_init"); - if (!mem_ctx) { - DEBUG(0,("ERROR: No memory to initialise messages database\n")); - return False; - } - tdb = tdb_wrap_open(NULL, lock_path(mem_ctx, "messages.tdb"), - 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR|O_CREAT,0600); - talloc_destroy(mem_ctx); - - if (!tdb) { - DEBUG(0,("ERROR: Failed to initialise messages database\n")); - return False; - } - - CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1); - - message_register(MSG_PING, ping_message); - - return True; -} - -/******************************************************************* - Form a static tdb key from a pid. -******************************************************************/ - -static TDB_DATA message_key_pid(pid_t pid) -{ - static char key[20]; - TDB_DATA kbuf; - - slprintf(key, sizeof(key)-1, "PID/%d", (int)pid); - - kbuf.dptr = (char *)key; - kbuf.dsize = strlen(key)+1; - return kbuf; -} - -/**************************************************************************** - Notify a process that it has a message. If the process doesn't exist - then delete its record in the database. -****************************************************************************/ - -static BOOL message_notify(pid_t pid) -{ - /* - * Doing kill with a non-positive pid causes messages to be - * sent to places we don't want. - */ - - SMB_ASSERT(pid > 0); - - if (kill(pid, SIGUSR1) == -1) { - if (errno == ESRCH) { - DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); - tdb_delete(tdb->tdb, message_key_pid(pid)); - } else { - DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); - } - return False; - } - return True; -} - -/**************************************************************************** - Send a message to a particular pid. -****************************************************************************/ - -static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, uint_t timeout) -{ - TDB_DATA kbuf; - TDB_DATA dbuf; - TDB_DATA old_dbuf; - struct message_rec rec; - char *ptr; - struct message_rec prec; - - /* - * Doing kill with a non-positive pid causes messages to be - * sent to places we don't want. - */ - - SMB_ASSERT(pid > 0); - - rec.msg_version = MESSAGE_VERSION; - rec.msg_type = msg_type; - rec.dest = pid; - rec.src = getpid(); - rec.len = len; - - kbuf = message_key_pid(pid); - - dbuf.dptr = (void *)malloc(len + sizeof(rec)); - if (!dbuf.dptr) - return False; - - memcpy(dbuf.dptr, &rec, sizeof(rec)); - if (len > 0) - memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len); - - dbuf.dsize = len + sizeof(rec); - - if (duplicates_allowed) { - - /* If duplicates are allowed we can just append the message and return. */ - - /* lock the record for the destination */ - if (timeout) { - if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); - return False; - } - } else { - if (tdb_chainlock(tdb->tdb, kbuf) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); - return False; - } - } - tdb_append(tdb->tdb, kbuf, dbuf); - tdb_chainunlock(tdb->tdb, kbuf); - - SAFE_FREE(dbuf.dptr); - errno = 0; /* paranoia */ - return message_notify(pid); - } - - /* lock the record for the destination */ - if (timeout) { - if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); - return False; - } - } else { - if (tdb_chainlock(tdb->tdb, kbuf) == -1) { - DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); - return False; - } - } - - old_dbuf = tdb_fetch(tdb->tdb, kbuf); - - if (!old_dbuf.dptr) { - /* its a new record */ - - tdb_store(tdb->tdb, kbuf, dbuf, TDB_REPLACE); - tdb_chainunlock(tdb->tdb, kbuf); - - SAFE_FREE(dbuf.dptr); - errno = 0; /* paranoia */ - return message_notify(pid); - } - - /* Not a new record. Check for duplicates. */ - - for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) { - /* - * First check if the message header matches, then, if it's a non-zero - * sized message, check if the data matches. If so it's a duplicate and - * we can discard it. JRA. - */ - - if (!memcmp(ptr, &rec, sizeof(rec))) { - if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { - tdb_chainunlock(tdb->tdb, kbuf); - DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); - SAFE_FREE(dbuf.dptr); - SAFE_FREE(old_dbuf.dptr); - return True; - } - } - memcpy(&prec, ptr, sizeof(prec)); - ptr += sizeof(rec) + prec.len; - } - - /* we're adding to an existing entry */ - - tdb_append(tdb->tdb, kbuf, dbuf); - tdb_chainunlock(tdb->tdb, kbuf); - - SAFE_FREE(old_dbuf.dptr); - SAFE_FREE(dbuf.dptr); - - errno = 0; /* paranoia */ - return message_notify(pid); -} - -/**************************************************************************** - Send a message to a particular pid - no timeout. -****************************************************************************/ - -BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed) -{ - return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0); -} - -/**************************************************************************** - Send a message to a particular pid, with timeout in seconds. -****************************************************************************/ - -BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, uint_t timeout) -{ - return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout); -} - -/**************************************************************************** - Retrieve all messages for the current process. -****************************************************************************/ - -static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) -{ - TDB_DATA kbuf; - TDB_DATA dbuf; - TDB_DATA null_dbuf; - - ZERO_STRUCT(null_dbuf); - - *msgs_buf = NULL; - *total_len = 0; - - kbuf = message_key_pid(getpid()); - - tdb_chainlock(tdb->tdb, kbuf); - dbuf = tdb_fetch(tdb->tdb, kbuf); - /* - * Replace with an empty record to keep the allocated - * space in the tdb. - */ - tdb_store(tdb->tdb, kbuf, null_dbuf, TDB_REPLACE); - tdb_chainunlock(tdb->tdb, kbuf); - - if (dbuf.dptr == NULL || dbuf.dsize == 0) { - SAFE_FREE(dbuf.dptr); - return False; - } - - *msgs_buf = dbuf.dptr; - *total_len = dbuf.dsize; - - return True; -} - -/**************************************************************************** - Parse out the next message for the current process. -****************************************************************************/ - -static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t *src, char **buf, size_t *len) -{ - struct message_rec rec; - char *ret_buf = *buf; - - *buf = NULL; - *len = 0; - - if (total_len - (ret_buf - msgs_buf) < sizeof(rec)) - return False; - - memcpy(&rec, ret_buf, sizeof(rec)); - ret_buf += sizeof(rec); - - if (rec.msg_version != MESSAGE_VERSION) { - DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION)); - return False; - } - - if (rec.len > 0) { - if (total_len - (ret_buf - msgs_buf) < rec.len) - return False; - } - - *len = rec.len; - *msg_type = rec.msg_type; - *src = rec.src; - *buf = ret_buf; - - return True; -} - -/**************************************************************************** - Receive and dispatch any messages pending for this process. - Notice that all dispatch handlers for a particular msg_type get called, - so you can register multiple handlers for a message. - *NOTE*: Dispatch functions must be able to cope with incoming - messages on an *odd* byte boundary. -****************************************************************************/ - -void message_dispatch(void) -{ - int msg_type; - pid_t src; - char *buf; - char *msgs_buf; - size_t len, total_len; - struct dispatch_fns *dfn; - int n_handled; - - if (!received_signal) - return; - - DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal)); - - received_signal = 0; - - if (!retrieve_all_messages(&msgs_buf, &total_len)) - return; - - for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { - DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n", - msg_type, (uint_t) src)); - n_handled = 0; - for (dfn = dispatch_fns; dfn; dfn = dfn->next) { - if (dfn->msg_type == msg_type) { - DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type)); - dfn->fn(msg_type, src, len ? (void *)buf : NULL, len); - n_handled++; - } - } - if (!n_handled) { - DEBUG(5,("message_dispatch: warning: no handlers registed for " - "msg_type %d in pid %u\n", - msg_type, (uint_t)getpid())); - } - } - SAFE_FREE(msgs_buf); -} - -/**************************************************************************** - Register a dispatch function for a particular message type. - *NOTE*: Dispatch functions must be able to cope with incoming - messages on an *odd* byte boundary. -****************************************************************************/ - -void message_register(int msg_type, - void (*fn)(int msg_type, pid_t pid, void *buf, size_t len)) -{ - struct dispatch_fns *dfn; - - dfn = (struct dispatch_fns *)malloc(sizeof(*dfn)); - - if (dfn != NULL) { - - ZERO_STRUCTPN(dfn); - - dfn->msg_type = msg_type; - dfn->fn = fn; - - DLIST_ADD(dispatch_fns, dfn); - } - else { - - DEBUG(0,("message_register: Not enough memory. malloc failed!\n")); - } -} - -/**************************************************************************** - De-register the function for a particular message type. -****************************************************************************/ - -void message_deregister(int msg_type) -{ - struct dispatch_fns *dfn, *next; - - for (dfn = dispatch_fns; dfn; dfn = next) { - next = dfn->next; - if (dfn->msg_type == msg_type) { - DLIST_REMOVE(dispatch_fns, dfn); - SAFE_FREE(dfn); - } - } -} - -struct msg_all { - int msg_type; - uint32_t msg_flag; - const void *buf; - size_t len; - BOOL duplicates; - int n_sent; -}; - -/**************************************************************************** - Send one of the messages for the broadcast. -****************************************************************************/ - -static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) -{ - struct connections_data crec; - struct msg_all *msg_all = (struct msg_all *)state; - - if (dbuf.dsize != sizeof(crec)) - return 0; - - memcpy(&crec, dbuf.dptr, sizeof(crec)); - - if (crec.cnum != -1) - return 0; - - /* Don't send if the receiver hasn't registered an interest. */ - - if(!(crec.bcast_msg_flags & msg_all->msg_flag)) - return 0; - - /* If the msg send fails because the pid was not found (i.e. smbd died), - * the msg has already been deleted from the messages.tdb.*/ - - if (!message_send_pid(crec.pid, msg_all->msg_type, - msg_all->buf, msg_all->len, - msg_all->duplicates)) { - - /* If the pid was not found delete the entry from connections.tdb */ - - if (errno == ESRCH) { - DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", - (uint_t)crec.pid, crec.cnum, crec.name)); - tdb_delete(the_tdb, kbuf); - } - } - msg_all->n_sent++; - return 0; -} - -/** - * Send a message to all smbd processes. - * - * It isn't very efficient, but should be OK for the sorts of - * applications that use it. When we need efficient broadcast we can add - * it. - * - * @param n_sent Set to the number of messages sent. This should be - * equal to the number of processes, but be careful for races. - * - * @retval True for success. - **/ -BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, - const void *buf, size_t len, - BOOL duplicates_allowed, - int *n_sent) -{ - struct msg_all msg_all; - - msg_all.msg_type = msg_type; - if (msg_type < 1000) - msg_all.msg_flag = FLAG_MSG_GENERAL; - else if (msg_type > 1000 && msg_type < 2000) - msg_all.msg_flag = FLAG_MSG_NMBD; - else if (msg_type > 2000 && msg_type < 3000) - msg_all.msg_flag = FLAG_MSG_PRINTING; - else if (msg_type > 3000 && msg_type < 4000) - msg_all.msg_flag = FLAG_MSG_SMBD; - else - return False; - - msg_all.buf = buf; - msg_all.len = len; - msg_all.duplicates = duplicates_allowed; - msg_all.n_sent = 0; - - tdb_traverse(conn_tdb, traverse_fn, &msg_all); - if (n_sent) - *n_sent = msg_all.n_sent; - return True; -} -/** @} **/ diff --git a/source4/lib/tallocmsg.c b/source4/lib/tallocmsg.c deleted file mode 100644 index 22870a934a..0000000000 --- a/source4/lib/tallocmsg.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - samba -- Unix SMB/CIFS implementation. - Copyright (C) 2001, 2002 by Martin Pool - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/** - * @file tallocmsg.c - * - * Glue code between talloc profiling and the Samba messaging system. - **/ - - -/** - * Respond to a POOL_USAGE message by sending back string form of memory - * usage stats. - **/ -void msg_pool_usage(int msg_type, pid_t src_pid, - void *UNUSED(buf), size_t UNUSED(len)) -{ - const char *reply="NOT IMPLEMENTED\n"; - TALLOC_CTX *reply_pool = talloc_init("msg_pool_usage"); - - SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); - - DEBUG(2,("Got POOL_USAGE\n")); - -#if 0 - reply = talloc_describe_all(reply_pool); -#endif - message_send_pid(src_pid, MSG_POOL_USAGE, - reply, strlen(reply)+1, True); - - talloc_destroy(reply_pool); -} - -/** - * Register handler for MSG_REQ_POOL_USAGE - **/ -void register_msg_pool_usage(void) -{ - message_register(MSG_REQ_POOL_USAGE, msg_pool_usage); - DEBUG(2, ("Registered MSG_REQ_POOL_USAGE\n")); -} -- cgit From 844de2b65c931120a2408365c00fa80cb65959fc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 05:29:03 +0000 Subject: r3015: fixed typo noticed by abartlett (This used to be commit b367209a9f94e471efed233639467babbb2b99d7) --- source4/lib/socket/socket.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index f364ca7c9f..f70a76262b 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -236,12 +236,13 @@ int socket_get_fd(struct socket_context *sock) const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) { - if (strequal("ip", name) || strequal("ipv4", name)) { + if (strcmp("ip", name) == 0 || + strcmp("ipv4", name) == 0) { return socket_ipv4_ops(); } - if (strequal("unix", name)) { - return socket_ipv4_ops(); + if (strcmp("unix", name) == 0) { + return socket_unixdom_ops(); } return NULL; -- cgit From 6591a226144d371a6b68fc5e7201a90a77dc9153 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 10:04:49 +0000 Subject: r3016: - converted the events code to talloc - added the new messaging system, based on unix domain sockets. It gets over 10k messages/second on my laptop without any socket cacheing, which is better than I expected. - added a LOCAL-MESSAGING torture test (This used to be commit 3af06478da7ab34a272226d8d9ac87e0a4940cfb) --- source4/lib/events.c | 46 +--- source4/lib/messaging/config.m4 | 1 + source4/lib/messaging/config.mk | 8 + source4/lib/messaging/messaging.c | 445 ++++++++++++++++++++++++++++++++++++++ source4/lib/socket/socket_unix.c | 10 + 5 files changed, 473 insertions(+), 37 deletions(-) create mode 100644 source4/lib/messaging/config.m4 create mode 100644 source4/lib/messaging/config.mk create mode 100644 source4/lib/messaging/messaging.c (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 4ae7cad8af..0e98b42503 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -71,11 +71,11 @@ call, and all subsequent calls pass this event_context as the first element. Event handlers also receive this as their first argument. */ -struct event_context *event_context_init(void) +struct event_context *event_context_init(TALLOC_CTX *mem_ctx) { struct event_context *ev; - ev = malloc(sizeof(*ev)); + ev = talloc_p(mem_ctx, struct event_context); if (!ev) return NULL; /* start off with no events */ @@ -91,40 +91,12 @@ struct event_context *event_context_init(void) */ void event_context_destroy(struct event_context *ev) { - struct fd_event *fde; - struct timed_event *te; - struct loop_event *le; - ev->ref_count--; if (ev->ref_count != 0) { return; } - for (fde=ev->fd_events; fde;) { - struct fd_event *next = fde->next; - event_remove_fd(ev, fde); - if (fde->ref_count == 0) { - free(fde); - } - fde=next; - } - for (te=ev->timed_events; te;) { - struct timed_event *next = te->next; - event_remove_timed(ev, te); - if (te->ref_count == 0) { - free(te); - } - te=next; - } - for (le=ev->loop_events; le;) { - struct loop_event *next = le->next; - event_remove_loop(ev, le); - if (le->ref_count == 0) { - free(le); - } - le=next; - } - free(ev); + talloc_free(ev); } @@ -175,7 +147,7 @@ struct event_context * event_context_merge(struct event_context *ev, struct even */ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) { - e = memdup(e, sizeof(*e)); + e = talloc_memdup(ev, e, sizeof(*e)); if (!e) return NULL; DLIST_ADD(ev->fd_events, e); e->ref_count = 1; @@ -245,7 +217,7 @@ void event_remove_fd_all_handler(struct event_context *ev, void *handler) */ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) { - e = memdup(e, sizeof(*e)); + e = talloc_memdup(ev, e, sizeof(*e)); if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->timed_events, e); @@ -274,7 +246,7 @@ BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) */ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e) { - e = memdup(e, sizeof(*e)); + e = talloc_memdup(ev, e, sizeof(*e)); if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->loop_events, e); @@ -330,7 +302,7 @@ int event_loop_once(struct event_context *ev) struct loop_event *next = le->next; if (le->ref_count == 0) { DLIST_REMOVE(ev->loop_events, le); - free(le); + talloc_unlink(ev, le); } else { le->ref_count++; le->handler(ev, le, t); @@ -351,7 +323,7 @@ int event_loop_once(struct event_context *ev) if (ev->maxfd == fe->fd) { ev->maxfd = EVENT_INVALID_MAXFD; } - free(fe); + talloc_unlink(ev, fe); } else { if (fe->flags & EVENT_FD_READ) { FD_SET(fe->fd, &r_fds); @@ -432,7 +404,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (te->ref_count == 0) { DLIST_REMOVE(ev->timed_events, te); - free(te); + talloc_unlink(ev, te); } else if (te->next_event <= t) { te->ref_count++; te->handler(ev, te, t); diff --git a/source4/lib/messaging/config.m4 b/source4/lib/messaging/config.m4 new file mode 100644 index 0000000000..1797069ff2 --- /dev/null +++ b/source4/lib/messaging/config.m4 @@ -0,0 +1 @@ +SMB_SUBSYSTEM_MK(MESSAGING,lib/messaging/config.mk) diff --git a/source4/lib/messaging/config.mk b/source4/lib/messaging/config.mk new file mode 100644 index 0000000000..6c30894779 --- /dev/null +++ b/source4/lib/messaging/config.mk @@ -0,0 +1,8 @@ + +################################################ +# Start SUBSYSTEM MESSAGING +[SUBSYSTEM::MESSAGING] +INIT_OBJ_FILES = \ + lib/messaging/messaging.o +# End SUBSYSTEM MESSAGING +################################################ diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c new file mode 100644 index 0000000000..f9caf5071c --- /dev/null +++ b/source4/lib/messaging/messaging.c @@ -0,0 +1,445 @@ +/* + Unix SMB/CIFS implementation. + + Samba internal messaging functions + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* change the message version with any incompatible changes in the protocol */ +#define MESSAGING_VERSION 1 + +struct messaging_state { + servid_t server_id; + struct socket_context *sock; + char *path; + struct dispatch_fn *dispatch; + + struct { + struct event_context *ev; + struct fd_event *fde; + } event; +}; + +/* we have a linked list of dispatch handlers that this messaging + server can deal with */ +struct dispatch_fn { + struct dispatch_fn *next, *prev; + uint32_t msg_type; + void *private; + void (*fn)(void *msg_ctx, void *private, + uint32_t msg_type, servid_t server_id, DATA_BLOB *data); +}; + +/* an individual message */ +struct messaging_rec { + struct messaging_rec *next, *prev; + + struct messaging_state *msg; + struct socket_context *sock; + struct fd_event *fde; + const char *path; + + struct { + uint32_t version; + uint32_t msg_type; + servid_t from; + servid_t to; + uint32_t length; + } header; + + DATA_BLOB data; + + uint32_t ndone; +}; + +/* + A useful function for testing the message system. +*/ +static void ping_message(void *msg_ctx, void *private, + uint32_t msg_type, servid_t src, DATA_BLOB *data) +{ + DEBUG(1,("INFO: Received PING message from server %u [%.*s]\n", + (uint_t)src, data->length, data->data?(const char *)data->data:"")); + messaging_send(msg_ctx, src, MSG_PONG, data); +} + +/* + return the path to a messaging socket +*/ +static char *messaging_path(TALLOC_CTX *mem_ctx, servid_t server_id) +{ + char *name = talloc_asprintf(mem_ctx, "messaging/msg.%u", (unsigned)server_id); + char *ret; + ret = lock_path(mem_ctx, name); + talloc_free(name); + return ret; +} + +/* + dispatch a fully received message +*/ +static void messaging_dispatch(struct messaging_state *msg, struct messaging_rec *rec) +{ + struct dispatch_fn *d; + for (d=msg->dispatch;d;d=d->next) { + if (d->msg_type == rec->header.msg_type) { + d->fn(msg, d->private, d->msg_type, rec->header.from, &rec->data); + } + } + + /* we don't free the record itself here as there may + be more messages from this client */ + data_blob_free(&rec->data); + rec->header.length = 0; + rec->ndone = 0; +} + + +/* + handle IO for a single message +*/ +static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, + time_t t, uint16_t flags) +{ + struct messaging_rec *rec = fde->private; + struct messaging_state *msg = rec->msg; + NTSTATUS status; + + if (rec->ndone < sizeof(rec->header)) { + /* receive the header */ + DATA_BLOB blob; + status = socket_recv(rec->sock, rec, + &blob, sizeof(rec->header) - rec->ndone, 0); + if (NT_STATUS_IS_ERR(status)) { + talloc_free(rec); + return; + } + + if (blob.length == 0) { + return; + } + + memcpy(rec->ndone + (char *)&rec->header, blob.data, blob.length); + rec->ndone += blob.length; + data_blob_free(&blob); + + if (rec->ndone == sizeof(rec->header)) { + if (rec->header.version != MESSAGING_VERSION) { + DEBUG(0,("meessage with wrong version %u\n", + rec->header.version)); + talloc_free(rec); + } + rec->data = data_blob_talloc(rec, NULL, rec->header.length); + if (rec->data.length != rec->header.length) { + DEBUG(0,("Unable to allocate message of size %u\n", + rec->header.length)); + talloc_free(rec); + } + } + } + + if (rec->ndone >= sizeof(rec->header) && + rec->ndone < sizeof(rec->header) + rec->header.length) { + /* receive the body, if any */ + DATA_BLOB blob; + status = socket_recv(rec->sock, rec, + &blob, sizeof(rec->header) + rec->header.length - rec->ndone, 0); + if (NT_STATUS_IS_ERR(status)) { + talloc_free(rec); + return; + } + + if (blob.length == 0) { + return; + } + + memcpy(rec->data.data + (rec->ndone - sizeof(rec->header)), + blob.data, blob.length); + + rec->ndone += blob.length; + } + + if (rec->ndone == sizeof(rec->header) + rec->header.length) { + /* we've got the whole message */ + messaging_dispatch(msg, rec); + } +} + +/* + destroy a messaging record +*/ +static int rec_destructor(void *ptr) +{ + struct messaging_rec *rec = ptr; + struct messaging_state *msg = rec->msg; + event_remove_fd(msg->event.ev, rec->fde); + return 0; +} + +/* + handle a new incoming connection +*/ +static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, + time_t t, uint16_t flags) +{ + struct messaging_state *msg = fde->private; + struct messaging_rec *rec; + NTSTATUS status; + struct fd_event fde2; + + rec = talloc_p(msg, struct messaging_rec); + if (rec == NULL) { + smb_panic("Unable to allocate messaging_rec"); + } + + status = socket_accept(msg->sock, &rec->sock, 0); + if (!NT_STATUS_IS_OK(status)) { + smb_panic("Unable to accept messaging_rec"); + } + talloc_steal(rec, rec->sock); + + rec->msg = msg; + rec->ndone = 0; + rec->header.length = 0; + rec->path = msg->path; + + fde2.private = rec; + fde2.fd = socket_get_fd(rec->sock); + fde2.flags = EVENT_FD_READ; + fde2.handler = messaging_recv_handler; + + rec->fde = event_add_fd(msg->event.ev, &fde2); + + talloc_set_destructor(rec, rec_destructor); +} + +/* + Register a dispatch function for a particular message type. +*/ +void messaging_register(void *ctx, void *private, + uint32_t msg_type, + void (*fn)(void *, void *, uint32_t, servid_t, DATA_BLOB *)) +{ + struct messaging_state *msg = ctx; + struct dispatch_fn *d; + + d = talloc_p(msg, struct dispatch_fn); + d->msg_type = msg_type; + d->private = private; + d->fn = fn; + DLIST_ADD(msg->dispatch, d); +} + +/* + De-register the function for a particular message type. +*/ +void messaging_deregister(void *ctx, uint32_t msg_type) +{ + struct messaging_state *msg = ctx; + struct dispatch_fn *d, *next; + + for (d = msg->dispatch; d; d = next) { + next = d->next; + if (d->msg_type == msg_type) { + DLIST_REMOVE(msg->dispatch, d); + talloc_free(d); + } + } +} + + + +/* + handle IO for sending a message +*/ +static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, + time_t t, uint16_t flags) +{ + struct messaging_rec *rec = fde->private; + NTSTATUS status; + + if (rec->ndone < sizeof(rec->header)) { + /* send the header */ + size_t nsent; + DATA_BLOB blob; + + blob.data = rec->ndone + (char *)&rec->header; + blob.length = sizeof(rec->header) - rec->ndone; + + status = socket_send(rec->sock, rec, &blob, &nsent, 0); + if (NT_STATUS_IS_ERR(status)) { + talloc_free(rec); + return; + } + + if (nsent == 0) { + return; + } + + rec->ndone += nsent; + } + + if (rec->ndone >= sizeof(rec->header) && + rec->ndone < sizeof(rec->header) + rec->header.length) { + /* send the body, if any */ + DATA_BLOB blob; + size_t nsent; + + blob.data = rec->data.data + (rec->ndone - sizeof(rec->header)); + blob.length = rec->header.length - (rec->ndone - sizeof(rec->header)); + + status = socket_send(rec->sock, rec, &blob, &nsent, 0); + if (NT_STATUS_IS_ERR(status)) { + talloc_free(rec); + return; + } + + rec->ndone += nsent; + } + + if (rec->ndone == sizeof(rec->header) + rec->header.length) { + /* we've done the whole message */ + talloc_free(rec); + } +} + + +/* + Send a message to a particular server +*/ +NTSTATUS messaging_send(void *msg_ctx, servid_t server, uint32_t msg_type, DATA_BLOB *data) +{ + struct messaging_state *msg = msg_ctx; + struct messaging_rec *rec; + NTSTATUS status; + struct fd_event fde; + + rec = talloc_p(msg, struct messaging_rec); + if (rec == NULL) { + return NT_STATUS_NO_MEMORY; + } + + rec->msg = msg; + rec->header.version = MESSAGING_VERSION; + rec->header.msg_type = msg_type; + rec->header.from = msg->server_id; + rec->header.to = server; + rec->header.length = data?data->length:0; + if (rec->header.length != 0) { + rec->data = data_blob_talloc(rec, data->data, data->length); + } else { + rec->data = data_blob(NULL, 0); + } + rec->ndone = 0; + + status = socket_create("unix", SOCKET_TYPE_STREAM, &rec->sock, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(rec); + return status; + } + talloc_steal(rec, rec->sock); + + rec->path = messaging_path(rec, server); + + status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(rec); + return status; + } + + fde.private = rec; + fde.fd = socket_get_fd(rec->sock); + fde.flags = EVENT_FD_WRITE; + fde.handler = messaging_send_handler; + + rec->fde = event_add_fd(msg->event.ev, &fde); + + talloc_set_destructor(rec, rec_destructor); + + return NT_STATUS_OK; +} + + +/* + destroy the messaging context +*/ +static int messaging_destructor(void *msg_ctx) +{ + struct messaging_state *msg = msg_ctx; + event_remove_fd(msg->event.ev, msg->event.fde); + return 0; +} + +/* + create the listening socket and setup the dispatcher +*/ +void *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id, struct event_context *ev) +{ + struct messaging_state *msg; + NTSTATUS status; + struct fd_event fde; + + msg = talloc_p(mem_ctx, struct messaging_state); + if (msg == NULL) { + return NULL; + } + + /* create the messaging directory if needed */ + msg->path = lock_path(msg, "messaging"); + mkdir(msg->path, 0700); + talloc_free(msg->path); + + msg->server_id = server_id; + msg->dispatch = NULL; + msg->path = messaging_path(msg, server_id); + + status = socket_create("unix", SOCKET_TYPE_STREAM, &msg->sock, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(msg); + return NULL; + } + + /* by stealing here we ensure that the socket is cleaned up (and even + deleted) on exit */ + talloc_steal(msg, msg->sock); + + status = socket_listen(msg->sock, msg->path, 0, 50, 0); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to setup messaging listener for '%s'\n", msg->path)); + talloc_free(msg); + return NULL; + } + + fde.private = msg; + fde.fd = socket_get_fd(msg->sock); + fde.flags = EVENT_FD_READ; + fde.handler = messaging_listen_handler; + + msg->event.ev = ev; + msg->event.fde = event_add_fd(ev, &fde); + + talloc_set_destructor(msg, messaging_destructor); + + messaging_register(msg, NULL, MSG_PING, ping_message); + + return msg; +} + + diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index d87eaf49c4..7e169c47a7 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -29,6 +29,7 @@ static NTSTATUS unixdom_init(struct socket_context *sock) if (sock->fd == -1) { return NT_STATUS_INSUFFICIENT_RESOURCES; } + sock->private_data = NULL; return NT_STATUS_OK; } @@ -36,6 +37,11 @@ static NTSTATUS unixdom_init(struct socket_context *sock) static void unixdom_close(struct socket_context *sock) { close(sock->fd); + /* if we were listening, then don't leave the socket lying + around in the filesystem */ + if (sock->private_data) { + unlink((const char *)sock->private_data); + } } static NTSTATUS unixdom_connect(struct socket_context *sock, @@ -82,6 +88,9 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, return NT_STATUS_INVALID_PARAMETER; } + /* delete if it already exists */ + unlink(my_address); + ZERO_STRUCT(my_addr); my_addr.sun_family = AF_UNIX; strncpy(my_addr.sun_path, my_address, sizeof(my_addr.sun_path)); @@ -104,6 +113,7 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, } sock->state = SOCKET_STATE_SERVER_LISTEN; + sock->private_data = (void *)talloc_strdup(sock, my_address); return NT_STATUS_OK; } -- cgit From 53891ed37e32a97380430e6911878f3b94133e01 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 11:37:22 +0000 Subject: r3017: nicer memory handling for event_context_merge() (This used to be commit 1cef44505e5de9b8ae5206522b624082ad2343b2) --- source4/lib/events.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 0e98b42503..2cedfc083c 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -81,7 +81,7 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) /* start off with no events */ ZERO_STRUCTP(ev); - ev->ref_count = 1; + ev->events = talloc(ev, 0); return ev; } @@ -91,11 +91,6 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) */ void event_context_destroy(struct event_context *ev) { - ev->ref_count--; - if (ev->ref_count != 0) { - return; - } - talloc_free(ev); } @@ -121,18 +116,18 @@ static void calc_maxfd(struct event_context *ev) this is used by modules that need to call on the events of a lower module */ -struct event_context * event_context_merge(struct event_context *ev, struct event_context *ev2) +struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2) { DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *); DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *); DLIST_CONCATENATE(ev->loop_events, ev2->loop_events, struct loop_event *); - ev->ref_count++; - ev2->fd_events = NULL; ev2->timed_events = NULL; ev2->loop_events = NULL; + talloc_steal(ev->events, ev2->events); + event_context_destroy(ev2); calc_maxfd(ev); @@ -147,7 +142,7 @@ struct event_context * event_context_merge(struct event_context *ev, struct even */ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) { - e = talloc_memdup(ev, e, sizeof(*e)); + e = talloc_memdup(ev->events, e, sizeof(*e)); if (!e) return NULL; DLIST_ADD(ev->fd_events, e); e->ref_count = 1; @@ -217,7 +212,7 @@ void event_remove_fd_all_handler(struct event_context *ev, void *handler) */ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) { - e = talloc_memdup(ev, e, sizeof(*e)); + e = talloc_memdup(ev->events, e, sizeof(*e)); if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->timed_events, e); @@ -246,7 +241,7 @@ BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) */ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e) { - e = talloc_memdup(ev, e, sizeof(*e)); + e = talloc_memdup(ev->events, e, sizeof(*e)); if (!e) return NULL; e->ref_count = 1; DLIST_ADD(ev->loop_events, e); @@ -302,7 +297,7 @@ int event_loop_once(struct event_context *ev) struct loop_event *next = le->next; if (le->ref_count == 0) { DLIST_REMOVE(ev->loop_events, le); - talloc_unlink(ev, le); + talloc_unlink(ev->events, le); } else { le->ref_count++; le->handler(ev, le, t); @@ -323,7 +318,7 @@ int event_loop_once(struct event_context *ev) if (ev->maxfd == fe->fd) { ev->maxfd = EVENT_INVALID_MAXFD; } - talloc_unlink(ev, fe); + talloc_unlink(ev->events, fe); } else { if (fe->flags & EVENT_FD_READ) { FD_SET(fe->fd, &r_fds); @@ -404,7 +399,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (te->ref_count == 0) { DLIST_REMOVE(ev->timed_events, te); - talloc_unlink(ev, te); + talloc_unlink(ev->events, te); } else if (te->next_event <= t) { te->ref_count++; te->handler(ev, te, t); -- cgit From 5882311fc46132e0f939d3297fd98787ebac41f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 12:41:04 +0000 Subject: r3018: handle STATUS_MORE_ENTRIES from socket_recv() in the messaging code (This used to be commit 13739b68d8357d5d330f12b851d0311feb81e545) --- source4/lib/messaging/messaging.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index f9caf5071c..7e87ea45df 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -125,6 +125,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd if (rec->ndone < sizeof(rec->header)) { /* receive the header */ DATA_BLOB blob; + blob.length = 0; status = socket_recv(rec->sock, rec, &blob, sizeof(rec->header) - rec->ndone, 0); if (NT_STATUS_IS_ERR(status)) { @@ -159,6 +160,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd rec->ndone < sizeof(rec->header) + rec->header.length) { /* receive the body, if any */ DATA_BLOB blob; + blob.length = 0; status = socket_recv(rec->sock, rec, &blob, sizeof(rec->header) + rec->header.length - rec->ndone, 0); if (NT_STATUS_IS_ERR(status)) { -- cgit From b071fe60d7c819935064d9b3c66cbf8b6696e4f8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 13:21:24 +0000 Subject: r3020: better error handling in socket_unix (This used to be commit 64514ff5b7734667a1364de925114091fe208b3a) --- source4/lib/socket/socket_unix.c | 93 +++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 50 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 7e169c47a7..1735c931b8 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -23,6 +23,40 @@ #include "includes.h" + + +/* + approximate errno mapping +*/ +static NTSTATUS unixdom_error(int ernum) +{ + switch (ernum) { + case EBADF: + case ENOTCONN: + case ENOTSOCK: + case EFAULT: + case EINVAL: + return NT_STATUS_INVALID_PARAMETER; + case EAGAIN: + case EINTR: + return STATUS_MORE_ENTRIES; + case ECONNREFUSED: + return NT_STATUS_CONNECTION_REFUSED; + case ENOBUFS: + case ENOMEM: + return NT_STATUS_NO_MEMORY; + case ENFILE: + case EMFILE: + return NT_STATUS_INSUFFICIENT_RESOURCES; + case EPIPE: + return NT_STATUS_CONNECTION_DISCONNECTED; + case EMSGSIZE: + return NT_STATUS_INVALID_BUFFER_SIZE; + } + + return NT_STATUS_UNSUCCESSFUL; +} + static NTSTATUS unixdom_init(struct socket_context *sock) { sock->fd = socket(PF_UNIX, SOCK_STREAM, 0); @@ -69,7 +103,7 @@ static NTSTATUS unixdom_connect(struct socket_context *sock, ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (ret == -1) { - return NT_STATUS_CONNECTION_REFUSED; + return unixdom_error(errno); } sock->state = SOCKET_STATE_CLIENT_CONNECTED; @@ -97,18 +131,18 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { - return NT_STATUS_UNSUCCESSFUL; + return unixdom_error(errno); } ret = listen(sock->fd, queue_size); if (ret == -1) { - return NT_STATUS_INSUFFICIENT_RESOURCES; + return unixdom_error(errno); } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, False); if (ret == -1) { - return NT_STATUS_INVALID_PARAMETER; + return unixdom_error(errno); } } @@ -128,7 +162,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { - return NT_STATUS_INSUFFICIENT_RESOURCES; + return unixdom_error(errno); } (*new_sock) = talloc_p(NULL, struct socket_context); @@ -180,23 +214,7 @@ static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, talloc_free(buf); return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - switch (errno) { - case EBADF: - case ENOTCONN: - case ENOTSOCK: - case EFAULT: - case EINVAL: - status = NT_STATUS_INVALID_PARAMETER; - break; - case EAGAIN: - case EINTR: - status = STATUS_MORE_ENTRIES; - break; - case ECONNREFUSED: - status = NT_STATUS_CONNECTION_REFUSED; - break; - } + NTSTATUS status = unixdom_error(errno); talloc_free(buf); return status; } @@ -216,6 +234,8 @@ static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, ssize_t len; int flgs = 0; + *sendlen = 0; + /* TODO: we need to map all flags here */ if (!(flags & SOCKET_FLAG_BLOCK)) { flgs |= MSG_DONTWAIT; @@ -223,34 +243,7 @@ static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - switch (errno) { - case EBADF: - case ENOTSOCK: - case EFAULT: - case EINVAL: - status = NT_STATUS_INVALID_PARAMETER; - break; - case EMSGSIZE: - status = NT_STATUS_INVALID_BUFFER_SIZE; - break; - case EAGAIN: - /*case EWOULDBLOCK: this is an alis of EAGAIN --metze */ - case EINTR: - *sendlen = 0; - status = STATUS_MORE_ENTRIES; - break; - case ENOBUFS: - status = NT_STATUS_FOOBAR; - break; - case ENOMEM: - status = NT_STATUS_NO_MEMORY; - break; - case EPIPE: - status = NT_STATUS_CONNECTION_DISCONNECTED; - break; - } - return status; + return unixdom_error(errno); } *sendlen = len; -- cgit From 6cc8941f05d5c41e04d83382a7e282fcc191ccd1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 13:33:03 +0000 Subject: r3023: added immediate send of messages when they are first queued. This makes things a bit more efficient (This used to be commit 8380225d326e4bfb3f15fddc72c097870713132a) --- source4/lib/messaging/messaging.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 7e87ea45df..2f9a43c847 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -375,6 +375,8 @@ NTSTATUS messaging_send(void *msg_ctx, servid_t server, uint32_t msg_type, DATA_ talloc_set_destructor(rec, rec_destructor); + messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE); + return NT_STATUS_OK; } -- cgit From ca7e02fd3708a048cd691e6c2fc0357ffcc3b694 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 22:28:26 +0000 Subject: r3026: - added automatic retry to messages when the servers listen queue is full. This means callers can just "send and forget" rather than having to check for a temporary failure. The mechanism takes nice advantage of the timed events handling is our events code. A message will only fail now if we completely run out of some resource (such as memory). - changed the test code not to do retries itself, but only to warn on real failures (This used to be commit 8cddc610a25e64c1ad39dd6a2fc2e7f467e04fc9) --- source4/lib/messaging/messaging.c | 49 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 2f9a43c847..a0aabbbc21 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -49,8 +49,6 @@ struct dispatch_fn { /* an individual message */ struct messaging_rec { - struct messaging_rec *next, *prev; - struct messaging_state *msg; struct socket_context *sock; struct fd_event *fde; @@ -323,6 +321,43 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd } +/* + when the servers listen queue is full we use this to backoff the message +*/ +static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, time_t t) +{ + struct messaging_rec *rec = te->private; + struct messaging_state *msg = rec->msg; + NTSTATUS status; + struct fd_event fde; + + status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + /* backoff again */ + te->next_event = t+1; + return; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("messaging: Lost message from %u to %u of type %u after backoff - %s\n", + rec->header.from, rec->header.to, rec->header.msg_type, nt_errstr(status))); + talloc_free(rec); + return; + } + + fde.private = rec; + fde.fd = socket_get_fd(rec->sock); + fde.flags = EVENT_FD_WRITE; + fde.handler = messaging_send_handler; + + rec->fde = event_add_fd(msg->event.ev, &fde); + + talloc_set_destructor(rec, rec_destructor); + + messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE); +} + + /* Send a message to a particular server */ @@ -361,6 +396,16 @@ NTSTATUS messaging_send(void *msg_ctx, servid_t server, uint32_t msg_type, DATA_ rec->path = messaging_path(rec, server); status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + /* backoff on this message - the servers listen queue is full */ + struct timed_event te; + te.next_event = time(NULL)+1; + te.handler = messaging_backoff_handler; + te.private = rec; + event_add_timed(msg->event.ev, &te); + return NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(status)) { talloc_free(rec); return status; -- cgit From d37acd0fe71923987a68377bf01040eaed245d9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 00:04:46 +0000 Subject: r3028: use talloc_free() instead of talloc_unlink(), as the event_context_merge() code leaves the events as grandchildren of the events context, not children, so talloc_unlink() will not work after the merge (This used to be commit 2d0dfe607dcfb522669d6fb3d566cf121d84274a) --- source4/lib/events.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 2cedfc083c..dac23ec6bc 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -297,7 +297,7 @@ int event_loop_once(struct event_context *ev) struct loop_event *next = le->next; if (le->ref_count == 0) { DLIST_REMOVE(ev->loop_events, le); - talloc_unlink(ev->events, le); + talloc_free(le); } else { le->ref_count++; le->handler(ev, le, t); @@ -318,7 +318,7 @@ int event_loop_once(struct event_context *ev) if (ev->maxfd == fe->fd) { ev->maxfd = EVENT_INVALID_MAXFD; } - talloc_unlink(ev->events, fe); + talloc_free(fe); } else { if (fe->flags & EVENT_FD_READ) { FD_SET(fe->fd, &r_fds); @@ -399,7 +399,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (te->ref_count == 0) { DLIST_REMOVE(ev->timed_events, te); - talloc_unlink(ev->events, te); + talloc_free(te); } else if (te->next_event <= t) { te->ref_count++; te->handler(ev, te, t); -- cgit From d0cc571e30bf49443ac7d1b1a0b896ee72d7d9a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 07:40:17 +0000 Subject: r3029: implemented byte range lock timeouts. This adds a pvfs_wait_message() routine which uses the new messaging system, event timers and talloc destructors to give a nice generic async event handling system with a easy to use interface. The extensions to pvfs_lock.c are based on calls to pvfs_wait_message() routines. We now pass all of our smbtorture locking tests, although while writing this code I have thought of some additonal tests that should be added, particularly for lock cancel operations. I'll work on that soon. This commit also extends the smbtorture lock tests to test the rather weird 0xEEFFFFFF locking semantics that I have discovered in win2003. Win2003 treats the 0xEEFFFFFF boundary as special, and will give different error codes on either side of it. Locks on both sides are allowed, the only difference is which error code is given when a lock is denied. Anyone like to hazard a guess as to why? It has me stumped. (This used to be commit 4395c0557ab175d6a8dd99df03c266325949ffa5) --- source4/lib/messaging/messaging.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index a0aabbbc21..e78ec83b4b 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -250,14 +250,15 @@ void messaging_register(void *ctx, void *private, /* De-register the function for a particular message type. */ -void messaging_deregister(void *ctx, uint32_t msg_type) +void messaging_deregister(void *ctx, uint32_t msg_type, void *private) { struct messaging_state *msg = ctx; struct dispatch_fn *d, *next; for (d = msg->dispatch; d; d = next) { next = d->next; - if (d->msg_type == msg_type) { + if (d->msg_type == msg_type && + d->private == private) { DLIST_REMOVE(msg->dispatch, d); talloc_free(d); } -- cgit From 384f87bd38c1133c90e2a57775f139532574e3cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 11:47:13 +0000 Subject: r3034: - fixed a bug in message dispatch, when the dispatch function called messaging_deregister() - added a pvfs_lock_close_pending() hook to remove pending locks on file close - fixed the private ptr argument to messaging_deregister() in pvfs_wait - fixed a bug in continuing lock requests after a lock that is blocking a pending lock is removed - removed bogus brl_unlock() call in lock continue - corrected error code for LOCKING_ANDX_CHANGE_LOCKTYPE - expanded the lock cancel test suite to test lock cancel by unlock and by close - added a testsuite for LOCKING_ANDX_CHANGE_LOCKTYPE (This used to be commit 5ef80f034d4aa4dd6810532c63ad041bfc019cb8) --- source4/lib/messaging/messaging.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index e78ec83b4b..b0ca9cc41e 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -95,8 +95,9 @@ static char *messaging_path(TALLOC_CTX *mem_ctx, servid_t server_id) */ static void messaging_dispatch(struct messaging_state *msg, struct messaging_rec *rec) { - struct dispatch_fn *d; - for (d=msg->dispatch;d;d=d->next) { + struct dispatch_fn *d, *next; + for (d=msg->dispatch;d;d=next) { + next = d->next; if (d->msg_type == rec->header.msg_type) { d->fn(msg, d->private, d->msg_type, rec->header.from, &rec->data); } -- cgit From 53e30b391d6f6704d365bbf956a2aa2ef8451000 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 06:29:41 +0000 Subject: r3052: added talloc_zero_p() and talloc_zero_array_p() calls, for allocating zeroed memory (This used to be commit 65b7316e9b4589b02a8bd94150ccbfe526f6d159) --- source4/lib/talloc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 5c1f3e7dcd..12b21d21e6 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -776,9 +776,9 @@ void talloc_enable_leak_report_full(void) /* talloc and zero memory. */ -void *talloc_zero(const void *ctx, size_t size) +void *_talloc_zero(const void *ctx, size_t size, const char *name) { - void *p = talloc(ctx, size); + void *p = talloc_named_const(ctx, size, name); if (p) { memset(p, '\0', size); @@ -939,6 +939,17 @@ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char * return talloc_named_const(ctx, el_size * count, name); } +/* + alloc an zero array, checking for integer overflow in the array size +*/ +void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + /* realloc an array, checking for integer overflow in the array size -- cgit From b2b8282b8cc1774ac9cbef9a31ac23705ca45ac2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 07:08:35 +0000 Subject: r3057: - moved the idtree.c code into lib/ - converted the tid handling to use a idtree instead of bitmaps (This used to be commit 4220914179d10132057216650b65ed7f7679717e) --- source4/lib/basic.mk | 3 +- source4/lib/idtree.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 source4/lib/idtree.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index b6f30b6feb..d525f5f156 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -48,7 +48,8 @@ ADD_OBJ_FILES = \ lib/crypto/hmacmd5.o \ lib/crypto/md4.o \ lib/db_wrap.o \ - lib/server_mutex.o + lib/server_mutex.o \ + lib/idtree.o REQUIRED_SUBSYSTEMS = \ LIBTDB CHARSET # End SUBSYSTEM LIBBASIC diff --git a/source4/lib/idtree.c b/source4/lib/idtree.c new file mode 100644 index 0000000000..80f7df97a0 --- /dev/null +++ b/source4/lib/idtree.c @@ -0,0 +1,360 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + see the section marked "public interface" below for documentation +*/ + +#include "includes.h" + +#define IDR_BITS 5 +#define IDR_FULL 0xfffffffful +#define TOP_LEVEL_FULL (IDR_FULL >> 30) +#define IDR_SIZE (1 << IDR_BITS) +#define IDR_MASK ((1 << IDR_BITS)-1) +#define MAX_ID_SHIFT (sizeof(int)*8 - 1) +#define MAX_ID_BIT (1U << MAX_ID_SHIFT) +#define MAX_ID_MASK (MAX_ID_BIT - 1) +#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS +#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL + +#define set_bit(bit, v) (v) |= (1<<(bit)) +#define clear_bit(bit, v) (v) &= ~(1<<(bit)) + +struct idr_layer { + uint32_t bitmap; + struct idr_layer *ary[IDR_SIZE]; + int count; +}; + +struct idr { + struct idr_layer *top; + struct idr_layer *id_free; + int layers; + int id_free_cnt; +}; + +static struct idr_layer *alloc_layer(struct idr *idp) +{ + struct idr_layer *p; + + if (!(p = idp->id_free)) + return NULL; + idp->id_free = p->ary[0]; + idp->id_free_cnt--; + p->ary[0] = NULL; + return p; +} + +static int find_next_bit(uint32_t bm, int maxid, int n) +{ + while (nary[0] = idp->id_free; + idp->id_free = p; + idp->id_free_cnt++; +} + +static int idr_pre_get(struct idr *idp) +{ + while (idp->id_free_cnt < IDR_FREE_MAX) { + struct idr_layer *new = talloc_zero_p(idp, struct idr_layer); + if(new == NULL) + return (0); + free_layer(idp, new); + } + return 1; +} + +static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) +{ + int n, m, sh; + struct idr_layer *p, *new; + struct idr_layer *pa[MAX_LEVEL]; + int l, id; + uint32_t bm; + + id = *starting_id; + p = idp->top; + l = idp->layers; + pa[l--] = NULL; + while (1) { + /* + * We run around this while until we reach the leaf node... + */ + n = (id >> (IDR_BITS*l)) & IDR_MASK; + bm = ~p->bitmap; + m = find_next_bit(bm, IDR_SIZE, n); + if (m == IDR_SIZE) { + /* no space available go back to previous layer. */ + l++; + id = (id | ((1 << (IDR_BITS*l))-1)) + 1; + if (!(p = pa[l])) { + *starting_id = id; + return -2; + } + continue; + } + if (m != n) { + sh = IDR_BITS*l; + id = ((id >> sh) ^ n ^ m) << sh; + } + if ((id >= MAX_ID_BIT) || (id < 0)) + return -1; + if (l == 0) + break; + /* + * Create the layer below if it is missing. + */ + if (!p->ary[m]) { + if (!(new = alloc_layer(idp))) + return -1; + p->ary[m] = new; + p->count++; + } + pa[l--] = p; + p = p->ary[m]; + } + /* + * We have reached the leaf node, plant the + * users pointer and return the raw id. + */ + p->ary[m] = (struct idr_layer *)ptr; + set_bit(m, p->bitmap); + p->count++; + /* + * If this layer is full mark the bit in the layer above + * to show that this part of the radix tree is full. + * This may complete the layer above and require walking + * up the radix tree. + */ + n = id; + while (p->bitmap == IDR_FULL) { + if (!(p = pa[++l])) + break; + n = n >> IDR_BITS; + set_bit((n & IDR_MASK), p->bitmap); + } + return(id); +} + +static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) +{ + struct idr_layer *p, *new; + int layers, v, id; + + idr_pre_get(idp); + + id = starting_id; +build_up: + p = idp->top; + layers = idp->layers; + if (!p) { + if (!(p = alloc_layer(idp))) + return -1; + layers = 1; + } + /* + * Add a new layer to the top of the tree if the requested + * id is larger than the currently allocated space. + */ + while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) { + layers++; + if (!p->count) + continue; + if (!(new = alloc_layer(idp))) { + /* + * The allocation failed. If we built part of + * the structure tear it down. + */ + for (new = p; p && p != idp->top; new = p) { + p = p->ary[0]; + new->ary[0] = NULL; + new->bitmap = new->count = 0; + free_layer(idp, new); + } + return -1; + } + new->ary[0] = p; + new->count = 1; + if (p->bitmap == IDR_FULL) + set_bit(0, new->bitmap); + p = new; + } + idp->top = p; + idp->layers = layers; + v = sub_alloc(idp, ptr, &id); + if (v == -2) + goto build_up; + return(v); +} + +static void sub_remove(struct idr *idp, int shift, int id) +{ + struct idr_layer *p = idp->top; + struct idr_layer **pa[MAX_LEVEL]; + struct idr_layer ***paa = &pa[0]; + + *paa = NULL; + *++paa = &idp->top; + + while ((shift > 0) && p) { + int n = (id >> shift) & IDR_MASK; + clear_bit(n, p->bitmap); + *++paa = &p->ary[n]; + p = p->ary[n]; + shift -= IDR_BITS; + } + if (p != NULL) { + int n = id & IDR_MASK; + clear_bit(n, p->bitmap); + p->ary[n] = NULL; + while(*paa && ! --((**paa)->count)){ + free_layer(idp, **paa); + **paa-- = NULL; + } + if ( ! *paa ) + idp->layers = 0; + } +} + +static void *_idr_find(struct idr *idp, int id) +{ + int n; + struct idr_layer *p; + + n = idp->layers * IDR_BITS; + p = idp->top; + /* + * This tests to see if bits outside the current tree are + * present. If so, tain't one of ours! + */ + if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)) + return NULL; + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + while (n > 0 && p) { + n -= IDR_BITS; + p = p->ary[(id >> n) & IDR_MASK]; + } + return((void *)p); +} + +static void _idr_remove(struct idr *idp, int id) +{ + struct idr_layer *p; + + if (_idr_find(idp, id) == NULL) { + DEBUG(0,("WARNING: attempt to remove non-existant id %d in idtree\n", + id)); + return; + } + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); + if ( idp->top && idp->top->count == 1 && + (idp->layers > 1) && + idp->top->ary[0]) { + /* We can drop a layer */ + p = idp->top->ary[0]; + idp->top->bitmap = idp->top->count = 0; + free_layer(idp, idp->top); + idp->top = p; + --idp->layers; + } + while (idp->id_free_cnt >= IDR_FREE_MAX) { + p = alloc_layer(idp); + talloc_free(p); + return; + } +} + +/************************************************************************ + this is the public interface +**************************************************************************/ + +/* + initialise a idr tree. The context return value must be passed to + all subsequent idr calls. To destroy the idr tree use talloc_free() + on this context + */ +void *idr_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero_p(mem_ctx, struct idr); +} + +/* + allocate the next available id, and assign 'ptr' into its slot. + you can retrieve later this pointer using idr_find() +*/ +int idr_get_new(void *idp, void *ptr, int limit) +{ + int ret = idr_get_new_above_int((struct idr *)idp, ptr, 0); + if (ret >= limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/* + allocate a new id, giving the first available value greater than or + equal to the given starting id +*/ +int idr_get_new_above(void *idp, void *ptr, int starting_id, int limit) +{ + int ret = idr_get_new_above_int((struct idr *)idp, ptr, starting_id); + if (ret >= limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/* + find a pointer value previously set with idr_get_new given an id +*/ +void *idr_find(void *idp, int id) +{ + return _idr_find((struct idr *)idp, id); +} + +/* + remove an id from the idr tree +*/ +void idr_remove(void *idp, int id) +{ + return _idr_remove((struct idr *)idp, id); +} -- cgit From 198be6fc777fa1cdd461beb55fe2c30544047177 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 07:10:56 +0000 Subject: r3058: we don't use the bitmap code any more, delete it (This used to be commit 2b0554b3b598accb1b2ddade1bf17fa2cc2cb05b) --- source4/lib/basic.mk | 1 - source4/lib/bitmap.c | 163 --------------------------------------------------- 2 files changed, 164 deletions(-) delete mode 100644 source4/lib/bitmap.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index d525f5f156..3baab26c5b 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -17,7 +17,6 @@ ADD_OBJ_FILES = \ lib/time.o \ lib/genrand.o \ lib/username.o \ - lib/bitmap.o \ lib/snprintf.o \ lib/dprintf.o \ lib/xfile.o \ diff --git a/source4/lib/bitmap.c b/source4/lib/bitmap.c deleted file mode 100644 index 5a8325d4ba..0000000000 --- a/source4/lib/bitmap.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple bitmap functions - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* these functions provide a simple way to allocate integers from a - pool without repetition */ - -/**************************************************************************** -allocate a bitmap of the specified size -****************************************************************************/ -struct bitmap *bitmap_allocate(int n) -{ - struct bitmap *bm; - - bm = (struct bitmap *)malloc(sizeof(*bm)); - - if (!bm) return NULL; - - bm->n = n; - bm->b = (uint32_t *)malloc(sizeof(bm->b[0])*(n+31)/32); - if (!bm->b) { - SAFE_FREE(bm); - return NULL; - } - - memset(bm->b, 0, sizeof(bm->b[0])*(n+31)/32); - - return bm; -} - -/**************************************************************************** -free a bitmap. -****************************************************************************/ - -void bitmap_free(struct bitmap *bm) -{ - if (!bm) - return; - - SAFE_FREE(bm->b); - SAFE_FREE(bm); -} - -/**************************************************************************** -talloc a bitmap -****************************************************************************/ -struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n) -{ - struct bitmap *bm; - - if (!mem_ctx) return NULL; - - bm = (struct bitmap *)talloc(mem_ctx, sizeof(*bm)); - - if (!bm) return NULL; - - bm->n = n; - bm->b = (uint32_t *)talloc(mem_ctx, sizeof(bm->b[0])*(n+31)/32); - if (!bm->b) { - return NULL; - } - - memset(bm->b, 0, sizeof(bm->b[0])*(n+31)/32); - - return bm; -} - -/**************************************************************************** -set a bit in a bitmap -****************************************************************************/ -BOOL bitmap_set(struct bitmap *bm, uint_t i) -{ - if (i >= bm->n) { - DEBUG(0,("Setting invalid bitmap entry %d (of %d)\n", - i, bm->n)); - return False; - } - bm->b[i/32] |= (1<<(i%32)); - return True; -} - -/**************************************************************************** -clear a bit in a bitmap -****************************************************************************/ -BOOL bitmap_clear(struct bitmap *bm, uint_t i) -{ - if (i >= bm->n) { - DEBUG(0,("clearing invalid bitmap entry %d (of %d)\n", - i, bm->n)); - return False; - } - bm->b[i/32] &= ~(1<<(i%32)); - return True; -} - -/**************************************************************************** -query a bit in a bitmap -****************************************************************************/ -BOOL bitmap_query(struct bitmap *bm, uint_t i) -{ - if (i >= bm->n) return False; - if (bm->b[i/32] & (1<<(i%32))) { - return True; - } - return False; -} - -/**************************************************************************** -find a zero bit in a bitmap starting at the specified offset, with -wraparound -****************************************************************************/ -int bitmap_find(struct bitmap *bm, uint_t ofs) -{ - uint_t i, j; - - if (ofs > bm->n) ofs = 0; - - i = ofs; - while (i < bm->n) { - if (~(bm->b[i/32])) { - j = i; - do { - if (!bitmap_query(bm, j)) return j; - j++; - } while (j & 31 && j < bm->n); - } - i += 32; - i &= ~31; - } - - i = 0; - while (i < ofs) { - if (~(bm->b[i/32])) { - j = i; - do { - if (!bitmap_query(bm, j)) return j; - j++; - } while (j & 31 && j < bm->n); - } - i += 32; - i &= ~31; - } - - return -1; -} -- cgit From 23d3b714f1b1af6fae60618cb55988f60a64cffd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 09:53:23 +0000 Subject: r3061: change a debug to help track down a charset problem (This used to be commit 4d2497b7f4cb6aa6fdf1e03b56f72b1022cb92b8) --- source4/lib/charcnv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 10063c9f3c..40e68df984 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -192,7 +192,8 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { /* conversion not supported, return -1*/ - DEBUG(3, ("convert_string_talloc: conversion not supported!\n")); + DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n", + charset_name(from), charset_name(to))); return -1; } -- cgit From 343545a8836d1665bb3c41974d743b03fd0b6446 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 10:15:34 +0000 Subject: r3063: our default dos charset is CP850, but some systems don't have that, so as a special case, automatically fall back to ASCII if its not found. (This used to be commit 55aeb33343180929fbd7b3568b058b506aee7540) --- source4/lib/charcnv.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 40e68df984..3c27d59664 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -98,6 +98,20 @@ static smb_iconv_t get_conv_handle(charset_t from, charset_t to) n2 = charset_name(to); conv_handles[from][to] = smb_iconv_open(n2,n1); + + if (conv_handles[from][to] == (smb_iconv_t)-1) { + if ((from == CH_DOS || to == CH_DOS) && + strcasecmp(charset_name(CH_DOS), "ASCII") != 0) { + DEBUG(0,("dos charset '%s' unavailable - using ASCII\n", + charset_name(CH_DOS))); + lp_set_cmdline("dos charset", "ASCII"); + + n1 = charset_name(from); + n2 = charset_name(to); + + conv_handles[from][to] = smb_iconv_open(n2,n1); + } + } return conv_handles[from][to]; } -- cgit From 72093ce62f1e09db86452720fe8280ad66824cde Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 12:06:01 +0000 Subject: r3064: - use UINT8_MAX and UINT16_MAX instead of hex values for idr_get_new() limits - change idr_get_new() to use > instead of >= in the limit check (This used to be commit 834b09929bcb8aabdd151b7c2306001497cabdb4) --- source4/lib/idtree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/idtree.c b/source4/lib/idtree.c index 80f7df97a0..1243c4f3b9 100644 --- a/source4/lib/idtree.c +++ b/source4/lib/idtree.c @@ -322,7 +322,7 @@ void *idr_init(TALLOC_CTX *mem_ctx) int idr_get_new(void *idp, void *ptr, int limit) { int ret = idr_get_new_above_int((struct idr *)idp, ptr, 0); - if (ret >= limit) { + if (ret > limit) { idr_remove(idp, ret); return -1; } @@ -336,7 +336,7 @@ int idr_get_new(void *idp, void *ptr, int limit) int idr_get_new_above(void *idp, void *ptr, int starting_id, int limit) { int ret = idr_get_new_above_int((struct idr *)idp, ptr, starting_id); - if (ret >= limit) { + if (ret > limit) { idr_remove(idp, ret); return -1; } -- cgit From 31e96d8def1dd2fea76d31a032d64e5917462dc8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 20 Oct 2004 02:02:00 +0000 Subject: r3073: Fix bug in the handling of null-terminated ASCII strings in RPC. Because we didn't count the null terminator, we would not move past it in the packet. Andrew Bartlett (This used to be commit 8b38bffc7098610c469ab61b7e0e6884f046f286) --- source4/lib/util_str.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 03ba1399ef..07a2c1dbd1 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1119,6 +1119,24 @@ int strcmp_safe(const char *s1, const char *s2) } +/******************************************************************* +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +********************************************************************/ +size_t ascii_len_n(const char *src, size_t n) +{ + size_t len; + + len = strnlen(src, n); + if (len+1 <= n) { + len += 1; + } + + return len; +} + + /******************************************************************* Return a string representing a CIFS attribute for a file. ********************************************************************/ -- cgit From 900e2cdf6d371ff67adaf83936cf9e2e455bf234 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Oct 2004 17:42:17 +0000 Subject: r3089: fix memleak metze (This used to be commit 52eab8dc17a1cd1a8c0382ab8d6e7f6c7ddeea19) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 18d51d1aa4..a11f137cc9 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -266,6 +266,7 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { unsigned int i; + ldb_free(ldb, msg->dn); ldb_free(ldb, msg->private_data); for (i=0;inum_elements;i++) { ldb_free(ldb, msg->elements[i].values); -- cgit From 3b96f7d0dd5936c7c11bdaa1c66ccaff88700386 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Oct 2004 19:19:03 +0000 Subject: r3091: link only the needed stuff metze (This used to be commit 71ccac56c21635e7f6eb8d558230f637f50149ad) --- source4/lib/tdb/config.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index dba0d3e1d4..06f97547bb 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -39,7 +39,7 @@ REQUIRED_LIBRARIES = GDBM OBJ_FILES= \ lib/tdb/tools/tdbtool.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbtool ################################################ @@ -69,6 +69,6 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbbackup.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbbackup ################################################ -- cgit From 8d48ca63db0ec8dc47a386bd1fa38be2827755f3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Oct 2004 19:21:10 +0000 Subject: r3092: prepare for build inside samba metze (This used to be commit f7564bf4d2efb702cf3d11237fbe2adf5efb1ebf) --- source4/lib/ldb/tools/ldbtest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index a5a8ea7a3a..e25a7cbcd6 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -39,12 +39,12 @@ static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=U static struct timeval tp1,tp2; -static void start_timer(void) +static void _start_timer(void) { gettimeofday(&tp1,NULL); } -static double end_timer(void) +static double _end_timer(void) { gettimeofday(&tp2,NULL); return((tp2.tv_sec - tp1.tv_sec) + @@ -259,9 +259,9 @@ static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) add_records(ldb, base_dn, nrecords); printf("Starting search on uid\n"); - start_timer(); + _start_timer(); search_uid(ldb, nrecords, nsearches); - printf("uid search took %.2f seconds\n", end_timer()); + printf("uid search took %.2f seconds\n", _end_timer()); printf("Modifying records\n"); modify_records(ldb, base_dn, nrecords); -- cgit From a9bd40549767c19207f3ec520a3e4346beeabef4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Oct 2004 19:28:02 +0000 Subject: r3093: - implment ldb_rename() and ldbrename - add tests for ldbrename - disable all tests which regenerate the index (this is broken for me...the process hangs, tridge we need to discuss that) - link only the needed stuff to the ldb tools - build ldbtest inside samba metze (This used to be commit 18552f4786c24e0019cc87726ef4c05365fe586e) --- source4/lib/ldb/Makefile.ldb | 5 +- source4/lib/ldb/common/ldb.c | 11 ++++ source4/lib/ldb/config.m4 | 4 ++ source4/lib/ldb/config.mk | 30 ++++++++-- source4/lib/ldb/include/ldb.h | 8 +++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 43 +++++++++++++- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 58 +++++++++++++++++++ source4/lib/ldb/tests/test-generic.sh | 22 ++++++-- source4/lib/ldb/tools/ldbrename.c | 103 ++++++++++++++++++++++++++++++++++ 9 files changed, 271 insertions(+), 13 deletions(-) create mode 100644 source4/lib/ldb/tools/ldbrename.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 6a87043114..38456a75e4 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -29,7 +29,7 @@ OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbtest +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest LIBS = $(LDB_LIB)($(OBJS)) @@ -60,6 +60,9 @@ bin/ldbmodify: tools/ldbmodify.o $(LIBS) bin/ldbedit: tools/ldbedit.o $(LIBS) $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) +bin/ldbrename: tools/ldbrename.o $(LIBS) + $(CC) -o bin/ldbrename tools/ldbrename.o $(LIB_FLAGS) + bin/ldbtest: tools/ldbtest.o $(LIBS) $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index c6e8d37671..fa4a64c19d 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -139,6 +139,17 @@ int ldb_delete(struct ldb_context *ldb, const char *dn) return ret; } +/* + rename a record in the database +*/ +int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +{ + int ret; + ret = ldb->ops->rename_record(ldb, olddn, newdn); + ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_rename(%s,%s) -> %d\n", olddn, newdn); + return ret; +} + /* return extended error information */ diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 5206a0fbfe..c48e9e161b 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -23,3 +23,7 @@ SMB_BINARY_MK(ldbmodify,lib/ldb/config.mk) SMB_BINARY_MK(ldbsearch,lib/ldb/config.mk) SMB_BINARY_MK(ldbedit,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbrename,lib/ldb/config.mk) + +SMB_BINARY_MK(ldbtest,lib/ldb/config.mk) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 66e8481950..3b2501a83b 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -59,7 +59,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBLDB + LIBLDB # End BINARY ldbadd ################################################ @@ -69,7 +69,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBLDB + LIBLDB # End BINARY ldbdel ################################################ @@ -79,7 +79,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBLDB + LIBLDB # End BINARY ldbmodify ################################################ @@ -89,7 +89,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBLDB + LIBLDB # End BINARY ldbsearch ################################################ @@ -99,6 +99,26 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBLDB + LIBLDB # End BINARY ldbedit ################################################ + +################################################ +# Start BINARY ldbrename +[BINARY::ldbrename] +OBJ_FILES= \ + lib/ldb/tools/ldbrename.o +REQUIRED_SUBSYSTEMS = \ + LIBLDB +# End BINARY ldbrename +################################################ + +################################################ +# Start BINARY ldbtest +[BINARY::ldbtest] +OBJ_FILES= \ + lib/ldb/tools/ldbtest.o +REQUIRED_SUBSYSTEMS = \ + LIBLDB +# End BINARY ldbtest +################################################ diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 4b1401f673..3c78f12fb5 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -2,6 +2,7 @@ ldb database library Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -30,6 +31,7 @@ * Description: defines for base ldb API * * Author: Andrew Tridgell + * Author: Stefan Metzmacher */ #ifndef _LDB_H_ @@ -131,6 +133,7 @@ struct ldb_backend_ops { int (*add_record)(struct ldb_context *, const struct ldb_message *); int (*modify_record)(struct ldb_context *, const struct ldb_message *); int (*delete_record)(struct ldb_context *, const char *); + int (*rename_record)(struct ldb_context *, const char *olddn, const char *newdn); const char * (*errstring)(struct ldb_context *); /* this is called when the alloc ops changes to ensure we @@ -234,6 +237,11 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message); +/* + rename a record in the database +*/ +int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn); + /* delete a record from the database */ diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 06d3884c16..5b682a493a 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -91,6 +91,41 @@ static int lldb_close(struct ldb_context *ldb) return ret; } +/* + rename a record +*/ +static int lldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +{ + struct lldb_private *lldb = ldb->private_data; + int ret = 0; + char *newrdn, *p; + const char *parentdn = ""; + + /* ignore ltdb specials */ + if (olddn[0] == '@' ||newdn[0] == '@') { + return 0; + } + + newrdn = ldb_strdup(ldb, newdn); + if (!newrdn) { + return -1; + } + + p = strchr(newrdn, ','); + if (p) { + *p++ = '\0'; + parentdn = p; + } + + lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL); + ldb_free(ldb, newrdn); + if (lldb->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + return ret; +} + /* delete a record */ @@ -465,6 +500,7 @@ static const struct ldb_backend_ops lldb_ops = { lldb_add, lldb_modify, lldb_delete, + lldb_rename, lldb_errstring }; @@ -478,7 +514,7 @@ struct ldb_context *lldb_connect(const char *url, { struct ldb_context *ldb = NULL; struct lldb_private *lldb = NULL; - int i; + int i, version = 3; ldb = calloc(1, sizeof(struct ldb_context)); if (!ldb) { @@ -501,6 +537,11 @@ struct ldb_context *lldb_connect(const char *url, goto failed; } + lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); + if (lldb->last_rc != LDAP_SUCCESS) { + goto failed; + } + ldb->ops = &lldb_ops; ldb->private_data = lldb; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index e36770f88b..934ec68958 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -2,6 +2,8 @@ ldb database library Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -30,6 +32,7 @@ * Description: core functions for tdb backend * * Author: Andrew Tridgell + * Author: Stefan Metzmacher */ #include "includes.h" @@ -581,6 +584,60 @@ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) return ret; } +/* + rename a record +*/ +static int ltdb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +{ + struct ltdb_private *ltdb = ldb->private_data; + int ret; + struct ldb_message msg; + const char *error_str; + + ltdb->last_err_string = NULL; + + if (ltdb_lock(ldb) != 0) { + return -1; + } + + /* in case any attribute of the message was indexed, we need + to fetch the old record */ + ret = ltdb_search_dn1(ldb, olddn, &msg); + if (ret != 1) { + /* not finding the old record is an error */ + goto failed; + } + + ldb_free(ldb, msg.dn); + msg.dn = ldb_strdup(ldb,newdn); + if (!msg.dn) { + ltdb_search_dn1_free(ldb, &msg); + goto failed; + } + + ret = ltdb_add(ldb, &msg); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &msg); + goto failed; + } + ltdb_search_dn1_free(ldb, &msg); + + ret = ltdb_delete(ldb, olddn); + error_str = ltdb->last_err_string; + if (ret == -1) { + ltdb_delete(ldb, newdn); + } + + ltdb->last_err_string = error_str; + + ltdb_unlock(ldb); + + return ret; +failed: + ltdb_unlock(ldb); + return -1; +} + /* close database */ @@ -621,6 +678,7 @@ static const struct ldb_backend_ops ltdb_ops = { ltdb_add, ltdb_modify, ltdb_delete, + ltdb_rename, ltdb_errstring, ltdb_cache_free }; diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 4cfae7affb..a012158de1 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -1,3 +1,5 @@ +echo "LDB_URL: $LDB_URL" + echo "Adding base elements" $VALGRIND bin/ldbadd tests/test.ldif || exit 1 @@ -7,14 +9,22 @@ $VALGRIND bin/ldbmodify tests/test-modify.ldif || exit 1 echo "Showing modified record" $VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 -echo "Starting ldbtest" -time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 +echo "Rename entry" +OLDDN="cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michigan,c=US" +NEWDN="cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US" +$VALGRIND bin/ldbrename "$OLDDN" "$NEWDN" || exit 1 + +echo "Showing renamed record" +$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 + +#echo "Starting ldbtest" +#time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 -echo "Adding index" -$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 +#echo "Adding index" +#$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 -echo "Starting ldbtest indexed" -time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 +#echo "Starting ldbtest indexed" +#time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 echo "Testing one level search" count=`$VALGRIND bin/ldbsearch -b 'ou=Groups,o=University of Michigan,c=US' -s one 'objectclass=*' none |grep ^dn | wc -l` diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c new file mode 100644 index 0000000000..3bc3c95208 --- /dev/null +++ b/source4/lib/ldb/tools/ldbrename.c @@ -0,0 +1,103 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbrename + * + * Description: utility to rename records - modelled on ldapmodrdn + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + */ + +#include "includes.h" + +static void usage(void) +{ + printf("Usage: ldbrename [] \n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Renames records in a ldb\n\n"); + exit(1); +} + + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + const char *ldb_url; + int opt, ret; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n\n"); + usage(); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + ldb_set_debug_stderr(ldb); + + if (argc < 2) { + usage(); + } + + ret = ldb_rename(ldb, argv[0], argv[1]); + if (ret == 0) { + printf("Renamed 1 record\n"); + } else { + printf("rename of '%s' to '%s' failed - %s\n", + argv[0], argv[1], ldb_errstring(ldb)); + } + + ldb_close(ldb); + + return ret; +} -- cgit From 6d18904b037a39aeff2cad29fb2db84e0d1b2fe4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Oct 2004 20:48:31 +0000 Subject: r3095: - fix a free'ing of msg.dn - reenable index tests metze (This used to be commit 1e7e94fdb10db831090f9bd37e39053dfcde04ce) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 1 - source4/lib/ldb/ldb_tdb/ldb_tdb.c | 3 ++- source4/lib/ldb/tests/test-generic.sh | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index a11f137cc9..18d51d1aa4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -266,7 +266,6 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) { unsigned int i; - ldb_free(ldb, msg->dn); ldb_free(ldb, msg->private_data); for (i=0;inum_elements;i++) { ldb_free(ldb, msg->elements[i].values); diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 934ec68958..3d136ea014 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -608,7 +608,6 @@ static int ltdb_rename(struct ldb_context *ldb, const char *olddn, const char *n goto failed; } - ldb_free(ldb, msg.dn); msg.dn = ldb_strdup(ldb,newdn); if (!msg.dn) { ltdb_search_dn1_free(ldb, &msg); @@ -617,9 +616,11 @@ static int ltdb_rename(struct ldb_context *ldb, const char *olddn, const char *n ret = ltdb_add(ldb, &msg); if (ret == -1) { + ldb_free(ldb, msg.dn); ltdb_search_dn1_free(ldb, &msg); goto failed; } + ldb_free(ldb, msg.dn); ltdb_search_dn1_free(ldb, &msg); ret = ltdb_delete(ldb, olddn); diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index a012158de1..b70b817732 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -17,14 +17,14 @@ $VALGRIND bin/ldbrename "$OLDDN" "$NEWDN" || exit 1 echo "Showing renamed record" $VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 -#echo "Starting ldbtest" -#time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 +echo "Starting ldbtest" +time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 -#echo "Adding index" -#$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 +echo "Adding index" +$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 -#echo "Starting ldbtest indexed" -#time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 +echo "Starting ldbtest indexed" +time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 echo "Testing one level search" count=`$VALGRIND bin/ldbsearch -b 'ou=Groups,o=University of Michigan,c=US' -s one 'objectclass=*' none |grep ^dn | wc -l` -- cgit From 95ddbe5ad29df57b3d5ad5b9f5be95f6e194d0e0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Oct 2004 00:26:43 +0000 Subject: r3100: support 'bin/smbclient //w2k3-101/c$ -U \\administrator@w2k3.vmnet1.vm.base' we need to send an empty string as userdomain in this case. fix bug #1317 in the client side metze (This used to be commit 958aa8de630b2a88f29ccdf80ac0fc44a8205401) --- source4/lib/cmdline/popt_common.c | 6 +++++- source4/lib/cmdline/popt_common.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 554b46a940..0cf57bb2e0 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -304,6 +304,7 @@ static void popt_common_credentials_callback(poptContext con, if ((p = strchr_m(tmp,'\\'))) { *p = 0; pstrcpy(cmdline_auth_info.domain,tmp); + cmdline_auth_info.got_domain = True; pstrcpy(cmdline_auth_info.username,p+1); } @@ -317,6 +318,7 @@ static void popt_common_credentials_callback(poptContext con, if (getenv("DOMAIN")) { pstrcpy(cmdline_auth_info.domain,getenv("DOMAIN")); + cmdline_auth_info.got_domain = True; } if (getenv("PASSWD")) { @@ -344,6 +346,7 @@ static void popt_common_credentials_callback(poptContext con, if ((p = strchr_m(tmp,'\\'))) { *p = 0; pstrcpy(cmdline_auth_info.domain,tmp); + cmdline_auth_info.got_domain = True; pstrcpy(cmdline_auth_info.username,p+1); } @@ -431,12 +434,13 @@ const char *cmdline_get_username(void) void cmdline_set_userdomain(const char *domain) { + cmdline_auth_info.got_domain = True; pstrcpy(cmdline_auth_info.domain, domain); } const char *cmdline_get_userdomain(void) { - if (cmdline_auth_info.domain[0]) { + if (cmdline_auth_info.got_domain) { return cmdline_auth_info.domain; } diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index bedf8f7f5d..06560d2be5 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -40,8 +40,9 @@ extern struct poptOption popt_common_credentials[]; struct cmdline_auth_info { pstring username; - pstring password; pstring domain; + BOOL got_domain; + pstring password; BOOL got_pass; BOOL use_kerberos; }; -- cgit From a1063840e7b316eba02fe6112fc09ad84fc96be5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Oct 2004 00:47:05 +0000 Subject: r3101: some minor fixes metze (This used to be commit 61de2229e27c55041cb4e1aac32bc1d8ed68a05c) --- source4/lib/cmdline/popt_common.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 0cf57bb2e0..266c99ae9e 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -257,15 +257,15 @@ static void get_credentials_file(const char *file, struct cmdline_auth_info *inf while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) val++; - if (strwicmp("password", param) == 0) - { + if (strwicmp("password", param) == 0) { pstrcpy(info->password, val); info->got_pass = True; - } - else if (strwicmp("username", param) == 0) + } else if (strwicmp("username", param) == 0) { pstrcpy(info->username, val); - else if (strwicmp("domain", param) == 0) + } else if (strwicmp("domain", param) == 0) { pstrcpy(info->domain,val); + info->got_domain = True; + } memset(buf, 0, sizeof(buf)); } x_fclose(auth); @@ -398,12 +398,13 @@ static void popt_common_credentials_callback(poptContext con, "%s$", lp_netbios_name()); pstrcpy(cmdline_auth_info.password,opt_password); SAFE_FREE(opt_password); + cmdline_auth_info.got_pass = True; - pstrcpy(cmdline_auth_info.password, lp_workgroup()); - + pstrcpy(cmdline_auth_info.domain, lp_workgroup()); + cmdline_auth_info.domain = True; + /* machine accounts only work with kerberos */ cmdline_auth_info.use_kerberos = True; - cmdline_auth_info.got_pass = True; } break; } -- cgit From 5b09d503fffc36de224bdbffb17a84316da0459a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Oct 2004 00:49:39 +0000 Subject: r3102: typo metze (This used to be commit 3bbda7475a63f939019a41a0b7da8d179c533d79) --- source4/lib/cmdline/popt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 266c99ae9e..05e92866b2 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -401,7 +401,7 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.got_pass = True; pstrcpy(cmdline_auth_info.domain, lp_workgroup()); - cmdline_auth_info.domain = True; + cmdline_auth_info.got_domain = True; /* machine accounts only work with kerberos */ cmdline_auth_info.use_kerberos = True; -- cgit From 517238f0aa1a578aec69a40e92022a7636780c3a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Oct 2004 06:46:04 +0000 Subject: r3130: - added a LOCAL-IDTREE test suite - made idtree return a "struct idr_context *" instead of a void* - more efficient idr_remove for ids that are not present (patch from Jim Houston) (This used to be commit f8d12d4b4ae5a38de7869deb782cb8f48504844c) --- source4/lib/idtree.c | 68 ++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/idtree.c b/source4/lib/idtree.c index 1243c4f3b9..c4370a812d 100644 --- a/source4/lib/idtree.c +++ b/source4/lib/idtree.c @@ -44,6 +44,7 @@ #define set_bit(bit, v) (v) |= (1<<(bit)) #define clear_bit(bit, v) (v) &= ~(1<<(bit)) +#define test_bit(bit, v) ((v) & (1<<(bit))) struct idr_layer { uint32_t bitmap; @@ -51,14 +52,14 @@ struct idr_layer { int count; }; -struct idr { +struct idr_context { struct idr_layer *top; struct idr_layer *id_free; int layers; int id_free_cnt; }; -static struct idr_layer *alloc_layer(struct idr *idp) +static struct idr_layer *alloc_layer(struct idr_context *idp) { struct idr_layer *p; @@ -72,18 +73,18 @@ static struct idr_layer *alloc_layer(struct idr *idp) static int find_next_bit(uint32_t bm, int maxid, int n) { - while (nary[0] = idp->id_free; idp->id_free = p; idp->id_free_cnt++; } -static int idr_pre_get(struct idr *idp) +static int idr_pre_get(struct idr_context *idp) { while (idp->id_free_cnt < IDR_FREE_MAX) { struct idr_layer *new = talloc_zero_p(idp, struct idr_layer); @@ -94,7 +95,7 @@ static int idr_pre_get(struct idr *idp) return 1; } -static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) +static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id) { int n, m, sh; struct idr_layer *p, *new; @@ -166,7 +167,7 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) return(id); } -static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) +static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id) { struct idr_layer *p, *new; int layers, v, id; @@ -217,24 +218,25 @@ build_up: return(v); } -static void sub_remove(struct idr *idp, int shift, int id) +static int sub_remove(struct idr_context *idp, int shift, int id) { struct idr_layer *p = idp->top; struct idr_layer **pa[MAX_LEVEL]; struct idr_layer ***paa = &pa[0]; + int n; *paa = NULL; *++paa = &idp->top; while ((shift > 0) && p) { - int n = (id >> shift) & IDR_MASK; + n = (id >> shift) & IDR_MASK; clear_bit(n, p->bitmap); *++paa = &p->ary[n]; p = p->ary[n]; shift -= IDR_BITS; } - if (p != NULL) { - int n = id & IDR_MASK; + n = id & IDR_MASK; + if (p != NULL && test_bit(n, p->bitmap)) { clear_bit(n, p->bitmap); p->ary[n] = NULL; while(*paa && ! --((**paa)->count)){ @@ -243,10 +245,12 @@ static void sub_remove(struct idr *idp, int shift, int id) } if ( ! *paa ) idp->layers = 0; + return 0; } + return -1; } -static void *_idr_find(struct idr *idp, int id) +static void *_idr_find(struct idr_context *idp, int id) { int n; struct idr_layer *p; @@ -270,20 +274,17 @@ static void *_idr_find(struct idr *idp, int id) return((void *)p); } -static void _idr_remove(struct idr *idp, int id) +static int _idr_remove(struct idr_context *idp, int id) { struct idr_layer *p; - if (_idr_find(idp, id) == NULL) { - DEBUG(0,("WARNING: attempt to remove non-existant id %d in idtree\n", - id)); - return; - } - /* Mask off upper bits we don't use for the search. */ id &= MAX_ID_MASK; - sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); + if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) { + return -1; + } + if ( idp->top && idp->top->count == 1 && (idp->layers > 1) && idp->top->ary[0]) { @@ -297,8 +298,8 @@ static void _idr_remove(struct idr *idp, int id) while (idp->id_free_cnt >= IDR_FREE_MAX) { p = alloc_layer(idp); talloc_free(p); - return; } + return 0; } /************************************************************************ @@ -310,18 +311,18 @@ static void _idr_remove(struct idr *idp, int id) all subsequent idr calls. To destroy the idr tree use talloc_free() on this context */ -void *idr_init(TALLOC_CTX *mem_ctx) +struct idr_context *idr_init(TALLOC_CTX *mem_ctx) { - return talloc_zero_p(mem_ctx, struct idr); + return talloc_zero_p(mem_ctx, struct idr_context); } /* allocate the next available id, and assign 'ptr' into its slot. you can retrieve later this pointer using idr_find() */ -int idr_get_new(void *idp, void *ptr, int limit) +int idr_get_new(struct idr_context *idp, void *ptr, int limit) { - int ret = idr_get_new_above_int((struct idr *)idp, ptr, 0); + int ret = idr_get_new_above_int(idp, ptr, 0); if (ret > limit) { idr_remove(idp, ret); return -1; @@ -333,9 +334,9 @@ int idr_get_new(void *idp, void *ptr, int limit) allocate a new id, giving the first available value greater than or equal to the given starting id */ -int idr_get_new_above(void *idp, void *ptr, int starting_id, int limit) +int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit) { - int ret = idr_get_new_above_int((struct idr *)idp, ptr, starting_id); + int ret = idr_get_new_above_int(idp, ptr, starting_id); if (ret > limit) { idr_remove(idp, ret); return -1; @@ -346,15 +347,20 @@ int idr_get_new_above(void *idp, void *ptr, int starting_id, int limit) /* find a pointer value previously set with idr_get_new given an id */ -void *idr_find(void *idp, int id) +void *idr_find(struct idr_context *idp, int id) { - return _idr_find((struct idr *)idp, id); + return _idr_find(idp, id); } /* remove an id from the idr tree */ -void idr_remove(void *idp, int id) +int idr_remove(struct idr_context *idp, int id) { - return _idr_remove((struct idr *)idp, id); + int ret; + ret = _idr_remove((struct idr_context *)idp, id); + if (ret != 0) { + DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id)); + } + return ret; } -- cgit From b9956de1b1319f1869efa79d76674484b7f41166 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 24 Oct 2004 16:31:00 +0000 Subject: r3164: Look up ncalrpc identifiers using the EPMAPPER. ncalrpc now works nicely :-) The various interface that support ncalrpc work nicely when tested with smbtorture and ncalrpc. Running RPC-SAMR against local smbd here is slightly faster using ncalrpc: ncalrpc: 1.8 sec ncacn_ip_tcp: 1.9 sec ncacn_np: 2.5 sec (This used to be commit 2cfc8f24ce209f47153d3a5bd7007dd1b0578b26) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index fd81983227..c819eb4254 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -105,7 +105,12 @@ static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct struct dcerpc_pipe *p; int n; - if(!h->credentials || !h->location) return WERR_INVALID_PARAM; + if (!h->credentials) return WERR_INVALID_PARAM; + + /* Default to local smbd if no connection is specified */ + if (!h->location) { + h->location = talloc_strdup(mem_ctx, "ncalrpc:"); + } user = talloc_strdup(mem_ctx, h->credentials); pass = strchr(user, '%'); -- cgit From d164190debf9499ffa6dbf46ee24fa98da36c14f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 24 Oct 2004 23:30:47 +0000 Subject: r3169: unlink() is called on the listening unix socket every time a child process exits. Commenting it out until we have a clean way of doing this. (This used to be commit fa0760dd5fa361be3b72dc4adc8b736e8a862606) --- source4/lib/socket/socket_unix.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 1735c931b8..038ce3b3b6 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -73,9 +73,13 @@ static void unixdom_close(struct socket_context *sock) close(sock->fd); /* if we were listening, then don't leave the socket lying around in the filesystem */ + +#if 0 + /* FIXME - this doesn't work after fork(), etc */ if (sock->private_data) { unlink((const char *)sock->private_data); } +#endif } static NTSTATUS unixdom_connect(struct socket_context *sock, -- cgit From 75ed4f7cc4d39b85cf6dba040cbf188fac3ed464 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 03:30:39 +0000 Subject: r3183: moved the unlink of the messaging unixdom socket to the messaging destructor (This used to be commit ab222b236a091d31b1f5f2cba150a11585ab5836) --- source4/lib/messaging/messaging.c | 1 + source4/lib/socket/socket_unix.c | 9 --------- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index b0ca9cc41e..13c1a049f8 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -435,6 +435,7 @@ static int messaging_destructor(void *msg_ctx) { struct messaging_state *msg = msg_ctx; event_remove_fd(msg->event.ev, msg->event.fde); + unlink(msg->path); return 0; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 038ce3b3b6..df929d92b4 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -71,15 +71,6 @@ static NTSTATUS unixdom_init(struct socket_context *sock) static void unixdom_close(struct socket_context *sock) { close(sock->fd); - /* if we were listening, then don't leave the socket lying - around in the filesystem */ - -#if 0 - /* FIXME - this doesn't work after fork(), etc */ - if (sock->private_data) { - unlink((const char *)sock->private_data); - } -#endif } static NTSTATUS unixdom_connect(struct socket_context *sock, -- cgit From 6b280c130002f8b24b2e6ff7edeaa52629e5388a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 03:36:00 +0000 Subject: r3184: don't setup socket options on unix domain sockets (our smb.conf socket options are really meant for tcp) (This used to be commit 238febb0088f85933c869052f4f83ff31f164df1) --- source4/lib/socket/socket_unix.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index df929d92b4..d75bb973fc 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -249,7 +249,6 @@ static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, static NTSTATUS unixdom_set_option(struct socket_context *sock, const char *option, const char *val) { - set_socket_options(sock->fd, option); return NT_STATUS_OK; } -- cgit From 98f9d5cdf6451298001dc7ac71336d4206010181 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 10:25:25 +0000 Subject: r3210: split lib/replace.o into a separate build subsystem LIBREPLACE, and make the ldb tools depend on it. This should help the build of the ldb tools on platforms without strnlen() or strndup() (This used to be commit e6ddb9d8f3a218b22b0176a2525b5daaca7170e4) --- source4/lib/basic.m4 | 1 + source4/lib/basic.mk | 10 ++++++++-- source4/lib/ldb/config.mk | 2 ++ source4/lib/replace.c | 33 +++++++++++++++++++++++++++++++++ source4/lib/util_str.c | 33 --------------------------------- 5 files changed, 44 insertions(+), 35 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index b233c842db..6701ddaee5 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -1,3 +1,4 @@ dnl # LIB BASIC subsystem +SMB_SUBSYSTEM_MK(LIBREPLACE,lib/basic.mk) SMB_SUBSYSTEM_MK(LIBBASIC,lib/basic.mk) diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 3baab26c5b..c7d3a264d2 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -1,5 +1,12 @@ # LIB BASIC subsystem +############################## +# Start SUBSYSTEM LIBREPLACE +[SUBSYSTEM::LIBREPLACE] +INIT_OBJ_FILES = lib/replace.o +# End SUBSYSTEM LIBREPLACE +############################## + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -11,7 +18,6 @@ ADD_OBJ_FILES = \ lib/interface.o \ lib/interfaces.o \ lib/pidfile.o \ - lib/replace.o \ lib/signal.o \ lib/system.o \ lib/time.o \ @@ -50,6 +56,6 @@ ADD_OBJ_FILES = \ lib/server_mutex.o \ lib/idtree.o REQUIRED_SUBSYSTEMS = \ - LIBTDB CHARSET + LIBTDB CHARSET LIBREPLACE # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 3b2501a83b..639652ea55 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -37,6 +37,8 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_alloc.o \ lib/ldb/common/ldb_debug.o +REQUIRED_SUBSYSTEMS = \ + LIBREPLACE # # End SUBSYSTEM LIBLDB ################################################ diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 64234f7042..f3a0df6ef6 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -480,3 +480,36 @@ char *rep_inet_ntoa(struct in_addr ip) #endif } #endif + + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ + char *strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + size_t strnlen(const char *s, size_t n) +{ + int i; + for (i=0; s[i] && i Date: Mon, 25 Oct 2004 23:26:13 +0000 Subject: r3223: continue the effort on LIBREPLACE to try to get the ldb tools to compile on platforms like solaris without having to link to the whole of the Samba4 lib directory. (This used to be commit f6862bfc1cbc9278914b4b73365f63d3da0a08dd) --- source4/lib/basic.mk | 3 ++- source4/lib/replace.c | 33 +++++++++++++++++++++++++++++++++ source4/lib/time.c | 33 --------------------------------- 3 files changed, 35 insertions(+), 34 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index c7d3a264d2..56fc19dca7 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -4,6 +4,8 @@ # Start SUBSYSTEM LIBREPLACE [SUBSYSTEM::LIBREPLACE] INIT_OBJ_FILES = lib/replace.o +ADD_OBJ_FILES = \ + lib/snprintf.o # End SUBSYSTEM LIBREPLACE ############################## @@ -23,7 +25,6 @@ ADD_OBJ_FILES = \ lib/time.o \ lib/genrand.o \ lib/username.o \ - lib/snprintf.o \ lib/dprintf.o \ lib/xfile.o \ lib/wins_srv.o \ diff --git a/source4/lib/replace.c b/source4/lib/replace.c index f3a0df6ef6..4ed99c833c 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -427,6 +427,39 @@ char *rep_inet_ntoa(struct in_addr ip) #endif /* HAVE_SYSLOG */ #endif /* HAVE_VSYSLOG */ +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + +/******************************************************************* + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + ******************************************************************/ +int get_time_zone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); +} #ifndef HAVE_TIMEGM /* diff --git a/source4/lib/time.c b/source4/lib/time.c index fec4dd62a2..3ca7be5540 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -49,39 +49,6 @@ void GetTimeOfDay(struct timeval *tval) #endif } -/******************************************************************* -yield the difference between *A and *B, in seconds, ignoring leap seconds -********************************************************************/ -static int tm_diff(struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (1900 - 1); - int by = b->tm_year + (1900 - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; -} - -/******************************************************************* - return the UTC offset in seconds west of UTC, or 0 if it cannot be determined - ******************************************************************/ -int get_time_zone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - if (!tm) - return 0; - tm_utc = *tm; - tm = localtime(&t); - if (!tm) - return 0; - return tm_diff(&tm_utc,tm); -} #define TIME_FIXUP_CONSTANT 11644473600LL -- cgit From 0b6c611b11d2307490413e030959aef0cd2ab1ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 05:35:26 +0000 Subject: r3238: rename null_mtime() to the more accurate name "null_time()", and expose it for use by the posix backend (This used to be commit 687633b5d68c8f883a4d9cdd92c660dabc5d7cfa) --- source4/lib/time.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 3ca7be5540..eae30f581b 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -102,13 +102,13 @@ void unix_to_nt_time(NTTIME *nt, time_t t) /**************************************************************************** -check if it's a null mtime +check if it's a null unix time ****************************************************************************/ -static BOOL null_mtime(time_t mtime) +BOOL null_time(time_t t) { - return mtime == 0 || - mtime == (time_t)0xFFFFFFFF || - mtime == (time_t)-1; + return t == 0 || + t == (time_t)0xFFFFFFFF || + t == (time_t)-1; } /******************************************************************* @@ -188,7 +188,7 @@ localtime for this sort of date) ********************************************************************/ void push_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) { - if (!null_mtime(unixdate)) { + if (!null_time(unixdate)) { unixdate -= zone_offset; } SIVAL(buf,offset,unixdate); @@ -258,7 +258,7 @@ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) { time_t t = (time_t)IVAL(date_ptr,0); - if (!null_mtime(t)) { + if (!null_time(t)) { t += zone_offset; } return t; -- cgit From f493f7be97e9200c28dc69d73e64044140743e0b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 13:16:50 +0000 Subject: r3261: added seek to RAW-SEARCH test (This used to be commit 05530bfb99011db8a00f5debcf8eec19b5e8a5d6) --- source4/lib/genrand.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index adc6d7344e..72e4997596 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -261,27 +261,36 @@ BOOL check_password_quality(const char *s) Use the random number generator to generate a random string. ********************************************************************/ -static char c_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; - -char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) +char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list) { size_t i; + size_t list_len = strlen(list); char *retstr = talloc(mem_ctx, len + 1); + if (!retstr) return NULL; - if (!retstr) - return NULL; - -again: generate_random_buffer(retstr, len); - for (i = 0; i < len; i++) - retstr[i] = c_list[retstr[i] % (sizeof(c_list)-1) ]; - + for (i = 0; i < len; i++) { + retstr[i] = list[retstr[i] % list_len]; + } retstr[i] = '\0'; + return retstr; +} + +char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) +{ + char *retstr; + const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; + +again: + retstr = generate_random_str_list(mem_ctx, len, c_list); + if (!retstr) return NULL; + /* we need to make sure the random string passes basic quality tests or it might be rejected by windows as a password */ if (len >= 7 && !check_password_quality(retstr)) { + talloc_free(retstr); goto again; } -- cgit From 2970ff9bd9e6b2d4d40eb3c5c2845e62141fe6f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 21:43:34 +0000 Subject: r3267: make LIBTDB depend on LIBREPLACE. This is needed for building the tdb tools on Solaris. (This used to be commit c5d338d06137fe7464849df02671d8ab833e3b4e) --- source4/lib/tdb/config.mk | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 06f97547bb..6339b91761 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -6,6 +6,8 @@ INIT_OBJ_FILES = \ ADD_OBJ_FILES = \ lib/tdb/common/tdbutil.o \ lib/tdb/common/spinlock.o +REQUIRED_SUBSYSTEMS = \ + LIBREPLACE # # End SUBSYSTEM LIBLDB ################################################ -- cgit From 05ad898f68a2df1b102af95fdba0704479bde073 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 22:45:33 +0000 Subject: r3271: use "struct messaging_context *" instead of "void *" in messaging API (This used to be commit cc93813e4a09c538ad485dc2b3cb4c9be34f3d18) --- source4/lib/messaging/messaging.c | 41 ++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 13c1a049f8..afd18b4f2f 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -25,7 +25,7 @@ /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 -struct messaging_state { +struct messaging_context { servid_t server_id; struct socket_context *sock; char *path; @@ -43,13 +43,13 @@ struct dispatch_fn { struct dispatch_fn *next, *prev; uint32_t msg_type; void *private; - void (*fn)(void *msg_ctx, void *private, + void (*fn)(struct messaging_context *msg, void *private, uint32_t msg_type, servid_t server_id, DATA_BLOB *data); }; /* an individual message */ struct messaging_rec { - struct messaging_state *msg; + struct messaging_context *msg; struct socket_context *sock; struct fd_event *fde; const char *path; @@ -70,12 +70,12 @@ struct messaging_rec { /* A useful function for testing the message system. */ -static void ping_message(void *msg_ctx, void *private, +static void ping_message(struct messaging_context *msg, void *private, uint32_t msg_type, servid_t src, DATA_BLOB *data) { DEBUG(1,("INFO: Received PING message from server %u [%.*s]\n", (uint_t)src, data->length, data->data?(const char *)data->data:"")); - messaging_send(msg_ctx, src, MSG_PONG, data); + messaging_send(msg, src, MSG_PONG, data); } /* @@ -93,7 +93,7 @@ static char *messaging_path(TALLOC_CTX *mem_ctx, servid_t server_id) /* dispatch a fully received message */ -static void messaging_dispatch(struct messaging_state *msg, struct messaging_rec *rec) +static void messaging_dispatch(struct messaging_context *msg, struct messaging_rec *rec) { struct dispatch_fn *d, *next; for (d=msg->dispatch;d;d=next) { @@ -118,7 +118,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd time_t t, uint16_t flags) { struct messaging_rec *rec = fde->private; - struct messaging_state *msg = rec->msg; + struct messaging_context *msg = rec->msg; NTSTATUS status; if (rec->ndone < sizeof(rec->header)) { @@ -189,7 +189,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd static int rec_destructor(void *ptr) { struct messaging_rec *rec = ptr; - struct messaging_state *msg = rec->msg; + struct messaging_context *msg = rec->msg; event_remove_fd(msg->event.ev, rec->fde); return 0; } @@ -200,7 +200,7 @@ static int rec_destructor(void *ptr) static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags) { - struct messaging_state *msg = fde->private; + struct messaging_context *msg = fde->private; struct messaging_rec *rec; NTSTATUS status; struct fd_event fde2; @@ -234,11 +234,10 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * /* Register a dispatch function for a particular message type. */ -void messaging_register(void *ctx, void *private, +void messaging_register(struct messaging_context *msg, void *private, uint32_t msg_type, - void (*fn)(void *, void *, uint32_t, servid_t, DATA_BLOB *)) + void (*fn)(struct messaging_context *, void *, uint32_t, servid_t, DATA_BLOB *)) { - struct messaging_state *msg = ctx; struct dispatch_fn *d; d = talloc_p(msg, struct dispatch_fn); @@ -251,9 +250,8 @@ void messaging_register(void *ctx, void *private, /* De-register the function for a particular message type. */ -void messaging_deregister(void *ctx, uint32_t msg_type, void *private) +void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private) { - struct messaging_state *msg = ctx; struct dispatch_fn *d, *next; for (d = msg->dispatch; d; d = next) { @@ -329,7 +327,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, time_t t) { struct messaging_rec *rec = te->private; - struct messaging_state *msg = rec->msg; + struct messaging_context *msg = rec->msg; NTSTATUS status; struct fd_event fde; @@ -363,9 +361,8 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve /* Send a message to a particular server */ -NTSTATUS messaging_send(void *msg_ctx, servid_t server, uint32_t msg_type, DATA_BLOB *data) +NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t msg_type, DATA_BLOB *data) { - struct messaging_state *msg = msg_ctx; struct messaging_rec *rec; NTSTATUS status; struct fd_event fde; @@ -431,9 +428,9 @@ NTSTATUS messaging_send(void *msg_ctx, servid_t server, uint32_t msg_type, DATA_ /* destroy the messaging context */ -static int messaging_destructor(void *msg_ctx) +static int messaging_destructor(void *ptr) { - struct messaging_state *msg = msg_ctx; + struct messaging_context *msg = ptr; event_remove_fd(msg->event.ev, msg->event.fde); unlink(msg->path); return 0; @@ -442,13 +439,13 @@ static int messaging_destructor(void *msg_ctx) /* create the listening socket and setup the dispatcher */ -void *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id, struct event_context *ev) +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id, struct event_context *ev) { - struct messaging_state *msg; + struct messaging_context *msg; NTSTATUS status; struct fd_event fde; - msg = talloc_p(mem_ctx, struct messaging_state); + msg = talloc_p(mem_ctx, struct messaging_context); if (msg == NULL) { return NULL; } -- cgit From 9d055846f225bea4953822f40fab1d2f1a2e2d07 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 27 Oct 2004 03:15:42 +0000 Subject: r3278: - rewrote the client side rpc connection code to use lib/socket/ rather than doing everything itself. This greatly simplifies the code, although I really don't like the socket_recv() interface (it always allocates memory for you, which means an extra memcpy in this code) - fixed several bugs in the socket_ipv4.c code, in particular client side code used a non-blocking connect but didn't handle EINPROGRESS, so it had no chance of working. Also fixed the error codes, using map_nt_error_from_unix() - cleaned up and expanded map_nt_error_from_unix() - changed interpret_addr2() to not take a mem_ctx. It makes absolutely no sense to allocate a fixed size 4 byte structure like this. Dozens of places in the code were also using interpret_addr2() incorrectly (precisely because the allocation made no sense) (This used to be commit 7f2c771b0e0e98c5c9e5cf662592d64d34ff1205) --- source4/lib/interface.c | 10 ++-- source4/lib/socket/socket.c | 2 +- source4/lib/socket/socket_ipv4.c | 105 +++++++++++---------------------------- source4/lib/socket/socket_unix.c | 26 +--------- source4/lib/util.c | 24 ++++----- source4/lib/util_sock.c | 8 +-- source4/lib/wins_srv.c | 4 +- 7 files changed, 54 insertions(+), 125 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/interface.c b/source4/lib/interface.c index 14abfbd09a..b842fbb292 100644 --- a/source4/lib/interface.c +++ b/source4/lib/interface.c @@ -116,7 +116,7 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (!p) { - ip = *interpret_addr2(mem_ctx, token); + ip = interpret_addr2(token); for (i=0;i 2) { - nmask = *interpret_addr2(mem_ctx, p); + nmask = interpret_addr2(p); } else { nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); } @@ -174,8 +174,8 @@ void load_interfaces(void) return; } - allones_ip = *interpret_addr2(mem_ctx, "255.255.255.255"); - loopback_ip = *interpret_addr2(mem_ctx, "127.0.0.1"); + allones_ip = interpret_addr2("255.255.255.255"); + loopback_ip = interpret_addr2("127.0.0.1"); SAFE_FREE(probed_ifaces); diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index f70a76262b..f5ee84a7cc 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -134,7 +134,7 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ } NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags) + DATA_BLOB *blob, size_t wantlen, uint32_t flags) { if (sock->type != SOCKET_TYPE_STREAM) { return NT_STATUS_INVALID_PARAMETER; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 23e34dd39b..20dfd3c92f 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -24,8 +24,7 @@ static NTSTATUS ipv4_tcp_init(struct socket_context *sock) { sock->fd = socket(PF_INET, SOCK_STREAM, 0); if (sock->fd == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } return NT_STATUS_OK; @@ -37,41 +36,34 @@ static void ipv4_tcp_close(struct socket_context *sock) } static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, - const char *my_address, int my_port, - const char *srv_address, int srv_port, - uint32_t flags) + const char *my_address, int my_port, + const char *srv_address, int srv_port, + uint32_t flags) { - struct sockaddr_in my_addr; struct sockaddr_in srv_addr; struct in_addr my_ip; struct in_addr srv_ip; int ret; - ret = inet_aton(my_address, &my_ip); - if (ret == 0) { - /* not a valid ipv4 address */ - return NT_STATUS_FOOBAR; - } + my_ip = interpret_addr2(my_address); - ZERO_STRUCT(my_addr); + if (my_ip.s_addr != 0 || my_port != 0) { + struct sockaddr_in my_addr; + ZERO_STRUCT(my_addr); #ifdef HAVE_SOCK_SIN_LEN - my_addr.sin_len = sizeof(my_addr); + my_addr.sin_len = sizeof(my_addr); #endif - my_addr.sin_addr = my_ip; - my_addr.sin_port = htons(my_port); - my_addr.sin_family = PF_INET; - - ret = inet_aton(srv_address, &srv_ip); - if (ret == 0) { - /* not a valid ipv4 address */ - return NT_STATUS_FOOBAR; + my_addr.sin_addr = my_ip; + my_addr.sin_port = htons(my_port); + my_addr.sin_family = PF_INET; + + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } } - ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); - if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; - } + srv_ip = interpret_addr2(srv_address); ZERO_STRUCT(srv_addr); #ifdef HAVE_SOCK_SIN_LEN @@ -81,20 +73,18 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, srv_addr.sin_port = htons(srv_port); srv_addr.sin_family = PF_INET; + ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, False); if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } } - ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); - if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; - } - sock->state = SOCKET_STATE_CLIENT_CONNECTED; return NT_STATUS_OK; @@ -108,11 +98,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, struct in_addr ip_addr; int ret; - ret = inet_aton(my_address, &ip_addr); - if (ret == 0) { - /* not a valid ipv4 address */ - return NT_STATUS_FOOBAR; - } + ip_addr = interpret_addr2(my_address); ZERO_STRUCT(my_addr); #ifdef HAVE_SOCK_SIN_LEN @@ -124,21 +110,18 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } ret = listen(sock->fd, queue_size); if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, False); if (ret == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } } @@ -155,8 +138,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { - /* TODO: we need to map from errno to NTSTATUS here! */ - return NT_STATUS_FOOBAR; + return map_nt_error_from_unix(errno); } /* TODO: we could add a 'accept_check' hook here @@ -257,34 +239,7 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - switch (errno) { - case EBADF: - case ENOTSOCK: - case EFAULT: - case EINVAL: - status = NT_STATUS_INVALID_PARAMETER; - break; - case EMSGSIZE: - status = NT_STATUS_INVALID_BUFFER_SIZE; - break; - case EAGAIN: - /*case EWOULDBLOCK: this is an alis of EAGAIN --metze */ - case EINTR: - *sendlen = 0; - status = STATUS_MORE_ENTRIES; - break; - case ENOBUFS: - status = NT_STATUS_FOOBAR; - break; - case ENOMEM: - status = NT_STATUS_NO_MEMORY; - break; - case EPIPE: - status = NT_STATUS_CONNECTION_DISCONNECTED; - break; - } - return status; + return map_nt_error_from_unix(errno); } *sendlen = len; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index d75bb973fc..90802eae66 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -30,31 +30,7 @@ */ static NTSTATUS unixdom_error(int ernum) { - switch (ernum) { - case EBADF: - case ENOTCONN: - case ENOTSOCK: - case EFAULT: - case EINVAL: - return NT_STATUS_INVALID_PARAMETER; - case EAGAIN: - case EINTR: - return STATUS_MORE_ENTRIES; - case ECONNREFUSED: - return NT_STATUS_CONNECTION_REFUSED; - case ENOBUFS: - case ENOMEM: - return NT_STATUS_NO_MEMORY; - case ENFILE: - case EMFILE: - return NT_STATUS_INSUFFICIENT_RESOURCES; - case EPIPE: - return NT_STATUS_CONNECTION_DISCONNECTED; - case EMSGSIZE: - return NT_STATUS_INVALID_BUFFER_SIZE; - } - - return NT_STATUS_UNSUCCESSFUL; + return map_nt_error_from_unix(ernum); } static NTSTATUS unixdom_init(struct socket_context *sock) diff --git a/source4/lib/util.c b/source4/lib/util.c index 0982694823..d7c5661f7d 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -406,16 +406,18 @@ BOOL is_ipaddress(const char *str) /**************************************************************************** Interpret an internet address or name into an IP address in 4 byte form. ****************************************************************************/ - uint32_t interpret_addr(const char *str) { struct hostent *hp; uint32_t res; - if (strcmp(str,"0.0.0.0") == 0) - return(0); - if (strcmp(str,"255.255.255.255") == 0) - return(0xFFFFFFFF); + if (str == NULL || + strcmp(str,"0.0.0.0") == 0) { + return 0; + } + if (strcmp(str,"255.255.255.255") == 0) { + return 0xFFFFFFFF; + } /* if it's in the form of an IP address then get the lib to interpret it */ if (is_ipaddress(str)) { @@ -444,16 +446,12 @@ uint32_t interpret_addr(const char *str) /******************************************************************* A convenient addition to interpret_addr(). ******************************************************************/ - -struct in_addr *interpret_addr2(TALLOC_CTX *mem_ctx, const char *str) +struct in_addr interpret_addr2(const char *str) { - struct in_addr *ret; + struct in_addr ret; uint32_t a = interpret_addr(str); - - ret = talloc(mem_ctx, sizeof(struct in_addr)); - if (!ret) return NULL; - ret->s_addr = a; - return(ret); + ret.s_addr = a; + return ret; } /******************************************************************* diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 387c72599a..638c44f705 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -408,14 +408,14 @@ int open_udp_socket(const char *host, int port) int type = SOCK_DGRAM; struct sockaddr_in sock_out; int res; - struct in_addr *addr; + struct in_addr addr; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("open_udp_socket"); if (!mem_ctx) { return -1; } - addr = interpret_addr2(mem_ctx, host); + addr = interpret_addr2(host); res = socket(PF_INET, type, 0); if (res == -1) { @@ -423,7 +423,7 @@ int open_udp_socket(const char *host, int port) } memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); + putip((char *)&sock_out.sin_addr,(char *)&addr); sock_out.sin_port = htons(port); sock_out.sin_family = PF_INET; @@ -508,7 +508,7 @@ char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); if (fd == -1) return name_buf; - addr = *interpret_addr2(mem_ctx, p); + addr = interpret_addr2(p); /* Look up the remote host name. */ if ((hp = gethostbyaddr((char *)&addr.s_addr, sizeof(addr.s_addr), AF_INET)) == 0) { diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index 71368658b0..eb7f280e6f 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -174,11 +174,11 @@ static void parse_ip(TALLOC_CTX *mem_ctx, struct tagged_ip *ip, const char *str) char *s = strchr(str, ':'); if (!s) { fstrcpy(ip->tag, "*"); - ip->ip = *interpret_addr2(mem_ctx, str); + ip->ip = interpret_addr2(str); return; } - ip->ip = *interpret_addr2(mem_ctx, s+1); + ip->ip = interpret_addr2(s+1); fstrcpy(ip->tag, str); s = strchr(ip->tag, ':'); if (s) *s = 0; -- cgit From 1f6fd130a35e4068ac7caa164b89516319c3d276 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 27 Oct 2004 03:45:35 +0000 Subject: r3279: Removed MSG_DONTWAIT flags as many platform don't have it. If a socket is non-blocking then adding MSG_DONTWAIT is pointless (it does nothing), so all we lose is the ability to set non-blocking on a packet-by-packet basis, which is not a very useful thing to have anyway if the socket is blocking then the code already adds MSG_WAITALL, so MSG_DONTWAIT is also not needed in that case. (This used to be commit b8a2afae67691a609b4a7a577fee3f9518adc9d2) --- source4/lib/socket/socket_ipv4.c | 11 +---------- source4/lib/socket/socket_unix.c | 9 --------- 2 files changed, 1 insertion(+), 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 20dfd3c92f..3fda0fe9fb 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -183,10 +183,6 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, flgs |= MSG_PEEK; } - if (!(flags & SOCKET_FLAG_BLOCK)) { - flgs |= MSG_DONTWAIT; - } - if (flags & SOCKET_FLAG_BLOCK) { flgs |= MSG_WAITALL; } @@ -227,16 +223,11 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, } static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; int flgs = 0; - /* TODO: we need to map all flags here */ - if (!(flags & SOCKET_FLAG_BLOCK)) { - flgs |= MSG_DONTWAIT; - } - len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { return map_nt_error_from_unix(errno); diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 90802eae66..eda1597df7 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -172,10 +172,6 @@ static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, flgs |= MSG_PEEK; } - if (!(flags & SOCKET_FLAG_BLOCK)) { - flgs |= MSG_DONTWAIT; - } - if (flags & SOCKET_FLAG_BLOCK) { flgs |= MSG_WAITALL; } @@ -207,11 +203,6 @@ static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, *sendlen = 0; - /* TODO: we need to map all flags here */ - if (!(flags & SOCKET_FLAG_BLOCK)) { - flgs |= MSG_DONTWAIT; - } - len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { return unixdom_error(errno); -- cgit From 93c32f81e2613c111d69ae6bcc37eb9e58788e28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 27 Oct 2004 21:29:55 +0000 Subject: r3300: initialise *sendlen on failure, to allow for callers to check only for NT_STATUS_IS_ERR() (This used to be commit 80a109de8458420ac0b40c563f4b3bc51424d759) --- source4/lib/socket/socket_ipv4.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 3fda0fe9fb..f280f804ef 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -228,6 +228,8 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, ssize_t len; int flgs = 0; + *sendlen = 0; + len = send(sock->fd, blob->data, blob->length, flgs); if (len == -1) { return map_nt_error_from_unix(errno); -- cgit From c6888da1487ab301292c3d4d05d0464833f3ce57 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 04:00:43 +0000 Subject: r3304: changed the API to lib/socket/ a little. The main change is to make socket_recv() take a pre-allocated buffer, rather than allocating one itself. This allows non-blocking users of this API to avoid a memcpy(). As a result our messaging code is now about 10% faster, and the ncacn_ip_tcp and ncalrpc code is also faster. The second change was to remove the unused mem_ctx argument from socket_send(). Having it there implied that memory could be allocated, which meant the caller had to worry about freeing that memory (if for example it is sending in a tight loop using the same memory context). Removing that unused argument keeps life simpler for users. (This used to be commit a16e4756cd68ca8aab4ffc59d4d9db0b6e44dbd1) --- source4/lib/messaging/messaging.c | 36 ++++++++++++++++------------------ source4/lib/socket/socket.c | 12 ++++++------ source4/lib/socket/socket.h | 8 ++++---- source4/lib/socket/socket_ipv4.c | 41 +++++++-------------------------------- source4/lib/socket/socket_unix.c | 25 +++++++----------------- 5 files changed, 41 insertions(+), 81 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index afd18b4f2f..09d0c43934 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -123,22 +123,21 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd if (rec->ndone < sizeof(rec->header)) { /* receive the header */ - DATA_BLOB blob; - blob.length = 0; - status = socket_recv(rec->sock, rec, - &blob, sizeof(rec->header) - rec->ndone, 0); + size_t nread; + + status = socket_recv(rec->sock, + rec->ndone + (char *)&rec->header, + sizeof(rec->header) - rec->ndone, &nread, 0); if (NT_STATUS_IS_ERR(status)) { talloc_free(rec); return; } - if (blob.length == 0) { + if (nread == 0) { return; } - memcpy(rec->ndone + (char *)&rec->header, blob.data, blob.length); - rec->ndone += blob.length; - data_blob_free(&blob); + rec->ndone += nread; if (rec->ndone == sizeof(rec->header)) { if (rec->header.version != MESSAGING_VERSION) { @@ -158,23 +157,22 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd if (rec->ndone >= sizeof(rec->header) && rec->ndone < sizeof(rec->header) + rec->header.length) { /* receive the body, if any */ - DATA_BLOB blob; - blob.length = 0; - status = socket_recv(rec->sock, rec, - &blob, sizeof(rec->header) + rec->header.length - rec->ndone, 0); + size_t nread; + + status = socket_recv(rec->sock, + rec->data.data + (rec->ndone - sizeof(rec->header)), + sizeof(rec->header) + rec->header.length - rec->ndone, + &nread, 0); if (NT_STATUS_IS_ERR(status)) { talloc_free(rec); return; } - if (blob.length == 0) { + if (nread == 0) { return; } - memcpy(rec->data.data + (rec->ndone - sizeof(rec->header)), - blob.data, blob.length); - - rec->ndone += blob.length; + rec->ndone += nread; } if (rec->ndone == sizeof(rec->header) + rec->header.length) { @@ -283,7 +281,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd blob.data = rec->ndone + (char *)&rec->header; blob.length = sizeof(rec->header) - rec->ndone; - status = socket_send(rec->sock, rec, &blob, &nsent, 0); + status = socket_send(rec->sock, &blob, &nsent, 0); if (NT_STATUS_IS_ERR(status)) { talloc_free(rec); return; @@ -305,7 +303,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd blob.data = rec->data.data + (rec->ndone - sizeof(rec->header)); blob.length = rec->header.length - (rec->ndone - sizeof(rec->header)); - status = socket_send(rec->sock, rec, &blob, &nsent, 0); + status = socket_send(rec->sock, &blob, &nsent, 0); if (NT_STATUS_IS_ERR(status)) { talloc_free(rec); return; diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index f5ee84a7cc..94d8b5bada 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -133,8 +133,8 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ return status; } -NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags) +NTSTATUS socket_recv(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags) { if (sock->type != SOCKET_TYPE_STREAM) { return NT_STATUS_INVALID_PARAMETER; @@ -149,11 +149,11 @@ NTSTATUS socket_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->recv(sock, mem_ctx, blob, wantlen, flags); + return sock->ops->recv(sock, buf, wantlen, nread, flags); } -NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +NTSTATUS socket_send(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { if (sock->type != SOCKET_TYPE_STREAM) { return NT_STATUS_INVALID_PARAMETER; @@ -168,7 +168,7 @@ NTSTATUS socket_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->send(sock, mem_ctx, blob, sendlen, flags); + return sock->ops->send(sock, blob, sendlen, flags); } NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index a089a1b78a..6562bb376b 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -46,10 +46,10 @@ struct socket_ops { struct socket_context **new_sock, uint32_t flags); /* general ops */ - NTSTATUS (*recv)(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags); - NTSTATUS (*send)(struct socket_context *sock, TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); + NTSTATUS (*recv)(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags); + NTSTATUS (*send)(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); void (*close)(struct socket_context *sock); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index f280f804ef..4de0d8cebe 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -166,18 +166,12 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags) +static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags) { ssize_t gotlen; - void *buf; int flgs = 0; - buf = talloc(mem_ctx, wantlen); - if (!buf) { - return NT_STATUS_NO_MEMORY; - } - /* TODO: we need to map all flags here */ if (flags & SOCKET_FLAG_PEEK) { flgs |= MSG_PEEK; @@ -187,42 +181,21 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, flgs |= MSG_WAITALL; } + *nread = 0; + gotlen = recv(sock->fd, buf, wantlen, flgs); if (gotlen == 0) { - talloc_free(buf); return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - switch (errno) { - case EBADF: - case ENOTCONN: - case ENOTSOCK: - case EFAULT: - case EINVAL: - status = NT_STATUS_INVALID_PARAMETER; - break; - case EAGAIN: - case EINTR: - status = STATUS_MORE_ENTRIES; - break; - case ECONNREFUSED: - status = NT_STATUS_CONNECTION_REFUSED; - break; - } - talloc_free(buf); - return status; + return map_nt_error_from_unix(errno); } - blob->length = gotlen; - blob->data = talloc_realloc(mem_ctx, buf, gotlen); - if (!blob->data) { - return NT_STATUS_NO_MEMORY; - } + *nread = gotlen; return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, +static NTSTATUS ipv4_tcp_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index eda1597df7..3a3ce5fe8a 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -155,18 +155,12 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, return NT_STATUS_OK; } -static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, size_t wantlen, uint32_t flags) +static NTSTATUS unixdom_recv(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags) { ssize_t gotlen; - void *buf; int flgs = 0; - buf = talloc(mem_ctx, wantlen); - if (!buf) { - return NT_STATUS_NO_MEMORY; - } - /* TODO: we need to map all flags here */ if (flags & SOCKET_FLAG_PEEK) { flgs |= MSG_PEEK; @@ -176,26 +170,21 @@ static NTSTATUS unixdom_recv(struct socket_context *sock, TALLOC_CTX *mem_ctx, flgs |= MSG_WAITALL; } + *nread = 0; + gotlen = recv(sock->fd, buf, wantlen, flgs); if (gotlen == 0) { - talloc_free(buf); return NT_STATUS_END_OF_FILE; } else if (gotlen == -1) { - NTSTATUS status = unixdom_error(errno); - talloc_free(buf); - return status; + return unixdom_error(errno); } - blob->length = gotlen; - blob->data = talloc_realloc(mem_ctx, buf, gotlen); - if (!blob->data) { - return NT_STATUS_NO_MEMORY; - } + *nread = gotlen; return NT_STATUS_OK; } -static NTSTATUS unixdom_send(struct socket_context *sock, TALLOC_CTX *mem_ctx, +static NTSTATUS unixdom_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; -- cgit From 34cd0662f0340720fa45dd16c82496cd76e92268 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 07:34:11 +0000 Subject: r3313: in socket_accept() make the new socket non-blocking unless SOCKET_FLAG_BLOCK is set. (This used to be commit a2d92aa431e0e9752387eebe741d9e6f376f74d7) --- source4/lib/socket/socket_ipv4.c | 8 ++++++++ source4/lib/socket/socket_unix.c | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 4de0d8cebe..71e1c62235 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -141,6 +141,14 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return map_nt_error_from_unix(errno); } + if (!(flags & SOCKET_FLAG_BLOCK)) { + int ret = set_blocking(new_fd, False); + if (ret == -1) { + close(new_fd); + return map_nt_error_from_unix(errno); + } + } + /* TODO: we could add a 'accept_check' hook here * which get the black/white lists via socket_set_accept_filter() * or something like that diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 3a3ce5fe8a..239e4eb069 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -136,6 +136,14 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, return unixdom_error(errno); } + if (!(flags & SOCKET_FLAG_BLOCK)) { + int ret = set_blocking(new_fd, False); + if (ret == -1) { + close(new_fd); + return map_nt_error_from_unix(errno); + } + } + (*new_sock) = talloc_p(NULL, struct socket_context); if (!(*new_sock)) { close(new_fd); -- cgit From 990d76f7cbd4339c30f650781c40463234fc47e1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 07:55:33 +0000 Subject: r3314: added a option "socket:testnonblock" to the generic socket code. If you set this option (either on the command line using --option or in smb.conf) then every socket recv or send will return short by random amounts. This allows you to test that the non-blocking socket logic in your code works correctly. I also removed the flags argument to socket_accept(), and instead made the new socket inherit the flags of the old socket, which makes more sense to me. (This used to be commit 406d356e698da01c84e8aa5b7894752b4403f63c) --- source4/lib/messaging/messaging.c | 2 +- source4/lib/socket/socket.c | 22 ++++++++++++++++++++-- source4/lib/socket/socket.h | 8 ++++---- source4/lib/socket/socket_ipv4.c | 6 +++--- source4/lib/socket/socket_unix.c | 7 +++---- 5 files changed, 31 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 09d0c43934..7f90bd4e40 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -208,7 +208,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * smb_panic("Unable to allocate messaging_rec"); } - status = socket_accept(msg->sock, &rec->sock, 0); + status = socket_accept(msg->sock, &rec->sock); if (!NT_STATUS_IS_OK(status)) { smb_panic("Unable to accept messaging_rec"); } diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 94d8b5bada..22b40e076c 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -60,6 +60,14 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co return status; } + /* by enabling "testnonblock" mode, all socket receive and + send calls on non-blocking sockets will randomly recv/send + less data than requested */ + if (!(flags & SOCKET_FLAG_BLOCK) && + lp_parm_bool(-1, "socket", "testnonblock", False)) { + (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK; + } + talloc_set_destructor(*new_sock, socket_destructor); return NT_STATUS_OK; @@ -108,7 +116,7 @@ NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int return sock->ops->listen(sock, my_address, port, queue_size, flags); } -NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock) { NTSTATUS status; @@ -124,7 +132,7 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ return NT_STATUS_NOT_IMPLEMENTED; } - status = sock->ops->accept(sock, new_sock, flags); + status = sock->ops->accept(sock, new_sock); if (NT_STATUS_IS_OK(status)) { talloc_set_destructor(*new_sock, socket_destructor); @@ -149,6 +157,10 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, return NT_STATUS_NOT_IMPLEMENTED; } + if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && wantlen > 1) { + return sock->ops->recv(sock, buf, 1+(random() % (wantlen-1)), nread, flags); + } + return sock->ops->recv(sock, buf, wantlen, nread, flags); } @@ -168,6 +180,12 @@ NTSTATUS socket_send(struct socket_context *sock, return NT_STATUS_NOT_IMPLEMENTED; } + if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && blob->length > 1) { + DATA_BLOB blob2 = *blob; + blob2.length = 1+(random() % (blob2.length-1)); + return sock->ops->send(sock, &blob2, sendlen, flags); + } + return sock->ops->send(sock, blob, sendlen, flags); } diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 6562bb376b..6e54a37b80 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -42,8 +42,7 @@ struct socket_ops { /* server ops */ NTSTATUS (*listen)(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags); - NTSTATUS (*accept)(struct socket_context *sock, - struct socket_context **new_sock, uint32_t flags); + NTSTATUS (*accept)(struct socket_context *sock, struct socket_context **new_sock); /* general ops */ NTSTATUS (*recv)(struct socket_context *sock, void *buf, @@ -78,8 +77,9 @@ enum socket_state { SOCKET_STATE_SERVER_ERROR }; -#define SOCKET_FLAG_BLOCK 0x00000001 -#define SOCKET_FLAG_PEEK 0x00000002 +#define SOCKET_FLAG_BLOCK 0x00000001 +#define SOCKET_FLAG_PEEK 0x00000002 +#define SOCKET_FLAG_TESTNONBLOCK 0x00000004 struct socket_context { enum socket_type type; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 71e1c62235..f9318a29bb 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -130,7 +130,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock, uint32_t flags) +static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock) { struct sockaddr_in cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); @@ -141,7 +141,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return map_nt_error_from_unix(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { + if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, False); if (ret == -1) { close(new_fd); @@ -164,7 +164,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte /* copy the socket_context */ (*new_sock)->type = sock->type; (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; - (*new_sock)->flags = flags; + (*new_sock)->flags = sock->flags; (*new_sock)->fd = new_fd; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 239e4eb069..d160d897ee 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -124,8 +124,7 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, } static NTSTATUS unixdom_accept(struct socket_context *sock, - struct socket_context **new_sock, - uint32_t flags) + struct socket_context **new_sock) { struct sockaddr_un cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); @@ -136,7 +135,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, return unixdom_error(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { + if (!(sock->flags & SOCKET_FLAG_BLOCK)) { int ret = set_blocking(new_fd, False); if (ret == -1) { close(new_fd); @@ -153,7 +152,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, /* copy the socket_context */ (*new_sock)->type = sock->type; (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; - (*new_sock)->flags = flags; + (*new_sock)->flags = sock->flags; (*new_sock)->fd = new_fd; -- cgit From 8c752ec86156ebfa78f91ee17fab896215bc9322 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 11:57:20 +0000 Subject: r3318: generate random STATUS_MORE_ENTRIES errors (1 in 10 packets) as well as randomly short recv/send when socket:testnonblock is enabled (This used to be commit 718175a265d34bfdbcbf0cc6b55dbf6b389f3194) --- source4/lib/socket/socket.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 22b40e076c..9bdd57d200 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -158,7 +158,11 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, } if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && wantlen > 1) { - return sock->ops->recv(sock, buf, 1+(random() % (wantlen-1)), nread, flags); + if (random() % 10 == 0) { + *nread = 0; + return STATUS_MORE_ENTRIES; + } + return sock->ops->recv(sock, buf, 1+(random() % wantlen), nread, flags); } return sock->ops->recv(sock, buf, wantlen, nread, flags); @@ -182,7 +186,11 @@ NTSTATUS socket_send(struct socket_context *sock, if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) && blob->length > 1) { DATA_BLOB blob2 = *blob; - blob2.length = 1+(random() % (blob2.length-1)); + if (random() % 10 == 0) { + *sendlen = 0; + return STATUS_MORE_ENTRIES; + } + blob2.length = 1+(random() % blob2.length); return sock->ops->send(sock, &blob2, sendlen, flags); } -- cgit From e481385391a25c19d82ce93fbec11a973cf82e9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 12:46:59 +0000 Subject: r3322: fixed a bunch of warnings in the build, including one case where it was a real bug (This used to be commit 02d5d0f685e44bd66aff4a007f0bf34c8f915574) --- source4/lib/iconv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index f4f7660bcd..3cca734d7b 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -131,7 +131,6 @@ size_t smb_iconv(smb_iconv_t cd, char **outbuf, size_t *outbytesleft) { char cvtbuf[2048]; - char *bufp = cvtbuf; size_t bufsize; /* in many cases we can go direct */ @@ -143,18 +142,19 @@ size_t smb_iconv(smb_iconv_t cd, /* otherwise we have to do it chunks at a time */ while (*inbytesleft > 0) { - bufp = cvtbuf; + char *bufp1 = cvtbuf; + const char *bufp2 = cvtbuf; + bufsize = sizeof(cvtbuf); if (cd->pull(cd->cd_pull, - inbuf, inbytesleft, &bufp, &bufsize) == -1 + inbuf, inbytesleft, &bufp1, &bufsize) == -1 && errno != E2BIG) return -1; - bufp = cvtbuf; bufsize = sizeof(cvtbuf) - bufsize; if (cd->push(cd->cd_push, - &bufp, &bufsize, + &bufp2, &bufsize, outbuf, outbytesleft) == -1) return -1; } -- cgit From a6ae640313a47ac2950c0948e4385fa934a5ef09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 13:19:39 +0000 Subject: r3323: more warning reductions (This used to be commit 5921587ec26e4892efc678421277e4969417d7f5) --- source4/lib/cmdline/readline.c | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 4 +++- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 6 ----- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 12 +--------- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 28 ++++++++++------------ .../lib/registry/reg_backend_w95/reg_backend_w95.c | 9 ------- source4/lib/time.c | 12 ++++++++-- 7 files changed, 27 insertions(+), 46 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 97201d00bb..83d476b0d1 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -51,7 +51,7 @@ ****************************************************************************/ static char *smb_readline_replacement(const char *prompt, void (*callback)(void), - char **(completion_fn)(const char *text, int start, int end)) + char **(completion_fn)(const char *text, int start, int end)) { fd_set fds; static pstring line; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 5b682a493a..9ac51b26fe 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -252,7 +252,9 @@ static int lldb_search(struct ldb_context *ldb, const char *base, LDAPMessage *ldapres, *msg; lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, - expression, attrs, 0, &ldapres); + expression, + discard_const_p(char *, attrs), + 0, &ldapres); if (lldb->last_rc != LDAP_SUCCESS) { return -1; } diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index d76b7715da..faa8a5e62c 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -57,12 +57,6 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * } -static int ldb_close_registry(void *data) -{ - ldb_close((struct ldb_context *)data); - return 0; -} - static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) { struct ldb_context *c = k->hive->backend_data; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 14fff5b60d..805f95fca1 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -934,7 +934,7 @@ static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR if(tmp->data_type == REG_SZ) { char *ret; - dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (const void **)&ret); + dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (void **)&ret); dtmp = ret; } @@ -1571,16 +1571,6 @@ error: #endif -static WERROR nt_close_registry (struct registry_hive *h) -{ - REGF *regf = h->backend_data; - if (regf->base) munmap(regf->base, regf->sbuf.st_size); - regf->base = NULL; - close(regf->fd); /* Ignore the error :-) */ - - return WERR_OK; -} - static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) { REGF *regf; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index c819eb4254..76c19d01ad 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -100,7 +100,8 @@ WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *cr static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { NTSTATUS status; - char *user, *pass; + char *user; + char *pass; struct rpc_key_data *mykeydata; struct dcerpc_pipe *p; int n; @@ -114,18 +115,18 @@ static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct user = talloc_strdup(mem_ctx, h->credentials); pass = strchr(user, '%'); - if(pass) - { - *pass = '\0'; pass++; + if (pass) { + pass = strdup(pass+1); } else { - pass = ""; + pass = strdup(""); } status = dcerpc_pipe_connect(&p, h->location, - DCERPC_WINREG_UUID, - DCERPC_WINREG_VERSION, - lp_workgroup(), - user, pass); + DCERPC_WINREG_UUID, + DCERPC_WINREG_VERSION, + lp_workgroup(), + user, pass); + free(pass); h->backend_data = p; @@ -145,12 +146,7 @@ static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol)); } -static WERROR rpc_close_registry(struct registry_hive *h) -{ - dcerpc_pipe_close((struct dcerpc_pipe *)h->backend_data); - return WERR_OK; -} - +#if 0 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) { struct winreg_OpenKey r; @@ -173,7 +169,7 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) return r.out.result; } - +#endif static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) { diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 2184a8855d..c285dac7c9 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -300,15 +300,6 @@ static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key return WERR_NO_MORE_ITEMS; } -static WERROR w95_close_reg(struct registry_hive *h) -{ - CREG *creg = h->backend_data; - if (creg->base) munmap(creg->base, creg->sbuf.st_size); - creg->base = NULL; - close(creg->fd); - return WERR_OK; -} - static WERROR w95_num_values(struct registry_key *k, int *count) { RGKN_KEY *rgkn_key = k->backend_data; diff --git a/source4/lib/time.c b/source4/lib/time.c index eae30f581b..5ea9b46844 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -310,7 +310,15 @@ char *ldap_timestring(TALLOC_CTX *mem_ctx, time_t t) tm->tm_sec); } - +/* + a hack to move the stupid gcc strftime warning to one place - see manual page +*/ +#ifdef HAVE_STRFTIME +size_t sys_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) +{ + return strftime(s, max, fmt, tm); +} +#endif /**************************************************************************** Return the date and time as a string @@ -333,7 +341,7 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) in the gcc warning, not a bug in this code. See a recent strftime() manual page for details. */ - strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + sys_strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); TimeBuf = talloc_strdup(mem_ctx, tempTime); #else TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); -- cgit From bb69e3bbe62209b95f06d7d296b9c9015ab1c9b5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 28 Oct 2004 18:57:48 +0000 Subject: r3329: Add support for IPv6 (This used to be commit d8298901243ca4ce2ec420fa523c8e1407e72513) --- source4/lib/socket/config.m4 | 1 + source4/lib/socket/config.mk | 8 + source4/lib/socket/socket.c | 4 + source4/lib/socket/socket_ipv6.c | 360 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 373 insertions(+) create mode 100644 source4/lib/socket/socket_ipv6.c (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index c91f21368f..588bf9064e 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,5 +1,6 @@ SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) +SMB_MODULE_MK(socket_ipv6,SOCKET,STATIC,lib/socket/config.mk) SMB_MODULE_MK(socket_unix,SOCKET,STATIC,lib/socket/config.mk) SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 6072f743ce..76e5895933 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -7,6 +7,14 @@ INIT_OBJ_FILES = \ # End MODULE socket_ipv4 ################################################ +################################################ +# Start MODULE socket_ipv6 +[MODULE::socket_ipv6] +INIT_OBJ_FILES = \ + lib/socket/socket_ipv6.o +# End MODULE socket_ipv6 +################################################ + ################################################ # Start MODULE socket_unix [MODULE::socket_unix] diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 9bdd57d200..c3cacbebd8 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -267,6 +267,10 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type return socket_ipv4_ops(); } + if (strcmp("ipv6", name) == 0) { + return socket_ipv6_ops(); + } + if (strcmp("unix", name) == 0) { return socket_unixdom_ops(); } diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c new file mode 100644 index 0000000000..268212dcca --- /dev/null +++ b/source4/lib/socket/socket_ipv6.c @@ -0,0 +1,360 @@ +/* + Unix SMB/CIFS implementation. + Socket IPv6 functions + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static struct in6_addr interpret_addr6(const char *name) +{ + struct hostent *he; + + if (name == NULL) return in6addr_any; + + he = gethostbyname2(name, PF_INET6); + + if (he == NULL) return in6addr_any; + + return *((struct in6_addr *)he->h_addr); +} + +static NTSTATUS ipv6_tcp_init(struct socket_context *sock) +{ + sock->fd = socket(PF_INET6, SOCK_STREAM, 0); + if (sock->fd == -1) { + return map_nt_error_from_unix(errno); + } + + return NT_STATUS_OK; +} + +static void ipv6_tcp_close(struct socket_context *sock) +{ + close(sock->fd); +} + +static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, + const char *my_address, int my_port, + const char *srv_address, int srv_port, + uint32_t flags) +{ + struct sockaddr_in6 srv_addr; + struct in6_addr my_ip; + struct in6_addr srv_ip; + int ret; + + my_ip = interpret_addr6(my_address); + + if (memcmp(&my_ip, &in6addr_any, sizeof(my_ip)) || my_port != 0) { + struct sockaddr_in6 my_addr; + ZERO_STRUCT(my_addr); + my_addr.sin6_addr = my_ip; + my_addr.sin6_port = htons(my_port); + my_addr.sin6_family = PF_INET6; + + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + srv_ip = interpret_addr6(srv_address); + + ZERO_STRUCT(srv_addr); + srv_addr.sin6_addr = srv_ip; + srv_addr.sin6_port = htons(srv_port); + srv_addr.sin6_family = PF_INET6; + + ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv6_tcp_listen(struct socket_context *sock, + const char *my_address, int port, + int queue_size, uint32_t flags) +{ + struct sockaddr_in6 my_addr; + struct in6_addr ip_addr; + int ret; + + ip_addr = interpret_addr6(my_address); + + ZERO_STRUCT(my_addr); + my_addr.sin6_addr = ip_addr; + my_addr.sin6_port = htons(port); + my_addr.sin6_family = PF_INET6; + + ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + ret = listen(sock->fd, queue_size); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + sock->state= SOCKET_STATE_SERVER_LISTEN; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_context **new_sock) +{ + struct sockaddr_in cli_addr; + socklen_t cli_addr_len = sizeof(cli_addr); + int new_fd; + + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); + if (new_fd == -1) { + return map_nt_error_from_unix(errno); + } + + if (!(sock->flags & SOCKET_FLAG_BLOCK)) { + int ret = set_blocking(new_fd, False); + if (ret == -1) { + close(new_fd); + return map_nt_error_from_unix(errno); + } + } + + /* TODO: we could add a 'accept_check' hook here + * which get the black/white lists via socket_set_accept_filter() + * or something like that + * --metze + */ + + (*new_sock) = talloc_p(NULL, struct socket_context); + if (!(*new_sock)) { + close(new_fd); + return NT_STATUS_NO_MEMORY; + } + + /* copy the socket_context */ + (*new_sock)->type = sock->type; + (*new_sock)->state = SOCKET_STATE_SERVER_CONNECTED; + (*new_sock)->flags = sock->flags; + + (*new_sock)->fd = new_fd; + + (*new_sock)->private_data = NULL; + (*new_sock)->ops = sock->ops; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv6_tcp_recv(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags) +{ + ssize_t gotlen; + int flgs = 0; + + /* TODO: we need to map all flags here */ + if (flags & SOCKET_FLAG_PEEK) { + flgs |= MSG_PEEK; + } + + if (flags & SOCKET_FLAG_BLOCK) { + flgs |= MSG_WAITALL; + } + + *nread = 0; + + gotlen = recv(sock->fd, buf, wantlen, flgs); + if (gotlen == 0) { + return NT_STATUS_END_OF_FILE; + } else if (gotlen == -1) { + return map_nt_error_from_unix(errno); + } + + *nread = gotlen; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv6_tcp_send(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +{ + ssize_t len; + int flgs = 0; + + *sendlen = 0; + + len = send(sock->fd, blob->data, blob->length, flgs); + if (len == -1) { + return map_nt_error_from_unix(errno); + } + + *sendlen = len; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv6_tcp_set_option(struct socket_context *sock, const char *option, const char *val) +{ + set_socket_options(sock->fd, option); + return NT_STATUS_OK; +} + +static char *ipv6_tcp_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + struct sockaddr_in6 peer_addr; + socklen_t len = sizeof(peer_addr); + struct hostent *he; + int ret; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return NULL; + } + + he = gethostbyaddr((char *)&peer_addr.sin6_addr, sizeof(peer_addr.sin6_addr), AF_INET6); + if (he == NULL) { + return NULL; + } + + return talloc_strdup(mem_ctx, he->h_name); +} + +static char *ipv6_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + struct sockaddr_in6 peer_addr; + socklen_t len = sizeof(peer_addr); + int ret; + struct hostent *he; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return NULL; + } + + he = gethostbyaddr(&peer_addr.sin6_addr, sizeof(peer_addr.sin6_addr), AF_INET6); + + if (!he || !he->h_name) { + return NULL; + } + + return talloc_strdup(mem_ctx, he->h_name); +} + +static int ipv6_tcp_get_peer_port(struct socket_context *sock) +{ + struct sockaddr_in6 peer_addr; + socklen_t len = sizeof(peer_addr); + int ret; + + ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len); + if (ret == -1) { + return -1; + } + + return ntohs(peer_addr.sin6_port); +} + +static char *ipv6_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +{ + struct sockaddr_in6 my_addr; + socklen_t len = sizeof(my_addr); + int ret; + struct hostent *he; + + ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len); + if (ret == -1) { + return NULL; + } + + he = gethostbyaddr((char *)&my_addr.sin6_addr, sizeof(my_addr.sin6_addr), AF_INET6); + if (he == NULL) { + return NULL; + } + + return talloc_strdup(mem_ctx, he->h_name); +} + +static int ipv6_tcp_get_my_port(struct socket_context *sock) +{ + struct sockaddr_in6 my_addr; + socklen_t len = sizeof(my_addr); + int ret; + + ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len); + if (ret == -1) { + return -1; + } + + return ntohs(my_addr.sin6_port); +} + +static int ipv6_tcp_get_fd(struct socket_context *sock) +{ + return sock->fd; +} + +static const struct socket_ops ipv6_tcp_ops = { + .name = "ipv6", + .type = SOCKET_TYPE_STREAM, + + .init = ipv6_tcp_init, + .connect = ipv6_tcp_connect, + .listen = ipv6_tcp_listen, + .accept = ipv6_tcp_accept, + .recv = ipv6_tcp_recv, + .send = ipv6_tcp_send, + .close = ipv6_tcp_close, + + .set_option = ipv6_tcp_set_option, + + .get_peer_name = ipv6_tcp_get_peer_name, + .get_peer_addr = ipv6_tcp_get_peer_addr, + .get_peer_port = ipv6_tcp_get_peer_port, + .get_my_addr = ipv6_tcp_get_my_addr, + .get_my_port = ipv6_tcp_get_my_port, + + .get_fd = ipv6_tcp_get_fd +}; + +const struct socket_ops *socket_ipv6_ops(void) +{ + return &ipv6_tcp_ops; +} + +NTSTATUS socket_ipv6_init(void) +{ + return NT_STATUS_OK; +} -- cgit From 148f07c94b885412250bba7d955c423adac2e5b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 21:36:27 +0000 Subject: r3333: added configure tests for ipv6 support (This used to be commit 9794570c6d0646cc34147bf8128802b181f658f0) --- source4/lib/socket/config.m4 | 7 ++++++- source4/lib/socket/socket.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 588bf9064e..8c4a9fe40c 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,6 +1,11 @@ SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) -SMB_MODULE_MK(socket_ipv6,SOCKET,STATIC,lib/socket/config.mk) SMB_MODULE_MK(socket_unix,SOCKET,STATIC,lib/socket/config.mk) +AC_CHECK_FUNCS(gethostbyname2, have_ipv6=true, have_ipv6=false) +if $have_ipv6 = true; then + AC_DEFINE(HAVE_SOCKET_IPV6,1,[Whether the system has ipv6 support]) + SMB_MODULE_MK(socket_ipv6,SOCKET,STATIC,lib/socket/config.mk) +fi + SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index c3cacbebd8..84bb1ccafe 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -267,9 +267,11 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type return socket_ipv4_ops(); } +#if HAVE_SOCKET_IPV6 if (strcmp("ipv6", name) == 0) { return socket_ipv6_ops(); } +#endif if (strcmp("unix", name) == 0) { return socket_unixdom_ops(); -- cgit From 08c4d0db0c22e6432e793f88bb93cf631f31ea20 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 28 Oct 2004 21:41:21 +0000 Subject: r3334: Allow disabling IPv6 support using socket:noipv6 (This used to be commit 9c13f42c1fd489a6a663f614a41c59730c18a054) --- source4/lib/socket/socket.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 84bb1ccafe..dbbae5ea7e 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -269,6 +269,10 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type #if HAVE_SOCKET_IPV6 if (strcmp("ipv6", name) == 0) { + if (lp_parm_bool(-1, "socket", "noipv6", False)) { + DEBUG(3, ("IPv6 support was disabled in smb.conf")); + return NULL; + } return socket_ipv6_ops(); } #endif -- cgit From 94c0b939c4735866945aea8b7a0377be4d814125 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 21:47:10 +0000 Subject: r3335: better configure support for ipv6 - thanks to a quick tutorial from metze (This used to be commit 76c4ba6d29a6ad1e21c2d7674e1f323e8d53d627) --- source4/lib/socket/config.m4 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 8c4a9fe40c..37eff7ded1 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -2,10 +2,16 @@ SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) SMB_MODULE_MK(socket_unix,SOCKET,STATIC,lib/socket/config.mk) +dnl test for ipv6 using the gethostbyname2() function. That should be sufficient +dnl for now AC_CHECK_FUNCS(gethostbyname2, have_ipv6=true, have_ipv6=false) if $have_ipv6 = true; then + SMB_MODULE_DEFAULT(socket_ipv6, STATIC) AC_DEFINE(HAVE_SOCKET_IPV6,1,[Whether the system has ipv6 support]) - SMB_MODULE_MK(socket_ipv6,SOCKET,STATIC,lib/socket/config.mk) fi +dnl don't build ipv6 by default, unless the above test enables it, or +dnl the configure uses --with-static-modules=socket_ipv6 +SMB_MODULE_MK(socket_ipv6,SOCKET,NOT,lib/socket/config.mk) + SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) -- cgit From 479bf22c813501f040adf7b6267b961748baa63f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 28 Oct 2004 23:06:12 +0000 Subject: r3340: Various fixes in the registry code. Implement the EnumKey call in the server. (This used to be commit da65a248c292a90342e1394ee4132ef2c7afd3c8) --- source4/lib/registry/common/reg_interface.c | 5 ++++- source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 5 ++++- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 16edadfcbb..6237a788b7 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -191,7 +191,10 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch if(!W_ERROR_IS_OK(werr)) return werr; - if(!ret->root) return WERR_GENERAL_FAILURE; + if(!ret->root) { + DEBUG(0, ("Backend %s didn't provide root key!\n", backend)); + return WERR_GENERAL_FAILURE; + } ret->root->hive = ret; ret->root->name = NULL; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index faa8a5e62c..b26ee6ec60 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -146,7 +146,10 @@ static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, str ldb_set_debug_stderr(c); hive->backend_data = c; - return ldb_open_key(mem_ctx, hive, "", k); + hive->root = talloc_zero_p(mem_ctx, struct registry_key); + hive->root->name = talloc_strdup(mem_ctx, ""); + + return WERR_OK; } static struct registry_operations reg_backend_ldb = { diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 76c19d01ad..5ed03c062c 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -85,7 +85,7 @@ struct { static WERROR rpc_query_key(struct registry_key *k); -WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) +static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) { int i = 0; *hives = talloc_p(mem_ctx, char *); -- cgit From 7ce7137ad4edb03acf6189568d4c3c4f6d8798fe Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 01:10:40 +0000 Subject: r3348: More registry fixes and additions. The following functions work right now against samba 4, at least with a ldb backend: winreg_Open* winreg_OpenKey winreg_EnumKey winreg_DeleteKey winreg_CreateKey (This used to be commit a71d51dd3b136a1bcde1704fe9830985e06bb01b) --- source4/lib/registry/common/reg_interface.c | 1 + .../registry/reg_backend_gconf/reg_backend_gconf.c | 10 ++--- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 46 +++++++++++++++++++++- 3 files changed, 50 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 6237a788b7..a9f7bf1d5f 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -367,6 +367,7 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, if(key->hive->functions->get_subkey_by_name) { error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); + /* FIXME: Fall back to reg_open_key rather then get_subkey_by_index */ } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index d8c8d951c1..4f8cc5466e 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -35,8 +35,8 @@ static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, if(!h->backend_data) return WERR_FOOBAR; *k = talloc_p(mem_ctx, struct registry_key); - (*k)->name = ""; - (*k)->path = ""; + (*k)->name = talloc_strdup(mem_ctx, ""); + (*k)->path = talloc_strdup(mem_ctx, ""); (*k)->backend_data = talloc_strdup(mem_ctx, "/"); return WERR_OK; } @@ -46,17 +46,15 @@ static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, cons struct registry_key *ret; char *fullpath; - fullpath = reg_path_win2unix(strdup(name)); + fullpath = talloc_asprintf(mem_ctx, "/%s", reg_path_win2unix(talloc_strdup(mem_ctx, name))); /* Check if key exists */ if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { - SAFE_FREE(fullpath); return WERR_DEST_NOT_FOUND; } ret = talloc_p(mem_ctx, struct registry_key); - ret->backend_data = talloc_strdup(mem_ctx, fullpath); - SAFE_FREE(fullpath); + ret->backend_data = fullpath; *key = ret; return WERR_OK; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index b26ee6ec60..a18bed5591 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -142,7 +142,10 @@ static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, str if (!hive->location) return WERR_INVALID_PARAM; c = ldb_connect(hive->location, 0, NULL); - if(!c) return WERR_FOOBAR; + if(!c) { + DEBUG(1, ("ldb_open_hive: %s\n", ldb_errstring(hive->backend_data))); + return WERR_FOOBAR; + } ldb_set_debug_stderr(c); hive->backend_data = c; @@ -152,8 +155,49 @@ static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, str return WERR_OK; } +static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sd, struct registry_key **newkey) +{ + struct ldb_context *ctx = parent->hive->backend_data; + struct ldb_message msg; + int ret; + + ZERO_STRUCT(msg); + + msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "key=%s,", name)); + + ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name)); + + ret = ldb_add(ctx, &msg); + if (ret < 0) { + DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); + return WERR_FOOBAR; + } + + *newkey = talloc_zero_p(mem_ctx, struct registry_key); + (*newkey)->backend_data = msg.dn; + (*newkey)->name = talloc_strdup(mem_ctx, name); + + return WERR_OK; +} + +static WERROR ldb_del_key (struct registry_key *key) +{ + int ret; + + ret = ldb_delete(key->hive->backend_data, key->backend_data); + + if (ret < 0) { + DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); + return WERR_FOOBAR; + } + + return WERR_OK; +} + static struct registry_operations reg_backend_ldb = { .name = "ldb", + .add_key = ldb_add_key, + .del_key = ldb_del_key, .open_hive = ldb_open_hive, .open_key = ldb_open_key, .get_value_by_index = ldb_get_value_by_id, -- cgit From 0caeda53d37740d18b38e6d37d0ecef8c6336820 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 07:00:14 +0000 Subject: r3356: in the standard process model we need to make sure we close all listening sockets after the fork to prevent the child still listening on incoming requests. I have also added an optimisation where we use dup()/close() to lower the file descriptor number of the new socket to the lowest possible after closing our listening sockets. This keeps the max fd num passed to select() low, which makes a difference to the speed of select(). (This used to be commit f2a9bbc317ba86ebe87c3ca27a3a0192de91014d) --- source4/lib/socket/socket.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index dbbae5ea7e..892695f6eb 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -260,6 +260,28 @@ int socket_get_fd(struct socket_context *sock) return sock->ops->get_fd(sock); } +/* + call dup() on a socket, and close the old fd. This is used to change + the fd to the lowest available number, to make select() more + efficient (select speed depends on the maxiumum fd number passed to + it) +*/ +NTSTATUS socket_dup(struct socket_context *sock) +{ + int fd; + if (sock->fd == -1) { + return NT_STATUS_INVALID_HANDLE; + } + fd = dup(sock->fd); + if (fd == -1) { + return map_nt_error_from_unix(errno); + } + close(sock->fd); + sock->fd = fd; + return NT_STATUS_OK; + +} + const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) { if (strcmp("ip", name) == 0 || -- cgit From dbf03959244c392073281c10badd2095397ad2f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 07:29:26 +0000 Subject: r3357: removed the need to use TDB_CLEAR_IF_FIRST in Samba4. We found a few months ago that TDB_CLEAR_IF_FIRST is extremely inefficient for large numbers of connections, due to a fundamental limitation in the way posix byte range locking is implemented. Rather than the nasty workaround we had for Samba3, we now have a single "cleanup tmp files" function that runs when smbd starts. That deletes the tmp tdbs, so TDB_CLEAR_IF_FIRST is not needed at all. (This used to be commit ffa285bc783c775a2d53a58fb691ca339e6c76ae) --- source4/lib/util.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index d7c5661f7d..8b27bf070c 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -705,15 +705,18 @@ char *name_to_fqdn(TALLOC_CTX *mem_ctx, const char *name) char *lock_path(TALLOC_CTX* mem_ctx, const char *name) { - char *fname; + char *fname, *dname; - fname = talloc_strdup(mem_ctx, lp_lockdir()); - trim_string(fname,"","/"); + dname = talloc_strdup(mem_ctx, lp_lockdir()); + trim_string(dname,"","/"); - if (!directory_exist(fname,NULL)) - mkdir(fname,0755); + if (!directory_exist(dname,NULL)) { + mkdir(dname,0755); + } - fname = talloc_asprintf(mem_ctx, "%s/%s", fname, name); + fname = talloc_asprintf(mem_ctx, "%s/%s", dname, name); + + talloc_free(dname); return fname; } -- cgit From 09d0b152b7bd85aa01898af81bd166a7673ab886 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 08:38:59 +0000 Subject: r3360: improved the deletion of tmp files. smbd now puts all tmp files in var/locks/smbd.tmp/ and deletes that dir on startup. (This used to be commit 7e942e7f1bd2c293a0e6648df43a96f8b8a2a295) --- source4/lib/messaging/messaging.c | 4 ++-- source4/lib/util.c | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 7f90bd4e40..125089ac62 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -85,7 +85,7 @@ static char *messaging_path(TALLOC_CTX *mem_ctx, servid_t server_id) { char *name = talloc_asprintf(mem_ctx, "messaging/msg.%u", (unsigned)server_id); char *ret; - ret = lock_path(mem_ctx, name); + ret = smbd_tmp_path(mem_ctx, name); talloc_free(name); return ret; } @@ -449,7 +449,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id } /* create the messaging directory if needed */ - msg->path = lock_path(msg, "messaging"); + msg->path = smbd_tmp_path(msg, "messaging"); mkdir(msg->path, 0700); talloc_free(msg->path); diff --git a/source4/lib/util.c b/source4/lib/util.c index 8b27bf070c..97d3d5dd1b 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -702,7 +702,6 @@ char *name_to_fqdn(TALLOC_CTX *mem_ctx, const char *name) /***************************************************************** A useful function for returning a path in the Samba lock directory. *****************************************************************/ - char *lock_path(TALLOC_CTX* mem_ctx, const char *name) { char *fname, *dname; @@ -736,6 +735,30 @@ char *lib_path(TALLOC_CTX* mem_ctx, const char *name) return fname; } +/* + return a path in the smbd.tmp directory, where all temporary file + for smbd go. If NULL is passed for name then return the directory + path itself +*/ +char *smbd_tmp_path(TALLOC_CTX *mem_ctx, const char *name) +{ + char *fname, *dname; + + dname = lock_path(mem_ctx, "smbd.tmp"); + if (!directory_exist(dname,NULL)) { + mkdir(dname,0755); + } + + if (name == NULL) { + return dname; + } + + fname = talloc_asprintf(mem_ctx, "%s/%s", dname, name); + talloc_free(dname); + + return fname; +} + /** * @brief Returns the platform specific shared library extension. * -- cgit From e78bfc960385a094b03faa462408d8c8391fcbaf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 11:39:08 +0000 Subject: r3366: updates from the junkcode version of talloc. The main change is to get rid of talloc_parent_chunk() from all commonly used code paths, so talloc_free() is now O(1) again. It was originally O(1), but the last round of changes broke that. Also some documentation updates (This used to be commit d4fe21cdb982c8046b19f671d872b43cdd2efc72) --- source4/lib/talloc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 12b21d21e6..131edfcb81 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -441,7 +441,7 @@ int talloc_free(void *ptr) if (tc->refs) { talloc_reference_destructor(tc->refs); - return 0; + return -1; } if (tc->destructor) { @@ -469,11 +469,13 @@ int talloc_free(void *ptr) struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); if (p) new_parent = p+1; } - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; + if (talloc_free(child) == -1) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = p+1; + } + talloc_steal(new_parent, child); } - talloc_free(talloc_steal(new_parent, child)); } if (tc->parent) { -- cgit From a29c24f180cc21b358c51a86632eb1cc2cb17868 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 11:44:59 +0000 Subject: r3367: More registry updates. Add support flush_key and close_hive. (This used to be commit c526273df238c994c4de3c1704c6e95433f2331c) --- source4/lib/registry/common/reg_interface.c | 33 ++++++++++++++++++++-- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 7 +++++ .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 7 +++++ 3 files changed, 44 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index a9f7bf1d5f..999203f4d1 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -157,6 +157,19 @@ WERROR reg_open(struct registry_context **ret, const char *backend, const char * return WERR_OK; } +WERROR reg_close (struct registry_context *ctx) +{ + int i; + for (i = 0; i < ctx->num_hives; i++) { + if (ctx->hives[i]->functions->close_hive) { + ctx->hives[i]->functions->close_hive(ctx->hives[i]); + } + } + talloc_destroy(ctx); + + return WERR_OK; +} + /* Open a registry file/host/etc */ WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) { @@ -367,7 +380,8 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, if(key->hive->functions->get_subkey_by_name) { error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); - /* FIXME: Fall back to reg_open_key rather then get_subkey_by_index */ + } else if(key->hive->functions->open_key) { + error = key->hive->functions->open_key(mem_ctx, key->hive, talloc_asprintf(mem_ctx, "%s\\%s", key->path, name), subkey); } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); @@ -589,9 +603,8 @@ WERROR reg_del_value(struct registry_value *val) return ret; } -WERROR reg_save(struct registry_context *h, const char *location) +WERROR reg_save (struct registry_context *ctx, const char *location) { - /* FIXME */ return WERR_NOT_SUPPORTED; } @@ -615,3 +628,17 @@ WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct SAFE_FREE(parent_name); return error; } + +WERROR reg_key_flush(struct registry_key *key) +{ + if (!key) { + return WERR_INVALID_PARAM; + } + + if (key->hive->functions->flush_key) { + return key->hive->functions->flush_key(key); + } + + /* No need for flushing, apparently */ + return WERR_OK; +} diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index a18bed5591..bd3afbdedf 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -194,11 +194,18 @@ static WERROR ldb_del_key (struct registry_key *key) return WERR_OK; } +static WERROR ldb_close_hive (struct registry_hive *hive) +{ + ldb_close (hive->backend_data); + return WERR_OK; +} + static struct registry_operations reg_backend_ldb = { .name = "ldb", .add_key = ldb_add_key, .del_key = ldb_del_key, .open_hive = ldb_open_hive, + .close_hive = ldb_close_hive, .open_key = ldb_open_key, .get_value_by_index = ldb_get_value_by_id, .get_subkey_by_index = ldb_get_subkey_by_id, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 5ed03c062c..31e55bc9a3 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -97,6 +97,12 @@ static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const c return WERR_OK; } +static WERROR rpc_close_hive (struct registry_hive *h) +{ + dcerpc_pipe_close(h->backend_data); + return WERR_OK; +} + static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) { NTSTATUS status; @@ -373,6 +379,7 @@ static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { static struct registry_operations reg_backend_rpc = { .name = "rpc", .open_hive = rpc_open_hive, + .close_hive = rpc_close_hive, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, .get_value_by_index = rpc_get_value_by_index, -- cgit From 9ba6c3885acb79d9c35e600f9a67f8ed0200edfd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 12:12:24 +0000 Subject: r3368: Default to rpc backend with binding "ncalrpc:" if no backend was specified in the various registry tools. Allow opening a remote registry to partly fail (I.e. if not all hives could be opened) (This used to be commit 313034b10d7a70d079e2bec1af38cf2a7cd918c1) --- source4/lib/registry/common/reg_interface.c | 12 ++++++++---- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 11 +++++++++-- source4/lib/registry/tools/regdiff.c | 4 ++-- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 6 +++--- source4/lib/registry/tools/regtree.c | 2 +- 6 files changed, 24 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 999203f4d1..044dc9a0ad 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -132,9 +132,9 @@ WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) { - WERROR error = reg_create(ret); + WERROR error = reg_create(ret), reterror = WERR_NO_MORE_ITEMS; char **hives; - int i; + int i, j; TALLOC_CTX *mem_ctx = talloc_init("reg_open"); if(!W_ERROR_IS_OK(error)) return error; @@ -147,11 +147,15 @@ WERROR reg_open(struct registry_context **ret, const char *backend, const char * if(!W_ERROR_IS_OK(error)) return error; + j = 0; for(i = 0; hives[i]; i++) { error = reg_import_hive(*ret, backend, location, credentials, hives[i]); - if(!W_ERROR_IS_OK(error)) return error; - (*ret)->hives[i]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); + if (W_ERROR_IS_OK(error)) { + reterror = WERR_OK; + (*ret)->hives[j]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); + j++; + } else if (!W_ERROR_IS_OK(reterror)) reterror = error; } return WERR_OK; diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 31e55bc9a3..27bd3ff957 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -122,6 +122,7 @@ static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct user = talloc_strdup(mem_ctx, h->credentials); pass = strchr(user, '%'); if (pass) { + *pass = '\0'; pass = strdup(pass+1); } else { pass = strdup(""); @@ -136,14 +137,20 @@ static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct h->backend_data = p; - if(NT_STATUS_IS_ERR(status)) return ntstatus_to_werror(status); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status))); + return ntstatus_to_werror(status); + } for(n = 0; known_hives[n].name; n++) { if(!strcmp(known_hives[n].name, h->backend_hivename)) break; } - if(!known_hives[n].name) return WERR_NO_MORE_ITEMS; + if(!known_hives[n].name) { + DEBUG(1, ("No such hive %s\n", known_hives[n].name)); + return WERR_NO_MORE_ITEMS; + } *k = talloc_p(mem_ctx, struct registry_key); (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 524e538591..41a29e46d3 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -158,7 +158,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, return 1; } - if(!backend1) backend1 = "dir"; + if(!backend1) backend1 = "rpc"; error = reg_open(&h1, backend1, location1, credentials1); if(!W_ERROR_IS_OK(error)) { @@ -173,7 +173,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, return 2; } - if(!backend2) backend2 = "dir"; + if(!backend2) backend2 = "rpc"; error = reg_open(&h2, backend2, location2, credentials2); if(!W_ERROR_IS_OK(error)) { diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 1b33628a71..eed249d353 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -760,7 +760,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd const char *location; const char *credentials = NULL; const char *patch; - const char *backend = "dir"; + const char *backend = "rpc"; struct registry_context *h; WERROR error; struct poptOption long_options[] = { diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 78fe36f1a0..db7af9d5b6 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -337,7 +337,7 @@ static char **reg_completion(const char *text, int start, int end) int main(int argc, char **argv) { int opt; - const char *backend = "dir"; + const char *backend = "rpc"; const char *credentials = NULL; struct registry_key *curkey = NULL; poptContext pc; @@ -363,6 +363,8 @@ static char **reg_completion(const char *text, int start, int end) while((opt = poptGetNextOpt(pc)) != -1) { } + setup_logging("regtree", True); + error = reg_open(&h, backend, poptPeekArg(pc), credentials); if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); @@ -370,8 +372,6 @@ static char **reg_completion(const char *text, int start, int end) } poptFreeContext(pc); - setup_logging("regtree", True); - curkey = h->hives[0]->root; while(True) { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index bc0055a891..66bce1e499 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -70,7 +70,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) int main(int argc, char **argv) { int opt, i; - const char *backend = "dir"; + const char *backend = "rpc"; const char *credentials = NULL; poptContext pc; struct registry_context *h; -- cgit From 9dc3f789c41cc63a784e087dc0f061e495e04bab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 13:38:37 +0000 Subject: r3369: More registry updates We now pass the RPC-WINREG torture test. Also, constructions like the following work now: regtree <-> smbd <-> NTUSER.DAT (This used to be commit df952e95cd1cbbfb62b4620e9452993aaef44ad3) --- source4/lib/registry/common/reg_interface.c | 76 +++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 044dc9a0ad..09267a6370 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -340,7 +340,7 @@ WERROR reg_key_num_subkeys(struct registry_key *key, int *count) talloc_destroy(mem_ctx); *count = i; - if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_OK; + if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK; return error; } @@ -351,8 +351,26 @@ WERROR reg_key_num_values(struct registry_key *key, int *count) { if(!key) return WERR_INVALID_PARAM; - - return key->hive->functions->num_values(key, count); + + if (key->hive->functions->num_values) { + return key->hive->functions->num_values(key, count); + } + + if(key->hive->functions->get_value_by_index) { + int i; + WERROR error; + struct registry_value *dest; + TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); + + for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++); + talloc_destroy(mem_ctx); + + *count = i; + if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK; + return error; + } + + return WERR_NOT_SUPPORTED; } WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey) @@ -646,3 +664,55 @@ WERROR reg_key_flush(struct registry_key *key) /* No need for flushing, apparently */ return WERR_OK; } + +WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint32 *max_subkeysize) +{ + int i = 0; + struct registry_key *subkey; + WERROR error; + TALLOC_CTX *mem_ctx = talloc_init("subkeysize"); + + *max_subkeylen = *max_subkeysize = 0; + + do { + error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey); + + if (W_ERROR_IS_OK(error)) { + *max_subkeysize = MAX(*max_subkeysize, 0xFF); + *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name)); + } + + i++; + } while (W_ERROR_IS_OK(error)); + + talloc_destroy(mem_ctx); + + return WERR_OK; +} + +WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint32 *max_valbufsize) +{ + int i = 0; + struct registry_value *value; + WERROR error; + TALLOC_CTX *mem_ctx = talloc_init("subkeysize"); + + *max_valnamelen = *max_valbufsize = 0; + + do { + error = reg_key_get_value_by_index(mem_ctx, key, i, &value); + + if (W_ERROR_IS_OK(error)) { + if (value->name) { + *max_valnamelen = MAX(*max_valnamelen, strlen(value->name)); + } + *max_valbufsize = MAX(*max_valbufsize, value->data_len); + } + + i++; + } while (W_ERROR_IS_OK(error)); + + talloc_destroy(mem_ctx); + + return WERR_OK; +} -- cgit From def0a74030714d07ed852178d9a8f2ec4ed16bab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 14:53:23 +0000 Subject: r3370: Initial work on Add Key/Delete Key/Add Value/Mod Value/Del Value support in gregedit (This used to be commit 33f429c61f2859e3ad60fa38823174bbd331d91a) --- source4/lib/registry/tools/regdiff.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 41a29e46d3..bedf3222d1 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -115,7 +115,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; - struct registry_context *h1, *h2; + struct registry_context *h1 = NULL, *h2; int from_null = 0; int i; WERROR error, error2; @@ -165,7 +165,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); return 1; } - } + } location2 = poptGetArg(pc); if(!location2) { @@ -196,8 +196,8 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, error2 = error = WERR_OK; - for(i = 0; i < h1->num_hives && i < h2->num_hives; i++) { - writediff(h1->hives[i]->root, h2->hives[i]->root, fd); + for(i = 0; (!h1 || i < h1->num_hives) && i < h2->num_hives; i++) { + writediff(h1?h1->hives[i]->root:NULL, h2->hives[i]->root, fd); } fclose(fd); -- cgit From 3ab24d0d2236241c3f7f04db1b08d1ee80ce5530 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 29 Oct 2004 21:53:42 +0000 Subject: r3374: Couple of bug fixes (This used to be commit f8e45e143087d333da4afc193b4fa1991ba04c63) --- source4/lib/registry/common/reg_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 09267a6370..70b600ba33 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -158,7 +158,7 @@ WERROR reg_open(struct registry_context **ret, const char *backend, const char * } else if (!W_ERROR_IS_OK(reterror)) reterror = error; } - return WERR_OK; + return reterror; } WERROR reg_close (struct registry_context *ctx) -- cgit From 48ce437be2e3da6d67844dfed3d574986c55a67e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 05:22:44 +0000 Subject: r3421: got rid of some unused code (This used to be commit 0333f417a86a54a328ca9bd908076f9fe8405dc7) --- source4/lib/tdb/tools/tdbtool.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 92009dcef4..50486122bc 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -343,43 +343,13 @@ static void move_rec(void) return; } -#if 0 -static int print_conn_key(TDB_DATA key) -{ - printf( "pid =%5d ", ((connections_key*)key.dptr)->pid); - printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum); - printf( "name =[%s]\n", ((connections_key*)key.dptr)->name); - return 0; -} - -static int print_conn_data(TDB_DATA dbuf) -{ - printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid); - printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum); - printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->name); - - printf( "uid =%5d ", ((connections_data*)dbuf.dptr)->uid); - printf( "addr =[%s]\n", ((connections_data*)dbuf.dptr)->addr); - printf( "gid =%5d ", ((connections_data*)dbuf.dptr)->gid); - printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine); - printf( "start = %s\n", ctime(&((connections_data*)dbuf.dptr)->start)); - return 0; -} -#endif - static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { -#if 0 - print_conn_key(key); - print_conn_data(dbuf); - return 0; -#else printf("\nkey %d bytes\n", key.dsize); print_asc(key.dptr, key.dsize); printf("\ndata %d bytes\n", dbuf.dsize); print_data(dbuf.dptr, dbuf.dsize); return 0; -#endif } static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -- cgit From 475c958450c863a8fc530ccf5bb712bd7a6e8aa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 05:46:52 +0000 Subject: r3425: got rid of a bunch of cruft from rewrite.h (This used to be commit 3f902f8d851d32fa81d89ed61bfda6edaea00984) --- source4/lib/interface.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/interface.c b/source4/lib/interface.c index b842fbb292..72568912af 100644 --- a/source4/lib/interface.c +++ b/source4/lib/interface.c @@ -26,6 +26,14 @@ static int total_probed; static struct in_addr allones_ip; struct in_addr loopback_ip; +/* used for network interfaces */ +struct interface { + struct interface *next, *prev; + struct in_addr ip; + struct in_addr bcast; + struct in_addr nmask; +}; + static struct interface *local_interfaces; #define ALLONES ((uint32_t)0xFFFFFFFF) -- cgit From 90067934cd3195df80f8b1e614629d51fffcb38b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 10:30:34 +0000 Subject: r3428: switched to using minimal includes for the auto-generated RPC code. The thing that finally convinced me that minimal includes was worth pursuing for rpc was a compiler (tcc) that failed to build Samba due to reaching internal limits of the size of include files. Also the fact that includes.h.gch was 16MB, which really seems excessive. This patch brings it back to 12M, which is still too large, but better. Note that this patch speeds up compile times for both the pch and non-pch case. This change also includes the addition iof a "depends()" option in our IDL files, allowing you to specify that one IDL file depends on another. This capability was needed for the auto-includes generation. (This used to be commit b8f5fa8ac8e8725f3d321004f0aedf4246fc6b49) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 27bd3ff957..f90b123bfc 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" +#include "librpc/gen_ndr/ndr_winreg.h" /** * This is the RPC backend for the registry library. -- cgit From 652b8b34f8b326f79771b03e039cfa3c6ba3427e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 20:21:54 +0000 Subject: r3441: some include file cleanups and general housekeeping (This used to be commit 73ea8ee6c268371d05cf74160f2ad451dd2ae699) --- source4/lib/cmdline/popt_common.c | 2 +- source4/lib/dprintf.c | 6 +- source4/lib/genrand.c | 4 +- source4/lib/pidfile.c | 8 +- source4/lib/replace.c | 2 +- source4/lib/signal.c | 2 +- source4/lib/system.c | 187 -------------------------------------- source4/lib/util.c | 42 ++++----- source4/lib/util_file.c | 94 +------------------ source4/lib/util_sock.c | 2 +- source4/lib/xfile.c | 4 +- 11 files changed, 38 insertions(+), 315 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 05e92866b2..bd46373d58 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -175,7 +175,7 @@ static void get_password_file(struct cmdline_auth_info *a) sscanf(p, "%d", &fd); close_it = False; } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = sys_open(p, O_RDONLY, 0); + fd = open(p, O_RDONLY, 0); pstrcpy(spec, p); if (fd < 0) { fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", diff --git a/source4/lib/dprintf.c b/source4/lib/dprintf.c index fe939f0e8d..5538c490ce 100644 --- a/source4/lib/dprintf.c +++ b/source4/lib/dprintf.c @@ -31,7 +31,7 @@ #include "includes.h" - int d_vfprintf(FILE *f, const char *format, va_list ap) +int d_vfprintf(FILE *f, const char *format, va_list ap) _PRINTF_ATTRIBUTE(2,0) { char *p, *p2; int ret, maxlen, clen; @@ -77,7 +77,7 @@ again: } - int d_fprintf(FILE *f, const char *format, ...) +int d_fprintf(FILE *f, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) { int ret; va_list ap; @@ -91,7 +91,7 @@ again: static FILE *outfile; - int d_printf(const char *format, ...) +int d_printf(const char *format, ...) _PRINTF_ATTRIBUTE(1,2) { int ret; va_list ap; diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 72e4997596..11771b32c9 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -118,7 +118,7 @@ static void do_filehash(const char *fname, unsigned char *the_hash) unsigned char tmp_md4[16]; int fd, n; - fd = sys_open(fname,O_RDONLY,0); + fd = open(fname,O_RDONLY,0); if (fd == -1) return; @@ -152,7 +152,7 @@ static int do_reseed(BOOL use_fd, int fd) if (fd != -1) return fd; - fd = sys_open( "/dev/urandom", O_RDONLY,0); + fd = open( "/dev/urandom", O_RDONLY,0); if(fd >= 0) return fd; } diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index 989f19b323..f8041a2005 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -37,7 +37,7 @@ pid_t pidfile_pid(const char *name) slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); - fd = sys_open(pidFile, O_NONBLOCK | O_RDONLY, 0644); + fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644); if (fd == -1) { return 0; } @@ -54,7 +54,7 @@ pid_t pidfile_pid(const char *name) goto noproc; } - if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_RDLCK)) { + if (fcntl_lock(fd,F_SETLK,0,1,F_RDLCK)) { /* we could get the lock - it can't be a Samba process */ goto noproc; } @@ -85,14 +85,14 @@ void pidfile_create(const char *name) exit(1); } - fd = sys_open(pidFile, O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL, 0644); + fd = open(pidFile, O_NONBLOCK | O_CREAT | O_WRONLY | O_EXCL, 0644); if (fd == -1) { DEBUG(0,("ERROR: can't open %s: Error was %s\n", pidFile, strerror(errno))); exit(1); } - if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_WRLCK)==False) { + if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False) { DEBUG(0,("ERROR: %s : fcntl lock of file %s failed. Error was %s\n", name, pidFile, strerror(errno))); exit(1); diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 4ed99c833c..c23c65c8c8 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -27,7 +27,7 @@ /******************************************************************* ftruncate for operating systems that don't have it ********************************************************************/ - int ftruncate(int f,SMB_OFF_T l) + int ftruncate(int f,off_t l) { struct flock fl; diff --git a/source4/lib/signal.c b/source4/lib/signal.c index bff4b91c1a..00fc214639 100644 --- a/source4/lib/signal.c +++ b/source4/lib/signal.c @@ -27,7 +27,7 @@ static void sig_cld(int signum) { - while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ; /* diff --git a/source4/lib/system.c b/source4/lib/system.c index e8a944d8f8..1407e7474e 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -128,193 +128,6 @@ ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct return ret; } -/******************************************************************* -A recvfrom wrapper that will deal with EINTR. -********************************************************************/ - -ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) -{ - ssize_t ret; - - do { - ret = recvfrom(s, buf, len, flags, from, fromlen); - } while (ret == -1 && errno == EINTR); - return ret; -} - -/******************************************************************* -A fcntl wrapper that will deal with EINTR. -********************************************************************/ - -int sys_fcntl_ptr(int fd, int cmd, void *arg) -{ - int ret; - - do { - ret = fcntl(fd, cmd, arg); - } while (ret == -1 && errno == EINTR); - return ret; -} - -/******************************************************************* -A fcntl wrapper that will deal with EINTR. -********************************************************************/ - -int sys_fcntl_long(int fd, int cmd, long arg) -{ - int ret; - - do { - ret = fcntl(fd, cmd, arg); - } while (ret == -1 && errno == EINTR); - return ret; -} - -/******************************************************************* -A stat() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf) -{ - int ret; -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64) - ret = stat64(fname, sbuf); -#else - ret = stat(fname, sbuf); -#endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; - return ret; -} - -/******************************************************************* - An fstat() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf) -{ - int ret; -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64) - ret = fstat64(fd, sbuf); -#else - ret = fstat(fd, sbuf); -#endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; - return ret; -} - -/******************************************************************* - An lstat() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf) -{ - int ret; -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64) - ret = lstat64(fname, sbuf); -#else - ret = lstat(fname, sbuf); -#endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; - return ret; -} - -/******************************************************************* - An ftruncate() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_ftruncate(int fd, SMB_OFF_T offset) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64) - return ftruncate64(fd, offset); -#else - return ftruncate(fd, offset); -#endif -} - -/******************************************************************* - An lseek() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64) - return lseek64(fd, offset, whence); -#else - return lseek(fd, offset, whence); -#endif -} - -/******************************************************************* - A creat() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_creat(const char *path, mode_t mode) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64) - return creat64(path, mode); -#else - /* - * If creat64 isn't defined then ensure we call a potential open64. - * JRA. - */ - return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); -#endif -} - -/******************************************************************* - An open() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -int sys_open(const char *path, int oflag, mode_t mode) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64) - return open64(path, oflag, mode); -#else - return open(path, oflag, mode); -#endif -} - -/******************************************************************* - An fopen() wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -FILE *sys_fopen(const char *path, const char *type) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64) - return fopen64(path, type); -#else - return fopen(path, type); -#endif -} - -/******************************************************************* - A readdir wrapper that will deal with 64 bit filesizes. -********************************************************************/ - -struct smb_dirent *sys_readdir(DIR *dirp) -{ -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64) - return readdir64(dirp); -#else - return readdir(dirp); -#endif -} - -/******************************************************************* -The wait() calls vary between systems -********************************************************************/ - -int sys_waitpid(pid_t pid,int *status,int options) -{ -#ifdef HAVE_WAITPID - return waitpid(pid,status,options); -#else /* HAVE_WAITPID */ - return wait4(pid, status, options, NULL); -#endif /* HAVE_WAITPID */ -} /******************************************************************* System wrapper for getwd diff --git a/source4/lib/util.c b/source4/lib/util.c index 97d3d5dd1b..07dc182580 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -40,13 +40,13 @@ const char *tmpdir(void) /******************************************************************* Check if a file exists - call vfs_file_exist for samba files. ********************************************************************/ -BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf) +BOOL file_exist(const char *fname, struct stat *sbuf) { - SMB_STRUCT_STAT st; + struct stat st; if (!sbuf) sbuf = &st; - if (sys_stat(fname,sbuf) != 0) + if (stat(fname,sbuf) != 0) return(False); return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode))); @@ -58,9 +58,9 @@ BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf) time_t file_modtime(const char *fname) { - SMB_STRUCT_STAT st; + struct stat st; - if (sys_stat(fname,&st) != 0) + if (stat(fname,&st) != 0) return(0); return(st.st_mtime); @@ -70,15 +70,15 @@ time_t file_modtime(const char *fname) Check if a directory exists. ********************************************************************/ -BOOL directory_exist(const char *dname,SMB_STRUCT_STAT *st) +BOOL directory_exist(const char *dname,struct stat *st) { - SMB_STRUCT_STAT st2; + struct stat st2; BOOL ret; if (!st) st = &st2; - if (sys_stat(dname,st) != 0) + if (stat(dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); @@ -90,12 +90,12 @@ BOOL directory_exist(const char *dname,SMB_STRUCT_STAT *st) /******************************************************************* Returns the size in bytes of the named file. ********************************************************************/ -SMB_OFF_T get_file_size(char *file_name) +off_t get_file_size(char *file_name) { - SMB_STRUCT_STAT buf; + struct stat buf; buf.st_size = 0; - if(sys_stat(file_name,&buf) != 0) - return (SMB_OFF_T)-1; + if(stat(file_name,&buf) != 0) + return (off_t)-1; return(buf.st_size); } @@ -120,9 +120,9 @@ void close_low_fds(BOOL stderr_too) if (i == 2 && !stderr_too) continue; - fd = sys_open("/dev/null",O_RDWR,0); + fd = open("/dev/null",O_RDWR,0); if (fd < 0) - fd = sys_open("/dev/null",O_WRONLY,0); + fd = open("/dev/null",O_WRONLY,0); if (fd < 0) { DEBUG(0,("Can't open /dev/null\n")); return; @@ -155,13 +155,13 @@ int set_blocking(int fd, BOOL set) #endif #endif - if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1) + if((val = fcntl(fd, F_GETFL, 0)) == -1) return -1; if(set) /* Turn blocking on - ie. clear nonblock flag */ val &= ~FLAG_TO_SET; else val |= FLAG_TO_SET; - return sys_fcntl_long( fd, F_SETFL, val); + return fcntl( fd, F_SETFL, val); #undef FLAG_TO_SET } @@ -198,7 +198,7 @@ void become_daemon(BOOL Fork) setsid(); #elif defined(TIOCNOTTY) { - int i = sys_open("/dev/tty", O_RDWR, 0); + int i = open("/dev/tty", O_RDWR, 0); if (i != -1) { ioctl(i, (int) TIOCNOTTY, (char *)0); close(i); @@ -509,9 +509,9 @@ BOOL process_exists(pid_t pid) is dealt with in posix.c ****************************************************************************/ -BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +BOOL fcntl_lock(int fd, int op, off_t offset, off_t count, int type) { - SMB_STRUCT_FLOCK lock; + struct flock lock; int ret; DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type)); @@ -522,13 +522,13 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) lock.l_len = count; lock.l_pid = 0; - ret = sys_fcntl_ptr(fd,op,&lock); + ret = fcntl(fd,op,&lock); if (ret == -1 && errno != 0) DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); /* a lock query */ - if (op == SMB_F_GETLK) { + if (op == F_GETLK) { if ((ret != -1) && (lock.l_type != F_UNLCK) && (lock.l_pid != 0) && diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index c4f794db0e..0093de9517 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -20,96 +20,6 @@ #include "includes.h" -static int gotalarm; - -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - -/*************************************************************** - Lock or unlock a fd for a known lock type. Abandon after waitsecs - seconds. -****************************************************************/ - -BOOL do_file_lock(int fd, int waitsecs, int type) -{ - SMB_STRUCT_FLOCK lock; - int ret; - void (*oldsig_handler)(int); - - gotalarm = 0; - oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - lock.l_pid = 0; - - alarm(waitsecs); - /* Note we must *NOT* use sys_fcntl here ! JRA */ - ret = fcntl(fd, SMB_F_SETLKW, &lock); - alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler); - - if (gotalarm) { - DEBUG(0, ("do_file_lock: failed to %s file.\n", - type == F_UNLCK ? "unlock" : "lock")); - return False; - } - - return (ret == 0); -} - - -/*************************************************************** - Lock an fd. Abandon after waitsecs seconds. -****************************************************************/ - -BOOL file_lock(int fd, int type, int secs, int *plock_depth) -{ - if (fd < 0) - return False; - - (*plock_depth)++; - - if ((*plock_depth) == 0) - { - if (!do_file_lock(fd, secs, type)) { - DEBUG(10,("file_lock: locking file failed, error = %s.\n", - strerror(errno))); - return False; - } - } - - return True; -} - -/*************************************************************** - Unlock an fd. Abandon after waitsecs seconds. -****************************************************************/ - -BOOL file_unlock(int fd, int *plock_depth) -{ - BOOL ret=True; - - if(*plock_depth == 1) - ret = do_file_lock(fd, 5, F_UNLCK); - - (*plock_depth)--; - - if(!ret) - DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", - strerror(errno))); - return ret; -} - - /************************************************************************* gets a line out of a file. line is of format "xxxx:xxxxxx:xxxxx:". @@ -280,10 +190,10 @@ load a file into memory from a fd. char *fd_load(int fd, size_t *size) { - SMB_STRUCT_STAT sbuf; + struct stat sbuf; char *p; - if (sys_fstat(fd, &sbuf) != 0) return NULL; + if (fstat(fd, &sbuf) != 0) return NULL; p = (char *)malloc(sbuf.st_size+1); if (!p) return NULL; diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 638c44f705..0cb23920f1 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -162,7 +162,7 @@ ssize_t read_udp_socket(int fd, char *buf, size_t len, struct sockaddr_in sock; socklen_t socklen = sizeof(sock); - ret = (ssize_t)sys_recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen); + ret = recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen); if (ret <= 0) { DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); return 0; diff --git a/source4/lib/xfile.c b/source4/lib/xfile.c index e01723904f..8572bd857a 100644 --- a/source4/lib/xfile.c +++ b/source4/lib/xfile.c @@ -109,7 +109,7 @@ XFILE *x_fopen(const char *fname, int flags, mode_t mode) ret->open_flags = flags; - ret->fd = sys_open(fname, flags, mode); + ret->fd = open(fname, flags, mode); if (ret->fd == -1) { SAFE_FREE(ret); return NULL; @@ -379,5 +379,5 @@ off_t x_tseek(XFILE *f, off_t offset, int whence) } f->flags &= ~X_FLAG_EOF; - return (off_t)sys_lseek(f->fd, offset, whence); + return lseek(f->fd, offset, whence); } -- cgit From 284349482f5293a9a23d0f72d7c2aab46b55843b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 22:48:25 +0000 Subject: r3443: the next stage in the include files re-organisation. I have created the include/system/ directory, which will contain the wrappers for the system includes for logical subsystems. So far I have created include/system/kerberos.h and include/system/network.h, which contain all the system includes for kerberos code and networking code. These are the included in subsystems that need kerberos or networking respectively. Note that this method avoids the mess of #ifdef HAVE_XXX_H in every C file, instead each C module includes the include/system/XXX.h file for the logical system support it needs, and the details are kept isolated in include/system/ This patch also creates a "struct ipv4_addr" which replaces "struct in_addr" in our code. That avoids every C file needing to import all the system networking headers. (This used to be commit 2e25c71853f8996f73755277e448e7d670810349) --- source4/lib/basic.m4 | 1 + source4/lib/basic.mk | 14 +- source4/lib/interface.c | 341 -------------------------------- source4/lib/interfaces.c | 407 --------------------------------------- source4/lib/netif/interface.c | 355 ++++++++++++++++++++++++++++++++++ source4/lib/netif/netif.c | 400 ++++++++++++++++++++++++++++++++++++++ source4/lib/netif/netif.h | 34 ++++ source4/lib/replace.c | 2 +- source4/lib/socket/access.c | 1 + source4/lib/socket/socket_ipv4.c | 13 +- source4/lib/socket/socket_ipv6.c | 1 + source4/lib/system.c | 22 +++ source4/lib/util.c | 15 +- source4/lib/util_sock.c | 21 +- source4/lib/util_strlist.c | 16 +- source4/lib/wins_srv.c | 30 +-- 16 files changed, 875 insertions(+), 798 deletions(-) delete mode 100644 source4/lib/interface.c delete mode 100644 source4/lib/interfaces.c create mode 100644 source4/lib/netif/interface.c create mode 100644 source4/lib/netif/netif.c create mode 100644 source4/lib/netif/netif.h (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index 6701ddaee5..1640ef2b9d 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -1,4 +1,5 @@ dnl # LIB BASIC subsystem SMB_SUBSYSTEM_MK(LIBREPLACE,lib/basic.mk) +SMB_SUBSYSTEM_MK(LIBNETIF,lib/basic.mk) SMB_SUBSYSTEM_MK(LIBBASIC,lib/basic.mk) diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 56fc19dca7..55e654ec74 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -9,6 +9,16 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBREPLACE ############################## +############################## +# Start SUBSYSTEM LIBNETIF +[SUBSYSTEM::LIBNETIF] +INIT_OBJ_FILES = \ + lib/netif/interface.o +ADD_OBJ_FILES = \ + lib/netif/netif.o +# End SUBSYSTEM LIBNETIF +############################## + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -17,8 +27,6 @@ ADD_OBJ_FILES = \ lib/debug.o \ lib/fault.o \ lib/getsmbpass.o \ - lib/interface.o \ - lib/interfaces.o \ lib/pidfile.o \ lib/signal.o \ lib/system.o \ @@ -57,6 +65,6 @@ ADD_OBJ_FILES = \ lib/server_mutex.o \ lib/idtree.o REQUIRED_SUBSYSTEMS = \ - LIBTDB CHARSET LIBREPLACE + LIBTDB CHARSET LIBREPLACE LIBNETIF # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/interface.c b/source4/lib/interface.c deleted file mode 100644 index 72568912af..0000000000 --- a/source4/lib/interface.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - Unix SMB/CIFS implementation. - multiple interface handling - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -static struct iface_struct *probed_ifaces; -static int total_probed; - -static struct in_addr allones_ip; -struct in_addr loopback_ip; - -/* used for network interfaces */ -struct interface { - struct interface *next, *prev; - struct in_addr ip; - struct in_addr bcast; - struct in_addr nmask; -}; - -static struct interface *local_interfaces; - -#define ALLONES ((uint32_t)0xFFFFFFFF) -#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES)) -#define MKNETADDR(_IP, _NM) (_IP & _NM) - -/**************************************************************************** -Try and find an interface that matches an ip. If we cannot, return NULL - **************************************************************************/ -static struct interface *iface_find(struct in_addr ip, BOOL CheckMask) -{ - struct interface *i; - if (is_zero_ip(ip)) return local_interfaces; - - for (i=local_interfaces;i;i=i->next) - if (CheckMask) { - if (same_net(i->ip,ip,i->nmask)) return i; - } else if ((i->ip).s_addr == ip.s_addr) return i; - - return NULL; -} - - -/**************************************************************************** -add an interface to the linked list of interfaces -****************************************************************************/ -static void add_interface(struct in_addr ip, struct in_addr nmask) -{ - struct interface *iface; - if (iface_find(ip, False)) { - DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); - return; - } - - if (ip_equal(nmask, allones_ip)) { - DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); - return; - } - - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - ZERO_STRUCTPN(iface); - - iface->ip = ip; - iface->nmask = nmask; - iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); - - DLIST_ADD(local_interfaces, iface); - - DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); -} - - - -/**************************************************************************** -interpret a single element from a interfaces= config line - -This handles the following different forms: - -1) wildcard interface name -2) DNS name -3) IP/masklen -4) ip/mask -5) bcast/mask -****************************************************************************/ -static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) -{ - struct in_addr ip, nmask; - char *p; - int i, added=0; - - zero_ip(&ip); - zero_ip(&nmask); - - /* first check if it is an interface name */ - for (i=0;i 2) { - nmask = interpret_addr2(p); - } else { - nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); - } - - /* maybe the first component was a broadcast address */ - if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || - ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { - for (i=0;i 0) { - probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); - } - - /* if we don't have a interfaces line then use all broadcast capable - interfaces except loopback */ - if (!ptr || !*ptr || !**ptr) { - if (total_probed <= 0) { - DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); - exit(1); - } - for (i=0;i 0 )&& (n != total_probed || - memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) { - return True; - } - - return False; -} - - -/**************************************************************************** - check if an IP is one of mine - **************************************************************************/ -BOOL ismyip(struct in_addr ip) -{ - struct interface *i; - for (i=local_interfaces;i;i=i->next) - if (ip_equal(i->ip,ip)) return True; - return False; -} - -/**************************************************************************** - check if a packet is from a local (known) net - **************************************************************************/ -BOOL is_local_net(struct in_addr from) -{ - struct interface *i; - for (i=local_interfaces;i;i=i->next) { - if((from.s_addr & i->nmask.s_addr) == - (i->ip.s_addr & i->nmask.s_addr)) - return True; - } - return False; -} - -/**************************************************************************** - how many interfaces do we have - **************************************************************************/ -int iface_count(void) -{ - int ret = 0; - struct interface *i; - - for (i=local_interfaces;i;i=i->next) - ret++; - return ret; -} - -/**************************************************************************** - return IP of the Nth interface - **************************************************************************/ -struct in_addr *iface_n_ip(int n) -{ - struct interface *i; - - for (i=local_interfaces;i && n;i=i->next) - n--; - - if (i) return &i->ip; - return NULL; -} - -/**************************************************************************** - return bcast of the Nth interface - **************************************************************************/ -struct in_addr *iface_n_bcast(int n) -{ - struct interface *i; - - for (i=local_interfaces;i && n;i=i->next) - n--; - - if (i) return &i->bcast; - return NULL; -} - - -/* these 3 functions return the ip/bcast/nmask for the interface - most appropriate for the given ip address. If they can't find - an appropriate interface they return the requested field of the - first known interface. */ - -struct in_addr *iface_ip(struct in_addr ip) -{ - struct interface *i = iface_find(ip, True); - return(i ? &i->ip : &local_interfaces->ip); -} - -/* - return True if a IP is directly reachable on one of our interfaces -*/ -BOOL iface_local(struct in_addr ip) -{ - return iface_find(ip, True) ? True : False; -} diff --git a/source4/lib/interfaces.c b/source4/lib/interfaces.c deleted file mode 100644 index 89ed144eec..0000000000 --- a/source4/lib/interfaces.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - Unix SMB/CIFS implementation. - return a list of network interfaces - Copyright (C) Andrew Tridgell 1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -/* working out the interfaces for a OS is an incredibly non-portable - thing. We have several possible implementations below, and autoconf - tries each of them to see what works - - Note that this file does _not_ include includes.h. That is so this code - can be called directly from the autoconf tests. That also means - this code cannot use any of the normal Samba debug stuff or defines. - This is standalone code. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef AUTOCONF_TEST -struct iface_struct { - char name[16]; - struct in_addr ip; - struct in_addr netmask; -}; -#else -#include "config.h" -#include "interfaces.h" -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifndef SIOCGIFCONF -#ifdef HAVE_SYS_SOCKIO_H -#include -#endif -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef HAVE_STRING_H -#include -#endif - -#ifdef HAVE_STRINGS_H -#include -#endif - -#ifdef __COMPAR_FN_T -#define QSORT_CAST (__compar_fn_t) -#endif - -#ifndef QSORT_CAST -#define QSORT_CAST (int (*)(const void *, const void *)) -#endif - -#if HAVE_IFACE_IFCONF - -/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 - V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. - - It probably also works on any BSD style system. */ - -/**************************************************************************** - get the netmask address for a local interface -****************************************************************************/ -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - struct ifconf ifc; - char buff[8192]; - int fd, i, n; - struct ifreq *ifr=NULL; - int total = 0; - struct in_addr ipaddr; - struct in_addr nmask; - char *iname; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - - if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { - close(fd); - return -1; - } - - ifr = ifc.ifc_req; - - n = ifc.ifc_len / sizeof(struct ifreq); - - /* Loop through interfaces, looking for given IP address */ - for (i=n-1;i>=0 && total < max_interfaces;i--) { - if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) { - continue; - } - - iname = ifr[i].ifr_name; - ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr; - - if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) { - continue; - } - - if (!(ifr[i].ifr_flags & IFF_UP)) { - continue; - } - - if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) { - continue; - } - - nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr; - - strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); - ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; - ifaces[total].ip = ipaddr; - ifaces[total].netmask = nmask; - total++; - } - - close(fd); - - return total; -} - -#elif HAVE_IFACE_IFREQ - -#ifndef I_STR -#include -#endif - -/**************************************************************************** -this should cover most of the streams based systems -Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code -****************************************************************************/ -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - struct ifreq ifreq; - struct strioctl strioctl; - char buff[8192]; - int fd, i, n; - struct ifreq *ifr=NULL; - int total = 0; - struct in_addr ipaddr; - struct in_addr nmask; - char *iname; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - strioctl.ic_cmd = SIOCGIFCONF; - strioctl.ic_dp = buff; - strioctl.ic_len = sizeof(buff); - if (ioctl(fd, I_STR, &strioctl) < 0) { - close(fd); - return -1; - } - - /* we can ignore the possible sizeof(int) here as the resulting - number of interface structures won't change */ - n = strioctl.ic_len / sizeof(struct ifreq); - - /* we will assume that the kernel returns the length as an int - at the start of the buffer if the offered size is a - multiple of the structure size plus an int */ - if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { - ifr = (struct ifreq *)(buff + sizeof(int)); - } else { - ifr = (struct ifreq *)buff; - } - - /* Loop through interfaces */ - - for (i = 0; isin_addr; - - strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); - ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; - ifaces[total].ip = ipaddr; - ifaces[total].netmask = nmask; - - total++; - } - - close(fd); - - return total; -} - -#elif HAVE_IFACE_AIX - -/**************************************************************************** -this one is for AIX (tested on 4.2) -****************************************************************************/ -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - char buff[8192]; - int fd, i; - struct ifconf ifc; - struct ifreq *ifr=NULL; - struct in_addr ipaddr; - struct in_addr nmask; - char *iname; - int total = 0; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - return -1; - } - - - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - - if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { - close(fd); - return -1; - } - - ifr = ifc.ifc_req; - - /* Loop through interfaces */ - i = ifc.ifc_len; - - while (i > 0 && total < max_interfaces) { - uint_t inc; - - inc = ifr->ifr_addr.sa_len; - - if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { - goto next; - } - - ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; - iname = ifr->ifr_name; - - if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { - goto next; - } - - if (!(ifr->ifr_flags & IFF_UP)) { - goto next; - } - - if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { - goto next; - } - - nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; - - strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); - ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; - ifaces[total].ip = ipaddr; - ifaces[total].netmask = nmask; - - total++; - - next: - /* - * Patch from Archie Cobbs (archie@whistle.com). The - * addresses in the SIOCGIFCONF interface list have a - * minimum size. Usually this doesn't matter, but if - * your machine has tunnel interfaces, etc. that have - * a zero length "link address", this does matter. */ - - if (inc < sizeof(ifr->ifr_addr)) - inc = sizeof(ifr->ifr_addr); - inc += IFNAMSIZ; - - ifr = (struct ifreq*) (((char*) ifr) + inc); - i -= inc; - } - - - close(fd); - return total; -} - -#else /* a dummy version */ -static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - return -1; -} -#endif - - -static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) -{ - int r; - r = strcmp(i1->name, i2->name); - if (r) return r; - r = ntohl(i1->ip.s_addr) - ntohl(i2->ip.s_addr); - if (r) return r; - r = ntohl(i1->netmask.s_addr) - ntohl(i2->netmask.s_addr); - return r; -} - -/* this wrapper is used to remove duplicates from the interface list generated - above */ -int get_interfaces(struct iface_struct *ifaces, int max_interfaces) -{ - int total, i, j; - - total = _get_interfaces(ifaces, max_interfaces); - if (total <= 0) return total; - - /* now we need to remove duplicates */ - qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CAST iface_comp); - - for (i=1;inext) + if (CheckMask) { + if (same_net(i->ip,tov4(ip),i->nmask)) return i; + } else if ((i->ip).s_addr == ip.s_addr) return i; + + return NULL; +} + + +/**************************************************************************** +add an interface to the linked list of interfaces +****************************************************************************/ +static void add_interface(struct in_addr ip, struct in_addr nmask) +{ + struct interface *iface; + if (iface_find(ip, False)) { + DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); + return; + } + + if (ip_equal(nmask, allones_ip)) { + DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); + return; + } + + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + ZERO_STRUCTPN(iface); + + iface->ip = tov4(ip); + iface->nmask = tov4(nmask); + iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); + + DLIST_ADD(local_interfaces, iface); + + DEBUG(2,("added interface ip=%s ",sys_inet_ntoa(iface->ip))); + DEBUG(2,("bcast=%s ",sys_inet_ntoa(iface->bcast))); + DEBUG(2,("nmask=%s\n",sys_inet_ntoa(iface->nmask))); +} + + + +/**************************************************************************** +interpret a single element from a interfaces= config line + +This handles the following different forms: + +1) wildcard interface name +2) DNS name +3) IP/masklen +4) ip/mask +5) bcast/mask +****************************************************************************/ +static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) +{ + struct in_addr ip, nmask; + char *p; + int i, added=0; + + ip.s_addr = 0; + nmask.s_addr = 0; + + /* first check if it is an interface name */ + for (i=0;i 2) { + nmask.s_addr = interpret_addr2(p).s_addr; + } else { + nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); + } + + /* maybe the first component was a broadcast address */ + if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || + ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { + for (i=0;i 0) { + probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); + } + + /* if we don't have a interfaces line then use all broadcast capable + interfaces except loopback */ + if (!ptr || !*ptr || !**ptr) { + if (total_probed <= 0) { + DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); + exit(1); + } + for (i=0;i 0 )&& (n != total_probed || + memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) { + return True; + } + + return False; +} + + +/**************************************************************************** + check if an IP is one of mine + **************************************************************************/ +BOOL ismyip(struct ipv4_addr ip) +{ + struct interface *i; + for (i=local_interfaces;i;i=i->next) + if (ip_equal(i->ip,ip)) return True; + return False; +} + +/**************************************************************************** + check if a packet is from a local (known) net + **************************************************************************/ +BOOL is_local_net(struct ipv4_addr from) +{ + struct interface *i; + for (i=local_interfaces;i;i=i->next) { + if((from.s_addr & i->nmask.s_addr) == + (i->ip.s_addr & i->nmask.s_addr)) + return True; + } + return False; +} + +/**************************************************************************** + how many interfaces do we have + **************************************************************************/ +int iface_count(void) +{ + int ret = 0; + struct interface *i; + + for (i=local_interfaces;i;i=i->next) + ret++; + return ret; +} + +/**************************************************************************** + return IP of the Nth interface + **************************************************************************/ +struct ipv4_addr *iface_n_ip(int n) +{ + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; + + if (i) return &i->ip; + return NULL; +} + +/**************************************************************************** + return bcast of the Nth interface + **************************************************************************/ +struct ipv4_addr *iface_n_bcast(int n) +{ + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; + + if (i) return &i->bcast; + return NULL; +} + + +/* these 3 functions return the ip/bcast/nmask for the interface + most appropriate for the given ip address. If they can't find + an appropriate interface they return the requested field of the + first known interface. */ + +struct ipv4_addr *iface_ip(struct ipv4_addr ip) +{ + struct in_addr in; + struct interface *i; + in.s_addr = ip.s_addr; + i = iface_find(in, True); + return(i ? &i->ip : &local_interfaces->ip); +} + +/* + return True if a IP is directly reachable on one of our interfaces +*/ +BOOL iface_local(struct ipv4_addr ip) +{ + struct in_addr in; + in.s_addr = ip.s_addr; + return iface_find(in, True) ? True : False; +} diff --git a/source4/lib/netif/netif.c b/source4/lib/netif/netif.c new file mode 100644 index 0000000000..729aeedbe3 --- /dev/null +++ b/source4/lib/netif/netif.c @@ -0,0 +1,400 @@ +/* + Unix SMB/CIFS implementation. + return a list of network interfaces + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* working out the interfaces for a OS is an incredibly non-portable + thing. We have several possible implementations below, and autoconf + tries each of them to see what works + + Note that this file does _not_ include includes.h. That is so this code + can be called directly from the autoconf tests. That also means + this code cannot use any of the normal Samba debug stuff or defines. + This is standalone code. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef AUTOCONF_TEST +#include "lib/netif/netif.h" +#include "config.h" +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#if HAVE_IFACE_IFCONF + +/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 + V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. + + It probably also works on any BSD style system. */ + +/**************************************************************************** + get the netmask address for a local interface +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + struct ifconf ifc; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + int total = 0; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + n = ifc.ifc_len / sizeof(struct ifreq); + + /* Loop through interfaces, looking for given IP address */ + for (i=n-1;i>=0 && total < max_interfaces;i--) { + if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) { + continue; + } + + iname = ifr[i].ifr_name; + ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr; + + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) { + continue; + } + + if (!(ifr[i].ifr_flags & IFF_UP)) { + continue; + } + + if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) { + continue; + } + + nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + total++; + } + + close(fd); + + return total; +} + +#elif HAVE_IFACE_IFREQ + +#ifndef I_STR +#include +#endif + +/**************************************************************************** +this should cover most of the streams based systems +Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + struct ifreq ifreq; + struct strioctl strioctl; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + int total = 0; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = buff; + strioctl.ic_len = sizeof(buff); + if (ioctl(fd, I_STR, &strioctl) < 0) { + close(fd); + return -1; + } + + /* we can ignore the possible sizeof(int) here as the resulting + number of interface structures won't change */ + n = strioctl.ic_len / sizeof(struct ifreq); + + /* we will assume that the kernel returns the length as an int + at the start of the buffer if the offered size is a + multiple of the structure size plus an int */ + if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { + ifr = (struct ifreq *)(buff + sizeof(int)); + } else { + ifr = (struct ifreq *)buff; + } + + /* Loop through interfaces */ + + for (i = 0; isin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + + total++; + } + + close(fd); + + return total; +} + +#elif HAVE_IFACE_AIX + +/**************************************************************************** +this one is for AIX (tested on 4.2) +****************************************************************************/ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + char buff[8192]; + int fd, i; + struct ifconf ifc; + struct ifreq *ifr=NULL; + struct in_addr ipaddr; + struct in_addr nmask; + char *iname; + int total = 0; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + /* Loop through interfaces */ + i = ifc.ifc_len; + + while (i > 0 && total < max_interfaces) { + uint_t inc; + + inc = ifr->ifr_addr.sa_len; + + if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { + goto next; + } + + ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; + iname = ifr->ifr_name; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { + goto next; + } + + if (!(ifr->ifr_flags & IFF_UP)) { + goto next; + } + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + goto next; + } + + nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; + + strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1); + ifaces[total].name[sizeof(ifaces[total].name)-1] = 0; + ifaces[total].ip = ipaddr; + ifaces[total].netmask = nmask; + + total++; + + next: + /* + * Patch from Archie Cobbs (archie@whistle.com). The + * addresses in the SIOCGIFCONF interface list have a + * minimum size. Usually this doesn't matter, but if + * your machine has tunnel interfaces, etc. that have + * a zero length "link address", this does matter. */ + + if (inc < sizeof(ifr->ifr_addr)) + inc = sizeof(ifr->ifr_addr); + inc += IFNAMSIZ; + + ifr = (struct ifreq*) (((char*) ifr) + inc); + i -= inc; + } + + + close(fd); + return total; +} + +#else /* a dummy version */ +static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + return -1; +} +#endif + + +static int iface_comp(struct iface_struct *i1, struct iface_struct *i2) +{ + int r; + r = strcmp(i1->name, i2->name); + if (r) return r; + r = ntohl(i1->ip.s_addr) - ntohl(i2->ip.s_addr); + if (r) return r; + r = ntohl(i1->netmask.s_addr) - ntohl(i2->netmask.s_addr); + return r; +} + +/* this wrapper is used to remove duplicates from the interface list generated + above */ +int get_interfaces(struct iface_struct *ifaces, int max_interfaces) +{ + int total, i, j; + + total = _get_interfaces(ifaces, max_interfaces); + if (total <= 0) return total; + + /* now we need to remove duplicates */ + qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CAST iface_comp); + + for (i=1;i +#include +#include + +struct iface_struct { + char name[16]; + struct in_addr ip; + struct in_addr netmask; +}; + +#define MAX_INTERFACES 128 + diff --git a/source4/lib/replace.c b/source4/lib/replace.c index c23c65c8c8..28c60130f8 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -326,7 +326,7 @@ duplicate a string #ifndef WITH_PTHREADS /* REWRITE: not thread safe */ #ifdef REPLACE_INET_NTOA -char *rep_inet_ntoa(struct in_addr ip) +char *rep_inet_ntoa(struct ipv4_addr ip) { uint8_t *p = (uint8_t *)&ip.s_addr; static char buf[18]; diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c index f33f8d56b1..f5093177dd 100644 --- a/source4/lib/socket/access.c +++ b/source4/lib/socket/access.c @@ -32,6 +32,7 @@ */ #include "includes.h" +#include "system/network.h" #define FAIL (-1) #define ALLONES ((uint32_t)0xFFFFFFFF) diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index f9318a29bb..9777705419 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/network.h" static NTSTATUS ipv4_tcp_init(struct socket_context *sock) { @@ -41,8 +42,8 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, uint32_t flags) { struct sockaddr_in srv_addr; - struct in_addr my_ip; - struct in_addr srv_ip; + struct ipv4_addr my_ip; + struct ipv4_addr srv_ip; int ret; my_ip = interpret_addr2(my_address); @@ -53,7 +54,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, #ifdef HAVE_SOCK_SIN_LEN my_addr.sin_len = sizeof(my_addr); #endif - my_addr.sin_addr = my_ip; + my_addr.sin_addr.s_addr = my_ip.s_addr; my_addr.sin_port = htons(my_port); my_addr.sin_family = PF_INET; @@ -69,7 +70,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, #ifdef HAVE_SOCK_SIN_LEN srv_addr.sin_len = sizeof(srv_addr); #endif - srv_addr.sin_addr = srv_ip; + srv_addr.sin_addr.s_addr= srv_ip.s_addr; srv_addr.sin_port = htons(srv_port); srv_addr.sin_family = PF_INET; @@ -95,7 +96,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, int queue_size, uint32_t flags) { struct sockaddr_in my_addr; - struct in_addr ip_addr; + struct ipv4_addr ip_addr; int ret; ip_addr = interpret_addr2(my_address); @@ -104,7 +105,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, #ifdef HAVE_SOCK_SIN_LEN my_addr.sin_len = sizeof(my_addr); #endif - my_addr.sin_addr = ip_addr; + my_addr.sin_addr.s_addr = ip_addr.s_addr; my_addr.sin_port = htons(port); my_addr.sin_family = PF_INET; diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 268212dcca..75e6fcab5c 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/network.h" static struct in6_addr interpret_addr6(const char *name) { diff --git a/source4/lib/system.c b/source4/lib/system.c index 1407e7474e..2baa412622 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/network.h" /* The idea is that this file will eventually have wrappers around all @@ -533,3 +534,24 @@ int sys_dup2(int oldfd, int newfd) #endif } + +const char *sys_inet_ntoa(struct ipv4_addr in) +{ + struct in_addr in2; + in2.s_addr = in.s_addr; + return inet_ntoa(in2); +} + +uint32_t sys_inet_addr(const char *s) +{ + return inet_addr(s); +} + +struct ipv4_addr sys_inet_makeaddr(int net, int host) +{ + struct in_addr in; + struct ipv4_addr in2; + in = inet_makeaddr(net, host); + in2.s_addr = in.s_addr; + return in2; +} diff --git a/source4/lib/util.c b/source4/lib/util.c index 07dc182580..7b6396fa93 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -23,6 +23,7 @@ */ #include "includes.h" +#include "system/network.h" /**************************************************************************n Find a suitable temporary directory. The result should be copied immediately @@ -421,7 +422,7 @@ uint32_t interpret_addr(const char *str) /* if it's in the form of an IP address then get the lib to interpret it */ if (is_ipaddress(str)) { - res = inet_addr(str); + res = sys_inet_addr(str); } else { /* otherwise assume it's a network name of some sort and use sys_gethostbyname */ @@ -446,9 +447,9 @@ uint32_t interpret_addr(const char *str) /******************************************************************* A convenient addition to interpret_addr(). ******************************************************************/ -struct in_addr interpret_addr2(const char *str) +struct ipv4_addr interpret_addr2(const char *str) { - struct in_addr ret; + struct ipv4_addr ret; uint32_t a = interpret_addr(str); ret.s_addr = a; return ret; @@ -458,7 +459,7 @@ struct in_addr interpret_addr2(const char *str) Check if an IP is the 0.0.0.0. ******************************************************************/ -BOOL is_zero_ip(struct in_addr ip) +BOOL is_zero_ip(struct ipv4_addr ip) { uint32_t a; putip((char *)&a,(char *)&ip); @@ -469,9 +470,9 @@ BOOL is_zero_ip(struct in_addr ip) Set an IP to 0.0.0.0. ******************************************************************/ -void zero_ip(struct in_addr *ip) +void zero_ip(struct ipv4_addr *ip) { - *ip = inet_makeaddr(0,0); + *ip = sys_inet_makeaddr(0,0); return; } @@ -480,7 +481,7 @@ void zero_ip(struct in_addr *ip) Are two IPs on the same subnet? ********************************************************************/ -BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) +BOOL same_net(struct ipv4_addr ip1,struct ipv4_addr ip2,struct ipv4_addr mask) { uint32_t net1,net2,nmask; diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 0cb23920f1..dbd71b58b6 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/network.h" /**************************************************************************** @@ -156,7 +157,7 @@ void set_socket_options(int fd, const char *options) ****************************************************************************/ ssize_t read_udp_socket(int fd, char *buf, size_t len, - struct in_addr *from_addr, int *from_port) + struct ipv4_addr *from_addr, int *from_port) { ssize_t ret; struct sockaddr_in sock; @@ -169,7 +170,7 @@ ssize_t read_udp_socket(int fd, char *buf, size_t len, } if (from_addr) { - *from_addr = sock.sin_addr; + from_addr->s_addr = sock.sin_addr.s_addr; } if (from_port) { *from_port = ntohs(sock.sin_port); @@ -337,7 +338,7 @@ int open_socket_in( int type, int port, int dlevel, uint32_t socket_addr, BOOL r /**************************************************************************** create an outgoing socket. timeout is in milliseconds. **************************************************************************/ -int open_socket_out(int type, struct in_addr *addr, int port, int timeout) +int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout) { struct sockaddr_in sock_out; int res,ret; @@ -360,7 +361,7 @@ int open_socket_out(int type, struct in_addr *addr, int port, int timeout) /* set it non-blocking */ set_blocking(res,False); - DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); + DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port)); /* and connect it to the destination */ connect_again: @@ -375,7 +376,7 @@ connect_again: if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); + DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port)); close(res); return -1; } @@ -389,7 +390,7 @@ connect_again: if (ret < 0) { DEBUG(2,("error connecting to %s:%d (%s)\n", - inet_ntoa(*addr),port,strerror(errno))); + sys_inet_ntoa(*addr),port,strerror(errno))); close(res); return -1; } @@ -408,7 +409,7 @@ int open_udp_socket(const char *host, int port) int type = SOCK_DGRAM; struct sockaddr_in sock_out; int res; - struct in_addr addr; + struct ipv4_addr addr; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("open_udp_socket"); @@ -442,7 +443,7 @@ int open_udp_socket(const char *host, int port) matchname - determine if host name matches IP address. Used to confirm a hostname lookup to prevent spoof attacks ******************************************************************/ -static BOOL matchname(char *remotehost, struct in_addr addr) +static BOOL matchname(char *remotehost, struct ipv4_addr addr) { struct hostent *hp; int i; @@ -480,7 +481,7 @@ static BOOL matchname(char *remotehost, struct in_addr addr) */ DEBUG(0,("host name/address mismatch: %s != %s\n", - inet_ntoa(addr), hp->h_name)); + sys_inet_ntoa(addr), hp->h_name)); return False; } @@ -492,7 +493,7 @@ char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) { char *name_buf; struct hostent *hp; - struct in_addr addr; + struct ipv4_addr addr; char *p; /* reverse lookups can be *very* expensive, and in many diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 12fb0946e2..0b32955ac2 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -228,7 +228,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) * reallocated to new length **/ -char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) +char* ipstr_list_add(char** ipstr_list, const struct ipv4_addr *ip) { char* new_ipstr = NULL; @@ -237,10 +237,10 @@ char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) /* attempt to convert ip to a string and append colon separator to it */ if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,sys_inet_ntoa(*ip)); SAFE_FREE(*ipstr_list); } else { - asprintf(&new_ipstr, "%s", inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s", sys_inet_ntoa(*ip)); } *ipstr_list = new_ipstr; return *ipstr_list; @@ -256,7 +256,7 @@ char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) * @return pointer to allocated ip string **/ -char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count) +char* ipstr_list_make(char** ipstr_list, const struct ipv4_addr* ip_list, int ip_count) { int i; @@ -283,7 +283,7 @@ char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_c * @return number of succesfully parsed addresses **/ -int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) +int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list) { fstring token_str; int count; @@ -294,14 +294,14 @@ int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); count++) { - struct in_addr addr; + struct ipv4_addr addr; /* convert single token to ip address */ - if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE ) + if ( (addr.s_addr = sys_inet_addr(token_str)) == INADDR_NONE ) break; /* prepare place for another in_addr structure */ - *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr)); + *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct ipv4_addr)); if (!*ip_list) return -1; (*ip_list)[count] = addr; diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index eb7f280e6f..d8be9e61d6 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -68,12 +68,12 @@ #define WINS_SRV_FMT "WINS_SRV_DEAD/%s,%s" /* wins_ip,src_ip */ -static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip) +static char *wins_srv_keystr(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) { char *keystr; - if (asprintf(&keystr, WINS_SRV_FMT, inet_ntoa(wins_ip), - inet_ntoa(src_ip)) == -1) { + if (asprintf(&keystr, WINS_SRV_FMT, sys_inet_ntoa(wins_ip), + sys_inet_ntoa(src_ip)) == -1) { DEBUG(0, ("wins_srv_is_dead: malloc error\n")); return NULL; } @@ -85,7 +85,7 @@ static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip) see if an ip is on the dead list */ -BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip) +BOOL wins_srv_is_dead(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) { char *keystr = wins_srv_keystr(wins_ip, src_ip); BOOL result; @@ -95,7 +95,7 @@ BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip) result = gencache_get(keystr, NULL, NULL); SAFE_FREE(keystr); - DEBUG(4, ("wins_srv_is_dead: %s is %s\n", inet_ntoa(wins_ip), + DEBUG(4, ("wins_srv_is_dead: %s is %s\n", sys_inet_ntoa(wins_ip), result ? "dead" : "alive")); return result; @@ -105,7 +105,7 @@ BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip) /* mark a wins server as being alive (for the moment) */ -void wins_srv_alive(struct in_addr wins_ip, struct in_addr src_ip) +void wins_srv_alive(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) { char *keystr = wins_srv_keystr(wins_ip, src_ip); @@ -113,13 +113,13 @@ void wins_srv_alive(struct in_addr wins_ip, struct in_addr src_ip) SAFE_FREE(keystr); DEBUG(4, ("wins_srv_alive: marking wins server %s alive\n", - inet_ntoa(wins_ip))); + sys_inet_ntoa(wins_ip))); } /* mark a wins server as temporarily dead */ -void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip) +void wins_srv_died(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) { char *keystr; @@ -133,7 +133,7 @@ void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip) SAFE_FREE(keystr); DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n", - inet_ntoa(wins_ip), DEATH_TIME, inet_ntoa(src_ip))); + sys_inet_ntoa(wins_ip), DEATH_TIME, sys_inet_ntoa(src_ip))); } /* @@ -160,7 +160,7 @@ uint_t wins_srv_count(void) attached */ struct tagged_ip { fstring tag; - struct in_addr ip; + struct ipv4_addr ip; }; /* @@ -267,7 +267,7 @@ void wins_srv_tags_free(char **list) return the IP of the currently active wins server for the given tag, or the zero IP otherwise */ -struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) +struct ipv4_addr wins_srv_ip_tag(const char *tag, struct ipv4_addr src_ip) { const char **list; int i; @@ -276,13 +276,13 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) /* if we are a wins server then we always just talk to ourselves */ if (lp_wins_support()) { - extern struct in_addr loopback_ip; + extern struct ipv4_addr loopback_ip; return loopback_ip; } list = lp_wins_server_list(); if (!list || !list[0]) { - struct in_addr ip; + struct ipv4_addr ip; zero_ip(&ip); return ip; } @@ -297,11 +297,11 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) } if (!wins_srv_is_dead(t_ip.ip, src_ip)) { char *src_name; - src_name = talloc_strdup(mem_ctx, inet_ntoa(src_ip)); + src_name = talloc_strdup(mem_ctx, sys_inet_ntoa(src_ip)); DEBUG(6,("Current wins server for tag '%s' with source %s is %s\n", tag, src_name, - inet_ntoa(t_ip.ip))); + sys_inet_ntoa(t_ip.ip))); goto exit; } } -- cgit From f20f1f994ac375ab96cc8a38075b99aa20041b3f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Nov 2004 23:37:12 +0000 Subject: r3445: made the gtk tooks use minimal includes. This approximately halves the total include lines in compiling C files in Samba (the .gch file is now 5M instead of 12M) This also gets rid of the silly gtk compile warning for non-gtk code (This used to be commit 8ebd20cf551c8c1fad98ec723d91873fa202b85a) --- source4/lib/replace.c | 10 ++++++++++ source4/lib/signal.c | 2 +- source4/lib/system.c | 2 ++ source4/lib/tdb/tools/tdbtorture.c | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 28c60130f8..c2180a168f 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/wait.h" void replace_dummy(void); void replace_dummy(void) {} @@ -546,3 +547,12 @@ int get_time_zone(time_t t) return i; } #endif + +int sys_waitpid(pid_t pid,int *status,int options) +{ +#ifdef HAVE_WAITPID + return waitpid(pid,status,options); +#else /* USE_WAITPID */ + return wait4(pid, status, options, NULL); +#endif /* USE_WAITPID */ +} diff --git a/source4/lib/signal.c b/source4/lib/signal.c index 00fc214639..bff4b91c1a 100644 --- a/source4/lib/signal.c +++ b/source4/lib/signal.c @@ -27,7 +27,7 @@ static void sig_cld(int signum) { - while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ; /* diff --git a/source4/lib/system.c b/source4/lib/system.c index 2baa412622..906219bd91 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/network.h" +#include "system/wait.h" /* The idea is that this file will eventually have wrappers around all @@ -555,3 +556,4 @@ struct ipv4_addr sys_inet_makeaddr(int net, int host) in2.s_addr = in.s_addr; return in2; } + diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 005a2713af..95eb71281c 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -217,7 +217,7 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, if (getpid() == pids[0]) { for (i=0;i Date: Mon, 1 Nov 2004 23:45:40 +0000 Subject: r3446: created include/system/iconv.h and include/system/shmem.h (This used to be commit 70055fb1f499cd40e996e56c7ba9ef8d2267b421) --- source4/lib/iconv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 3cca734d7b..98905c4b84 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/iconv.h" /** -- cgit From ead3508ac81ff3ed2a48753f3b5e23537ba6ec73 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 00:24:21 +0000 Subject: r3447: more include/system/XXX.h include files (This used to be commit 264ce9181089922547e8f6f67116f2d7277a5105) --- source4/lib/events.c | 2 ++ source4/lib/fsusage.c | 1 + source4/lib/gencache.c | 1 + source4/lib/messaging/messaging.c | 1 + source4/lib/module.c | 1 + source4/lib/registry/reg_backend_dir/reg_backend_dir.c | 1 + source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 1 + source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 1 + source4/lib/registry/tools/regshell.c | 1 + source4/lib/replace.c | 1 + source4/lib/tdb/common/tdb.c | 2 ++ source4/lib/tdb/tools/tdbtorture.c | 1 + source4/lib/time.c | 1 + source4/lib/util_file.c | 1 + source4/lib/wins_srv.c | 1 + 15 files changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index dac23ec6bc..276b3d08e9 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -65,6 +65,8 @@ */ #include "includes.h" +#include "system/time.h" +#include "system/select.h" /* create a event_context structure. This must be the first events diff --git a/source4/lib/fsusage.c b/source4/lib/fsusage.c index bff6fdda03..f817672544 100644 --- a/source4/lib/fsusage.c +++ b/source4/lib/fsusage.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/filesys.h" /* Return the number of TOSIZE-byte blocks used by diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index a176dc5ae8..f32db598f8 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "system/time.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_TDB diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 125089ac62..a2316919cb 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/time.h" /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 diff --git a/source4/lib/module.c b/source4/lib/module.c index 67fb830e6f..58764683d5 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/dir.h" #ifdef HAVE_DLOPEN diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 95d4c47af0..2273a86771 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/dir.h" static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) { diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index 805f95fca1..a8d1752070 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -304,6 +304,7 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, *************************************************************************/ #include "includes.h" +#include "system/shmem.h" #define REG_KEY_LIST_SIZE 10 #define FLAG_HAS_NAME 0x01 diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index c285dac7c9..448af66eec 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" +#include "system/shmem.h" /** * The registry starts with a header that contains pointers to diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index db7af9d5b6..8449446c86 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/time.h" /* * ck/cd - change key diff --git a/source4/lib/replace.c b/source4/lib/replace.c index c2180a168f..60faa473b6 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -20,6 +20,7 @@ #include "includes.h" #include "system/wait.h" +#include "system/time.h" void replace_dummy(void); void replace_dummy(void) {} diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 67d9f9903d..d41809c3d8 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -66,6 +66,8 @@ #include "spinlock.h" #else #include "includes.h" +#include "system/time.h" +#include "system/shmem.h" #endif #define TDB_MAGIC_FOOD "TDB file\n" diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 95eb71281c..6471aec3ad 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -21,6 +21,7 @@ #else #include "includes.h" +#include "system/time.h" #endif diff --git a/source4/lib/time.c b/source4/lib/time.c index 5ea9b46844..cfceebf9cb 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/time.h" #ifndef TIME_T_MIN #define TIME_T_MIN 0 diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 0093de9517..1dbaf1147e 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/shmem.h" /************************************************************************* gets a line out of a file. diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index d8be9e61d6..c9a5549cdc 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/time.h" /* This is pretty much a complete rewrite of the earlier code. The main -- cgit From 26c6b4c70bd85d8030a96651f2a255a4d48fcda1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 01:42:45 +0000 Subject: r3449: more include file reduction the ldb part isn't ideal, I will have to think of a better solution (This used to be commit 6b1f86aea8427a8e957b1aeb0ec2f507297f07cb) --- source4/lib/genrand.c | 1 + source4/lib/ldb/common/ldb_ldif.c | 1 + source4/lib/ldb/common/ldb_parse.c | 1 + source4/lib/ldb/common/ldb_utf8.c | 1 + source4/lib/ldb/include/includes.h | 8 ++++++++ source4/lib/socket/access.c | 1 + source4/lib/tdb/tools/tdbdump.c | 1 + source4/lib/util.c | 1 + source4/lib/util_str.c | 1 + source4/lib/util_unistr.c | 1 + 10 files changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 11771b32c9..7289719791 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/iconv.h" static unsigned char hash[258]; static uint32 counter; diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index c693d211a9..01706304d9 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -37,6 +37,7 @@ */ #include "includes.h" +#include /* diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index b037284a24..feec8fc0f2 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -43,6 +43,7 @@ #include "includes.h" #include "ldb/include/ldb_parse.h" +#include /* diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 1e467d23af..e92d318bae 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include /* TODO: diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 1d3ac2a50e..44ff672266 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -28,3 +28,11 @@ #include "tdb.h" #include "proto.h" +#ifdef HAVE_INTPTR_T +#define discard_const(ptr) ((void *)((intptr_t)(ptr))) +#else +#define discard_const(ptr) ((void *)(ptr)) +#endif +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) + + diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c index f5093177dd..c90bf203dd 100644 --- a/source4/lib/socket/access.c +++ b/source4/lib/socket/access.c @@ -33,6 +33,7 @@ #include "includes.h" #include "system/network.h" +#include "system/iconv.h" #define FAIL (-1) #define ALLONES ((uint32_t)0xFFFFFFFF) diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 0e179f8c3e..822f65e594 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -37,6 +37,7 @@ #else #include "includes.h" +#include "system/iconv.h" #endif diff --git a/source4/lib/util.c b/source4/lib/util.c index 7b6396fa93..2ce34f58d9 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -24,6 +24,7 @@ #include "includes.h" #include "system/network.h" +#include "system/iconv.h" /**************************************************************************n Find a suitable temporary directory. The result should be copied immediately diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 95c0b84d98..9fd6dd5356 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "system/iconv.h" /** * @file diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 7d10b92c43..bd4aea7c41 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/iconv.h" /* these 2 tables define the unicode case handling. They are loaded at startup either via mmap() or read() from the lib directory */ -- cgit From 452ddd94ba22bebe0fda5ee6a7ddceae2057fe40 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 02:01:04 +0000 Subject: r3450: portability fixes - fix rep_inet_ntoa() for IRIX - lib/signal.c needs system/wait.h - some systems define a macro "accept", which breaks the lib/socket/ structures. use fn_ as a prefix for the structure elements to avoid the problem (This used to be commit ced1a0fcdc8d8e47755ce4391c19f8b12862eb60) --- source4/lib/signal.c | 1 + source4/lib/socket/socket.c | 58 ++++++++++++++++++++-------------------- source4/lib/socket/socket.h | 28 +++++++++---------- source4/lib/socket/socket_ipv4.c | 40 +++++++++++++-------------- source4/lib/socket/socket_ipv6.c | 40 +++++++++++++-------------- source4/lib/socket/socket_unix.c | 40 +++++++++++++-------------- 6 files changed, 104 insertions(+), 103 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/signal.c b/source4/lib/signal.c index bff4b91c1a..66d3e1f76e 100644 --- a/source4/lib/signal.c +++ b/source4/lib/signal.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/wait.h" /**************************************************************************** Catch child exits and reap the child zombie status. diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 892695f6eb..c2865cd9f0 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -26,8 +26,8 @@ static int socket_destructor(void *ptr) { struct socket_context *sock = ptr; - if (sock->ops->close) { - sock->ops->close(sock); + if (sock->ops->fn_close) { + sock->ops->fn_close(sock); } return 0; } @@ -54,7 +54,7 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co return NT_STATUS_INVALID_PARAMETER; } - status = (*new_sock)->ops->init((*new_sock)); + status = (*new_sock)->ops->fn_init((*new_sock)); if (!NT_STATUS_IS_OK(status)) { talloc_free(*new_sock); return status; @@ -92,11 +92,11 @@ NTSTATUS socket_connect(struct socket_context *sock, return NT_STATUS_INVALID_PARAMETER; } - if (!sock->ops->connect) { + if (!sock->ops->fn_connect) { return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->connect(sock, my_address, my_port, server_address, server_port, flags); + return sock->ops->fn_connect(sock, my_address, my_port, server_address, server_port, flags); } NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) @@ -109,11 +109,11 @@ NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int return NT_STATUS_INVALID_PARAMETER; } - if (!sock->ops->listen) { + if (!sock->ops->fn_listen) { return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->listen(sock, my_address, port, queue_size, flags); + return sock->ops->fn_listen(sock, my_address, port, queue_size, flags); } NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock) @@ -128,11 +128,11 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ return NT_STATUS_INVALID_PARAMETER; } - if (!sock->ops->accept) { + if (!sock->ops->fn_accept) { return NT_STATUS_NOT_IMPLEMENTED; } - status = sock->ops->accept(sock, new_sock); + status = sock->ops->fn_accept(sock, new_sock); if (NT_STATUS_IS_OK(status)) { talloc_set_destructor(*new_sock, socket_destructor); @@ -153,7 +153,7 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, return NT_STATUS_INVALID_PARAMETER; } - if (!sock->ops->recv) { + if (!sock->ops->fn_recv) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -162,10 +162,10 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, *nread = 0; return STATUS_MORE_ENTRIES; } - return sock->ops->recv(sock, buf, 1+(random() % wantlen), nread, flags); + return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread, flags); } - return sock->ops->recv(sock, buf, wantlen, nread, flags); + return sock->ops->fn_recv(sock, buf, wantlen, nread, flags); } NTSTATUS socket_send(struct socket_context *sock, @@ -180,7 +180,7 @@ NTSTATUS socket_send(struct socket_context *sock, return NT_STATUS_INVALID_PARAMETER; } - if (!sock->ops->send) { + if (!sock->ops->fn_send) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -191,73 +191,73 @@ NTSTATUS socket_send(struct socket_context *sock, return STATUS_MORE_ENTRIES; } blob2.length = 1+(random() % blob2.length); - return sock->ops->send(sock, &blob2, sendlen, flags); + return sock->ops->fn_send(sock, &blob2, sendlen, flags); } - return sock->ops->send(sock, blob, sendlen, flags); + return sock->ops->fn_send(sock, blob, sendlen, flags); } NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) { - if (!sock->ops->set_option) { + if (!sock->ops->fn_set_option) { return NT_STATUS_NOT_IMPLEMENTED; } - return sock->ops->set_option(sock, option, val); + return sock->ops->fn_set_option(sock, option, val); } char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) { - if (!sock->ops->get_peer_name) { + if (!sock->ops->fn_get_peer_name) { return NULL; } - return sock->ops->get_peer_name(sock, mem_ctx); + return sock->ops->fn_get_peer_name(sock, mem_ctx); } char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { - if (!sock->ops->get_peer_addr) { + if (!sock->ops->fn_get_peer_addr) { return NULL; } - return sock->ops->get_peer_addr(sock, mem_ctx); + return sock->ops->fn_get_peer_addr(sock, mem_ctx); } int socket_get_peer_port(struct socket_context *sock) { - if (!sock->ops->get_peer_port) { + if (!sock->ops->fn_get_peer_port) { return -1; } - return sock->ops->get_peer_port(sock); + return sock->ops->fn_get_peer_port(sock); } char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { - if (!sock->ops->get_my_addr) { + if (!sock->ops->fn_get_my_addr) { return NULL; } - return sock->ops->get_my_addr(sock, mem_ctx); + return sock->ops->fn_get_my_addr(sock, mem_ctx); } int socket_get_my_port(struct socket_context *sock) { - if (!sock->ops->get_my_port) { + if (!sock->ops->fn_get_my_port) { return -1; } - return sock->ops->get_my_port(sock); + return sock->ops->fn_get_my_port(sock); } int socket_get_fd(struct socket_context *sock) { - if (!sock->ops->get_fd) { + if (!sock->ops->fn_get_fd) { return -1; } - return sock->ops->get_fd(sock); + return sock->ops->fn_get_fd(sock); } /* diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 6e54a37b80..7a8d335962 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -31,36 +31,36 @@ struct socket_ops { const char *name; enum socket_type type; - NTSTATUS (*init)(struct socket_context *sock); + NTSTATUS (*fn_init)(struct socket_context *sock); /* client ops */ - NTSTATUS (*connect)(struct socket_context *sock, + NTSTATUS (*fn_connect)(struct socket_context *sock, const char *my_address, int my_port, const char *server_address, int server_port, uint32_t flags); /* server ops */ - NTSTATUS (*listen)(struct socket_context *sock, + NTSTATUS (*fn_listen)(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags); - NTSTATUS (*accept)(struct socket_context *sock, struct socket_context **new_sock); + NTSTATUS (*fn_accept)(struct socket_context *sock, struct socket_context **new_sock); /* general ops */ - NTSTATUS (*recv)(struct socket_context *sock, void *buf, + NTSTATUS (*fn_recv)(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags); - NTSTATUS (*send)(struct socket_context *sock, + NTSTATUS (*fn_send)(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); - void (*close)(struct socket_context *sock); + void (*fn_close)(struct socket_context *sock); - NTSTATUS (*set_option)(struct socket_context *sock, const char *option, const char *val); + NTSTATUS (*fn_set_option)(struct socket_context *sock, const char *option, const char *val); - char *(*get_peer_name)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - char *(*get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - int (*get_peer_port)(struct socket_context *sock); - char *(*get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); - int (*get_my_port)(struct socket_context *sock); + char *(*fn_get_peer_name)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + char *(*fn_get_peer_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*fn_get_peer_port)(struct socket_context *sock); + char *(*fn_get_my_addr)(struct socket_context *sock, TALLOC_CTX *mem_ctx); + int (*fn_get_my_port)(struct socket_context *sock); - int (*get_fd)(struct socket_context *sock); + int (*fn_get_fd)(struct socket_context *sock); }; enum socket_state { diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 9777705419..263f5aa255 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -310,26 +310,26 @@ static int ipv4_tcp_get_fd(struct socket_context *sock) } static const struct socket_ops ipv4_tcp_ops = { - .name = "ipv4", - .type = SOCKET_TYPE_STREAM, - - .init = ipv4_tcp_init, - .connect = ipv4_tcp_connect, - .listen = ipv4_tcp_listen, - .accept = ipv4_tcp_accept, - .recv = ipv4_tcp_recv, - .send = ipv4_tcp_send, - .close = ipv4_tcp_close, - - .set_option = ipv4_tcp_set_option, - - .get_peer_name = ipv4_tcp_get_peer_name, - .get_peer_addr = ipv4_tcp_get_peer_addr, - .get_peer_port = ipv4_tcp_get_peer_port, - .get_my_addr = ipv4_tcp_get_my_addr, - .get_my_port = ipv4_tcp_get_my_port, - - .get_fd = ipv4_tcp_get_fd + .name = "ipv4", + .type = SOCKET_TYPE_STREAM, + + .fn_init = ipv4_tcp_init, + .fn_connect = ipv4_tcp_connect, + .fn_listen = ipv4_tcp_listen, + .fn_accept = ipv4_tcp_accept, + .fn_recv = ipv4_tcp_recv, + .fn_send = ipv4_tcp_send, + .fn_close = ipv4_tcp_close, + + .fn_set_option = ipv4_tcp_set_option, + + .fn_get_peer_name = ipv4_tcp_get_peer_name, + .fn_get_peer_addr = ipv4_tcp_get_peer_addr, + .fn_get_peer_port = ipv4_tcp_get_peer_port, + .fn_get_my_addr = ipv4_tcp_get_my_addr, + .fn_get_my_port = ipv4_tcp_get_my_port, + + .fn_get_fd = ipv4_tcp_get_fd }; const struct socket_ops *socket_ipv4_ops(void) diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 75e6fcab5c..c8683446ec 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -328,26 +328,26 @@ static int ipv6_tcp_get_fd(struct socket_context *sock) } static const struct socket_ops ipv6_tcp_ops = { - .name = "ipv6", - .type = SOCKET_TYPE_STREAM, - - .init = ipv6_tcp_init, - .connect = ipv6_tcp_connect, - .listen = ipv6_tcp_listen, - .accept = ipv6_tcp_accept, - .recv = ipv6_tcp_recv, - .send = ipv6_tcp_send, - .close = ipv6_tcp_close, - - .set_option = ipv6_tcp_set_option, - - .get_peer_name = ipv6_tcp_get_peer_name, - .get_peer_addr = ipv6_tcp_get_peer_addr, - .get_peer_port = ipv6_tcp_get_peer_port, - .get_my_addr = ipv6_tcp_get_my_addr, - .get_my_port = ipv6_tcp_get_my_port, - - .get_fd = ipv6_tcp_get_fd + .name = "ipv6", + .type = SOCKET_TYPE_STREAM, + + .fn_init = ipv6_tcp_init, + .fn_connect = ipv6_tcp_connect, + .fn_listen = ipv6_tcp_listen, + .fn_accept = ipv6_tcp_accept, + .fn_recv = ipv6_tcp_recv, + .fn_send = ipv6_tcp_send, + .fn_close = ipv6_tcp_close, + + .fn_set_option = ipv6_tcp_set_option, + + .fn_get_peer_name = ipv6_tcp_get_peer_name, + .fn_get_peer_addr = ipv6_tcp_get_peer_addr, + .fn_get_peer_port = ipv6_tcp_get_peer_port, + .fn_get_my_addr = ipv6_tcp_get_my_addr, + .fn_get_my_port = ipv6_tcp_get_my_port, + + .fn_get_fd = ipv6_tcp_get_fd }; const struct socket_ops *socket_ipv6_ops(void) diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index d160d897ee..f09573802a 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -246,26 +246,26 @@ static int unixdom_get_fd(struct socket_context *sock) } static const struct socket_ops unixdom_ops = { - .name = "unix", - .type = SOCKET_TYPE_STREAM, - - .init = unixdom_init, - .connect = unixdom_connect, - .listen = unixdom_listen, - .accept = unixdom_accept, - .recv = unixdom_recv, - .send = unixdom_send, - .close = unixdom_close, - - .set_option = unixdom_set_option, - - .get_peer_name = unixdom_get_peer_name, - .get_peer_addr = unixdom_get_peer_addr, - .get_peer_port = unixdom_get_peer_port, - .get_my_addr = unixdom_get_my_addr, - .get_my_port = unixdom_get_my_port, - - .get_fd = unixdom_get_fd + .name = "unix", + .type = SOCKET_TYPE_STREAM, + + .fn_init = unixdom_init, + .fn_connect = unixdom_connect, + .fn_listen = unixdom_listen, + .fn_accept = unixdom_accept, + .fn_recv = unixdom_recv, + .fn_send = unixdom_send, + .fn_close = unixdom_close, + + .fn_set_option = unixdom_set_option, + + .fn_get_peer_name = unixdom_get_peer_name, + .fn_get_peer_addr = unixdom_get_peer_addr, + .fn_get_peer_port = unixdom_get_peer_port, + .fn_get_my_addr = unixdom_get_my_addr, + .fn_get_my_port = unixdom_get_my_port, + + .fn_get_fd = unixdom_get_fd }; const struct socket_ops *socket_unixdom_ops(void) -- cgit From edbfc0f6e70150e321822365bf0eead2821551bd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 02:57:18 +0000 Subject: r3453: - split out the auth and popt includes - tidied up some of the system includes - moved a few more structures back from misc.idl to netlogon.idl and samr.idl now that pidl knows about inter-IDL dependencies (This used to be commit 7b7477ac42d96faac1b0ff361525d2c63cedfc64) --- source4/lib/cmdline/popt_common.c | 1 + source4/lib/registry/tools/regdiff.c | 1 + source4/lib/registry/tools/regpatch.c | 1 + source4/lib/registry/tools/regshell.c | 1 + source4/lib/registry/tools/regtree.c | 1 + 5 files changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index bd46373d58..80be23d364 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "lib/cmdline/popt_common.h" /* Handle command line options: * -d,--debuglevel diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index bedf3222d1..1d69734f21 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "lib/cmdline/popt_common.h" static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) { diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index eed249d353..298a922fbf 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "lib/cmdline/popt_common.h" /* * Routines to parse a REGEDIT4 file diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 8449446c86..fcc7204423 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "lib/cmdline/popt_common.h" #include "system/time.h" /* diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 66bce1e499..64948b06fe 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "lib/cmdline/popt_common.h" static void print_tree(int l, struct registry_key *p, int fullpath, int novals) { -- cgit From 6148deca663f7b6504b044120b166d6c9ae28750 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 03:13:06 +0000 Subject: r3454: moved a few more things out if includes.h into the include/system/ include files. this brings us down to about 11k lines of headers included with includes.h, while still retaining the speed of building with pch (This used to be commit 10188869ef072309ca580b8b933e172571fcdda7) --- source4/lib/cmdline/popt_common.c | 1 + source4/lib/module.c | 1 + source4/lib/system.c | 1 + source4/lib/tdb/common/tdb.c | 1 + source4/lib/xfile.c | 1 + 5 files changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 80be23d364..7d4dead4de 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/passwd.h" #include "lib/cmdline/popt_common.h" /* Handle command line options: diff --git a/source4/lib/module.c b/source4/lib/module.c index 58764683d5..9e568f601a 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/dir.h" +#include "system/filesys.h" #ifdef HAVE_DLOPEN diff --git a/source4/lib/system.c b/source4/lib/system.c index 906219bd91..5e106c96eb 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/network.h" #include "system/wait.h" +#include "system/filesys.h" /* The idea is that this file will eventually have wrappers around all diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index d41809c3d8..afe2ca1621 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -68,6 +68,7 @@ #include "includes.h" #include "system/time.h" #include "system/shmem.h" +#include "system/filesys.h" #endif #define TDB_MAGIC_FOOD "TDB file\n" diff --git a/source4/lib/xfile.c b/source4/lib/xfile.c index 8572bd857a..856e5dd6e6 100644 --- a/source4/lib/xfile.c +++ b/source4/lib/xfile.c @@ -30,6 +30,7 @@ */ #include "includes.h" +#include "system/filesys.h" #define XBUFSIZE BUFSIZ -- cgit From f4ec1497a1047eab8a2077694c7629ca6bb9eaa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 03:44:52 +0000 Subject: r3455: some more portability fixes. We nearly compile on solaris again now. (This used to be commit 4f33247f1ca60416415a61a7afac43c9dc8a61fd) --- source4/lib/replace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 60faa473b6..35e0277c59 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/wait.h" #include "system/time.h" +#include "system/network.h" void replace_dummy(void); void replace_dummy(void) {} @@ -328,7 +329,7 @@ duplicate a string #ifndef WITH_PTHREADS /* REWRITE: not thread safe */ #ifdef REPLACE_INET_NTOA -char *rep_inet_ntoa(struct ipv4_addr ip) + char *rep_inet_ntoa(struct in_addr ip) { uint8_t *p = (uint8_t *)&ip.s_addr; static char buf[18]; -- cgit From 5011f901aa0140ed60a0b58e80ab0f14810ba432 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 03:58:27 +0000 Subject: r3457: s_addr is a macro on solaris, so we can't use it in structure names. arrgh. (This used to be commit 7842b23d01c53009259a2461600bd01159cecebf) --- source4/lib/netif/interface.c | 30 +++++++++++++++--------------- source4/lib/socket/socket_ipv4.c | 8 ++++---- source4/lib/system.c | 4 ++-- source4/lib/util.c | 8 ++++---- source4/lib/util_sock.c | 4 ++-- source4/lib/util_strlist.c | 2 +- 6 files changed, 28 insertions(+), 28 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 75fdf8c976..1db0f5caee 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -45,7 +45,7 @@ static struct interface *local_interfaces; static struct ipv4_addr tov4(struct in_addr in) { struct ipv4_addr in2; - in2.s_addr = in.s_addr; + in2.addr = in.s_addr; return in2; } @@ -60,7 +60,7 @@ static struct interface *iface_find(struct in_addr ip, BOOL CheckMask) for (i=local_interfaces;i;i=i->next) if (CheckMask) { if (same_net(i->ip,tov4(ip),i->nmask)) return i; - } else if ((i->ip).s_addr == ip.s_addr) return i; + } else if (i->ip.addr == ip.s_addr) return i; return NULL; } @@ -77,7 +77,7 @@ static void add_interface(struct in_addr ip, struct in_addr nmask) return; } - if (ip_equal(nmask, allones_ip)) { + if (nmask.s_addr == allones_ip.addr) { DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); return; } @@ -89,7 +89,7 @@ static void add_interface(struct in_addr ip, struct in_addr nmask) iface->ip = tov4(ip); iface->nmask = tov4(nmask); - iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); + iface->bcast.addr = MKBCADDR(iface->ip.addr, iface->nmask.addr); DLIST_ADD(local_interfaces, iface); @@ -133,10 +133,10 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (!p) { - ip.s_addr = interpret_addr2(token).s_addr; + ip.s_addr = interpret_addr2(token).addr; for (i=0;i 2) { - nmask.s_addr = interpret_addr2(p).s_addr; + nmask.s_addr = interpret_addr2(p).addr; } else { nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); } @@ -219,8 +219,8 @@ void load_interfaces(void) exit(1); } for (i=0;inext) - if (ip_equal(i->ip,ip)) return True; + if (ipv4_equal(i->ip,ip)) return True; return False; } @@ -281,8 +281,8 @@ BOOL is_local_net(struct ipv4_addr from) { struct interface *i; for (i=local_interfaces;i;i=i->next) { - if((from.s_addr & i->nmask.s_addr) == - (i->ip.s_addr & i->nmask.s_addr)) + if((from.addr & i->nmask.addr) == + (i->ip.addr & i->nmask.addr)) return True; } return False; @@ -339,7 +339,7 @@ struct ipv4_addr *iface_ip(struct ipv4_addr ip) { struct in_addr in; struct interface *i; - in.s_addr = ip.s_addr; + in.s_addr = ip.addr; i = iface_find(in, True); return(i ? &i->ip : &local_interfaces->ip); } @@ -350,6 +350,6 @@ struct ipv4_addr *iface_ip(struct ipv4_addr ip) BOOL iface_local(struct ipv4_addr ip) { struct in_addr in; - in.s_addr = ip.s_addr; + in.s_addr = ip.addr; return iface_find(in, True) ? True : False; } diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 263f5aa255..eebbd61219 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -48,13 +48,13 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, my_ip = interpret_addr2(my_address); - if (my_ip.s_addr != 0 || my_port != 0) { + if (my_ip.addr != 0 || my_port != 0) { struct sockaddr_in my_addr; ZERO_STRUCT(my_addr); #ifdef HAVE_SOCK_SIN_LEN my_addr.sin_len = sizeof(my_addr); #endif - my_addr.sin_addr.s_addr = my_ip.s_addr; + my_addr.sin_addr.s_addr = my_ip.addr; my_addr.sin_port = htons(my_port); my_addr.sin_family = PF_INET; @@ -70,7 +70,7 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, #ifdef HAVE_SOCK_SIN_LEN srv_addr.sin_len = sizeof(srv_addr); #endif - srv_addr.sin_addr.s_addr= srv_ip.s_addr; + srv_addr.sin_addr.s_addr= srv_ip.addr; srv_addr.sin_port = htons(srv_port); srv_addr.sin_family = PF_INET; @@ -105,7 +105,7 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, #ifdef HAVE_SOCK_SIN_LEN my_addr.sin_len = sizeof(my_addr); #endif - my_addr.sin_addr.s_addr = ip_addr.s_addr; + my_addr.sin_addr.s_addr = ip_addr.addr; my_addr.sin_port = htons(port); my_addr.sin_family = PF_INET; diff --git a/source4/lib/system.c b/source4/lib/system.c index 5e106c96eb..d50005e8c8 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -540,7 +540,7 @@ int sys_dup2(int oldfd, int newfd) const char *sys_inet_ntoa(struct ipv4_addr in) { struct in_addr in2; - in2.s_addr = in.s_addr; + in2.s_addr = in.addr; return inet_ntoa(in2); } @@ -554,7 +554,7 @@ struct ipv4_addr sys_inet_makeaddr(int net, int host) struct in_addr in; struct ipv4_addr in2; in = inet_makeaddr(net, host); - in2.s_addr = in.s_addr; + in2.addr = in.s_addr; return in2; } diff --git a/source4/lib/util.c b/source4/lib/util.c index 2ce34f58d9..5385174ce4 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -452,7 +452,7 @@ struct ipv4_addr interpret_addr2(const char *str) { struct ipv4_addr ret; uint32_t a = interpret_addr(str); - ret.s_addr = a; + ret.addr = a; return ret; } @@ -486,9 +486,9 @@ BOOL same_net(struct ipv4_addr ip1,struct ipv4_addr ip2,struct ipv4_addr mask) { uint32_t net1,net2,nmask; - nmask = ntohl(mask.s_addr); - net1 = ntohl(ip1.s_addr); - net2 = ntohl(ip2.s_addr); + nmask = ntohl(mask.addr); + net1 = ntohl(ip1.addr); + net2 = ntohl(ip2.addr); return((net1 & nmask) == (net2 & nmask)); } diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index dbd71b58b6..876698535b 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -170,7 +170,7 @@ ssize_t read_udp_socket(int fd, char *buf, size_t len, } if (from_addr) { - from_addr->s_addr = sock.sin_addr.s_addr; + from_addr->addr = sock.sin_addr.s_addr; } if (from_port) { *from_port = ntohs(sock.sin_port); @@ -512,7 +512,7 @@ char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) addr = interpret_addr2(p); /* Look up the remote host name. */ - if ((hp = gethostbyaddr((char *)&addr.s_addr, sizeof(addr.s_addr), AF_INET)) == 0) { + if ((hp = gethostbyaddr((char *)&addr.addr, sizeof(addr.addr), AF_INET)) == 0) { DEBUG(1,("Gethostbyaddr failed for %s\n",p)); name_buf = talloc_strdup(mem_ctx, p); } else { diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 0b32955ac2..db459b2f0f 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -297,7 +297,7 @@ int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list) struct ipv4_addr addr; /* convert single token to ip address */ - if ( (addr.s_addr = sys_inet_addr(token_str)) == INADDR_NONE ) + if ( (addr.addr = sys_inet_addr(token_str)) == INADDR_NONE ) break; /* prepare place for another in_addr structure */ -- cgit From 8692564e350db4dfa4a9ef4c4cb014d76b284d3b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 04:17:30 +0000 Subject: r3458: more solaris portability fixes, the main one being that we can't use a structure element called "open" as its a macro on solaris. (This used to be commit 4e92e15c4e396b1d8cd211192888fea68c2cf0f9) --- source4/lib/fault.c | 1 + source4/lib/system.c | 116 --------------------------------------------------- 2 files changed, 1 insertion(+), 116 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/fault.c b/source4/lib/fault.c index ed1e7c4366..ac2d4109fd 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/wait.h" static void (*cont_fn)(void *); diff --git a/source4/lib/system.c b/source4/lib/system.c index d50005e8c8..46490bb17e 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -335,122 +335,6 @@ void sys_srandom(uint_t seed) #endif } -/************************************************************************** - Returns equivalent to NGROUPS_MAX - using sysconf if needed. -****************************************************************************/ - -int groups_max(void) -{ -#if defined(SYSCONF_SC_NGROUPS_MAX) - int ret = sysconf(_SC_NGROUPS_MAX); - return (ret == -1) ? NGROUPS_MAX : ret; -#else - return NGROUPS_MAX; -#endif -} - -/************************************************************************** - Wrapper for getgroups. Deals with broken (int) case. -****************************************************************************/ - -int sys_getgroups(int setlen, gid_t *gidset) -{ -#if !defined(HAVE_BROKEN_GETGROUPS) - return getgroups(setlen, gidset); -#else - - GID_T gid; - GID_T *group_list; - int i, ngroups; - - if(setlen == 0) { - return getgroups(setlen, &gid); - } - - /* - * Broken case. We need to allocate a - * GID_T array of size setlen. - */ - - if(setlen < 0) { - errno = EINVAL; - return -1; - } - - if (setlen == 0) - setlen = groups_max(); - - if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { - DEBUG(0,("sys_getgroups: Malloc fail.\n")); - return -1; - } - - if((ngroups = getgroups(setlen, group_list)) < 0) { - int saved_errno = errno; - SAFE_FREE(group_list); - errno = saved_errno; - return -1; - } - - for(i = 0; i < ngroups; i++) - gidset[i] = (gid_t)group_list[i]; - - SAFE_FREE(group_list); - return ngroups; -#endif /* HAVE_BROKEN_GETGROUPS */ -} - -#ifdef HAVE_SETGROUPS - -/************************************************************************** - Wrapper for setgroups. Deals with broken (int) case. Automatically used - if we have broken getgroups. -****************************************************************************/ - -int sys_setgroups(int setlen, gid_t *gidset) -{ -#if !defined(HAVE_BROKEN_GETGROUPS) - return setgroups(setlen, gidset); -#else - - GID_T *group_list; - int i ; - - if (setlen == 0) - return 0 ; - - if (setlen < 0 || setlen > groups_max()) { - errno = EINVAL; - return -1; - } - - /* - * Broken case. We need to allocate a - * GID_T array of size setlen. - */ - - if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) { - DEBUG(0,("sys_setgroups: Malloc fail.\n")); - return -1; - } - - for(i = 0; i < setlen; i++) - group_list[i] = (GID_T) gidset[i]; - - if(setgroups(setlen, group_list) != 0) { - int saved_errno = errno; - SAFE_FREE(group_list); - errno = saved_errno; - return -1; - } - - SAFE_FREE(group_list); - return 0 ; -#endif /* HAVE_BROKEN_GETGROUPS */ -} - -#endif /* HAVE_SETGROUPS */ - struct passwd *sys_getpwent(void) { return getpwent(); -- cgit From 2df2d1b67f9bf2907f452688b2c54b73052cfb49 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 04:51:57 +0000 Subject: r3461: another place where "open" was used as a structure element (This used to be commit 1087ea830e7aead86d54a1836512e88554afc919) --- source4/lib/tdb/tools/tdbtorture.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 6471aec3ad..e90a967138 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/time.h" +#include "system/wait.h" #endif -- cgit From a1d0b97ed40fe6985bb45b1715309638e7faaffc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 06:14:15 +0000 Subject: r3462: separate out the crypto includes (This used to be commit 3f75117db921e493bb77a5dc14b8ce91a6288f30) --- source4/lib/basic.m4 | 2 ++ source4/lib/basic.mk | 19 ++++++++++++++----- source4/lib/crypto/crc32.h | 2 ++ source4/lib/crypto/crypto.h | 24 ++++++++++++++++++++++++ source4/lib/crypto/hmacmd5.c | 1 + source4/lib/crypto/hmacmd5.h | 39 +++++++++++++++++++++++++++++++++++++++ source4/lib/crypto/md4.h | 1 + source4/lib/crypto/md5.h | 24 ++++++++++++++++++++++++ source4/lib/genrand.c | 1 + 9 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 source4/lib/crypto/crc32.h create mode 100644 source4/lib/crypto/crypto.h create mode 100644 source4/lib/crypto/hmacmd5.h create mode 100644 source4/lib/crypto/md4.h create mode 100644 source4/lib/crypto/md5.h (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 index 1640ef2b9d..b3327b6dcc 100644 --- a/source4/lib/basic.m4 +++ b/source4/lib/basic.m4 @@ -2,4 +2,6 @@ dnl # LIB BASIC subsystem SMB_SUBSYSTEM_MK(LIBREPLACE,lib/basic.mk) SMB_SUBSYSTEM_MK(LIBNETIF,lib/basic.mk) +SMB_SUBSYSTEM_NOPROTO(LIBCRYPTO) +SMB_SUBSYSTEM_MK(LIBCRYPTO,lib/basic.mk) SMB_SUBSYSTEM_MK(LIBBASIC,lib/basic.mk) diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 55e654ec74..e7d710eec6 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -19,6 +19,19 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBNETIF ############################## +############################## +# Start SUBSYSTEM LIBCRYPTO +[SUBSYSTEM::LIBCRYPTO] +INIT_OBJ_FILES = \ + lib/crypto/crc32.o +ADD_OBJ_FILES = \ + lib/crypto/md5.o \ + lib/crypto/hmacmd5.o \ + lib/crypto/md4.o +# End SUBSYSTEM LIBCRYPTO +############################## + + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -57,14 +70,10 @@ ADD_OBJ_FILES = \ lib/module.o \ lib/mutex.o \ lib/events.o \ - lib/crypto/crc32.o \ - lib/crypto/md5.o \ - lib/crypto/hmacmd5.o \ - lib/crypto/md4.o \ lib/db_wrap.o \ lib/server_mutex.o \ lib/idtree.o REQUIRED_SUBSYSTEMS = \ - LIBTDB CHARSET LIBREPLACE LIBNETIF + LIBTDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/crypto/crc32.h b/source4/lib/crypto/crc32.h new file mode 100644 index 0000000000..a1030c14df --- /dev/null +++ b/source4/lib/crypto/crc32.h @@ -0,0 +1,2 @@ +uint32_t crc32_calc_buffer( const char *buffer, uint32_t count); + diff --git a/source4/lib/crypto/crypto.h b/source4/lib/crypto/crypto.h new file mode 100644 index 0000000000..e7a0c290a5 --- /dev/null +++ b/source4/lib/crypto/crypto.h @@ -0,0 +1,24 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "lib/crypto/md5.h" +#include "lib/crypto/md4.h" +#include "lib/crypto/hmacmd5.h" +#include "lib/crypto/crc32.h" diff --git a/source4/lib/crypto/hmacmd5.c b/source4/lib/crypto/hmacmd5.c index 9b24279f71..2045f9a9d7 100644 --- a/source4/lib/crypto/hmacmd5.c +++ b/source4/lib/crypto/hmacmd5.c @@ -24,6 +24,7 @@ */ #include "includes.h" +#include "lib/crypto/crypto.h" /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. diff --git a/source4/lib/crypto/hmacmd5.h b/source4/lib/crypto/hmacmd5.h new file mode 100644 index 0000000000..fb6692a05f --- /dev/null +++ b/source4/lib/crypto/hmacmd5.h @@ -0,0 +1,39 @@ +/* + Unix SMB/CIFS implementation. + Interface header: Scheduler service + Copyright (C) Luke Kenneth Casson Leighton 1996-1999 + Copyright (C) Andrew Tridgell 1992-1999 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _HMAC_MD5_H + +typedef struct +{ + struct MD5Context ctx; + uint8_t k_ipad[65]; + uint8_t k_opad[65]; + +} HMACMD5Context; + +void hmac_md5_init_limK_to_64(const uint8_t *key, int key_len, + HMACMD5Context *ctx); +void hmac_md5_update(const uint8_t *text, int text_len, HMACMD5Context *ctx); +void hmac_md5_final(uint8_t *digest, HMACMD5Context *ctx); +void hmac_md5(const uint8_t key[16], const uint8_t *data, int data_len, uint8_t *digest); +void hmac_md5_init_rfc2104(const uint8_t *key, int key_len, HMACMD5Context *ctx); + +#endif /* _HMAC_MD5_H */ diff --git a/source4/lib/crypto/md4.h b/source4/lib/crypto/md4.h new file mode 100644 index 0000000000..234e488e4f --- /dev/null +++ b/source4/lib/crypto/md4.h @@ -0,0 +1 @@ +void mdfour(uint8_t *out, const uint8_t *in, int n); diff --git a/source4/lib/crypto/md5.h b/source4/lib/crypto/md5.h new file mode 100644 index 0000000000..cd23979f8a --- /dev/null +++ b/source4/lib/crypto/md5.h @@ -0,0 +1,24 @@ +#ifndef MD5_H +#define MD5_H +#ifndef HEADER_MD5_H +/* Try to avoid clashes with OpenSSL */ +#define HEADER_MD5_H +#endif + +struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + uint8_t in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, uint8_t const *buf, + uint_t len); +void MD5Final(uint8_t digest[16], struct MD5Context *context); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 7289719791..46a73e6d2e 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/iconv.h" +#include "lib/crypto/crypto.h" static unsigned char hash[258]; static uint32 counter; -- cgit From 3643fb11092e28a9538ef32cedce8ff21ad86a28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 06:42:15 +0000 Subject: r3463: separated out some more headers (asn_1.h, messages.h, dlinklist.h and ioctl.h) (This used to be commit b97e395c814762024336c1cf4d7c25be8da5813a) --- source4/lib/db_wrap.c | 1 + source4/lib/events.c | 1 + source4/lib/iconv.c | 1 + source4/lib/messaging/messaging.c | 2 ++ source4/lib/module.c | 1 + source4/lib/netif/interface.c | 1 + source4/lib/registry/common/reg_interface.c | 1 + source4/lib/tdb/common/tdbutil.c | 3 ++- 8 files changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 251741c5b0..c786185499 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -28,6 +28,7 @@ */ #include "includes.h" +#include "dlinklist.h" static struct ldb_wrap *ldb_list; static struct tdb_wrap *tdb_list; diff --git a/source4/lib/events.c b/source4/lib/events.c index 276b3d08e9..4fb1e42ba3 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -67,6 +67,7 @@ #include "includes.h" #include "system/time.h" #include "system/select.h" +#include "dlinklist.h" /* create a event_context structure. This must be the first events diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 98905c4b84..c4fea25db5 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "dlinklist.h" #include "system/iconv.h" diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index a2316919cb..48d608ee94 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -22,6 +22,8 @@ #include "includes.h" #include "system/time.h" +#include "messages.h" +#include "dlinklist.h" /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 diff --git a/source4/lib/module.c b/source4/lib/module.c index 9e568f601a..80360e4e72 100644 --- a/source4/lib/module.c +++ b/source4/lib/module.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/dir.h" #include "system/filesys.h" +#include "dlinklist.h" #ifdef HAVE_DLOPEN diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 1db0f5caee..3555170123 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/network.h" #include "lib/netif/netif.h" +#include "dlinklist.h" static struct iface_struct *probed_ifaces; static int total_probed; diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 70b600ba33..76a1d04b08 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "dlinklist.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 0e0a6eca28..c9b5dc05e6 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -19,7 +19,8 @@ */ #include "includes.h" -#include +#include "system/glob.h" +#include "dlinklist.h" /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ -- cgit From a42142439aee9e75796e25cdf05e042174926abf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 06:52:59 +0000 Subject: r3464: split out registry.h, rap.h and ldap_server.h (This used to be commit 70d2090f6bf2c7e0caf1e9c020f330de88871f8e) --- source4/lib/registry/common/reg_interface.c | 1 + source4/lib/registry/common/reg_util.c | 1 + source4/lib/registry/reg_backend_dir/reg_backend_dir.c | 1 + source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c | 1 + source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 1 + source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 1 + source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 1 + source4/lib/registry/tools/regdiff.c | 1 + source4/lib/registry/tools/regpatch.c | 1 + source4/lib/registry/tools/regshell.c | 1 + source4/lib/registry/tools/regtree.c | 1 + 11 files changed, 11 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 76a1d04b08..b2d659258d 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -20,6 +20,7 @@ #include "includes.h" #include "dlinklist.h" +#include "registry.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index c7354fe909..052ccc347b 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "registry.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 2273a86771..247d723252 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "registry.h" #include "system/dir.h" static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index bd3afbdedf..22c81018c7 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "registry.h" static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index a8d1752070..c1b9b43445 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -304,6 +304,7 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, *************************************************************************/ #include "includes.h" +#include "registry.h" #include "system/shmem.h" #define REG_KEY_LIST_SIZE 10 diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index f90b123bfc..954e7684bb 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" +#include "registry.h" #include "librpc/gen_ndr/ndr_winreg.h" /** diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 448af66eec..72ec882b8a 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" +#include "registry.h" #include "system/shmem.h" /** diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 1d69734f21..c1b8d2949e 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "registry.h" #include "lib/cmdline/popt_common.h" static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 298a922fbf..ae4d331e3c 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "registry.h" #include "lib/cmdline/popt_common.h" /* diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index fcc7204423..583624fbab 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "registry.h" #include "lib/cmdline/popt_common.h" #include "system/time.h" diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 64948b06fe..8fd73aef85 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "registry.h" #include "lib/cmdline/popt_common.h" static void print_tree(int l, struct registry_key *p, int fullpath, int novals) -- cgit From aa34fcebf8aa0660574a7c6976b33b3f37985e27 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 07:18:24 +0000 Subject: r3466: split out request.h, signing.h, and smb_server.h (This used to be commit 7c4e6ebf05790dd6e29896dd316db0fff613aa4e) --- source4/lib/substitute.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c index 3de2966f56..a01b90450a 100644 --- a/source4/lib/substitute.c +++ b/source4/lib/substitute.c @@ -20,6 +20,7 @@ #include "includes.h" +#include "smb_server/smb_server.h" /* oh bugger - I realy didn't want to have a top-level context anywhere, but until we change all lp_*() calls to take a context -- cgit From fe3c2456e22b69c1b146b490e2338a065ec402ea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 09:55:57 +0000 Subject: r3470: removed some unused functions (should fix the build on IRIX 6.4) (This used to be commit b4c727a8dd74c9603a58c019d4be8b423209e04d) --- source4/lib/system.c | 126 ++++++--------------------------------------------- 1 file changed, 15 insertions(+), 111 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/system.c b/source4/lib/system.c index 46490bb17e..1e986497e4 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -75,6 +75,21 @@ int sys_usleep(long usecs) #endif /* HAVE_USLEEP */ } + +/******************************************************************* + System wrapper for getwd +********************************************************************/ +char *sys_getwd(char *s) +{ + char *wd; +#ifdef HAVE_GETCWD + wd = (char *)getcwd(s, sizeof (pstring)); +#else + wd = (char *)getwd(s); +#endif + return wd; +} + /******************************************************************* A read wrapper that will deal with EINTR. ********************************************************************/ @@ -103,63 +118,7 @@ ssize_t sys_write(int fd, const void *buf, size_t count) return ret; } -/******************************************************************* -A send wrapper that will deal with EINTR. -********************************************************************/ - -ssize_t sys_send(int s, const void *msg, size_t len, int flags) -{ - ssize_t ret; - do { - ret = send(s, msg, len, flags); - } while (ret == -1 && errno == EINTR); - return ret; -} - -/******************************************************************* -A sendto wrapper that will deal with EINTR. -********************************************************************/ - -ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) -{ - ssize_t ret; - - do { - ret = sendto(s, msg, len, flags, to, tolen); - } while (ret == -1 && errno == EINTR); - return ret; -} - - -/******************************************************************* - System wrapper for getwd -********************************************************************/ - -char *sys_getwd(char *s) -{ - char *wd; -#ifdef HAVE_GETCWD - wd = (char *)getcwd(s, sizeof (pstring)); -#else - wd = (char *)getwd(s); -#endif - return wd; -} - -/******************************************************************* -system wrapper for link -********************************************************************/ - -int sys_link(const char *oldpath, const char *newpath) -{ -#ifndef HAVE_LINK - errno = ENOSYS; - return -1; -#else - return link(oldpath, newpath); -#endif -} /******************************************************************* os/2 also doesn't have chroot @@ -335,41 +294,6 @@ void sys_srandom(uint_t seed) #endif } -struct passwd *sys_getpwent(void) -{ - return getpwent(); -} - -void sys_endpwent(void) -{ - endpwent(); -} - -/************************************************************************** - Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid() -****************************************************************************/ - -struct passwd *sys_getpwnam(const char *name) -{ - return getpwnam(name); -} - -struct passwd *sys_getpwuid(uid_t uid) -{ - return getpwuid(uid); -} - -struct group *sys_getgrnam(const char *name) -{ - return getgrnam(name); -} - -struct group *sys_getgrgid(gid_t gid) -{ - return getgrgid(gid); -} - - /************************************************************************** Wrappers for dlopen, dlsym, dlclose. ****************************************************************************/ @@ -392,15 +316,6 @@ void *sys_dlsym(void *handle, const char *symbol) #endif } -int sys_dlclose (void *handle) -{ -#if defined(HAVE_DLCLOSE) - return dlclose(handle); -#else - return 0; -#endif -} - const char *sys_dlerror(void) { #if defined(HAVE_DLERROR) @@ -410,17 +325,6 @@ const char *sys_dlerror(void) #endif } -int sys_dup2(int oldfd, int newfd) -{ -#if defined(HAVE_DUP2) - return dup2(oldfd, newfd); -#else - errno = ENOSYS; - return -1; -#endif -} - - const char *sys_inet_ntoa(struct ipv4_addr in) { struct in_addr in2; -- cgit From c9ec1bbbae8e08c14587ce29185211f298fd6c58 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 09:59:19 +0000 Subject: r3471: split out capabilities code from lib/system.c - should fix IRIX 6.5 build (This used to be commit 34ffcd38a5544173aca85fbcec2f7ebfd5ec1f25) --- source4/lib/capability.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/system.c | 81 ---------------------------------- 2 files changed, 112 insertions(+), 81 deletions(-) create mode 100644 source4/lib/capability.c (limited to 'source4/lib') diff --git a/source4/lib/capability.c b/source4/lib/capability.c new file mode 100644 index 0000000000..0cebd33303 --- /dev/null +++ b/source4/lib/capability.c @@ -0,0 +1,112 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + capabilities fns - will be needed when we enable kernel oplocks +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/wait.h" +#include "system/filesys.h" + + +#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES) +/************************************************************************** + Try and abstract process capabilities (for systems that have them). +****************************************************************************/ +static BOOL set_process_capability( uint32_t cap_flag, BOOL enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return False; + } + + if(enable) + cap->cap_effective |= CAP_NETWORK_MGT; + else + cap->cap_effective &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return False; + } + + cap_free(cap); + + DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return True; +} + +/************************************************************************** + Try and abstract inherited process capabilities (for systems that have them). +****************************************************************************/ + +static BOOL set_inherited_process_capability( uint32_t cap_flag, BOOL enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return False; + } + + if(enable) + cap->cap_inheritable |= CAP_NETWORK_MGT; + else + cap->cap_inheritable &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return False; + } + + cap_free(cap); + + DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return True; +} +#endif + +/**************************************************************************** + Gain the oplock capability from the kernel if possible. +****************************************************************************/ + +void oplock_set_capability(BOOL this_process, BOOL inherit) +{ +#if HAVE_KERNEL_OPLOCKS_IRIX + set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process); + set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit); +#endif +} + diff --git a/source4/lib/system.c b/source4/lib/system.c index 1e986497e4..9fa71c449a 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -181,87 +181,6 @@ struct hostent *sys_gethostbyname(const char *name) } -#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES) -/************************************************************************** - Try and abstract process capabilities (for systems that have them). -****************************************************************************/ -static BOOL set_process_capability( uint32_t cap_flag, BOOL enable ) -{ - if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { - cap_t cap = cap_get_proc(); - - if (cap == NULL) { - DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", - strerror(errno))); - return False; - } - - if(enable) - cap->cap_effective |= CAP_NETWORK_MGT; - else - cap->cap_effective &= ~CAP_NETWORK_MGT; - - if (cap_set_proc(cap) == -1) { - DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", - strerror(errno))); - cap_free(cap); - return False; - } - - cap_free(cap); - - DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); - } - return True; -} - -/************************************************************************** - Try and abstract inherited process capabilities (for systems that have them). -****************************************************************************/ - -static BOOL set_inherited_process_capability( uint32_t cap_flag, BOOL enable ) -{ - if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { - cap_t cap = cap_get_proc(); - - if (cap == NULL) { - DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", - strerror(errno))); - return False; - } - - if(enable) - cap->cap_inheritable |= CAP_NETWORK_MGT; - else - cap->cap_inheritable &= ~CAP_NETWORK_MGT; - - if (cap_set_proc(cap) == -1) { - DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", - strerror(errno))); - cap_free(cap); - return False; - } - - cap_free(cap); - - DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); - } - return True; -} -#endif - -/**************************************************************************** - Gain the oplock capability from the kernel if possible. -****************************************************************************/ - -void oplock_set_capability(BOOL this_process, BOOL inherit) -{ -#if HAVE_KERNEL_OPLOCKS_IRIX - set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process); - set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit); -#endif -} - /************************************************************************** Wrapper for random(). ****************************************************************************/ -- cgit From c2c044386109fc61d71ac89e2a4b8a0d9c6ac186 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 10:13:26 +0000 Subject: r3472: fixed build of reg_backend_gconf (This used to be commit d8a4af5282a1a3002def250f4857469ffb84d183) --- source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 4f8cc5466e..382bc6dba5 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "registry.h" #include static WERROR gerror_to_werror(GError *error) -- cgit From 6bd02aa5046b606171a680e6f8aefba31b744af1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 11:42:35 +0000 Subject: r3478: split out some more pieces of includes.h (This used to be commit 8e9212ecfc61c509f686363d8ec412ce54bc1c8d) --- source4/lib/util_strlist.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index db459b2f0f..a9198031a1 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/network.h" /** List of Strings manipulation functions -- cgit From 8228a362a9d70ae51c04d11840fa081794d26c68 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 11:53:44 +0000 Subject: r3480: moved some signal defines into include/system (This used to be commit a954e707ef5b23af84ef8f622336e36379c4a373) --- source4/lib/tdb/common/tdbutil.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index c9b5dc05e6..b5187162cf 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -20,6 +20,7 @@ #include "includes.h" #include "system/glob.h" +#include "system/wait.h" #include "dlinklist.h" /* these are little tdb utility functions that are meant to make -- cgit From a99b6219a810a1cd10bd62a6716780602808f0cd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 12:15:17 +0000 Subject: r3481: split out client.h and events.h (This used to be commit c6f486574470a311e0d336c026103f131451e21e) --- source4/lib/events.c | 1 + source4/lib/messaging/messaging.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 4fb1e42ba3..f53a244c6d 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -68,6 +68,7 @@ #include "system/time.h" #include "system/select.h" #include "dlinklist.h" +#include "events.h" /* create a event_context structure. This must be the first events diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 48d608ee94..f862b2d505 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "events.h" #include "system/time.h" #include "messages.h" #include "dlinklist.h" -- cgit From e8e94a93b554d357c577850c4abf85d942333bec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 12:43:25 +0000 Subject: r3482: fixed a warning and an error from the IRIX 6.4 build (This used to be commit 8ec3cf8b2ba149b7d6a15689e9b77685c6da3179) --- source4/lib/iconv.c | 2 +- source4/lib/socket/socket_unix.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index c4fea25db5..a08e0ee69a 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -56,7 +56,7 @@ static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); -static const struct charset_functions const builtin_functions[] = { +static const struct charset_functions builtin_functions[] = { /* windows is closest to UTF-16 */ {"UCS-2LE", iconv_copy, iconv_copy}, {"UTF-16LE", iconv_copy, iconv_copy}, diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index f09573802a..0ba4797219 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "system/network.h" -- cgit From 7573366629ce719471729587b918ccff71f5413d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 2 Nov 2004 17:09:06 +0000 Subject: r3488: Start using RemoteActivation (This used to be commit b4e81ffc648d30c4c501b168d5e2e562941648ac) --- source4/lib/dcom/common/main.c | 92 ++++++++++++++++++++++++++++++++++++++++++ source4/lib/dcom/config.mk | 2 +- source4/lib/dcom/main.c | 65 ----------------------------- source4/lib/dcom/procedure | 8 ---- 4 files changed, 93 insertions(+), 74 deletions(-) create mode 100644 source4/lib/dcom/common/main.c delete mode 100644 source4/lib/dcom/main.c delete mode 100644 source4/lib/dcom/procedure (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c new file mode 100644 index 0000000000..a490c32c14 --- /dev/null +++ b/source4/lib/dcom/common/main.c @@ -0,0 +1,92 @@ +/* + Unix SMB/CIFS implementation. + Main DCOM functionality + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_epmapper.h" +#include "librpc/gen_ndr/ndr_remact.h" + +static WERROR dcom_binding_from_oxid(TALLOC_CTX *mem_ctx, HYPER_T oxid, struct dcerpc_binding *bd) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} + +static WERROR dcom_tower_from_oxid(TALLOC_CTX *mem_ctx, HYPER_T oxid, struct epm_tower *bd) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} + +static WERROR dcom_get_class_object (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) +{ + struct RemoteActivation r; + NTSTATUS status; + struct GUID iids[2]; + uint16 protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }; + + ZERO_STRUCT(r.in); + r.in.this.version.MajorVersion = 5; + r.in.this.version.MinorVersion = 1; + uuid_generate_random(&r.in.this.cid); + r.in.Clsid = clsid; + r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; + r.in.num_protseqs = 3; + r.in.protseq = protseq; + r.in.Interfaces = 1; + GUID_from_string(DCERPC_IUNKNOWN_UUID, &iids[0]); + r.in.pIIDs = iids; + r.in.Mode = MODE_GET_CLASS_OBJECT; + + status = dcerpc_RemoteActivation(p, mem_ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + fprintf(stderr, "RemoteActivation: %s\n", nt_errstr(status)); + return ntstatus_to_werror(status); + } + + if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } + if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } + if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } + + return WERR_OK; +} + +static WERROR dcom_create_instance (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) +{ + return WERR_NOT_SUPPORTED; +} + +static uint32 IUnknown_AddRef(void) +{ + /* FIXME: Tell local server we're adding a reference to this interface on this object. Local server can then call RemAddRef() if necessary */ + return 0; +} + +static uint32 IUnknown_Release(void) +{ + /* FIXME: Tell local server we're releasing a reference to this interface on this object. Local server can then call RemRelease() if necessary */ + return 0; +} + +static WERROR IUnknown_QueryInterface(struct GUID *riid, void **data) +{ + /* FIXME: Ask local server for interface pointer. Local server can then + * call RemQueryInterface if necessary */ + return WERR_NOT_SUPPORTED; +} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index ef7cbf40c8..98b7031407 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM LIBDCOM [SUBSYSTEM::LIBDCOM] INIT_OBJ_FILES = \ - lib/dcom/main.o + lib/dcom/common/main.o # # End SUBSYSTEM LIBDCOM ################################################ diff --git a/source4/lib/dcom/main.c b/source4/lib/dcom/main.c deleted file mode 100644 index 515322e27a..0000000000 --- a/source4/lib/dcom/main.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Main DCOM functionality - Copyright (C) 2004 Jelmer Vernooij - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -void CoInitializeEx(void *reserved, uint32 thread_options) -{ - /* FIXME */ -} - -void CoInitialize(void *reserved) -{ - CoInitializeEx(reserved, 0); -} - -void CoUnitialize(void) -{ - /* FIXME */ -} - -void CoRegisterClassObject(void) -{ - /* FIXME */ -} - -void CoUnregisterClassObject(void) -{ - /* FIXME */ -} - -void CoCreateInstanceEx(struct GUID *clsid, void *iface, uint32 context, struct COSERVERINFO *pcsi, uint32 num, struct MULTI_QI *results) -{ - /* FIXME: Connect to remote server and :*/ - - /* FIXME: Call RemoteActivation() */ - /* FIXME: Call ServerAlive() on IOXIDResolver */ - -} - -void CoCreateInstance(void) -{ - CoCreateInstanceEx(/*FIXME*/); -} - -void CoRegisterClassObject(void) -{ - /* FIXME */ -} diff --git a/source4/lib/dcom/procedure b/source4/lib/dcom/procedure deleted file mode 100644 index dc89d00bb2..0000000000 --- a/source4/lib/dcom/procedure +++ /dev/null @@ -1,8 +0,0 @@ -Required infrastructure: - - CoCreateInstance function - - Proxy and Stub (class ?) - - - - Bind to IOXIDResolver - - ServerAlive2() - - Bind to ISystemActivator -- cgit From 6f214cc510a59b7a65ee9d4486baf14a3e579f73 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Nov 2004 00:17:12 +0000 Subject: r3494: got rid of include/rewrite.h, and split out the dynconfig.h header (This used to be commit 558de54ec6432a4ae90aa14a585f32c6cd03ced2) --- source4/lib/cmdline/popt_common.c | 1 + source4/lib/debug.c | 1 + source4/lib/registry/tools/regdiff.c | 1 + source4/lib/registry/tools/regpatch.c | 1 + source4/lib/registry/tools/regshell.c | 1 + source4/lib/registry/tools/regtree.c | 1 + source4/lib/substitute.c | 1 + source4/lib/util.c | 1 + 8 files changed, 8 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 7d4dead4de..6422b84b44 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/debug.c b/source4/lib/debug.c index 4f6ba125d3..f1e9cec38e 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "dynconfig.h" /* this global variable determines what messages are printed */ int DEBUGLEVEL; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index c1b8d2949e..80f4a5c49f 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "registry.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index ae4d331e3c..38eabb60a9 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "registry.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 583624fbab..d705a0b802 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "registry.h" #include "lib/cmdline/popt_common.h" #include "system/time.h" diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 8fd73aef85..a8225c026d 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "registry.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c index a01b90450a..a351db1af2 100644 --- a/source4/lib/substitute.c +++ b/source4/lib/substitute.c @@ -37,6 +37,7 @@ void sub_set_context(struct substitute_context *subptr) */ static void setup_string(char **dest, const char *str) { +#define SAFE_NETBIOS_CHARS ". -_" char *s; s = strdup(str); diff --git a/source4/lib/util.c b/source4/lib/util.c index 5385174ce4..d8e9cb50f9 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -23,6 +23,7 @@ */ #include "includes.h" +#include "dynconfig.h" #include "system/network.h" #include "system/iconv.h" -- cgit From dde07058075d357cfdc63624c8dcaa67ebd40add Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Nov 2004 10:09:48 +0000 Subject: r3507: - added deferred replies on sharing violation in pvfs open. The deferred reply is short-circuited immediately when the file is closed by another user, allowing it to be opened by the waiting user. - added a sane set of timeval manipulation routines - converted all the events code and code that uses it to use struct timeval instead of time_t, which allows for microsecond resolution instead of 1 second resolution. This was needed for doing the pvfs deferred open code, and is why the patch is so big. (This used to be commit 0d51511d408d91eb5f68a35e980e0875299b1831) --- source4/lib/basic.mk | 3 +- source4/lib/events.c | 23 +++---- source4/lib/messaging/messaging.c | 51 +++++++++++--- source4/lib/time.c | 141 +++++++++++++++++++++++++++++++++++++- source4/lib/unix_privs.c | 69 +++++++++++++++++++ 5 files changed, 258 insertions(+), 29 deletions(-) create mode 100644 source4/lib/unix_privs.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index e7d710eec6..827aa0a57c 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -72,7 +72,8 @@ ADD_OBJ_FILES = \ lib/events.o \ lib/db_wrap.o \ lib/server_mutex.o \ - lib/idtree.o + lib/idtree.o \ + lib/unix_privs.o REQUIRED_SUBSYSTEMS = \ LIBTDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO # End SUBSYSTEM LIBBASIC diff --git a/source4/lib/events.c b/source4/lib/events.c index f53a244c6d..0ca6b66598 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -285,15 +285,14 @@ void event_loop_exit(struct event_context *ev, int code) */ int event_loop_once(struct event_context *ev) { - time_t t; fd_set r_fds, w_fds; struct fd_event *fe; struct loop_event *le; struct timed_event *te; int selrtn; - struct timeval tval; + struct timeval tval, t; - t = time(NULL); + t = timeval_current(); /* the loop events are called on each loop. Be careful to allow the event to remove itself */ @@ -310,7 +309,6 @@ int event_loop_once(struct event_context *ev) le = next; } - ZERO_STRUCT(tval); FD_ZERO(&r_fds); FD_ZERO(&w_fds); @@ -336,17 +334,12 @@ int event_loop_once(struct event_context *ev) /* start with a reasonable max timeout */ tval.tv_sec = 600; + tval.tv_usec = 0; /* work out the right timeout for all timed events */ for (te=ev->timed_events;te;te=te->next) { - int timeout = te->next_event - t; - if (timeout < 0) { - timeout = 0; - } - if (te->ref_count && - timeout < tval.tv_sec) { - tval.tv_sec = timeout; - } + struct timeval tv = timeval_diff(&te->next_event, &t); + tval = timeval_min(&tv, &tval); } /* only do a select() if there're fd_events @@ -368,7 +361,7 @@ int event_loop_once(struct event_context *ev) */ selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); - t = time(NULL); + t = timeval_current(); if (selrtn == -1 && errno == EBADF) { /* the socket is dead! this should never @@ -404,11 +397,11 @@ int event_loop_once(struct event_context *ev) if (te->ref_count == 0) { DLIST_REMOVE(ev->timed_events, te); talloc_free(te); - } else if (te->next_event <= t) { + } else if (timeval_compare(&te->next_event, &t) >= 0) { te->ref_count++; te->handler(ev, te, t); te->ref_count--; - if (te->next_event <= t) { + if (timeval_compare(&te->next_event, &t) >= 0) { /* the handler didn't set a time for the next event - remove the event */ event_remove_timed(ev, te); diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index f862b2d505..041554a7c0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -29,6 +29,9 @@ /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 +/* the number of microseconds to backoff in retrying to send a message */ +#define MESSAGING_BACKOFF 250000 + struct messaging_context { servid_t server_id; struct socket_context *sock; @@ -119,7 +122,7 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r handle IO for a single message */ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, - time_t t, uint16_t flags) + struct timeval t, uint16_t flags) { struct messaging_rec *rec = fde->private; struct messaging_context *msg = rec->msg; @@ -200,7 +203,7 @@ static int rec_destructor(void *ptr) handle a new incoming connection */ static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, - time_t t, uint16_t flags) + struct timeval t, uint16_t flags) { struct messaging_context *msg = fde->private; struct messaging_rec *rec; @@ -272,7 +275,7 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void handle IO for sending a message */ static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, - time_t t, uint16_t flags) + struct timeval t, uint16_t flags) { struct messaging_rec *rec = fde->private; NTSTATUS status; @@ -323,20 +326,34 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd } +/* + wrapper around socket_connect with raised privileges +*/ +static NTSTATUS try_connect(struct messaging_rec *rec) +{ + NTSTATUS status; + void *priv = root_privileges(); + status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + talloc_free(priv); + return status; +} + + /* when the servers listen queue is full we use this to backoff the message */ -static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, time_t t) +static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, + struct timeval t) { struct messaging_rec *rec = te->private; struct messaging_context *msg = rec->msg; NTSTATUS status; struct fd_event fde; - status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff again */ - te->next_event = t+1; + te->next_event = timeval_add(&t, 0, MESSAGING_BACKOFF); return; } @@ -356,7 +373,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve talloc_set_destructor(rec, rec_destructor); - messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE); + messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); } @@ -396,11 +413,11 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t rec->path = messaging_path(rec, server); - status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); + status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff on this message - the servers listen queue is full */ struct timed_event te; - te.next_event = time(NULL)+1; + te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF); te.handler = messaging_backoff_handler; te.private = rec; event_add_timed(msg->event.ev, &te); @@ -421,11 +438,25 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t talloc_set_destructor(rec, rec_destructor); - messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE); + messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); return NT_STATUS_OK; } +/* + Send a message to a particular server, with the message containing a single pointer +*/ +NTSTATUS messaging_send_ptr(struct messaging_context *msg, servid_t server, + uint32_t msg_type, void *ptr) +{ + DATA_BLOB blob; + + blob.data = (void *)&ptr; + blob.length = sizeof(void *); + + return messaging_send(msg, server, msg_type, &blob); +} + /* destroy the messaging context diff --git a/source4/lib/time.c b/source4/lib/time.c index cfceebf9cb..9e6da2cfa6 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -386,9 +386,144 @@ NTTIME nttime_from_string(const char *s) return strtoull(s, NULL, 0); } -int64_t usec_time_diff(struct timeval *larget, struct timeval *smallt) +/* + return (tv1 - tv2) in microseconds +*/ +int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2) +{ + int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; + return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); +} + + +/* + return a zero timeval +*/ +struct timeval timeval_zero(void) { - int64_t sec_diff = larget->tv_sec - smallt->tv_sec; - return (sec_diff * 1000000) + (int64_t)(larget->tv_usec - smallt->tv_usec); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; } +/* + return a timeval for the current time +*/ +struct timeval timeval_current(void) +{ + struct timeval tv; + GetTimeOfDay(&tv); + return tv; +} + +/* + return a timeval struct with the given elements +*/ +struct timeval timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + + +/* + return a timeval ofs microseconds after tv +*/ +struct timeval timeval_add(struct timeval *tv, uint32_t secs, uint32_t usecs) +{ + struct timeval tv2 = *tv; + const uint_t million = 1000000; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / million; + tv2.tv_usec = tv2.tv_usec % million; + return tv2; +} + +/* + return the sum of two timeval structures +*/ +struct timeval timeval_sum(struct timeval *tv1, struct timeval *tv2) +{ + return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); +} + +/* + return a timeval secs/usecs into the future +*/ +struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, secs, usecs); +} + +/* + compare two timeval structures. + Return 1 if tv2 > tv1 + Return 0 if tv2 == tv1 + Return -1 if tv2 < tv1 +*/ +int timeval_compare(struct timeval *tv1, struct timeval *tv2) +{ + if (tv2->tv_sec > tv1->tv_sec) return 1; + if (tv2->tv_sec < tv1->tv_sec) return -1; + if (tv2->tv_usec > tv1->tv_usec) return 1; + if (tv2->tv_usec < tv1->tv_usec) return -1; + return 0; +} + +/* + return True if a timer is in the past +*/ +BOOL timeval_expired(struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + if (tv2.tv_sec > tv->tv_sec) return True; + if (tv2.tv_sec < tv->tv_sec) return False; + return (tv2.tv_usec >= tv->tv_usec); +} + +/* + return the number of seconds elapsed since a given time +*/ +double timeval_elapsed(struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return (tv2.tv_sec - tv->tv_sec) + + (tv2.tv_usec - tv->tv_usec)*1.0e-6; +} + +/* + return the lesser of two timevals +*/ +struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) return *tv1; + if (tv1->tv_sec > tv2->tv_sec) return *tv2; + if (tv1->tv_usec < tv2->tv_usec) return *tv1; + return *tv2; +} + +/* + return the difference between two timevals as a timeval + if tv2 comes after tv1, then return a zero timeval + (this is *tv1 - *tv2) +*/ +struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2) +{ + struct timeval t; + if (timeval_compare(tv1, tv2) >= 0) { + return timeval_zero(); + } + t.tv_sec = tv1->tv_sec - tv2->tv_sec; + if (tv2->tv_usec > tv1->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv2->tv_usec - tv1->tv_usec); + } else { + t.tv_usec = tv1->tv_usec - tv2->tv_usec; + } + return t; +} diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c new file mode 100644 index 0000000000..c65f490aeb --- /dev/null +++ b/source4/lib/unix_privs.c @@ -0,0 +1,69 @@ +/* + Unix SMB/CIFS implementation. + + gain/lose root privileges + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/passwd.h" + +/* + there are times when smbd needs to temporarily gain root privileges + to do some operation. To do this you call root_privileges(), which + returns a talloc handle. To restore your previous privileges + talloc_free() this pointer. + + Note that this call is considered successful even if it does not + manage to gain too privileges, but it will call smb_abort() if it + fails to restore the privileges afterwards. The logic is that + failing to gain root access can be caught by whatever operation + needs to be run as root failing, but failing to lose the root + privileges is dangerous. + + This also means that this code is safe to be called from completely + unprivileged processes. +*/ + +struct saved_state { + uid_t uid; +}; + +static int privileges_destructor(void *ptr) +{ + struct saved_state *s = ptr; + if (geteuid() != s->uid && + seteuid(s->uid) != 0) { + smb_panic("Failed to restore privileges"); + } + return 0; +} + +void *root_privileges(void) +{ + struct saved_state *s; + s = talloc_p(NULL, struct saved_state); + if (!s) return NULL; + s->uid = geteuid(); + if (s->uid != 0) { + seteuid(0); + } + talloc_set_destructor(s, privileges_destructor); + return s; +} + -- cgit From f8f1d1b089d9228c1fba049cc9d38ef30030641e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 3 Nov 2004 14:51:49 +0000 Subject: r3510: fix build on SuSE 9.1 metze (This used to be commit 9cc1ab4eb2d5dd42ca8261c4781dd0168954c069) --- source4/lib/getsmbpass.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/getsmbpass.c b/source4/lib/getsmbpass.c index b6ae09b318..0d8f4a4b7e 100644 --- a/source4/lib/getsmbpass.c +++ b/source4/lib/getsmbpass.c @@ -19,6 +19,8 @@ Cambridge, MA 02139, USA. */ /* Modified to use with samba by Jeremy Allison, 8th July 1995. */ #include "includes.h" +#include "include/system/terminal.h" +#include "include/system/wait.h" #ifdef REPLACE_GETPASS @@ -40,16 +42,16 @@ static struct termio t; #define TCSANOW 0 #endif -static int tcgetattr(int fd, struct termio *t) +static int tcgetattr(int fd, struct termio *_t) { - return ioctl(fd, TCGETA, t); + return ioctl(fd, TCGETA, _t); } -static int tcsetattr(int fd, int flags, struct termio *t) +static int tcsetattr(int fd, int flags, struct termio *_t) { if(flags & TCSAFLUSH) ioctl(fd, TCFLSH, TCIOFLUSH); - return ioctl(fd, TCSETS, t); + return ioctl(fd, TCSETS, _t); } #elif !defined(TCSAFLUSH) @@ -65,14 +67,14 @@ static struct sgttyb t; #define TCSAFLUSH 1 #define TCSANOW 0 -static int tcgetattr(int fd, struct sgttyb *t) +static int tcgetattr(int fd, struct sgttyb *_t) { - return ioctl(fd, TIOCGETP, (char *)t); + return ioctl(fd, TIOCGETP, (char *)_t); } -static int tcsetattr(int fd, int flags, struct sgttyb *t) +static int tcsetattr(int fd, int flags, struct sgttyb *_t) { - return ioctl(fd, TIOCSETP, (char *)t); + return ioctl(fd, TIOCSETP, (char *)_t); } #else /* POSIX TERMIO HANDLING */ -- cgit From 6d3c74a67b935f348777feb3fac7653a9c4277a8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Nov 2004 20:32:28 +0000 Subject: r3513: Add (the infrastructure for) DCOM support. Contents: - Support for sending over the object UUID in DCERPC calls - Simple torture test for the DCOM "Simple" object - Generate extra argument for "object" interfaces in pidl - Some stubs for common DCOM functions (This used to be commit c052f2e1edd816206d8974af3140cec7ef97a70c) --- source4/lib/dcom/common/dcom.h | 30 ++++++++++++++++++++++ source4/lib/dcom/common/main.c | 57 ++++++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 source4/lib/dcom/common/dcom.h (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h new file mode 100644 index 0000000000..871bead376 --- /dev/null +++ b/source4/lib/dcom/common/dcom.h @@ -0,0 +1,30 @@ +/* + Unix SMB/CIFS implementation. + DCOM standard objects + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _DCOM_H /* _DCOM_H */ +#define _DCOM_H + +struct dcom_interface +{ + struct dcerpc_pipe *pipe; + struct GUID ipid; /* Appears in object field */ +}; + +#endif /* _DCOM_H */ diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index a490c32c14..f567b639e5 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -34,9 +34,39 @@ static WERROR dcom_tower_from_oxid(TALLOC_CTX *mem_ctx, HYPER_T oxid, struct epm return WERR_NOT_SUPPORTED; } -static WERROR dcom_get_class_object (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) +static WERROR dcom_create_instance (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) +{ + return WERR_NOT_SUPPORTED; +} + +static uint32 IUnknown_AddRef(void) +{ + /* FIXME: Tell local server we're adding a reference to this interface on this object. Local server can then call RemAddRef() if necessary */ + return 0; +} + +static uint32 IUnknown_Release(void) +{ + /* FIXME: Tell local server we're releasing a reference to this interface on this object. Local server can then call RemRelease() if necessary */ + return 0; +} + +static WERROR IUnknown_QueryInterface(struct GUID *riid, void **data) +{ + /* FIXME: Ask local server for interface pointer. Local server can then + * call RemQueryInterface if necessary */ + return WERR_NOT_SUPPORTED; +} + +WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip) +{ + return WERR_NOT_SUPPORTED; +} + +WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface **ip) { struct RemoteActivation r; + struct dcerpc_pipe *p = NULL; /* FIXME */ NTSTATUS status; struct GUID iids[2]; uint16 protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }; @@ -45,7 +75,7 @@ static WERROR dcom_get_class_object (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.this.version.MajorVersion = 5; r.in.this.version.MinorVersion = 1; uuid_generate_random(&r.in.this.cid); - r.in.Clsid = clsid; + r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; r.in.num_protseqs = 3; r.in.protseq = protseq; @@ -64,29 +94,6 @@ static WERROR dcom_get_class_object (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - return WERR_OK; -} -static WERROR dcom_create_instance (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) -{ - return WERR_NOT_SUPPORTED; -} - -static uint32 IUnknown_AddRef(void) -{ - /* FIXME: Tell local server we're adding a reference to this interface on this object. Local server can then call RemAddRef() if necessary */ - return 0; -} - -static uint32 IUnknown_Release(void) -{ - /* FIXME: Tell local server we're releasing a reference to this interface on this object. Local server can then call RemRelease() if necessary */ - return 0; -} - -static WERROR IUnknown_QueryInterface(struct GUID *riid, void **data) -{ - /* FIXME: Ask local server for interface pointer. Local server can then - * call RemQueryInterface if necessary */ return WERR_NOT_SUPPORTED; } -- cgit From 9a65c54c72cb5cbbe3d57df32193568850266b3b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Nov 2004 21:44:18 +0000 Subject: r3514: Allow specification of username, password and domain and try to set up connection. (This used to be commit 8076db7a1f9e11c725e481a0bda4dbc354c9612f) --- source4/lib/dcom/common/dcom.h | 4 ++ source4/lib/dcom/common/main.c | 120 +++++++++++++++++++++++++++++++---------- 2 files changed, 97 insertions(+), 27 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 871bead376..091200d4c1 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -21,6 +21,10 @@ #ifndef _DCOM_H /* _DCOM_H */ #define _DCOM_H +struct IUnknown_AddRef; +struct IUnknown_Release; +struct IUnknown_QueryInterface; + struct dcom_interface { struct dcerpc_pipe *pipe; diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index f567b639e5..3c95caebe0 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -22,54 +22,121 @@ #include "librpc/gen_ndr/ndr_epmapper.h" #include "librpc/gen_ndr/ndr_remact.h" -static WERROR dcom_binding_from_oxid(TALLOC_CTX *mem_ctx, HYPER_T oxid, struct dcerpc_binding *bd) -{ - /* FIXME */ - return WERR_NOT_SUPPORTED; -} +#define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } -static WERROR dcom_tower_from_oxid(TALLOC_CTX *mem_ctx, HYPER_T oxid, struct epm_tower *bd) +static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const char *domain, const char *user, const char *pass) { - /* FIXME */ - return WERR_NOT_SUPPORTED; + struct dcerpc_binding bd; + enum dcerpc_transport_t available_transports[] = { NCACN_IP_TCP, NCACN_NP }; + int i; + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc_init("dcom_connect"); + + /* Allow server name to contain a binding string */ + if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { + status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + talloc_destroy(mem_ctx); + return status; + } + talloc_destroy(mem_ctx); + + ZERO_STRUCT(bd); + bd.host = server; + + if (server == NULL) { + bd.transport = NCALRPC; + return dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + } + + for (i = 0; i < ARRAY_SIZE(available_transports); i++) + { + bd.transport = available_transports[i]; + + status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + + if (NT_STATUS_IS_OK(status)) { + return status; + } + } + + return status; } -static WERROR dcom_create_instance (struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct GUID clsid) +static WERROR dcom_connect_oxid(TALLOC_CTX *mem_ctx, struct dcerpc_pipe **p, HYPER_T oxid) { + /* FIXME */ return WERR_NOT_SUPPORTED; } -static uint32 IUnknown_AddRef(void) +NTSTATUS dcerpc_IUnknown_AddRef(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *r) { /* FIXME: Tell local server we're adding a reference to this interface on this object. Local server can then call RemAddRef() if necessary */ - return 0; + return NT_STATUS_NOT_SUPPORTED; } -static uint32 IUnknown_Release(void) +NTSTATUS dcerpc_IUnknown_Release(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_Release *r) { /* FIXME: Tell local server we're releasing a reference to this interface on this object. Local server can then call RemRelease() if necessary */ - return 0; + return NT_STATUS_NOT_SUPPORTED; } -static WERROR IUnknown_QueryInterface(struct GUID *riid, void **data) +NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *r) { /* FIXME: Ask local server for interface pointer. Local server can then * call RemQueryInterface if necessary */ - return WERR_NOT_SUPPORTED; + return NT_STATUS_NOT_SUPPORTED; } -WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip) +WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, const char *domain, const char *user, const char *pass) { - return WERR_NOT_SUPPORTED; + struct RemoteActivation r; + struct dcerpc_pipe *p; + NTSTATUS status; + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + + status = dcom_connect(&p, server, domain, user, pass); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); + return ntstatus_to_werror(status); + } + + ZERO_STRUCT(r.in); + r.in.this.version.MajorVersion = 5; + r.in.this.version.MinorVersion = 1; + uuid_generate_random(&r.in.this.cid); + r.in.Clsid = *clsid; + r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; + r.in.num_protseqs = ARRAY_SIZE(protseq); + r.in.protseq = protseq; + r.in.Interfaces = num_ifaces; + r.in.pIIDs = iid; + + status = dcerpc_RemoteActivation(p, mem_ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } + if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } + if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } + + /* FIXME: Fill ip */ + return WERR_OK; } -WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface **ip) +WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface **ip, const char *domain, const char *user, const char *pass) { struct RemoteActivation r; - struct dcerpc_pipe *p = NULL; /* FIXME */ + struct dcerpc_pipe *p; NTSTATUS status; - struct GUID iids[2]; - uint16 protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }; + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + + status = dcom_connect(&p, server, domain, user, pass); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); + return ntstatus_to_werror(status); + } ZERO_STRUCT(r.in); r.in.this.version.MajorVersion = 5; @@ -77,16 +144,15 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char uuid_generate_random(&r.in.this.cid); r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; - r.in.num_protseqs = 3; + r.in.num_protseqs = ARRAY_SIZE(protseq); r.in.protseq = protseq; r.in.Interfaces = 1; - GUID_from_string(DCERPC_IUNKNOWN_UUID, &iids[0]); - r.in.pIIDs = iids; + r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; status = dcerpc_RemoteActivation(p, mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { - fprintf(stderr, "RemoteActivation: %s\n", nt_errstr(status)); + DEBUG(1, ("Error while running RemoteActivation - %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } @@ -94,6 +160,6 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - - return WERR_NOT_SUPPORTED; + /* FIXME: Fill ip */ + return WERR_OK; } -- cgit From 695677f4bb078291c683931d5017f339811abf90 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 4 Nov 2004 01:09:43 +0000 Subject: r3515: Fix RemoteActivation correctly this time (-: Thanks to tridge for some help on this one! (This used to be commit 1104667190aa144e2c7d79ece9a55502b98d0351) --- source4/lib/dcom/common/dcom.h | 2 +- source4/lib/dcom/common/main.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 091200d4c1..d97364a125 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -28,7 +28,7 @@ struct IUnknown_QueryInterface; struct dcom_interface { struct dcerpc_pipe *pipe; - struct GUID ipid; /* Appears in object field */ + struct OBJREF object; }; #endif /* _DCOM_H */ diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 3c95caebe0..5bc8e5c6d4 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -90,6 +90,7 @@ NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcerpc_pipe *p, struct GUID *o, T WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, const char *domain, const char *user, const char *pass) { struct RemoteActivation r; + int i; struct dcerpc_pipe *p; NTSTATUS status; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; @@ -110,7 +111,8 @@ WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *s r.in.protseq = protseq; r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; - + r.out.ifaces = talloc_array_p(mem_ctx, struct pMInterfacePointer, num_ifaces); + status = dcerpc_RemoteActivation(p, mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status))); @@ -121,15 +123,21 @@ WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *s if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - /* FIXME: Fill ip */ + *ip = talloc_array_p(mem_ctx, struct dcom_interface, num_ifaces); + for (i = 0; i < num_ifaces; i++) { + (*ip)[i].object = r.out.ifaces[i].p->obj; + (*ip)[i].pipe = NULL; /* FIXME */ + } + return WERR_OK; } -WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface **ip, const char *domain, const char *user, const char *pass) +WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *ip, const char *domain, const char *user, const char *pass) { struct RemoteActivation r; struct dcerpc_pipe *p; NTSTATUS status; + struct pMInterfacePointer pm; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; status = dcom_connect(&p, server, domain, user, pass); @@ -149,6 +157,7 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char r.in.Interfaces = 1; r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; + r.out.ifaces = ± status = dcerpc_RemoteActivation(p, mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -160,6 +169,8 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - /* FIXME: Fill ip */ + ip->pipe = NULL; /* FIXME */ + ip->object = pm.p->obj; + return WERR_OK; } -- cgit From a9c00f35f9d7d59b36c286abb2e72613b32ba775 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Nov 2004 02:19:25 +0000 Subject: r3518: fixed some includes to be consistent. - use #include for operating system includes - use includes relative to include/ for things like system/wait.h also fixed the thread backend to work somewhat. To fix it properly we need to do this: - add a configure test for support for thread local storage (the __thread keyword) - refuse to do pthreads if tls doesn't work - refuse to do pthreads if seteuid() affects process instead of thread - defined THREAD_LOCAL as __thread when WITH_PTHREADS - add THREAD_LOCAL to all the global data structures that should be thread local (there are quite a few) right now the thread backend falls over when you hit it with several connections at once, due to the lack of __thread on some critical structures. (This used to be commit 0dc1deabd0b53bc7a6f6cee2ed99e2cbbe422262) --- source4/lib/getsmbpass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/getsmbpass.c b/source4/lib/getsmbpass.c index 0d8f4a4b7e..4ffcde8dfd 100644 --- a/source4/lib/getsmbpass.c +++ b/source4/lib/getsmbpass.c @@ -19,8 +19,8 @@ Cambridge, MA 02139, USA. */ /* Modified to use with samba by Jeremy Allison, 8th July 1995. */ #include "includes.h" -#include "include/system/terminal.h" -#include "include/system/wait.h" +#include "system/terminal.h" +#include "system/wait.h" #ifdef REPLACE_GETPASS -- cgit From 92cac50045398b2d45ac45dd0d53eed3c41d4d00 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Nov 2004 10:16:53 +0000 Subject: r3527: I hate compiler warnings... metze (This used to be commit d264aacfd5b96c1fdb57fd1b6206835a7526eb3c) --- source4/lib/dcom/common/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 5bc8e5c6d4..7a8def25c5 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -62,11 +62,13 @@ static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const c return status; } +#if 0 static WERROR dcom_connect_oxid(TALLOC_CTX *mem_ctx, struct dcerpc_pipe **p, HYPER_T oxid) { /* FIXME */ return WERR_NOT_SUPPORTED; } +#endif NTSTATUS dcerpc_IUnknown_AddRef(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *r) { -- cgit From e8010adffe44f1ad0d82c7b5c7d5fe2cf7d53afd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 07:23:06 +0000 Subject: r3543: fixed some #include lines to make them more consistent, and fixed conditional compilation of xattr client code (This used to be commit 321fb06a627f4deae649ab014bc881721d37b3dd) --- source4/lib/registry/tools/regpatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 38eabb60a9..4ad7e162a3 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -59,7 +59,7 @@ #define CMD_KEY 1 #define CMD_VAL 2 -#include +#include "includes.h" typedef struct val_spec_list { struct val_spec_list *next; -- cgit From 3a7eff64f27158dc428d3f881c4dc1e613ac6665 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 09:19:42 +0000 Subject: r3546: including includes.h twice causes gcc 3.4 to crash with pch (This used to be commit 51c1c2af687ed351d12e6d933659d94f5925728c) --- source4/lib/registry/tools/regpatch.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 4ad7e162a3..d70d7b8457 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -59,8 +59,6 @@ #define CMD_KEY 1 #define CMD_VAL 2 -#include "includes.h" - typedef struct val_spec_list { struct val_spec_list *next; char *name; -- cgit From 2b4e716f7aec49469b2b523c86762c8d4bacb4d1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 10:53:20 +0000 Subject: r3548: removed extra net/if.h include (This used to be commit 1551f211d983398a4f27eaeebdd4bf05f8beb330) --- source4/lib/netif/netif.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/netif.c b/source4/lib/netif/netif.c index 729aeedbe3..9fe4d21bc9 100644 --- a/source4/lib/netif/netif.c +++ b/source4/lib/netif/netif.c @@ -40,7 +40,6 @@ #include #include #include -#include #ifndef AUTOCONF_TEST #include "lib/netif/netif.h" -- cgit From 438a54b8b4df147405bba0b3b55a895d81a27b8a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 5 Nov 2004 12:20:27 +0000 Subject: r3553: Allow talloc_reference to take a NULL pointer for the "ptr" argument. This allows potentially NULL pointers to be referenced, without an if () for every use. (previously, it would segfault). Update doco, and allow talloc_unlink to match. Andrew Bartlett (This used to be commit 59757c7f9d0e08e3acacfb3116f6205057d5b119) --- source4/lib/talloc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 131edfcb81..239958258b 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -222,9 +222,13 @@ static int talloc_reference_destructor(void *ptr) */ void *talloc_reference(const void *context, const void *ptr) { - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc; struct talloc_reference_handle *handle; + if (ptr == NULL) return NULL; + + tc = talloc_chunk_from_ptr(ptr); handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); + if (handle == NULL) return NULL; /* note that we hang the destructor off the handle, not the @@ -273,6 +277,10 @@ int talloc_unlink(const void *context, void *ptr) struct talloc_chunk *tc_p, *new_p; void *new_parent; + if (ptr == NULL) { + return -1; + } + if (context == NULL) { context = null_context; } -- cgit From e1f38d81383c4adcb28b8e6e4bc0b3c7600277d4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 03:44:16 +0000 Subject: r3571: rough guesses at what abartlet really wanted to do in his last commit (which I suspect was missing some pieces) this at least fixes the build so i can keep going on pvfs. Please review/fix Andrew. (This used to be commit bffd18d09df04c1e492ef12f744ff4b6c561d53c) --- source4/lib/data_blob.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 7803179d39..d2147be6b2 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -61,6 +61,18 @@ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t leng return ret; } + +/******************************************************************* + construct a data blob which is a reference to another blob, in +the given mem context +*******************************************************************/ +DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + DATA_BLOB ret = *blob; + ret.data = talloc_reference(mem_ctx, ret.data); + return ret; +} + /******************************************************************* construct a zero data blob, using supplied TALLOC_CTX. use this sparingly as it initialises data - better to initialise -- cgit From 4c06ac06a13eaff5b314ad97cce824d615c06f9a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 6 Nov 2004 05:40:34 +0000 Subject: r3572: Thanks to tridge for his patience with my build breakage. This concludes the proper fixes. Andrew Bartlett (This used to be commit c1d025793f2994c8f1cab304c3394ab186654071) --- source4/lib/data_blob.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index d2147be6b2..c5f15f1271 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -63,13 +63,18 @@ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t leng /******************************************************************* - construct a data blob which is a reference to another blob, in -the given mem context + reference a data blob, to the supplied TALLOC_CTX. + Returns a NULL DATA_BLOB on failure *******************************************************************/ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) { DATA_BLOB ret = *blob; - ret.data = talloc_reference(mem_ctx, ret.data); + + ret.data = talloc_reference(mem_ctx, blob->data); + + if (!ret.data) { + return data_blob(NULL, 0); + } return ret; } -- cgit From 800212bc12a90a6c32d68c6a01edc3142bd93369 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 12:10:57 +0000 Subject: r3578: a couple of include changes that should help with FreeBSD (This used to be commit d8c4a660a08d7be8b69e4e5458bdcc1cb492506e) --- source4/lib/netif/netif.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/netif/netif.c b/source4/lib/netif/netif.c index 9fe4d21bc9..2a87a7a610 100644 --- a/source4/lib/netif/netif.c +++ b/source4/lib/netif/netif.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include -- cgit From 481bba9e7f6ebfef11c7c7d778a1b465886abfa9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 12:14:14 +0000 Subject: r3579: with the gcc warning flag from abartlet we don't need sys_strftime() (This used to be commit 041f77b6a19c98599fe18d2eb4e86db00b40014e) --- source4/lib/time.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 9e6da2cfa6..e1f1395fea 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -311,16 +311,6 @@ char *ldap_timestring(TALLOC_CTX *mem_ctx, time_t t) tm->tm_sec); } -/* - a hack to move the stupid gcc strftime warning to one place - see manual page -*/ -#ifdef HAVE_STRFTIME -size_t sys_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) -{ - return strftime(s, max, fmt, tm); -} -#endif - /**************************************************************************** Return the date and time as a string ****************************************************************************/ @@ -342,7 +332,7 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) in the gcc warning, not a bug in this code. See a recent strftime() manual page for details. */ - sys_strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); TimeBuf = talloc_strdup(mem_ctx, tempTime); #else TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); -- cgit From 81f6d0b0150672ab7546f667ab00f58e9152d782 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 6 Nov 2004 20:06:56 +0000 Subject: r3581: fix some signedness warnings with gcc-4.0 (there some callers to be fixed later) metze (This used to be commit dfb062c63c5445023055045ba40979eb58f1740e) --- source4/lib/util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index d8e9cb50f9..1202cb3aae 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -565,9 +565,8 @@ static void print_asc(int level, const uint8_t *buf,int len) DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.')); } -void dump_data(int level, const char *buf1,int len) +void dump_data(int level, const uint8_t *buf,int len) { - const uint8_t *buf = (const uint8_t *)buf1; int i=0; if (len<=0) return; -- cgit From 71db46ea665606384f2be1be708c74c97c9adfb2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 6 Nov 2004 23:23:15 +0000 Subject: r3586: Fix some of the issues with the module init functions. Both subsystems and modules can now have init functions, which can be specified in .mk files (INIT_FUNCTION = ...) The build system will define : - SUBSYSTEM_init_static_modules that calls the init functions of all statically compiled modules. Failing to load will generate an error which is not fatal - BINARY_init_subsystems that calls the init functions (if defined) for the subsystems the binary depends on This removes the hack with the "static bool Initialised = " and the "lazy_init" functions (This used to be commit 7a8244761bfdfdfb48f8264d76951ebdfbf7bd8a) --- source4/lib/iconv.c | 4 +++- source4/lib/ldb/config.m4 | 4 ++-- source4/lib/registry/common/reg_interface.c | 17 +++++------------ source4/lib/registry/config.mk | 7 +++++++ source4/lib/registry/tools/regdiff.c | 1 + source4/lib/registry/tools/regpatch.c | 1 + source4/lib/registry/tools/regshell.c | 1 + source4/lib/registry/tools/regtree.c | 1 + source4/lib/socket/socket_ipv4.c | 5 ----- source4/lib/socket/socket_ipv6.c | 5 ----- source4/lib/socket/socket_unix.c | 5 ----- 11 files changed, 21 insertions(+), 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index a08e0ee69a..085ec0ec2f 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -100,7 +100,9 @@ static void lazy_initialize_iconv(void) if (!initialized) { initialized = True; register_subsystem("charset", charset_register_backend); - + + charset_init_static_modules; + for(i = 0; builtin_functions[i].name; i++) register_backend("charset", &builtin_functions[i]); } diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index c48e9e161b..a4e7a0dba9 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -2,12 +2,12 @@ if test x"$with_ldap_support" = x"yes"; then SMB_MODULE_DEFAULT(libldb_ldap,STATIC) fi +SMB_SUBSYSTEM_MK(LIBLDB,lib/ldb/config.mk) + SMB_MODULE_MK(libldb_ldap,LIBLDB,NOT,lib/ldb/config.mk) SMB_MODULE_MK(libldb_tdb,LIBLDB,STATIC,lib/ldb/config.mk) -SMB_SUBSYSTEM_MK(LIBLDB,lib/ldb/config.mk) - if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libldb,YES) fi diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index b2d659258d..0399fc26aa 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -59,24 +59,19 @@ NTSTATUS registry_register(const void *_function) return NT_STATUS_OK; } -static BOOL registry_init(void) +NTSTATUS registry_init(void) { - static BOOL initialised; NTSTATUS status; - if(initialised) { - return True; - } - status = register_subsystem("registry", registry_register); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status))); - return False; + return status; } - initialised = True; - static_init_registry; - return True; + registry_init_static_modules; + + return NT_STATUS_OK; } /* Find a backend in the list of available backends */ @@ -84,8 +79,6 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { struct reg_init_function_entry *entry; - if(registry_init() == False) return NULL; - entry = backends; while(entry) { diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 659e705d5d..dacd6d5295 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -3,6 +3,7 @@ ################################################ # Start MODULE registry_nt4 [MODULE::registry_nt4] +INIT_FUNCTION = registry_nt4_init INIT_OBJ_FILES = \ lib/registry/reg_backend_nt4/reg_backend_nt4.o # End MODULE registry_nt4 @@ -11,6 +12,7 @@ INIT_OBJ_FILES = \ ################################################ # Start MODULE registry_w95 [MODULE::registry_w95] +INIT_FUNCTION = registry_w95_init INIT_OBJ_FILES = \ lib/registry/reg_backend_w95/reg_backend_w95.o # End MODULE registry_w95 @@ -19,6 +21,7 @@ INIT_OBJ_FILES = \ ################################################ # Start MODULE registry_dir [MODULE::registry_dir] +INIT_FUNCTION = registry_dir_init INIT_OBJ_FILES = \ lib/registry/reg_backend_dir/reg_backend_dir.o # End MODULE registry_dir @@ -27,6 +30,7 @@ INIT_OBJ_FILES = \ ################################################ # Start MODULE registry_rpc [MODULE::registry_rpc] +INIT_FUNCTION = registry_rpc_init INIT_OBJ_FILES = \ lib/registry/reg_backend_rpc/reg_backend_rpc.o REQUIRED_SUBSYSTEMS = \ @@ -37,6 +41,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start MODULE registry_gconf [MODULE::registry_gconf] +INIT_FUNCTION = registry_gconf_init INIT_OBJ_FILES = \ lib/registry/reg_backend_gconf/reg_backend_gconf.o REQUIRED_LIBRARIES = \ @@ -47,6 +52,7 @@ REQUIRED_LIBRARIES = \ ################################################ # Start MODULE registry_ldb [MODULE::registry_ldb] +INIT_FUNCTION = registry_ldb_init INIT_OBJ_FILES = \ lib/registry/reg_backend_ldb/reg_backend_ldb.o REQUIRED_SUBSYSTEMS = \ @@ -57,6 +63,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start SUBSYSTEM REGISTRY [SUBSYSTEM::REGISTRY] +INIT_FUNCTION = registry_init INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 80f4a5c49f..55c8f1e72f 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -131,6 +131,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, POPT_TABLEEND }; + regdiff_init_subsystems; if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index d70d7b8457..a8b2f83ee1 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -771,6 +771,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd POPT_TABLEEND }; + regpatch_init_subsystems; if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index d705a0b802..8d044f6fa2 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -356,6 +356,7 @@ static char **reg_completion(const char *text, int start, int end) POPT_TABLEEND }; + regshell_init_subsystems; if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index a8225c026d..ced7a00f94 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -88,6 +88,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) POPT_TABLEEND }; + regtree_init_subsystems; if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index eebbd61219..88570512a4 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -336,8 +336,3 @@ const struct socket_ops *socket_ipv4_ops(void) { return &ipv4_tcp_ops; } - -NTSTATUS socket_ipv4_init(void) -{ - return NT_STATUS_OK; -} diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index c8683446ec..1685f17572 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -354,8 +354,3 @@ const struct socket_ops *socket_ipv6_ops(void) { return &ipv6_tcp_ops; } - -NTSTATUS socket_ipv6_init(void) -{ - return NT_STATUS_OK; -} diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 0ba4797219..e35453e6e0 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -273,8 +273,3 @@ const struct socket_ops *socket_unixdom_ops(void) { return &unixdom_ops; } - -NTSTATUS socket_unixdom_init(void) -{ - return NT_STATUS_OK; -} -- cgit From 396b5bdafe781bb7313a24ade4a94d6821628aab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 7 Nov 2004 10:34:35 +0000 Subject: r3598: hopefully fix the build on stratos (This used to be commit e6e8a9c7f014ddf7c92476a6713582303bb944a0) --- source4/lib/charcnv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 3c27d59664..bfb1081474 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/iconv.h" /** * @file -- cgit From 485df40bf96abbd80d69ff2a9fdca86516a4eae7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 7 Nov 2004 16:47:46 +0000 Subject: r3601: Lots of smaller DCOM updates and fixes. Adds oxid tables, proper use of contexts. (This used to be commit 93eb3cd99c4fb065a69eabcead0c33804259c976) --- source4/lib/dcom/common/dcom.h | 14 ++- source4/lib/dcom/common/main.c | 207 +++++++++++++++++++++++++++++++++++------ 2 files changed, 189 insertions(+), 32 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index d97364a125..06407cf2f4 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -25,10 +25,22 @@ struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; +struct dcom_oxid_mapping; + +struct dcom_context +{ + struct dcom_oxid_mapping *oxids; + const char *domain; + const char *user; + const char *password; +}; + struct dcom_interface { + struct dcom_context *ctx; struct dcerpc_pipe *pipe; - struct OBJREF object; + struct OBJREF *objref; + uint32_t private_references; }; #endif /* _DCOM_H */ diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 7a8def25c5..a2650e3446 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -19,12 +19,15 @@ */ #include "includes.h" +#include "dlinklist.h" #include "librpc/gen_ndr/ndr_epmapper.h" #include "librpc/gen_ndr/ndr_remact.h" +#include "librpc/gen_ndr/ndr_oxidresolver.h" +#include "librpc/gen_ndr/ndr_dcom.h" #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } -static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const char *domain, const char *user, const char *pass) +static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe **p, const char *server) { struct dcerpc_binding bd; enum dcerpc_transport_t available_transports[] = { NCACN_IP_TCP, NCACN_NP }; @@ -34,7 +37,7 @@ static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const c /* Allow server name to contain a binding string */ if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { - status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); talloc_destroy(mem_ctx); return status; } @@ -45,14 +48,14 @@ static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const c if (server == NULL) { bd.transport = NCALRPC; - return dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + return dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); } for (i = 0; i < ARRAY_SIZE(available_transports); i++) { bd.transport = available_transports[i]; - status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, domain, user, pass); + status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); if (NT_STATUS_IS_OK(status)) { return status; @@ -62,34 +65,73 @@ static NTSTATUS dcom_connect(struct dcerpc_pipe **p, const char *server, const c return status; } -#if 0 -static WERROR dcom_connect_oxid(TALLOC_CTX *mem_ctx, struct dcerpc_pipe **p, HYPER_T oxid) +static NTSTATUS dcom_connect_STRINGBINDINGARRAY(struct dcom_context *ctx, struct dcerpc_pipe **p, DATA_BLOB *stringbindingarray) { - /* FIXME */ - return WERR_NOT_SUPPORTED; + return NT_STATUS_NOT_SUPPORTED; } -#endif -NTSTATUS dcerpc_IUnknown_AddRef(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *r) +static NTSTATUS dcom_connect_DUALSTRINGBINDINGARRAY(struct dcom_context *ctx, struct dcerpc_pipe **p, struct DUALSTRINGARRAY *array) { - /* FIXME: Tell local server we're adding a reference to this interface on this object. Local server can then call RemAddRef() if necessary */ return NT_STATUS_NOT_SUPPORTED; } -NTSTATUS dcerpc_IUnknown_Release(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_Release *r) +NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) { - /* FIXME: Tell local server we're releasing a reference to this interface on this object. Local server can then call RemRelease() if necessary */ - return NT_STATUS_NOT_SUPPORTED; + struct RemAddRef r; + struct REMINTERFACEREF ref; + + /* This is rather inefficient, but we'll patch it up later */ + r.in.cInterfaceRefs = 1; + r.in.InterfaceRefs = &ref; + + return dcerpc_RemAddRef(p, mem_ctx, &r); +} + +NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_Release *rr) +{ + struct RemRelease r; + struct REMINTERFACEREF ref; + + p->private_references--; + + /* Only do the remote version of this call when all local references have + * been released */ + if (p->private_references == 0) { + NTSTATUS status; + r.in.cInterfaceRefs = 1; + r.in.InterfaceRefs = &ref; + + status = dcerpc_RemRelease(p, mem_ctx, &r); + + if (NT_STATUS_IS_OK(status)) { + talloc_destroy(p); + } + + return status; + } + + return NT_STATUS_OK; } -NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcerpc_pipe *p, struct GUID *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *r) +NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *rr) { /* FIXME: Ask local server for interface pointer. Local server can then * call RemQueryInterface if necessary */ return NT_STATUS_NOT_SUPPORTED; } -WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, const char *domain, const char *user, const char *pass) +WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user, const char *pass) +{ + *ctx = talloc_p(NULL, struct dcom_context); + (*ctx)->oxids = NULL; + (*ctx)->domain = talloc_strdup(*ctx, domain); + (*ctx)->user = talloc_strdup(*ctx, user); + (*ctx)->password = talloc_strdup(*ctx, pass); + + return WERR_OK; +} + +WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, WERROR *results) { struct RemoteActivation r; int i; @@ -97,7 +139,7 @@ WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *s NTSTATUS status; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - status = dcom_connect(&p, server, domain, user, pass); + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); return ntstatus_to_werror(status); @@ -113,28 +155,35 @@ WERROR dcom_create_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *s r.in.protseq = protseq; r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; - r.out.ifaces = talloc_array_p(mem_ctx, struct pMInterfacePointer, num_ifaces); + r.out.ifaces = talloc_array_p(ctx, struct pMInterfacePointer, num_ifaces); - status = dcerpc_RemoteActivation(p, mem_ctx, &r); + status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } - if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } - if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } - if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } + if(!W_ERROR_IS_OK(r.out.result)) { + return r.out.result; + } + + if(!W_ERROR_IS_OK(r.out.hr)) { + return r.out.hr; + } - *ip = talloc_array_p(mem_ctx, struct dcom_interface, num_ifaces); + *ip = talloc_array_p(ctx, struct dcom_interface, num_ifaces); for (i = 0; i < num_ifaces; i++) { - (*ip)[i].object = r.out.ifaces[i].p->obj; - (*ip)[i].pipe = NULL; /* FIXME */ + results[i] = r.out.results[i]; + (*ip)[i].private_references = 1; + (*ip)[i].objref = &r.out.ifaces[i].p->obj; + (*ip)[i].pipe = NULL; + (*ip)[i].ctx = ctx; } return WERR_OK; } -WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *ip, const char *domain, const char *user, const char *pass) +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *ip) { struct RemoteActivation r; struct dcerpc_pipe *p; @@ -142,7 +191,7 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char struct pMInterfacePointer pm; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - status = dcom_connect(&p, server, domain, user, pass); + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); return ntstatus_to_werror(status); @@ -161,7 +210,7 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char r.in.Mode = MODE_GET_CLASS_OBJECT; r.out.ifaces = ± - status = dcerpc_RemoteActivation(p, mem_ctx, &r); + status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while running RemoteActivation - %s\n", nt_errstr(status))); return ntstatus_to_werror(status); @@ -170,9 +219,105 @@ WERROR dcom_get_class_object(TALLOC_CTX *mem_ctx, struct GUID *clsid, const char if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - - ip->pipe = NULL; /* FIXME */ - ip->object = pm.p->obj; + + ip->private_references = 1; + ip->pipe = NULL; + ip->objref = &pm.p->obj; + ip->ctx = ctx; return WERR_OK; } + +struct dcom_oxid_mapping { + struct dcom_oxid_mapping *prev, *next; + struct DUALSTRINGARRAY bindings; + HYPER_T oxid; + struct dcerpc_pipe *pipe; +}; + +static struct dcom_oxid_mapping *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +{ + struct dcom_oxid_mapping *m; + + for (m = ctx->oxids;m;m = m->next) { + if (m->oxid == oxid) { + return m; + } + } + + return NULL; +} + +NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) +{ + struct dcom_oxid_mapping *m; + HYPER_T oxid; + NTSTATUS status; + + SMB_ASSERT(iface->objref->signature == OBJREF_SIGNATURE); + + if (iface->objref->flags & OBJREF_HANDLER) { + DEBUG(0, ("dcom_get_pipe: OBJREF_HANDLER not supported!\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + if (iface->objref->flags & OBJREF_CUSTOM) { + DEBUG(0, ("dcom_get_pipe: OBJREF_CUSTOM not supported!\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + DEBUG(1, ("DCOM: Connecting to %s\n", GUID_string(NULL, &iface->objref->iid))); + + oxid = iface->objref->u_objref.u_standard.std.oxid; + + m = oxid_mapping_by_oxid(iface->ctx, oxid); + + /* Add OXID mapping if none present yet */ + if (!m) { + struct dcerpc_pipe *po; + struct ResolveOxid r; + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + + DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", oxid)); + + m = talloc_zero_p(iface->ctx, struct dcom_oxid_mapping); + m->oxid = oxid; + + status = dcom_connect_STRINGBINDINGARRAY(iface->ctx, &po, &iface->objref->u_objref.u_standard.saResAddr); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); + return status; + } + + r.in.pOxid = oxid; + r.in.cRequestedProtseqs = ARRAY_SIZE(protseq); + r.in.arRequestedProtseqs = protseq; + r.out.ppdsaOxidBindings = &m->bindings; + + status = dcerpc_ResolveOxid(po, iface->ctx, &r); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error while resolving OXID: %s\n", nt_errstr(status))); + return status; + } + + dcerpc_pipe_close(po); + + DLIST_ADD(iface->ctx->oxids, m); + } + + if (m->pipe) { + *p = m->pipe; + /* FIXME: Switch to correct IID using an alter context call */ + return NT_STATUS_OK; + } + + status = dcom_connect_DUALSTRINGBINDINGARRAY(iface->ctx, &m->pipe, &m->bindings); + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + *p = m->pipe; + return NT_STATUS_OK; +} -- cgit From f2d715cd858833e87a57d99ff6716e6af045558a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 7 Nov 2004 21:30:59 +0000 Subject: r3606: More DCOM fixes: - OXID tables work now. IOXIDResolver is used if there is used for getting a STRINGBINDING if none is known yet - Add custom dissectors for STRINGARRAY and DUALSTRINGARRAY. If there's a way to get rid of these later on (by supporting them thru pidl somehow), I'd be happy to use that instead of doing it manually. I can now get to the point where we have created an object and are connected to it. The only thing left to do is being able to set the Object UUID properly.. (This used to be commit 54e1e5edca50d3cd496c080715e84ec62cb2a10c) --- source4/lib/dcom/common/dcom.h | 2 + source4/lib/dcom/common/main.c | 113 ++++++++++++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 06407cf2f4..526340c384 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -21,6 +21,8 @@ #ifndef _DCOM_H /* _DCOM_H */ #define _DCOM_H +#include "librpc/ndr/ndr_dcom.h" + struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index a2650e3446..a4fcb7ec0d 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -27,6 +27,42 @@ #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } +struct dcom_oxid_mapping { + struct dcom_oxid_mapping *prev, *next; + struct DUALSTRINGARRAY bindings; + HYPER_T oxid; + struct dcerpc_pipe *pipe; +}; + +static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) +{ + char *host, *endpoint; + + ZERO_STRUCTP(b); + + b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId); + + if (b->transport == -1) { + DEBUG(1, ("Can't find transport match endpoint protocol %d\n", bd->wTowerId)); + return NT_STATUS_NOT_SUPPORTED; + } + + host = talloc_strdup(mem_ctx, bd->NetworkAddr); + endpoint = strchr(host, '['); + + if (endpoint) { + *endpoint = '\0'; + endpoint++; + + endpoint[strlen(endpoint)-1] = '\0'; + } + + b->host = host; + b->endpoint = endpoint; + + return NT_STATUS_OK; +} + static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe **p, const char *server) { struct dcerpc_binding bd; @@ -37,7 +73,11 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * /* Allow server name to contain a binding string */ if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { - status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); + status = dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->domain, ctx->user, ctx->password); + talloc_destroy(mem_ctx); return status; } @@ -48,14 +88,20 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * if (server == NULL) { bd.transport = NCALRPC; - return dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); + return dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->domain, ctx->user, ctx->password); } for (i = 0; i < ARRAY_SIZE(available_transports); i++) { bd.transport = available_transports[i]; - status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); + status = dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->domain, ctx->user, ctx->password); if (NT_STATUS_IS_OK(status)) { return status; @@ -65,16 +111,6 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * return status; } -static NTSTATUS dcom_connect_STRINGBINDINGARRAY(struct dcom_context *ctx, struct dcerpc_pipe **p, DATA_BLOB *stringbindingarray) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -static NTSTATUS dcom_connect_DUALSTRINGBINDINGARRAY(struct dcom_context *ctx, struct dcerpc_pipe **p, struct DUALSTRINGARRAY *array) -{ - return NT_STATUS_NOT_SUPPORTED; -} - NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) { struct RemAddRef r; @@ -133,6 +169,7 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, WERROR *results) { + struct dcom_oxid_mapping *m; struct RemoteActivation r; int i; struct dcerpc_pipe *p; @@ -156,6 +193,8 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; r.out.ifaces = talloc_array_p(ctx, struct pMInterfacePointer, num_ifaces); + m = talloc_zero_p(ctx, struct dcom_oxid_mapping); + r.out.pdsaOxidBindings = &m->bindings; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -180,11 +219,17 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch (*ip)[i].ctx = ctx; } + /* Add the OXID data for the returned oxid */ + m->oxid = r.out.pOxid; + m->bindings = *r.out.pdsaOxidBindings; + DLIST_ADD(ctx->oxids, m); + return WERR_OK; } WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *ip) { + struct dcom_oxid_mapping *m; struct RemoteActivation r; struct dcerpc_pipe *p; NTSTATUS status; @@ -209,6 +254,8 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; r.out.ifaces = ± + m = talloc_zero_p(ctx, struct dcom_oxid_mapping); + r.out.pdsaOxidBindings = &m->bindings; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -220,21 +267,20 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } + /* Set up the interface data */ ip->private_references = 1; ip->pipe = NULL; ip->objref = &pm.p->obj; ip->ctx = ctx; + + /* Add the OXID data for the returned oxid */ + m->oxid = r.out.pOxid; + m->bindings = *r.out.pdsaOxidBindings; + DLIST_ADD(ctx->oxids, m); return WERR_OK; } -struct dcom_oxid_mapping { - struct dcom_oxid_mapping *prev, *next; - struct DUALSTRINGARRAY bindings; - HYPER_T oxid; - struct dcerpc_pipe *pipe; -}; - static struct dcom_oxid_mapping *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) { struct dcom_oxid_mapping *m; @@ -251,6 +297,8 @@ static struct dcom_oxid_mapping *oxid_mapping_by_oxid (struct dcom_context *ctx, NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) { struct dcom_oxid_mapping *m; + struct dcerpc_binding binding; + struct GUID iid; HYPER_T oxid; NTSTATUS status; @@ -269,6 +317,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) DEBUG(1, ("DCOM: Connecting to %s\n", GUID_string(NULL, &iface->objref->iid))); oxid = iface->objref->u_objref.u_standard.std.oxid; + iid = iface->objref->iid; m = oxid_mapping_by_oxid(iface->ctx, oxid); @@ -283,7 +332,15 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) m = talloc_zero_p(iface->ctx, struct dcom_oxid_mapping); m->oxid = oxid; - status = dcom_connect_STRINGBINDINGARRAY(iface->ctx, &po, &iface->objref->u_objref.u_standard.saResAddr); + /* FIXME: Check other string bindings as well, not just 0 */ + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[0]); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error parsing string binding")); + return status; + } + + status = dcerpc_pipe_connect_b(&po, &binding, DCERPC_IOXIDRESOLVER_UUID, DCERPC_IOXIDRESOLVER_VERSION, iface->ctx->domain, iface->ctx->user, iface->ctx->password); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); @@ -311,12 +368,22 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) /* FIXME: Switch to correct IID using an alter context call */ return NT_STATUS_OK; } - - status = dcom_connect_DUALSTRINGBINDINGARRAY(iface->ctx, &m->pipe, &m->bindings); + + /* FIXME: Check other string bindings as well, not just 0 */ + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[0]); if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error parsing string binding")); return status; } + + status = dcerpc_pipe_connect_b(&m->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); *p = m->pipe; return NT_STATUS_OK; -- cgit From 8c2e179d477c99ab9c52e6b9af19a86d553d10b5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 8 Nov 2004 02:12:15 +0000 Subject: r3611: DCOM client support works!! The torture test DCOM-SIMPLE now successfully does an IStream_Read and a IStream_Write call. This test can now be run successfully against the "Simple DCOM" Visual Studio example. (You have to quote out line 337 in pidl. pidl complains if the variable that contains the array size follows the array. I still need to fix this properly) Next goals: - Clean up code - Server side support - Support custom marshalling - Support DCOM interfaces in files other then dcom.idl (This used to be commit 8693344772a9b700533179f4bacfe27ec27dfcfe) --- source4/lib/dcom/common/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index a4fcb7ec0d..8b947ba8ef 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -128,6 +128,8 @@ NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct RemRelease r; struct REMINTERFACEREF ref; + return NT_STATUS_NOT_SUPPORTED; + p->private_references--; /* Only do the remote version of this call when all local references have @@ -314,8 +316,6 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) return NT_STATUS_NOT_SUPPORTED; } - DEBUG(1, ("DCOM: Connecting to %s\n", GUID_string(NULL, &iface->objref->iid))); - oxid = iface->objref->u_objref.u_standard.std.oxid; iid = iface->objref->iid; -- cgit From 73c1f61350a01c0cc5825ae0a08bb4c03121eda4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 8 Nov 2004 20:54:00 +0000 Subject: r3625: Couple of minor DCOM bugfixes (This used to be commit 6f5bf44ade8bad10c6cf08a7d6e3528ec6b4ec8a) --- source4/lib/dcom/common/dcom.h | 9 +++-- source4/lib/dcom/common/local.c | 72 +++++++++++++++++++++++++++++++++++++ source4/lib/dcom/common/main.c | 79 +++++++++++------------------------------ source4/lib/dcom/config.mk | 3 +- 4 files changed, 100 insertions(+), 63 deletions(-) create mode 100644 source4/lib/dcom/common/local.c (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 526340c384..23db4c355f 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -27,11 +27,14 @@ struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; -struct dcom_oxid_mapping; - struct dcom_context { - struct dcom_oxid_mapping *oxids; + struct dcom_oxid_mapping { + struct dcom_oxid_mapping *prev, *next; + struct DUALSTRINGARRAY bindings; + HYPER_T oxid; + struct dcerpc_pipe *pipe; + } *oxids; const char *domain; const char *user; const char *password; diff --git a/source4/lib/dcom/common/local.c b/source4/lib/dcom/common/local.c new file mode 100644 index 0000000000..3c5405e9dc --- /dev/null +++ b/source4/lib/dcom/common/local.c @@ -0,0 +1,72 @@ +/* + Unix SMB/CIFS implementation. + Implementation of some of the local COM calls. Interfaces: + - IUnknown + + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "librpc/gen_ndr/ndr_dcom.h" + +NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) +{ + struct RemAddRef r; + struct REMINTERFACEREF ref; + + /* This is rather inefficient, but we'll patch it up later */ + r.in.cInterfaceRefs = 1; + r.in.InterfaceRefs = &ref; + + return dcerpc_RemAddRef(p, mem_ctx, &r); +} + +NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_Release *rr) +{ + struct RemRelease r; + struct REMINTERFACEREF ref; + + return NT_STATUS_NOT_SUPPORTED; + + p->private_references--; + + /* Only do the remote version of this call when all local references have + * been released */ + if (p->private_references == 0) { + NTSTATUS status; + r.in.cInterfaceRefs = 1; + r.in.InterfaceRefs = &ref; + + status = dcerpc_RemRelease(p, mem_ctx, &r); + + if (NT_STATUS_IS_OK(status)) { + talloc_destroy(p); + } + + return status; + } + + return NT_STATUS_OK; +} + +NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *rr) +{ + /* FIXME: Ask local server for interface pointer. Local server can then + * call RemQueryInterface if necessary */ + return NT_STATUS_NOT_SUPPORTED; +} diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 8b947ba8ef..c276b5e61a 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -27,13 +27,6 @@ #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } -struct dcom_oxid_mapping { - struct dcom_oxid_mapping *prev, *next; - struct DUALSTRINGARRAY bindings; - HYPER_T oxid; - struct dcerpc_pipe *pipe; -}; - static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) { char *host, *endpoint; @@ -111,53 +104,6 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * return status; } -NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) -{ - struct RemAddRef r; - struct REMINTERFACEREF ref; - - /* This is rather inefficient, but we'll patch it up later */ - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - return dcerpc_RemAddRef(p, mem_ctx, &r); -} - -NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_Release *rr) -{ - struct RemRelease r; - struct REMINTERFACEREF ref; - - return NT_STATUS_NOT_SUPPORTED; - - p->private_references--; - - /* Only do the remote version of this call when all local references have - * been released */ - if (p->private_references == 0) { - NTSTATUS status; - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - status = dcerpc_RemRelease(p, mem_ctx, &r); - - if (NT_STATUS_IS_OK(status)) { - talloc_destroy(p); - } - - return status; - } - - return NT_STATUS_OK; -} - -NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *rr) -{ - /* FIXME: Ask local server for interface pointer. Local server can then - * call RemQueryInterface if necessary */ - return NT_STATUS_NOT_SUPPORTED; -} - WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user, const char *pass) { *ctx = talloc_p(NULL, struct dcom_context); @@ -303,6 +249,9 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) struct GUID iid; HYPER_T oxid; NTSTATUS status; + int i; + + *p = NULL; SMB_ASSERT(iface->objref->signature == OBJREF_SIGNATURE); @@ -332,8 +281,11 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) m = talloc_zero_p(iface->ctx, struct dcom_oxid_mapping); m->oxid = oxid; - /* FIXME: Check other string bindings as well, not just 0 */ - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[0]); + i = 0; + do { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); + i++; + } while (!NT_STATUS_IS_OK(status) && iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error parsing string binding")); @@ -364,13 +316,22 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) } if (m->pipe) { + if (!uuid_equal(&m->pipe->syntax.uuid, &iid)) { + m->pipe->syntax.uuid = iid; + status = dcerpc_alter(m->pipe, iface->ctx); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + } *p = m->pipe; - /* FIXME: Switch to correct IID using an alter context call */ return NT_STATUS_OK; } - /* FIXME: Check other string bindings as well, not just 0 */ - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[0]); + i = 0; + do { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[i]); + i++; + } while (NT_STATUS_IS_ERR(status) && m->bindings.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error parsing string binding")); diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 98b7031407..39424e6b25 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -2,7 +2,8 @@ # Start SUBSYSTEM LIBDCOM [SUBSYSTEM::LIBDCOM] INIT_OBJ_FILES = \ - lib/dcom/common/main.o + lib/dcom/common/main.o \ + lib/dcom/common/local.o # # End SUBSYSTEM LIBDCOM ################################################ -- cgit From e056ed97d79c046a7f4b9562ad785fc54719a8ce Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 8 Nov 2004 22:18:18 +0000 Subject: r3626: More minor DCOM fixes (This used to be commit 709f279b192c8f9eeea04749169c00f2d57b20d3) --- source4/lib/dcom/common/main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index c276b5e61a..b2cb782953 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -115,6 +115,13 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user return WERR_OK; } +WERROR dcom_ping(struct dcom_context *ctx) +{ + /* FIXME: If OID's waiting in queue, do a ComplexPing call */ + /* FIXME: otherwise, do a SimplePing call */ + return WERR_OK; +} + WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, WERROR *results) { struct dcom_oxid_mapping *m; @@ -131,8 +138,8 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch } ZERO_STRUCT(r.in); - r.in.this.version.MajorVersion = 5; - r.in.this.version.MinorVersion = 1; + r.in.this.version.MajorVersion = COM_MAJOR_VERSION; + r.in.this.version.MinorVersion = COM_MINOR_VERSION; uuid_generate_random(&r.in.this.cid); r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; @@ -171,7 +178,7 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch m->oxid = r.out.pOxid; m->bindings = *r.out.pdsaOxidBindings; DLIST_ADD(ctx->oxids, m); - + return WERR_OK; } @@ -191,8 +198,8 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const } ZERO_STRUCT(r.in); - r.in.this.version.MajorVersion = 5; - r.in.this.version.MinorVersion = 1; + r.in.this.version.MajorVersion = COM_MAJOR_VERSION; + r.in.this.version.MinorVersion = COM_MINOR_VERSION; uuid_generate_random(&r.in.this.cid); r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; -- cgit From 099d8cc9722e04f31217f883ce4420945c22ae04 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 Nov 2004 11:00:13 +0000 Subject: r3656: allow easy testing of the "realloc changes the pointer" type of problem that abartlet recently fixed. (This used to be commit 70e53a21f25360d3421758f5c37972ebc2337a9c) --- source4/lib/talloc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 239958258b..0b1f5b7cb5 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -40,6 +40,11 @@ #include "includes.h" #endif +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + #define MAX_TALLOC_SIZE 0x10000000 #define TALLOC_MAGIC 0xe814ec4f #define TALLOC_MAGIC_FREE 0x7faebef3 @@ -538,7 +543,15 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n /* by resetting magic we catch users of the old memory */ tc->magic = TALLOC_MAGIC_FREE; +#if ALWAYS_REALLOC + new_ptr = malloc(size + sizeof(*tc)); + if (new_ptr) { + memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + free(tc); + } +#else new_ptr = realloc(tc, size + sizeof(*tc)); +#endif if (!new_ptr) { tc->magic = TALLOC_MAGIC; return NULL; -- cgit From 0d696dc0e9867889fe198e61ed576af51ee732d1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 10 Nov 2004 21:20:51 +0000 Subject: r3667: Small COM fixes (This used to be commit 7484b9be7423ccd7e37432951700939e8a53d513) --- source4/lib/dcom/common/dcom.h | 1 + source4/lib/dcom/common/local.c | 10 ++++++++++ source4/lib/dcom/common/main.c | 30 ++++++++++++++++-------------- 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 23db4c355f..320b5a4a9f 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -38,6 +38,7 @@ struct dcom_context const char *domain; const char *user; const char *password; + uint32_t dcerpc_flags; }; struct dcom_interface diff --git a/source4/lib/dcom/common/local.c b/source4/lib/dcom/common/local.c index 3c5405e9dc..a68f5f4593 100644 --- a/source4/lib/dcom/common/local.c +++ b/source4/lib/dcom/common/local.c @@ -70,3 +70,13 @@ NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *me * call RemQueryInterface if necessary */ return NT_STATUS_NOT_SUPPORTED; } + +NTSTATUS dcerpc_IClassFactory_CreateInstance(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_CreateInstance *rr) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +NTSTATUS dcerpc_IClassFactory_LockServer(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_LockServer *rr) +{ + return NT_STATUS_NOT_SUPPORTED; +} diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index b2cb782953..996432181a 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -291,15 +291,16 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) i = 0; do { status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); - i++; - } while (!NT_STATUS_IS_OK(status) && iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error parsing string binding")); - return status; - } + if (NT_STATUS_IS_OK(status)) { + binding.flags = iface->ctx->dcerpc_flags; + status = dcerpc_pipe_connect_b(&po, &binding, DCERPC_IOXIDRESOLVER_UUID, DCERPC_IOXIDRESOLVER_VERSION, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + } else { + DEBUG(1, ("Error parsing string binding - %s", nt_errstr(status))); + } - status = dcerpc_pipe_connect_b(&po, &binding, DCERPC_IOXIDRESOLVER_UUID, DCERPC_IOXIDRESOLVER_VERSION, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + i++; + } while (!NT_STATUS_IS_OK(status) && iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); @@ -337,17 +338,18 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) i = 0; do { status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[i]); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error parsing string binding")); + } else { + binding.flags = iface->ctx->dcerpc_flags; + status = dcerpc_pipe_connect_b(&m->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + } + i++; } while (NT_STATUS_IS_ERR(status) && m->bindings.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error parsing string binding")); - return status; - } - - status = dcerpc_pipe_connect_b(&m->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); - - if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); return status; } -- cgit From 79c5d73a71c35f5b16232072a7b52033cb9364cb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 12 Nov 2004 00:48:24 +0000 Subject: r3689: Large number of COM updates: - Work on server side and local COM support (should work, just no example classes yet) - Use vtables so that local and remote calls can be used transparently - Generate 'proxies and stubs' rather then heavily modified code in client.pm and server.pm. proxies (client side code) are generated in proxy.pm, stubs (server side dispatchers) are generated in stubs.pm - Support registering classes and interfaces - DCOM interfaces no longer have to be in the same IDL file as their base interface, which will allow us to split up dcom.idl (This used to be commit 7466947a23985f9bb15209b67880f7b94dc515c8) --- source4/lib/dcom/common/dcom.h | 36 +++++- source4/lib/dcom/common/local.c | 82 ------------- source4/lib/dcom/common/main.c | 243 ++++++++++++++++++++++++++------------- source4/lib/dcom/common/tables.c | 114 ++++++++++++++++++ source4/lib/dcom/config.mk | 4 +- 5 files changed, 310 insertions(+), 169 deletions(-) delete mode 100644 source4/lib/dcom/common/local.c create mode 100644 source4/lib/dcom/common/tables.c (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 320b5a4a9f..9c09cc17d9 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -29,11 +29,18 @@ struct IUnknown_QueryInterface; struct dcom_context { - struct dcom_oxid_mapping { - struct dcom_oxid_mapping *prev, *next; + struct dcom_object_exporter { + struct dcom_object_exporter *prev, *next; + struct STRINGARRAY resolver_address; struct DUALSTRINGARRAY bindings; HYPER_T oxid; struct dcerpc_pipe *pipe; + struct dcom_object + { + struct dcom_object *prev, *next; + HYPER_T oid; + void *private_data; + } *objects; } *oxids; const char *domain; const char *user; @@ -41,11 +48,32 @@ struct dcom_context uint32_t dcerpc_flags; }; +/* Specific implementation of one or more interfaces */ +struct dcom_class +{ + const char *prog_id; + struct GUID clsid; + void (*get_class_object) (struct GUID *iid, void **vtable); +}; + struct dcom_interface +{ + struct GUID iid; + int num_methods; + struct GUID base_iid; + const void *proxy_vtable; +}; + +struct dcom_interface_p { struct dcom_context *ctx; - struct dcerpc_pipe *pipe; - struct OBJREF *objref; + const struct dcom_interface *interface; + const void *vtable; /* Points to one of the available implementations */ + struct GUID ipid; + struct dcom_object *object; + int objref_flags; + int orpc_flags; + struct dcom_object_exporter *ox; uint32_t private_references; }; diff --git a/source4/lib/dcom/common/local.c b/source4/lib/dcom/common/local.c deleted file mode 100644 index a68f5f4593..0000000000 --- a/source4/lib/dcom/common/local.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Implementation of some of the local COM calls. Interfaces: - - IUnknown - - Copyright (C) 2004 Jelmer Vernooij - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "dlinklist.h" -#include "librpc/gen_ndr/ndr_dcom.h" - -NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) -{ - struct RemAddRef r; - struct REMINTERFACEREF ref; - - /* This is rather inefficient, but we'll patch it up later */ - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - return dcerpc_RemAddRef(p, mem_ctx, &r); -} - -NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_Release *rr) -{ - struct RemRelease r; - struct REMINTERFACEREF ref; - - return NT_STATUS_NOT_SUPPORTED; - - p->private_references--; - - /* Only do the remote version of this call when all local references have - * been released */ - if (p->private_references == 0) { - NTSTATUS status; - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - status = dcerpc_RemRelease(p, mem_ctx, &r); - - if (NT_STATUS_IS_OK(status)) { - talloc_destroy(p); - } - - return status; - } - - return NT_STATUS_OK; -} - -NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *rr) -{ - /* FIXME: Ask local server for interface pointer. Local server can then - * call RemQueryInterface if necessary */ - return NT_STATUS_NOT_SUPPORTED; -} - -NTSTATUS dcerpc_IClassFactory_CreateInstance(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_CreateInstance *rr) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -NTSTATUS dcerpc_IClassFactory_LockServer(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_LockServer *rr) -{ - return NT_STATUS_NOT_SUPPORTED; -} diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 996432181a..60f866aede 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -111,10 +111,31 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user (*ctx)->domain = talloc_strdup(*ctx, domain); (*ctx)->user = talloc_strdup(*ctx, user); (*ctx)->password = talloc_strdup(*ctx, pass); + (*ctx)->dcerpc_flags = 0; return WERR_OK; } +static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +{ + struct dcom_object_exporter *m; + + for (m = ctx->oxids;m;m = m->next) { + if (m->oxid == oxid) { + break; + } + } + + /* Add oxid mapping if we couldn't find one */ + if (!m) { + m = talloc_zero_p(ctx, struct dcom_object_exporter); + m->oxid = oxid; + DLIST_ADD(ctx->oxids, m); + } + + return m; +} + WERROR dcom_ping(struct dcom_context *ctx) { /* FIXME: If OID's waiting in queue, do a ComplexPing call */ @@ -122,11 +143,12 @@ WERROR dcom_ping(struct dcom_context *ctx) return WERR_OK; } -WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface **ip, WERROR *results) +WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { - struct dcom_oxid_mapping *m; struct RemoteActivation r; + struct DUALSTRINGARRAY dualstring; int i; + struct dcom_object_exporter *m; struct dcerpc_pipe *p; NTSTATUS status; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; @@ -148,8 +170,7 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; r.out.ifaces = talloc_array_p(ctx, struct pMInterfacePointer, num_ifaces); - m = talloc_zero_p(ctx, struct dcom_oxid_mapping); - r.out.pdsaOxidBindings = &m->bindings; + r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -165,28 +186,33 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch return r.out.hr; } - *ip = talloc_array_p(ctx, struct dcom_interface, num_ifaces); + *ip = talloc_array_p(ctx, struct dcom_interface_p *, num_ifaces); for (i = 0; i < num_ifaces; i++) { results[i] = r.out.results[i]; - (*ip)[i].private_references = 1; - (*ip)[i].objref = &r.out.ifaces[i].p->obj; - (*ip)[i].pipe = NULL; - (*ip)[i].ctx = ctx; + (*ip)[i] = NULL; + if (W_ERROR_IS_OK(results[i])) { + status = dcom_ifacep_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].p->obj); + if (NT_STATUS_IS_OK(status)) { + (*ip)[i]->private_references = 1; + } else { + results[i] = ntstatus_to_werror(status); + } + } } /* Add the OXID data for the returned oxid */ - m->oxid = r.out.pOxid; + m = oxid_mapping_by_oxid(ctx, r.out.pOxid); m->bindings = *r.out.pdsaOxidBindings; - DLIST_ADD(ctx->oxids, m); return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *ip) +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) { - struct dcom_oxid_mapping *m; + struct dcom_object_exporter *m; struct RemoteActivation r; struct dcerpc_pipe *p; + struct DUALSTRINGARRAY dualstring; NTSTATUS status; struct pMInterfacePointer pm; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; @@ -209,8 +235,7 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; r.out.ifaces = ± - m = talloc_zero_p(ctx, struct dcom_oxid_mapping); - r.out.pdsaOxidBindings = &m->bindings; + r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -223,74 +248,160 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } /* Set up the interface data */ - ip->private_references = 1; - ip->pipe = NULL; - ip->objref = &pm.p->obj; - ip->ctx = ctx; + dcom_ifacep_from_OBJREF(ctx, ip, &pm.p->obj); + (*ip)->private_references = 1; /* Add the OXID data for the returned oxid */ - m->oxid = r.out.pOxid; + m = oxid_mapping_by_oxid(ctx, r.out.pOxid); m->bindings = *r.out.pdsaOxidBindings; - DLIST_ADD(ctx->oxids, m); return WERR_OK; } -static struct dcom_oxid_mapping *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) { - struct dcom_oxid_mapping *m; + struct dcerpc_binding binding; + struct GUID iid; + HYPER_T oxid; + NTSTATUS status; + int i; + + *p = NULL; - for (m = ctx->oxids;m;m = m->next) { - if (m->oxid == oxid) { - return m; + oxid = iface->ox->oxid; + iid = iface->interface->iid; + + if (iface->ox->pipe) { + if (!uuid_equal(&iface->ox->pipe->syntax.uuid, &iid)) { + iface->ox->pipe->syntax.uuid = iid; + status = dcerpc_alter(iface->ox->pipe, iface->ctx); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + } + *p = iface->ox->pipe; + return NT_STATUS_OK; + } + + i = 0; + do { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error parsing string binding")); + } else { + binding.flags = iface->ctx->dcerpc_flags; + status = dcerpc_pipe_connect_b(&iface->ox->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); } + + i++; + } while (NT_STATUS_IS_ERR(status) && iface->ox->bindings.stringbindings[i]); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); + return status; } - return NULL; + DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); + + *p = iface->ox->pipe; + return NT_STATUS_OK; } -NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) +struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T oid) { - struct dcom_oxid_mapping *m; - struct dcerpc_binding binding; - struct GUID iid; - HYPER_T oxid; - NTSTATUS status; - int i; + struct dcom_object *o; - *p = NULL; + for (o = ox->objects; o; o = o->next) { + if (o->oid == oid) { + break; + } + } + + if (o == NULL) { + o = talloc_zero_p(ox, struct dcom_object); + o->oid = oid; + DLIST_ADD(ox->objects, o); + } - SMB_ASSERT(iface->objref->signature == OBJREF_SIGNATURE); + return o; +} + +NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) +{ + struct dcom_interface_p *p = talloc_p(ctx, struct dcom_interface_p); - if (iface->objref->flags & OBJREF_HANDLER) { - DEBUG(0, ("dcom_get_pipe: OBJREF_HANDLER not supported!\n")); + p->ctx = ctx; + p->interface = dcom_interface_by_iid(&o->iid); + if (!p->interface) { + DEBUG(0, ("Unable to find interface with IID %s\n", GUID_string(ctx, &o->iid))); return NT_STATUS_NOT_SUPPORTED; } - if (iface->objref->flags & OBJREF_CUSTOM) { - DEBUG(0, ("dcom_get_pipe: OBJREF_CUSTOM not supported!\n")); + p->private_references = 0; + p->objref_flags = o->flags; + + switch(p->objref_flags) { + case OBJREF_NULL: + p->object = NULL; + p->ox = NULL; + p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); + ZERO_STRUCT(p->ipid); + *_p = p; + return NT_STATUS_OK; + + case OBJREF_STANDARD: + p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_standard.std.oxid); + p->ipid = o->u_objref.u_standard.std.ipid; + p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); + p->ox->resolver_address = o->u_objref.u_standard.saResAddr; + p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); + *_p = p; + return NT_STATUS_OK; + + case OBJREF_HANDLER: + p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_handler.std.oxid ); + p->ipid = o->u_objref.u_handler.std.ipid; + p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); + p->ox->resolver_address = o->u_objref.u_handler.saResAddr; + p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid); + /* FIXME: Do the custom unmarshaling call */ + + *_p = p; + return NT_STATUS_OK; + + case OBJREF_CUSTOM: + { + const struct dcom_interface *imarshal = dcom_vtable_by_clsid(&o->u_objref.u_custom.clsid); + p->vtable = NULL; + + /* FIXME: Do the actual custom unmarshaling call */ + p->ox = NULL; + p->object = NULL; + ZERO_STRUCT(p->ipid); + *_p = p; return NT_STATUS_NOT_SUPPORTED; + } } - oxid = iface->objref->u_objref.u_standard.std.oxid; - iid = iface->objref->iid; - - m = oxid_mapping_by_oxid(iface->ctx, oxid); + return NT_STATUS_NOT_SUPPORTED; + +#if 0 + struct dcom_oxid_mapping *m; /* Add OXID mapping if none present yet */ if (!m) { struct dcerpc_pipe *po; struct ResolveOxid r; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", oxid)); + DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", p->ox->oxid)); - m = talloc_zero_p(iface->ctx, struct dcom_oxid_mapping); + m = talloc_zero_p(p->ctx, struct dcom_oxid_mapping); m->oxid = oxid; i = 0; do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); + status = dcerpc_binding_from_STRINGBINDING(p->ctx, &binding, p->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_OK(status)) { binding.flags = iface->ctx->dcerpc_flags; @@ -300,7 +411,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) } i++; - } while (!NT_STATUS_IS_OK(status) && iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); + } while (!NT_STATUS_IS_OK(status) && iface->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); @@ -322,39 +433,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) DLIST_ADD(iface->ctx->oxids, m); } +#endif - if (m->pipe) { - if (!uuid_equal(&m->pipe->syntax.uuid, &iid)) { - m->pipe->syntax.uuid = iid; - status = dcerpc_alter(m->pipe, iface->ctx); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - } - *p = m->pipe; - return NT_STATUS_OK; - } - - i = 0; - do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[i]); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error parsing string binding")); - } else { - binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&m->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); - } - - i++; - } while (NT_STATUS_IS_ERR(status) && m->bindings.stringbindings[i]); - - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); - return status; - } - - DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); - - *p = m->pipe; - return NT_STATUS_OK; + return NT_STATUS_NOT_SUPPORTED; } diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c new file mode 100644 index 0000000000..d6b7cfa78f --- /dev/null +++ b/source4/lib/dcom/common/tables.c @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + DCOM interface and class tables + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" + +static struct class_list { + struct class_list *prev, *next; + struct dcom_class class; +} *classes = NULL; + +static struct interface_list { + struct interface_list *prev, *next; + struct dcom_interface interface; +} *interfaces = NULL; + +const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) +{ + struct interface_list *l = interfaces; + + while(l) { + + if (uuid_equal(iid, &l->interface.iid)) + return &l->interface; + + l = l->next; + } + + return NULL; +} + +const void *dcom_vtable_by_clsid(const struct GUID *clsid) +{ + struct class_list *c = classes; + + while(c) { + + if (uuid_equal(clsid, &c->class.clsid)) + return &c->class; + + c = c->next; + } + + return NULL; +} + +const void *dcom_proxy_vtable_by_iid(const struct GUID *iid) +{ + const struct dcom_interface *iface = dcom_interface_by_iid(iid); + + if (!iface) { + return NULL; + } + + return iface->proxy_vtable; +} + +static NTSTATUS dcom_register_interface(const void *_iface) +{ + const struct dcom_interface *iface = _iface; + struct interface_list *l = talloc_zero_p(interfaces, struct interface_list); + + l->interface = *iface; + + DLIST_ADD(interfaces, l); + + return NT_STATUS_OK; +} + +static NTSTATUS dcom_register_class(const void *_class) +{ + const struct dcom_class *class = _class; + struct class_list *l = talloc_zero_p(classes, struct class_list); + + l->class = *class; + + DLIST_ADD(classes, l); + + return NT_STATUS_OK; +} + +NTSTATUS libdcom_init(void) +{ + NTSTATUS status; + + status = register_subsystem("dcom_interface", dcom_register_interface); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + register_subsystem("dcom_class", dcom_register_class); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + return status; +} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 39424e6b25..6ebf16324f 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -1,9 +1,11 @@ ################################################ # Start SUBSYSTEM LIBDCOM [SUBSYSTEM::LIBDCOM] +INIT_FUNCTION = libdcom_init INIT_OBJ_FILES = \ lib/dcom/common/main.o \ - lib/dcom/common/local.o + lib/dcom/common/tables.o +REQUIRED_SUBSYSTEMS = LIBRPC # # End SUBSYSTEM LIBDCOM ################################################ -- cgit From d309966e3191405f5a17555c394b4a1934fbfcab Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 13 Nov 2004 13:33:45 +0000 Subject: r3723: Now that timestring() always returns talloc'ed memory, we don't need this talloc strdup here (do we?). Andrew Bartlett (This used to be commit d6aca06793b4bc72399c7357c5f357d6db036513) --- source4/lib/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index e1f1395fea..b13ad24b34 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -347,7 +347,7 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) { time_t t = nt_time_to_unix(nt); - return talloc_strdup(mem_ctx, timestring(mem_ctx, t)); + return timestring(mem_ctx, t); } -- cgit From 7367d23713a34a6c29a492adb365292399adffe8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 14 Nov 2004 13:52:16 +0000 Subject: r3730: More build system fixes and simplifications the hierarchy in the init functions is correct now will also make it easier to implement some other features (This used to be commit cbe819a75568403ac8850ea4d344c607a46d61c2) --- source4/lib/cmdline/config.m4 | 7 +++---- source4/lib/ldb/config.mk | 4 ++-- source4/lib/popt/config.m4 | 5 ++--- source4/lib/registry/config.mk | 3 +-- source4/lib/tdb/config.mk | 3 +-- 5 files changed, 9 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index 8316dff10f..a8b50c786f 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -72,10 +72,9 @@ AC_CHECK_LIB(readline, rl_completion_matches, TMP_LIBCMDLINE_OBJS="lib/cmdline/readline.o lib/cmdline/popt_common.o" TMP_LIBCMDLINE_LIBS="$TERMLIBS" -#hack... -LIBS="$LIBS $TERMLIBS" +SMB_EXT_LIB(READLINE, [$TERMLIBS]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], - [ALLLIBS], - [LIBPOPT]) + [], + [LIBPOPT EXT_LIB_READLINE]) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 639652ea55..10b8c76f97 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -3,8 +3,8 @@ [MODULE::libldb_ldap] INIT_OBJ_FILES = \ lib/ldb/ldb_ldap/ldb_ldap.o -REQUIRED_LIBRARIES = \ - LDAP +REQUIRED_SUBSYSTEMS = \ + EXT_LIB_LDAP # End MODULE libldb_tdb ################################################ diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index 5af1d08d20..ff4455efa2 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -33,9 +33,8 @@ else AC_MSG_RESULT(no) fi -#hack -LIBS="$LIBS ${TMP_LIBPOPT_LIBS}" +SMB_EXT_LIB(POPT, [${TMP_LIBPOPT_LIBS}]) SMB_SUBSYSTEM(LIBPOPT,[], [${TMP_LIBPOPT_OBJS}], - []) + [EXT_LIB_POPT]) diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index dacd6d5295..bebd8bf1d7 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -44,8 +44,7 @@ REQUIRED_SUBSYSTEMS = \ INIT_FUNCTION = registry_gconf_init INIT_OBJ_FILES = \ lib/registry/reg_backend_gconf/reg_backend_gconf.o -REQUIRED_LIBRARIES = \ - gconf +REQUIRED_SUBSYSTEMS = EXT_LIB_gconf # End MODULE registry_gconf ################################################ diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 6339b91761..1801e30e0a 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -30,8 +30,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbtest.o REQUIRED_SUBSYSTEMS = \ - LIBTDB -REQUIRED_LIBRARIES = GDBM + LIBTDB EXT_LIB_GDBM # End BINARY tdbtest ################################################ -- cgit From 8e16d8a76f8a3b8ccc89eb317c8e5daa6cf43b71 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 14 Nov 2004 16:22:01 +0000 Subject: r3733: More build system fixes/features: - Use .mk files directly (no need for a SMB_*_MK() macro when adding a new SUBSYSTEM, MODULE or BINARY). This allows addition of new modules and subsystems without running configure - Add support for generating .dot files with the Samba4 dependency tree (as used by the graphviz and springgraph utilities) (This used to be commit 64826da834e26ee0488674e27a0eae36491ee179) --- source4/lib/basic.m4 | 7 ------- source4/lib/basic.mk | 10 +++++----- source4/lib/dcom/config.m4 | 1 - source4/lib/ldb/config.m4 | 22 ---------------------- source4/lib/ldb/config.mk | 2 ++ source4/lib/messaging/config.m4 | 1 - source4/lib/registry/config.m4 | 16 ---------------- source4/lib/registry/config.mk | 6 ++++++ source4/lib/socket/config.m4 | 6 ------ source4/lib/socket/config.mk | 3 +++ source4/lib/tdb/config.m4 | 13 ------------- source4/lib/tdb/config.mk | 1 + 12 files changed, 17 insertions(+), 71 deletions(-) delete mode 100644 source4/lib/basic.m4 delete mode 100644 source4/lib/dcom/config.m4 delete mode 100644 source4/lib/messaging/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/basic.m4 b/source4/lib/basic.m4 deleted file mode 100644 index b3327b6dcc..0000000000 --- a/source4/lib/basic.m4 +++ /dev/null @@ -1,7 +0,0 @@ -dnl # LIB BASIC subsystem - -SMB_SUBSYSTEM_MK(LIBREPLACE,lib/basic.mk) -SMB_SUBSYSTEM_MK(LIBNETIF,lib/basic.mk) -SMB_SUBSYSTEM_NOPROTO(LIBCRYPTO) -SMB_SUBSYSTEM_MK(LIBCRYPTO,lib/basic.mk) -SMB_SUBSYSTEM_MK(LIBBASIC,lib/basic.mk) diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 827aa0a57c..68f41db089 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -22,6 +22,7 @@ ADD_OBJ_FILES = \ ############################## # Start SUBSYSTEM LIBCRYPTO [SUBSYSTEM::LIBCRYPTO] +NOPROTO = YES INIT_OBJ_FILES = \ lib/crypto/crc32.o ADD_OBJ_FILES = \ @@ -31,7 +32,6 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBCRYPTO ############################## - ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -66,15 +66,15 @@ ADD_OBJ_FILES = \ lib/select.o \ lib/pam_errors.o \ intl/lang_tdb.o \ - lib/gencache.o \ lib/module.o \ lib/mutex.o \ lib/events.o \ - lib/db_wrap.o \ lib/server_mutex.o \ lib/idtree.o \ - lib/unix_privs.o + lib/unix_privs.o \ + lib/db_wrap.o \ + lib/gencache.o REQUIRED_SUBSYSTEMS = \ - LIBTDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO + LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/dcom/config.m4 b/source4/lib/dcom/config.m4 deleted file mode 100644 index 206b916fa6..0000000000 --- a/source4/lib/dcom/config.m4 +++ /dev/null @@ -1 +0,0 @@ -SMB_SUBSYSTEM_MK(LIBDCOM,lib/dcom/config.mk) diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index a4e7a0dba9..5701b1b5c3 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -2,28 +2,6 @@ if test x"$with_ldap_support" = x"yes"; then SMB_MODULE_DEFAULT(libldb_ldap,STATIC) fi -SMB_SUBSYSTEM_MK(LIBLDB,lib/ldb/config.mk) - -SMB_MODULE_MK(libldb_ldap,LIBLDB,NOT,lib/ldb/config.mk) - -SMB_MODULE_MK(libldb_tdb,LIBLDB,STATIC,lib/ldb/config.mk) - if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libldb,YES) fi - -SMB_LIBRARY_MK(libldb,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbadd,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbdel,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbmodify,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbsearch,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbedit,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbrename,lib/ldb/config.mk) - -SMB_BINARY_MK(ldbtest,lib/ldb/config.mk) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 10b8c76f97..81c6382292 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -1,6 +1,7 @@ ################################################ # Start MODULE libldb_ldap [MODULE::libldb_ldap] +SUBSYSTEM = LIBLDB INIT_OBJ_FILES = \ lib/ldb/ldb_ldap/ldb_ldap.o REQUIRED_SUBSYSTEMS = \ @@ -11,6 +12,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start MODULE libldb_tdb [MODULE::libldb_tdb] +SUBSYSTEM = LIBLDB INIT_OBJ_FILES = \ lib/ldb/ldb_tdb/ldb_tdb.o ADD_OBJ_FILES = \ diff --git a/source4/lib/messaging/config.m4 b/source4/lib/messaging/config.m4 deleted file mode 100644 index 1797069ff2..0000000000 --- a/source4/lib/messaging/config.m4 +++ /dev/null @@ -1 +0,0 @@ -SMB_SUBSYSTEM_MK(MESSAGING,lib/messaging/config.mk) diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index f3681e7828..abadcbe1a0 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -15,22 +15,6 @@ if test t$SMB_EXT_LIB_ENABLE_gconf = tYES; then SMB_MODULE_DEFAULT(registry_gconf, STATIC) fi -SMB_MODULE_MK(registry_nt4, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_w95, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_dir, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_rpc, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_gconf, REGISTRY, STATIC, lib/registry/config.mk) -SMB_MODULE_MK(registry_ldb, REGISTRY, STATIC, lib/registry/config.mk) - -SMB_SUBSYSTEM_MK(REGISTRY,lib/registry/config.mk) - -SMB_BINARY_MK(regdiff, lib/registry/config.mk) -SMB_BINARY_MK(regpatch, lib/registry/config.mk) -SMB_BINARY_MK(regshell, lib/registry/config.mk) -SMB_BINARY_MK(regtree, lib/registry/config.mk) - if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libwinregistry, YES) fi - -SMB_LIBRARY_MK(libwinregistry, lib/registry/config.mk) diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index bebd8bf1d7..1a12b0ade6 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -4,6 +4,7 @@ # Start MODULE registry_nt4 [MODULE::registry_nt4] INIT_FUNCTION = registry_nt4_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_nt4/reg_backend_nt4.o # End MODULE registry_nt4 @@ -13,6 +14,7 @@ INIT_OBJ_FILES = \ # Start MODULE registry_w95 [MODULE::registry_w95] INIT_FUNCTION = registry_w95_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_w95/reg_backend_w95.o # End MODULE registry_w95 @@ -22,6 +24,7 @@ INIT_OBJ_FILES = \ # Start MODULE registry_dir [MODULE::registry_dir] INIT_FUNCTION = registry_dir_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_dir/reg_backend_dir.o # End MODULE registry_dir @@ -31,6 +34,7 @@ INIT_OBJ_FILES = \ # Start MODULE registry_rpc [MODULE::registry_rpc] INIT_FUNCTION = registry_rpc_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_rpc/reg_backend_rpc.o REQUIRED_SUBSYSTEMS = \ @@ -42,6 +46,7 @@ REQUIRED_SUBSYSTEMS = \ # Start MODULE registry_gconf [MODULE::registry_gconf] INIT_FUNCTION = registry_gconf_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_gconf/reg_backend_gconf.o REQUIRED_SUBSYSTEMS = EXT_LIB_gconf @@ -52,6 +57,7 @@ REQUIRED_SUBSYSTEMS = EXT_LIB_gconf # Start MODULE registry_ldb [MODULE::registry_ldb] INIT_FUNCTION = registry_ldb_init +SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_ldb/reg_backend_ldb.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 37eff7ded1..1140c139cb 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,7 +1,4 @@ -SMB_MODULE_MK(socket_ipv4,SOCKET,STATIC,lib/socket/config.mk) -SMB_MODULE_MK(socket_unix,SOCKET,STATIC,lib/socket/config.mk) - dnl test for ipv6 using the gethostbyname2() function. That should be sufficient dnl for now AC_CHECK_FUNCS(gethostbyname2, have_ipv6=true, have_ipv6=false) @@ -12,6 +9,3 @@ fi dnl don't build ipv6 by default, unless the above test enables it, or dnl the configure uses --with-static-modules=socket_ipv6 -SMB_MODULE_MK(socket_ipv6,SOCKET,NOT,lib/socket/config.mk) - -SMB_SUBSYSTEM_MK(SOCKET,lib/socket/config.mk) diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 76e5895933..6217fbc079 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -2,6 +2,7 @@ ################################################ # Start MODULE socket_ipv4 [MODULE::socket_ipv4] +SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv4.o # End MODULE socket_ipv4 @@ -10,6 +11,7 @@ INIT_OBJ_FILES = \ ################################################ # Start MODULE socket_ipv6 [MODULE::socket_ipv6] +SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv6.o # End MODULE socket_ipv6 @@ -18,6 +20,7 @@ INIT_OBJ_FILES = \ ################################################ # Start MODULE socket_unix [MODULE::socket_unix] +SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_unix.o # End MODULE socket_unix diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index d9b44b75a5..414ccfdfed 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,12 +1,8 @@ -SMB_SUBSYSTEM_MK(LIBTDB,lib/tdb/config.mk) - if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtdb,YES) fi -SMB_LIBRARY_MK(libtdb,lib/tdb/config.mk) - ############################### # start SMB_EXT_LIB_GDBM # check for gdbm.h and -lgdbm @@ -23,12 +19,3 @@ SMB_BINARY_ENABLE(tdbtest, NO) if test x"$SMB_EXT_LIB_ENABLE_GDBM" = x"YES"; then SMB_BINARY_ENABLE(tdbtest, YES) fi -SMB_BINARY_MK(tdbtest,lib/tdb/config.mk) - -SMB_BINARY_MK(tdbtorture,lib/tdb/config.mk) - -SMB_BINARY_MK(tdbdump,lib/tdb/config.mk) - -# these are broken -#SMB_BINARY_MK(tdbtool,lib/tdb/config.mk) -#SMB_BINARY_MK(tdbbackup,lib/tdb/config.mk) diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 1801e30e0a..bfcd462453 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -67,6 +67,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbbackup [BINARY::tdbbackup] +ENABLE = NO OBJ_FILES= \ lib/tdb/tools/tdbbackup.o REQUIRED_SUBSYSTEMS = \ -- cgit From 836f6ea0bfea0721c55fc155f6f4b19a1316c1ef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 14 Nov 2004 16:34:30 +0000 Subject: r3734: Fix some incorrect dependencies (This used to be commit 3add9e7de52496b135a230cccfd2d99a8b77ddd0) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 1a12b0ade6..9c6ed24148 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -38,7 +38,7 @@ SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_rpc/reg_backend_rpc.o REQUIRED_SUBSYSTEMS = \ - LIBSMB + LIBRPC # End MODULE registry_rpc ################################################ -- cgit From 31ded4901b4529ad2e49871502cab5ecba71483a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 14 Nov 2004 22:23:23 +0000 Subject: r3737: - Get rid of the register_subsystem() and register_backend() functions. - Re-disable tdbtool (it was building fine on my Debian box but other machines were having problems) (This used to be commit 0d7bb2c40b7a9ed59df3f8944133ea562697e814) --- source4/lib/basic.mk | 1 - source4/lib/dcom/common/tables.c | 21 +-- source4/lib/dcom/config.mk | 1 - source4/lib/iconv.c | 19 +-- source4/lib/module.c | 172 --------------------- source4/lib/registry/common/reg_interface.c | 15 -- source4/lib/registry/config.mk | 1 - .../lib/registry/reg_backend_dir/reg_backend_dir.c | 2 +- .../registry/reg_backend_gconf/reg_backend_gconf.c | 2 +- .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 2 +- .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 2 +- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- .../lib/registry/reg_backend_w95/reg_backend_w95.c | 2 +- source4/lib/tdb/config.mk | 1 + 14 files changed, 10 insertions(+), 233 deletions(-) delete mode 100644 source4/lib/module.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 68f41db089..7360eddf94 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -66,7 +66,6 @@ ADD_OBJ_FILES = \ lib/select.o \ lib/pam_errors.o \ intl/lang_tdb.o \ - lib/module.o \ lib/mutex.o \ lib/events.o \ lib/server_mutex.o \ diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index d6b7cfa78f..f9f1c49380 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -72,7 +72,7 @@ const void *dcom_proxy_vtable_by_iid(const struct GUID *iid) return iface->proxy_vtable; } -static NTSTATUS dcom_register_interface(const void *_iface) +NTSTATUS dcom_register_interface(const void *_iface) { const struct dcom_interface *iface = _iface; struct interface_list *l = talloc_zero_p(interfaces, struct interface_list); @@ -84,7 +84,7 @@ static NTSTATUS dcom_register_interface(const void *_iface) return NT_STATUS_OK; } -static NTSTATUS dcom_register_class(const void *_class) +NTSTATUS dcom_register_class(const void *_class) { const struct dcom_class *class = _class; struct class_list *l = talloc_zero_p(classes, struct class_list); @@ -95,20 +95,3 @@ static NTSTATUS dcom_register_class(const void *_class) return NT_STATUS_OK; } - -NTSTATUS libdcom_init(void) -{ - NTSTATUS status; - - status = register_subsystem("dcom_interface", dcom_register_interface); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - - register_subsystem("dcom_class", dcom_register_class); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - - return status; -} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 6ebf16324f..21d90024d4 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -1,7 +1,6 @@ ################################################ # Start SUBSYSTEM LIBDCOM [SUBSYSTEM::LIBDCOM] -INIT_FUNCTION = libdcom_init INIT_OBJ_FILES = \ lib/dcom/common/main.o \ lib/dcom/common/tables.o diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 085ec0ec2f..045ed36320 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -73,7 +73,7 @@ static const struct charset_functions builtin_functions[] = { static struct charset_functions *charsets = NULL; -static NTSTATUS charset_register_backend(const void *_funcs) +NTSTATUS charset_register_backend(const void *_funcs) { struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); struct charset_functions *c = charsets; @@ -92,22 +92,6 @@ static NTSTATUS charset_register_backend(const void *_funcs) return NT_STATUS_OK; } -static void lazy_initialize_iconv(void) -{ - static BOOL initialized = False; - int i; - - if (!initialized) { - initialized = True; - register_subsystem("charset", charset_register_backend); - - charset_init_static_modules; - - for(i = 0; builtin_functions[i].name; i++) - register_backend("charset", &builtin_functions[i]); - } -} - #ifdef HAVE_NATIVE_ICONV /* if there was an error then reset the internal state, this ensures that we don't have a shift state remaining for @@ -179,7 +163,6 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) smb_iconv_t ret; struct charset_functions *from, *to; - lazy_initialize_iconv(); from = charsets; to = charsets; diff --git a/source4/lib/module.c b/source4/lib/module.c deleted file mode 100644 index 80360e4e72..0000000000 --- a/source4/lib/module.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Unix SMB/CIFS implementation. - module loading system - - Copyright (C) Jelmer Vernooij 2002-2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "system/dir.h" -#include "system/filesys.h" -#include "dlinklist.h" - -#ifdef HAVE_DLOPEN - -/* Load module (or directory with modules) recursively. - * Includes running the init_module() function */ -NTSTATUS smb_load_module(const char *module_name) -{ - void *handle; - init_module_function init; - NTSTATUS status; - const char *error; - struct stat st; - DIR *dir; - struct dirent *dirent; - - if(stat(module_name, &st) < 0) { - DEBUG(0, ("Can't stat module '%s'\n", module_name)); - return NT_STATUS_UNSUCCESSFUL; - } - - /* If the argument is a directory, recursively load all files / - * directories in it */ - - /* How about symlinks pointing to themselves - wouldn't we rather - * want to use wildcards here? */ - if(S_ISDIR(st.st_mode)) { - dir = opendir(module_name); - while ((dirent = readdir(dir))) { - smb_load_module(dirent->d_name); - } - } - - /* Always try to use LAZY symbol resolving; if the plugin has - * backwards compatibility, there might be symbols in the - * plugin referencing to old (removed) functions - */ - handle = sys_dlopen(module_name, RTLD_LAZY); - - if(!handle) { - DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } - - init = (init_module_function)sys_dlsym(handle, "init_module"); - - /* we must check sys_dlerror() to determine if it worked, because - sys_dlsym() can validly return NULL */ - error = sys_dlerror(); - if (error) { - DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error)); - return NT_STATUS_UNSUCCESSFUL; - } - - status = init(); - - DEBUG(2, ("Module '%s' loaded\n", module_name)); - - return status; -} - -/* Load all modules in list and return number of - * modules that has been successfully loaded */ -int smb_load_modules(const char **modules) -{ - int i; - int success = 0; - - for(i = 0; modules[i]; i++){ - if(NT_STATUS_IS_OK(smb_load_module(modules[i]))) { - success++; - } - } - - DEBUG(2, ("%d modules successfully loaded\n", success)); - - return success; -} - -#else /* HAVE_DLOPEN */ - -NTSTATUS smb_load_module(const char *module_name) -{ - DEBUG(0,("This samba executable has not been built with plugin support\n")); - return NT_STATUS_NOT_SUPPORTED; -} - -int smb_load_modules(const char **modules) -{ - DEBUG(0,("This samba executable has not been built with plugin support\n")); - return -1; -} - -#endif /* HAVE_DLOPEN */ - -void init_modules(void) -{ - if(lp_preload_modules()) - smb_load_modules(lp_preload_modules()); -} - -struct subsystem { - char *name; - register_backend_function callback; - struct subsystem *prev, *next; -}; - -static struct subsystem *subsystems = NULL; - -NTSTATUS register_subsystem(const char *name, register_backend_function callback) -{ - struct subsystem *s; - struct subsystem *t = subsystems; - - while(t) { - if(!strcmp(name, t->name)) { - /* its already registered! */ - DEBUG(0,("Subsystem '%s' already registered\n", name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - t = t->next; - } - - s = smb_xmalloc(sizeof(struct subsystem)); - - s->name = smb_xstrdup(name); - s->callback = callback; - s->prev = s->next = NULL; - - DLIST_ADD(subsystems, s); - - return NT_STATUS_OK; -} - -NTSTATUS register_backend(const char *subsystem, const void *args) -{ - /* Find the specified subsystem */ - struct subsystem *s = subsystems; - - while(s) { - if(!strcmp(subsystem, s->name)) return s->callback(args); - s = s->next; - } - - DEBUG(0, ("Unable to register backend for subsystem '%s'\n", subsystem)); - - return NT_STATUS_NOT_IMPLEMENTED; -} diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 0399fc26aa..77440cea0f 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -59,21 +59,6 @@ NTSTATUS registry_register(const void *_function) return NT_STATUS_OK; } -NTSTATUS registry_init(void) -{ - NTSTATUS status; - - status = register_subsystem("registry", registry_register); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Error registering registry subsystem: %s\n", nt_errstr(status))); - return status; - } - - registry_init_static_modules; - - return NT_STATUS_OK; -} - /* Find a backend in the list of available backends */ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) { diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 9c6ed24148..ec9dbec7db 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -68,7 +68,6 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start SUBSYSTEM REGISTRY [SUBSYSTEM::REGISTRY] -INIT_FUNCTION = registry_init INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c index 247d723252..8712e7ce7c 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c @@ -144,5 +144,5 @@ static struct registry_operations reg_backend_dir = { NTSTATUS registry_dir_init(void) { - return register_backend("registry", ®_backend_dir); + return registry_register(®_backend_dir); } diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c index 382bc6dba5..fd258ca285 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c @@ -189,5 +189,5 @@ static struct registry_operations reg_backend_gconf = { NTSTATUS registry_gconf_init(void) { - return register_backend("registry", ®_backend_gconf); + return registry_register(®_backend_gconf); } diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index 22c81018c7..bdebe34ff4 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -214,5 +214,5 @@ static struct registry_operations reg_backend_ldb = { NTSTATUS registry_ldb_init(void) { - return register_backend("registry", ®_backend_ldb); + return registry_register(®_backend_ldb); } diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index c1b9b43445..aac6e548a8 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -1743,5 +1743,5 @@ static struct registry_operations reg_backend_nt4 = { NTSTATUS registry_nt4_init(void) { - return register_backend("registry", ®_backend_nt4); + return registry_register(®_backend_nt4); } diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 954e7684bb..47afc31d96 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -401,5 +401,5 @@ static struct registry_operations reg_backend_rpc = { NTSTATUS registry_rpc_init(void) { - return register_backend("registry", ®_backend_rpc); + return registry_register(®_backend_rpc); } diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index 72ec882b8a..fb73e9052c 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -352,5 +352,5 @@ static struct registry_operations reg_backend_w95 = { NTSTATUS registry_w95_init(void) { - return register_backend("registry", ®_backend_w95); + return registry_register(®_backend_w95); } diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index bfcd462453..96c2c590cb 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -37,6 +37,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbtool [BINARY::tdbtool] +ENABLE = NO OBJ_FILES= \ lib/tdb/tools/tdbtool.o REQUIRED_SUBSYSTEMS = \ -- cgit From f7cbd3450b0099cc2b79e786b9a4fe3fdd9594ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Nov 2004 00:15:25 +0000 Subject: r3742: make test-ldap give a sane error message when the openldap schema files are missing and auto-link the files if they are found in /etc/ldap/schema/ (This used to be commit 88b03ffc85d43ac83193a093cdb246794d74c4e4) --- source4/lib/ldb/tests/test-ldap.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-ldap.sh b/source4/lib/ldb/tests/test-ldap.sh index 29b40ff455..3e285a39a9 100755 --- a/source4/lib/ldb/tests/test-ldap.sh +++ b/source4/lib/ldb/tests/test-ldap.sh @@ -1,5 +1,24 @@ #!/bin/sh +SCHEMA_NEEDED="core nis cosine inetorgperson openldap" + +# setup needed schema files +for f in $SCHEMA_NEEDED; do + if [ ! -r tests/schema/$f.schema ]; then + mkdir -p tests/schema + if [ -r /etc/ldap/schema/$f.schema ]; then + ln -s /etc/ldap/schema/$f.schema tests/schema/$f.schema + continue; + fi + + echo "ERROR: you need the following OpenLDAP schema files in tests/schema/" + for f in $SCHEMA_NEEDED; do + echo " $f.schema" + done + exit 1 + fi +done + tests/init_slapd.sh tests/start_slapd.sh -- cgit From c66dbe0c3e57eabacd28658891e356b724fd3fba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Nov 2004 00:31:32 +0000 Subject: r3743: auto-support the RH schema location as well (This used to be commit 4fc794d0b4bc6f2a0115628589f9366800a369ca) --- source4/lib/ldb/tests/test-ldap.sh | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-ldap.sh b/source4/lib/ldb/tests/test-ldap.sh index 3e285a39a9..37827219c0 100755 --- a/source4/lib/ldb/tests/test-ldap.sh +++ b/source4/lib/ldb/tests/test-ldap.sh @@ -10,6 +10,10 @@ for f in $SCHEMA_NEEDED; do ln -s /etc/ldap/schema/$f.schema tests/schema/$f.schema continue; fi + if [ -r /etc/openldap/schema/$f.schema ]; then + ln -s /etc/openldap/schema/$f.schema tests/schema/$f.schema + continue; + fi echo "ERROR: you need the following OpenLDAP schema files in tests/schema/" for f in $SCHEMA_NEEDED; do -- cgit From 34ddb33b4bf14587f4cd5d7972095df6ffa33e02 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 15 Nov 2004 00:32:37 +0000 Subject: r3744: Support building subsystems as a shared library. Modules don't work yet, so while this does compile, it does not work yet. (This used to be commit 3d885562c9f83d60c5d4957b067e35387dfa50dd) --- source4/lib/dcom/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 21d90024d4..f0b4031fc1 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -4,7 +4,7 @@ INIT_OBJ_FILES = \ lib/dcom/common/main.o \ lib/dcom/common/tables.o -REQUIRED_SUBSYSTEMS = LIBRPC +REQUIRED_SUBSYSTEMS = LIBNDR_RAW LIBNDR_GEN LIBRPC_RAW # # End SUBSYSTEM LIBDCOM ################################################ -- cgit From eac720f0518acb055ba3f8a8946f3c026c1bd4ae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 15 Nov 2004 08:51:31 +0000 Subject: r3750: fix the build metze (This used to be commit 51630caeb1419565b4196c5672f113373586dafc) --- source4/lib/cmdline/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index a8b50c786f..a242e2c5e5 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -77,4 +77,4 @@ SMB_EXT_LIB(READLINE, [$TERMLIBS]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], [], - [LIBPOPT EXT_LIB_READLINE]) + [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS]) -- cgit From 5b397619ccd3a2189c053209387093b60ff53094 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 15 Nov 2004 11:13:35 +0000 Subject: r3753: Have some modules default to "NOT" and enable them again when their dependencies are found (This used to be commit 8e7e98ae5fca8be8c6a0b4c543b6828c46172171) --- source4/lib/ldb/config.m4 | 2 ++ source4/lib/socket/config.m4 | 1 + 2 files changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 5701b1b5c3..1a65eebd01 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,7 +1,9 @@ +SMB_MODULE_DEFAULT(libldb_ldap,NOT) if test x"$with_ldap_support" = x"yes"; then SMB_MODULE_DEFAULT(libldb_ldap,STATIC) fi +SMB_LIBRARY_ENABLE(libldb,NO) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libldb,YES) fi diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 1140c139cb..b301c6060c 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -2,6 +2,7 @@ dnl test for ipv6 using the gethostbyname2() function. That should be sufficient dnl for now AC_CHECK_FUNCS(gethostbyname2, have_ipv6=true, have_ipv6=false) +SMB_MODULE_DEFAULT(socket_ipv6, NOT) if $have_ipv6 = true; then SMB_MODULE_DEFAULT(socket_ipv6, STATIC) AC_DEFINE(HAVE_SOCKET_IPV6,1,[Whether the system has ipv6 support]) -- cgit From 679e95db033fd11d17c1f1ac5e44f6cc4df2220e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Nov 2004 11:40:27 +0000 Subject: r3754: merge in ldb modules support from the tmp branch ldbPlugins (This used to be commit 71323f424b4561af1fdddd2358629049be3dad8c) --- source4/lib/ldb/Makefile.ldb | 8 +- source4/lib/ldb/common/ldb.c | 56 ++++++------ source4/lib/ldb/config.mk | 12 ++- source4/lib/ldb/include/ldb.h | 40 +++++---- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 53 +++++++---- source4/lib/ldb/ldb_tdb/ldb_cache.c | 57 ++++++------ source4/lib/ldb/ldb_tdb/ldb_index.c | 121 +++++++++++++------------ source4/lib/ldb/ldb_tdb/ldb_match.c | 27 +++--- source4/lib/ldb/ldb_tdb/ldb_search.c | 81 +++++++++-------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 167 +++++++++++++++++++---------------- source4/lib/ldb/tools/ldbadd.c | 22 ++++- source4/lib/ldb/tools/ldbdel.c | 22 ++++- source4/lib/ldb/tools/ldbedit.c | 22 ++++- source4/lib/ldb/tools/ldbmodify.c | 22 ++++- source4/lib/ldb/tools/ldbrename.c | 22 ++++- source4/lib/ldb/tools/ldbsearch.c | 23 ++++- source4/lib/ldb/tools/ldbtest.c | 22 ++++- 17 files changed, 487 insertions(+), 290 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 38456a75e4..7666f5bd31 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -23,9 +23,11 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ - common/ldb_alloc.o common/ldb_debug.o + common/ldb_alloc.o common/ldb_debug.o common/ldb_modules.o -OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) +MODULES_OBJ=modules/timestamps.o + +OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a @@ -67,7 +69,7 @@ bin/ldbtest: tools/ldbtest.o $(LIBS) $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) manpages: - man/build_manpages.sh + -man/build_manpages.sh clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) man/man?/*.[13] diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index fa4a64c19d..4fe2088daf 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -47,20 +47,32 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, const char *options[]) { + struct ldb_context *ldb_ctx = NULL; if (strncmp(url, "tdb:", 4) == 0 || strchr(url, ':') == NULL) { - return ltdb_connect(url, flags, options); + ldb_ctx = ltdb_connect(url, flags, options); } #if HAVE_LDAP if (strncmp(url, "ldap", 4) == 0) { - return lldb_connect(url, flags, options); + ldb_ctx = lldb_connect(url, flags, options); } #endif - errno = EINVAL; - return NULL; + + if (!ldb_ctx) { + errno = EINVAL; + return NULL; + } + + if (ldb_load_modules(ldb_ctx, options) != 0) { + ldb_close(ldb_ctx); + errno = EINVAL; + return NULL; + } + + return ldb_ctx; } /* @@ -68,8 +80,7 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, */ int ldb_close(struct ldb_context *ldb) { - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_close"); - return ldb->ops->close(ldb); + return ldb->modules->ops->close(ldb->modules); } @@ -84,12 +95,7 @@ int ldb_search(struct ldb_context *ldb, const char *expression, const char * const *attrs, struct ldb_message ***res) { - int ret; - ret = ldb->ops->search(ldb, base, scope, expression, attrs, res); - - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_search(%s) -> %d records\n", - expression, ret); - return ret; + return ldb->modules->ops->search(ldb->modules, base, scope, expression, attrs, res); } /* @@ -97,7 +103,7 @@ int ldb_search(struct ldb_context *ldb, */ int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) { - return ldb->ops->search_free(ldb, msgs); + return ldb->modules->ops->search_free(ldb->modules, msgs); } @@ -108,10 +114,7 @@ int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { - int ret; - ret = ldb->ops->add_record(ldb, message); - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_add(%s) -> %d\n", message->dn, ret); - return ret; + return ldb->modules->ops->add_record(ldb->modules, message); } /* @@ -120,11 +123,7 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { - int ret; - ret = ldb->ops->modify_record(ldb, message); - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_modify(%s) -> %d\n", - message->dn, ret); - return ret; + return ldb->modules->ops->modify_record(ldb->modules, message); } @@ -133,10 +132,7 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const char *dn) { - int ret; - ret = ldb->ops->delete_record(ldb, dn); - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_delete(%s) -> %d\n", dn, ret); - return ret; + return ldb->modules->ops->delete_record(ldb->modules, dn); } /* @@ -144,10 +140,7 @@ int ldb_delete(struct ldb_context *ldb, const char *dn) */ int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) { - int ret; - ret = ldb->ops->rename_record(ldb, olddn, newdn); - ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_rename(%s,%s) -> %d\n", olddn, newdn); - return ret; + return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); } /* @@ -155,5 +148,6 @@ int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) */ const char *ldb_errstring(struct ldb_context *ldb) { - return ldb->ops->errstring(ldb); + return ldb->modules->ops->errstring(ldb->modules); } + diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 81c6382292..46fd4e12ae 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -1,3 +1,12 @@ +################################################ +# Start MODULE libldb_timestamps +[MODULE::libldb_timestamps] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/modules/timestamps.o +# End MODULE libldb_timestamps +################################################ + ################################################ # Start MODULE libldb_ldap [MODULE::libldb_ldap] @@ -38,7 +47,8 @@ ADD_OBJ_FILES = \ lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_alloc.o \ - lib/ldb/common/ldb_debug.o + lib/ldb/common/ldb_debug.o \ + lib/ldb/common/ldb_modules.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE # diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 3c78f12fb5..6a06678e0e 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -121,26 +121,39 @@ struct ldb_context; typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *); +struct ldb_module_ops; + +/* basic module structure */ +struct ldb_module { + struct ldb_module *prev, *next; + struct ldb_context *ldb; + void *private_data; + const struct ldb_module_ops *ops; +}; + /* - these function pointers define the operations that a ldb backend must perform + these function pointers define the operations that a ldb module must perform they correspond exactly to the ldb_*() interface */ -struct ldb_backend_ops { - int (*close)(struct ldb_context *); - int (*search)(struct ldb_context *, const char *, enum ldb_scope, +struct ldb_module_ops { + const char *name; + int (*close)(struct ldb_module *); + int (*search)(struct ldb_module *, const char *, enum ldb_scope, const char *, const char * const [], struct ldb_message ***); - int (*search_free)(struct ldb_context *, struct ldb_message **); - int (*add_record)(struct ldb_context *, const struct ldb_message *); - int (*modify_record)(struct ldb_context *, const struct ldb_message *); - int (*delete_record)(struct ldb_context *, const char *); - int (*rename_record)(struct ldb_context *, const char *olddn, const char *newdn); - const char * (*errstring)(struct ldb_context *); + int (*search_free)(struct ldb_module *, struct ldb_message **); + int (*add_record)(struct ldb_module *, const struct ldb_message *); + int (*modify_record)(struct ldb_module *, const struct ldb_message *); + int (*delete_record)(struct ldb_module *, const char *); + int (*rename_record)(struct ldb_module *, const char *, const char *); + const char * (*errstring)(struct ldb_module *); /* this is called when the alloc ops changes to ensure we don't have any old allocated data in the context */ - void (*cache_free)(struct ldb_context *); + void (*cache_free)(struct ldb_module *); }; +/* the modules init function */ +typedef struct ldb_module *(*init_ldb_module_function)(void); /* the user can optionally supply a allocator function. It is presumed @@ -172,11 +185,8 @@ struct ldb_debug_ops { every ldb connection is started by establishing a ldb_context */ struct ldb_context { - /* a private pointer for the backend to use */ - void *private_data; - /* the operations provided by the backend */ - const struct ldb_backend_ops *ops; + struct ldb_module *modules; /* memory allocation info */ struct ldb_alloc_ops alloc_ops; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 9ac51b26fe..96aee088a7 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -68,10 +68,11 @@ static const char *lldb_option_find(const struct lldb_private *lldb, const char /* close/free the connection */ -static int lldb_close(struct ldb_context *ldb) +static int lldb_close(struct ldb_module *module) { int i, ret = 0; - struct lldb_private *lldb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) { ret = -1; @@ -94,9 +95,10 @@ static int lldb_close(struct ldb_context *ldb) /* rename a record */ -static int lldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn) { - struct lldb_private *lldb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; int ret = 0; char *newrdn, *p; const char *parentdn = ""; @@ -129,9 +131,9 @@ static int lldb_rename(struct ldb_context *ldb, const char *olddn, const char *n /* delete a record */ -static int lldb_delete(struct ldb_context *ldb, const char *dn) +static int lldb_delete(struct ldb_module *module, const char *dn) { - struct lldb_private *lldb = ldb->private_data; + struct lldb_private *lldb = module->private_data; int ret = 0; /* ignore ltdb specials */ @@ -171,8 +173,9 @@ static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) /* free a search result */ -static int lldb_search_free(struct ldb_context *ldb, struct ldb_message **res) +static int lldb_search_free(struct ldb_module *module, struct ldb_message **res) { + struct ldb_context *ldb = module->ldb; int i; for (i=0;res[i];i++) { if (lldb_msg_free(ldb, res[i]) != 0) { @@ -243,11 +246,12 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, /* search for matching records */ -static int lldb_search(struct ldb_context *ldb, const char *base, +static int lldb_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { - struct lldb_private *lldb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; int count, msg_count; LDAPMessage *ldapres, *msg; @@ -335,7 +339,7 @@ static int lldb_search(struct ldb_context *ldb, const char *base, return msg_count; failed: - if (*res) lldb_search_free(ldb, *res); + if (*res) lldb_search_free(module, *res); return -1; } @@ -434,9 +438,10 @@ failed: /* add a record */ -static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) +static int lldb_add(struct ldb_module *module, const struct ldb_message *msg) { - struct lldb_private *lldb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; LDAPMod **mods; int ret = 0; @@ -461,9 +466,10 @@ static int lldb_add(struct ldb_context *ldb, const struct ldb_message *msg) /* modify a record */ -static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) { - struct lldb_private *lldb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; LDAPMod **mods; int ret = 0; @@ -488,14 +494,15 @@ static int lldb_modify(struct ldb_context *ldb, const struct ldb_message *msg) /* return extended error information */ -static const char *lldb_errstring(struct ldb_context *ldb) +static const char *lldb_errstring(struct ldb_module *module) { - struct lldb_private *lldb = ldb->private_data; + struct lldb_private *lldb = module->private_data; return ldap_err2string(lldb->last_rc); } -static const struct ldb_backend_ops lldb_ops = { +static const struct ldb_module_ops lldb_ops = { + "ldap", lldb_close, lldb_search, lldb_search_free, @@ -544,8 +551,16 @@ struct ldb_context *lldb_connect(const char *url, goto failed; } - ldb->ops = &lldb_ops; - ldb->private_data = lldb; + ldb->modules = ldb_malloc_p(ldb, struct ldb_module); + if (!ldb->modules) { + ldb_free(ldb, ldb); + errno = ENOMEM; + goto failed; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = lldb; + ldb->modules->ops = &lldb_ops; if (options) { /* take a copy of the options array, so we don't have to rely diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 55dea406b5..cf175090e6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -38,9 +38,10 @@ /* initialise the baseinfo record */ -static int ltdb_baseinfo_init(struct ldb_context *ldb) +static int ltdb_baseinfo_init(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; struct ldb_message msg; struct ldb_message_element el; struct ldb_val val; @@ -77,7 +78,7 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) } val.length = 1; - ret = ltdb_store(ldb, &msg, TDB_INSERT); + ret = ltdb_store(module, &msg, TDB_INSERT); ldb_free(ldb, msg.dn); ldb_free(ldb, el.name); @@ -89,17 +90,18 @@ static int ltdb_baseinfo_init(struct ldb_context *ldb) /* free any cache records */ -void ltdb_cache_free(struct ldb_context *ldb) +void ltdb_cache_free(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; struct ldb_alloc_ops alloc = ldb->alloc_ops; ldb->alloc_ops.alloc = NULL; ltdb->sequence_number = 0; - ltdb_search_dn1_free(ldb, <db->cache.baseinfo); - ltdb_search_dn1_free(ldb, <db->cache.indexlist); - ltdb_search_dn1_free(ldb, <db->cache.subclasses); - ltdb_search_dn1_free(ldb, <db->cache.attributes); + ltdb_search_dn1_free(module, <db->cache.baseinfo); + ltdb_search_dn1_free(module, <db->cache.indexlist); + ltdb_search_dn1_free(module, <db->cache.subclasses); + ltdb_search_dn1_free(module, <db->cache.attributes); ldb_free(ldb, ltdb->cache.last_attribute.name); memset(<db->cache, 0, sizeof(ltdb->cache)); @@ -110,26 +112,27 @@ void ltdb_cache_free(struct ldb_context *ldb) /* load the cache records */ -int ltdb_cache_load(struct ldb_context *ldb) +int ltdb_cache_load(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; double seq; struct ldb_alloc_ops alloc = ldb->alloc_ops; ldb->alloc_ops.alloc = NULL; - ltdb_search_dn1_free(ldb, <db->cache.baseinfo); + ltdb_search_dn1_free(module, <db->cache.baseinfo); - if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { + if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { goto failed; } /* possibly initialise the baseinfo */ if (!ltdb->cache.baseinfo.dn) { - if (ltdb_baseinfo_init(ldb) != 0) { + if (ltdb_baseinfo_init(module) != 0) { goto failed; } - if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { + if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { goto failed; } } @@ -145,17 +148,17 @@ int ltdb_cache_load(struct ldb_context *ldb) ldb_free(ldb, ltdb->cache.last_attribute.name); memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute)); - ltdb_search_dn1_free(ldb, <db->cache.indexlist); - ltdb_search_dn1_free(ldb, <db->cache.subclasses); - ltdb_search_dn1_free(ldb, <db->cache.attributes); + ltdb_search_dn1_free(module, <db->cache.indexlist); + ltdb_search_dn1_free(module, <db->cache.subclasses); + ltdb_search_dn1_free(module, <db->cache.attributes); - if (ltdb_search_dn1(ldb, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { + if (ltdb_search_dn1(module, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { goto failed; } - if (ltdb_search_dn1(ldb, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { + if (ltdb_search_dn1(module, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { goto failed; } - if (ltdb_search_dn1(ldb, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { + if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { goto failed; } @@ -172,9 +175,10 @@ failed: /* increase the sequence number to indicate a database change */ -int ltdb_increase_sequence_number(struct ldb_context *ldb) +int ltdb_increase_sequence_number(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; struct ldb_message msg; struct ldb_message_element el; struct ldb_val val; @@ -197,7 +201,7 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) val.data = s; val.length = strlen(s); - ret = ltdb_modify_internal(ldb, &msg); + ret = ltdb_modify_internal(module, &msg); ldb_free(ldb, s); ldb_free(ldb, msg.dn); @@ -215,9 +219,10 @@ int ltdb_increase_sequence_number(struct ldb_context *ldb) return the attribute flags from the @ATTRIBUTES record for the given attribute */ -int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) +int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; const char *attrs; const struct { const char *name; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index cfd097e361..d54208777d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -107,11 +107,12 @@ static int list_cmp(const char **s1, const char **s2) /* return a list of dn's that might match a simple indexed search or */ -static int ltdb_index_dn_simple(struct ldb_context *ldb, +static int ltdb_index_dn_simple(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) { + struct ldb_context *ldb = module->ldb; char *dn = NULL; int ret; unsigned int i, j; @@ -123,7 +124,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* if the value is a wildcard then we can't do a match via indexing */ - if (ltdb_has_wildcard(ldb, tree->u.simple.attr, &tree->u.simple.value)) { + if (ltdb_has_wildcard(module, tree->u.simple.attr, &tree->u.simple.value)) { return -1; } @@ -138,7 +139,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, dn = ldb_dn_key(ldb, tree->u.simple.attr, &tree->u.simple.value); if (!dn) return -1; - ret = ltdb_search_dn1(ldb, dn, &msg); + ret = ltdb_search_dn1(module, dn, &msg); ldb_free(ldb, dn); if (ret == 0 || ret == -1) { return ret; @@ -163,14 +164,14 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, ldb_strdup(ldb, (char *)el->values[j].data); if (!list->dn[list->count]) { dn_list_free(ldb, list); - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); return -1; } list->count++; } } - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp); @@ -184,12 +185,13 @@ static int list_union(struct ldb_context *, struct dn_list *, const struct dn_li return a list of dn's that might match a simple indexed search on the special objectclass attribute */ -static int ltdb_index_dn_objectclass(struct ldb_context *ldb, +static int ltdb_index_dn_objectclass(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; unsigned int i; int ret; const char *target = tree->u.simple.value.data; @@ -197,7 +199,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, list->count = 0; list->dn = NULL; - ret = ltdb_index_dn_simple(ldb, tree, index_list, list); + ret = ltdb_index_dn_simple(module, tree, index_list, list); for (i=0;icache.subclasses.num_elements;i++) { struct ldb_message_element *el = <db->cache.subclasses.elements[i]; @@ -212,7 +214,7 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, return -1; } tree2.u.simple.value = el->values[j]; - if (ltdb_index_dn_objectclass(ldb, &tree2, + if (ltdb_index_dn_objectclass(module, &tree2, index_list, &list2) == 1) { if (list->count == 0) { *list = list2; @@ -233,15 +235,15 @@ static int ltdb_index_dn_objectclass(struct ldb_context *ldb, /* return a list of dn's that might match a leaf indexed search */ -static int ltdb_index_dn_leaf(struct ldb_context *ldb, +static int ltdb_index_dn_leaf(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) { if (ldb_attr_cmp(tree->u.simple.attr, LTDB_OBJECTCLASS) == 0) { - return ltdb_index_dn_objectclass(ldb, tree, index_list, list); + return ltdb_index_dn_objectclass(module, tree, index_list, list); } - return ltdb_index_dn_simple(ldb, tree, index_list, list); + return ltdb_index_dn_simple(module, tree, index_list, list); } @@ -331,7 +333,7 @@ static int list_union(struct ldb_context *ldb, return 0; } -static int ltdb_index_dn(struct ldb_context *ldb, +static int ltdb_index_dn(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list); @@ -340,11 +342,12 @@ static int ltdb_index_dn(struct ldb_context *ldb, /* OR two index results */ -static int ltdb_index_dn_or(struct ldb_context *ldb, +static int ltdb_index_dn_or(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) { + struct ldb_context *ldb = module->ldb; unsigned int i; int ret; @@ -355,7 +358,7 @@ static int ltdb_index_dn_or(struct ldb_context *ldb, for (i=0;iu.list.num_elements;i++) { struct dn_list list2; int v; - v = ltdb_index_dn(ldb, tree->u.list.elements[i], index_list, &list2); + v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, &list2); if (v == 0) { /* 0 || X == X */ @@ -395,7 +398,7 @@ static int ltdb_index_dn_or(struct ldb_context *ldb, /* NOT an index results */ -static int ltdb_index_dn_not(struct ldb_context *ldb, +static int ltdb_index_dn_not(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) @@ -414,11 +417,12 @@ static int ltdb_index_dn_not(struct ldb_context *ldb, /* AND two index results */ -static int ltdb_index_dn_and(struct ldb_context *ldb, +static int ltdb_index_dn_and(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) { + struct ldb_context *ldb = module->ldb; unsigned int i; int ret; @@ -429,7 +433,7 @@ static int ltdb_index_dn_and(struct ldb_context *ldb, for (i=0;iu.list.num_elements;i++) { struct dn_list list2; int v; - v = ltdb_index_dn(ldb, tree->u.list.elements[i], index_list, &list2); + v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, &list2); if (v == 0) { /* 0 && X == 0 */ @@ -465,7 +469,7 @@ static int ltdb_index_dn_and(struct ldb_context *ldb, return a list of dn's that might match a indexed search or -1 if an error. return 0 for no matches, or 1 for matches */ -static int ltdb_index_dn(struct ldb_context *ldb, +static int ltdb_index_dn(struct ldb_module *module, struct ldb_parse_tree *tree, const struct ldb_message *index_list, struct dn_list *list) @@ -474,19 +478,19 @@ static int ltdb_index_dn(struct ldb_context *ldb, switch (tree->operation) { case LDB_OP_SIMPLE: - ret = ltdb_index_dn_leaf(ldb, tree, index_list, list); + ret = ltdb_index_dn_leaf(module, tree, index_list, list); break; case LDB_OP_AND: - ret = ltdb_index_dn_and(ldb, tree, index_list, list); + ret = ltdb_index_dn_and(module, tree, index_list, list); break; case LDB_OP_OR: - ret = ltdb_index_dn_or(ldb, tree, index_list, list); + ret = ltdb_index_dn_or(module, tree, index_list, list); break; case LDB_OP_NOT: - ret = ltdb_index_dn_not(ldb, tree, index_list, list); + ret = ltdb_index_dn_not(module, tree, index_list, list); break; } @@ -497,7 +501,7 @@ static int ltdb_index_dn(struct ldb_context *ldb, filter a candidate dn_list from an indexed search into a set of results extracting just the given attributes */ -static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree, +static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tree, const char *base, enum ldb_scope scope, const struct dn_list *dn_list, @@ -508,7 +512,7 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree for (i=0;icount;i++) { struct ldb_message msg; int ret; - ret = ltdb_search_dn1(ldb, dn_list->dn[i], &msg); + ret = ltdb_search_dn1(module, dn_list->dn[i], &msg); if (ret == 0) { /* the record has disappeared? yes, this can happen */ continue; @@ -519,10 +523,10 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree return -1; } - if (ldb_message_match(ldb, &msg, tree, base, scope) == 1) { - ret = ltdb_add_attr_results(ldb, &msg, attrs, &count, res); + if (ldb_message_match(module, &msg, tree, base, scope) == 1) { + ret = ltdb_add_attr_results(module, &msg, attrs, &count, res); } - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); if (ret != 0) { return -1; } @@ -536,13 +540,14 @@ static int ldb_index_filter(struct ldb_context *ldb, struct ldb_parse_tree *tree returns -1 if an indexed search is not possible, in which case the caller should call ltdb_search_full() */ -int ltdb_search_indexed(struct ldb_context *ldb, +int ltdb_search_indexed(struct ldb_module *module, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; struct dn_list dn_list; int ret; @@ -551,12 +556,12 @@ int ltdb_search_indexed(struct ldb_context *ldb, return -1; } - ret = ltdb_index_dn(ldb, tree, <db->cache.indexlist, &dn_list); + ret = ltdb_index_dn(module, tree, <db->cache.indexlist, &dn_list); if (ret == 1) { /* we've got a candidate list - now filter by the full tree and extract the needed attributes */ - ret = ldb_index_filter(ldb, tree, base, scope, &dn_list, + ret = ldb_index_filter(module, tree, base, scope, &dn_list, attrs, res); dn_list_free(ldb, &dn_list); } @@ -638,9 +643,10 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, /* add an index entry for one message element */ -static int ltdb_index_add1(struct ldb_context *ldb, char *dn, +static int ltdb_index_add1(struct ldb_module *module, char *dn, struct ldb_message_element *el, int v_idx) { + struct ldb_context *ldb = module->ldb; struct ldb_message msg; char *dn_key; int ret, added=0, added_dn=0; @@ -651,7 +657,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, return -1; } - ret = ltdb_search_dn1(ldb, dn_key, &msg); + ret = ltdb_search_dn1(module, dn_key, &msg); if (ret == -1) { ldb_free(ldb, dn_key); return -1; @@ -686,7 +692,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, } if (ret == 0) { - ret = ltdb_store(ldb, &msg, TDB_REPLACE); + ret = ltdb_store(module, &msg, TDB_REPLACE); } if (added) { @@ -696,7 +702,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, ldb_free(ldb, msg.dn); } - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); return ret; } @@ -705,9 +711,9 @@ static int ltdb_index_add1(struct ldb_context *ldb, char *dn, add the index entries for a new record return -1 on failure */ -int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) +int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; unsigned int i, j; @@ -723,7 +729,7 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) continue; } for (j=0;jelements[i].num_values;j++) { - ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i], j); + ret = ltdb_index_add1(module, msg->dn, &msg->elements[i], j); if (ret == -1) { return -1; } @@ -737,9 +743,10 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) /* delete an index entry for one message element */ -static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, +static int ltdb_index_del1(struct ldb_module *module, const char *dn, struct ldb_message_element *el, int v_idx) { + struct ldb_context *ldb = module->ldb; struct ldb_message msg; char *dn_key; int ret, i; @@ -750,7 +757,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, return -1; } - ret = ltdb_search_dn1(ldb, dn_key, &msg); + ret = ltdb_search_dn1(module, dn_key, &msg); if (ret == -1) { ldb_free(ldb, dn_key); return -1; @@ -768,7 +775,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, if (i == -1) { ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn %s not found in %s\n", dn, dn_key); /* it ain't there. hmmm */ - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); ldb_free(ldb, dn_key); return 0; } @@ -782,12 +789,12 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, msg.elements[i].num_values--; if (msg.elements[i].num_values == 0) { - ret = ltdb_delete_noindex(ldb, dn_key); + ret = ltdb_delete_noindex(module, dn_key); } else { - ret = ltdb_store(ldb, &msg, TDB_REPLACE); + ret = ltdb_store(module, &msg, TDB_REPLACE); } - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); ldb_free(ldb, dn_key); return ret; @@ -797,9 +804,9 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, delete the index entries for a record return -1 on failure */ -int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) +int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; unsigned int i, j; @@ -816,7 +823,7 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) continue; } for (j=0;jelements[i].num_values;j++) { - ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i], j); + ret = ltdb_index_del1(module, msg->dn, &msg->elements[i], j); if (ret == -1) { return -1; } @@ -844,7 +851,7 @@ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, vo */ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { - struct ldb_context *ldb = state; + struct ldb_module *module = state; struct ldb_message msg; int ret; @@ -853,7 +860,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return 0; } - ret = ltdb_unpack_data(ldb, &data, &msg); + ret = ltdb_unpack_data(module->ldb, &data, &msg); if (ret != 0) { return -1; } @@ -862,9 +869,9 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * msg.dn = key.dptr+3; } - ret = ltdb_index_add(ldb, &msg); + ret = ltdb_index_add(module, &msg); - ltdb_unpack_data_free(ldb, &msg); + ltdb_unpack_data_free(module->ldb, &msg); return ret; } @@ -872,14 +879,14 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * /* force a complete reindex of the database */ -int ltdb_reindex(struct ldb_context *ldb) +int ltdb_reindex(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; - ltdb_cache_free(ldb); + ltdb_cache_free(module); - if (ltdb_cache_load(ldb) != 0) { + if (ltdb_cache_load(module) != 0) { return -1; } @@ -891,7 +898,7 @@ int ltdb_reindex(struct ldb_context *ldb) } /* now traverse adding any indexes for normal LDB records */ - ret = tdb_traverse(ltdb->tdb, re_index, ldb); + ret = tdb_traverse(ltdb->tdb, re_index, module); if (ret == -1) { errno = EIO; return -1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 6f55496042..52e9f5afc7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -137,10 +137,10 @@ static int ldb_val_equal_wildcard(struct ldb_context *ldb, return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_objectclass(struct ldb_context *ldb, +static int ldb_val_equal_objectclass(struct ldb_module *module, const struct ldb_val *v1, const struct ldb_val *v2) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; unsigned int i; if (ldb_val_equal_case_insensitive(v1, v2) == 1) { @@ -152,7 +152,7 @@ static int ldb_val_equal_objectclass(struct ldb_context *ldb, if (ldb_attr_cmp(el->name, v2->data) == 0) { unsigned int j; for (j=0;jnum_values;j++) { - if (ldb_val_equal_objectclass(ldb, v1, &el->values[j])) { + if (ldb_val_equal_objectclass(module, v1, &el->values[j])) { return 1; } } @@ -171,14 +171,15 @@ static int ldb_val_equal_objectclass(struct ldb_context *ldb, return 1 for a match, 0 for a mis-match */ -int ldb_val_equal(struct ldb_context *ldb, +int ldb_val_equal(struct ldb_module *module, const char *attr_name, const struct ldb_val *v1, const struct ldb_val *v2) { - int flags = ltdb_attribute_flags(ldb, attr_name); + struct ldb_context *ldb = module->ldb; + int flags = ltdb_attribute_flags(module, attr_name); if (flags & LTDB_FLAG_OBJECTCLASS) { - return ldb_val_equal_objectclass(ldb, v1, v2); + return ldb_val_equal_objectclass(module, v1, v2); } if (flags & LTDB_FLAG_INTEGER) { @@ -254,7 +255,7 @@ static int scope_match(const char *dn, const char *base, enum ldb_scope scope) /* match a leaf node */ -static int match_leaf(struct ldb_context *ldb, +static int match_leaf(struct ldb_module *module, struct ldb_message *msg, struct ldb_parse_tree *tree, const char *base, @@ -279,7 +280,7 @@ static int match_leaf(struct ldb_context *ldb, return 1; } for (j=0;jelements[i].num_values;j++) { - if (ldb_val_equal(ldb, msg->elements[i].name, + if (ldb_val_equal(module, msg->elements[i].name, &msg->elements[i].values[j], &tree->u.simple.value)) { return 1; @@ -299,7 +300,7 @@ static int match_leaf(struct ldb_context *ldb, this is a recursive function, and does short-circuit evaluation */ -int ldb_message_match(struct ldb_context *ldb, +int ldb_message_match(struct ldb_module *module, struct ldb_message *msg, struct ldb_parse_tree *tree, const char *base, @@ -313,11 +314,11 @@ int ldb_message_match(struct ldb_context *ldb, break; case LDB_OP_NOT: - return ! ldb_message_match(ldb, msg, tree->u.not.child, base, scope); + return ! ldb_message_match(module, msg, tree->u.not.child, base, scope); case LDB_OP_AND: for (i=0;iu.list.num_elements;i++) { - v = ldb_message_match(ldb, msg, tree->u.list.elements[i], + v = ldb_message_match(module, msg, tree->u.list.elements[i], base, scope); if (!v) return 0; } @@ -325,12 +326,12 @@ int ldb_message_match(struct ldb_context *ldb, case LDB_OP_OR: for (i=0;iu.list.num_elements;i++) { - v = ldb_message_match(ldb, msg, tree->u.list.elements[i], + v = ldb_message_match(module, msg, tree->u.list.elements[i], base, scope); if (v) return 1; } return 0; } - return match_leaf(ldb, msg, tree, base, scope); + return match_leaf(module, msg, tree, base, scope); } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 18d51d1aa4..cb93483881 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -131,12 +131,14 @@ static int msg_add_element(struct ldb_context *ldb, /* add all elements from one message into another */ -static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret, +static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret, const struct ldb_message *msg) { + struct ldb_context *ldb = module->ldb; unsigned int i; + for (i=0;inum_elements;i++) { - int flags = ltdb_attribute_flags(ldb, msg->elements[i].name); + int flags = ltdb_attribute_flags(module, msg->elements[i].name); if ((msg->dn[0] != '@') && (flags & LTDB_FLAG_HIDDEN)) { continue; } @@ -152,10 +154,11 @@ static int msg_add_all_elements(struct ldb_context *ldb, struct ldb_message *ret /* pull the specified list of attributes from a message */ -static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, +static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, const struct ldb_message *msg, const char * const *attrs) { + struct ldb_context *ldb = module->ldb; struct ldb_message *ret; int i; @@ -175,7 +178,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, ret->private_data = NULL; if (!attrs) { - if (msg_add_all_elements(ldb, ret, msg) != 0) { + if (msg_add_all_elements(module, ret, msg) != 0) { msg_free_all_parts(ldb, ret); return NULL; } @@ -186,7 +189,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, struct ldb_message_element *el; if (strcmp(attrs[i], "*") == 0) { - if (msg_add_all_elements(ldb, ret, msg) != 0) { + if (msg_add_all_elements(module, ret, msg) != 0) { msg_free_all_parts(ldb, ret); return NULL; } @@ -237,7 +240,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, see if a ldb_val is a wildcard return 1 if yes, 0 if no */ -int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, +int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val) { int flags; @@ -251,7 +254,7 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, return 0; } - flags = ltdb_attribute_flags(ldb, attr_name); + flags = ltdb_attribute_flags(module, attr_name); if (flags & LTDB_FLAG_WILDCARD) { return 1; } @@ -263,8 +266,9 @@ int ltdb_has_wildcard(struct ldb_context *ldb, const char *attr_name, /* free the results of a ltdb_search_dn1 search */ -void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) +void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg) { + struct ldb_context *ldb = module->ldb; unsigned int i; ldb_free(ldb, msg->private_data); for (i=0;inum_elements;i++) { @@ -281,16 +285,17 @@ void ltdb_search_dn1_free(struct ldb_context *ldb, struct ldb_message *msg) return 1 on success, 0 on record-not-found and -1 on error */ -int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message *msg) +int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; int ret; TDB_DATA tdb_key, tdb_data, tdb_data2; memset(msg, 0, sizeof(*msg)); /* form the key */ - tdb_key = ltdb_key(ldb, dn); + tdb_key = ltdb_key(module, dn); if (!tdb_key.dptr) { return -1; } @@ -335,20 +340,21 @@ int ltdb_search_dn1(struct ldb_context *ldb, const char *dn, struct ldb_message /* search the database for a single simple dn */ -int ltdb_search_dn(struct ldb_context *ldb, char *dn, +int ltdb_search_dn(struct ldb_module *module, char *dn, const char * const attrs[], struct ldb_message ***res) { + struct ldb_context *ldb = module->ldb; int ret; struct ldb_message msg, *msg2; - ret = ltdb_search_dn1(ldb, dn, &msg); + ret = ltdb_search_dn1(module, dn, &msg); if (ret != 1) { return ret; } - msg2 = ltdb_pull_attrs(ldb, &msg, attrs); + msg2 = ltdb_pull_attrs(module, &msg, attrs); - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); if (!msg2) { return -1; @@ -371,16 +377,17 @@ int ltdb_search_dn(struct ldb_context *ldb, char *dn, add a set of attributes from a record to a set of results return 0 on success, -1 on failure */ -int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, +int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], unsigned int *count, struct ldb_message ***res) { + struct ldb_context *ldb = module->ldb; struct ldb_message *msg2; struct ldb_message **res2; /* pull the attributes that the user wants */ - msg2 = ltdb_pull_attrs(ldb, msg, attrs); + msg2 = ltdb_pull_attrs(module, msg, attrs); if (!msg2) { return -1; } @@ -406,7 +413,7 @@ int ltdb_add_attr_results(struct ldb_context *ldb, struct ldb_message *msg, internal search state during a full db search */ struct ltdb_search_info { - struct ldb_context *ldb; + struct ldb_module *module; struct ldb_parse_tree *tree; const char *base; enum ldb_scope scope; @@ -432,7 +439,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* unpack the record */ - ret = ltdb_unpack_data(sinfo->ldb, &data, &msg); + ret = ltdb_unpack_data(sinfo->module->ldb, &data, &msg); if (ret == -1) { sinfo->failures++; return 0; @@ -443,19 +450,19 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* see if it matches the given expression */ - if (!ldb_message_match(sinfo->ldb, &msg, sinfo->tree, + if (!ldb_message_match(sinfo->module, &msg, sinfo->tree, sinfo->base, sinfo->scope)) { - ltdb_unpack_data_free(sinfo->ldb, &msg); + ltdb_unpack_data_free(sinfo->module->ldb, &msg); return 0; } - ret = ltdb_add_attr_results(sinfo->ldb, &msg, sinfo->attrs, &sinfo->count, &sinfo->msgs); + ret = ltdb_add_attr_results(sinfo->module, &msg, sinfo->attrs, &sinfo->count, &sinfo->msgs); if (ret == -1) { sinfo->failures++; } - ltdb_unpack_data_free(sinfo->ldb, &msg); + ltdb_unpack_data_free(sinfo->module->ldb, &msg); return ret; } @@ -464,9 +471,10 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi /* free a set of search results */ -int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) +int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; int i; ltdb->last_err_string = NULL; @@ -486,18 +494,18 @@ int ltdb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) search the database with a LDAP-like expression. this is the "full search" non-indexed variant */ -static int ltdb_search_full(struct ldb_context *ldb, +static int ltdb_search_full(struct ldb_module *module, const char *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; struct ltdb_search_info sinfo; sinfo.tree = tree; - sinfo.ldb = ldb; + sinfo.module = module; sinfo.scope = scope; sinfo.base = base; sinfo.attrs = attrs; @@ -508,7 +516,7 @@ static int ltdb_search_full(struct ldb_context *ldb, ret = tdb_traverse(ltdb->tdb, search_func, &sinfo); if (ret == -1) { - ltdb_search_free(ldb, sinfo.msgs); + ltdb_search_free(module, sinfo.msgs); return -1; } @@ -521,17 +529,18 @@ static int ltdb_search_full(struct ldb_context *ldb, search the database with a LDAP-like expression. choses a search method */ -int ltdb_search(struct ldb_context *ldb, const char *base, +int ltdb_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const attrs[], struct ldb_message ***res) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; struct ldb_parse_tree *tree; int ret; ltdb->last_err_string = NULL; - if (ltdb_cache_load(ldb) != 0) { + if (ltdb_cache_load(module) != 0) { return -1; } @@ -546,13 +555,13 @@ int ltdb_search(struct ldb_context *ldb, const char *base, if (tree->operation == LDB_OP_SIMPLE && ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 && - !ltdb_has_wildcard(ldb, tree->u.simple.attr, &tree->u.simple.value)) { + !ltdb_has_wildcard(module, tree->u.simple.attr, &tree->u.simple.value)) { /* yay! its a nice simple one */ - ret = ltdb_search_dn(ldb, tree->u.simple.value.data, attrs, res); + ret = ltdb_search_dn(module, tree->u.simple.value.data, attrs, res); } else { - ret = ltdb_search_indexed(ldb, base, scope, tree, attrs, res); + ret = ltdb_search_indexed(module, base, scope, tree, attrs, res); if (ret == -1) { - ret = ltdb_search_full(ldb, base, scope, tree, attrs, res); + ret = ltdb_search_full(module, base, scope, tree, attrs, res); } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 3d136ea014..a2aa5a7aca 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -45,8 +45,9 @@ note that the key for a record can depend on whether the dn refers to a case sensitive index record or not */ -struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn) +struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) { + struct ldb_context *ldb = module->ldb; TDB_DATA key; char *key_str = NULL; char *dn_folded = NULL; @@ -74,7 +75,7 @@ struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn) if (!attr_name) { goto failed; } - flags = ltdb_attribute_flags(ldb, attr_name); + flags = ltdb_attribute_flags(module, attr_name); if (flags & LTDB_FLAG_CASE_INSENSITIVE) { dn_folded = ldb_casefold(ldb, dn); @@ -119,13 +120,14 @@ failed: /* lock the database for write - currently a single lock is used */ -static int ltdb_lock(struct ldb_context *ldb) +static int ltdb_lock(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; TDB_DATA key; int ret; - key = ltdb_key(ldb, "LDBLOCK"); + key = ltdb_key(module, "LDBLOCK"); if (!key.dptr) { return -1; } @@ -140,12 +142,13 @@ static int ltdb_lock(struct ldb_context *ldb) /* unlock the database after a ltdb_lock() */ -static void ltdb_unlock(struct ldb_context *ldb) +static void ltdb_unlock(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; TDB_DATA key; - key = ltdb_key(ldb, "LDBLOCK"); + key = ltdb_key(module, "LDBLOCK"); if (!key.dptr) { return; } @@ -160,18 +163,18 @@ static void ltdb_unlock(struct ldb_context *ldb) we've made a modification to a dn - possibly reindex and update sequence number */ -static int ltdb_modified(struct ldb_context *ldb, const char *dn) +static int ltdb_modified(struct ldb_module *module, const char *dn) { int ret = 0; if (strcmp(dn, LTDB_INDEXLIST) == 0 || strcmp(dn, LTDB_ATTRIBUTES) == 0) { - ret = ltdb_reindex(ldb); + ret = ltdb_reindex(module); } if (ret == 0 && strcmp(dn, LTDB_BASEINFO) != 0) { - ret = ltdb_increase_sequence_number(ldb); + ret = ltdb_increase_sequence_number(module); } return ret; @@ -180,13 +183,14 @@ static int ltdb_modified(struct ldb_context *ldb, const char *dn) /* store a record into the db */ -int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) +int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key, tdb_data; int ret; - tdb_key = ltdb_key(ldb, msg->dn); + tdb_key = ltdb_key(module, msg->dn); if (!tdb_key.dptr) { return -1; } @@ -202,7 +206,7 @@ int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs) goto done; } - ret = ltdb_index_add(ldb, msg); + ret = ltdb_index_add(module, msg); if (ret == -1) { tdb_delete(ltdb->tdb, tdb_key); } @@ -218,29 +222,29 @@ done: /* add a record to the database */ -static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) +static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; ltdb->last_err_string = NULL; - if (ltdb_lock(ldb) != 0) { + if (ltdb_lock(module) != 0) { return -1; } - if (ltdb_cache_load(ldb) != 0) { - ltdb_unlock(ldb); + if (ltdb_cache_load(module) != 0) { + ltdb_unlock(module); return -1; } - ret = ltdb_store(ldb, msg, TDB_INSERT); + ret = ltdb_store(module, msg, TDB_INSERT); if (ret == 0) { - ltdb_modified(ldb, msg->dn); + ltdb_modified(module, msg->dn); } - ltdb_unlock(ldb); + ltdb_unlock(module); return ret; } @@ -249,13 +253,14 @@ static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg) delete a record from the database, not updating indexes (used for deleting index records) */ -int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) +int ltdb_delete_noindex(struct ldb_module *module, const char *dn) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key; int ret; - tdb_key = ltdb_key(ldb, dn); + tdb_key = ltdb_key(module, dn); if (!tdb_key.dptr) { return -1; } @@ -269,51 +274,51 @@ int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn) /* delete a record from the database */ -static int ltdb_delete(struct ldb_context *ldb, const char *dn) +static int ltdb_delete(struct ldb_module *module, const char *dn) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; struct ldb_message msg; ltdb->last_err_string = NULL; - if (ltdb_lock(ldb) != 0) { + if (ltdb_lock(module) != 0) { return -1; } - if (ltdb_cache_load(ldb) != 0) { - ltdb_unlock(ldb); + if (ltdb_cache_load(module) != 0) { + ltdb_unlock(module); return -1; } /* in case any attribute of the message was indexed, we need to fetch the old record */ - ret = ltdb_search_dn1(ldb, dn, &msg); + ret = ltdb_search_dn1(module, dn, &msg); if (ret != 1) { /* not finding the old record is an error */ goto failed; } - ret = ltdb_delete_noindex(ldb, dn); + ret = ltdb_delete_noindex(module, dn); if (ret == -1) { - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); goto failed; } /* remove any indexed attributes */ - ret = ltdb_index_del(ldb, &msg); + ret = ltdb_index_del(module, &msg); - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); if (ret == 0) { - ltdb_modified(ldb, dn); + ltdb_modified(module, dn); } - ltdb_unlock(ldb); + ltdb_unlock(module); return ret; failed: - ltdb_unlock(ldb); + ltdb_unlock(module); return -1; } @@ -416,11 +421,12 @@ static int msg_delete_attribute(struct ldb_context *ldb, return 0 on success, -1 on failure */ -static int msg_delete_element(struct ldb_context *ldb, +static int msg_delete_element(struct ldb_module *module, struct ldb_message *msg, const char *name, const struct ldb_val *val) { + struct ldb_context *ldb = module->ldb; unsigned int i; int found; struct ldb_message_element *el; @@ -433,7 +439,7 @@ static int msg_delete_element(struct ldb_context *ldb, el = &msg->elements[found]; for (i=0;inum_values;i++) { - if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) { + if (ldb_val_equal(module, msg->elements[i].name, &el->values[i], val)) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], sizeof(el->values[i])*(el->num_values-(i+1))); @@ -457,15 +463,16 @@ static int msg_delete_element(struct ldb_context *ldb, get away with it, but if we ever have really large attribute lists then we'll need to look at this again */ -int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) +int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key, tdb_data; struct ldb_message msg2; unsigned i, j; int ret; - tdb_key = ltdb_key(ldb, msg->dn); + tdb_key = ltdb_key(module, msg->dn); if (!tdb_key.dptr) { return -1; } @@ -527,7 +534,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) break; } for (j=0;jelements[i].num_values;j++) { - if (msg_delete_element(ldb, + if (msg_delete_element(module, &msg2, msg->elements[i].name, &msg->elements[i].values[j]) != 0) { @@ -540,7 +547,7 @@ int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg) } /* we've made all the mods - save the modified record back into the database */ - ret = ltdb_store(ldb, &msg2, TDB_MODIFY); + ret = ltdb_store(module, &msg2, TDB_MODIFY); ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); @@ -557,29 +564,29 @@ failed: /* modify a record */ -static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) +static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; int ret; ltdb->last_err_string = NULL; - if (ltdb_lock(ldb) != 0) { + if (ltdb_lock(module) != 0) { return -1; } - if (ltdb_cache_load(ldb) != 0) { - ltdb_unlock(ldb); + if (ltdb_cache_load(module) != 0) { + ltdb_unlock(module); return -1; } - ret = ltdb_modify_internal(ldb, msg); + ret = ltdb_modify_internal(module, msg); if (ret == 0) { - ltdb_modified(ldb, msg->dn); + ltdb_modified(module, msg->dn); } - ltdb_unlock(ldb); + ltdb_unlock(module); return ret; } @@ -587,22 +594,23 @@ static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg) /* rename a record */ -static int ltdb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +static int ltdb_rename(struct ldb_module *module, const char *olddn, const char *newdn) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; int ret; struct ldb_message msg; const char *error_str; ltdb->last_err_string = NULL; - if (ltdb_lock(ldb) != 0) { + if (ltdb_lock(module) != 0) { return -1; } /* in case any attribute of the message was indexed, we need to fetch the old record */ - ret = ltdb_search_dn1(ldb, olddn, &msg); + ret = ltdb_search_dn1(module, olddn, &msg); if (ret != 1) { /* not finding the old record is an error */ goto failed; @@ -610,46 +618,47 @@ static int ltdb_rename(struct ldb_context *ldb, const char *olddn, const char *n msg.dn = ldb_strdup(ldb,newdn); if (!msg.dn) { - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); goto failed; } - ret = ltdb_add(ldb, &msg); + ret = ltdb_add(module, &msg); if (ret == -1) { ldb_free(ldb, msg.dn); - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); goto failed; } ldb_free(ldb, msg.dn); - ltdb_search_dn1_free(ldb, &msg); + ltdb_search_dn1_free(module, &msg); - ret = ltdb_delete(ldb, olddn); + ret = ltdb_delete(module, olddn); error_str = ltdb->last_err_string; if (ret == -1) { - ltdb_delete(ldb, newdn); + ltdb_delete(module, newdn); } ltdb->last_err_string = error_str; - ltdb_unlock(ldb); + ltdb_unlock(module); return ret; failed: - ltdb_unlock(ldb); + ltdb_unlock(module); return -1; } /* close database */ -static int ltdb_close(struct ldb_context *ldb) +static int ltdb_close(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; int ret; ltdb->last_err_string = NULL; - ltdb_cache_free(ldb); + ltdb_cache_free(module); ldb_set_alloc(ldb, NULL, NULL); ret = tdb_close(ltdb->tdb); @@ -662,9 +671,9 @@ static int ltdb_close(struct ldb_context *ldb) /* return extended error information */ -static const char *ltdb_errstring(struct ldb_context *ldb) +static const char *ltdb_errstring(struct ldb_module *module) { - struct ltdb_private *ltdb = ldb->private_data; + struct ltdb_private *ltdb = module->private_data; if (ltdb->last_err_string) { return ltdb->last_err_string; } @@ -672,7 +681,8 @@ static const char *ltdb_errstring(struct ldb_context *ldb) } -static const struct ldb_backend_ops ltdb_ops = { +static const struct ldb_module_ops ltdb_ops = { + "tdb", ltdb_close, ltdb_search, ltdb_search_free, @@ -743,8 +753,17 @@ struct ldb_context *ltdb_connect(const char *url, memset(<db->cache, 0, sizeof(ltdb->cache)); - ldb->private_data = ltdb; - ldb->ops = <db_ops; + ldb->modules = ldb_malloc_p(ldb, struct ldb_module); + if (!ldb->modules) { + tdb_close(tdb); + free(ldb); + errno = ENOMEM; + return NULL; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = ltdb; + ldb->modules->ops = <db_ops; return ldb; } diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 9383197ed0..6d04800502 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -83,16 +83,34 @@ static int process_file(struct ldb_context *ldb, FILE *f) struct ldb_context *ldb; int count=0; const char *ldb_url; + const char **options = NULL; + int ldbopts; int opt, i; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hH:o:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -108,7 +126,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) argc -= optind; argv += optind; - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index d36db5429a..42dc9c19d8 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -72,13 +72,16 @@ static void usage(void) int main(int argc, char * const argv[]) { struct ldb_context *ldb; + const char **options = NULL; + int ldbopts; int ret, i; const char *ldb_url; int opt, recursive=0; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:r")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hH:ro:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; @@ -88,6 +91,21 @@ static void usage(void) recursive=1; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -108,7 +126,7 @@ static void usage(void) exit(1); } - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); exit(1); diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index b97c40ff1a..fc3b28872e 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -304,6 +304,8 @@ static void usage(void) const char *expression = NULL; const char *ldb_url; const char *basedn = NULL; + const char **options = NULL; + int ldbopts; int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; const char *editor; @@ -321,7 +323,8 @@ static void usage(void) editor = "vi"; } - while ((opt = getopt(argc, argv, "hab:e:H:s:v")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hab:e:H:s:vo:")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -353,6 +356,21 @@ static void usage(void) verbose++; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -381,7 +399,7 @@ static void usage(void) attrs = (const char * const *)argv; } - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index b6ca2993ce..823855ff1e 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -85,16 +85,34 @@ static int process_file(struct ldb_context *ldb, FILE *f) struct ldb_context *ldb; int count=0; const char *ldb_url; + const char **options = NULL; + int ldbopts; int opt, i; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hH:o:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -110,7 +128,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) argc -= optind; argv += optind; - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 3bc3c95208..3e47e17b17 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -51,16 +51,34 @@ static void usage(void) { struct ldb_context *ldb; const char *ldb_url; + const char **options = NULL; + int ldbopts; int opt, ret; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hH:o:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -76,7 +94,7 @@ static void usage(void) argc -= optind; argv += optind; - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 137299d89b..1e7bb1ce4c 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -89,13 +89,15 @@ static int do_search(struct ldb_context *ldb, const char * const * attrs = NULL; const char *ldb_url; const char *basedn = NULL; - int opt; + const char **options = NULL; + int opt, ldbopts; enum ldb_scope scope = LDB_SCOPE_SUBTREE; int interactive = 0, ret=0; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "b:H:s:hi")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "b:H:s:o:hi")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -119,6 +121,21 @@ static int do_search(struct ldb_context *ldb, interactive = 1; break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -143,7 +160,7 @@ static int do_search(struct ldb_context *ldb, attrs = (const char * const *)(argv+1); } - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); exit(1); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index e25a7cbcd6..5d90dc797d 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -358,13 +358,16 @@ static void usage(void) int main(int argc, char * const argv[]) { struct ldb_context *ldb; + const char **options = NULL; + int ldbopts; int opt; int nrecords = 5000; int nsearches = 2000; ldb_url = getenv("LDB_URL"); - while ((opt = getopt(argc, argv, "hH:r:s:b:")) != EOF) { + ldbopts = 0; + while ((opt = getopt(argc, argv, "hH:r:s:b:o:")) != EOF) { switch (opt) { case 'H': ldb_url = optarg; @@ -382,6 +385,21 @@ static void usage(void) nsearches = atoi(optarg); break; + case 'o': + ldbopts++; + if (options == NULL) { + options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); + } else { + options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); + if (options == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(-1); + } + } + options[ldbopts - 1] = optarg; + options[ldbopts] = NULL; + break; + case 'h': default: usage(); @@ -397,7 +415,7 @@ static void usage(void) argc -= optind; argv += optind; - ldb = ldb_connect(ldb_url, 0, NULL); + ldb = ldb_connect(ldb_url, 0, options); if (!ldb) { perror("ldb_connect"); -- cgit From 79ebe463e2aed9125c9086f6bff99adeef5e4b88 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Nov 2004 11:42:17 +0000 Subject: r3755: add missing files (This used to be commit 0b715b6ce21d23970d207d57e90133be17790d15) --- source4/lib/ldb/common/ldb_modules.c | 265 +++++++++++++++++++++++++++++++++ source4/lib/ldb/include/dlinklist.h | 93 ++++++++++++ source4/lib/ldb/modules/skel.c | 123 ++++++++++++++++ source4/lib/ldb/modules/timestamps.c | 277 +++++++++++++++++++++++++++++++++++ 4 files changed, 758 insertions(+) create mode 100644 source4/lib/ldb/common/ldb_modules.c create mode 100644 source4/lib/ldb/include/dlinklist.h create mode 100644 source4/lib/ldb/modules/skel.c create mode 100644 source4/lib/ldb/modules/timestamps.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c new file mode 100644 index 0000000000..a7cfd81d46 --- /dev/null +++ b/source4/lib/ldb/common/ldb_modules.c @@ -0,0 +1,265 @@ + +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb modules core + * + * Description: core modules routines + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "dlinklist.h" +#include +#include +#include + +#define LDB_MODULE_PREFIX "modules" +#define LDB_MODULE_PREFIX_LEN 7 +#define LDB_MODULE_SEP ':' + +int ldb_load_modules(struct ldb_context *ldb, const char *options[]) +{ + struct ldb_module *current; + char **modules; + char *p, *q; + int pn, i; + + /* find out which modules we are requested to activate */ + modules = NULL; + pn = 0; + + if (options) { + + for (i = 0; options[i] != NULL; i++) { + + if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) { + + p = q = ldb_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]); + if (*q != ':') { + ldb_free(ldb, q); + return -1; + } + do { + *p = '\0'; + q = p + 1; + pn++; + modules = ldb_realloc_array(ldb, modules, sizeof(char *), pn); + if (!modules) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); + return -1; + } + modules[pn - 1] = q; + } while ((p = strchr(q, LDB_MODULE_SEP))); + } + } + } + + if (!modules) { /* no modules in the options, look for @MODULES in the db */ + int ret, j, k; + char * attrs[] = { "@MODULE" }; + struct ldb_message **msg; + + ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msg); + if (ret == 0) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); + } else { + if (ret < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb)); + return -1; + } + if (ret > 1) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); + return -1; + } + + for (j = 0; j < msg[0]->num_elements; j++) { + for (k = 0; k < msg[0]->elements[j].num_values; k++) { + pn++; + modules = ldb_realloc_array(ldb, modules, sizeof(char *), pn); + if (!modules) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); + return -1; + } + modules[pn - 1] = ldb_strndup(ldb, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length); + if (!modules[pn - 1]) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); + return -1; + } + } + } + } + ldb_search_free(ldb, msg); + } + + if (modules) { + + for (i = 0; i < pn; i++) { + + if (strcmp(modules[i], "timestamps") == 0) { + current = timestamps_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } +#if 0 + if (strcmp(modules[i], "schema") == 0) { + current = schema_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } +#endif +#ifdef HAVE_DLOPEN_DISABLED + { + void *handle; + init_ldb_module_function init; + struct stat st; + const char *errstr; + + if (stat(modules[i], &st) < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + return -1; + } + + handle = dlopen(modules[i], RTLD_LAZY); + + if (!handle) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror()); + return -1; + } + + init = (init_ldb_module_function)dlsym(handle, "init_module"); + + errstr = dlerror(); + if (errstr) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr); + return -1; + } + + current = init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + } +#else + ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + return -1; +#endif + } + } + + return 0; +} + +/* + helper functions to call the next module in chain +*/ +int ldb_next_close(struct ldb_module *module) +{ + if (!module->next) { + return -1; + } + return module->next->ops->close(module->next); +} + +int ldb_next_search(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + if (!module->next) { + return -1; + } + return module->next->ops->search(module->next, base, scope, expression, attrs, res); +} + +int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg) +{ + if (!module->next) { + return -1; + } + return module->next->ops->search_free(module->next, msg); +} + +int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message) +{ + if (!module->next) { + return -1; + } + return module->next->ops->add_record(module->next, message); +} + +int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message) +{ + if (!module->next) { + return -1; + } + return module->next->ops->modify_record(module->next, message); +} + +int ldb_next_delete_record(struct ldb_module *module, const char *dn) +{ + if (!module->next) { + return -1; + } + return module->next->ops->delete_record(module->next, dn); +} + +int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + if (!module->next) { + return -1; + } + return module->next->ops->rename_record(module->next, olddn, newdn); +} + +const char *ldb_next_errstring(struct ldb_module *module) +{ + if (!module->next) { + return NULL; + } + return module->next->ops->errstring(module->next); +} + +void ldb_next_cache_free(struct ldb_module *module) +{ + if (!module->next) { + return; + } + module->next->ops->cache_free(module->next); +} diff --git a/source4/lib/ldb/include/dlinklist.h b/source4/lib/ldb/include/dlinklist.h new file mode 100644 index 0000000000..40f7f0a0c7 --- /dev/null +++ b/source4/lib/ldb/include/dlinklist.h @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + some simple double linked list macros + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + + +/* hook into the front of the list */ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* promote an element to the top of the list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* hook into the end of the list - needs a tmp pointer */ +#define DLIST_ADD_END(list, p, type) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + type tmp; \ + for (tmp = (list); tmp->next; tmp = tmp->next) ; \ + tmp->next = (p); \ + (p)->next = NULL; \ + (p)->prev = tmp; \ + } \ +} while (0) + +/* demote an element to the end of the list, needs a tmp pointer */ +#define DLIST_DEMOTE(list, p, tmp) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p, tmp); \ +} while (0) + +/* concatenate two lists - putting all elements of the 2nd list at the + end of the first list */ +#define DLIST_CONCATENATE(list1, list2, type) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + type tmp; \ + for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ + tmp->next = (list2); \ + (list2)->prev = tmp; \ + } \ +} while (0) diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c new file mode 100644 index 0000000000..1d6314ee74 --- /dev/null +++ b/source4/lib/ldb/modules/skel.c @@ -0,0 +1,123 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb skel module + * + * Description: example module + * + * Author: Simo Sorce + */ + +#include "includes.h" + +/* close */ +static int skel_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int skel_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int skel_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + +/* add_record */ +static int skel_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + return ldb_next_add_record(module, msg); +} + +/* modify_record */ +static int skel_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + return ldb_next_modify_record(module, msg); +} + +/* delete_record */ +static int skel_delete_record(struct ldb_module *module, const char *dn) +{ + return ldb_next_delete_record(module, dn); +} + +/* rename_record */ +static int skel_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + return ldb_next_rename_record(module, olddn, newdn); +} + +/* return extended error information */ +static const char *skel_errstring(struct ldb_module *module) +{ + return ldb_next_errstring(module); +} + +static void skel_cache_free(struct ldb_module *module) +{ + ldb_next_cache_free(module); +} + +static const struct ldb_module_ops skel_ops = { + "skel", + skel_close, + skel_search, + skel_search_free, + skel_add_record, + skel_modify_record, + skel_delete_record, + skel_rename_record, + skel_errstring, + skel_cache_free +}; + +#ifdef HAVE_DLOPEN + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + + ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + if (!ctx) + return NULL; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->private_data = NULL; + ctx->ops = &skel_ops; + + return ctx; +} diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c new file mode 100644 index 0000000000..64d7616fb1 --- /dev/null +++ b/source4/lib/ldb/modules/timestamps.c @@ -0,0 +1,277 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb timestamps module + * + * Description: add object timestamping functionality + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include + +static int timestamps_close(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); + return ldb_next_close(module); +} + +static int timestamps_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int timestamps_search_free(struct ldb_module *module, struct ldb_message **res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search_free\n"); + return ldb_next_search_free(module, res); +} + +static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) +{ + struct ldb_val *values; + char *name, *timestr; + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, attr_name) == 0) { + return 0; + } + } + + msg->elements = ldb_realloc_array(ldb, msg->elements, sizeof(struct ldb_message_element), msg->num_elements + 1); + name = ldb_strdup(ldb, attr_name); + timestr = ldb_strdup(ldb, time_string); + values = ldb_malloc(ldb, sizeof(struct ldb_val)); + if (!msg->elements || !name || !timestr || !values) { + return -1; + } + + msg->elements[msg->num_elements].name = name; + msg->elements[msg->num_elements].flags = flags; + msg->elements[msg->num_elements].num_values = 1; + msg->elements[msg->num_elements].values = values; + msg->elements[msg->num_elements].values[0].data = timestr; + msg->elements[msg->num_elements].values[0].length = strlen(timestr); + + msg->num_elements += 1; + + return 0; +} + +static void free_elements(struct ldb_context *ldb, struct ldb_message *msg, int real_el_num) +{ + int i; + + for (i = real_el_num; i < msg->num_elements; i++) { + ldb_free(ldb, msg->elements[i].name); + ldb_free(ldb, msg->elements[i].values[0].data); + ldb_free(ldb, msg->elements[i].values); + } + ldb_free(ldb, msg->elements); + ldb_free(ldb, msg); +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2 = NULL; + struct tm *tm; + char *timestr; + time_t timeval; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); + + if (msg->dn[0] != '@') { /* do not manipulate our control entries */ + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } + + /* formatted like: 20040408072012.0Z */ + ldb_asprintf(module->ldb, ×tr, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (!timestr) { + return -1; + } + + msg2 = ldb_malloc_p(module->ldb, struct ldb_message); + if (!msg2) { + return -1; + } + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + add_time_element(module->ldb, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + + ldb_free(module->ldb, timestr); + } + + if (msg2) { + ret = ldb_next_add_record(module, msg2); + free_elements(module->ldb, msg2, msg->num_elements); + } else { + ret = ldb_next_add_record(module, msg); + } + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2 = NULL; + struct tm *tm; + char *timestr; + time_t timeval; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); + + if (msg->dn[0] != '@') { /* do not manipulate our control entries */ + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } + + /* formatted like: 20040408072012.0Z */ + ldb_asprintf(module->ldb, ×tr, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + + if (!timestr) { + return -1; + } + + msg2 = ldb_malloc_p(module->ldb, struct ldb_message); + if (!msg2) { + return -1; + } + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + + ldb_free(module->ldb, timestr); + } + + if (msg2) { + ret = ldb_next_modify_record(module, msg2); + free_elements(module->ldb, msg2, msg->num_elements); + } else { + ret = ldb_next_modify_record(module, msg); + } + + return ret; +} + +static int timestamps_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int timestamps_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +/* return extended error information */ +static const char *timestamps_errstring(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); + return ldb_next_errstring(module); +} + +static void timestamps_cache_free(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_cache_free\n"); + ldb_next_cache_free(module); +} + +static const struct ldb_module_ops timestamps_ops = { + "timestamps", + timestamps_close, + timestamps_search, + timestamps_search_free, + timestamps_add_record, + timestamps_modify_record, + timestamps_delete_record, + timestamps_rename_record, + timestamps_errstring, + timestamps_cache_free +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + + ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + if (!ctx) + return NULL; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->private_data = NULL; + ctx->ops = ×tamps_ops; + + return ctx; +} -- cgit From 950f3eb508a70f2304f76a8307582690d4715670 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Nov 2004 12:30:28 +0000 Subject: r3757: Some fixes for ldb_ldap Now we pass also the test-ldap tests :-) (This used to be commit 0d58b1dc5aa0b00a924c1c5506f0c500c0b37b3e) --- source4/lib/ldb/common/ldb_modules.c | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 4 ++++ source4/lib/ldb/tests/init_slapd.sh | 4 +--- source4/lib/ldb/tests/slapd.conf | 4 ++-- source4/lib/ldb/tests/start_slapd.sh | 2 -- source4/lib/ldb/tests/test-generic.sh | 2 ++ source4/lib/ldb/tests/test-ldap.sh | 1 + 7 files changed, 11 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index a7cfd81d46..37be07c1ca 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -80,7 +80,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } } - if (!modules) { /* no modules in the options, look for @MODULES in the db */ + if (!modules && strcmp("ldap", ldb->modules->ops->name)) { /* no modules in the options, look for @MODULES in the db (not for ldap) */ int ret, j, k; char * attrs[] = { "@MODULE" }; struct ldb_message **msg; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 96aee088a7..7fb6a0b3f7 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -255,6 +255,10 @@ static int lldb_search(struct ldb_module *module, const char *base, int count, msg_count; LDAPMessage *ldapres, *msg; + if (base == NULL) { + base = ""; + } + lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, expression, discard_const_p(char *, attrs), diff --git a/source4/lib/ldb/tests/init_slapd.sh b/source4/lib/ldb/tests/init_slapd.sh index 65700f6c18..fc1ed16a4c 100755 --- a/source4/lib/ldb/tests/init_slapd.sh +++ b/source4/lib/ldb/tests/init_slapd.sh @@ -1,6 +1,4 @@ -#!/bin/sh - -export PATH=/usr/sbin:$PATH +#!/bin/sh rm -rf tests/tmp/db mkdir -p tests/tmp/db diff --git a/source4/lib/ldb/tests/slapd.conf b/source4/lib/ldb/tests/slapd.conf index 10d15b541c..61c8627e18 100644 --- a/source4/lib/ldb/tests/slapd.conf +++ b/source4/lib/ldb/tests/slapd.conf @@ -14,8 +14,8 @@ access to * by * write allow update_anon bind_anon_dn -modulepath /usr/lib/ldap -moduleload back_bdb +#modulepath /usr/lib/ldap +#moduleload back_bdb defaultsearchbase "o=University of Michigan,c=US" diff --git a/source4/lib/ldb/tests/start_slapd.sh b/source4/lib/ldb/tests/start_slapd.sh index d03a0fca32..a7ec69c855 100755 --- a/source4/lib/ldb/tests/start_slapd.sh +++ b/source4/lib/ldb/tests/start_slapd.sh @@ -1,7 +1,5 @@ #!/bin/sh -export PATH=/usr/sbin:$PATH - mkdir -p tests/tmp/db slapd -f tests/slapd.conf -h "`tests/ldapi_url.sh`" $* diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index b70b817732..c4647a7ba3 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -1,3 +1,5 @@ +#!/bin/sh + echo "LDB_URL: $LDB_URL" echo "Adding base elements" diff --git a/source4/lib/ldb/tests/test-ldap.sh b/source4/lib/ldb/tests/test-ldap.sh index 37827219c0..4fcd328cad 100755 --- a/source4/lib/ldb/tests/test-ldap.sh +++ b/source4/lib/ldb/tests/test-ldap.sh @@ -1,5 +1,6 @@ #!/bin/sh +export PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH SCHEMA_NEEDED="core nis cosine inetorgperson openldap" # setup needed schema files -- cgit From 57d2043479d290bbfa8d2752da454efea330606e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Nov 2004 14:16:10 +0000 Subject: r3760: mention -o switch in help message (This used to be commit 0e7d8753101f22aa192ac5628675a0374484d0e9) --- source4/lib/ldb/tools/ldbadd.c | 2 ++ source4/lib/ldb/tools/ldbdel.c | 2 ++ source4/lib/ldb/tools/ldbmodify.c | 2 ++ source4/lib/ldb/tools/ldbrename.c | 2 ++ source4/lib/ldb/tools/ldbsearch.c | 2 ++ 5 files changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 6d04800502..b0c9d8a366 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -41,6 +41,8 @@ static void usage(void) printf("Usage: ldbadd \n"); printf("Options:\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); printf("\n"); printf("Adds records to a ldb, reading ldif the specified list of files\n\n"); exit(1); diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 42dc9c19d8..839cb4cbe2 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -64,6 +64,8 @@ static void usage(void) printf("Options:\n"); printf(" -r recursively delete the given subtree\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); printf("\n"); printf("Deletes records from a ldb\n\n"); exit(1); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 823855ff1e..ac8958f4ac 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -41,6 +41,8 @@ static void usage(void) printf("Usage: ldbmodify \n"); printf("Options:\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); printf("\n"); printf("Modifies a ldb based upon ldif change records\n\n"); exit(1); diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 3e47e17b17..17b445c9e5 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -41,6 +41,8 @@ static void usage(void) printf("Usage: ldbrename [] \n"); printf("Options:\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); printf("\n"); printf("Renames records in a ldb\n\n"); exit(1); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 1e7bb1ce4c..81c46b437c 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -42,6 +42,8 @@ static void usage(void) printf(" -s base|sub|one choose search scope\n"); printf(" -b basedn choose baseDN\n"); printf(" -i read search expressions from stdin\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); exit(1); } -- cgit From e81157c7379116d83b9906e27c9fd418c779d129 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Nov 2004 06:14:36 +0000 Subject: r3782: use ldb_ namespace metze (This used to be commit 9003698e0fba28551d41d41dec159cc9c42ce7d2) --- source4/lib/ldb/common/util.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index 68537a7864..c8aa5019e2 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -41,7 +41,7 @@ return -1 if not found, or the index of the first occurance of needle if found */ -int list_find(const void *needle, +int ldb_list_find(const void *needle, const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn) { const char *base_p = base; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index d54208777d..93e358e4d2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -272,7 +272,7 @@ static int list_intersect(struct ldb_context *ldb, list3.count = 0; for (i=0;icount;i++) { - if (list_find(list->dn[i], list2->dn, list2->count, + if (ldb_list_find(list->dn[i], list2->dn, list2->count, sizeof(char *), (comparison_fn_t)strcmp) != -1) { list3.dn[list3.count] = list->dn[i]; list3.count++; @@ -315,7 +315,7 @@ static int list_union(struct ldb_context *ldb, list->dn = d; for (i=0;icount;i++) { - if (list_find(list2->dn[i], list->dn, count, + if (ldb_list_find(list2->dn[i], list->dn, count, sizeof(char *), (comparison_fn_t)strcmp) == -1) { list->dn[list->count] = ldb_strdup(ldb, list2->dn[i]); if (!list->dn[list->count]) { -- cgit From 8a18778286a16423d7d6e483fdb308a91e294efe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Nov 2004 09:00:52 +0000 Subject: r3783: - don't use make proto for ldb anymore - split ldh.h out of samba's includes.h - make ldb_context and ldb_module private to the subsystem - use ltdb_ prefix for all ldb_tdb functions metze (This used to be commit f5ee40d6ce8224e280070975efc9911558fe675c) --- source4/lib/db_wrap.c | 1 + source4/lib/ldb/Makefile.ldb | 3 - source4/lib/ldb/common/ldb.c | 2 + source4/lib/ldb/common/ldb_alloc.c | 4 +- source4/lib/ldb/common/ldb_debug.c | 2 + source4/lib/ldb/common/ldb_ldif.c | 2 + source4/lib/ldb/common/ldb_modules.c | 10 +- source4/lib/ldb/common/ldb_msg.c | 27 +++++ source4/lib/ldb/common/ldb_parse.c | 2 + source4/lib/ldb/common/ldb_utf8.c | 2 + source4/lib/ldb/common/util.c | 2 + source4/lib/ldb/config.mk | 3 + source4/lib/ldb/include/includes.h | 8 +- source4/lib/ldb/include/ldb.h | 93 ++++++--------- source4/lib/ldb/include/ldb_parse.h | 3 + source4/lib/ldb/include/ldb_private.h | 126 +++++++++++++++++++++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 + source4/lib/ldb/ldb_tdb/ldb_cache.c | 2 + source4/lib/ldb/ldb_tdb/ldb_index.c | 8 +- source4/lib/ldb/ldb_tdb/ldb_match.c | 43 +++---- source4/lib/ldb/ldb_tdb/ldb_pack.c | 13 ++- source4/lib/ldb/ldb_tdb/ldb_search.c | 40 ++----- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 12 +- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 69 +++++++++++ source4/lib/ldb/modules/skel.c | 2 + source4/lib/ldb/modules/timestamps.c | 2 + source4/lib/ldb/tools/ldbadd.c | 1 + source4/lib/ldb/tools/ldbdel.c | 1 + source4/lib/ldb/tools/ldbedit.c | 1 + source4/lib/ldb/tools/ldbmodify.c | 1 + source4/lib/ldb/tools/ldbrename.c | 1 + source4/lib/ldb/tools/ldbsearch.c | 1 + source4/lib/ldb/tools/ldbtest.c | 1 + .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 1 + 34 files changed, 354 insertions(+), 137 deletions(-) create mode 100644 source4/lib/ldb/include/ldb_private.h (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index c786185499..e9055399ad 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -29,6 +29,7 @@ #include "includes.h" #include "dlinklist.h" +#include "lib/ldb/include/ldb.h" static struct ldb_wrap *ldb_list; static struct tdb_wrap *tdb_list; diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 7666f5bd31..a7c86b4e82 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -74,9 +74,6 @@ manpages: clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) man/man?/*.[13] -proto: - perl ../../script/mkproto.pl */*.c > include/proto.h - etags: etags */*.[ch] diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 4fe2088daf..0fb371011f 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* connect to a database. The URL can either be one of the following forms diff --git a/source4/lib/ldb/common/ldb_alloc.c b/source4/lib/ldb/common/ldb_alloc.c index 0053c5e73f..7dc12b142e 100644 --- a/source4/lib/ldb/common/ldb_alloc.c +++ b/source4/lib/ldb/common/ldb_alloc.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* @@ -122,7 +124,7 @@ void *ldb_strdup(struct ldb_context *ldb, const char *str) /* a ldb wrapper for asprintf(), using ldb_malloc() */ -int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) _PRINTF_ATTRIBUTE(3, 4) +int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) { int len, len2; va_list ap; diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c index 0a187cd62d..6ba3f30b2d 100644 --- a/source4/lib/ldb/common/ldb_debug.c +++ b/source4/lib/ldb/common/ldb_debug.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 01706304d9..bd99468182 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -37,6 +37,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 37be07c1ca..1a6a334b8d 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -34,6 +34,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "dlinklist.h" #include #include @@ -82,10 +84,10 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) if (!modules && strcmp("ldap", ldb->modules->ops->name)) { /* no modules in the options, look for @MODULES in the db (not for ldap) */ int ret, j, k; - char * attrs[] = { "@MODULE" }; + const char * const attrs[] = { "@MODULE" , NULL}; struct ldb_message **msg; - ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msg); + ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); if (ret == 0) { ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); } else { @@ -144,7 +146,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) #ifdef HAVE_DLOPEN_DISABLED { void *handle; - init_ldb_module_function init; + ldb_module_init_function init; struct stat st; const char *errstr; @@ -160,7 +162,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return -1; } - init = (init_ldb_module_function)dlsym(handle, "init_module"); + init = (ldb_module_init_function)dlsym(handle, "init_module"); errstr = dlerror(); if (errstr) { diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 170a7ae5e4..18859c86dd 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* @@ -83,6 +85,31 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, return NULL; } +/* + duplicate a ldb_val structure +*/ +struct ldb_val ldb_val_dup(struct ldb_context *ldb, + const struct ldb_val *v) +{ + struct ldb_val v2; + v2.length = v->length; + if (v->length == 0) { + v2.data = NULL; + return v2; + } + + /* the +1 is to cope with buggy C library routines like strndup + that look one byte beyond */ + v2.data = ldb_malloc(ldb, v->length+1); + if (!v2.data) { + v2.length = 0; + return v2; + } + + memcpy(v2.data, v->data, v->length); + ((char *)v2.data)[v->length] = 0; + return v2; +} /* add an empty element to a message diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index feec8fc0f2..1e00a05d55 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -42,6 +42,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_parse.h" #include diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index e92d318bae..01bd8eb9ac 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include /* diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index c8aa5019e2..af738f352a 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 46fd4e12ae..a026ae1229 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -15,6 +15,7 @@ INIT_OBJ_FILES = \ lib/ldb/ldb_ldap/ldb_ldap.o REQUIRED_SUBSYSTEMS = \ EXT_LIB_LDAP +NOPROTO = YES # End MODULE libldb_tdb ################################################ @@ -32,6 +33,7 @@ ADD_OBJ_FILES = \ lib/ldb/ldb_tdb/ldb_cache.o REQUIRED_SUBSYSTEMS = \ LIBTDB +NOPROTO = YES # End MODULE libldb_tdb ################################################ @@ -51,6 +53,7 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_modules.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE +NOPROTO = YES # # End SUBSYSTEM LIBLDB ################################################ diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 44ff672266..4926e1524a 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -19,14 +19,8 @@ #include #include - -#ifndef _PRINTF_ATTRIBUTE -#define _PRINTF_ATTRIBUTE(a,b) -#endif - #include "ldb.h" -#include "tdb.h" -#include "proto.h" +#include "ldb_private.h" #ifdef HAVE_INTPTR_T #define discard_const(ptr) ((void *)((intptr_t)(ptr))) diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 6a06678e0e..03d0cc7a3b 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -121,39 +121,7 @@ struct ldb_context; typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *); -struct ldb_module_ops; - -/* basic module structure */ -struct ldb_module { - struct ldb_module *prev, *next; - struct ldb_context *ldb; - void *private_data; - const struct ldb_module_ops *ops; -}; - -/* - these function pointers define the operations that a ldb module must perform - they correspond exactly to the ldb_*() interface -*/ -struct ldb_module_ops { - const char *name; - int (*close)(struct ldb_module *); - int (*search)(struct ldb_module *, const char *, enum ldb_scope, - const char *, const char * const [], struct ldb_message ***); - int (*search_free)(struct ldb_module *, struct ldb_message **); - int (*add_record)(struct ldb_module *, const struct ldb_message *); - int (*modify_record)(struct ldb_module *, const struct ldb_message *); - int (*delete_record)(struct ldb_module *, const char *); - int (*rename_record)(struct ldb_module *, const char *, const char *); - const char * (*errstring)(struct ldb_module *); - - /* this is called when the alloc ops changes to ensure we - don't have any old allocated data in the context */ - void (*cache_free)(struct ldb_module *); -}; - -/* the modules init function */ -typedef struct ldb_module *(*init_ldb_module_function)(void); +struct ldb_module; /* the user can optionally supply a allocator function. It is presumed @@ -180,22 +148,6 @@ struct ldb_debug_ops { void *context; }; - -/* - every ldb connection is started by establishing a ldb_context -*/ -struct ldb_context { - /* the operations provided by the backend */ - struct ldb_module *modules; - - /* memory allocation info */ - struct ldb_alloc_ops alloc_ops; - - /* memory allocation info */ - struct ldb_debug_ops debug_ops; -}; - - #define LDB_FLG_RDONLY 1 /* @@ -285,6 +237,9 @@ int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif /* useful functions for ldb_message structure manipulation */ +int ldb_dn_cmp(const char *dn1, const char *dn2); +int ldb_attr_cmp(const char *dn1, const char *dn2); + /* find an element within an message */ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, const char *attr_name); @@ -305,6 +260,12 @@ int ldb_msg_add(struct ldb_context *ldb, struct ldb_message *msg, const struct ldb_message_element *el, int flags); +int ldb_msg_add_value(struct ldb_context *ldb, + struct ldb_message *msg, + const char *attr_name, + struct ldb_val *val); +int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr_name, char *str); /* compare two message elements - return 0 on match */ int ldb_msg_element_compare(struct ldb_message_element *el1, @@ -313,19 +274,27 @@ int ldb_msg_element_compare(struct ldb_message_element *el1, /* find elements in a message and convert to a specific type, with a give default value if not found. Assumes that elements are single valued */ +const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name); int ldb_msg_find_int(const struct ldb_message *msg, const char *attr_name, int default_value); unsigned int ldb_msg_find_uint(const struct ldb_message *msg, const char *attr_name, unsigned int default_value); +int64_t ldb_msg_find_int64(const struct ldb_message *msg, + const char *attr_name, + int64_t default_value); +uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, + const char *attr_name, + uint64_t default_value); double ldb_msg_find_double(const struct ldb_message *msg, const char *attr_name, double default_value); const char *ldb_msg_find_string(const struct ldb_message *msg, const char *attr_name, const char *default_value); - +struct ldb_val ldb_val_dup(struct ldb_context *ldb, + const struct ldb_val *v); /* this allows the user to choose their own allocation function @@ -341,6 +310,24 @@ int ldb_set_alloc(struct ldb_context *ldb, void *(*alloc)(const void *context, void *ptr, size_t size), void *context); +/* these are used as type safe versions of the ldb allocation functions */ +#define ldb_malloc_p(ldb, type) (type *)ldb_malloc(ldb, sizeof(type)) +#define ldb_malloc_array_p(ldb, type, count) (type *)ldb_realloc_array(ldb, NULL, sizeof(type), count) +#define ldb_realloc_p(ldb, p, type, count) (type *)ldb_realloc_array(ldb, p, sizeof(type), count) + +void *ldb_realloc(struct ldb_context *ldb, void *ptr, size_t size); +void *ldb_malloc(struct ldb_context *ldb, size_t size); +void ldb_free(struct ldb_context *ldb, void *ptr); +void *ldb_strndup(struct ldb_context *ldb, const char *str, size_t maxlen); +void *ldb_strdup(struct ldb_context *ldb, const char *str); +void *ldb_realloc_array(struct ldb_context *ldb, + void *ptr, size_t el_size, unsigned count); + +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a,b) +#endif +int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); + /* this allows the user to set a debug function for error reporting */ @@ -352,10 +339,4 @@ int ldb_set_debug(struct ldb_context *ldb, /* this sets up debug to print messages on stderr */ int ldb_set_debug_stderr(struct ldb_context *ldb); - -/* these are used as type safe versions of the ldb allocation functions */ -#define ldb_malloc_p(ldb, type) (type *)ldb_malloc(ldb, sizeof(type)) -#define ldb_malloc_array_p(ldb, type, count) (type *)ldb_realloc_array(ldb, NULL, sizeof(type), count) -#define ldb_realloc_p(ldb, p, type, count) (type *)ldb_realloc_array(ldb, p, sizeof(type), count) - #endif diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h index 930799d7b6..d9125d05ed 100644 --- a/source4/lib/ldb/include/ldb_parse.h +++ b/source4/lib/ldb/include/ldb_parse.h @@ -54,4 +54,7 @@ struct ldb_parse_tree { } u; }; +struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s); +void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree); + #endif diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h new file mode 100644 index 0000000000..dfd388b8c6 --- /dev/null +++ b/source4/lib/ldb/include/ldb_private.h @@ -0,0 +1,126 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb private header + * + * Description: defines internal ldb structures used by th esubsystem and modules + * + * Author: Andrew Tridgell + * Author: Stefan Metzmacher + */ + +#ifndef _LDB_PRIVATE_H_ +#define _LDB_PRIVATE_H_ 1 + +struct ldb_context; + +struct ldb_module_ops; + +/* basic module structure */ +struct ldb_module { + struct ldb_module *prev, *next; + struct ldb_context *ldb; + void *private_data; + const struct ldb_module_ops *ops; +}; + +/* + these function pointers define the operations that a ldb module must perform + they correspond exactly to the ldb_*() interface +*/ +struct ldb_module_ops { + const char *name; + int (*close)(struct ldb_module *); + int (*search)(struct ldb_module *, const char *, enum ldb_scope, + const char *, const char * const [], struct ldb_message ***); + int (*search_free)(struct ldb_module *, struct ldb_message **); + int (*add_record)(struct ldb_module *, const struct ldb_message *); + int (*modify_record)(struct ldb_module *, const struct ldb_message *); + int (*delete_record)(struct ldb_module *, const char *); + int (*rename_record)(struct ldb_module *, const char *, const char *); + const char * (*errstring)(struct ldb_module *); + + /* this is called when the alloc ops changes to ensure we + don't have any old allocated data in the context */ + void (*cache_free)(struct ldb_module *); +}; + +/* the modules init function */ +typedef struct ldb_module *(*ldb_module_init_function)(void); + +/* + every ldb connection is started by establishing a ldb_context +*/ +struct ldb_context { + /* the operations provided by the backend */ + struct ldb_module *modules; + + /* memory allocation info */ + struct ldb_alloc_ops alloc_ops; + + /* memory allocation info */ + struct ldb_debug_ops debug_ops; +}; + +/* The following definitions come from lib/ldb/common/ldb_modules.c */ + +int ldb_load_modules(struct ldb_context *ldb, const char *options[]); +int ldb_next_close(struct ldb_module *module); +int ldb_next_search(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, struct ldb_message ***res); +int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg); +int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message); +int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); +int ldb_next_delete_record(struct ldb_module *module, const char *dn); +int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn); +const char *ldb_next_errstring(struct ldb_module *module); +void ldb_next_cache_free(struct ldb_module *module); + +/* The following definitions come from lib/ldb/common/util.c */ +int ldb_list_find(const void *needle, + const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn); + +/* The following definitions come from lib/ldb/common/ldb_debug.c */ +void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); + +/* The following definitions come from lib/ldb/common/ldb_ldif.c */ +char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len); +int ldb_should_b64_encode(const struct ldb_val *val); + +struct ldb_context *ltdb_connect(const char *url, + unsigned int flags, + const char *options[]); +struct ldb_context *lldb_connect(const char *url, + unsigned int flags, + const char *options[]); +struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); + +#endif diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 7fb6a0b3f7..85604dfe76 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_ldap/ldb_ldap.h" #if 0 diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index cf175090e6..a8eb9ae916 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 93e358e4d2..b651aa38c1 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" @@ -523,7 +525,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr return -1; } - if (ldb_message_match(module, &msg, tree, base, scope) == 1) { + if (ltdb_message_match(module, &msg, tree, base, scope) == 1) { ret = ltdb_add_attr_results(module, &msg, attrs, &count, res); } ltdb_search_dn1_free(module, &msg); @@ -860,7 +862,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return 0; } - ret = ltdb_unpack_data(module->ldb, &data, &msg); + ret = ltdb_unpack_data(module, &data, &msg); if (ret != 0) { return -1; } @@ -871,7 +873,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * ret = ltdb_index_add(module, &msg); - ltdb_unpack_data_free(module->ldb, &msg); + ltdb_unpack_data_free(module, &msg); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 52e9f5afc7..4a51cfddf0 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -33,16 +33,17 @@ */ #include "includes.h" -#include +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" - +#include /* see if two ldb_val structures contain the same data as integers return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2) +static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2) { int i1, i2; @@ -56,7 +57,7 @@ static int ldb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val see if two ldb_val structures contain the same data as case insensitive strings return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_case_insensitive(const struct ldb_val *v1, +static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1, const struct ldb_val *v2) { if (v1->length != v2->length) { @@ -73,10 +74,11 @@ static int ldb_val_equal_case_insensitive(const struct ldb_val *v1, and case insensitive return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_wildcard_ci(struct ldb_context *ldb, +static int ltdb_val_equal_wildcard_ci(struct ldb_module *module, const struct ldb_val *v1, const struct ldb_val *v2) { + struct ldb_context *ldb = module->ldb; char *s1, *s2; int ret; @@ -110,13 +112,13 @@ static int ldb_val_equal_wildcard_ci(struct ldb_context *ldb, see if two ldb_val structures contain the same data with wildcards return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_wildcard(struct ldb_context *ldb, +static int ltdb_val_equal_wildcard(struct ldb_module *module, const struct ldb_val *v1, const struct ldb_val *v2, int flags) { if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - return ldb_val_equal_wildcard_ci(ldb, v1, v2); + return ltdb_val_equal_wildcard_ci(module, v1, v2); } if (!v1->data || !v2->data) { return v1->data == v2->data; @@ -137,13 +139,13 @@ static int ldb_val_equal_wildcard(struct ldb_context *ldb, return 1 for a match, 0 for a mis-match */ -static int ldb_val_equal_objectclass(struct ldb_module *module, +static int ltdb_val_equal_objectclass(struct ldb_module *module, const struct ldb_val *v1, const struct ldb_val *v2) { struct ltdb_private *ltdb = module->private_data; unsigned int i; - if (ldb_val_equal_case_insensitive(v1, v2) == 1) { + if (ltdb_val_equal_case_insensitive(v1, v2) == 1) { return 1; } @@ -152,7 +154,7 @@ static int ldb_val_equal_objectclass(struct ldb_module *module, if (ldb_attr_cmp(el->name, v2->data) == 0) { unsigned int j; for (j=0;jnum_values;j++) { - if (ldb_val_equal_objectclass(module, v1, &el->values[j])) { + if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) { return 1; } } @@ -171,27 +173,26 @@ static int ldb_val_equal_objectclass(struct ldb_module *module, return 1 for a match, 0 for a mis-match */ -int ldb_val_equal(struct ldb_module *module, +int ltdb_val_equal(struct ldb_module *module, const char *attr_name, const struct ldb_val *v1, const struct ldb_val *v2) { - struct ldb_context *ldb = module->ldb; int flags = ltdb_attribute_flags(module, attr_name); if (flags & LTDB_FLAG_OBJECTCLASS) { - return ldb_val_equal_objectclass(module, v1, v2); + return ltdb_val_equal_objectclass(module, v1, v2); } if (flags & LTDB_FLAG_INTEGER) { - return ldb_val_equal_integer(v1, v2); + return ltdb_val_equal_integer(v1, v2); } if (flags & LTDB_FLAG_WILDCARD) { - return ldb_val_equal_wildcard(ldb, v1, v2, flags); + return ltdb_val_equal_wildcard(module, v1, v2, flags); } if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - return ldb_val_equal_case_insensitive(v1, v2); + return ltdb_val_equal_case_insensitive(v1, v2); } if (v1->length != v2->length) return 0; @@ -280,7 +281,7 @@ static int match_leaf(struct ldb_module *module, return 1; } for (j=0;jelements[i].num_values;j++) { - if (ldb_val_equal(module, msg->elements[i].name, + if (ltdb_val_equal(module, msg->elements[i].name, &msg->elements[i].values[j], &tree->u.simple.value)) { return 1; @@ -300,7 +301,7 @@ static int match_leaf(struct ldb_module *module, this is a recursive function, and does short-circuit evaluation */ -int ldb_message_match(struct ldb_module *module, +int ltdb_message_match(struct ldb_module *module, struct ldb_message *msg, struct ldb_parse_tree *tree, const char *base, @@ -314,11 +315,11 @@ int ldb_message_match(struct ldb_module *module, break; case LDB_OP_NOT: - return ! ldb_message_match(module, msg, tree->u.not.child, base, scope); + return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope); case LDB_OP_AND: for (i=0;iu.list.num_elements;i++) { - v = ldb_message_match(module, msg, tree->u.list.elements[i], + v = ltdb_message_match(module, msg, tree->u.list.elements[i], base, scope); if (!v) return 0; } @@ -326,7 +327,7 @@ int ldb_message_match(struct ldb_module *module, case LDB_OP_OR: for (i=0;iu.list.num_elements;i++) { - v = ldb_message_match(module, msg, tree->u.list.elements[i], + v = ltdb_message_match(module, msg, tree->u.list.elements[i], base, scope); if (v) return 1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index ad856d2faf..9515beeaa7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" /* change this if the data format ever changes */ @@ -65,10 +67,11 @@ static unsigned int pull_uint32(uint8_t *p, int ofs) caller frees the data buffer after use */ -int ltdb_pack_data(struct ldb_context *ldb, +int ltdb_pack_data(struct ldb_module *module, const struct ldb_message *message, struct TDB_DATA *data) { + struct ldb_context *ldb = module->ldb; unsigned int i, j, real_elements=0; size_t size; char *p; @@ -138,9 +141,10 @@ int ltdb_pack_data(struct ldb_context *ldb, /* free the memory allocated from a ltdb_unpack_data() */ -void ltdb_unpack_data_free(struct ldb_context *ldb, +void ltdb_unpack_data_free(struct ldb_module *module, struct ldb_message *message) { + struct ldb_context *ldb = module->ldb; unsigned int i; for (i=0;inum_elements;i++) { @@ -160,10 +164,11 @@ void ltdb_unpack_data_free(struct ldb_context *ldb, TDB_DATA data. This means the caller only has to free the elements and values arrays. This can be done with ltdb_unpack_data_free() */ -int ltdb_unpack_data(struct ldb_context *ldb, +int ltdb_unpack_data(struct ldb_module *module, const struct TDB_DATA *data, struct ldb_message *message) { + struct ldb_context *ldb = module->ldb; char *p; unsigned int remaining; unsigned int i, j; @@ -274,7 +279,7 @@ int ltdb_unpack_data(struct ldb_context *ldb, return 0; failed: - ltdb_unpack_data_free(ldb, message); + ltdb_unpack_data_free(module, message); return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index cb93483881..903c4cb802 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" @@ -55,34 +57,6 @@ static void msg_free_all_parts(struct ldb_context *ldb, struct ldb_message *msg) } -/* - duplicate a ldb_val structure -*/ -struct ldb_val ldb_val_dup(struct ldb_context *ldb, - const struct ldb_val *v) -{ - struct ldb_val v2; - v2.length = v->length; - if (v->length == 0) { - v2.data = NULL; - return v2; - } - - /* the +1 is to cope with buggy C library routines like strndup - that look one byte beyond */ - v2.data = ldb_malloc(ldb, v->length+1); - if (!v2.data) { - v2.length = 0; - return v2; - } - - memcpy(v2.data, v->data, v->length); - ((char *)v2.data)[v->length] = 0; - return v2; -} - - - /* add one element to a message */ @@ -319,7 +293,7 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag msg->num_elements = 0; msg->elements = NULL; - ret = ltdb_unpack_data(ldb, &tdb_data2, msg); + ret = ltdb_unpack_data(module, &tdb_data2, msg); if (ret == -1) { ldb_free(ldb, tdb_data2.dptr); return -1; @@ -439,7 +413,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* unpack the record */ - ret = ltdb_unpack_data(sinfo->module->ldb, &data, &msg); + ret = ltdb_unpack_data(sinfo->module, &data, &msg); if (ret == -1) { sinfo->failures++; return 0; @@ -450,9 +424,9 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* see if it matches the given expression */ - if (!ldb_message_match(sinfo->module, &msg, sinfo->tree, + if (!ltdb_message_match(sinfo->module, &msg, sinfo->tree, sinfo->base, sinfo->scope)) { - ltdb_unpack_data_free(sinfo->module->ldb, &msg); + ltdb_unpack_data_free(sinfo->module, &msg); return 0; } @@ -462,7 +436,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi sinfo->failures++; } - ltdb_unpack_data_free(sinfo->module->ldb, &msg); + ltdb_unpack_data_free(sinfo->module, &msg); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index a2aa5a7aca..5f6af43f94 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -36,6 +36,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" /* @@ -195,7 +197,7 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg return -1; } - ret = ltdb_pack_data(ldb, msg, &tdb_data); + ret = ltdb_pack_data(module, msg, &tdb_data); if (ret == -1) { ldb_free(ldb, tdb_key.dptr); return -1; @@ -439,7 +441,7 @@ static int msg_delete_element(struct ldb_module *module, el = &msg->elements[found]; for (i=0;inum_values;i++) { - if (ldb_val_equal(module, msg->elements[i].name, &el->values[i], val)) { + if (ltdb_val_equal(module, msg->elements[i].name, &el->values[i], val)) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], sizeof(el->values[i])*(el->num_values-(i+1))); @@ -483,7 +485,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms return -1; } - ret = ltdb_unpack_data(ldb, &tdb_data, &msg2); + ret = ltdb_unpack_data(module, &tdb_data, &msg2); if (ret == -1) { ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); @@ -551,13 +553,13 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(ldb, &msg2); + ltdb_unpack_data_free(module, &msg2); return ret; failed: ldb_free(ldb, tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(ldb, &msg2); + ltdb_unpack_data_free(module, &msg2); return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index b6660c5825..7b926e21a2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -1,3 +1,8 @@ + +#ifdef STANDALONE +#include "tdb.h" +#endif + /* this private structure is used by the ltdb backend in the ldb_context */ struct ltdb_private { @@ -43,3 +48,67 @@ struct ltdb_private { #define LTDB_FLAG_WILDCARD (1<<2) #define LTDB_FLAG_OBJECTCLASS (1<<3) #define LTDB_FLAG_HIDDEN (1<<4) + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_cache.c */ + +void ltdb_cache_free(struct ldb_module *module); +int ltdb_cache_load(struct ldb_module *module); +int ltdb_increase_sequence_number(struct ldb_module *module); +int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name); + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_index.c */ + +struct ldb_parse_tree; + +int ltdb_search_indexed(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const attrs[], struct ldb_message ***res); +int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg); +int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg); +int ltdb_reindex(struct ldb_module *module); + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_pack.c */ + +int ltdb_pack_data(struct ldb_module *module, + const struct ldb_message *message, + struct TDB_DATA *data); +void ltdb_unpack_data_free(struct ldb_module *module, + struct ldb_message *message); +int ltdb_unpack_data(struct ldb_module *module, + const struct TDB_DATA *data, + struct ldb_message *message); + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_search.c */ + +int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, + const struct ldb_val *val); +void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg); +int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg); +int ltdb_search_dn(struct ldb_module *module, char *dn, + const char * const attrs[], struct ldb_message ***res); +int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, + const char * const attrs[], + unsigned int *count, + struct ldb_message ***res); +int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs); +int ltdb_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const attrs[], struct ldb_message ***res); + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */ +struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn); +int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); +int ltdb_delete_noindex(struct ldb_module *module, const char *dn); +int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); + +/* The following definitions come from lib/ldb/ldb_tdb/ldb_match.c */ +int ltdb_val_equal(struct ldb_module *module, + const char *attr_name, + const struct ldb_val *v1, const struct ldb_val *v2); +int ltdb_message_match(struct ldb_module *module, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope); diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 1d6314ee74..331a2de5e4 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" /* close */ static int skel_close(struct ldb_module *module) diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 64d7616fb1..521c59d241 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -33,6 +33,8 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include static int timestamps_close(struct ldb_module *module) diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index b0c9d8a366..d7f890b155 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static int failures; diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 839cb4cbe2..dc1c734284 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) { diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index fc3b28872e..fd45248c0e 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static int verbose; diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index ac8958f4ac..a660b814da 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static int failures; diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 17b445c9e5..f702cbd7f2 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -35,6 +35,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static void usage(void) { diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 81c46b437c..9f6b2f617a 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static void usage(void) { diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 5d90dc797d..f3be8e1e5c 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "ldb/include/ldb.h" static const char *ldb_url; static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c index bdebe34ff4..380a8010f2 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c @@ -20,6 +20,7 @@ #include "includes.h" #include "registry.h" +#include "lib/ldb/include/ldb.h" static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { -- cgit From 856ee665374071c89f5ecf540dcc3d68ccf2ff16 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 17 Nov 2004 14:35:29 +0000 Subject: r3810: create a LIB_SECURITY subsystem - move dom_sid, security_descriptor, security_* funtions to one place and rename some of them metze (This used to be commit b620bdd672cfdf0e009492e648b0709e6b6d8596) --- source4/lib/basic.mk | 4 +-- source4/lib/util_secdesc.c | 51 ---------------------------- source4/lib/util_sid.c | 85 ---------------------------------------------- 3 files changed, 1 insertion(+), 139 deletions(-) delete mode 100644 source4/lib/util_secdesc.c delete mode 100644 source4/lib/util_sid.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 7360eddf94..1f790a8ca2 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -51,8 +51,6 @@ ADD_OBJ_FILES = \ lib/wins_srv.o \ lib/util_str.o \ lib/util_strlist.o \ - lib/util_sid.o \ - lib/util_secdesc.o \ lib/util_uuid.o \ lib/util_unistr.o \ lib/util_file.o \ @@ -74,6 +72,6 @@ ADD_OBJ_FILES = \ lib/db_wrap.o \ lib/gencache.o REQUIRED_SUBSYSTEMS = \ - LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL + LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO LIB_SECURITY EXT_LIB_DL # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/util_secdesc.c b/source4/lib/util_secdesc.c deleted file mode 100644 index 92887b21d9..0000000000 --- a/source4/lib/util_secdesc.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - security descriptror utility functions - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* - return a blank security descriptor (no owners, dacl or sacl) -*/ -struct security_descriptor *sd_initialise(TALLOC_CTX *mem_ctx) -{ - struct security_descriptor *sd; - - sd = talloc_p(mem_ctx, struct security_descriptor); - if (!sd) { - return NULL; - } - - sd->revision = SD_REVISION; - /* we mark as self relative, even though it isn't while it remains - a pointer in memory because this simplifies the ndr code later. - All SDs that we store/emit are in fact SELF_RELATIVE - */ - sd->type = SEC_DESC_SELF_RELATIVE; - - sd->owner_sid = NULL; - sd->group_sid = NULL; - sd->sacl = NULL; - sd->dacl = NULL; - - return sd; -} - diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c deleted file mode 100644 index cb2ec3eb75..0000000000 --- a/source4/lib/util_sid.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 - Copyright (C) Jeremy Allison 1999 - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Simo Sorce 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/***************************************************************** - Compare the auth portion of two sids. -*****************************************************************/ - -static int sid_compare_auth(const struct dom_sid *sid1, const struct dom_sid *sid2) -{ - int i; - - if (sid1 == sid2) - return 0; - if (!sid1) - return -1; - if (!sid2) - return 1; - - if (sid1->sid_rev_num != sid2->sid_rev_num) - return sid1->sid_rev_num - sid2->sid_rev_num; - - for (i = 0; i < 6; i++) - if (sid1->id_auth[i] != sid2->id_auth[i]) - return sid1->id_auth[i] - sid2->id_auth[i]; - - return 0; -} - -/***************************************************************** - Compare two sids. -*****************************************************************/ - -static int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) -{ - int i; - - if (sid1 == sid2) - return 0; - if (!sid1) - return -1; - if (!sid2) - return 1; - - /* Compare most likely different rids, first: i.e start at end */ - if (sid1->num_auths != sid2->num_auths) - return sid1->num_auths - sid2->num_auths; - - for (i = sid1->num_auths-1; i >= 0; --i) - if (sid1->sub_auths[i] != sid2->sub_auths[i]) - return sid1->sub_auths[i] - sid2->sub_auths[i]; - - return sid_compare_auth(sid1, sid2); -} - -/***************************************************************** - Compare two sids. -*****************************************************************/ - -BOOL sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2) -{ - return sid_compare(sid1, sid2) == 0; -} -- cgit From d95a256d1b7f579666c852740d32ba0f446a4c66 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 19 Nov 2004 20:21:13 +0000 Subject: r3881: Split up the LIBNDR_GEN subsystem into NDR_* and RPC_NDR_* subsystems. This reduces the total size of the samba binaries from 119 Mb to 73 Mb. Next step will be to have the build system obtain some of this information by itself, so that we don't have to write ~10 lines per interface manually. (This used to be commit 16d905f6b0cbec591eebc44ee2ac9516a5730378) --- source4/lib/dcom/common/rot.c | 29 +++++++++++++++++++++++++++++ source4/lib/dcom/config.mk | 6 ++++-- source4/lib/registry/config.mk | 3 +-- 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 source4/lib/dcom/common/rot.c (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c new file mode 100644 index 0000000000..291022f925 --- /dev/null +++ b/source4/lib/dcom/common/rot.c @@ -0,0 +1,29 @@ +/* + Unix SMB/CIFS implementation. + + Running object table functions + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +struct dcom_interface_p *dcom_get_iface_p(struct GUID *ipid) +{ + /* FIXME */ + return NULL; +} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index f0b4031fc1..9fda924881 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -3,8 +3,10 @@ [SUBSYSTEM::LIBDCOM] INIT_OBJ_FILES = \ lib/dcom/common/main.o \ - lib/dcom/common/tables.o -REQUIRED_SUBSYSTEMS = LIBNDR_RAW LIBNDR_GEN LIBRPC_RAW + lib/dcom/common/tables.o \ + lib/dcom/common/rot.o +REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ + RPC_NDR_OXIDRESOLVER # # End SUBSYSTEM LIBDCOM ################################################ diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index ec9dbec7db..b91ec647a0 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -37,8 +37,7 @@ INIT_FUNCTION = registry_rpc_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_rpc/reg_backend_rpc.o -REQUIRED_SUBSYSTEMS = \ - LIBRPC +REQUIRED_SUBSYSTEMS = RPC_NDR_WINREG # End MODULE registry_rpc ################################################ -- cgit From d53fd3d8d5c99ae22a4d74065dc45e2f4e36a382 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 20 Nov 2004 18:51:58 +0000 Subject: r3891: Add rot (Running Object Table) interface (This used to be commit 4840eaeed3cfd72026babb382f26929c29702713) --- source4/lib/dcom/common/rot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c index 291022f925..95f83d000c 100644 --- a/source4/lib/dcom/common/rot.c +++ b/source4/lib/dcom/common/rot.c @@ -22,6 +22,7 @@ #include "includes.h" + struct dcom_interface_p *dcom_get_iface_p(struct GUID *ipid) { /* FIXME */ -- cgit From a4de8cd6a5a882a8d49fdb4b0e625ffdc6b401bb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 Nov 2004 15:51:54 +0000 Subject: r3897: add a locking infrastructure (This used to be commit a99c0adb09e2bc77b876d23cb2d0711ccffd83ca) --- source4/lib/ldb/common/ldb_modules.c | 16 +++++++++++ source4/lib/ldb/include/ldb_private.h | 4 +++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 31 ++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 50 ++++++++++++++++++++++------------- source4/lib/ldb/modules/skel.c | 14 ++++++++++ source4/lib/ldb/modules/timestamps.c | 14 ++++++++++ 6 files changed, 111 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 1a6a334b8d..71ec3fdc00 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -250,6 +250,22 @@ int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const c return module->next->ops->rename_record(module->next, olddn, newdn); } +int ldb_next_named_lock(struct ldb_module *module, const char *lockname) +{ + if (!module->next) { + return -1; + } + return module->next->ops->named_lock(module->next, lockname); +} + +int ldb_next_named_unlock(struct ldb_module *module, const char *lockname) +{ + if (!module->next) { + return -1; + } + return module->next->ops->named_unlock(module->next, lockname); +} + const char *ldb_next_errstring(struct ldb_module *module) { if (!module->next) { diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index dfd388b8c6..720d8928dd 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -63,6 +63,8 @@ struct ldb_module_ops { int (*modify_record)(struct ldb_module *, const struct ldb_message *); int (*delete_record)(struct ldb_module *, const char *); int (*rename_record)(struct ldb_module *, const char *, const char *); + int (*named_lock)(struct ldb_module *, const char *); + int (*named_unlock)(struct ldb_module *, const char *); const char * (*errstring)(struct ldb_module *); /* this is called when the alloc ops changes to ensure we @@ -101,6 +103,8 @@ int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *mes int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_delete_record(struct ldb_module *module, const char *dn); int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn); +int ldb_next_named_lock(struct ldb_module *module, const char *lockname); +int ldb_next_named_unlock(struct ldb_module *module, const char *lockname); const char *ldb_next_errstring(struct ldb_module *module); void ldb_next_cache_free(struct ldb_module *module); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 85604dfe76..d9640f247a 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -496,6 +496,35 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) return ret; } +static int lldb_lock(struct ldb_module *module, const char *lockname) +{ + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; + int ret = 0; + + if (lockname == NULL) { + return -1; + } + + /* TODO implement a local locking mechanism here */ + + return ret; +} + +static int lldb_unlock(struct ldb_module *module, const char *lockname) +{ + struct ldb_context *ldb = module->ldb; + struct lldb_private *lldb = module->private_data; + int ret = 0; + + if (lockname == NULL) { + return -1; + } + + /* TODO implement a local unlocking mechanism here */ + + return ret; +} /* return extended error information @@ -516,6 +545,8 @@ static const struct ldb_module_ops lldb_ops = { lldb_modify, lldb_delete, lldb_rename, + lldb_lock, + lldb_unlock, lldb_errstring }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 5f6af43f94..4049900a23 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -40,6 +40,8 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" +#define LDBLOCK "INT_LDBLOCK" + /* form a TDB_DATA for a record key caller frees @@ -122,14 +124,18 @@ failed: /* lock the database for write - currently a single lock is used */ -static int ltdb_lock(struct ldb_module *module) +static int ltdb_lock(struct ldb_module *module, const char *lockname) { struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA key; int ret; - key = ltdb_key(module, "LDBLOCK"); + if (lockname == NULL) { + return -1; + } + + key = ltdb_key(module, lockname); if (!key.dptr) { return -1; } @@ -144,20 +150,26 @@ static int ltdb_lock(struct ldb_module *module) /* unlock the database after a ltdb_lock() */ -static void ltdb_unlock(struct ldb_module *module) +static int ltdb_unlock(struct ldb_module *module, const char *lockname) { struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA key; - key = ltdb_key(module, "LDBLOCK"); + if (lockname == NULL) { + return -1; + } + + key = ltdb_key(module, lockname); if (!key.dptr) { - return; + return -1; } tdb_chainunlock(ltdb->tdb, key); ldb_free(ldb, key.dptr); + + return 0; } @@ -231,12 +243,12 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ltdb->last_err_string = NULL; - if (ltdb_lock(module) != 0) { + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return -1; } @@ -246,7 +258,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ltdb_modified(module, msg->dn); } - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return ret; } @@ -284,12 +296,12 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) ltdb->last_err_string = NULL; - if (ltdb_lock(module) != 0) { + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return -1; } @@ -316,11 +328,11 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) ltdb_modified(module, dn); } - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return ret; failed: - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return -1; } @@ -573,12 +585,12 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ltdb->last_err_string = NULL; - if (ltdb_lock(module) != 0) { + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return -1; } @@ -588,7 +600,7 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ltdb_modified(module, msg->dn); } - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return ret; } @@ -606,7 +618,7 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char ltdb->last_err_string = NULL; - if (ltdb_lock(module) != 0) { + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } @@ -641,11 +653,11 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char ltdb->last_err_string = error_str; - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return ret; failed: - ltdb_unlock(module); + ltdb_unlock(module, LDBLOCK); return -1; } @@ -692,6 +704,8 @@ static const struct ldb_module_ops ltdb_ops = { ltdb_modify, ltdb_delete, ltdb_rename, + ltdb_lock, + ltdb_unlock, ltdb_errstring, ltdb_cache_free }; diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 331a2de5e4..3581969c18 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -80,6 +80,18 @@ static int skel_rename_record(struct ldb_module *module, const char *olddn, cons return ldb_next_rename_record(module, olddn, newdn); } +/* named_lock */ +static const char *skel_named_lock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_lock(module, lockname); +} + +/* named_unlock */ +static const char *skel_named_unlock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_unlock(module, lockname); +} + /* return extended error information */ static const char *skel_errstring(struct ldb_module *module) { @@ -100,6 +112,8 @@ static const struct ldb_module_ops skel_ops = { skel_modify_record, skel_delete_record, skel_rename_record, + skel_named_lock, + skel_named_unlock, skel_errstring, skel_cache_free }; diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 521c59d241..fde87ef4a6 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -230,6 +230,18 @@ static int timestamps_rename_record(struct ldb_module *module, const char *olddn return ldb_next_rename_record(module, olddn, newdn); } +static int timestamps_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int timestamps_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + /* return extended error information */ static const char *timestamps_errstring(struct ldb_module *module) { @@ -252,6 +264,8 @@ static const struct ldb_module_ops timestamps_ops = { timestamps_modify_record, timestamps_delete_record, timestamps_rename_record, + timestamps_lock, + timestamps_unlock, timestamps_errstring, timestamps_cache_free }; -- cgit From cc368fa69e6a205516c64712aee701fe0cf6d20b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Nov 2004 17:47:09 +0000 Subject: r3898: Work towards local/server DCOM support, start working on Simple example server side implementation (This used to be commit 98afb504d95ccca4d6ec48273e10b52ccfa26ad0) --- source4/lib/dcom/classes/simple.c | 39 ++++++++++++ source4/lib/dcom/common/dcom.h | 5 +- source4/lib/dcom/common/main.c | 126 +++++++++++++++++++++++++++++++++++--- source4/lib/dcom/common/rot.c | 10 ++- source4/lib/dcom/common/tables.c | 5 +- source4/lib/dcom/config.mk | 6 ++ 6 files changed, 177 insertions(+), 14 deletions(-) create mode 100644 source4/lib/dcom/classes/simple.c (limited to 'source4/lib') diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c new file mode 100644 index 0000000000..e8b8730267 --- /dev/null +++ b/source4/lib/dcom/classes/simple.c @@ -0,0 +1,39 @@ +/* + Unix SMB/CIFS implementation. + Simple class + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/dcom/common/dcom.h" + +static struct dcom_IClassFactory_vtable simple_classobject; + +NTSTATUS dcom_simple_init(void) +{ + struct GUID iid; + struct dcom_class simple_class = { + "Samba.Simple", + }; + + GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); + + simple_class.class_object = dcom_new_local_ifacep(NULL, dcom_interface_by_iid(&iid), &simple_classobject, NULL); + + GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); + return dcom_register_class(&simple_class); +} diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 9c09cc17d9..d8e3797c73 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -26,6 +26,7 @@ struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; +struct dcom_interface_p; struct dcom_context { @@ -53,7 +54,9 @@ struct dcom_class { const char *prog_id; struct GUID clsid; - void (*get_class_object) (struct GUID *iid, void **vtable); + + /* IUnknown */ + struct dcom_interface_p *class_object; }; struct dcom_interface diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 60f866aede..3730137268 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -143,15 +143,15 @@ WERROR dcom_ping(struct dcom_context *ctx) return WERR_OK; } -WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + struct dcerpc_pipe *p; + struct dcom_object_exporter *m; + NTSTATUS status; struct RemoteActivation r; struct DUALSTRINGARRAY dualstring; int i; - struct dcom_object_exporter *m; - struct dcerpc_pipe *p; - NTSTATUS status; - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { @@ -207,7 +207,60 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +{ + struct dcom_interface_p *factory, *iunk; + struct QueryInterface qr; + struct Release rr; + struct CreateInstance cr; + WERROR error; + int i; + NTSTATUS status; + + if (server != NULL) { + return dcom_create_object_remote(ctx, clsid, server, num_ifaces, iid, ip, results); + } + + /* Obtain class object */ + error = dcom_get_class_object(ctx, clsid, server, iid, &factory); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); + return error; + } + + dcom_OBJREF_from_ifacep(ctx, &cr.in.pUnknown->obj, factory); + + GUID_from_string(DCERPC_ICLASSFACTORY_UUID, cr.in.iid); + + /* Run IClassFactory::CreateInstance() */ + status = dcom_IClassFactory_CreateInstance(factory, ctx, &cr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + /* Release class object */ + status = dcom_IUnknown_Release(factory, ctx, &rr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3, ("Error freeing class factory: %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + /* Do one or more QueryInterface calls */ + for (i = 0; i < num_ifaces; i++) { + qr.in.iid = &iid[i]; + status = dcom_IUnknown_QueryInterface(iunk, ctx, &qr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(4, ("Error obtaining interface %s : %s\n", GUID_string(NULL, &iid[i]), nt_errstr(status))); + return ntstatus_to_werror(status); + } + results[i] = qr.out.result; + } + + return WERR_OK; +} + +WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) { struct dcom_object_exporter *m; struct RemoteActivation r; @@ -258,6 +311,36 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const return WERR_OK; } +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +{ + const struct dcom_class *c; + struct QueryInterface qi; + NTSTATUS status; + + if (server != NULL) { + return dcom_get_class_object_remote(ctx, clsid, server, iid, ip); + } + + c = dcom_class_by_clsid(clsid); + if (!c) { + /* FIXME: Better error code.. */ + return WERR_DEST_NOT_FOUND; + } + + qi.in.iid = iid; + + status = dcom_IUnknown_QueryInterface(c->class_object, ctx, &qi ); + if (NT_STATUS_IS_ERR(status)) { + return ntstatus_to_werror(status); + } + + if (!W_ERROR_IS_OK(qi.out.result)) { return qi.out.result; } + + dcom_ifacep_from_OBJREF(ctx, ip, &qi.out.data->obj); + + return WERR_OK; +} + NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) { struct dcerpc_binding binding; @@ -326,6 +409,12 @@ struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T return o; } + +NTSTATUS dcom_OBJREF_from_ifacep(struct dcom_context *ctx, struct OBJREF *o, struct dcom_interface_p *_p) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) { struct dcom_interface_p *p = talloc_p(ctx, struct dcom_interface_p); @@ -363,7 +452,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface p->ipid = o->u_objref.u_handler.std.ipid; p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); p->ox->resolver_address = o->u_objref.u_handler.saResAddr; - p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid); +/*FIXME p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/ /* FIXME: Do the custom unmarshaling call */ *_p = p; @@ -371,7 +460,6 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface case OBJREF_CUSTOM: { - const struct dcom_interface *imarshal = dcom_vtable_by_clsid(&o->u_objref.u_custom.clsid); p->vtable = NULL; /* FIXME: Do the actual custom unmarshaling call */ @@ -437,3 +525,25 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface return NT_STATUS_NOT_SUPPORTED; } + +HYPER_T dcom_get_current_oxid(void) +{ + return getpid(); +} + +struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct dcom_interface *iface, void *vtable, struct dcom_object *object) +{ + struct dcom_interface_p *ip = talloc_p(ctx, struct dcom_interface_p); + + ip->ctx = ctx; + ip->interface = iface; + ip->vtable = vtable; + uuid_generate_random(&ip->ipid); + ip->object = object; + ip->objref_flags = 0; + ip->orpc_flags = 0; + ip->ox = NULL; + ip->private_references = 1; + + return ip; +} diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c index 95f83d000c..7acdbe066e 100644 --- a/source4/lib/dcom/common/rot.c +++ b/source4/lib/dcom/common/rot.c @@ -22,9 +22,13 @@ #include "includes.h" - -struct dcom_interface_p *dcom_get_iface_p(struct GUID *ipid) +struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) { - /* FIXME */ + /* FIXME: Call the local ROT and do a + * rot_get_interface_pointer call */ + + /* FIXME: Perhaps have a local (thread-local) table with + * local DCOM objects so that not every DCOM call requires a lookup + * to the ROT? */ return NULL; } diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index f9f1c49380..f615662b47 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -46,14 +46,15 @@ const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) return NULL; } -const void *dcom_vtable_by_clsid(const struct GUID *clsid) +const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) { struct class_list *c = classes; while(c) { - if (uuid_equal(clsid, &c->class.clsid)) + if (uuid_equal(clsid, &c->class.clsid)) { return &c->class; + } c = c->next; } diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 9fda924881..d599231525 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -7,6 +7,12 @@ INIT_OBJ_FILES = \ lib/dcom/common/rot.o REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ RPC_NDR_OXIDRESOLVER + +[MODULE::DCOM_SIMPLE] +SUBSYSTEM = LIBDCOM +INIT_FUNCTION = dcom_simple_init +INIT_OBJ_FILES = \ + lib/dcom/classes/simple.o # # End SUBSYSTEM LIBDCOM ################################################ -- cgit From 90b06b4ea8d8d06e9cd9f6678b4086eda49204bd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Nov 2004 17:35:37 +0000 Subject: r3926: fix compiler warnings metze (This used to be commit a9cbaa3cff470f58031972d53ecb6f5856b187e0) --- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index d9640f247a..b9c3865acc 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -498,8 +498,6 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) static int lldb_lock(struct ldb_module *module, const char *lockname) { - struct ldb_context *ldb = module->ldb; - struct lldb_private *lldb = module->private_data; int ret = 0; if (lockname == NULL) { @@ -513,8 +511,6 @@ static int lldb_lock(struct ldb_module *module, const char *lockname) static int lldb_unlock(struct ldb_module *module, const char *lockname) { - struct ldb_context *ldb = module->ldb; - struct lldb_private *lldb = module->private_data; int ret = 0; if (lockname == NULL) { -- cgit From 5c55901266a4f176e77d41ceb6674b0d89eaef3a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Nov 2004 18:02:35 +0000 Subject: r3960: fix compiler warnings metze (This used to be commit 54d5b418a75d421a9c6c09bc084454f11e9b7b44) --- source4/lib/crypto/crc32.c | 2 +- source4/lib/crypto/crc32.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/crc32.c b/source4/lib/crypto/crc32.c index f2d76332f9..00cee243b4 100644 --- a/source4/lib/crypto/crc32.c +++ b/source4/lib/crypto/crc32.c @@ -55,7 +55,7 @@ static const unsigned long CRCTable[256] = 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; -uint32_t crc32_calc_buffer( const char *buffer, uint32_t count) +uint32_t crc32_calc_buffer(const uint8_t *buffer, uint32_t count) { uint32_t crc=0xffffffff, i; for(i=0;i Date: Thu, 25 Nov 2004 18:23:58 +0000 Subject: r3961: - fix compiler warnings - remove unused typedef metze (This used to be commit 19613122a5222b152044b1f86136496b95d4a3e3) --- source4/lib/crypto/md5.c | 3 ++- source4/lib/crypto/md5.h | 7 +------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index 07028e9043..38ef3fdfbd 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -22,6 +22,7 @@ #include "md5.h" + static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); /* @@ -57,7 +58,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, uint8_t const *buf, uint_t len) +void MD5Update(struct MD5Context *ctx, const uint8_t const *buf, uint_t len) { register uint32_t t; diff --git a/source4/lib/crypto/md5.h b/source4/lib/crypto/md5.h index cd23979f8a..a622cf232a 100644 --- a/source4/lib/crypto/md5.h +++ b/source4/lib/crypto/md5.h @@ -12,13 +12,8 @@ struct MD5Context { }; void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, uint8_t const *buf, +void MD5Update(struct MD5Context *context, const uint8_t const *buf, uint_t len); void MD5Final(uint8_t digest[16], struct MD5Context *context); -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ -typedef struct MD5Context MD5_CTX; - #endif /* !MD5_H */ -- cgit From 3acaf09bd8e1c418e32a6a98a33f6df96a3d534b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Nov 2004 19:02:42 +0000 Subject: r3964: fix compiler warnings metze (This used to be commit f34171bbb3185aa5bc79915c060e09a36179307c) --- source4/lib/genrand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 46a73e6d2e..b4651dffe8 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -196,7 +196,7 @@ static int do_reseed(BOOL use_fd, int fd) Interface to the (hopefully) good crypto random number generator. ********************************************************************/ -void generate_random_buffer( unsigned char *out, int len) +void generate_random_buffer(uint8_t *out, int len) { static int urand_fd = -1; unsigned char md4_buf[64]; @@ -271,7 +271,7 @@ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list char *retstr = talloc(mem_ctx, len + 1); if (!retstr) return NULL; - generate_random_buffer(retstr, len); + generate_random_buffer((uint8_t *)retstr, len); for (i = 0; i < len; i++) { retstr[i] = list[retstr[i] % list_len]; } -- cgit From 4bc68cba73cfdf8f6aac75d8fcc1bdb22f29acd3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Nov 2004 19:12:16 +0000 Subject: r3965: fix compiler warnings metze (This used to be commit 0614fa3b168265e69a611936dd7c1f7a078e53dd) --- source4/lib/util.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 1202cb3aae..2351a98eae 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -787,7 +787,7 @@ void dump_data_pw(const char *msg, const uint8_t * data, size_t len) /* see if a range of memory is all zero. A NULL pointer is considered to be all zero */ -BOOL all_zero(const char *ptr, uint_t size) +BOOL all_zero(const uint8_t *ptr, uint_t size) { int i; if (!ptr) return True; @@ -796,5 +796,3 @@ BOOL all_zero(const char *ptr, uint_t size) } return True; } - - -- cgit From c199c2af1fa686962bb313222a0a0a29625ec450 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Nov 2004 19:27:17 +0000 Subject: r3968: fix compiler warnings metze (This used to be commit 6440476f7f2fd5776ec4a21240e7482603000d19) --- source4/lib/tdb/tools/tdbdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 822f65e594..dbb647cbbf 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -43,7 +43,7 @@ static void print_data(TDB_DATA d) { - unsigned char *p = d.dptr; + unsigned char *p = (unsigned char *)d.dptr; int len = d.dsize; while (len--) { if (isprint(*p) && !strchr("\"\\", *p)) { -- cgit From e90061865467600a9d8a34f92e60a296cbf19234 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Nov 2004 20:03:46 +0000 Subject: r3972: use GUID_* naming context and move GUID_* functions to one place metze (This used to be commit 523e6acf4fec5d4946fa7c0c89f40d7d712c9f3a) --- source4/lib/basic.mk | 1 - source4/lib/dcom/common/main.c | 8 +++--- source4/lib/dcom/common/tables.c | 4 +-- source4/lib/util_uuid.c | 62 ---------------------------------------- 4 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 source4/lib/util_uuid.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 1f790a8ca2..e4275bea49 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -51,7 +51,6 @@ ADD_OBJ_FILES = \ lib/wins_srv.o \ lib/util_str.o \ lib/util_strlist.o \ - lib/util_uuid.o \ lib/util_unistr.o \ lib/util_file.o \ lib/data_blob.o \ diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 3730137268..61fd7d3ff7 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -162,7 +162,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c ZERO_STRUCT(r.in); r.in.this.version.MajorVersion = COM_MAJOR_VERSION; r.in.this.version.MinorVersion = COM_MINOR_VERSION; - uuid_generate_random(&r.in.this.cid); + r.in.this.cid = GUID_random(); r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; r.in.num_protseqs = ARRAY_SIZE(protseq); @@ -279,7 +279,7 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid ZERO_STRUCT(r.in); r.in.this.version.MajorVersion = COM_MAJOR_VERSION; r.in.this.version.MinorVersion = COM_MINOR_VERSION; - uuid_generate_random(&r.in.this.cid); + r.in.this.cid = GUID_random(); r.in.Clsid = *clsid; r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; r.in.num_protseqs = ARRAY_SIZE(protseq); @@ -355,7 +355,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) iid = iface->interface->iid; if (iface->ox->pipe) { - if (!uuid_equal(&iface->ox->pipe->syntax.uuid, &iid)) { + if (!GUID_equal(&iface->ox->pipe->syntax.uuid, &iid)) { iface->ox->pipe->syntax.uuid = iid; status = dcerpc_alter(iface->ox->pipe, iface->ctx); if (NT_STATUS_IS_ERR(status)) { @@ -538,7 +538,7 @@ struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const s ip->ctx = ctx; ip->interface = iface; ip->vtable = vtable; - uuid_generate_random(&ip->ipid); + ip->ipid = GUID_random(); ip->object = object; ip->objref_flags = 0; ip->orpc_flags = 0; diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index f615662b47..6b0d99cae3 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -37,7 +37,7 @@ const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) while(l) { - if (uuid_equal(iid, &l->interface.iid)) + if (GUID_equal(iid, &l->interface.iid)) return &l->interface; l = l->next; @@ -52,7 +52,7 @@ const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) while(c) { - if (uuid_equal(clsid, &c->class.clsid)) { + if (GUID_equal(clsid, &c->class.clsid)) { return &c->class; } diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c deleted file mode 100644 index a11b7bd3ed..0000000000 --- a/source4/lib/util_uuid.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * UUID server routines - * Copyright (C) Theodore Ts'o 1996, 1997, - * Copyright (C) Jim McDonough 2002. - * Copyright (C) Andrew Tridgell 2003. - * - * 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 - * (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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -void uuid_generate_random(struct GUID *out) -{ - generate_random_buffer((unsigned char *)out, sizeof(struct GUID)); - out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; - out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; -} - -BOOL uuid_all_zero(const struct GUID *u) -{ - if (u->time_low != 0 || - u->time_mid != 0 || - u->time_hi_and_version != 0 || - u->clock_seq[0] != 0 || - u->clock_seq[1] != 0 || - !all_zero(u->node, 6)) { - return False; - } - return True; -} - -BOOL uuid_equal(const struct GUID *u1, const struct GUID *u2) -{ - if (u1->time_low != u2->time_low || - u1->time_mid != u2->time_mid || - u1->time_hi_and_version != u2->time_hi_and_version || - u1->clock_seq[0] != u2->clock_seq[0] || - u1->clock_seq[1] != u2->clock_seq[1] || - memcmp(u1->node, u2->node, 6) != 0) { - return False; - } - return True; -} - -BOOL policy_handle_empty(struct policy_handle *h) -{ - return (h->handle_type == 0 && uuid_all_zero(&h->uuid)); -} - -- cgit From b6b01064279c0cf5bae8b2324c760f1f7f6be457 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 25 Nov 2004 23:05:43 +0000 Subject: r3976: changed NBENCH to use the same recording method as the latest dbench, where the warmup phase continues until all clients have done some file IO. This gives more repeatable results when under high load (This used to be commit aca0658f6dfe8b7c90afcac87e8cc68965a4288d) --- source4/lib/time.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index b13ad24b34..8d477fac02 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -476,14 +476,22 @@ BOOL timeval_expired(struct timeval *tv) return (tv2.tv_usec >= tv->tv_usec); } +/* + return the number of seconds elapsed between two times +*/ +double timeval_elapsed2(struct timeval *tv1, struct timeval *tv2) +{ + return (tv2->tv_sec - tv1->tv_sec) + + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; +} + /* return the number of seconds elapsed since a given time */ double timeval_elapsed(struct timeval *tv) { struct timeval tv2 = timeval_current(); - return (tv2.tv_sec - tv->tv_sec) + - (tv2.tv_usec - tv->tv_usec)*1.0e-6; + return timeval_elapsed2(tv, &tv2); } /* @@ -497,6 +505,17 @@ struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2) return *tv2; } +/* + return the greater of two timevals +*/ +struct timeval timeval_max(struct timeval *tv1, struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return *tv1; + if (tv1->tv_sec < tv2->tv_sec) return *tv2; + if (tv1->tv_usec > tv2->tv_usec) return *tv1; + return *tv2; +} + /* return the difference between two timevals as a timeval if tv2 comes after tv1, then return a zero timeval -- cgit From 2ed4ff13d509218785d9941dc17219958ab04223 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Nov 2004 02:15:43 +0000 Subject: r4010: fixed parsing of null attributes in the ldb ldif parser (This used to be commit b4fd76f78eadd8648ceed508766235e80702aa8f) --- source4/lib/ldb/common/ldb_ldif.c | 8 ++++++-- source4/lib/ldb/tests/init.ldif | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index bd99468182..94e15805a6 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -128,7 +128,11 @@ int ldb_should_b64_encode(const struct ldb_val *val) unsigned int i; uint8_t *p = val->data; - if (val->length == 0 || p[0] == ' ' || p[0] == ':') { + if (val->length == 0) { + return 0; + } + + if (p[0] == ' ' || p[0] == ':') { return 1; } @@ -377,7 +381,7 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) *attr = *s; - while (isspace(*p)) { + while (*p == ' ' || *p == '\t') { p++; } diff --git a/source4/lib/ldb/tests/init.ldif b/source4/lib/ldb/tests/init.ldif index a9ed4506fb..3b0eeffe2f 100644 --- a/source4/lib/ldb/tests/init.ldif +++ b/source4/lib/ldb/tests/init.ldif @@ -9,6 +9,7 @@ o: UM o: U-M o: U of M description: The University of Michigan at Ann Arbor +seeAlso: postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 09 $ US telephonenumber: +1 313 764-1817 -- cgit From b6c4b63dc59d10e7f93e726282b6f93f64dd7bb8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Nov 2004 22:55:36 +0000 Subject: r4022: fix compiler warnings metze (This used to be commit 79d0eb2f677f9e985ba476a9680f68537d41be6f) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 5 +++-- source4/lib/ldb/ldb_tdb/ldb_pack.c | 4 ++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index b651aa38c1..df0a436172 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -80,7 +80,7 @@ static char *ldb_dn_key(struct ldb_context *ldb, see if a attribute value is in the list of indexed attributes */ static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, - int *v_idx, const char *key) + unsigned int *v_idx, const char *key) { unsigned int i, j; for (i=0;inum_elements;i++) { @@ -509,7 +509,8 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr const struct dn_list *dn_list, const char * const attrs[], struct ldb_message ***res) { - unsigned int count = 0, i; + unsigned int i; + int count = 0; for (i=0;icount;i++) { struct ldb_message msg; diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 9515beeaa7..bfbc4841a6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -44,7 +44,7 @@ #define LTDB_PACKING_FORMAT_NODN 0x26011966 /* use a portable integer format */ -static void put_uint32(uint8_t *p, int ofs, unsigned int val) +static void put_uint32(char *p, int ofs, unsigned int val) { p += ofs; p[0] = val&0xFF; @@ -53,7 +53,7 @@ static void put_uint32(uint8_t *p, int ofs, unsigned int val) p[3] = (val>>24) & 0xFF; } -static unsigned int pull_uint32(uint8_t *p, int ofs) +static unsigned int pull_uint32(char *p, int ofs) { p += ofs; return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 903c4cb802..27718a4c86 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -353,7 +353,7 @@ int ltdb_search_dn(struct ldb_module *module, char *dn, */ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], - unsigned int *count, + int *count, struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 7b926e21a2..2cc25b3152 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -90,7 +90,7 @@ int ltdb_search_dn(struct ldb_module *module, char *dn, const char * const attrs[], struct ldb_message ***res); int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], - unsigned int *count, + int *count, struct ldb_message ***res); int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs); int ltdb_search(struct ldb_module *module, const char *base, -- cgit From 34b1367373aee57c2a21ec9a993e715c62c37620 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 1 Dec 2004 16:51:37 +0000 Subject: r4027: add a useful function for debugging metze (This used to be commit 41b1ba53fc201b7b9f9d806dccef6258b2a1d157) --- source4/lib/data_blob.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index c5f15f1271..a4506fee45 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -142,3 +142,21 @@ BOOL data_blob_equal(const DATA_BLOB *d1, const DATA_BLOB *d2) return False; } +/******************************************************************* +print the data_blob as hex string +*******************************************************************/ +char *data_blob_hex_string(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + int i; + char *hex_string; + + hex_string = talloc_array_p(mem_ctx, char, (blob->length*2)+1); + if (!hex_string) { + return NULL; + } + + for (i = 0; i < blob->length; i++) + slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]); + + return hex_string; +} -- cgit From cc8f4358cca2404895015e2351394f2f4a16e025 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Dec 2004 04:37:36 +0000 Subject: r4035: more effort on consistent naming of the access mask bits. This removes the duplicate named SEC_RIGHTS_MAXIMUM_ALLOWED and SEC_RIGHTS_FULL_CONTROL, which are just other names for SEC_FLAG_MAXIMUM_ALLOWED and SEC_RIGHTS_FILE_ALL. The latter names match the new naming conventions in security.idl Also added names for the generic->specific mappings for files are directories (This used to be commit 17a4e0b3aca227b40957ed1e0c57e498debc6ddf) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 47afc31d96..1a7cb38af5 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -47,7 +47,7 @@ static void init_winreg_String(struct winreg_String *name, const char *s) unknown.unknown0 = 0x84e0; \ unknown.unknown1 = 0x0000; \ r.in.unknown = &unknown; \ - r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED; \ + r.in.access_required = SEC_FLAG_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ -- cgit From 4183b2ac3832cdc2055d7eb3ed7121a9ea91085c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Dec 2004 04:51:56 +0000 Subject: r4037: fixed a bunch of "might be uninitialised" warnings after enabling -O1 in my compile (This used to be commit 0928b1f5b68c858922c3ea6c27ed03b5091c6221) --- source4/lib/dcom/common/main.c | 2 +- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/reg_backend_w95/reg_backend_w95.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 61fd7d3ff7..09c5fd280c 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -209,7 +209,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { - struct dcom_interface_p *factory, *iunk; + struct dcom_interface_p *factory, *iunk = NULL; struct QueryInterface qr; struct Release rr; struct CreateInstance cr; diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 77440cea0f..dea8861745 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -614,7 +614,7 @@ WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct { char *parent_name; char *last; - struct registry_key *root; + struct registry_key *root = NULL; WERROR error; parent_name = strdup(key->path); diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c index fb73e9052c..445d13a99c 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c @@ -320,7 +320,7 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i DWORD i; DWORD offset = 0; RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); - RGDB_VALUE *curval; + RGDB_VALUE *curval = NULL; if(!rgdb_key) return WERR_FOOBAR; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 8d044f6fa2..3333299088 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -245,7 +245,7 @@ static char **reg_complete_command(const char *text, int end) { /* Complete command */ char **matches; - int i, len, samelen, count=1; + int i, len, samelen=0, count=1; matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); if (!matches) return NULL; -- cgit From 7ea35407632984b1f88d2d5b75fff1b6dc77c09b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Dec 2004 10:14:40 +0000 Subject: r4038: fix sign/unsign bug I introduced in -r 4022 this caused new ldb record to be corrupt if the length was > 12b byte thanks tridge for finding this metze (This used to be commit 6998c37b473d8efeb2ed5285f10f469a29ad787a) --- source4/lib/ldb/ldb_tdb/ldb_pack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index bfbc4841a6..0ebf62df8d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -44,7 +44,7 @@ #define LTDB_PACKING_FORMAT_NODN 0x26011966 /* use a portable integer format */ -static void put_uint32(char *p, int ofs, unsigned int val) +static void put_uint32(uint32 *p, int ofs, unsigned int val) { p += ofs; p[0] = val&0xFF; @@ -53,7 +53,7 @@ static void put_uint32(char *p, int ofs, unsigned int val) p[3] = (val>>24) & 0xFF; } -static unsigned int pull_uint32(char *p, int ofs) +static unsigned int pull_uint32(uint32 *p, int ofs) { p += ofs; return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); -- cgit From 4754082feabdb7af88883d8dc89324834c9cbca1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Dec 2004 10:28:19 +0000 Subject: r4039: added a test for an element > 128 bytes in length, to ensure we test for sign extending errors in element length (This used to be commit 07378fca6c12ffffcd3fe5e91f4d70ef838a45d5) --- source4/lib/ldb/tests/test.ldif | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif index 2d7e1f95de..b9afad8b63 100644 --- a/source4/lib/ldb/tests/test.ldif +++ b/source4/lib/ldb/tests/test.ldif @@ -409,6 +409,9 @@ postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104 mail: uham@mail.alumni.example.com +seeAlso: a long attribute name, longer than 128 bytes so that we + trigger sign extension problems in tdb_pack, no thats not long enough + yet, maybe this is. I'll just keep going till it triggers the error homephone: +1 313 555 8421 pager: +1 313 555 2844 facsimiletelephonenumber: +1 313 555 9700 -- cgit From 785e7eb4527fdd6faffc1b23500c7c7ccbe59a93 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Dec 2004 10:35:25 +0000 Subject: r4040: sorry today is not my day... uint32 != uint8_t ... metze (This used to be commit a8a3b8ee341fda041383df225ea2b7f9b589fc04) --- source4/lib/ldb/ldb_tdb/ldb_pack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 0ebf62df8d..9515beeaa7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -44,7 +44,7 @@ #define LTDB_PACKING_FORMAT_NODN 0x26011966 /* use a portable integer format */ -static void put_uint32(uint32 *p, int ofs, unsigned int val) +static void put_uint32(uint8_t *p, int ofs, unsigned int val) { p += ofs; p[0] = val&0xFF; @@ -53,7 +53,7 @@ static void put_uint32(uint32 *p, int ofs, unsigned int val) p[3] = (val>>24) & 0xFF; } -static unsigned int pull_uint32(uint32 *p, int ofs) +static unsigned int pull_uint32(uint8_t *p, int ofs) { p += ofs; return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); -- cgit From 64b516b10546619d3b1adef7fcc4cfef3ad610f9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Dec 2004 18:27:08 +0000 Subject: r4045: readd krb5 support defaulted to disable use: gensec:krb5=yes gensec:ms_krb5=yes to enable it or -k on the client tools on the command line metze (This used to be commit 0ae5794cf44933d2554e0356baaca24c7a784f71) --- source4/lib/cmdline/popt_common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 6422b84b44..c7bd35cbab 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -373,6 +373,8 @@ static void popt_common_credentials_callback(poptContext con, #else cmdline_auth_info.use_kerberos = True; cmdline_auth_info.got_pass = True; + lp_set_cmdline("gensec:krb5", "True"); + lp_set_cmdline("gensec:ms_krb5", "True"); #endif break; -- cgit From 58c326809a816703dc516c3022c9c4dbb9d09445 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Dec 2004 06:24:38 +0000 Subject: r4052: fixed a bunch of code to use the type safe _p allocation macros (This used to be commit 80d15fa3402a9d1183467463f6b21c0b674bc442) --- source4/lib/util.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 2351a98eae..2d149e6e3d 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -796,3 +796,20 @@ BOOL all_zero(const uint8_t *ptr, uint_t size) } return True; } + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *realloc_array(void *ptr, size_t el_size, unsigned count) +{ +#define MAX_MALLOC_SIZE 0x7fffffff + if (count == 0 || + count >= MAX_MALLOC_SIZE/el_size) { + return NULL; + } + if (!ptr) { + return malloc(el_size * count); + } + return realloc(ptr, el_size * count); +} + -- cgit From e5ce904ddbd6175ba86ed827bf096b76b11b5511 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Dec 2004 06:42:06 +0000 Subject: r4054: got rid of Realloc(), replacing it with the type safe macro realloc_p() (This used to be commit b0f6e21481745d1b2ced28d9ed6f09f6ffd99562) --- source4/lib/util.c | 25 ------------------------- source4/lib/util_file.c | 2 +- source4/lib/util_strlist.c | 6 +++--- source4/lib/wins_srv.c | 2 +- 4 files changed, 5 insertions(+), 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 2d149e6e3d..ac5124840e 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -215,31 +215,6 @@ void become_daemon(BOOL Fork) } -/**************************************************************************** - Expand a pointer to be a particular size. -****************************************************************************/ - -void *Realloc(void *p,size_t size) -{ - void *ret=NULL; - - if (size == 0) { - SAFE_FREE(p); - DEBUG(5,("Realloc asked for 0 bytes\n")); - return NULL; - } - - if (!p) - ret = (void *)malloc(size); - else - ret = (void *)realloc(p,size); - - if (!ret) - DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size)); - - return(ret); -} - /**************************************************************************** Free memory, checks for NULL. Use directly SAFE_FREE() diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 1dbaf1147e..f9697fb337 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -172,7 +172,7 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f) char *t; maxlen *= 2; - t = (char *)Realloc(s,maxlen); + t = realloc_p(s, char, maxlen); if (!t) { DEBUG(0,("fgets_slash: failed to expand buffer!\n")); SAFE_FREE(s); diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index a9198031a1..33f824dcf8 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -53,7 +53,7 @@ char **str_list_make(const char *string, const char *sep) while (next_token(&str, tok, sep, sizeof(tok))) { if (num == lsize) { lsize += S_LIST_ABS; - rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); + rlist = realloc_p(list, char *, lsize + 1); if (!rlist) { DEBUG(0,("str_list_make: Unable to allocate memory")); str_list_free(&list); @@ -94,7 +94,7 @@ BOOL str_list_copy(char ***dest, const char **src) while (src[num]) { if (num == lsize) { lsize += S_LIST_ABS; - rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1))); + rlist = realloc_p(list, char *, lsize + 1); if (!rlist) { DEBUG(0,("str_list_copy: Unable to re-allocate memory")); str_list_free(&list); @@ -302,7 +302,7 @@ int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list) break; /* prepare place for another in_addr structure */ - *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct ipv4_addr)); + *ip_list = realloc_p(*ip_list, struct ipv4_addr, count + 1); if (!*ip_list) return -1; (*ip_list)[count] = addr; diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index c9a5549cdc..094de8d6b0 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -238,7 +238,7 @@ char **wins_srv_tags(void) } /* add it to the list */ - ret = (char **)Realloc(ret, (count+2) * sizeof(char *)); + ret = realloc_p(ret, char *, count+2); ret[count] = strdup(t_ip.tag); if (!ret[count]) break; count++; -- cgit From 6e6374cb5bcffb4df8bdb0a83327fff92b61ac84 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Dec 2004 07:20:30 +0000 Subject: r4055: fixed more places to use type safe allocation macros (This used to be commit eec698254f67365f27b4b7569fa982e22472aca1) --- source4/lib/gencache.c | 5 ++--- source4/lib/netif/interface.c | 2 +- source4/lib/registry/common/reg_interface.c | 4 ++-- source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c | 16 ++++++++-------- source4/lib/registry/tools/regshell.c | 4 ++-- source4/lib/replace.c | 2 +- source4/lib/util_file.c | 2 +- source4/lib/util_getent.c | 12 ++++++------ source4/lib/wins_srv.c | 2 +- source4/lib/xfile.c | 2 +- 10 files changed, 25 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index f32db598f8..160367cfe9 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -253,8 +253,7 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) time_t t; unsigned i; - v = (char*)malloc(sizeof(char) * - (databuf.dsize - TIMEOUT_LEN)); + v = malloc_array_p(char, databuf.dsize - TIMEOUT_LEN); SAFE_FREE(databuf.dptr); sscanf(entry_buf, CACHE_DATA_FMT, (int*)&i, v); @@ -338,7 +337,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time } entry = strndup(databuf.dptr, databuf.dsize); SAFE_FREE(databuf.dptr); - valstr = (char*)malloc(sizeof(char) * (databuf.dsize - TIMEOUT_LEN)); + valstr = malloc_array_p(char, databuf.dsize - TIMEOUT_LEN); sscanf(entry, CACHE_DATA_FMT, (int*)(&i), valstr); timeout = i; diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 3555170123..c73a2e3d7b 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -83,7 +83,7 @@ static void add_interface(struct in_addr ip, struct in_addr nmask) return; } - iface = (struct interface *)malloc(sizeof(*iface)); + iface = malloc_p(struct interface); if (!iface) return; ZERO_STRUCTPN(iface); diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index dea8861745..f7d3af0705 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -51,7 +51,7 @@ NTSTATUS registry_register(const void *_function) return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = malloc(sizeof(struct reg_init_function_entry)); + entry = malloc_p(struct reg_init_function_entry); entry->functions = functions; DLIST_ADD(backends, entry); @@ -85,7 +85,7 @@ WERROR reg_create(struct registry_context **_ret) TALLOC_CTX *mem_ctx; struct registry_context *ret; mem_ctx = talloc_init("registry handle"); - ret = talloc(mem_ctx, sizeof(struct registry_context)); + ret = talloc_p(mem_ctx, struct registry_context); ret->mem_ctx = mem_ctx; ZERO_STRUCTP(ret); *_ret = ret; diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c index aac6e548a8..381f0c3bcf 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c @@ -540,7 +540,7 @@ static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) { SEC_DESC *tmp; - tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC)); + tmp = malloc_p(SEC_DESC); tmp->revision = 1; tmp->type = SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT; @@ -577,7 +577,7 @@ static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) REGF *regf = h->backend_data; KEY_SEC_DESC *tsec = NULL; - tsec = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + tsec = malloc_p(KEY_SEC_DESC); tsec->ref_cnt = 1; tsec->state = SEC_DESC_NBK; @@ -682,7 +682,7 @@ static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, in { REGF *regf = h->backend_data; if (!regf->sk_map) { /* Allocate a block of 10 */ - regf->sk_map = (SK_MAP *)malloc(sizeof(SK_MAP) * 10); + regf->sk_map = malloc_array_p(SK_MAP, 10); regf->sk_map_size = 10; regf->sk_count = 1; (regf->sk_map)[0].sk_off = sk_off; @@ -742,7 +742,7 @@ static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_m return tmp; } else { /* Allocate a new one */ - tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + tmp = malloc_p(KEY_SEC_DESC); memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ tmp->state = SEC_DESC_RES; if (!alloc_sk_map_entry(h, tmp, sk_off)) { @@ -756,7 +756,7 @@ static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc { SEC_DESC *tmp = NULL; - tmp = (SEC_DESC *)malloc(sizeof(SEC_DESC)); + tmp = malloc_p(SEC_DESC); tmp->revision = SVAL(&sec_desc->revision,0); tmp->type = SVAL(&sec_desc->type,0); @@ -838,7 +838,7 @@ static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int */ if (!tmp) { - tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); + tmp = malloc_p(KEY_SEC_DESC); memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* @@ -1154,7 +1154,7 @@ static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); - tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); + tmp = malloc_p(HBIN_BLK); memset(tmp, 0, sizeof(HBIN_BLK)); tmp->data = malloc(size); @@ -1553,7 +1553,7 @@ static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { REGF *regf = h->backend_data; HBIN_BLK *tmp = NULL; - tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); + tmp = malloc_p(HBIN_BLK); memset(tmp, 0, sizeof(HBIN_BLK)); tmp->type = REG_OUTBLK_HDR; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 3333299088..f18b012720 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -247,7 +247,7 @@ static char **reg_complete_command(const char *text, int end) char **matches; int i, len, samelen=0, count=1; - matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); + matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; matches[0] = NULL; @@ -301,7 +301,7 @@ static char **reg_complete_key(const char *text, int end) TALLOC_CTX *mem_ctx; /* Complete argument */ - matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS); + matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; matches[0] = NULL; diff --git a/source4/lib/replace.c b/source4/lib/replace.c index 35e0277c59..ca367da9b5 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -205,7 +205,7 @@ Corrections by richard.kettlewell@kewill.com struct group *g; char *gr; - if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) { + if((grouplst = malloc_array_p(gid_t, max_gr)) == NULL) { DEBUG(0,("initgroups: malloc fail !\n")); return -1; } diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index f9697fb337..2b2fe2b2af 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -281,7 +281,7 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) if (s[0] == '\n') i++; } - ret = (char **)malloc(sizeof(ret[0])*(i+2)); + ret = malloc_array_p(char *, i+2); if (!ret) { SAFE_FREE(p); return NULL; diff --git a/source4/lib/util_getent.c b/source4/lib/util_getent.c index 599e4bb917..9f58472fb8 100644 --- a/source4/lib/util_getent.c +++ b/source4/lib/util_getent.c @@ -33,7 +33,7 @@ struct sys_grent * getgrent_list(void) struct sys_grent *gent; struct group *grp; - gent = (struct sys_grent *) malloc(sizeof(struct sys_grent)); + gent = malloc_p(struct sys_grent); if (gent == NULL) { DEBUG (0, ("Out of memory in getgrent_list!\n")); return NULL; @@ -67,7 +67,7 @@ struct sys_grent * getgrent_list(void) ; /* alloc space for gr_mem string pointers */ - if ((gent->gr_mem = (char **) malloc((num+1) * sizeof(char *))) == NULL) + if ((gent->gr_mem = malloc_array_p(char *, num+1)) == NULL) goto err; memset(gent->gr_mem, '\0', (num+1) * sizeof(char *)); @@ -80,7 +80,7 @@ struct sys_grent * getgrent_list(void) grp = getgrent(); if (grp) { - gent->next = (struct sys_grent *) malloc(sizeof(struct sys_grent)); + gent->next = malloc_p(struct sys_grent); if (gent->next == NULL) goto err; gent = gent->next; @@ -134,7 +134,7 @@ struct sys_pwent * getpwent_list(void) struct sys_pwent *pent; struct passwd *pwd; - pent = (struct sys_pwent *) malloc(sizeof(struct sys_pwent)); + pent = malloc_p(struct sys_pwent); if (pent == NULL) { DEBUG (0, ("Out of memory in getpwent_list!\n")); return NULL; @@ -170,7 +170,7 @@ struct sys_pwent * getpwent_list(void) pwd = getpwent(); if (pwd) { - pent->next = (struct sys_pwent *) malloc(sizeof(struct sys_pwent)); + pent->next = malloc_p(struct sys_pwent); if (pent->next == NULL) goto err; pent = pent->next; @@ -223,7 +223,7 @@ static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_he ; for (i = 0; i < num_users; i++) { - struct sys_userlist *entry = (struct sys_userlist *)malloc(sizeof(*entry)); + struct sys_userlist *entry = malloc_p(struct sys_userlist); if (entry == NULL) { free_userlist(list_head); return NULL; diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c index 094de8d6b0..0338db8b3d 100644 --- a/source4/lib/wins_srv.c +++ b/source4/lib/wins_srv.c @@ -204,7 +204,7 @@ char **wins_srv_tags(void) if (lp_wins_support()) { /* give the caller something to chew on. This makes the rest of the logic simpler (ie. less special cases) */ - ret = (char **)malloc(sizeof(char *)*2); + ret = malloc_array_p(char *, 2); if (!ret) return NULL; ret[0] = strdup("*"); ret[1] = NULL; diff --git a/source4/lib/xfile.c b/source4/lib/xfile.c index 856e5dd6e6..794e3f0f5e 100644 --- a/source4/lib/xfile.c +++ b/source4/lib/xfile.c @@ -96,7 +96,7 @@ XFILE *x_fopen(const char *fname, int flags, mode_t mode) { XFILE *ret; - ret = (XFILE *)malloc(sizeof(XFILE)); + ret = malloc_p(XFILE); if (!ret) return NULL; memset(ret, 0, sizeof(XFILE)); -- cgit From 2f9e170f45e128eb6ab6bd97c9c8b40dcd9a97fa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Dec 2004 09:30:38 +0000 Subject: r4058: added a type safe version of smb_xmalloc() (This used to be commit 1235afa5fe3a396cd7a180cbc500834a30fbaa80) --- source4/lib/registry/tools/regpatch.c | 8 ++++---- source4/lib/util_pw.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index a8b2f83ee1..9b37b7952b 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -154,7 +154,7 @@ static void print_line(struct cmd_line *cl) */ static struct cmd_line *get_cmd_line(int fd) { - struct cmd_line *cl = (CMD_LINE *)smb_xmalloc(sizeof(CMD_LINE)); + struct cmd_line *cl = smb_xmalloc_p(CMD_LINE); int i = 0, rc; uint8_t ch; @@ -445,7 +445,7 @@ static CMD *regedit4_get_cmd(int fd) struct cmd_line *cl = NULL; struct val_spec_list *vl = NULL; - cmd = (struct command_s *)smb_xmalloc(sizeof(struct command_s)); + cmd = smb_xmalloc_p(struct command_s); cmd->cmd = CMD_NONE; cmd->key = NULL; @@ -488,7 +488,7 @@ static CMD *regedit4_get_cmd(int fd) * There could be a \ on the end which we need to * handle at some time */ - vl = (struct val_spec_list *)smb_xmalloc(sizeof(struct val_spec_list)); + vl = smb_xmalloc_p(struct val_spec_list); vl->next = NULL; vl->val = NULL; vl->name = parse_value(cl, &vl->type, &vl->val); @@ -607,7 +607,7 @@ static CMD_FILE *cmd_file_create(const char *file) return NULL; } - tmp = (CMD_FILE *)smb_xmalloc(sizeof(CMD_FILE)); + tmp = smb_xmalloc_p(CMD_FILE); /* * Let's fill in some of the fields; diff --git a/source4/lib/util_pw.c b/source4/lib/util_pw.c index 9d075a05e8..19893e396f 100644 --- a/source4/lib/util_pw.c +++ b/source4/lib/util_pw.c @@ -24,7 +24,7 @@ static struct passwd *alloc_copy_passwd(const struct passwd *from) { - struct passwd *ret = smb_xmalloc(sizeof(struct passwd)); + struct passwd *ret = smb_xmalloc_p(struct passwd); ZERO_STRUCTP(ret); ret->pw_name = smb_xstrdup(from->pw_name); ret->pw_passwd = smb_xstrdup(from->pw_passwd); -- cgit From 9012a501533126c4c0ac25a16fd6439a45df3d9a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Dec 2004 10:14:03 +0000 Subject: r4059: moved the ldb -o option parsing to a common routine (This used to be commit ee52c1e38c9bac852458196ffbd677cca62a3965) --- source4/lib/ldb/common/util.c | 20 ++++++++++++++++++++ source4/lib/ldb/include/ldb_private.h | 2 ++ source4/lib/ldb/tools/ldbadd.c | 14 ++------------ source4/lib/ldb/tools/ldbdel.c | 14 ++------------ source4/lib/ldb/tools/ldbedit.c | 14 ++------------ source4/lib/ldb/tools/ldbmodify.c | 14 ++------------ source4/lib/ldb/tools/ldbrename.c | 14 ++------------ source4/lib/ldb/tools/ldbsearch.c | 14 ++------------ source4/lib/ldb/tools/ldbtest.c | 14 ++------------ 9 files changed, 36 insertions(+), 84 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index af738f352a..0c9cf297c1 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -86,3 +86,23 @@ int ldb_list_find(const void *needle, return -1; } + + +/* + common code for parsing -o options in ldb tools +*/ +const char **ldb_options_parse(const char **options, int *ldbopts, const char *arg) +{ + if (*ldbopts == 0) { + options = malloc(sizeof(char *) * 2); + } else { + options = realloc(options, sizeof(char *)*((*ldbopts)+2)); + } + if (options == NULL) { + fprintf(stderr, "Out of memory in options parsing!\n"); + exit(-1); + } + options[(*ldbopts)++] = arg; + options[*ldbopts] = NULL; + return options; +} diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 720d8928dd..a2171162ad 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -127,4 +127,6 @@ struct ldb_context *lldb_connect(const char *url, const char *options[]); struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); +const char **ldb_options_parse(const char **options, int *ldbopts, const char *arg); + #endif diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index d7f890b155..9d19a1db0a 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static int failures; @@ -100,18 +101,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index dc1c734284..29d3b39730 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) { @@ -95,18 +96,7 @@ static void usage(void) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index fd45248c0e..f84d05440f 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static int verbose; @@ -358,18 +359,7 @@ static void usage(void) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index a660b814da..5fabba57b7 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static int failures; @@ -102,18 +103,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index f702cbd7f2..3ee001cf23 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -36,6 +36,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static void usage(void) { @@ -68,18 +69,7 @@ static void usage(void) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 9f6b2f617a..fced589572 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static void usage(void) { @@ -125,18 +126,7 @@ static int do_search(struct ldb_context *ldb, break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index f3be8e1e5c..645bc93fd3 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" static const char *ldb_url; static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; @@ -387,18 +388,7 @@ static void usage(void) break; case 'o': - ldbopts++; - if (options == NULL) { - options = (const char **)malloc(sizeof(char *) * (ldbopts + 1)); - } else { - options = (const char **)realloc(options, sizeof(char *) * (ldbopts + 1)); - if (options == NULL) { - fprintf(stderr, "Out of memory!\n"); - exit(-1); - } - } - options[ldbopts - 1] = optarg; - options[ldbopts] = NULL; + options = ldb_options_parse(options, &ldbopts, optarg); break; case 'h': -- cgit From 9112a632f6791ffc3c3c1aadd214cbaba8fe816e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 4 Dec 2004 13:56:25 +0000 Subject: r4063: - change char * -> uint8_t in struct request_buffer - change smbcli_read/write to take void * for the buffers to match read(2)/write(2) all this fixes a lot of gcc-4 warnings metze (This used to be commit b94f92bc6637f748d6f7049f4f9a30b0b8d18a7a) --- source4/lib/messaging/messaging.c | 2 +- source4/lib/time.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 041554a7c0..6975f45c8e 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -285,7 +285,7 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd size_t nsent; DATA_BLOB blob; - blob.data = rec->ndone + (char *)&rec->header; + blob.data = rec->ndone + (uint8_t *)&rec->header; blob.length = sizeof(rec->header) - rec->ndone; status = socket_send(rec->sock, &blob, &nsent, 0); diff --git a/source4/lib/time.c b/source4/lib/time.c index 8d477fac02..504b5d6ac3 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -164,7 +164,7 @@ static uint32_t make_dos_date(time_t unixdate, int zone_offset) put a dos date into a buffer (time/date format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void push_dos_date(char *buf, int offset, time_t unixdate, int zone_offset) +void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset) { uint32_t x = make_dos_date(unixdate, zone_offset); SIVAL(buf,offset,x); @@ -174,7 +174,7 @@ void push_dos_date(char *buf, int offset, time_t unixdate, int zone_offset) put a dos date into a buffer (date/time format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void push_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) +void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset) { uint32_t x; x = make_dos_date(unixdate, zone_offset); @@ -187,7 +187,7 @@ put a dos 32 bit "unix like" date into a buffer. This routine takes GMT and converts it to LOCAL time before putting it (most SMBs assume localtime for this sort of date) ********************************************************************/ -void push_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) +void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset) { if (!null_time(unixdate)) { unixdate -= zone_offset; @@ -354,7 +354,7 @@ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) /* put a NTTIME into a packet */ -void push_nttime(void *base, uint16_t offset, NTTIME t) +void push_nttime(uint8_t *base, uint16_t offset, NTTIME t) { SBVAL(base, offset, t); } @@ -362,7 +362,7 @@ void push_nttime(void *base, uint16_t offset, NTTIME t) /* pull a NTTIME from a packet */ -NTTIME pull_nttime(void *base, uint16_t offset) +NTTIME pull_nttime(uint8_t *base, uint16_t offset) { NTTIME ret = BVAL(base, offset); return ret; -- cgit From 9922c2d0357a89db4ee4abbb0beded6a0f24b010 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 4 Dec 2004 14:28:06 +0000 Subject: r4064: use the same name for type on both ends for long term we should remove all typedef's metze (This used to be commit 4b3f552cb373a0d91526412fc31699959c96a007) --- source4/lib/registry/tools/regpatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 9b37b7952b..be60b96019 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -154,7 +154,7 @@ static void print_line(struct cmd_line *cl) */ static struct cmd_line *get_cmd_line(int fd) { - struct cmd_line *cl = smb_xmalloc_p(CMD_LINE); + CMD_LINE *cl = smb_xmalloc_p(CMD_LINE); int i = 0, rc; uint8_t ch; -- cgit From a42dba94d0d6d8203d845f771817d4e48b8c5205 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Dec 2004 06:45:51 +0000 Subject: r4071: - ldap does allow adding additional attribute values with a modify operation, but not if the value already exists - fixed syntax of test.ldif for ldap backend (This used to be commit 29225d0bec39038e42e68849bd9378898f062081) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 9 +++++++-- source4/lib/ldb/tests/test-modify.ldif | 3 +++ source4/lib/ldb/tests/test.ldif | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 4049900a23..6623fd0052 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -516,8 +516,13 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms already exists */ ret = find_element(&msg2, msg->elements[i].name); if (ret != -1) { - ltdb->last_err_string = "Attribute exists"; - goto failed; + for (j=0;jelements[i].num_values;j++) { + if (ldb_msg_find_val(&msg2.elements[ret], + &msg->elements[i].values[j])) { + ltdb->last_err_string = "Type or value exists"; + goto failed; + } + } } if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { goto failed; diff --git a/source4/lib/ldb/tests/test-modify.ldif b/source4/lib/ldb/tests/test-modify.ldif index 78d8353d3c..37ef8293e6 100644 --- a/source4/lib/ldb/tests/test-modify.ldif +++ b/source4/lib/ldb/tests/test-modify.ldif @@ -4,6 +4,9 @@ changetype: modify add: drink drink: mango lassi - +add: drink +drink: lemonade +- delete: pager - replace: telephonenumber diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif index b9afad8b63..8d6c0c750e 100644 --- a/source4/lib/ldb/tests/test.ldif +++ b/source4/lib/ldb/tests/test.ldif @@ -409,8 +409,8 @@ postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109 seealso: cn=All Staff,ou=Groups,o=University of Michigan,c=US homepostaladdress: 123 Anystreet $ Ann Arbor, MI 48104 mail: uham@mail.alumni.example.com -seeAlso: a long attribute name, longer than 128 bytes so that we - trigger sign extension problems in tdb_pack, no thats not long enough +description: a long attribute name, longer than 128 bytes so that we + trigger sign extension problems in tdb_pack, no thats not long enough yet, maybe this is. I'll just keep going till it triggers the error homephone: +1 313 555 8421 pager: +1 313 555 2844 -- cgit From 4b533a90705115410575943ba0cf7630925f7421 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 8 Dec 2004 22:13:28 +0000 Subject: r4106: Add full name of two more hives (This used to be commit c1023db5e8336e495c06acae1773a28d7fc90658) --- source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index 1a7cb38af5..fae5d3f14e 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -64,6 +64,8 @@ openhive(HKCU) openhive(HKPD) openhive(HKU) openhive(HKCR) +openhive(HKDD) +openhive(HKCC) struct rpc_key_data { struct policy_handle pol; @@ -82,6 +84,8 @@ struct { { "HKEY_CLASSES_ROOT", open_HKCR }, { "HKEY_PERFORMANCE_DATA", open_HKPD }, { "HKEY_USERS", open_HKU }, +{ "HKEY_DYN_DATA", open_HKDD }, +{ "HKEY_CURRENT_CONFIG", open_HKCC }, { NULL, NULL } }; -- cgit From 2f1193715ff5815498f16cba4391d7ba5f212366 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 9 Dec 2004 12:42:29 +0000 Subject: r4116: fixed compilation of EnumValue code in winreg rpc backend thanks to volker for pointing this out (This used to be commit 2b67f18bdb58164697efd428391d4cbc46398464) --- .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 30 ++++++++++------------ 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c index fae5d3f14e..3969a763e0 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c @@ -226,9 +226,10 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p struct rpc_key_data *mykeydata = parent->backend_data; WERROR error; struct winreg_EnumValue r; - uint32 type, len1, len2 = 0; - struct EnumValueIn buf_name, buf_val; + uint32 type, len1, zero = 0; NTSTATUS status; + uint8_t buf8; + uint16_t buf16; if(mykeydata->num_values == -1) { error = rpc_query_key(parent); @@ -239,19 +240,13 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p r.in.handle = &mykeydata->pol; r.in.enum_index = n; - r.in.name_in.len = 0; - r.in.name_in.max_len = mykeydata->max_valnamelen * 2; - buf_name.max_len = mykeydata->max_valnamelen; - buf_name.offset = 0; - buf_name.len = 0; - r.in.name_in.buffer = &buf_name; + r.in.name_in.length = 0; + r.in.name_in.size = mykeydata->max_valnamelen * 2; + r.in.name_in.name = &buf16; r.in.type = &type; - buf_val.max_len = mykeydata->max_valdatalen; - buf_val.offset = 0; - buf_val.len = 0; - r.in.value_in = &buf_val; - r.in.value_len1 = &len1; - r.in.value_len2 = &len2; + r.in.value = &buf8; + r.in.length = &zero; + r.in.size = &len1; r.out.type = &type; @@ -261,13 +256,14 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p return WERR_GENERAL_FAILURE; } - if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + if(NT_STATUS_IS_OK(status) && + W_ERROR_IS_OK(r.out.result) && r.out.length) { *value = talloc_p(mem_ctx, struct registry_value); (*value)->parent = parent; (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); (*value)->data_type = type; - (*value)->data_len = r.out.value_out->buffer.length; - (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value_out->buffer.data, r.out.value_out->buffer.length); + (*value)->data_len = *r.out.length; + (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value, *r.out.length); return WERR_OK; } -- cgit From 06fbfade75af40d2d68f86a71a8dd5eaa3ecd0ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Dec 2004 03:41:54 +0000 Subject: r4123: set locale to C to ensure ascii string functions work thanks to Bjoern JACKE for pointing this out (This used to be commit 53c4d0a7d83181afbe01bbbb0840cb2a086b45da) --- source4/lib/charcnv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index bfb1081474..fc1f511403 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -88,6 +88,17 @@ static smb_iconv_t get_conv_handle(charset_t from, charset_t to) to look at */ if (initialised == 0) { initialised = 1; + +#ifdef HAVE_SETLOCALE + /* we set back the locale to C to get ASCII-compatible + toupper/lower functions. For now we do not need + any other POSIX localisations anyway. When we + should really need localized string functions one + day we need to write our own ascii_tolower etc. + */ + setlocale(LC_ALL, "C"); +#endif + atexit(init_iconv); } -- cgit From 60c69445f6fa86b27bd697cc8af52b582f620725 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Dec 2004 04:41:56 +0000 Subject: r4124: include locale.h to get LC_ALL in include/system/iconv.h (This used to be commit 573230ea99136bd66d00bac18effd28b1e5ba76f) --- source4/lib/charcnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index fc1f511403..7e9750e948 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -89,7 +89,7 @@ static smb_iconv_t get_conv_handle(charset_t from, charset_t to) if (initialised == 0) { initialised = 1; -#ifdef HAVE_SETLOCALE +#ifdef LC_ALL /* we set back the locale to C to get ASCII-compatible toupper/lower functions. For now we do not need any other POSIX localisations anyway. When we -- cgit From 444a86792471c0bef33dde15c7a4a33e16a951b4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 10 Dec 2004 20:07:04 +0000 Subject: r4132: - Bunch of rather large fixes in the registry - Added some README files Not everything works yet, e.g. the EnumValue test appears to be broken. (This used to be commit c169e86c1f52763b83e77e509f89cb91f9b69071) --- source4/lib/registry/README | 30 + source4/lib/registry/common/reg_interface.c | 182 +- source4/lib/registry/config.mk | 17 +- source4/lib/registry/reg_backend_dir.c | 148 ++ .../lib/registry/reg_backend_dir/reg_backend_dir.c | 148 -- source4/lib/registry/reg_backend_gconf.c | 193 +++ .../registry/reg_backend_gconf/reg_backend_gconf.c | 193 --- source4/lib/registry/reg_backend_ldb.c | 219 +++ .../lib/registry/reg_backend_ldb/reg_backend_ldb.c | 219 --- source4/lib/registry/reg_backend_nt4.c | 1747 ++++++++++++++++++++ .../lib/registry/reg_backend_nt4/reg_backend_nt4.c | 1747 -------------------- source4/lib/registry/reg_backend_rpc.c | 398 +++++ .../lib/registry/reg_backend_rpc/reg_backend_rpc.c | 405 ----- source4/lib/registry/reg_backend_w95.c | 356 ++++ .../lib/registry/reg_backend_w95/reg_backend_w95.c | 356 ---- source4/lib/registry/reg_backend_wine.c | 48 + .../registry/reg_backend_wine/reg_backend_wine.c | 33 - source4/lib/registry/reg_samba.c | 62 + source4/lib/registry/tools/regdiff.c | 76 +- source4/lib/registry/tools/regpatch.c | 25 +- source4/lib/registry/tools/regshell.c | 87 +- source4/lib/registry/tools/regtree.c | 38 +- 22 files changed, 3418 insertions(+), 3309 deletions(-) create mode 100644 source4/lib/registry/README create mode 100644 source4/lib/registry/reg_backend_dir.c delete mode 100644 source4/lib/registry/reg_backend_dir/reg_backend_dir.c create mode 100644 source4/lib/registry/reg_backend_gconf.c delete mode 100644 source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c create mode 100644 source4/lib/registry/reg_backend_ldb.c delete mode 100644 source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c create mode 100644 source4/lib/registry/reg_backend_nt4.c delete mode 100644 source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c create mode 100644 source4/lib/registry/reg_backend_rpc.c delete mode 100644 source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c create mode 100644 source4/lib/registry/reg_backend_w95.c delete mode 100644 source4/lib/registry/reg_backend_w95/reg_backend_w95.c create mode 100644 source4/lib/registry/reg_backend_wine.c delete mode 100644 source4/lib/registry/reg_backend_wine/reg_backend_wine.c create mode 100644 source4/lib/registry/reg_samba.c (limited to 'source4/lib') diff --git a/source4/lib/registry/README b/source4/lib/registry/README new file mode 100644 index 0000000000..757029cdc2 --- /dev/null +++ b/source4/lib/registry/README @@ -0,0 +1,30 @@ +This is the registry library. The registry is basically a bunch of hives +(HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc) that can be loaded from +different places. + +The various registry backends provide support for loading/saving specific types +of hives: + - ldb + - w95 (USER.DAT-style files) + - nt4 (NTUSER.DAT-style files) + - gconf (GNOME configuration) + - rpc (Remote individual hives) + +Instead of opening individual hives, one can also open a 'complete' registry by +using one of these three functions: + + - reg_open_local() - load local registry, see below + - reg_open_remote() - connect to remote registry over RPC + - reg_open_wine() (not working yet) + +reg_open_local() loads a set of hives based on smb.conf settings. +Lines in smb.conf should have the following syntax: + +registry: = : + +So an example usage could be: + +registry:HKEY_CURRENT_USER = nt4:NTUSER.DAT +registry:HKEY_LOCAL_MACHINE = ldb:tdb://registry.tdb + +WERR_NOT_SUPPORTED will be returned for all hives that haven't been set. diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f7d3af0705..740d849db1 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -30,32 +30,25 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); -#define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)) - /* Register new backend */ -NTSTATUS registry_register(const void *_function) +NTSTATUS registry_register(const void *_hive_ops) { - const struct registry_operations *functions = _function; + const struct hive_operations *hive_ops = _hive_ops; struct reg_init_function_entry *entry = backends; - if (!functions || !functions->name) { - DEBUG(0, ("Invalid arguments while registering registry backend\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - DEBUG(5,("Attempting to register registry backend %s\n", functions->name)); + DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name)); /* Check for duplicates */ - if (reg_find_backend_entry(functions->name)) { - DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name)); + if (reg_find_backend_entry(hive_ops->name)) { + DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name)); return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = malloc_p(struct reg_init_function_entry); - entry->functions = functions; + entry = talloc_p(NULL, struct reg_init_function_entry); + entry->hive_functions = hive_ops; DLIST_ADD(backends, entry); - DEBUG(5,("Successfully added registry backend '%s'\n", functions->name)); + DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name)); return NT_STATUS_OK; } @@ -67,7 +60,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) entry = backends; while(entry) { - if (strcmp(entry->functions->name, name) == 0) return entry; + if (strcmp(entry->hive_functions->name, name) == 0) return entry; entry = entry->next; } @@ -80,85 +73,83 @@ BOOL reg_has_backend(const char *backend) return reg_find_backend_entry(backend) != NULL?True:False; } -WERROR reg_create(struct registry_context **_ret) +static struct { + uint32 hkey; + const char *name; +} hkey_names[] = { - TALLOC_CTX *mem_ctx; - struct registry_context *ret; - mem_ctx = talloc_init("registry handle"); - ret = talloc_p(mem_ctx, struct registry_context); - ret->mem_ctx = mem_ctx; - ZERO_STRUCTP(ret); - *_ret = ret; - return WERR_OK; -} - -WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives) + {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" }, + {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" }, + {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" }, + {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" }, + {HKEY_USERS, "HKEY_USERS" }, + {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" }, + {HKEY_DYN_DATA, "HKEY_DYN_DATA" }, + {HKEY_PT, "HKEY_PT" }, + {HKEY_PN, "HKEY_PN" }, + { 0, NULL } +}; + +int reg_list_hives(TALLOC_CTX *mem_ctx, char ***hives, uint32_t **hkeys) { - struct reg_init_function_entry *entry; - - entry = reg_find_backend_entry(backend); - - if (!entry) { - DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); - return WERR_GENERAL_FAILURE; - } + int i; + *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names)); + *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(hkey_names)); - if(!entry->functions->list_available_hives) { - return WERR_NOT_SUPPORTED; + for (i = 0; hkey_names[i].name; i++) { + (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name); + (*hkeys)[i] = hkey_names[i].hkey; } - return entry->functions->list_available_hives(mem_ctx, location, credentials, hives); + return i; } -WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) +const char *reg_get_hkey_name(uint32_t hkey) { - WERROR error = reg_create(ret), reterror = WERR_NO_MORE_ITEMS; - char **hives; - int i, j; - TALLOC_CTX *mem_ctx = talloc_init("reg_open"); - - if(!W_ERROR_IS_OK(error)) return error; - - error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives); - - if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) { - return reg_import_hive(*ret, backend, location, credentials, NULL); + int i; + for (i = 0; hkey_names[i].name; i++) { + if (hkey_names[i].hkey == hkey) return hkey_names[i].name; } - - if(!W_ERROR_IS_OK(error)) return error; - j = 0; - for(i = 0; hives[i]; i++) - { - error = reg_import_hive(*ret, backend, location, credentials, hives[i]); - if (W_ERROR_IS_OK(error)) { - reterror = WERR_OK; - (*ret)->hives[j]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); - j++; - } else if (!W_ERROR_IS_OK(reterror)) reterror = error; + return NULL; +} + +WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, struct registry_key **key) +{ + int i; + + for (i = 0; hkey_names[i].name; i++) { + if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].hkey, key); } - return reterror; + DEBUG(1, ("No hive with name '%s'\n", name)); + + return WERR_BADFILE; } WERROR reg_close (struct registry_context *ctx) { - int i; - for (i = 0; i < ctx->num_hives; i++) { - if (ctx->hives[i]->functions->close_hive) { - ctx->hives[i]->functions->close_hive(ctx->hives[i]); - } - } talloc_destroy(ctx); return WERR_OK; } +WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry_key **key) +{ + WERROR ret = ctx->get_hive(ctx, hkey, key); + + if (W_ERROR_IS_OK(ret)) { + (*key)->name = talloc_strdup(*key, reg_get_hkey_name(hkey)); + (*key)->path = ""; + } + + return ret; +} + /* Open a registry file/host/etc */ -WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) +WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) { struct registry_hive *ret; - TALLOC_CTX *mem_ctx; struct reg_init_function_entry *entry; WERROR werr; @@ -169,24 +160,21 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch return WERR_GENERAL_FAILURE; } - if(!entry->functions->open_hive) { + if(!entry->hive_functions || !entry->hive_functions->open_hive) { return WERR_NOT_SUPPORTED; } - - mem_ctx = h->mem_ctx; - ret = talloc_p(mem_ctx, struct registry_hive); - ret->location = location?talloc_strdup(mem_ctx, location):NULL; - ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL; - ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; - ret->functions = entry->functions; + ret = talloc_p(parent_ctx, struct registry_hive); + ret->location = location?talloc_strdup(ret, location):NULL; + ret->functions = entry->hive_functions; ret->backend_data = NULL; - ret->reg_ctx = h; - ret->name = NULL; + ret->reg_ctx = parent_ctx; - werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); + werr = entry->hive_functions->open_hive(ret, &ret->root); - if(!W_ERROR_IS_OK(werr)) return werr; + if(!W_ERROR_IS_OK(werr)) { + return werr; + } if(!ret->root) { DEBUG(0, ("Backend %s didn't provide root key!\n", backend)); @@ -195,12 +183,9 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch ret->root->hive = ret; ret->root->name = NULL; - ret->root->path = talloc_strdup(mem_ctx, ""); - - /* Add hive to context */ - h->num_hives++; - h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives); - h->hives[h->num_hives-1] = ret; + ret->root->path = talloc_strdup(ret, ""); + + *root = ret->root; return WERR_OK; } @@ -217,7 +202,7 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co else hivelength = strlen(name); hivename = strndup(name, hivelength); - error = reg_get_hive(handle, hivename, &hive); + error = reg_get_hive_by_name(handle, hivename, &hive); SAFE_FREE(hivename); if(!W_ERROR_IS_OK(error)) { @@ -272,7 +257,8 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char return WERR_NOT_SUPPORTED; } - fullname = reg_make_path(mem_ctx, parent, name); + + fullname = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)); error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); @@ -499,7 +485,7 @@ WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const cha else hivelength = strlen(name); hivename = strndup(name, hivelength); - error = reg_get_hive(handle, hivename, &hive); + error = reg_get_hive_by_name(handle, hivename, &hive); SAFE_FREE(hivename); if(!W_ERROR_IS_OK(error)) return error; @@ -578,19 +564,7 @@ WERROR reg_val_set(struct registry_key *key, const char *value, int type, void * return WERR_NOT_SUPPORTED; } -WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) -{ - int i; - for(i = 0; i < h->num_hives; i++) - { - if(!strcmp(h->hives[i]->name, name)) { - *key = h->hives[i]->root; - return WERR_OK; - } - } - return WERR_NO_MORE_ITEMS; -} WERROR reg_del_value(struct registry_value *val) { diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index b91ec647a0..af9fb83bab 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -6,7 +6,7 @@ INIT_FUNCTION = registry_nt4_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_nt4/reg_backend_nt4.o + lib/registry/reg_backend_nt4.o # End MODULE registry_nt4 ################################################ @@ -16,7 +16,7 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_w95_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_w95/reg_backend_w95.o + lib/registry/reg_backend_w95.o # End MODULE registry_w95 ################################################ @@ -26,7 +26,7 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_dir_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_dir/reg_backend_dir.o + lib/registry/reg_backend_dir.o # End MODULE registry_dir ################################################ @@ -36,18 +36,20 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_rpc_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_rpc/reg_backend_rpc.o + lib/registry/reg_backend_rpc.o REQUIRED_SUBSYSTEMS = RPC_NDR_WINREG # End MODULE registry_rpc ################################################ + + ################################################ # Start MODULE registry_gconf [MODULE::registry_gconf] INIT_FUNCTION = registry_gconf_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_gconf/reg_backend_gconf.o + lib/registry/reg_backend_gconf.o REQUIRED_SUBSYSTEMS = EXT_LIB_gconf # End MODULE registry_gconf ################################################ @@ -58,7 +60,7 @@ REQUIRED_SUBSYSTEMS = EXT_LIB_gconf INIT_FUNCTION = registry_ldb_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_ldb/reg_backend_ldb.o + lib/registry/reg_backend_ldb.o REQUIRED_SUBSYSTEMS = \ LIBLDB # End MODULE registry_ldb @@ -70,7 +72,8 @@ REQUIRED_SUBSYSTEMS = \ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ - lib/registry/common/reg_util.o + lib/registry/common/reg_util.o \ + lib/registry/reg_samba.o REQUIRED_SUBSYSTEMS = \ LIBBASIC # End MODULE registry_ldb diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c new file mode 100644 index 0000000000..5c3ed3c44c --- /dev/null +++ b/source4/lib/registry/reg_backend_dir.c @@ -0,0 +1,148 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "registry.h" +#include "system/dir.h" + +static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) +{ + char *path; + int ret; + asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name); + path = reg_path_win2unix(path); + ret = mkdir(path, 0700); + SAFE_FREE(path); + if(ret == 0)return WERR_OK; /* FIXME */ + return WERR_INVALID_PARAM; +} + +static WERROR reg_dir_del_key(struct registry_key *k) +{ + return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; +} + +static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **subkey) +{ + DIR *d; + char *fullpath; + struct registry_key *ret; + + if(!name) { + DEBUG(0, ("NULL pointer passed as directory name!")); + return WERR_INVALID_PARAM; + } + + + fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); + fullpath = reg_path_win2unix(fullpath); + + d = opendir(fullpath); + if(!d) { + DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); + return WERR_BADFILE; + } + closedir(d); + ret = talloc_p(mem_ctx, struct registry_key); + ret->hive = h; + ret->path = fullpath; + *subkey = ret; + return WERR_OK; +} + +static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **key) +{ + struct dirent *e; + char *fullpath = k->backend_data; + int i = 0; + DIR *d; + + d = opendir(fullpath); + + if(!d) return WERR_INVALID_PARAM; + + while((e = readdir(d))) { + if( strcmp(e->d_name, ".") && + strcmp(e->d_name, "..")) { + struct stat stbuf; + char *thispath; + + /* Check if file is a directory */ + asprintf(&thispath, "%s/%s", fullpath, e->d_name); + stat(thispath, &stbuf); + + if(S_ISDIR(stbuf.st_mode)) { + i++; + if(i == idx) { + (*key) = talloc_p(mem_ctx, struct registry_key); + (*key)->name = e->d_name; + (*key)->path = NULL; + (*key)->backend_data = talloc_strdup(mem_ctx, thispath); + SAFE_FREE(thispath); + closedir(d); + return WERR_OK; + } + } + + SAFE_FREE(thispath); + } + } + + closedir(d); + + return WERR_NO_MORE_ITEMS; +} + +static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key) +{ + if(!h->location) return WERR_INVALID_PARAM; + + *key = talloc_p(h, struct registry_key); + (*key)->backend_data = talloc_strdup(*key, h->location); + return WERR_OK; +} + +static WERROR reg_dir_set_value(struct registry_key *p, const char *name, int type, void *data, int len) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} + +static WERROR reg_dir_del_value(struct registry_value *v) +{ + /* FIXME*/ + return WERR_NOT_SUPPORTED; +} + +static struct hive_operations reg_backend_dir = { + .name = "dir", + .open_hive = reg_dir_open, + .open_key = reg_dir_open_key, + .add_key = reg_dir_add_key, + .del_key = reg_dir_del_key, + .get_subkey_by_index = reg_dir_key_by_index, + .set_value = reg_dir_set_value, + .del_value = reg_dir_del_value, +}; + +NTSTATUS registry_dir_init(void) +{ + return registry_register(®_backend_dir); +} diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c deleted file mode 100644 index 8712e7ce7c..0000000000 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - Copyright (C) Jelmer Vernooij 2004. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "registry.h" -#include "system/dir.h" - -static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) -{ - char *path; - int ret; - asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name); - path = reg_path_win2unix(path); - ret = mkdir(path, 0700); - SAFE_FREE(path); - if(ret == 0)return WERR_OK; /* FIXME */ - return WERR_INVALID_PARAM; -} - -static WERROR reg_dir_del_key(struct registry_key *k) -{ - return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; -} - -static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **subkey) -{ - DIR *d; - char *fullpath; - struct registry_key *ret; - - if(!name) { - DEBUG(0, ("NULL pointer passed as directory name!")); - return WERR_INVALID_PARAM; - } - - - fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); - fullpath = reg_path_win2unix(fullpath); - - d = opendir(fullpath); - if(!d) { - DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); - return WERR_BADFILE; - } - closedir(d); - ret = talloc_p(mem_ctx, struct registry_key); - ret->hive = h; - ret->path = fullpath; - *subkey = ret; - return WERR_OK; -} - -static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **key) -{ - struct dirent *e; - char *fullpath = k->backend_data; - int i = 0; - DIR *d; - - d = opendir(fullpath); - - if(!d) return WERR_INVALID_PARAM; - - while((e = readdir(d))) { - if( strcmp(e->d_name, ".") && - strcmp(e->d_name, "..")) { - struct stat stbuf; - char *thispath; - - /* Check if file is a directory */ - asprintf(&thispath, "%s/%s", fullpath, e->d_name); - stat(thispath, &stbuf); - - if(S_ISDIR(stbuf.st_mode)) { - i++; - if(i == idx) { - (*key) = talloc_p(mem_ctx, struct registry_key); - (*key)->name = e->d_name; - (*key)->path = NULL; - (*key)->backend_data = talloc_strdup(mem_ctx, thispath); - SAFE_FREE(thispath); - closedir(d); - return WERR_OK; - } - } - - SAFE_FREE(thispath); - } - } - - closedir(d); - - return WERR_NO_MORE_ITEMS; -} - -static WERROR reg_dir_open(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) -{ - if(!h->location) return WERR_INVALID_PARAM; - - *key = talloc_p(mem_ctx, struct registry_key); - (*key)->backend_data = talloc_strdup(mem_ctx, h->location); - return WERR_OK; -} - -static WERROR reg_dir_set_value(struct registry_key *p, const char *name, int type, void *data, int len) -{ - /* FIXME */ - return WERR_NOT_SUPPORTED; -} - -static WERROR reg_dir_del_value(struct registry_value *v) -{ - /* FIXME*/ - return WERR_NOT_SUPPORTED; -} - -static struct registry_operations reg_backend_dir = { - .name = "dir", - .open_hive = reg_dir_open, - .open_key = reg_dir_open_key, - .add_key = reg_dir_add_key, - .del_key = reg_dir_del_key, - .get_subkey_by_index = reg_dir_key_by_index, - .set_value = reg_dir_set_value, - .del_value = reg_dir_del_value, -}; - -NTSTATUS registry_dir_init(void) -{ - return registry_register(®_backend_dir); -} diff --git a/source4/lib/registry/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c new file mode 100644 index 0000000000..2fed2417b7 --- /dev/null +++ b/source4/lib/registry/reg_backend_gconf.c @@ -0,0 +1,193 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "registry.h" +#include + +static WERROR gerror_to_werror(GError *error) +{ + if(error == NULL) return WERR_OK; + /* FIXME */ + return WERR_FOOBAR; +} + +static WERROR reg_open_gconf_hive(struct registry_hive *h, struct registry_key **k) +{ + g_type_init(); + h->backend_data = (void *)gconf_client_get_default(); + if(!h->backend_data) return WERR_FOOBAR; + + *k = talloc_p(h, struct registry_key); + (*k)->name = talloc_strdup(*k, ""); + (*k)->path = talloc_strdup(*k, ""); + (*k)->backend_data = talloc_strdup(*k, "/"); + return WERR_OK; +} + +static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +{ + struct registry_key *ret; + char *fullpath; + + fullpath = talloc_asprintf(mem_ctx, "/%s", reg_path_win2unix(talloc_strdup(mem_ctx, name))); + + /* Check if key exists */ + if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { + return WERR_DEST_NOT_FOUND; + } + + ret = talloc_p(mem_ctx, struct registry_key); + ret->backend_data = fullpath; + + *key = ret; + return WERR_OK; +} + +static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_value **val) +{ + GSList *entries; + GSList *cur; + GConfEntry *entry; + GConfValue *value; + struct registry_value *newval; + char *fullpath = p->backend_data; + int i; + cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + entry = cur->data; + value = gconf_entry_get_value(entry); + + newval = talloc_p(mem_ctx, struct registry_value); + newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); + if(value) { + switch(value->type) { + case GCONF_VALUE_INVALID: + newval->data_type = REG_NONE; + break; + + case GCONF_VALUE_STRING: + newval->data_type = REG_SZ; + newval->data_blk = talloc_strdup(mem_ctx, gconf_value_get_string(value)); + newval->data_len = strlen(newval->data_blk); + break; + + case GCONF_VALUE_INT: + newval->data_type = REG_DWORD; + newval->data_blk = talloc_p(mem_ctx, long); + *((long *)newval->data_blk) = gconf_value_get_int(value); + newval->data_len = sizeof(long); + break; + + case GCONF_VALUE_FLOAT: + newval->data_blk = talloc_p(mem_ctx, double); + newval->data_type = REG_BINARY; + *((double *)newval->data_blk) = gconf_value_get_float(value); + newval->data_len = sizeof(double); + break; + + case GCONF_VALUE_BOOL: + newval->data_blk = talloc_p(mem_ctx, BOOL); + newval->data_type = REG_BINARY; + *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); + newval->data_len = sizeof(BOOL); + break; + + default: + newval->data_type = REG_NONE; + DEBUG(0, ("Not implemented..\n")); + break; + } + } else newval->data_type = REG_NONE; + + g_slist_free(entries); + *val = newval; + return WERR_OK; +} + +static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_key **sub) +{ + GSList *dirs; + GSList *cur; + int i; + char *fullpath = p->backend_data; + cur = dirs = gconf_client_all_dirs((GConfClient*)p->hive->backend_data, fullpath,NULL); + + for(i = 0; i < idx && cur; i++) cur = cur->next; + + if(!cur) return WERR_NO_MORE_ITEMS; + + *sub = talloc_p(mem_ctx, struct registry_key); + (*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1); + (*sub)->backend_data = talloc_strdup(mem_ctx, cur->data); + + g_slist_free(dirs); + return WERR_OK; +} + +static WERROR gconf_set_value(struct registry_key *key, const char *valname, int type, void *data, int len) +{ + GError *error = NULL; + char *valpath; + asprintf(&valpath, "%s/%s", key->path, valname); + + switch(type) { + case REG_SZ: + case REG_EXPAND_SZ: + gconf_client_set_string((GConfClient *)key->hive->backend_data, valpath, data, &error); + SAFE_FREE(valpath); + return gerror_to_werror(error); + + case REG_DWORD: + gconf_client_set_int((GConfClient *)key->hive->backend_data, valpath, + *((int *)data), &error); + SAFE_FREE(valpath); + return gerror_to_werror(error); + default: + DEBUG(0, ("Unsupported type: %d\n", type)); + SAFE_FREE(valpath); + return WERR_NOT_SUPPORTED; + } + + return WERR_NOT_SUPPORTED; +} + +static struct hive_operations reg_backend_gconf = { + .name = "gconf", + .open_hive = reg_open_gconf_hive, + .open_key = gconf_open_key, + .get_subkey_by_index = gconf_get_subkey_by_id, + .get_value_by_index = gconf_get_value_by_id, + .set_value = gconf_set_value, + + /* Note: + * since GConf uses schemas for what keys and values are allowed, there + * is no way of 'emulating' add_key and del_key here. + */ +}; + +NTSTATUS registry_gconf_init(void) +{ + return registry_register(®_backend_gconf); +} diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c deleted file mode 100644 index fd258ca285..0000000000 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - Copyright (C) Jelmer Vernooij 2004. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "registry.h" -#include - -static WERROR gerror_to_werror(GError *error) -{ - if(error == NULL) return WERR_OK; - /* FIXME */ - return WERR_FOOBAR; -} - -static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) -{ - g_type_init(); - h->backend_data = (void *)gconf_client_get_default(); - if(!h->backend_data) return WERR_FOOBAR; - - *k = talloc_p(mem_ctx, struct registry_key); - (*k)->name = talloc_strdup(mem_ctx, ""); - (*k)->path = talloc_strdup(mem_ctx, ""); - (*k)->backend_data = talloc_strdup(mem_ctx, "/"); - return WERR_OK; -} - -static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) -{ - struct registry_key *ret; - char *fullpath; - - fullpath = talloc_asprintf(mem_ctx, "/%s", reg_path_win2unix(talloc_strdup(mem_ctx, name))); - - /* Check if key exists */ - if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { - return WERR_DEST_NOT_FOUND; - } - - ret = talloc_p(mem_ctx, struct registry_key); - ret->backend_data = fullpath; - - *key = ret; - return WERR_OK; -} - -static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_value **val) -{ - GSList *entries; - GSList *cur; - GConfEntry *entry; - GConfValue *value; - struct registry_value *newval; - char *fullpath = p->backend_data; - int i; - cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL); - - for(i = 0; i < idx && cur; i++) cur = cur->next; - - if(!cur) return WERR_NO_MORE_ITEMS; - - entry = cur->data; - value = gconf_entry_get_value(entry); - - newval = talloc_p(mem_ctx, struct registry_value); - newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); - if(value) { - switch(value->type) { - case GCONF_VALUE_INVALID: - newval->data_type = REG_NONE; - break; - - case GCONF_VALUE_STRING: - newval->data_type = REG_SZ; - newval->data_blk = talloc_strdup(mem_ctx, gconf_value_get_string(value)); - newval->data_len = strlen(newval->data_blk); - break; - - case GCONF_VALUE_INT: - newval->data_type = REG_DWORD; - newval->data_blk = talloc_p(mem_ctx, long); - *((long *)newval->data_blk) = gconf_value_get_int(value); - newval->data_len = sizeof(long); - break; - - case GCONF_VALUE_FLOAT: - newval->data_blk = talloc_p(mem_ctx, double); - newval->data_type = REG_BINARY; - *((double *)newval->data_blk) = gconf_value_get_float(value); - newval->data_len = sizeof(double); - break; - - case GCONF_VALUE_BOOL: - newval->data_blk = talloc_p(mem_ctx, BOOL); - newval->data_type = REG_BINARY; - *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); - newval->data_len = sizeof(BOOL); - break; - - default: - newval->data_type = REG_NONE; - DEBUG(0, ("Not implemented..\n")); - break; - } - } else newval->data_type = REG_NONE; - - g_slist_free(entries); - *val = newval; - return WERR_OK; -} - -static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_key **sub) -{ - GSList *dirs; - GSList *cur; - int i; - char *fullpath = p->backend_data; - cur = dirs = gconf_client_all_dirs((GConfClient*)p->hive->backend_data, fullpath,NULL); - - for(i = 0; i < idx && cur; i++) cur = cur->next; - - if(!cur) return WERR_NO_MORE_ITEMS; - - *sub = talloc_p(mem_ctx, struct registry_key); - (*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1); - (*sub)->backend_data = talloc_strdup(mem_ctx, cur->data); - - g_slist_free(dirs); - return WERR_OK; -} - -static WERROR gconf_set_value(struct registry_key *key, const char *valname, int type, void *data, int len) -{ - GError *error = NULL; - char *valpath; - asprintf(&valpath, "%s/%s", key->path, valname); - - switch(type) { - case REG_SZ: - case REG_EXPAND_SZ: - gconf_client_set_string((GConfClient *)key->hive->backend_data, valpath, data, &error); - SAFE_FREE(valpath); - return gerror_to_werror(error); - - case REG_DWORD: - gconf_client_set_int((GConfClient *)key->hive->backend_data, valpath, - *((int *)data), &error); - SAFE_FREE(valpath); - return gerror_to_werror(error); - default: - DEBUG(0, ("Unsupported type: %d\n", type)); - SAFE_FREE(valpath); - return WERR_NOT_SUPPORTED; - } - - return WERR_NOT_SUPPORTED; -} - -static struct registry_operations reg_backend_gconf = { - .name = "gconf", - .open_hive = reg_open_gconf_hive, - .open_key = gconf_open_key, - .get_subkey_by_index = gconf_get_subkey_by_id, - .get_value_by_index = gconf_get_value_by_id, - .set_value = gconf_set_value, - - /* Note: - * since GConf uses schemas for what keys and values are allowed, there - * is no way of 'emulating' add_key and del_key here. - */ -}; - -NTSTATUS registry_gconf_init(void) -{ - return registry_register(®_backend_gconf); -} diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c new file mode 100644 index 0000000000..7eaf6194a5 --- /dev/null +++ b/source4/lib/registry/reg_backend_ldb.c @@ -0,0 +1,219 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "registry.h" +#include "lib/ldb/include/ldb.h" + +static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) +{ + char *ret = talloc_strdup(mem_ctx, ""); + char *mypath = strdup(path); + char *end = mypath, *begin; + + if(add) + ret = talloc_asprintf_append(ret, "%s", add); + + while(end) { + char *keyname; + begin = strrchr(end, '\\'); + + if(begin) keyname = begin + 1; + else keyname = mypath; + + if(strlen(keyname)) + ret = talloc_asprintf_append(ret, "key=%s,", keyname); + + if(begin) { + *begin = '\0'; + end = begin-1; + } else { + end = NULL; + } + } + + SAFE_FREE(mypath); + + ret[strlen(ret)-1] = '\0'; + + if(strlen(ret) == 0) return NULL; + + return ret; +} + + +static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) +{ + struct ldb_context *c = k->hive->backend_data; + int ret; + struct ldb_message **msg; + struct ldb_message_element *el; + + ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); + + if(ret < 0) { + DEBUG(0, ("Error getting subkeys for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); + return WERR_FOOBAR; + } + + if(idx >= ret) return WERR_NO_MORE_ITEMS; + + el = ldb_msg_find_element(msg[idx], "key"); + + *subkey = talloc_p(mem_ctx, struct registry_key); + (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); + (*subkey)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); + + ldb_search_free(c, msg); + return WERR_OK; +} + +static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) +{ + struct ldb_context *c = k->hive->backend_data; + int ret; + struct ldb_message **msg; + struct ldb_message_element *el; + + ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); + + if(ret < 0) { + DEBUG(0, ("Error getting values for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); + return WERR_FOOBAR; + } + + if(idx >= ret) return WERR_NO_MORE_ITEMS; + + el = ldb_msg_find_element(msg[idx], "value"); + + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); + (*value)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); + + ldb_search_free(c, msg); + return WERR_OK; +} + +static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +{ + struct ldb_context *c = h->backend_data; + struct ldb_message **msg; + char *ldap_path; + int ret; + ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); + + ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); + + if(ret == 0) { + return WERR_NO_MORE_ITEMS; + } else if(ret < 0) { + DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c))); + return WERR_FOOBAR; + } + + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); + (*key)->backend_data = talloc_strdup(mem_ctx, msg[0]->dn); + + ldb_search_free(c, msg); + + return WERR_OK; +} + +static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) +{ + struct ldb_context *c; + + if (!hive->location) return WERR_INVALID_PARAM; + c = ldb_connect(hive->location, 0, NULL); + + if(!c) { + DEBUG(1, ("ldb_open_hive: %s\n", ldb_errstring(hive->backend_data))); + return WERR_FOOBAR; + } + ldb_set_debug_stderr(c); + hive->backend_data = c; + + hive->root = talloc_zero_p(hive, struct registry_key); + hive->root->name = talloc_strdup(hive->root, ""); + + return WERR_OK; +} + +static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sd, struct registry_key **newkey) +{ + struct ldb_context *ctx = parent->hive->backend_data; + struct ldb_message msg; + int ret; + + ZERO_STRUCT(msg); + + msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "key=%s,", name)); + + ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name)); + + ret = ldb_add(ctx, &msg); + if (ret < 0) { + DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); + return WERR_FOOBAR; + } + + *newkey = talloc_zero_p(mem_ctx, struct registry_key); + (*newkey)->backend_data = msg.dn; + (*newkey)->name = talloc_strdup(mem_ctx, name); + + return WERR_OK; +} + +static WERROR ldb_del_key (struct registry_key *key) +{ + int ret; + + ret = ldb_delete(key->hive->backend_data, key->backend_data); + + if (ret < 0) { + DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); + return WERR_FOOBAR; + } + + return WERR_OK; +} + +static WERROR ldb_close_hive (struct registry_hive *hive) +{ + ldb_close (hive->backend_data); + return WERR_OK; +} + +static struct hive_operations reg_backend_ldb = { + .name = "ldb", + .add_key = ldb_add_key, + .del_key = ldb_del_key, + .open_hive = ldb_open_hive, + .close_hive = ldb_close_hive, + .open_key = ldb_open_key, + .get_value_by_index = ldb_get_value_by_id, + .get_subkey_by_index = ldb_get_subkey_by_id, +}; + +NTSTATUS registry_ldb_init(void) +{ + return registry_register(®_backend_ldb); +} diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c deleted file mode 100644 index 380a8010f2..0000000000 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - Copyright (C) Jelmer Vernooij 2004. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "registry.h" -#include "lib/ldb/include/ldb.h" - -static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) -{ - char *ret = talloc_strdup(mem_ctx, ""); - char *mypath = strdup(path); - char *end = mypath, *begin; - - if(add) - ret = talloc_asprintf_append(ret, "%s", add); - - while(end) { - char *keyname; - begin = strrchr(end, '\\'); - - if(begin) keyname = begin + 1; - else keyname = mypath; - - if(strlen(keyname)) - ret = talloc_asprintf_append(ret, "key=%s,", keyname); - - if(begin) { - *begin = '\0'; - end = begin-1; - } else { - end = NULL; - } - } - - SAFE_FREE(mypath); - - ret[strlen(ret)-1] = '\0'; - - if(strlen(ret) == 0) return NULL; - - return ret; -} - - -static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) -{ - struct ldb_context *c = k->hive->backend_data; - int ret; - struct ldb_message **msg; - struct ldb_message_element *el; - - ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); - - if(ret < 0) { - DEBUG(0, ("Error getting subkeys for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); - return WERR_FOOBAR; - } - - if(idx >= ret) return WERR_NO_MORE_ITEMS; - - el = ldb_msg_find_element(msg[idx], "key"); - - *subkey = talloc_p(mem_ctx, struct registry_key); - (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*subkey)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); - - ldb_search_free(c, msg); - return WERR_OK; -} - -static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) -{ - struct ldb_context *c = k->hive->backend_data; - int ret; - struct ldb_message **msg; - struct ldb_message_element *el; - - ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); - - if(ret < 0) { - DEBUG(0, ("Error getting values for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); - return WERR_FOOBAR; - } - - if(idx >= ret) return WERR_NO_MORE_ITEMS; - - el = ldb_msg_find_element(msg[idx], "value"); - - *value = talloc_p(mem_ctx, struct registry_value); - (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*value)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); - - ldb_search_free(c, msg); - return WERR_OK; -} - -static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) -{ - struct ldb_context *c = h->backend_data; - struct ldb_message **msg; - char *ldap_path; - int ret; - ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); - - ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); - - if(ret == 0) { - return WERR_NO_MORE_ITEMS; - } else if(ret < 0) { - DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c))); - return WERR_FOOBAR; - } - - *key = talloc_p(mem_ctx, struct registry_key); - (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); - (*key)->backend_data = talloc_strdup(mem_ctx, msg[0]->dn); - - ldb_search_free(c, msg); - - return WERR_OK; -} - -static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) -{ - struct ldb_context *c; - - if (!hive->location) return WERR_INVALID_PARAM; - c = ldb_connect(hive->location, 0, NULL); - - if(!c) { - DEBUG(1, ("ldb_open_hive: %s\n", ldb_errstring(hive->backend_data))); - return WERR_FOOBAR; - } - ldb_set_debug_stderr(c); - hive->backend_data = c; - - hive->root = talloc_zero_p(mem_ctx, struct registry_key); - hive->root->name = talloc_strdup(mem_ctx, ""); - - return WERR_OK; -} - -static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sd, struct registry_key **newkey) -{ - struct ldb_context *ctx = parent->hive->backend_data; - struct ldb_message msg; - int ret; - - ZERO_STRUCT(msg); - - msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "key=%s,", name)); - - ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name)); - - ret = ldb_add(ctx, &msg); - if (ret < 0) { - DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); - return WERR_FOOBAR; - } - - *newkey = talloc_zero_p(mem_ctx, struct registry_key); - (*newkey)->backend_data = msg.dn; - (*newkey)->name = talloc_strdup(mem_ctx, name); - - return WERR_OK; -} - -static WERROR ldb_del_key (struct registry_key *key) -{ - int ret; - - ret = ldb_delete(key->hive->backend_data, key->backend_data); - - if (ret < 0) { - DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); - return WERR_FOOBAR; - } - - return WERR_OK; -} - -static WERROR ldb_close_hive (struct registry_hive *hive) -{ - ldb_close (hive->backend_data); - return WERR_OK; -} - -static struct registry_operations reg_backend_ldb = { - .name = "ldb", - .add_key = ldb_add_key, - .del_key = ldb_del_key, - .open_hive = ldb_open_hive, - .close_hive = ldb_close_hive, - .open_key = ldb_open_key, - .get_value_by_index = ldb_get_value_by_id, - .get_subkey_by_index = ldb_get_subkey_by_id, -}; - -NTSTATUS registry_ldb_init(void) -{ - return registry_register(®_backend_ldb); -} diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c new file mode 100644 index 0000000000..117d8d1b81 --- /dev/null +++ b/source4/lib/registry/reg_backend_nt4.c @@ -0,0 +1,1747 @@ +/* + Samba Unix/Linux SMB client utility libeditreg.c + Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com + Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/************************************************************************* + + A utility to edit a Windows NT/2K etc registry file. + + Many of the ideas in here come from other people and software. + I first looked in Wine in misc/registry.c and was also influenced by + http://www.wednesday.demon.co.uk/dosreg.html + + Which seems to contain comments from someone else. I reproduce them here + incase the site above disappears. It actually comes from + http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. + + The goal here is to read the registry into memory, manipulate it, and then + write it out if it was changed by any actions of the user. + +The windows NT registry has 2 different blocks, where one can occur many +times... + +the "regf"-Block +================ + +"regf" is obviously the abbreviation for "Registry file". "regf" is the +signature of the header-block which is always 4kb in size, although only +the first 64 bytes seem to be used and a checksum is calculated over +the first 0x200 bytes only! + +Offset Size Contents +0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 +0x00000004 D-Word ???? //see struct REG_HANDLE +0x00000008 D-Word ???? Always the same value as at 0x00000004 +0x0000000C Q-Word last modify date in WinNT date-format +0x00000014 D-Word 1 +0x00000018 D-Word 3 +0x0000001C D-Word 0 +0x00000020 D-Word 1 +0x00000024 D-Word Offset of 1st key record +0x00000028 D-Word Size of the data-blocks (Filesize-4kb) +0x0000002C D-Word 1 +0x000001FC D-Word Sum of all D-Words from 0x00000000 to +0x000001FB //XOR of all words. Nigel + +I have analyzed more registry files (from multiple machines running +NT 4.0 german version) and could not find an explanation for the values +marked with ???? the rest of the first 4kb page is not important... + +the "hbin"-Block +================ +I don't know what "hbin" stands for, but this block is always a multiple +of 4kb in size. + +Inside these hbin-blocks the different records are placed. The memory- +management looks like a C-compiler heap management to me... + +hbin-Header +=========== +Offset Size Contents +0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 +0x0004 D-Word Offset from the 1st hbin-Block +0x0008 D-Word Offset to the next hbin-Block +0x001C D-Word Block-size + +The values in 0x0008 and 0x001C should be the same, so I don't know +if they are correct or swapped... + +From offset 0x0020 inside a hbin-block data is stored with the following +format: + +Offset Size Contents +0x0000 D-Word Data-block size //this size must be a +multiple of 8. Nigel +0x0004 ???? Data + +If the size field is negative (bit 31 set), the corresponding block +is free and has a size of -blocksize! + +That does not seem to be true. All block lengths seem to be negative! +(Richard Sharpe) + +The data is stored as one record per block. Block size is a multiple +of 4 and the last block reaches the next hbin-block, leaving no room. + +(That also seems incorrect, in that the block size if a multiple of 8. +That is, the block, including the 4 byte header, is always a multiple of +8 bytes. Richard Sharpe.) + +Records in the hbin-blocks +========================== + +nk-Record + + The nk-record can be treated as a combination of tree-record and + key-record of the win 95 registry. + +lf-Record + + The lf-record is the counterpart to the RGKN-record (the + hash-function) + +vk-Record + + The vk-record consists information to a single value (value key). + +sk-Record + + sk (? Security Key ?) is the ACL of the registry. + +Value-Lists + + The value-lists contain information about which values are inside a + sub-key and don't have a header. + +Datas + + The datas of the registry are (like the value-list) stored without a + header. + +All offset-values are relative to the first hbin-block and point to the +block-size field of the record-entry. to get the file offset, you have to add +the header size (4kb) and the size field (4 bytes)... + +the nk-Record +============= +Offset Size Contents +0x0000 Word ID: ASCII-"nk" = 0x6B6E +0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel +0x0004 Q-Word write-date/time in windows nt notation +0x0010 D-Word Offset of Owner/Parent key +0x0014 D-Word number of sub-Keys +0x001C D-Word Offset of the sub-key lf-Records +0x0024 D-Word number of values +0x0028 D-Word Offset of the Value-List +0x002C D-Word Offset of the sk-Record + +0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel +0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel +0x0048 Word name-length +0x004A Word class-name length +0x004C ???? key-name + +the Value-List +============== +Offset Size Contents +0x0000 D-Word Offset 1st Value +0x0004 D-Word Offset 2nd Value +0x???? D-Word Offset nth Value + +To determine the number of values, you have to look at the owner-nk-record! + +The vk-Record +============= +Offset Size Contents +0x0000 Word ID: ASCII-"vk" = 0x6B76 +0x0002 Word name length +0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel +0x0008 D-Word Offset of Data +0x000C D-Word Type of value +0x0010 Word Flag +0x0012 Word Unused (data-trash) +0x0014 ???? Name + +If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) + +If the data-size is lower 5, the data-offset value is used to store the data itself! + +The data-types +============== +Wert Beteutung +0x0001 RegSZ: character string (in UNICODE!) +0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) +0x0003 RegBin: raw-binary value +0x0004 RegDWord: Dword +0x0007 RegMultiSZ: multiple strings, seperated with 0 + (UNICODE!) + +The "lf"-record +=============== +Offset Size Contents +0x0000 Word ID: ASCII-"lf" = 0x666C +0x0002 Word number of keys +0x0004 ???? Hash-Records + +Hash-Record +=========== +Offset Size Contents +0x0000 D-Word Offset of corresponding "nk"-Record +0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! + +Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the +key-name you have to change the hash-value too! + +//These hashrecords must be sorted low to high within the lf record. Nigel. + +The "sk"-block +============== +(due to the complexity of the SAM-info, not clear jet) +(This is just a self-relative security descriptor in the data. R Sharpe.) + + +Offset Size Contents +0x0000 Word ID: ASCII-"sk" = 0x6B73 +0x0002 Word Unused +0x0004 D-Word Offset of previous "sk"-Record +0x0008 D-Word Offset of next "sk"-Record +0x000C D-Word usage-counter +0x0010 D-Word Size of "sk"-record in bytes +???? //standard self +relative security desciptor. Nigel +???? ???? Security and auditing settings... +???? + +The usage counter counts the number of references to this +"sk"-record. You can use one "sk"-record for the entire registry! + +Windows nt date/time format +=========================== +The time-format is a 64-bit integer which is incremented every +0,0000001 seconds by 1 (I don't know how accurate it realy is!) +It starts with 0 at the 1st of january 1601 0:00! All values are +stored in GMT time! The time-zone is important to get the real +time! + +Common values for win95 and win-nt +================================== +Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). +If a value has no name (length=0, flag(bit 0)=0), it is treated as the +"Default" entry... +If a value has no data (length=0), it is displayed as empty. + +simplyfied win-3.?? registry: +============================= + ++-----------+ +| next rec. |---+ +----->+------------+ +| first sub | | | | Usage cnt. | +| name | | +-->+------------+ | | length | +| value | | | | next rec. | | | text |------->+-------+ ++-----------+ | | | name rec. |--+ +------------+ | xxxxx | + +------------+ | | value rec. |-------->+------------+ +-------+ + v | +------------+ | Usage cnt. | ++-----------+ | | length | +| next rec. | | | text |------->+-------+ +| first sub |------+ +------------+ | xxxxx | +| name | +-------+ +| value | ++-----------+ + +Greatly simplyfied structure of the nt-registry: +================================================ + ++---------------------------------------------------------------+ +| | +v | ++---------+ +---------->+-----------+ +----->+---------+ | +| "nk" | | | lf-rec. | | | nk-rec. | | +| ID | | | # of keys | | | parent |---+ +| Date | | | 1st key |--+ | .... | +| parent | | +-----------+ +---------+ +| suk-keys|-----+ +| values |--------------------->+----------+ +| SK-rec. |---------------+ | 1. value |--> +----------+ +| class |--+ | +----------+ | vk-rec. | ++---------+ | | | .... | + v | | data |--> +-------+ + +------------+ | +----------+ | xxxxx | + | Class name | | +-------+ + +------------+ | + v + +---------+ +---------+ + +----->| next sk |--->| Next sk |--+ + | +---| prev sk |<---| prev sk | | + | | | .... | | ... | | + | | +---------+ +---------+ | + | | ^ | + | | | | + | +--------------------+ | + +----------------------------------+ + +--------------------------------------------------------------------------- + +Hope this helps.... (Although it was "fun" for me to uncover this things, + it took me several sleepless nights ;) + + B.D. + +*************************************************************************/ + +#include "includes.h" +#include "registry.h" +#include "system/shmem.h" + +#define REG_KEY_LIST_SIZE 10 +#define FLAG_HAS_NAME 0x01 +/*FIXME*/ + +/* + * Structures for dealing with the on-disk format of the registry + */ + +const char *def_owner_sid_str = NULL; + +/* + * These definitions are for the in-memory registry structure. + * It is a tree structure that mimics what you see with tools like regedit + */ + + +/* + * Definition of a Key. It has a name, classname, date/time last modified, + * sub-keys, values, and a security descriptor + */ + +#define REG_ROOT_KEY 1 +#define REG_SUB_KEY 2 +#define REG_SYM_LINK 3 + +/* + * All of the structures below actually have a four-byte length before them + * which always seems to be negative. The following macro retrieves that + * size as an integer + */ + +#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) + +typedef uint_t DWORD; +typedef unsigned short WORD; + +typedef struct sk_struct SK_HDR; +/* + * This structure keeps track of the output format of the registry + */ +#define REG_OUTBLK_HDR 1 +#define REG_OUTBLK_HBIN 2 + +typedef struct regf_block { + DWORD REGF_ID; /* regf */ + DWORD uk1; + DWORD uk2; + DWORD tim1, tim2; + DWORD uk3; /* 1 */ + DWORD uk4; /* 3 */ + DWORD uk5; /* 0 */ + DWORD uk6; /* 1 */ + DWORD first_key; /* offset */ + uint_t dblk_size; + DWORD uk7[116]; /* 1 */ + DWORD chksum; +} REGF_HDR; + +typedef struct hbin_sub_struct { + DWORD dblocksize; + char data[1]; +} HBIN_SUB_HDR; + +typedef struct hbin_struct { + DWORD HBIN_ID; /* hbin */ + DWORD off_from_first; + DWORD off_to_next; + DWORD uk1; + DWORD uk2; + DWORD uk3; + DWORD uk4; + DWORD blk_size; + HBIN_SUB_HDR hbin_sub_hdr; +} HBIN_HDR; + +typedef struct nk_struct { + WORD NK_ID; + WORD type; + DWORD t1, t2; + DWORD uk1; + DWORD own_off; + DWORD subk_num; + DWORD uk2; + DWORD lf_off; + DWORD uk3; + DWORD val_cnt; + DWORD val_off; + DWORD sk_off; + DWORD clsnam_off; + DWORD unk4[4]; + DWORD unk5; + WORD nam_len; + WORD clsnam_len; + char key_nam[1]; /* Actual length determined by nam_len */ +} NK_HDR; + +struct sk_struct { + WORD SK_ID; + WORD uk1; + DWORD prev_off; + DWORD next_off; + DWORD ref_cnt; + DWORD rec_size; + char sec_desc[1]; +}; + +typedef struct key_sec_desc_s { + struct key_sec_desc_s *prev, *next; + int ref_cnt; + int state; + int offset; + SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ + SEC_DESC *sec_desc; +} KEY_SEC_DESC; + +/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ +typedef struct sk_map_s { + int sk_off; + KEY_SEC_DESC *key_sec_desc; +} SK_MAP; + +typedef struct vk_struct { + WORD VK_ID; + WORD nam_len; + DWORD dat_len; /* If top-bit set, offset contains the data */ + DWORD dat_off; + DWORD dat_type; + WORD flag; /* =1, has name, else no name (=Default). */ + WORD unk1; + char dat_name[1]; /* Name starts here ... */ +} VK_HDR; + +typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */ + +typedef struct hash_struct { + DWORD nk_off; + char hash[4]; +} HASH_REC; + + +typedef struct lf_struct { + WORD LF_ID; + WORD key_count; + struct hash_struct hr[1]; /* Array of hash records, depending on key_count */} LF_HDR; + + + +/* + * This structure keeps track of the output format of the registry + */ +#define REG_OUTBLK_HDR 1 +#define REG_OUTBLK_HBIN 2 + +typedef struct hbin_blk_s { + int type, size; + struct hbin_blk_s *next; + char *data; /* The data block */ + uint_t file_offset; /* Offset in file */ + uint_t free_space; /* Amount of free space in block */ + uint_t fsp_off; /* Start of free space in block */ + int complete, stored; +} HBIN_BLK; + +typedef struct regf_struct_s { + int reg_type; + int fd; + struct stat sbuf; + char *base; + BOOL modified; + NTTIME last_mod_time; + NK_HDR *first_key; + int sk_count, sk_map_size; + SK_MAP *sk_map; + const char *owner_sid_str; + SEC_DESC *def_sec_desc; + /* + * These next pointers point to the blocks used to contain the + * keys when we are preparing to write them to a file + */ + HBIN_BLK *blk_head, *blk_tail, *free_space; +} REGF; + +static DWORD str_to_dword(const char *a) { + int i; + unsigned long ret = 0; + for(i = strlen(a)-1; i >= 0; i--) { + ret = ret * 0x100 + a[i]; + } + return ret; +} + +#if 0 + +/* + * Create an ACE + */ +static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, const char *sid) +{ + DOM_SID s; + SEC_ACCESS access; + access.mask = perms; + if(!string_to_sid(&s, sid))return False; + init_sec_ace(ace, &s, type, access, flags); + return True; +} + +/* + * Create a default ACL + */ +static SEC_ACL *nt_create_default_acl(struct registry_hive *regf) +{ + SEC_ACE aces[8]; + + if(!nt_create_ace(&aces[0], 0x00, 0x0, 0xF003F, regf->owner_sid_str)) return NULL; + if(!nt_create_ace(&aces[1], 0x00, 0x0, 0xF003F, "S-1-5-18")) return NULL; + if(!nt_create_ace(&aces[2], 0x00, 0x0, 0xF003F, "S-1-5-32-544")) return NULL; + if(!nt_create_ace(&aces[3], 0x00, 0x0, 0x20019, "S-1-5-12")) return NULL; + if(!nt_create_ace(&aces[4], 0x00, 0x0B, GENERIC_RIGHT_ALL_ACCESS, regf->owner_sid_str)) return NULL; + if(!nt_create_ace(&aces[5], 0x00, 0x0B, 0x10000000, "S-1-5-18")) return NULL; + if(!nt_create_ace(&aces[6], 0x00, 0x0B, 0x10000000, "S-1-5-32-544")) return NULL; + if(!nt_create_ace(&aces[7], 0x00, 0x0B, 0x80000000, "S-1-5-12")) return NULL; + + return make_sec_acl(regf->mem_ctx, 2, 8, aces); +} + +/* + * Create a default security descriptor. We pull in things from env + * if need be + */ +static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) +{ + SEC_DESC *tmp; + + tmp = malloc_p(SEC_DESC); + + tmp->revision = 1; + tmp->type = SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT; + if (!string_to_sid(tmp->owner_sid, "S-1-5-32-544")) goto error; + if (!string_to_sid(tmp->grp_sid, "S-1-5-18")) goto error; + tmp->sacl = NULL; + tmp->dacl = nt_create_default_acl(regf); + + return tmp; + + error: + if (tmp) nt_delete_sec_desc(tmp); + return NULL; +} + +/* + * We will implement inheritence that is based on what the parent's SEC_DESC + * says, but the Owner and Group SIDs can be overwridden from the command line + * and additional ACEs can be applied from the command line etc. + */ +static KEY_SEC_DESC *nt_inherit_security(struct registry_key *key) +{ + + if (!key) return NULL; + return key->security; +} + +/* + * Create an initial security descriptor and init other structures, if needed + * We assume that the initial security stuff is empty ... + */ +static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) +{ + REGF *regf = h->backend_data; + KEY_SEC_DESC *tsec = NULL; + + tsec = malloc_p(KEY_SEC_DESC); + + tsec->ref_cnt = 1; + tsec->state = SEC_DESC_NBK; + tsec->offset = 0; + + tsec->sec_desc = regf->def_sec_desc; + + return tsec; +} +#endif + +/* + * Get the starting record for NT Registry file + */ + +/* + * Where we keep all the regf stuff for one registry. + * This is the structure that we use to tie the in memory tree etc + * together. By keeping separate structs, we can operate on different + * registries at the same time. + * Currently, the SK_MAP is an array of mapping structure. + * Since we only need this on input and output, we fill in the structure + * as we go on input. On output, we know how many SK items we have, so + * we can allocate the structure as we need to. + * If you add stuff here that is dynamically allocated, add the + * appropriate free statements below. + */ + +#define REG_HANDLE_REGTYPE_NONE 0 +#define REG_HANDLE_REGTYPE_NT 1 +#define REG_HANDLE_REGTYPE_W9X 2 + +#define TTTONTTIME(r, t1, t2) (r)->last_mod_time = (t1) | (((uint64_t)(t2)) << 32) + +#define REGF_HDR_BLKSIZ 0x1000 + +#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) +#define LOCN(base, f) ((base) + OFF(f)) + +/* Get the header of the registry. Return a pointer to the structure + * If the mmap'd area has not been allocated, then mmap the input file + */ +static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) +{ + REGF *regf = h->backend_data; + SMB_REG_ASSERT(regf); + + if (!regf->base) { /* Try to mmap etc the file */ + + if ((regf->fd = open(h->location, O_RDONLY, 0000)) <0) { + return NULL; /* What about errors? */ + } + + if (fstat(regf->fd, ®f->sbuf) < 0) { + return NULL; + } + + regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0); + + if ((int)regf->base == 1) { + DEBUG(0,("Could not mmap file: %s, %s\n", h->location, + strerror(errno))); + return NULL; + } + } + + /* + * At this point, regf->base != NULL, and we should be able to read the + * header + */ + + SMB_REG_ASSERT(regf->base != NULL); + + return (REGF_HDR *)regf->base; +} + +/* + * Validate a regf header + * For now, do nothing, but we should check the checksum + */ +static int valid_regf_hdr(REGF_HDR *regf_hdr) +{ + if (!regf_hdr) return 0; + + return 1; +} + +#if 0 + +/* + * Process an SK header ... + * Every time we see a new one, add it to the map. Otherwise, just look it up. + * We will do a simple linear search for the moment, since many KEYs have the + * same security descriptor. + * We allocate the map in increments of 10 entries. + */ + +/* + * Create a new entry in the map, and increase the size of the map if needed + */ +static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, int sk_off) +{ + REGF *regf = h->backend_data; + if (!regf->sk_map) { /* Allocate a block of 10 */ + regf->sk_map = malloc_array_p(SK_MAP, 10); + regf->sk_map_size = 10; + regf->sk_count = 1; + (regf->sk_map)[0].sk_off = sk_off; + (regf->sk_map)[0].key_sec_desc = tmp; + } + else { /* Simply allocate a new slot, unless we have to expand the list */ + int ndx = regf->sk_count; + if (regf->sk_count >= regf->sk_map_size) { + regf->sk_map = (SK_MAP *)realloc(regf->sk_map, + (regf->sk_map_size + 10)*sizeof(SK_MAP)); + if (!regf->sk_map) { + free(tmp); + return NULL; + } + /* + * ndx already points at the first entry of the new block + */ + regf->sk_map_size += 10; + } + (regf->sk_map)[ndx].sk_off = sk_off; + (regf->sk_map)[ndx].key_sec_desc = tmp; + regf->sk_count++; + } + return regf->sk_map; +} + +/* + * Search for a KEY_SEC_DESC in the sk_map, but don't create one if not + * found + */ +KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) +{ + int i; + + if (!sk_map) return NULL; + + for (i = 0; i < count; i++) { + + if (sk_map[i].sk_off == sk_off) + return sk_map[i].key_sec_desc; + + } + + return NULL; + +} + +/* + * Allocate a KEY_SEC_DESC if we can't find one in the map + */ +static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_map, int sk_off) +{ + REGF *regf = h->backend_data; + KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); + + if (tmp) { + return tmp; + } + else { /* Allocate a new one */ + tmp = malloc_p(KEY_SEC_DESC); + memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ + tmp->state = SEC_DESC_RES; + if (!alloc_sk_map_entry(h, tmp, sk_off)) { + return NULL; + } + return tmp; + } +} + +static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc) +{ + SEC_DESC *tmp = NULL; + + tmp = malloc_p(SEC_DESC); + + tmp->revision = SVAL(&sec_desc->revision,0); + tmp->type = SVAL(&sec_desc->type,0); + DEBUG(2, ("SEC_DESC Rev: %0X, Type: %0X\n", tmp->revision, tmp->type)); + DEBUGADD(2, ("SEC_DESC Owner Off: %0X\n", IVAL(&sec_desc->off_owner_sid,0))); + DEBUGADD(2, ("SEC_DESC Group Off: %0X\n", IVAL(&sec_desc->off_grp_sid,0))); + DEBUGADD(2, ("SEC_DESC DACL Off: %0X\n", IVAL(&sec_desc->off_dacl,0))); + tmp->owner_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_owner_sid,0))); + if (!tmp->owner_sid) { + free(tmp); + return NULL; + } + tmp->grp_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_grp_sid,0))); + if (!tmp->grp_sid) { + free(tmp); + return NULL; + } + + /* Now pick up the SACL and DACL */ + + DEBUG(0, ("%d, %d\n", IVAL(&sec_desc->off_sacl,0), IVAL(&sec_desc->off_dacl,0))); + + if (sec_desc->off_sacl) + tmp->sacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_sacl,0))); + else + tmp->sacl = NULL; + + if (sec_desc->off_dacl) + tmp->dacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_dacl,0))); + else + tmp->dacl = NULL; + + return tmp; +} + +static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_off, int size) +{ + KEY_SEC_DESC *tmp = NULL; + int sk_next_off, sk_prev_off, sk_size; + SEC_DESC *sec_desc; + + if (!sk_hdr) return NULL; + + if (SVAL(&sk_hdr->SK_ID,0) != str_to_dword("sk")) { + DEBUG(0, ("Unrecognized SK Header ID: %08X, %s\n", (int)sk_hdr, + regf->regfile_name)); + return NULL; + } + + if (-size < (sk_size = IVAL(&sk_hdr->rec_size,0))) { + DEBUG(0, ("Incorrect SK record size: %d vs %d. %s\n", + -size, sk_size, regf->regfile_name)); + return NULL; + } + + /* + * Now, we need to look up the SK Record in the map, and return it + * Since the map contains the SK_OFF mapped to KEY_SEC_DESC, we can + * use that + */ + + if (regf->sk_map && + ((tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off)) != NULL) + && (tmp->state == SEC_DESC_OCU)) { + tmp->ref_cnt++; + return tmp; + } + + /* Here, we have an item in the map that has been reserved, or tmp==NULL. */ + + SMB_REG_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); + + /* + * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the + * new KEY_SEC_DESC to the mapping structure, since the offset supplied is + * the actual offset of structure. The same offset will be used by + * all future references to this structure + * We could put all this unpleasantness in a function. + */ + + if (!tmp) { + tmp = malloc_p(KEY_SEC_DESC); + memset(tmp, 0, sizeof(KEY_SEC_DESC)); + + /* + * Allocate an entry in the SK_MAP ... + * We don't need to free tmp, because that is done for us if the + * sm_map entry can't be expanded when we need more space in the map. + */ + + if (!alloc_sk_map_entry(regf, tmp, sk_off)) { + return NULL; + } + } + + tmp->ref_cnt++; + tmp->state = SEC_DESC_OCU; + + /* + * Now, process the actual sec desc and plug the values in + */ + + sec_desc = (SEC_DESC *)&sk_hdr->sec_desc[0]; + tmp->sec_desc = process_sec_desc(regf, sec_desc); + + /* + * Now forward and back links. Here we allocate an entry in the sk_map + * if it does not exist, and mark it reserved + */ + + sk_prev_off = IVAL(&sk_hdr->prev_off,0); + tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off); + SMB_REG_ASSERT(tmp->prev != NULL); + sk_next_off = IVAL(&sk_hdr->next_off,0); + tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off); + SMB_REG_ASSERT(tmp->next != NULL); + + return tmp; +} +#endif + +/* + * Process a VK header and return a value + */ +static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR *vk_hdr, int size, struct registry_value **value) +{ + REGF *regf = parent->hive->backend_data; + int nam_len, dat_len, flag, dat_type, dat_off, vk_id; + struct registry_value *tmp = NULL; + + if (!vk_hdr) return WERR_INVALID_PARAM; + + if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { + DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", + vk_id, (int)vk_hdr, parent->hive->location)); + return WERR_GENERAL_FAILURE; + } + + nam_len = SVAL(&vk_hdr->nam_len,0); + flag = SVAL(&vk_hdr->flag,0); + dat_type = IVAL(&vk_hdr->dat_type,0); + dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ + dat_off = IVAL(&vk_hdr->dat_off,0); + + tmp = talloc_p(mem_ctx, struct registry_value); + tmp->data_type = dat_type; + + if (flag & FLAG_HAS_NAME) { + tmp->name = talloc_strndup(mem_ctx, vk_hdr->dat_name, nam_len); + } else { + tmp->name = NULL; + } + + /* + * Allocate space and copy the data as a BLOB + */ + + if (dat_len&0x7FFFFFFF) { + + char *dtmp = (char *)talloc(mem_ctx, dat_len&0x7FFFFFFF); + + if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ + char *dat_ptr = LOCN(regf->base, dat_off); + memcpy(dtmp, dat_ptr, dat_len); + } + else { /* The data is in the offset or type */ + /* + * FIXME. + * Some registry files seem to have weird fields. If top bit is set, + * but len is 0, the type seems to be the value ... + * Not sure how to handle this last type for the moment ... + */ + dat_len = dat_len & 0x7FFFFFFF; + memcpy(dtmp, &dat_off, dat_len); + } + + + if(tmp->data_type == REG_SZ) { + char *ret; + dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (void **)&ret); + dtmp = ret; + } + + + tmp->data_blk = dtmp; + tmp->data_len = dat_len; + } + + *value = tmp; + return WERR_OK; +} + +#if 0 /* unused */ + +static BOOL vl_verify(VL_TYPE vl, int count, int size) +{ + if(!vl) return False; + if (-size < (count+1)*sizeof(int)){ + DEBUG(0, ("Error in VL header format. Size less than space required. %d\n", -size)); + return False; + } + return True; +} + +#endif + +static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) +{ + int lf_id; + if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { + DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n", + lf_id, (int)lf_hdr, h->location)); + return WERR_INVALID_PARAM; + } + return WERR_OK; +} + +static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, int *count) +{ + WERROR error; + + error = lf_verify(h, lf_hdr, size); + if(!W_ERROR_IS_OK(error)) return error; + + SMB_REG_ASSERT(size < 0); + + *count = SVAL(&lf_hdr->key_count,0); + DEBUG(2, ("Key Count: %u\n", *count)); + if (*count <= 0) return WERR_INVALID_PARAM; + + return WERR_OK; +} + + +static WERROR nk_to_key(TALLOC_CTX *, struct registry_hive *regf, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **); + + + +/* + * Process an LF Header and return a list of sub-keys + */ +static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_HDR *lf_hdr, int size, int n, struct registry_key **key) +{ + REGF *regf = parent->hive->backend_data; + int count, nk_off; + NK_HDR *nk_hdr; + WERROR error; + + if (!lf_hdr) return WERR_INVALID_PARAM; + + error = lf_verify(parent->hive, lf_hdr, size); + if(!W_ERROR_IS_OK(error)) return error; + + SMB_REG_ASSERT(size < 0); + + count = SVAL(&lf_hdr->key_count,0); + DEBUG(2, ("Key Count: %u\n", count)); + if (count <= 0) return WERR_GENERAL_FAILURE; + if (n >= count) return WERR_NO_MORE_ITEMS; + + nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); + DEBUG(2, ("NK Offset: %0X\n", nk_off)); + nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); + return nk_to_key(mem_ctx, parent->hive, nk_hdr, BLK_SIZE(nk_hdr), parent, key); +} + +static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **key) +{ + REGF *regf = h->backend_data; + struct registry_key *tmp = NULL, *own; + int namlen, clsname_len, sk_off, own_off; + uint_t nk_id; + SK_HDR *sk_hdr; + int type; + char key_name[1024]; + + if (!nk_hdr) return WERR_INVALID_PARAM; + + if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { + DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", + nk_id, (int)nk_hdr, parent->hive->location)); + return WERR_INVALID_PARAM; + } + + SMB_REG_ASSERT(size < 0); + + namlen = SVAL(&nk_hdr->nam_len,0); + clsname_len = SVAL(&nk_hdr->clsnam_len,0); + + /* + * The value of -size should be ge + * (sizeof(NK_HDR) - 1 + namlen) + * The -1 accounts for the fact that we included the first byte of + * the name in the structure. clsname_len is the length of the thing + * pointed to by clsnam_off + */ + + if (-size < (sizeof(NK_HDR) - 1 + namlen)) { + DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); + DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", + sizeof(NK_HDR), namlen, clsname_len)); + return WERR_GENERAL_FAILURE; + } + + DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", namlen, clsname_len)); + + /* Fish out the key name and process the LF list */ + + SMB_REG_ASSERT(namlen < sizeof(key_name)); + + strncpy(key_name, nk_hdr->key_nam, namlen); + key_name[namlen] = '\0'; + + type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); + if(type == REG_ROOT_KEY && parent) { + DEBUG(0,("Root key encountered below root level!\n")); + return WERR_GENERAL_FAILURE; + } + + tmp = talloc_p(mem_ctx, struct registry_key); + tmp->name = talloc_strdup(mem_ctx, key_name); + tmp->backend_data = nk_hdr; + + DEBUG(2, ("Key name: %s\n", key_name)); + + /* + * Fish out the class name, it is in UNICODE, while the key name is + * ASCII :-) + */ + + if (clsname_len) { /* Just print in Ascii for now */ + void *clsnamep; + int clsnam_off; + + clsnam_off = IVAL(&nk_hdr->clsnam_off,0); + clsnamep = LOCN(regf->base, clsnam_off); + DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); + + pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); + + DEBUGADD(2,(" Class Name: %s\n", tmp->class_name)); + + } + + /* + * Process the owner offset ... + */ + + own_off = IVAL(&nk_hdr->own_off,0); + own = (struct registry_key *)LOCN(regf->base, own_off); + DEBUG(2, ("Owner Offset: %0X\n", own_off)); + + DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", + (uint_t)own, (uint_t)nk_hdr)); + + /* + * We should verify that the owner field is correct ... + * for now, we don't worry ... + */ + + /* + * Also handle the SK header ... + */ + + sk_off = IVAL(&nk_hdr->sk_off,0); + sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); + DEBUG(2, ("SK Offset: %0X\n", sk_off)); + + if (sk_off != -1) { + +#if 0 + tmp->security = process_sk(regf, sk_hdr, sk_off, BLK_SIZE(sk_hdr)); +#endif + + } + + *key = tmp; + return WERR_OK; +} + +#if 0 /* unused */ + +/* + * Allocate a new hbin block, set up the header for the block etc + */ +static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) +{ + REGF *regf = h->backend_data; + HBIN_BLK *tmp; + HBIN_HDR *hdr; + + if (!regf || !size) return NULL; + + /* Round size up to multiple of REGF_HDR_BLKSIZ */ + + size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); + + tmp = malloc_p(HBIN_BLK); + memset(tmp, 0, sizeof(HBIN_BLK)); + + tmp->data = malloc(size); + + memset(tmp->data, 0, size); /* Make it pristine */ + + tmp->size = size; + /*FIXMEtmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size;*/ + + tmp->free_space = size - (sizeof(HBIN_HDR) - sizeof(HBIN_SUB_HDR)); + tmp->fsp_off = size - tmp->free_space; + + /* + * Now, build the header in the data block + */ + hdr = (HBIN_HDR *)tmp->data; + hdr->HBIN_ID = str_to_dword("hbin"); + hdr->off_from_first = tmp->file_offset - REGF_HDR_BLKSIZ; + hdr->off_to_next = tmp->size; + hdr->blk_size = tmp->size; + + /* + * Now link it in + */ + + regf->blk_tail->next = tmp; + regf->blk_tail = tmp; + if (!regf->free_space) regf->free_space = tmp; + + return tmp; +} + +/* + * Allocate a unit of space ... and return a pointer as function param + * and the block's offset as a side effect + */ +static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) +{ + REGF *regf = h->backend_data; + int tmp = 0; + void *ret = NULL; + HBIN_BLK *blk; + + if (!regf || !size || !off) return NULL; + + SMB_REG_ASSERT(regf->blk_head != NULL); + + /* + * round up size to include header and then to 8-byte boundary + */ + size = (size + 4 + 7) & ~7; + + /* + * Check if there is space, if none, grab a block + */ + if (!regf->free_space) { + if (!nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) + return NULL; + } + + /* + * Now, chain down the list of blocks looking for free space + */ + + for (blk = regf->free_space; blk != NULL; blk = blk->next) { + if (blk->free_space <= size) { + tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; + ret = blk->data + blk->fsp_off; + blk->free_space -= size; + blk->fsp_off += size; + + /* Insert the header */ + ((HBIN_SUB_HDR *)ret)->dblocksize = -size; + + /* + * Fix up the free space ptr + * If it is NULL, we fix it up next time + */ + + if (!blk->free_space) + regf->free_space = blk->next; + + *off = tmp; + return (((char *)ret)+4);/* The pointer needs to be to the data struct */ + } + } + + /* + * If we got here, we need to add another block, which might be + * larger than one block -- deal with that later + */ + if (nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) { + blk = regf->free_space; + tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; + ret = blk->data + blk->fsp_off; + blk->free_space -= size; + blk->fsp_off += size; + + /* Insert the header */ + ((HBIN_SUB_HDR *)ret)->dblocksize = -size; + + /* + * Fix up the free space ptr + * If it is NULL, we fix it up next time + */ + + if (!blk->free_space) + regf->free_space = blk->next; + + *off = tmp; + return (((char *)ret) + 4);/* The pointer needs to be to the data struct */ + } + + return NULL; +} + +/* + * Store a SID at the location provided + */ +static int nt_store_SID(struct registry_hive *regf, DOM_SID *sid, uint8_t *locn) +{ + int i; + uint8_t *p = locn; + + if (!regf || !sid || !locn) return 0; + + *p = sid->sid_rev_num; p++; + *p = sid->num_auths; p++; + + for (i=0; i < 6; i++) { + *p = sid->id_auth[i]; p++; + } + + for (i=0; i < sid->num_auths; i++) { + SIVAL(p, 0, sid->sub_auths[i]); p+=4; + } + + return p - locn; + +} + +static int nt_store_ace(struct registry_hive *regf, SEC_ACE *ace, uint8_t *locn) +{ + int size = 0; + SEC_ACE *reg_ace = (SEC_ACE *)locn; + uint8_t *p; + + if (!regf || !ace || !locn) return 0; + + reg_ace->type = ace->type; + reg_ace->flags = ace->flags; + + /* Deal with the length when we have stored the SID */ + + p = (uint8_t *)®_ace->info.mask; + + SIVAL(p, 0, ace->info.mask); p += 4; + + size = nt_store_SID(regf, &ace->trustee, p); + + size += 8; /* Size of the fixed header */ + + p = (uint8_t *)®_ace->size; + + SSVAL(p, 0, size); + + return size; +} + +/* + * Store an ACL at the location provided + */ +static int nt_store_acl(struct registry_hive *regf, SEC_ACL *acl, uint8_t *locn) { + int size = 0, i; + uint8_t *p = locn, *s; + + if (!regf || !acl || !locn) return 0; + + /* + * Now store the header and then the ACEs ... + */ + + SSVAL(p, 0, acl->revision); + + p += 2; s = p; /* Save this for the size field */ + + p += 2; + + SIVAL(p, 0, acl->num_aces); + + p += 4; + + for (i = 0; i < acl->num_aces; i++) { + size = nt_store_ace(regf, &acl->ace[i], p); + p += size; + } + + size = s - locn; + SSVAL(s, 0, size); + return size; +} + +/* + * Flatten and store the Sec Desc + * Windows lays out the DACL first, but since there is no SACL, it might be + * that first, then the owner, then the group SID. So, we do it that way + * too. + */ +static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char *locn) +{ + SEC_DESC *rsd = (SEC_DESC *)locn; + uint_t size = 0, off = 0; + + if (!regf || !sd || !locn) return 0; + + /* + * Now, fill in the first two fields, then lay out the various fields + * as needed + */ + + rsd->revision = SEC_DESC_REVISION; + rsd->type = SEC_DESC_DACL_PRESENT | SEC_DESC_SELF_RELATIVE; + + off = 4 * sizeof(DWORD) + 4; + + if (sd->sacl){ + size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); + rsd->off_sacl = off; + } + else + rsd->off_sacl = 0; + + off += size; + + if (sd->dacl) { + rsd->off_dacl = off; + size = nt_store_acl(regf, sd->dacl, (char *)(locn + off)); + } + else { + rsd->off_dacl = 0; + } + + off += size; + + /* Now the owner and group SIDs */ + + if (sd->owner_sid) { + rsd->off_owner_sid = off; + size = nt_store_SID(regf, sd->owner_sid, (char *)(locn + off)); + } + else { + rsd->off_owner_sid = 0; + } + + off += size; + + if (sd->grp_sid) { + rsd->off_grp_sid = off; + size = nt_store_SID(regf, sd->grp_sid, (char *)(locn + off)); + } + else { + rsd->off_grp_sid = 0; + } + + off += size; + + return size; +} + +/* + * Store the security information + * + * If it has already been stored, just get its offset from record + * otherwise, store it and record its offset + */ +static uint_t nt_store_security(struct registry_hive *regf, KEY_SEC_DESC *sec) +{ + int size = 0; + uint_t sk_off; + SK_HDR *sk_hdr; + + if (sec->offset) return sec->offset; + + /* + * OK, we don't have this one in the file yet. We must compute the + * size taken by the security descriptor as a self-relative SD, which + * means making one pass over each structure and figuring it out + */ + +/* FIXME size = sec_desc_size(sec->sec_desc); */ + + /* Allocate that much space */ + + sk_hdr = nt_alloc_regf_space(regf, size, &sk_off); + sec->sk_hdr = sk_hdr; + + if (!sk_hdr) return 0; + + /* Now, lay out the sec_desc in the space provided */ + + sk_hdr->SK_ID = str_to_dword("sk"); + + /* + * We can't deal with the next and prev offset in the SK_HDRs until the + * whole tree has been stored, then we can go and deal with them + */ + + sk_hdr->ref_cnt = sec->ref_cnt; + sk_hdr->rec_size = size; /* Is this correct */ + + /* Now, lay out the sec_desc */ + + if (!nt_store_sec_desc(regf, sec->sec_desc, (char *)&sk_hdr->sec_desc)) + return 0; + + return sk_off; + +} + +/* + * Store a KEY in the file ... + * + * We store this depth first, and defer storing the lf struct until + * all the sub-keys have been stored. + * + * We store the NK hdr, any SK header, class name, and VK structure, then + * recurse down the LF structures ... + * + * We return the offset of the NK struct + * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... + */ +static int nt_store_reg_key(struct registry_hive *regf, struct registry_key *key) +{ + NK_HDR *nk_hdr; + uint_t nk_off, sk_off, size; + + if (!regf || !key) return 0; + + size = sizeof(NK_HDR) + strlen(key->name) - 1; + nk_hdr = nt_alloc_regf_space(regf, size, &nk_off); + if (!nk_hdr) goto error; + + key->offset = nk_off; /* We will need this later */ + + /* + * Now fill in each field etc ... + */ + + nk_hdr->NK_ID = str_to_dword("nk"); + if (key->type == REG_ROOT_KEY) + nk_hdr->type = 0x2C; + else + nk_hdr->type = 0x20; + + /* FIXME: Fill in the time of last update */ + + if (key->type != REG_ROOT_KEY) + nk_hdr->own_off = key->owner->offset; + + if (key->sub_keys) + nk_hdr->subk_num = key->sub_keys->key_count; + + /* + * Now, process the Sec Desc and then store its offset + */ + + sk_off = nt_store_security(regf, key->security); + nk_hdr->sk_off = sk_off; + + /* + * Then, store the val list and store its offset + */ + if (key->values) { + nk_hdr->val_cnt = key->values->val_count; + nk_hdr->val_off = nt_store_val_list(regf, key->values); + } + else { + nk_hdr->val_off = -1; + nk_hdr->val_cnt = 0; + } + + /* + * Finally, store the subkeys, and their offsets + */ + +error: + return 0; +} + +/* + * Store the registry header ... + * We actually create the registry header block and link it to the chain + * of output blocks. + */ +static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { + REGF *regf = h->backend_data; + HBIN_BLK *tmp = NULL; + + tmp = malloc_p(HBIN_BLK); + + memset(tmp, 0, sizeof(HBIN_BLK)); + tmp->type = REG_OUTBLK_HDR; + tmp->size = REGF_HDR_BLKSIZ; + tmp->data = malloc(REGF_HDR_BLKSIZ); + if (!tmp->data) goto error; + + memset(tmp->data, 0, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ + regf->blk_head = regf->blk_tail = tmp; + + return (REGF_HDR *)tmp->data; + +error: + if (tmp) free(tmp); + return NULL; +} + +#endif + +static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) +{ + REGF *regf; + REGF_HDR *regf_hdr; + uint_t regf_id, hbin_id; + HBIN_HDR *hbin_hdr; + + regf = (REGF *)talloc_p(h, REGF); + memset(regf, 0, sizeof(REGF)); + regf->owner_sid_str = NULL; /* FIXME: Fill in */ + h->backend_data = regf; + + DEBUG(5, ("Attempting to load registry file\n")); + + /* Get the header */ + + if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) { + DEBUG(0, ("Unable to get header\n")); + return WERR_GENERAL_FAILURE; + } + + /* Now process that header and start to read the rest in */ + + if ((regf_id = IVAL(®f_hdr->REGF_ID,0)) != str_to_dword("regf")) { + DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n", + regf_id, h->location)); + return WERR_GENERAL_FAILURE; + } + + /* + * Validate the header ... + */ + if (!valid_regf_hdr(regf_hdr)) { + DEBUG(0, ("Registry file header does not validate: %s\n", + h->location)); + return WERR_GENERAL_FAILURE; + } + + /* Update the last mod date, and then go get the first NK record and on */ + + TTTONTTIME(regf, IVAL(®f_hdr->tim1,0), IVAL(®f_hdr->tim2,0)); + + /* + * The hbin hdr seems to be just uninteresting garbage. Check that + * it is there, but that is all. + */ + + hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ); + + if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) { + DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", + hbin_id, h->location)); + return WERR_GENERAL_FAILURE; + } + + /* + * Get a pointer to the first key from the hreg_hdr + */ + + DEBUG(2, ("First Key: %0X\n", + IVAL(®f_hdr->first_key, 0))); + + regf->first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key,0)); + DEBUGADD(2, ("First Key Offset: %0X\n", + IVAL(®f_hdr->first_key, 0))); + + DEBUGADD(2, ("Data Block Size: %d\n", + IVAL(®f_hdr->dblk_size, 0))); + + DEBUGADD(2, ("Offset to next hbin block: %0X\n", + IVAL(&hbin_hdr->off_to_next, 0))); + + DEBUGADD(2, ("HBIN block size: %0X\n", + IVAL(&hbin_hdr->blk_size, 0))); + + /* + * Unmap the registry file, as we might want to read in another + * tree etc. + */ + + h->backend_data = regf; + + return nk_to_key(h, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); +} + + +static WERROR nt_num_subkeys(struct registry_key *k, int *num) +{ + REGF *regf = k->hive->backend_data; + LF_HDR *lf_hdr; + int lf_off; + NK_HDR *nk_hdr = k->backend_data; + lf_off = IVAL(&nk_hdr->lf_off,0); + DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); + if(lf_off == -1) { + *num = 0; + return WERR_OK; + } + lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); + + return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); +} + +static WERROR nt_num_values(struct registry_key *k, int *count) +{ + NK_HDR *nk_hdr = k->backend_data; + *count = IVAL(&nk_hdr->val_cnt,0); + return WERR_OK; +} + +static WERROR nt_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_value **value) +{ + VL_TYPE *vl; + int val_off, vk_off; + int val_count; + VK_HDR *vk_hdr; + REGF *regf = k->hive->backend_data; + NK_HDR *nk_hdr = k->backend_data; + val_count = IVAL(&nk_hdr->val_cnt,0); + val_off = IVAL(&nk_hdr->val_off,0); + vl = (VL_TYPE *)LOCN(regf->base, val_off); + DEBUG(2, ("Val List Offset: %0X\n", val_off)); + if(n < 0) return WERR_INVALID_PARAM; + if(n >= val_count) return WERR_NO_MORE_ITEMS; + + vk_off = IVAL(&vl[n],0); + vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); + return vk_to_val(mem_ctx, k, vk_hdr, BLK_SIZE(vk_hdr), value); +} + +static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_key **subkey) +{ + REGF *regf = k->hive->backend_data; + int lf_off; + NK_HDR *nk_hdr = k->backend_data; + LF_HDR *lf_hdr; + lf_off = IVAL(&nk_hdr->lf_off,0); + DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); + + /* + * No more subkeys if lf_off == -1 + */ + + if (lf_off != -1) { + lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); + return lf_get_entry(mem_ctx, k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); + } + + return WERR_NO_MORE_ITEMS; +} + +static struct hive_operations reg_backend_nt4 = { + .name = "nt4", + .open_hive = nt_open_hive, + .num_subkeys = nt_num_subkeys, + .num_values = nt_num_values, + .get_subkey_by_index = nt_key_by_index, + .get_value_by_index = nt_value_by_index, + + /* TODO: + .add_key + .add_value + .del_key + .del_value + .update_value + */ +}; + +NTSTATUS registry_nt4_init(void) +{ + return registry_register(®_backend_nt4); +} diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c deleted file mode 100644 index 381f0c3bcf..0000000000 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ /dev/null @@ -1,1747 +0,0 @@ -/* - Samba Unix/Linux SMB client utility libeditreg.c - Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com - Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/************************************************************************* - - A utility to edit a Windows NT/2K etc registry file. - - Many of the ideas in here come from other people and software. - I first looked in Wine in misc/registry.c and was also influenced by - http://www.wednesday.demon.co.uk/dosreg.html - - Which seems to contain comments from someone else. I reproduce them here - incase the site above disappears. It actually comes from - http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. - - The goal here is to read the registry into memory, manipulate it, and then - write it out if it was changed by any actions of the user. - -The windows NT registry has 2 different blocks, where one can occur many -times... - -the "regf"-Block -================ - -"regf" is obviously the abbreviation for "Registry file". "regf" is the -signature of the header-block which is always 4kb in size, although only -the first 64 bytes seem to be used and a checksum is calculated over -the first 0x200 bytes only! - -Offset Size Contents -0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 -0x00000004 D-Word ???? //see struct REG_HANDLE -0x00000008 D-Word ???? Always the same value as at 0x00000004 -0x0000000C Q-Word last modify date in WinNT date-format -0x00000014 D-Word 1 -0x00000018 D-Word 3 -0x0000001C D-Word 0 -0x00000020 D-Word 1 -0x00000024 D-Word Offset of 1st key record -0x00000028 D-Word Size of the data-blocks (Filesize-4kb) -0x0000002C D-Word 1 -0x000001FC D-Word Sum of all D-Words from 0x00000000 to -0x000001FB //XOR of all words. Nigel - -I have analyzed more registry files (from multiple machines running -NT 4.0 german version) and could not find an explanation for the values -marked with ???? the rest of the first 4kb page is not important... - -the "hbin"-Block -================ -I don't know what "hbin" stands for, but this block is always a multiple -of 4kb in size. - -Inside these hbin-blocks the different records are placed. The memory- -management looks like a C-compiler heap management to me... - -hbin-Header -=========== -Offset Size Contents -0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 -0x0004 D-Word Offset from the 1st hbin-Block -0x0008 D-Word Offset to the next hbin-Block -0x001C D-Word Block-size - -The values in 0x0008 and 0x001C should be the same, so I don't know -if they are correct or swapped... - -From offset 0x0020 inside a hbin-block data is stored with the following -format: - -Offset Size Contents -0x0000 D-Word Data-block size //this size must be a -multiple of 8. Nigel -0x0004 ???? Data - -If the size field is negative (bit 31 set), the corresponding block -is free and has a size of -blocksize! - -That does not seem to be true. All block lengths seem to be negative! -(Richard Sharpe) - -The data is stored as one record per block. Block size is a multiple -of 4 and the last block reaches the next hbin-block, leaving no room. - -(That also seems incorrect, in that the block size if a multiple of 8. -That is, the block, including the 4 byte header, is always a multiple of -8 bytes. Richard Sharpe.) - -Records in the hbin-blocks -========================== - -nk-Record - - The nk-record can be treated as a combination of tree-record and - key-record of the win 95 registry. - -lf-Record - - The lf-record is the counterpart to the RGKN-record (the - hash-function) - -vk-Record - - The vk-record consists information to a single value (value key). - -sk-Record - - sk (? Security Key ?) is the ACL of the registry. - -Value-Lists - - The value-lists contain information about which values are inside a - sub-key and don't have a header. - -Datas - - The datas of the registry are (like the value-list) stored without a - header. - -All offset-values are relative to the first hbin-block and point to the -block-size field of the record-entry. to get the file offset, you have to add -the header size (4kb) and the size field (4 bytes)... - -the nk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"nk" = 0x6B6E -0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel -0x0004 Q-Word write-date/time in windows nt notation -0x0010 D-Word Offset of Owner/Parent key -0x0014 D-Word number of sub-Keys -0x001C D-Word Offset of the sub-key lf-Records -0x0024 D-Word number of values -0x0028 D-Word Offset of the Value-List -0x002C D-Word Offset of the sk-Record - -0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel -0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel -0x0048 Word name-length -0x004A Word class-name length -0x004C ???? key-name - -the Value-List -============== -Offset Size Contents -0x0000 D-Word Offset 1st Value -0x0004 D-Word Offset 2nd Value -0x???? D-Word Offset nth Value - -To determine the number of values, you have to look at the owner-nk-record! - -The vk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"vk" = 0x6B76 -0x0002 Word name length -0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel -0x0008 D-Word Offset of Data -0x000C D-Word Type of value -0x0010 Word Flag -0x0012 Word Unused (data-trash) -0x0014 ???? Name - -If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) - -If the data-size is lower 5, the data-offset value is used to store the data itself! - -The data-types -============== -Wert Beteutung -0x0001 RegSZ: character string (in UNICODE!) -0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) -0x0003 RegBin: raw-binary value -0x0004 RegDWord: Dword -0x0007 RegMultiSZ: multiple strings, seperated with 0 - (UNICODE!) - -The "lf"-record -=============== -Offset Size Contents -0x0000 Word ID: ASCII-"lf" = 0x666C -0x0002 Word number of keys -0x0004 ???? Hash-Records - -Hash-Record -=========== -Offset Size Contents -0x0000 D-Word Offset of corresponding "nk"-Record -0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! - -Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the -key-name you have to change the hash-value too! - -//These hashrecords must be sorted low to high within the lf record. Nigel. - -The "sk"-block -============== -(due to the complexity of the SAM-info, not clear jet) -(This is just a self-relative security descriptor in the data. R Sharpe.) - - -Offset Size Contents -0x0000 Word ID: ASCII-"sk" = 0x6B73 -0x0002 Word Unused -0x0004 D-Word Offset of previous "sk"-Record -0x0008 D-Word Offset of next "sk"-Record -0x000C D-Word usage-counter -0x0010 D-Word Size of "sk"-record in bytes -???? //standard self -relative security desciptor. Nigel -???? ???? Security and auditing settings... -???? - -The usage counter counts the number of references to this -"sk"-record. You can use one "sk"-record for the entire registry! - -Windows nt date/time format -=========================== -The time-format is a 64-bit integer which is incremented every -0,0000001 seconds by 1 (I don't know how accurate it realy is!) -It starts with 0 at the 1st of january 1601 0:00! All values are -stored in GMT time! The time-zone is important to get the real -time! - -Common values for win95 and win-nt -================================== -Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). -If a value has no name (length=0, flag(bit 0)=0), it is treated as the -"Default" entry... -If a value has no data (length=0), it is displayed as empty. - -simplyfied win-3.?? registry: -============================= - -+-----------+ -| next rec. |---+ +----->+------------+ -| first sub | | | | Usage cnt. | -| name | | +-->+------------+ | | length | -| value | | | | next rec. | | | text |------->+-------+ -+-----------+ | | | name rec. |--+ +------------+ | xxxxx | - +------------+ | | value rec. |-------->+------------+ +-------+ - v | +------------+ | Usage cnt. | -+-----------+ | | length | -| next rec. | | | text |------->+-------+ -| first sub |------+ +------------+ | xxxxx | -| name | +-------+ -| value | -+-----------+ - -Greatly simplyfied structure of the nt-registry: -================================================ - -+---------------------------------------------------------------+ -| | -v | -+---------+ +---------->+-----------+ +----->+---------+ | -| "nk" | | | lf-rec. | | | nk-rec. | | -| ID | | | # of keys | | | parent |---+ -| Date | | | 1st key |--+ | .... | -| parent | | +-----------+ +---------+ -| suk-keys|-----+ -| values |--------------------->+----------+ -| SK-rec. |---------------+ | 1. value |--> +----------+ -| class |--+ | +----------+ | vk-rec. | -+---------+ | | | .... | - v | | data |--> +-------+ - +------------+ | +----------+ | xxxxx | - | Class name | | +-------+ - +------------+ | - v - +---------+ +---------+ - +----->| next sk |--->| Next sk |--+ - | +---| prev sk |<---| prev sk | | - | | | .... | | ... | | - | | +---------+ +---------+ | - | | ^ | - | | | | - | +--------------------+ | - +----------------------------------+ - ---------------------------------------------------------------------------- - -Hope this helps.... (Although it was "fun" for me to uncover this things, - it took me several sleepless nights ;) - - B.D. - -*************************************************************************/ - -#include "includes.h" -#include "registry.h" -#include "system/shmem.h" - -#define REG_KEY_LIST_SIZE 10 -#define FLAG_HAS_NAME 0x01 -/*FIXME*/ - -/* - * Structures for dealing with the on-disk format of the registry - */ - -const char *def_owner_sid_str = NULL; - -/* - * These definitions are for the in-memory registry structure. - * It is a tree structure that mimics what you see with tools like regedit - */ - - -/* - * Definition of a Key. It has a name, classname, date/time last modified, - * sub-keys, values, and a security descriptor - */ - -#define REG_ROOT_KEY 1 -#define REG_SUB_KEY 2 -#define REG_SYM_LINK 3 - -/* - * All of the structures below actually have a four-byte length before them - * which always seems to be negative. The following macro retrieves that - * size as an integer - */ - -#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) - -typedef uint_t DWORD; -typedef unsigned short WORD; - -typedef struct sk_struct SK_HDR; -/* - * This structure keeps track of the output format of the registry - */ -#define REG_OUTBLK_HDR 1 -#define REG_OUTBLK_HBIN 2 - -typedef struct regf_block { - DWORD REGF_ID; /* regf */ - DWORD uk1; - DWORD uk2; - DWORD tim1, tim2; - DWORD uk3; /* 1 */ - DWORD uk4; /* 3 */ - DWORD uk5; /* 0 */ - DWORD uk6; /* 1 */ - DWORD first_key; /* offset */ - uint_t dblk_size; - DWORD uk7[116]; /* 1 */ - DWORD chksum; -} REGF_HDR; - -typedef struct hbin_sub_struct { - DWORD dblocksize; - char data[1]; -} HBIN_SUB_HDR; - -typedef struct hbin_struct { - DWORD HBIN_ID; /* hbin */ - DWORD off_from_first; - DWORD off_to_next; - DWORD uk1; - DWORD uk2; - DWORD uk3; - DWORD uk4; - DWORD blk_size; - HBIN_SUB_HDR hbin_sub_hdr; -} HBIN_HDR; - -typedef struct nk_struct { - WORD NK_ID; - WORD type; - DWORD t1, t2; - DWORD uk1; - DWORD own_off; - DWORD subk_num; - DWORD uk2; - DWORD lf_off; - DWORD uk3; - DWORD val_cnt; - DWORD val_off; - DWORD sk_off; - DWORD clsnam_off; - DWORD unk4[4]; - DWORD unk5; - WORD nam_len; - WORD clsnam_len; - char key_nam[1]; /* Actual length determined by nam_len */ -} NK_HDR; - -struct sk_struct { - WORD SK_ID; - WORD uk1; - DWORD prev_off; - DWORD next_off; - DWORD ref_cnt; - DWORD rec_size; - char sec_desc[1]; -}; - -typedef struct key_sec_desc_s { - struct key_sec_desc_s *prev, *next; - int ref_cnt; - int state; - int offset; - SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ - SEC_DESC *sec_desc; -} KEY_SEC_DESC; - -/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ -typedef struct sk_map_s { - int sk_off; - KEY_SEC_DESC *key_sec_desc; -} SK_MAP; - -typedef struct vk_struct { - WORD VK_ID; - WORD nam_len; - DWORD dat_len; /* If top-bit set, offset contains the data */ - DWORD dat_off; - DWORD dat_type; - WORD flag; /* =1, has name, else no name (=Default). */ - WORD unk1; - char dat_name[1]; /* Name starts here ... */ -} VK_HDR; - -typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */ - -typedef struct hash_struct { - DWORD nk_off; - char hash[4]; -} HASH_REC; - - -typedef struct lf_struct { - WORD LF_ID; - WORD key_count; - struct hash_struct hr[1]; /* Array of hash records, depending on key_count */} LF_HDR; - - - -/* - * This structure keeps track of the output format of the registry - */ -#define REG_OUTBLK_HDR 1 -#define REG_OUTBLK_HBIN 2 - -typedef struct hbin_blk_s { - int type, size; - struct hbin_blk_s *next; - char *data; /* The data block */ - uint_t file_offset; /* Offset in file */ - uint_t free_space; /* Amount of free space in block */ - uint_t fsp_off; /* Start of free space in block */ - int complete, stored; -} HBIN_BLK; - -typedef struct regf_struct_s { - int reg_type; - int fd; - struct stat sbuf; - char *base; - BOOL modified; - NTTIME last_mod_time; - NK_HDR *first_key; - int sk_count, sk_map_size; - SK_MAP *sk_map; - const char *owner_sid_str; - SEC_DESC *def_sec_desc; - /* - * These next pointers point to the blocks used to contain the - * keys when we are preparing to write them to a file - */ - HBIN_BLK *blk_head, *blk_tail, *free_space; -} REGF; - -static DWORD str_to_dword(const char *a) { - int i; - unsigned long ret = 0; - for(i = strlen(a)-1; i >= 0; i--) { - ret = ret * 0x100 + a[i]; - } - return ret; -} - -#if 0 - -/* - * Create an ACE - */ -static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, const char *sid) -{ - DOM_SID s; - SEC_ACCESS access; - access.mask = perms; - if(!string_to_sid(&s, sid))return False; - init_sec_ace(ace, &s, type, access, flags); - return True; -} - -/* - * Create a default ACL - */ -static SEC_ACL *nt_create_default_acl(struct registry_hive *regf) -{ - SEC_ACE aces[8]; - - if(!nt_create_ace(&aces[0], 0x00, 0x0, 0xF003F, regf->owner_sid_str)) return NULL; - if(!nt_create_ace(&aces[1], 0x00, 0x0, 0xF003F, "S-1-5-18")) return NULL; - if(!nt_create_ace(&aces[2], 0x00, 0x0, 0xF003F, "S-1-5-32-544")) return NULL; - if(!nt_create_ace(&aces[3], 0x00, 0x0, 0x20019, "S-1-5-12")) return NULL; - if(!nt_create_ace(&aces[4], 0x00, 0x0B, GENERIC_RIGHT_ALL_ACCESS, regf->owner_sid_str)) return NULL; - if(!nt_create_ace(&aces[5], 0x00, 0x0B, 0x10000000, "S-1-5-18")) return NULL; - if(!nt_create_ace(&aces[6], 0x00, 0x0B, 0x10000000, "S-1-5-32-544")) return NULL; - if(!nt_create_ace(&aces[7], 0x00, 0x0B, 0x80000000, "S-1-5-12")) return NULL; - - return make_sec_acl(regf->mem_ctx, 2, 8, aces); -} - -/* - * Create a default security descriptor. We pull in things from env - * if need be - */ -static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) -{ - SEC_DESC *tmp; - - tmp = malloc_p(SEC_DESC); - - tmp->revision = 1; - tmp->type = SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT; - if (!string_to_sid(tmp->owner_sid, "S-1-5-32-544")) goto error; - if (!string_to_sid(tmp->grp_sid, "S-1-5-18")) goto error; - tmp->sacl = NULL; - tmp->dacl = nt_create_default_acl(regf); - - return tmp; - - error: - if (tmp) nt_delete_sec_desc(tmp); - return NULL; -} - -/* - * We will implement inheritence that is based on what the parent's SEC_DESC - * says, but the Owner and Group SIDs can be overwridden from the command line - * and additional ACEs can be applied from the command line etc. - */ -static KEY_SEC_DESC *nt_inherit_security(struct registry_key *key) -{ - - if (!key) return NULL; - return key->security; -} - -/* - * Create an initial security descriptor and init other structures, if needed - * We assume that the initial security stuff is empty ... - */ -static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) -{ - REGF *regf = h->backend_data; - KEY_SEC_DESC *tsec = NULL; - - tsec = malloc_p(KEY_SEC_DESC); - - tsec->ref_cnt = 1; - tsec->state = SEC_DESC_NBK; - tsec->offset = 0; - - tsec->sec_desc = regf->def_sec_desc; - - return tsec; -} -#endif - -/* - * Get the starting record for NT Registry file - */ - -/* - * Where we keep all the regf stuff for one registry. - * This is the structure that we use to tie the in memory tree etc - * together. By keeping separate structs, we can operate on different - * registries at the same time. - * Currently, the SK_MAP is an array of mapping structure. - * Since we only need this on input and output, we fill in the structure - * as we go on input. On output, we know how many SK items we have, so - * we can allocate the structure as we need to. - * If you add stuff here that is dynamically allocated, add the - * appropriate free statements below. - */ - -#define REG_HANDLE_REGTYPE_NONE 0 -#define REG_HANDLE_REGTYPE_NT 1 -#define REG_HANDLE_REGTYPE_W9X 2 - -#define TTTONTTIME(r, t1, t2) (r)->last_mod_time = (t1) | (((uint64_t)(t2)) << 32) - -#define REGF_HDR_BLKSIZ 0x1000 - -#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) -#define LOCN(base, f) ((base) + OFF(f)) - -/* Get the header of the registry. Return a pointer to the structure - * If the mmap'd area has not been allocated, then mmap the input file - */ -static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) -{ - REGF *regf = h->backend_data; - SMB_REG_ASSERT(regf); - - if (!regf->base) { /* Try to mmap etc the file */ - - if ((regf->fd = open(h->location, O_RDONLY, 0000)) <0) { - return NULL; /* What about errors? */ - } - - if (fstat(regf->fd, ®f->sbuf) < 0) { - return NULL; - } - - regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0); - - if ((int)regf->base == 1) { - DEBUG(0,("Could not mmap file: %s, %s\n", h->location, - strerror(errno))); - return NULL; - } - } - - /* - * At this point, regf->base != NULL, and we should be able to read the - * header - */ - - SMB_REG_ASSERT(regf->base != NULL); - - return (REGF_HDR *)regf->base; -} - -/* - * Validate a regf header - * For now, do nothing, but we should check the checksum - */ -static int valid_regf_hdr(REGF_HDR *regf_hdr) -{ - if (!regf_hdr) return 0; - - return 1; -} - -#if 0 - -/* - * Process an SK header ... - * Every time we see a new one, add it to the map. Otherwise, just look it up. - * We will do a simple linear search for the moment, since many KEYs have the - * same security descriptor. - * We allocate the map in increments of 10 entries. - */ - -/* - * Create a new entry in the map, and increase the size of the map if needed - */ -static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, int sk_off) -{ - REGF *regf = h->backend_data; - if (!regf->sk_map) { /* Allocate a block of 10 */ - regf->sk_map = malloc_array_p(SK_MAP, 10); - regf->sk_map_size = 10; - regf->sk_count = 1; - (regf->sk_map)[0].sk_off = sk_off; - (regf->sk_map)[0].key_sec_desc = tmp; - } - else { /* Simply allocate a new slot, unless we have to expand the list */ - int ndx = regf->sk_count; - if (regf->sk_count >= regf->sk_map_size) { - regf->sk_map = (SK_MAP *)realloc(regf->sk_map, - (regf->sk_map_size + 10)*sizeof(SK_MAP)); - if (!regf->sk_map) { - free(tmp); - return NULL; - } - /* - * ndx already points at the first entry of the new block - */ - regf->sk_map_size += 10; - } - (regf->sk_map)[ndx].sk_off = sk_off; - (regf->sk_map)[ndx].key_sec_desc = tmp; - regf->sk_count++; - } - return regf->sk_map; -} - -/* - * Search for a KEY_SEC_DESC in the sk_map, but don't create one if not - * found - */ -KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) -{ - int i; - - if (!sk_map) return NULL; - - for (i = 0; i < count; i++) { - - if (sk_map[i].sk_off == sk_off) - return sk_map[i].key_sec_desc; - - } - - return NULL; - -} - -/* - * Allocate a KEY_SEC_DESC if we can't find one in the map - */ -static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_map, int sk_off) -{ - REGF *regf = h->backend_data; - KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); - - if (tmp) { - return tmp; - } - else { /* Allocate a new one */ - tmp = malloc_p(KEY_SEC_DESC); - memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ - tmp->state = SEC_DESC_RES; - if (!alloc_sk_map_entry(h, tmp, sk_off)) { - return NULL; - } - return tmp; - } -} - -static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc) -{ - SEC_DESC *tmp = NULL; - - tmp = malloc_p(SEC_DESC); - - tmp->revision = SVAL(&sec_desc->revision,0); - tmp->type = SVAL(&sec_desc->type,0); - DEBUG(2, ("SEC_DESC Rev: %0X, Type: %0X\n", tmp->revision, tmp->type)); - DEBUGADD(2, ("SEC_DESC Owner Off: %0X\n", IVAL(&sec_desc->off_owner_sid,0))); - DEBUGADD(2, ("SEC_DESC Group Off: %0X\n", IVAL(&sec_desc->off_grp_sid,0))); - DEBUGADD(2, ("SEC_DESC DACL Off: %0X\n", IVAL(&sec_desc->off_dacl,0))); - tmp->owner_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_owner_sid,0))); - if (!tmp->owner_sid) { - free(tmp); - return NULL; - } - tmp->grp_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_grp_sid,0))); - if (!tmp->grp_sid) { - free(tmp); - return NULL; - } - - /* Now pick up the SACL and DACL */ - - DEBUG(0, ("%d, %d\n", IVAL(&sec_desc->off_sacl,0), IVAL(&sec_desc->off_dacl,0))); - - if (sec_desc->off_sacl) - tmp->sacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_sacl,0))); - else - tmp->sacl = NULL; - - if (sec_desc->off_dacl) - tmp->dacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_dacl,0))); - else - tmp->dacl = NULL; - - return tmp; -} - -static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_off, int size) -{ - KEY_SEC_DESC *tmp = NULL; - int sk_next_off, sk_prev_off, sk_size; - SEC_DESC *sec_desc; - - if (!sk_hdr) return NULL; - - if (SVAL(&sk_hdr->SK_ID,0) != str_to_dword("sk")) { - DEBUG(0, ("Unrecognized SK Header ID: %08X, %s\n", (int)sk_hdr, - regf->regfile_name)); - return NULL; - } - - if (-size < (sk_size = IVAL(&sk_hdr->rec_size,0))) { - DEBUG(0, ("Incorrect SK record size: %d vs %d. %s\n", - -size, sk_size, regf->regfile_name)); - return NULL; - } - - /* - * Now, we need to look up the SK Record in the map, and return it - * Since the map contains the SK_OFF mapped to KEY_SEC_DESC, we can - * use that - */ - - if (regf->sk_map && - ((tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off)) != NULL) - && (tmp->state == SEC_DESC_OCU)) { - tmp->ref_cnt++; - return tmp; - } - - /* Here, we have an item in the map that has been reserved, or tmp==NULL. */ - - SMB_REG_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); - - /* - * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the - * new KEY_SEC_DESC to the mapping structure, since the offset supplied is - * the actual offset of structure. The same offset will be used by - * all future references to this structure - * We could put all this unpleasantness in a function. - */ - - if (!tmp) { - tmp = malloc_p(KEY_SEC_DESC); - memset(tmp, 0, sizeof(KEY_SEC_DESC)); - - /* - * Allocate an entry in the SK_MAP ... - * We don't need to free tmp, because that is done for us if the - * sm_map entry can't be expanded when we need more space in the map. - */ - - if (!alloc_sk_map_entry(regf, tmp, sk_off)) { - return NULL; - } - } - - tmp->ref_cnt++; - tmp->state = SEC_DESC_OCU; - - /* - * Now, process the actual sec desc and plug the values in - */ - - sec_desc = (SEC_DESC *)&sk_hdr->sec_desc[0]; - tmp->sec_desc = process_sec_desc(regf, sec_desc); - - /* - * Now forward and back links. Here we allocate an entry in the sk_map - * if it does not exist, and mark it reserved - */ - - sk_prev_off = IVAL(&sk_hdr->prev_off,0); - tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off); - SMB_REG_ASSERT(tmp->prev != NULL); - sk_next_off = IVAL(&sk_hdr->next_off,0); - tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off); - SMB_REG_ASSERT(tmp->next != NULL); - - return tmp; -} -#endif - -/* - * Process a VK header and return a value - */ -static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR *vk_hdr, int size, struct registry_value **value) -{ - REGF *regf = parent->hive->backend_data; - int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - struct registry_value *tmp = NULL; - - if (!vk_hdr) return WERR_INVALID_PARAM; - - if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { - DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", - vk_id, (int)vk_hdr, parent->hive->location)); - return WERR_GENERAL_FAILURE; - } - - nam_len = SVAL(&vk_hdr->nam_len,0); - flag = SVAL(&vk_hdr->flag,0); - dat_type = IVAL(&vk_hdr->dat_type,0); - dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ - dat_off = IVAL(&vk_hdr->dat_off,0); - - tmp = talloc_p(mem_ctx, struct registry_value); - tmp->data_type = dat_type; - - if (flag & FLAG_HAS_NAME) { - tmp->name = talloc_strndup(mem_ctx, vk_hdr->dat_name, nam_len); - } else { - tmp->name = NULL; - } - - /* - * Allocate space and copy the data as a BLOB - */ - - if (dat_len&0x7FFFFFFF) { - - char *dtmp = (char *)talloc(mem_ctx, dat_len&0x7FFFFFFF); - - if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ - char *dat_ptr = LOCN(regf->base, dat_off); - memcpy(dtmp, dat_ptr, dat_len); - } - else { /* The data is in the offset or type */ - /* - * FIXME. - * Some registry files seem to have weird fields. If top bit is set, - * but len is 0, the type seems to be the value ... - * Not sure how to handle this last type for the moment ... - */ - dat_len = dat_len & 0x7FFFFFFF; - memcpy(dtmp, &dat_off, dat_len); - } - - - if(tmp->data_type == REG_SZ) { - char *ret; - dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (void **)&ret); - dtmp = ret; - } - - - tmp->data_blk = dtmp; - tmp->data_len = dat_len; - } - - *value = tmp; - return WERR_OK; -} - -#if 0 /* unused */ - -static BOOL vl_verify(VL_TYPE vl, int count, int size) -{ - if(!vl) return False; - if (-size < (count+1)*sizeof(int)){ - DEBUG(0, ("Error in VL header format. Size less than space required. %d\n", -size)); - return False; - } - return True; -} - -#endif - -static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) -{ - int lf_id; - if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { - DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n", - lf_id, (int)lf_hdr, h->location)); - return WERR_INVALID_PARAM; - } - return WERR_OK; -} - -static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, int *count) -{ - WERROR error; - - error = lf_verify(h, lf_hdr, size); - if(!W_ERROR_IS_OK(error)) return error; - - SMB_REG_ASSERT(size < 0); - - *count = SVAL(&lf_hdr->key_count,0); - DEBUG(2, ("Key Count: %u\n", *count)); - if (*count <= 0) return WERR_INVALID_PARAM; - - return WERR_OK; -} - - -static WERROR nk_to_key(TALLOC_CTX *, struct registry_hive *regf, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **); - - - -/* - * Process an LF Header and return a list of sub-keys - */ -static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_HDR *lf_hdr, int size, int n, struct registry_key **key) -{ - REGF *regf = parent->hive->backend_data; - int count, nk_off; - NK_HDR *nk_hdr; - WERROR error; - - if (!lf_hdr) return WERR_INVALID_PARAM; - - error = lf_verify(parent->hive, lf_hdr, size); - if(!W_ERROR_IS_OK(error)) return error; - - SMB_REG_ASSERT(size < 0); - - count = SVAL(&lf_hdr->key_count,0); - DEBUG(2, ("Key Count: %u\n", count)); - if (count <= 0) return WERR_GENERAL_FAILURE; - if (n >= count) return WERR_NO_MORE_ITEMS; - - nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); - DEBUG(2, ("NK Offset: %0X\n", nk_off)); - nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - return nk_to_key(mem_ctx, parent->hive, nk_hdr, BLK_SIZE(nk_hdr), parent, key); -} - -static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **key) -{ - REGF *regf = h->backend_data; - struct registry_key *tmp = NULL, *own; - int namlen, clsname_len, sk_off, own_off; - uint_t nk_id; - SK_HDR *sk_hdr; - int type; - char key_name[1024]; - - if (!nk_hdr) return WERR_INVALID_PARAM; - - if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { - DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", - nk_id, (int)nk_hdr, parent->hive->location)); - return WERR_INVALID_PARAM; - } - - SMB_REG_ASSERT(size < 0); - - namlen = SVAL(&nk_hdr->nam_len,0); - clsname_len = SVAL(&nk_hdr->clsnam_len,0); - - /* - * The value of -size should be ge - * (sizeof(NK_HDR) - 1 + namlen) - * The -1 accounts for the fact that we included the first byte of - * the name in the structure. clsname_len is the length of the thing - * pointed to by clsnam_off - */ - - if (-size < (sizeof(NK_HDR) - 1 + namlen)) { - DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); - DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", - sizeof(NK_HDR), namlen, clsname_len)); - return WERR_GENERAL_FAILURE; - } - - DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", namlen, clsname_len)); - - /* Fish out the key name and process the LF list */ - - SMB_REG_ASSERT(namlen < sizeof(key_name)); - - strncpy(key_name, nk_hdr->key_nam, namlen); - key_name[namlen] = '\0'; - - type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); - if(type == REG_ROOT_KEY && parent) { - DEBUG(0,("Root key encountered below root level!\n")); - return WERR_GENERAL_FAILURE; - } - - tmp = talloc_p(mem_ctx, struct registry_key); - tmp->name = talloc_strdup(mem_ctx, key_name); - tmp->backend_data = nk_hdr; - - DEBUG(2, ("Key name: %s\n", key_name)); - - /* - * Fish out the class name, it is in UNICODE, while the key name is - * ASCII :-) - */ - - if (clsname_len) { /* Just print in Ascii for now */ - void *clsnamep; - int clsnam_off; - - clsnam_off = IVAL(&nk_hdr->clsnam_off,0); - clsnamep = LOCN(regf->base, clsnam_off); - DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - - pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); - - DEBUGADD(2,(" Class Name: %s\n", tmp->class_name)); - - } - - /* - * Process the owner offset ... - */ - - own_off = IVAL(&nk_hdr->own_off,0); - own = (struct registry_key *)LOCN(regf->base, own_off); - DEBUG(2, ("Owner Offset: %0X\n", own_off)); - - DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", - (uint_t)own, (uint_t)nk_hdr)); - - /* - * We should verify that the owner field is correct ... - * for now, we don't worry ... - */ - - /* - * Also handle the SK header ... - */ - - sk_off = IVAL(&nk_hdr->sk_off,0); - sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); - DEBUG(2, ("SK Offset: %0X\n", sk_off)); - - if (sk_off != -1) { - -#if 0 - tmp->security = process_sk(regf, sk_hdr, sk_off, BLK_SIZE(sk_hdr)); -#endif - - } - - *key = tmp; - return WERR_OK; -} - -#if 0 /* unused */ - -/* - * Allocate a new hbin block, set up the header for the block etc - */ -static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) -{ - REGF *regf = h->backend_data; - HBIN_BLK *tmp; - HBIN_HDR *hdr; - - if (!regf || !size) return NULL; - - /* Round size up to multiple of REGF_HDR_BLKSIZ */ - - size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); - - tmp = malloc_p(HBIN_BLK); - memset(tmp, 0, sizeof(HBIN_BLK)); - - tmp->data = malloc(size); - - memset(tmp->data, 0, size); /* Make it pristine */ - - tmp->size = size; - /*FIXMEtmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size;*/ - - tmp->free_space = size - (sizeof(HBIN_HDR) - sizeof(HBIN_SUB_HDR)); - tmp->fsp_off = size - tmp->free_space; - - /* - * Now, build the header in the data block - */ - hdr = (HBIN_HDR *)tmp->data; - hdr->HBIN_ID = str_to_dword("hbin"); - hdr->off_from_first = tmp->file_offset - REGF_HDR_BLKSIZ; - hdr->off_to_next = tmp->size; - hdr->blk_size = tmp->size; - - /* - * Now link it in - */ - - regf->blk_tail->next = tmp; - regf->blk_tail = tmp; - if (!regf->free_space) regf->free_space = tmp; - - return tmp; -} - -/* - * Allocate a unit of space ... and return a pointer as function param - * and the block's offset as a side effect - */ -static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) -{ - REGF *regf = h->backend_data; - int tmp = 0; - void *ret = NULL; - HBIN_BLK *blk; - - if (!regf || !size || !off) return NULL; - - SMB_REG_ASSERT(regf->blk_head != NULL); - - /* - * round up size to include header and then to 8-byte boundary - */ - size = (size + 4 + 7) & ~7; - - /* - * Check if there is space, if none, grab a block - */ - if (!regf->free_space) { - if (!nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) - return NULL; - } - - /* - * Now, chain down the list of blocks looking for free space - */ - - for (blk = regf->free_space; blk != NULL; blk = blk->next) { - if (blk->free_space <= size) { - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret)+4);/* The pointer needs to be to the data struct */ - } - } - - /* - * If we got here, we need to add another block, which might be - * larger than one block -- deal with that later - */ - if (nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) { - blk = regf->free_space; - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret) + 4);/* The pointer needs to be to the data struct */ - } - - return NULL; -} - -/* - * Store a SID at the location provided - */ -static int nt_store_SID(struct registry_hive *regf, DOM_SID *sid, uint8_t *locn) -{ - int i; - uint8_t *p = locn; - - if (!regf || !sid || !locn) return 0; - - *p = sid->sid_rev_num; p++; - *p = sid->num_auths; p++; - - for (i=0; i < 6; i++) { - *p = sid->id_auth[i]; p++; - } - - for (i=0; i < sid->num_auths; i++) { - SIVAL(p, 0, sid->sub_auths[i]); p+=4; - } - - return p - locn; - -} - -static int nt_store_ace(struct registry_hive *regf, SEC_ACE *ace, uint8_t *locn) -{ - int size = 0; - SEC_ACE *reg_ace = (SEC_ACE *)locn; - uint8_t *p; - - if (!regf || !ace || !locn) return 0; - - reg_ace->type = ace->type; - reg_ace->flags = ace->flags; - - /* Deal with the length when we have stored the SID */ - - p = (uint8_t *)®_ace->info.mask; - - SIVAL(p, 0, ace->info.mask); p += 4; - - size = nt_store_SID(regf, &ace->trustee, p); - - size += 8; /* Size of the fixed header */ - - p = (uint8_t *)®_ace->size; - - SSVAL(p, 0, size); - - return size; -} - -/* - * Store an ACL at the location provided - */ -static int nt_store_acl(struct registry_hive *regf, SEC_ACL *acl, uint8_t *locn) { - int size = 0, i; - uint8_t *p = locn, *s; - - if (!regf || !acl || !locn) return 0; - - /* - * Now store the header and then the ACEs ... - */ - - SSVAL(p, 0, acl->revision); - - p += 2; s = p; /* Save this for the size field */ - - p += 2; - - SIVAL(p, 0, acl->num_aces); - - p += 4; - - for (i = 0; i < acl->num_aces; i++) { - size = nt_store_ace(regf, &acl->ace[i], p); - p += size; - } - - size = s - locn; - SSVAL(s, 0, size); - return size; -} - -/* - * Flatten and store the Sec Desc - * Windows lays out the DACL first, but since there is no SACL, it might be - * that first, then the owner, then the group SID. So, we do it that way - * too. - */ -static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char *locn) -{ - SEC_DESC *rsd = (SEC_DESC *)locn; - uint_t size = 0, off = 0; - - if (!regf || !sd || !locn) return 0; - - /* - * Now, fill in the first two fields, then lay out the various fields - * as needed - */ - - rsd->revision = SEC_DESC_REVISION; - rsd->type = SEC_DESC_DACL_PRESENT | SEC_DESC_SELF_RELATIVE; - - off = 4 * sizeof(DWORD) + 4; - - if (sd->sacl){ - size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); - rsd->off_sacl = off; - } - else - rsd->off_sacl = 0; - - off += size; - - if (sd->dacl) { - rsd->off_dacl = off; - size = nt_store_acl(regf, sd->dacl, (char *)(locn + off)); - } - else { - rsd->off_dacl = 0; - } - - off += size; - - /* Now the owner and group SIDs */ - - if (sd->owner_sid) { - rsd->off_owner_sid = off; - size = nt_store_SID(regf, sd->owner_sid, (char *)(locn + off)); - } - else { - rsd->off_owner_sid = 0; - } - - off += size; - - if (sd->grp_sid) { - rsd->off_grp_sid = off; - size = nt_store_SID(regf, sd->grp_sid, (char *)(locn + off)); - } - else { - rsd->off_grp_sid = 0; - } - - off += size; - - return size; -} - -/* - * Store the security information - * - * If it has already been stored, just get its offset from record - * otherwise, store it and record its offset - */ -static uint_t nt_store_security(struct registry_hive *regf, KEY_SEC_DESC *sec) -{ - int size = 0; - uint_t sk_off; - SK_HDR *sk_hdr; - - if (sec->offset) return sec->offset; - - /* - * OK, we don't have this one in the file yet. We must compute the - * size taken by the security descriptor as a self-relative SD, which - * means making one pass over each structure and figuring it out - */ - -/* FIXME size = sec_desc_size(sec->sec_desc); */ - - /* Allocate that much space */ - - sk_hdr = nt_alloc_regf_space(regf, size, &sk_off); - sec->sk_hdr = sk_hdr; - - if (!sk_hdr) return 0; - - /* Now, lay out the sec_desc in the space provided */ - - sk_hdr->SK_ID = str_to_dword("sk"); - - /* - * We can't deal with the next and prev offset in the SK_HDRs until the - * whole tree has been stored, then we can go and deal with them - */ - - sk_hdr->ref_cnt = sec->ref_cnt; - sk_hdr->rec_size = size; /* Is this correct */ - - /* Now, lay out the sec_desc */ - - if (!nt_store_sec_desc(regf, sec->sec_desc, (char *)&sk_hdr->sec_desc)) - return 0; - - return sk_off; - -} - -/* - * Store a KEY in the file ... - * - * We store this depth first, and defer storing the lf struct until - * all the sub-keys have been stored. - * - * We store the NK hdr, any SK header, class name, and VK structure, then - * recurse down the LF structures ... - * - * We return the offset of the NK struct - * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... - */ -static int nt_store_reg_key(struct registry_hive *regf, struct registry_key *key) -{ - NK_HDR *nk_hdr; - uint_t nk_off, sk_off, size; - - if (!regf || !key) return 0; - - size = sizeof(NK_HDR) + strlen(key->name) - 1; - nk_hdr = nt_alloc_regf_space(regf, size, &nk_off); - if (!nk_hdr) goto error; - - key->offset = nk_off; /* We will need this later */ - - /* - * Now fill in each field etc ... - */ - - nk_hdr->NK_ID = str_to_dword("nk"); - if (key->type == REG_ROOT_KEY) - nk_hdr->type = 0x2C; - else - nk_hdr->type = 0x20; - - /* FIXME: Fill in the time of last update */ - - if (key->type != REG_ROOT_KEY) - nk_hdr->own_off = key->owner->offset; - - if (key->sub_keys) - nk_hdr->subk_num = key->sub_keys->key_count; - - /* - * Now, process the Sec Desc and then store its offset - */ - - sk_off = nt_store_security(regf, key->security); - nk_hdr->sk_off = sk_off; - - /* - * Then, store the val list and store its offset - */ - if (key->values) { - nk_hdr->val_cnt = key->values->val_count; - nk_hdr->val_off = nt_store_val_list(regf, key->values); - } - else { - nk_hdr->val_off = -1; - nk_hdr->val_cnt = 0; - } - - /* - * Finally, store the subkeys, and their offsets - */ - -error: - return 0; -} - -/* - * Store the registry header ... - * We actually create the registry header block and link it to the chain - * of output blocks. - */ -static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { - REGF *regf = h->backend_data; - HBIN_BLK *tmp = NULL; - - tmp = malloc_p(HBIN_BLK); - - memset(tmp, 0, sizeof(HBIN_BLK)); - tmp->type = REG_OUTBLK_HDR; - tmp->size = REGF_HDR_BLKSIZ; - tmp->data = malloc(REGF_HDR_BLKSIZ); - if (!tmp->data) goto error; - - memset(tmp->data, 0, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ - regf->blk_head = regf->blk_tail = tmp; - - return (REGF_HDR *)tmp->data; - -error: - if (tmp) free(tmp); - return NULL; -} - -#endif - -static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) -{ - REGF *regf; - REGF_HDR *regf_hdr; - uint_t regf_id, hbin_id; - HBIN_HDR *hbin_hdr; - - regf = (REGF *)talloc_p(mem_ctx, REGF); - memset(regf, 0, sizeof(REGF)); - regf->owner_sid_str = h->credentials; - h->backend_data = regf; - - DEBUG(5, ("Attempting to load registry file\n")); - - /* Get the header */ - - if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) { - DEBUG(0, ("Unable to get header\n")); - return WERR_GENERAL_FAILURE; - } - - /* Now process that header and start to read the rest in */ - - if ((regf_id = IVAL(®f_hdr->REGF_ID,0)) != str_to_dword("regf")) { - DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n", - regf_id, h->location)); - return WERR_GENERAL_FAILURE; - } - - /* - * Validate the header ... - */ - if (!valid_regf_hdr(regf_hdr)) { - DEBUG(0, ("Registry file header does not validate: %s\n", - h->location)); - return WERR_GENERAL_FAILURE; - } - - /* Update the last mod date, and then go get the first NK record and on */ - - TTTONTTIME(regf, IVAL(®f_hdr->tim1,0), IVAL(®f_hdr->tim2,0)); - - /* - * The hbin hdr seems to be just uninteresting garbage. Check that - * it is there, but that is all. - */ - - hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ); - - if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) { - DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", - hbin_id, h->location)); - return WERR_GENERAL_FAILURE; - } - - /* - * Get a pointer to the first key from the hreg_hdr - */ - - DEBUG(2, ("First Key: %0X\n", - IVAL(®f_hdr->first_key, 0))); - - regf->first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key,0)); - DEBUGADD(2, ("First Key Offset: %0X\n", - IVAL(®f_hdr->first_key, 0))); - - DEBUGADD(2, ("Data Block Size: %d\n", - IVAL(®f_hdr->dblk_size, 0))); - - DEBUGADD(2, ("Offset to next hbin block: %0X\n", - IVAL(&hbin_hdr->off_to_next, 0))); - - DEBUGADD(2, ("HBIN block size: %0X\n", - IVAL(&hbin_hdr->blk_size, 0))); - - /* - * Unmap the registry file, as we might want to read in another - * tree etc. - */ - - h->backend_data = regf; - - return nk_to_key(mem_ctx, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); -} - - -static WERROR nt_num_subkeys(struct registry_key *k, int *num) -{ - REGF *regf = k->hive->backend_data; - LF_HDR *lf_hdr; - int lf_off; - NK_HDR *nk_hdr = k->backend_data; - lf_off = IVAL(&nk_hdr->lf_off,0); - DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); - if(lf_off == -1) { - *num = 0; - return WERR_OK; - } - lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - - return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); -} - -static WERROR nt_num_values(struct registry_key *k, int *count) -{ - NK_HDR *nk_hdr = k->backend_data; - *count = IVAL(&nk_hdr->val_cnt,0); - return WERR_OK; -} - -static WERROR nt_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_value **value) -{ - VL_TYPE *vl; - int val_off, vk_off; - int val_count; - VK_HDR *vk_hdr; - REGF *regf = k->hive->backend_data; - NK_HDR *nk_hdr = k->backend_data; - val_count = IVAL(&nk_hdr->val_cnt,0); - val_off = IVAL(&nk_hdr->val_off,0); - vl = (VL_TYPE *)LOCN(regf->base, val_off); - DEBUG(2, ("Val List Offset: %0X\n", val_off)); - if(n < 0) return WERR_INVALID_PARAM; - if(n >= val_count) return WERR_NO_MORE_ITEMS; - - vk_off = IVAL(&vl[n],0); - vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - return vk_to_val(mem_ctx, k, vk_hdr, BLK_SIZE(vk_hdr), value); -} - -static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_key **subkey) -{ - REGF *regf = k->hive->backend_data; - int lf_off; - NK_HDR *nk_hdr = k->backend_data; - LF_HDR *lf_hdr; - lf_off = IVAL(&nk_hdr->lf_off,0); - DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); - - /* - * No more subkeys if lf_off == -1 - */ - - if (lf_off != -1) { - lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_get_entry(mem_ctx, k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); - } - - return WERR_NO_MORE_ITEMS; -} - -static struct registry_operations reg_backend_nt4 = { - .name = "nt4", - .open_hive = nt_open_hive, - .num_subkeys = nt_num_subkeys, - .num_values = nt_num_values, - .get_subkey_by_index = nt_key_by_index, - .get_value_by_index = nt_value_by_index, - - /* TODO: - .add_key - .add_value - .del_key - .del_value - .update_value - */ -}; - -NTSTATUS registry_nt4_init(void) -{ - return registry_register(®_backend_nt4); -} diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c new file mode 100644 index 0000000000..18563b2478 --- /dev/null +++ b/source4/lib/registry/reg_backend_rpc.c @@ -0,0 +1,398 @@ +/* + Samba Unix/Linux SMB implementation + RPC backend for the registry library + Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "registry.h" +#include "librpc/gen_ndr/ndr_winreg.h" + +static struct hive_operations reg_backend_rpc; + +/** + * This is the RPC backend for the registry library. + */ + +static void init_winreg_String(struct winreg_String *name, const char *s) +{ + name->name = s; + if (s) { + name->name_len = 2 * (strlen_m(s) + 1); + name->name_size = name->name_len; + } else { + name->name_len = 0; + name->name_size = 0; + } +} + + +#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ +{ \ + struct winreg_Open ## u r; \ + struct winreg_OpenUnknown unknown; \ + NTSTATUS status; \ + \ + unknown.unknown0 = 0x84e0; \ + unknown.unknown1 = 0x0000; \ + r.in.unknown = &unknown; \ + r.in.access_required = SEC_FLAG_MAXIMUM_ALLOWED; \ + r.out.handle = hnd;\ + \ + status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ + if (NT_STATUS_IS_ERR(status)) {\ + DEBUG(0,("Error executing open\n"));\ + return ntstatus_to_werror(status);\ + }\ +\ + return r.out.result;\ +} + +openhive(HKLM) +openhive(HKCU) +openhive(HKPD) +openhive(HKU) +openhive(HKCR) +openhive(HKDD) +openhive(HKCC) + +struct rpc_key_data { + struct policy_handle pol; + int num_subkeys; + int num_values; + int max_valnamelen; + int max_valdatalen; +}; + +struct { + uint32 hkey; + WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); +} known_hives[] = { +{ HKEY_LOCAL_MACHINE, open_HKLM }, +{ HKEY_CURRENT_USER, open_HKCU }, +{ HKEY_CLASSES_ROOT, open_HKCR }, +{ HKEY_PERFORMANCE_DATA, open_HKPD }, +{ HKEY_USERS, open_HKU }, +{ HKEY_DYN_DATA, open_HKDD }, +{ HKEY_CURRENT_CONFIG, open_HKCC }, +{ 0, NULL } +}; + +static WERROR rpc_query_key(struct registry_key *k); + +static WERROR rpc_get_hive (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k) +{ + int n; + struct registry_hive *h; + struct rpc_key_data *mykeydata; + + for(n = 0; known_hives[n].hkey; n++) + { + if(known_hives[n].hkey == hkey_type) break; + } + + if(!known_hives[n].open) { + DEBUG(1, ("No such hive %d\n", hkey_type)); + return WERR_NO_MORE_ITEMS; + } + + h = talloc_p(ctx, struct registry_hive); + h->functions = ®_backend_rpc; + h->location = NULL; + h->backend_data = ctx->backend_data; + h->reg_ctx = ctx; + + (*k) = h->root = talloc_p(h, struct registry_key); + (*k)->hive = h; + (*k)->backend_data = mykeydata = talloc_p(*k, struct rpc_key_data); + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; + return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol)); +} + +static int rpc_close (void *_h) +{ + struct registry_context *h = _h; + dcerpc_pipe_close(h->backend_data); + return 0; +} + +#if 0 +static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) +{ + struct winreg_OpenKey r; + struct rpc_key_data *mykeydata; + + k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; + + /* Then, open the handle using the hive */ + + memset(&r, 0, sizeof(struct winreg_OpenKey)); + r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); + init_winreg_String(&r.in.keyname, k->path); + r.in.unknown = 0x00000000; + r.in.access_mask = 0x02000000; + r.out.handle = &mykeydata->pol; + + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); + + return r.out.result; +} +#endif + +static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) +{ + struct rpc_key_data *mykeydata; + struct winreg_OpenKey r; + + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->name = talloc_strdup(mem_ctx, name); + + (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); + mykeydata->num_values = -1; + mykeydata->num_subkeys = -1; + + /* Then, open the handle using the hive */ + + memset(&r, 0, sizeof(struct winreg_OpenKey)); + r.in.handle = &(((struct rpc_key_data *)h->backend_data)->pol); + init_winreg_String(&r.in.keyname, name); + r.in.unknown = 0x00000000; + r.in.access_mask = 0x02000000; + r.out.handle = &mykeydata->pol; + + dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r); + + return r.out.result; +} + +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +{ + return rpc_open_rel_key(mem_ctx, h->root, name, key); +} + +static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) +{ + struct rpc_key_data *mykeydata = parent->backend_data; + WERROR error; + struct winreg_EnumValue r; + uint32 type, len1, zero = 0; + NTSTATUS status; + uint8_t buf8; + uint16_t buf16; + + if(mykeydata->num_values == -1) { + error = rpc_query_key(parent); + if(!W_ERROR_IS_OK(error)) return error; + } + + len1 = mykeydata->max_valdatalen; + + r.in.handle = &mykeydata->pol; + r.in.enum_index = n; + r.in.name_in.length = 0; + r.in.name_in.size = mykeydata->max_valnamelen * 2; + r.in.name_in.name = &buf16; + r.in.type = &type; + r.in.value = &buf8; + r.in.length = &zero; + r.in.size = &len1; + r.out.type = &type; + + + status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); + return WERR_GENERAL_FAILURE; + } + + if(NT_STATUS_IS_OK(status) && + W_ERROR_IS_OK(r.out.result) && r.out.length) { + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->parent = parent; + (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); + (*value)->data_type = type; + (*value)->data_len = *r.out.length; + (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value, *r.out.length); + return WERR_OK; + } + + return r.out.result; +} + +static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) +{ + struct winreg_EnumKey r; + struct winreg_EnumKeyNameRequest keyname; + struct winreg_String classname; + struct winreg_Time tm; + struct rpc_key_data *mykeydata = parent->backend_data; + NTSTATUS status; + + r.in.handle = &mykeydata->pol; + keyname.unknown = 0x0000020a; + init_winreg_String(&keyname.key_name, NULL); + init_winreg_String(&classname, NULL); + r.in.in_name = &keyname; + r.in.class = &classname; + tm.low = tm.high = 0x7fffffff; + r.in.last_changed_time = &tm; + + r.in.enum_index = n; + r.in.unknown = r.out.unknown = 0x0414; + r.in.key_name_len = r.out.key_name_len = 0; + status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); + if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { + return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); + } + + return r.out.result; +} + +static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) +{ + return WERR_NOT_SUPPORTED; +} + +static WERROR rpc_query_key(struct registry_key *k) +{ + NTSTATUS status; + struct winreg_QueryInfoKey r; + struct rpc_key_data *mykeydata = k->backend_data; + TALLOC_CTX *mem_ctx = talloc_init("query_key"); + + init_winreg_String(&r.in.class, NULL); + r.in.handle = &mykeydata->pol; + + status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r); + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + if (W_ERROR_IS_OK(r.out.result)) { + mykeydata->num_subkeys = r.out.num_subkeys; + mykeydata->num_values = r.out.num_values; + mykeydata->max_valnamelen = r.out.max_valnamelen; + mykeydata->max_valdatalen = r.out.max_valbufsize; + } + + return r.out.result; +} + +static WERROR rpc_del_key(struct registry_key *k) +{ + NTSTATUS status; + struct rpc_key_data *mykeydata = k->backend_data; + struct winreg_DeleteKey r; + struct registry_key *parent; + WERROR error; + TALLOC_CTX *mem_ctx = talloc_init("del_key"); + + error = reg_key_get_parent(mem_ctx, k, &parent); + if(!W_ERROR_IS_OK(error)) { + talloc_destroy(mem_ctx); + return error; + } + + mykeydata = parent->backend_data; + + r.in.handle = &mykeydata->pol; + init_winreg_String(&r.in.key, k->name); + + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); + + talloc_destroy(mem_ctx); + + return r.out.result; +} + +static WERROR rpc_num_values(struct registry_key *key, int *count) { + struct rpc_key_data *mykeydata = key->backend_data; + WERROR error; + + if(mykeydata->num_values == -1) { + error = rpc_query_key(key); + if(!W_ERROR_IS_OK(error)) return error; + } + + *count = mykeydata->num_values; + return WERR_OK; +} + +static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { + struct rpc_key_data *mykeydata = key->backend_data; + WERROR error; + + if(mykeydata->num_subkeys == -1) { + error = rpc_query_key(key); + if(!W_ERROR_IS_OK(error)) return error; + } + + *count = mykeydata->num_subkeys; + return WERR_OK; +} + +static struct hive_operations reg_backend_rpc = { + .name = "rpc", + .open_key = rpc_open_key, + .get_subkey_by_index = rpc_get_subkey_by_index, + .get_value_by_index = rpc_get_value_by_index, + .add_key = rpc_add_key, + .del_key = rpc_del_key, + .num_subkeys = rpc_num_subkeys, + .num_values = rpc_num_values, +}; + +WERROR reg_open_remote (struct registry_context **ctx, const char *user, const char *pass, const char *location) +{ + NTSTATUS status; + struct dcerpc_pipe *p; + + *ctx = talloc_p(NULL, struct registry_context); + + /* Default to local smbd if no connection is specified */ + if (!location) { + location = talloc_strdup(ctx, "ncalrpc:"); + } + + status = dcerpc_pipe_connect(&p, location, + DCERPC_WINREG_UUID, + DCERPC_WINREG_VERSION, + lp_workgroup(), + user, pass); + (*ctx)->backend_data = p; + + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status))); + return ntstatus_to_werror(status); + } + + (*ctx)->get_hive = rpc_get_hive; + + talloc_set_destructor(*ctx, rpc_close); + + return WERR_OK; +} + +NTSTATUS registry_rpc_init(void) +{ + return registry_register(®_backend_rpc); +} diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c deleted file mode 100644 index 3969a763e0..0000000000 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - Samba Unix/Linux SMB implementation - RPC backend for the registry library - Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "includes.h" -#include "registry.h" -#include "librpc/gen_ndr/ndr_winreg.h" - -/** - * This is the RPC backend for the registry library. - */ - -static void init_winreg_String(struct winreg_String *name, const char *s) -{ - name->name = s; - if (s) { - name->name_len = 2 * (strlen_m(s) + 1); - name->name_size = name->name_len; - } else { - name->name_len = 0; - name->name_size = 0; - } -} - - -#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ -{ \ - struct winreg_Open ## u r; \ - struct winreg_OpenUnknown unknown; \ - NTSTATUS status; \ - \ - unknown.unknown0 = 0x84e0; \ - unknown.unknown1 = 0x0000; \ - r.in.unknown = &unknown; \ - r.in.access_required = SEC_FLAG_MAXIMUM_ALLOWED; \ - r.out.handle = hnd;\ - \ - status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ - if (NT_STATUS_IS_ERR(status)) {\ - DEBUG(0,("Error executing open\n"));\ - return ntstatus_to_werror(status);\ - }\ -\ - return r.out.result;\ -} - -openhive(HKLM) -openhive(HKCU) -openhive(HKPD) -openhive(HKU) -openhive(HKCR) -openhive(HKDD) -openhive(HKCC) - -struct rpc_key_data { - struct policy_handle pol; - int num_subkeys; - int num_values; - int max_valnamelen; - int max_valdatalen; -}; - -struct { - const char *name; - WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); -} known_hives[] = { -{ "HKEY_LOCAL_MACHINE", open_HKLM }, -{ "HKEY_CURRENT_USER", open_HKCU }, -{ "HKEY_CLASSES_ROOT", open_HKCR }, -{ "HKEY_PERFORMANCE_DATA", open_HKPD }, -{ "HKEY_USERS", open_HKU }, -{ "HKEY_DYN_DATA", open_HKDD }, -{ "HKEY_CURRENT_CONFIG", open_HKCC }, -{ NULL, NULL } -}; - -static WERROR rpc_query_key(struct registry_key *k); - -static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) -{ - int i = 0; - *hives = talloc_p(mem_ctx, char *); - for(i = 0; known_hives[i].name; i++) { - *hives = talloc_realloc_p(mem_ctx, *hives, char *, i+2); - (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name); - } - (*hives)[i] = NULL; - return WERR_OK; -} - -static WERROR rpc_close_hive (struct registry_hive *h) -{ - dcerpc_pipe_close(h->backend_data); - return WERR_OK; -} - -static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) -{ - NTSTATUS status; - char *user; - char *pass; - struct rpc_key_data *mykeydata; - struct dcerpc_pipe *p; - int n; - - if (!h->credentials) return WERR_INVALID_PARAM; - - /* Default to local smbd if no connection is specified */ - if (!h->location) { - h->location = talloc_strdup(mem_ctx, "ncalrpc:"); - } - - user = talloc_strdup(mem_ctx, h->credentials); - pass = strchr(user, '%'); - if (pass) { - *pass = '\0'; - pass = strdup(pass+1); - } else { - pass = strdup(""); - } - - status = dcerpc_pipe_connect(&p, h->location, - DCERPC_WINREG_UUID, - DCERPC_WINREG_VERSION, - lp_workgroup(), - user, pass); - free(pass); - - h->backend_data = p; - - if(NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status))); - return ntstatus_to_werror(status); - } - - for(n = 0; known_hives[n].name; n++) - { - if(!strcmp(known_hives[n].name, h->backend_hivename)) break; - } - - if(!known_hives[n].name) { - DEBUG(1, ("No such hive %s\n", known_hives[n].name)); - return WERR_NO_MORE_ITEMS; - } - - *k = talloc_p(mem_ctx, struct registry_key); - (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); - mykeydata->num_values = -1; - mykeydata->num_subkeys = -1; - return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol)); -} - -#if 0 -static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) -{ - struct winreg_OpenKey r; - struct rpc_key_data *mykeydata; - - k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); - mykeydata->num_values = -1; - mykeydata->num_subkeys = -1; - - /* Then, open the handle using the hive */ - - memset(&r, 0, sizeof(struct winreg_OpenKey)); - r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); - init_winreg_String(&r.in.keyname, k->path); - r.in.unknown = 0x00000000; - r.in.access_mask = 0x02000000; - r.out.handle = &mykeydata->pol; - - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); - - return r.out.result; -} -#endif - -static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) -{ - struct rpc_key_data *mykeydata; - struct winreg_OpenKey r; - - *key = talloc_p(mem_ctx, struct registry_key); - (*key)->name = talloc_strdup(mem_ctx, name); - - (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); - mykeydata->num_values = -1; - mykeydata->num_subkeys = -1; - - /* Then, open the handle using the hive */ - - memset(&r, 0, sizeof(struct winreg_OpenKey)); - r.in.handle = &(((struct rpc_key_data *)h->backend_data)->pol); - init_winreg_String(&r.in.keyname, name); - r.in.unknown = 0x00000000; - r.in.access_mask = 0x02000000; - r.out.handle = &mykeydata->pol; - - dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r); - - return r.out.result; -} - -static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) -{ - return rpc_open_rel_key(mem_ctx, h->root, name, key); -} - -static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) -{ - struct rpc_key_data *mykeydata = parent->backend_data; - WERROR error; - struct winreg_EnumValue r; - uint32 type, len1, zero = 0; - NTSTATUS status; - uint8_t buf8; - uint16_t buf16; - - if(mykeydata->num_values == -1) { - error = rpc_query_key(parent); - if(!W_ERROR_IS_OK(error)) return error; - } - - len1 = mykeydata->max_valdatalen; - - r.in.handle = &mykeydata->pol; - r.in.enum_index = n; - r.in.name_in.length = 0; - r.in.name_in.size = mykeydata->max_valnamelen * 2; - r.in.name_in.name = &buf16; - r.in.type = &type; - r.in.value = &buf8; - r.in.length = &zero; - r.in.size = &len1; - r.out.type = &type; - - - status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); - if(NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); - return WERR_GENERAL_FAILURE; - } - - if(NT_STATUS_IS_OK(status) && - W_ERROR_IS_OK(r.out.result) && r.out.length) { - *value = talloc_p(mem_ctx, struct registry_value); - (*value)->parent = parent; - (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); - (*value)->data_type = type; - (*value)->data_len = *r.out.length; - (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value, *r.out.length); - return WERR_OK; - } - - return r.out.result; -} - -static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) -{ - struct winreg_EnumKey r; - struct winreg_EnumKeyNameRequest keyname; - struct winreg_String classname; - struct winreg_Time tm; - struct rpc_key_data *mykeydata = parent->backend_data; - NTSTATUS status; - - r.in.handle = &mykeydata->pol; - keyname.unknown = 0x0000020a; - init_winreg_String(&keyname.key_name, NULL); - init_winreg_String(&classname, NULL); - r.in.in_name = &keyname; - r.in.class = &classname; - tm.low = tm.high = 0x7fffffff; - r.in.last_changed_time = &tm; - - r.in.enum_index = n; - r.in.unknown = r.out.unknown = 0x0414; - r.in.key_name_len = r.out.key_name_len = 0; - status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); - if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); - } - - return r.out.result; -} - -static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) -{ - return WERR_NOT_SUPPORTED; -} - -static WERROR rpc_query_key(struct registry_key *k) -{ - NTSTATUS status; - struct winreg_QueryInfoKey r; - struct rpc_key_data *mykeydata = k->backend_data; - TALLOC_CTX *mem_ctx = talloc_init("query_key"); - - init_winreg_String(&r.in.class, NULL); - r.in.handle = &mykeydata->pol; - - status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r); - talloc_destroy(mem_ctx); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - if (W_ERROR_IS_OK(r.out.result)) { - mykeydata->num_subkeys = r.out.num_subkeys; - mykeydata->num_values = r.out.num_values; - mykeydata->max_valnamelen = r.out.max_valnamelen; - mykeydata->max_valdatalen = r.out.max_valbufsize; - } - - return r.out.result; -} - -static WERROR rpc_del_key(struct registry_key *k) -{ - NTSTATUS status; - struct rpc_key_data *mykeydata = k->backend_data; - struct winreg_DeleteKey r; - struct registry_key *parent; - WERROR error; - TALLOC_CTX *mem_ctx = talloc_init("del_key"); - - error = reg_key_get_parent(mem_ctx, k, &parent); - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } - - mykeydata = parent->backend_data; - - r.in.handle = &mykeydata->pol; - init_winreg_String(&r.in.key, k->name); - - status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); - - talloc_destroy(mem_ctx); - - return r.out.result; -} - -static WERROR rpc_num_values(struct registry_key *key, int *count) { - struct rpc_key_data *mykeydata = key->backend_data; - WERROR error; - - if(mykeydata->num_values == -1) { - error = rpc_query_key(key); - if(!W_ERROR_IS_OK(error)) return error; - } - - *count = mykeydata->num_values; - return WERR_OK; -} - -static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { - struct rpc_key_data *mykeydata = key->backend_data; - WERROR error; - - if(mykeydata->num_subkeys == -1) { - error = rpc_query_key(key); - if(!W_ERROR_IS_OK(error)) return error; - } - - *count = mykeydata->num_subkeys; - return WERR_OK; -} - -static struct registry_operations reg_backend_rpc = { - .name = "rpc", - .open_hive = rpc_open_hive, - .close_hive = rpc_close_hive, - .open_key = rpc_open_key, - .get_subkey_by_index = rpc_get_subkey_by_index, - .get_value_by_index = rpc_get_value_by_index, - .add_key = rpc_add_key, - .del_key = rpc_del_key, - .num_subkeys = rpc_num_subkeys, - .num_values = rpc_num_values, - .list_available_hives = rpc_list_hives, -}; - -NTSTATUS registry_rpc_init(void) -{ - return registry_register(®_backend_rpc); -} diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c new file mode 100644 index 0000000000..a94ad86c2c --- /dev/null +++ b/source4/lib/registry/reg_backend_w95.c @@ -0,0 +1,356 @@ +/* + Samba Unix/Linux SMB client utility libeditreg.c + Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org + + Backend for Windows '95 registry files. Explanation of file format + comes from http://www.cs.mun.ca/~michael/regutils/. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "registry.h" +#include "system/shmem.h" + +/** + * The registry starts with a header that contains pointers to + * the rgdb. + * + * After the main header follows the RGKN header (key index table). + * The RGKN keys are listed after each other. They are put into + * blocks, the first having a length of 0x2000 bytes, the others + * being 0x1000 bytes long. + * + * After the RGKN header follow one or more RGDB blocks. These blocks + * contain keys. A key is followed by its name and its values. + * + * Values are followed by their name and then their data. + * + * Basically the idea is that the RGKN contains the associations between + * the keys and the RGDB contains the actual data. + */ + +typedef uint_t DWORD; +typedef unsigned short WORD; + +typedef struct creg_block { + DWORD CREG_ID; /* CREG */ + DWORD uk1; + DWORD rgdb_offset; + DWORD chksum; + WORD num_rgdb; + WORD flags; + DWORD uk2; + DWORD uk3; + DWORD uk4; +} CREG_HDR; + +typedef struct rgkn_block { + DWORD RGKN_ID; /* RGKN */ + DWORD size; + DWORD root_offset; + DWORD free_offset; + DWORD flags; + DWORD chksum; + DWORD uk1; + DWORD uk2; +} RGKN_HDR; + +typedef struct reg_id { + WORD id; + WORD rgdb; +} REG_ID; + +typedef struct rgkn_key { + DWORD type; /* 0x00000000 = normal key, 0x80000000 = free block */ + DWORD hash; /* Contains either hash or size of free blocks that follows */ + DWORD next_free; + DWORD parent_offset; + DWORD first_child_offset; + DWORD next_offset; + REG_ID id; +} RGKN_KEY; + + +typedef struct rgdb_block { + DWORD RGDB_ID; /* RGDB */ + DWORD size; + DWORD unused_size; + WORD flags; + WORD section; + DWORD free_offset; /* -1 if there is no free space */ + WORD max_id; + WORD first_free_id; + DWORD uk1; + DWORD chksum; +} RGDB_HDR; + +typedef struct rgdb_key { + DWORD size; + REG_ID id; + DWORD used_size; + WORD name_len; + WORD num_values; + DWORD uk1; +} RGDB_KEY; + +typedef struct rgdb_value { + DWORD type; + DWORD uk1; + WORD name_len; + WORD data_len; +} RGDB_VALUE; + +typedef struct creg_struct_s { + int fd; + BOOL modified; + char *base; + struct stat sbuf; + CREG_HDR *creg_hdr; + RGKN_HDR *rgkn_hdr; + RGDB_KEY ***rgdb_keys; +} CREG; + +#define RGKN_START_SIZE 0x2000 +#define RGKN_INC_SIZE 0x1000 + +#define LOCN_RGKN(creg, o) ((RGKN_KEY *)((creg)->base + sizeof(CREG_HDR) + o)) +#define LOCN_RGDB_BLOCK(creg, o) (((creg)->base + (creg)->creg_hdr->rgdb_offset + o)) +#define LOCN_RGDB_KEY(creg, rgdb, id) ((RGDB_KEY *)((creg)->rgdb_keys[(rgdb)][(id)])) + +static DWORD str_to_dword(const char *a) { + int i; + unsigned long ret = 0; + for(i = strlen(a)-1; i >= 0; i--) { + ret = ret * 0x100 + a[i]; + } + return ret; +} + +#if 0 /* unused */ + +static DWORD calc_hash(const char *str) { + DWORD ret = 0; + int i; + for(i = 0; str[i] && str[i] != '\\'; i++) { + ret+=toupper(str[i]); + } + return ret; +} + +static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off) +{ + off_t i; + for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) { + RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i); + if(key->type == 0) { + DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, (long)key->hash)); + } else if(key->type == 0x80000000) { + DEBUG(3,("free\n")); + i += key->hash; + } else { + DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type)); + } + } +} + +#endif + +static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) +{ + DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size; + DWORD offset = 0; + + while(offset < used_size) { + RGDB_KEY *key = (RGDB_KEY *)(((char *)rgdb_hdr) + sizeof(RGDB_HDR) + offset); + + if(!(key->id.id == 0xFFFF && key->id.rgdb == 0xFFFF))creg->rgdb_keys[key->id.rgdb][key->id.id] = key; + offset += key->size; + } +} + +static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) +{ + CREG *creg; + DWORD creg_id, rgkn_id; + DWORD i; + DWORD offset; + + creg = talloc_p(h, CREG); + memset(creg, 0, sizeof(CREG)); + h->backend_data = creg; + + if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) { + return WERR_FOOBAR; + } + + if (fstat(creg->fd, &creg->sbuf) < 0) { + return WERR_FOOBAR; + } + + creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0); + + if ((int)creg->base == 1) { + DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno))); + return WERR_FOOBAR; + } + + creg->creg_hdr = (CREG_HDR *)creg->base; + + if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) { + DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n", + creg_id, h->location)); + return WERR_FOOBAR; + } + + creg->rgkn_hdr = (RGKN_HDR *)LOCN_RGKN(creg, 0); + + if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { + DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", + rgkn_id, h->location)); + return WERR_FOOBAR; + } + +#if 0 + /* If'ed out because we only need to parse this stuff when allocating new + * entries (which we don't do at the moment */ + /* First parse the 0x2000 long block */ + parse_rgkn_block(creg, sizeof(RGKN_HDR), 0x2000); + + /* Then parse the other 0x1000 length blocks */ + for(offset = 0x2000; offset < creg->rgkn_hdr->size; offset+=0x1000) { + parse_rgkn_block(creg, offset, offset+0x1000); + } +#endif + + creg->rgdb_keys = talloc_array_p(h, RGDB_KEY **, creg->creg_hdr->num_rgdb); + + offset = 0; + DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); + for(i = 0; i < creg->creg_hdr->num_rgdb; i++) { + RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset); + + if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { + DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n", + rgdb_hdr->RGDB_ID, h->location)); + return WERR_FOOBAR; + } else { + DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); + } + + + creg->rgdb_keys[i] = talloc_array_p(h, RGDB_KEY *, rgdb_hdr->max_id+1); + memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); + + parse_rgdb_block(creg, rgdb_hdr); + + offset+=rgdb_hdr->size; + } + + /* First element in rgkn should be root key */ + *root = talloc_p(h, struct registry_key); + (*root)->name = NULL; + (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); + + return WERR_OK; +} + +static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **key) +{ + CREG *creg = parent->hive->backend_data; + RGKN_KEY *rgkn_key = parent->backend_data; + RGKN_KEY *child; + DWORD child_offset; + DWORD cur = 0; + + /* Get id of first child */ + child_offset = rgkn_key->first_child_offset; + + while(child_offset != 0xFFFFFFFF) { + child = LOCN_RGKN(creg, child_offset); + + /* n == cur ? return! */ + if(cur == n) { + RGDB_KEY *rgdb_key; + rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); + if(!rgdb_key) { + DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); + return WERR_FOOBAR; + } + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->backend_data = child; + (*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); + return WERR_OK; + } + + cur++; + + child_offset = child->next_offset; + } + + return WERR_NO_MORE_ITEMS; +} + +static WERROR w95_num_values(struct registry_key *k, int *count) +{ + RGKN_KEY *rgkn_key = k->backend_data; + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + + if(!rgdb_key) return WERR_FOOBAR; + + *count = rgdb_key->num_values; + + return WERR_OK; +} + +static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) +{ + RGKN_KEY *rgkn_key = k->backend_data; + DWORD i; + DWORD offset = 0; + RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); + RGDB_VALUE *curval = NULL; + + if(!rgdb_key) return WERR_FOOBAR; + + if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS; + + for(i = 0; i < idx; i++) { + curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); + offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len; + } + + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->backend_data = curval; + (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); + + (*value)->data_len = curval->data_len; + (*value)->data_blk = talloc_memdup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); + (*value)->data_type = curval->type; + + return WERR_OK; +} + +static struct hive_operations reg_backend_w95 = { + .name = "w95", + .open_hive = w95_open_reg, + .get_value_by_index = w95_get_value_by_id, + .num_values = w95_num_values, + .get_subkey_by_index = w95_get_subkey_by_index, +}; + +NTSTATUS registry_w95_init(void) +{ + return registry_register(®_backend_w95); +} diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95/reg_backend_w95.c deleted file mode 100644 index 445d13a99c..0000000000 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - Samba Unix/Linux SMB client utility libeditreg.c - Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org - - Backend for Windows '95 registry files. Explanation of file format - comes from http://www.cs.mun.ca/~michael/regutils/. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "includes.h" -#include "registry.h" -#include "system/shmem.h" - -/** - * The registry starts with a header that contains pointers to - * the rgdb. - * - * After the main header follows the RGKN header (key index table). - * The RGKN keys are listed after each other. They are put into - * blocks, the first having a length of 0x2000 bytes, the others - * being 0x1000 bytes long. - * - * After the RGKN header follow one or more RGDB blocks. These blocks - * contain keys. A key is followed by its name and its values. - * - * Values are followed by their name and then their data. - * - * Basically the idea is that the RGKN contains the associations between - * the keys and the RGDB contains the actual data. - */ - -typedef uint_t DWORD; -typedef unsigned short WORD; - -typedef struct creg_block { - DWORD CREG_ID; /* CREG */ - DWORD uk1; - DWORD rgdb_offset; - DWORD chksum; - WORD num_rgdb; - WORD flags; - DWORD uk2; - DWORD uk3; - DWORD uk4; -} CREG_HDR; - -typedef struct rgkn_block { - DWORD RGKN_ID; /* RGKN */ - DWORD size; - DWORD root_offset; - DWORD free_offset; - DWORD flags; - DWORD chksum; - DWORD uk1; - DWORD uk2; -} RGKN_HDR; - -typedef struct reg_id { - WORD id; - WORD rgdb; -} REG_ID; - -typedef struct rgkn_key { - DWORD type; /* 0x00000000 = normal key, 0x80000000 = free block */ - DWORD hash; /* Contains either hash or size of free blocks that follows */ - DWORD next_free; - DWORD parent_offset; - DWORD first_child_offset; - DWORD next_offset; - REG_ID id; -} RGKN_KEY; - - -typedef struct rgdb_block { - DWORD RGDB_ID; /* RGDB */ - DWORD size; - DWORD unused_size; - WORD flags; - WORD section; - DWORD free_offset; /* -1 if there is no free space */ - WORD max_id; - WORD first_free_id; - DWORD uk1; - DWORD chksum; -} RGDB_HDR; - -typedef struct rgdb_key { - DWORD size; - REG_ID id; - DWORD used_size; - WORD name_len; - WORD num_values; - DWORD uk1; -} RGDB_KEY; - -typedef struct rgdb_value { - DWORD type; - DWORD uk1; - WORD name_len; - WORD data_len; -} RGDB_VALUE; - -typedef struct creg_struct_s { - int fd; - BOOL modified; - char *base; - struct stat sbuf; - CREG_HDR *creg_hdr; - RGKN_HDR *rgkn_hdr; - RGDB_KEY ***rgdb_keys; -} CREG; - -#define RGKN_START_SIZE 0x2000 -#define RGKN_INC_SIZE 0x1000 - -#define LOCN_RGKN(creg, o) ((RGKN_KEY *)((creg)->base + sizeof(CREG_HDR) + o)) -#define LOCN_RGDB_BLOCK(creg, o) (((creg)->base + (creg)->creg_hdr->rgdb_offset + o)) -#define LOCN_RGDB_KEY(creg, rgdb, id) ((RGDB_KEY *)((creg)->rgdb_keys[(rgdb)][(id)])) - -static DWORD str_to_dword(const char *a) { - int i; - unsigned long ret = 0; - for(i = strlen(a)-1; i >= 0; i--) { - ret = ret * 0x100 + a[i]; - } - return ret; -} - -#if 0 /* unused */ - -static DWORD calc_hash(const char *str) { - DWORD ret = 0; - int i; - for(i = 0; str[i] && str[i] != '\\'; i++) { - ret+=toupper(str[i]); - } - return ret; -} - -static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off) -{ - off_t i; - for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) { - RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i); - if(key->type == 0) { - DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, (long)key->hash)); - } else if(key->type == 0x80000000) { - DEBUG(3,("free\n")); - i += key->hash; - } else { - DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type)); - } - } -} - -#endif - -static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) -{ - DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size; - DWORD offset = 0; - - while(offset < used_size) { - RGDB_KEY *key = (RGDB_KEY *)(((char *)rgdb_hdr) + sizeof(RGDB_HDR) + offset); - - if(!(key->id.id == 0xFFFF && key->id.rgdb == 0xFFFF))creg->rgdb_keys[key->id.rgdb][key->id.id] = key; - offset += key->size; - } -} - -static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **root) -{ - CREG *creg; - DWORD creg_id, rgkn_id; - DWORD i; - DWORD offset; - - creg = talloc_p(mem_ctx, CREG); - memset(creg, 0, sizeof(CREG)); - h->backend_data = creg; - - if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) { - return WERR_FOOBAR; - } - - if (fstat(creg->fd, &creg->sbuf) < 0) { - return WERR_FOOBAR; - } - - creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0); - - if ((int)creg->base == 1) { - DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno))); - return WERR_FOOBAR; - } - - creg->creg_hdr = (CREG_HDR *)creg->base; - - if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) { - DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n", - creg_id, h->location)); - return WERR_FOOBAR; - } - - creg->rgkn_hdr = (RGKN_HDR *)LOCN_RGKN(creg, 0); - - if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) { - DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n", - rgkn_id, h->location)); - return WERR_FOOBAR; - } - -#if 0 - /* If'ed out because we only need to parse this stuff when allocating new - * entries (which we don't do at the moment */ - /* First parse the 0x2000 long block */ - parse_rgkn_block(creg, sizeof(RGKN_HDR), 0x2000); - - /* Then parse the other 0x1000 length blocks */ - for(offset = 0x2000; offset < creg->rgkn_hdr->size; offset+=0x1000) { - parse_rgkn_block(creg, offset, offset+0x1000); - } -#endif - - creg->rgdb_keys = talloc_array_p(mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); - - offset = 0; - DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); - for(i = 0; i < creg->creg_hdr->num_rgdb; i++) { - RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset); - - if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) { - DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n", - rgdb_hdr->RGDB_ID, h->location)); - return WERR_FOOBAR; - } else { - DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id)); - } - - - creg->rgdb_keys[i] = talloc_array_p(mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); - memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); - - parse_rgdb_block(creg, rgdb_hdr); - - offset+=rgdb_hdr->size; - } - - /* First element in rgkn should be root key */ - *root = talloc_p(mem_ctx, struct registry_key); - (*root)->name = NULL; - (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); - - return WERR_OK; -} - -static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **key) -{ - CREG *creg = parent->hive->backend_data; - RGKN_KEY *rgkn_key = parent->backend_data; - RGKN_KEY *child; - DWORD child_offset; - DWORD cur = 0; - - /* Get id of first child */ - child_offset = rgkn_key->first_child_offset; - - while(child_offset != 0xFFFFFFFF) { - child = LOCN_RGKN(creg, child_offset); - - /* n == cur ? return! */ - if(cur == n) { - RGDB_KEY *rgdb_key; - rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id); - if(!rgdb_key) { - DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); - return WERR_FOOBAR; - } - *key = talloc_p(mem_ctx, struct registry_key); - (*key)->backend_data = child; - (*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); - return WERR_OK; - } - - cur++; - - child_offset = child->next_offset; - } - - return WERR_NO_MORE_ITEMS; -} - -static WERROR w95_num_values(struct registry_key *k, int *count) -{ - RGKN_KEY *rgkn_key = k->backend_data; - RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); - - if(!rgdb_key) return WERR_FOOBAR; - - *count = rgdb_key->num_values; - - return WERR_OK; -} - -static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) -{ - RGKN_KEY *rgkn_key = k->backend_data; - DWORD i; - DWORD offset = 0; - RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); - RGDB_VALUE *curval = NULL; - - if(!rgdb_key) return WERR_FOOBAR; - - if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS; - - for(i = 0; i < idx; i++) { - curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset); - offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len; - } - - *value = talloc_p(mem_ctx, struct registry_value); - (*value)->backend_data = curval; - (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); - - (*value)->data_len = curval->data_len; - (*value)->data_blk = talloc_memdup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); - (*value)->data_type = curval->type; - - return WERR_OK; -} - -static struct registry_operations reg_backend_w95 = { - .name = "w95", - .open_hive = w95_open_reg, - .get_value_by_index = w95_get_value_by_id, - .num_values = w95_num_values, - .get_subkey_by_index = w95_get_subkey_by_index, -}; - -NTSTATUS registry_w95_init(void) -{ - return registry_register(®_backend_w95); -} diff --git a/source4/lib/registry/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine.c new file mode 100644 index 0000000000..8a3458b52c --- /dev/null +++ b/source4/lib/registry/reg_backend_wine.c @@ -0,0 +1,48 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/registry/common/registry.h" +#include "windows/registry.h" + +static WERROR wine_open_reg (struct registry_hive *h, struct registry_key **key) +{ + /* FIXME: Open h->location and mmap it */ +} + + + +static REG_OPS reg_backend_wine = { + .name = "wine", + .open_hive = wine_open_reg, + +}; + +NTSTATUS registry_wine_init(void) +{ + register_backend("registry", ®_backend_wine); + return NT_STATUS_OK; +} + +WERROR reg_open_wine(struct registry_key **ctx) +{ + /* FIXME: Open ~/.wine/system.reg, etc */ + return WERR_NOT_SUPPORTED; +} diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine/reg_backend_wine.c deleted file mode 100644 index 249af27e13..0000000000 --- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - Copyright (C) Jelmer Vernooij 2004. - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/registry/common/registry.h" -#include "windows/registry.h" - -static REG_OPS reg_backend_wine = { - .name = "wine", -}; - -NTSTATUS registry_wine_init(void) -{ - register_backend("registry", ®_backend_wine); - return NT_STATUS_OK; -} diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c new file mode 100644 index 0000000000..a19029524d --- /dev/null +++ b/source4/lib/registry/reg_samba.c @@ -0,0 +1,62 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Jelmer Vernooij 2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, struct registry_key **k) +{ + WERROR error; + const char *conf; + char *backend, *location; + const char *hivename = reg_get_hkey_name(hkey); + + *k = NULL; + + conf = lp_parm_string(-1, "registry", hivename); + + if (!conf) { + return WERR_NOT_SUPPORTED; + } + + backend = talloc_strdup(NULL, conf); + location = strchr(backend, ':'); + + if (location) { + *location = '\0'; + location++; + } + + error = reg_open_hive(ctx, backend, location, NULL, k); + + talloc_destroy(backend); + + return error; +} + +WERROR reg_open_local (struct registry_context **ctx) +{ + *ctx = talloc_p(NULL, struct registry_context); + (*ctx)->get_hive = reg_samba_get_hive; + + return WERR_OK; +} diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 55c8f1e72f..fc2954b6af 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -113,21 +113,19 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, { int opt; poptContext pc; - const char *backend1 = NULL, *backend2 = NULL; - const char *location2; - const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; - struct registry_context *h1 = NULL, *h2; + struct registry_context *h1 = NULL, *h2 = NULL; int from_null = 0; int i; WERROR error, error2; struct poptOption long_options[] = { POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, NULL, 'c', "credentials", NULL}, + POPT_COMMON_CREDENTIALS {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, - {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" }, + {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL", NULL }, + {"remote", 'R', POPT_ARG_STRING, NULL, 0, "Connect to remote server" , NULL }, + {"local", 'L', POPT_ARG_NONE, NULL, 0, "Open local registry", NULL }, POPT_TABLEEND }; @@ -141,49 +139,24 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { + error = WERR_OK; switch(opt) { - case 'c': - if(!credentials1 && !from_null) credentials1 = poptGetOptArg(pc); - else if(!credentials2) credentials2 = poptGetOptArg(pc); + case 'L': + if (!h1 && !from_null) error = reg_open_local(&h1); + else if (!h2) error = reg_open_local(&h2); break; - case 'b': - if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); - else if(!backend2) backend2 = poptGetOptArg(pc); + case 'R': + if (!h1 && !from_null) error = reg_open_remote(&h1, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); + else if (!h2) error = reg_open_remote(&h2, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); break; } - } - setup_logging(argv[0], True); - if(!from_null) { - const char *location1; - location1 = poptGetArg(pc); - if(!location1) { - poptPrintUsage(pc, stderr, 0); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error: %s\n", win_errstr(error)); return 1; } - - if(!backend1) backend1 = "rpc"; - - error = reg_open(&h1, backend1, location1, credentials1); - if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); - return 1; - } - } - - location2 = poptGetArg(pc); - if(!location2) { - poptPrintUsage(pc, stderr, 0); - return 2; - } - - if(!backend2) backend2 = "rpc"; - - error = reg_open(&h2, backend2, location2, credentials2); - if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); - return 1; } + setup_logging(argv[0], True); poptFreeContext(pc); @@ -196,12 +169,25 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, } fprintf(fd, "REGEDIT4\n\n"); - fprintf(fd, "; Generated using regdiff\n"); + fprintf(fd, "; Generated using regdiff, part of Samba\n"); error2 = error = WERR_OK; - for(i = 0; (!h1 || i < h1->num_hives) && i < h2->num_hives; i++) { - writediff(h1?h1->hives[i]->root:NULL, h2->hives[i]->root, fd); + for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++) { + struct registry_key *r1, *r2; + error = reg_get_hive(h1, i, &r1); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_hkey_name(i))); + continue; + } + + error = reg_get_hive(h2, i, &r2); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_hkey_name(i))); + continue; + } + + writediff(r1, r2, fd); } fclose(fd); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index be60b96019..a4a4649c96 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -758,16 +758,14 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd { int opt; poptContext pc; - const char *location; - const char *credentials = NULL; const char *patch; - const char *backend = "rpc"; struct registry_context *h; + const char *remote = NULL; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 'c', "credentials (user%password", NULL}, + POPT_COMMON_CREDENTIALS + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, POPT_TABLEEND }; @@ -785,25 +783,22 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd setup_logging(argv[0], True); - location = poptGetArg(pc); - if(!location) { - poptPrintUsage(pc, stderr, 0); - return 1; + if (remote) { + error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else { + error = reg_open_local (&h); } - error = reg_open(&h, backend, location, credentials); - if(!h) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); + if (W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error: %s\n", win_errstr(error)); return 1; } - + patch = poptGetArg(pc); if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); nt_apply_reg_command_file(h, patch); - talloc_destroy(h->mem_ctx); - return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index f18b012720..3fd9dab268 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -164,15 +164,23 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key * static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - int i; - for(i = 0; i < cur->hive->reg_ctx->num_hives; i++) { + if (!cur->hive->reg_ctx) { + fprintf(stderr, "Only one hive loaded\n"); + return cur; + } - if(argc == 1) { - printf("%s\n", cur->hive->reg_ctx->hives[i]->name); - } else if(!strcmp(cur->hive->reg_ctx->hives[i]->name, argv[1])) { - return cur->hive->reg_ctx->hives[i]->root; - } + if (argc == 1) { + printf("%s\n", cur->hive->root->name); + } else { + struct registry_key *newroot; + WERROR error = reg_get_hive_by_name(cur->hive->reg_ctx, argv[1], &newroot); + if (W_ERROR_IS_OK(error)) { + return newroot; + } else { + fprintf(stderr, "Can't switch to hive %s: %s\n", cur->hive->root->name, win_errstr(error)); + } } + return NULL; } @@ -274,11 +282,7 @@ static char **reg_complete_command(const char *text, int end) matches[0] = strdup(matches[1]); break; default: - matches[0] = malloc(samelen+1); - if (!matches[0]) - goto cleanup; - strncpy(matches[0], matches[1], samelen); - matches[0][samelen] = 0; + matches[0] = strndup(matches[1], samelen); } matches[count] = NULL; return matches; @@ -295,11 +299,11 @@ cleanup: static char **reg_complete_key(const char *text, int end) { struct registry_key *subkey; - int i, j = 0; + int i, j = 1; + int samelen = 0; int len; char **matches; TALLOC_CTX *mem_ctx; - /* Complete argument */ matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; @@ -313,6 +317,12 @@ static char **reg_complete_key(const char *text, int end) if(!strncmp(text, subkey->name, len)) { matches[j] = strdup(subkey->name); j++; + + if (j == 1) + samelen = strlen(matches[j]); + else + while (strncmp(matches[j], matches[j-1], samelen) != 0) + samelen--; } } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) { break; @@ -322,8 +332,20 @@ static char **reg_complete_key(const char *text, int end) return NULL; } } - matches[j] = NULL; talloc_destroy(mem_ctx); + + if (j == 1) { /* No matches at all */ + SAFE_FREE(matches); + return NULL; + } + + if (j == 2) { /* Exact match */ + matches[0] = strdup(matches[1]); + } else { + matches[0] = strndup(matches[1], samelen); + } + + matches[j] = NULL; return matches; } @@ -341,18 +363,18 @@ static char **reg_completion(const char *text, int start, int end) int main(int argc, char **argv) { int opt; - const char *backend = "rpc"; - const char *credentials = NULL; + const char *backend = NULL; struct registry_key *curkey = NULL; poptContext pc; WERROR error; TALLOC_CTX *mem_ctx = talloc_init("cmd"); - struct registry_context *h; + const char *remote = NULL; + struct registry_context *h = NULL; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL}, + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, POPT_TABLEEND }; @@ -370,20 +392,31 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); - error = reg_open(&h, backend, poptPeekArg(pc), credentials); + if (remote) { + error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else if (backend) { + error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); + } else { + error = reg_open_local(&h); + } + if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + fprintf(stderr, "Unable to open registry\n"); return 1; } - poptFreeContext(pc); - - curkey = h->hives[0]->root; + if (h) { + /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */ + reg_get_hive(h, HKEY_CLASSES_ROOT, &curkey); + } + + poptFreeContext(pc); + while(True) { char *line, *prompt; - if(curkey->hive->name) { - asprintf(&prompt, "%s:%s> ", curkey->hive->name, curkey->path); + if(curkey->hive->root->name) { + asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path); } else { asprintf(&prompt, "%s> ", curkey->path); } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index ced7a00f94..8ff68229eb 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -36,7 +36,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) /* Hive name */ if(p->hive->root == p) { - if(p->hive->name) printf("%s\n", p->hive->name); else printf("\n"); + if(p->hive->root->name) printf("%s\n", p->hive->root->name); else printf("\n"); } else { if(!p->name) printf("\n"); if(fullpath) printf("%s\n", p->path); @@ -73,17 +73,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) int main(int argc, char **argv) { int opt, i; - const char *backend = "rpc"; - const char *credentials = NULL; + const char *backend = NULL; + const char *remote = NULL; poptContext pc; - struct registry_context *h; + struct registry_context *h = NULL; + struct registry_key *root = NULL; WERROR error; int fullpath = 0, no_values = 0; struct poptOption long_options[] = { POPT_AUTOHELP + POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%password)", NULL}, + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL }, {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, POPT_TABLEEND }; @@ -102,7 +104,14 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) setup_logging("regtree", True); - error = reg_open(&h, backend, poptPeekArg(pc), credentials); + if (remote) { + error = reg_open_remote(&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else if (backend) { + error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); + } else { + error = reg_open_local (&h); + } + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error)); return 1; @@ -110,10 +119,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) poptFreeContext(pc); error = WERR_OK; - - for(i = 0; i < h->num_hives; i++) { - print_tree(0, h->hives[i]->root, fullpath, no_values); - } + if (!h) { + print_tree(0, root, fullpath, no_values); + } else { + for(i = HKEY_CLASSES_ROOT; i < HKEY_PN; i++) { + error = reg_get_hive(h, i, &root); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Skipping %s\n", reg_get_hkey_name(i)); + continue; + } + print_tree(0, root, fullpath, no_values); + } + } + return 0; } -- cgit From 1cd129b102ea36e534c73805884ad023a03f0329 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 10 Dec 2004 20:50:49 +0000 Subject: r4133: Cache results of subkey and value queries (This used to be commit 1e12971137f50077e04a0432572275baf4fde35e) --- source4/lib/registry/reg_backend_ldb.c | 84 +++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 7eaf6194a5..e833299b7e 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -22,6 +22,24 @@ #include "registry.h" #include "lib/ldb/include/ldb.h" +struct ldb_key_data +{ + const char *dn; + struct ldb_message **subkeys, **values; + int subkey_count, value_count; +}; + +static int reg_close_ldb_key (void *data) +{ + struct registry_key *key = data; + struct ldb_key_data *kd = key->backend_data; + struct ldb_context *c = key->hive->backend_data; + + ldb_search_free(c, kd->subkeys); kd->subkeys = NULL; + ldb_search_free(c, kd->values); kd->values = NULL; + return 0; +} + static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) { char *ret = talloc_strdup(mem_ctx, ""); @@ -62,52 +80,56 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) { struct ldb_context *c = k->hive->backend_data; - int ret; - struct ldb_message **msg; struct ldb_message_element *el; + struct ldb_key_data *kd = k->backend_data, *newkd; - ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&msg); + /* Do a search if necessary */ + if (kd->subkeys == NULL) { + kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&kd->subkeys); - if(ret < 0) { - DEBUG(0, ("Error getting subkeys for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); - return WERR_FOOBAR; - } + if(kd->subkey_count < 0) { + DEBUG(0, ("Error getting subkeys for '%s': %s\n", kd->dn, ldb_errstring(c))); + return WERR_FOOBAR; + } + } - if(idx >= ret) return WERR_NO_MORE_ITEMS; - - el = ldb_msg_find_element(msg[idx], "key"); + if (idx >= kd->subkey_count) return WERR_NO_MORE_ITEMS; + + el = ldb_msg_find_element(kd->subkeys[idx], "key"); *subkey = talloc_p(mem_ctx, struct registry_key); + talloc_set_destructor(*subkey, reg_close_ldb_key); (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*subkey)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); + (*subkey)->backend_data = newkd = talloc_zero_p(*subkey, struct ldb_key_data); + newkd->dn = talloc_strdup(mem_ctx, kd->subkeys[idx]->dn); - ldb_search_free(c, msg); return WERR_OK; } static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) { struct ldb_context *c = k->hive->backend_data; - int ret; - struct ldb_message **msg; struct ldb_message_element *el; + struct ldb_key_data *kd = k->backend_data; - ret = ldb_search(c, (char *)k->backend_data, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&msg); + /* Do the search if necessary */ + if (kd->values == NULL) { + kd->value_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&kd->values); - if(ret < 0) { - DEBUG(0, ("Error getting values for '%s': %s\n", (char *)k->backend_data, ldb_errstring(c))); - return WERR_FOOBAR; + if(kd->value_count < 0) { + DEBUG(0, ("Error getting values for '%s': %s\n", kd->dn, ldb_errstring(c))); + return WERR_FOOBAR; + } } - if(idx >= ret) return WERR_NO_MORE_ITEMS; + if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS; - el = ldb_msg_find_element(msg[idx], "value"); + el = ldb_msg_find_element(kd->values[idx], "value"); *value = talloc_p(mem_ctx, struct registry_value); (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*value)->backend_data = talloc_strdup(mem_ctx, msg[idx]->dn); + (*value)->backend_data = talloc_strdup(mem_ctx, kd->values[idx]->dn); - ldb_search_free(c, msg); return WERR_OK; } @@ -117,8 +139,9 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c struct ldb_message **msg; char *ldap_path; int ret; + struct ldb_key_data *newkd; ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); - + ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); if(ret == 0) { @@ -129,8 +152,10 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c } *key = talloc_p(mem_ctx, struct registry_key); + talloc_set_destructor(*key, reg_close_ldb_key); (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); - (*key)->backend_data = talloc_strdup(mem_ctx, msg[0]->dn); + (*key)->backend_data = newkd = talloc_zero_p(*key, struct ldb_key_data); + newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); ldb_search_free(c, msg); @@ -152,7 +177,10 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) hive->backend_data = c; hive->root = talloc_zero_p(hive, struct registry_key); + talloc_set_destructor (hive->root, reg_close_ldb_key); hive->root->name = talloc_strdup(hive->root, ""); + hive->root->backend_data = talloc_zero_p(hive->root, struct ldb_key_data); + return WERR_OK; } @@ -161,6 +189,7 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message msg; + struct ldb_key_data *newkd; int ret; ZERO_STRUCT(msg); @@ -176,17 +205,20 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con } *newkey = talloc_zero_p(mem_ctx, struct registry_key); - (*newkey)->backend_data = msg.dn; (*newkey)->name = talloc_strdup(mem_ctx, name); + (*newkey)->backend_data = newkd = talloc_zero_p(*newkey, struct ldb_key_data); + newkd->dn = msg.dn; + return WERR_OK; } static WERROR ldb_del_key (struct registry_key *key) { int ret; + struct ldb_key_data *kd = key->backend_data; - ret = ldb_delete(key->hive->backend_data, key->backend_data); + ret = ldb_delete(key->hive->backend_data, kd->dn); if (ret < 0) { DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); -- cgit From 6fb61740076f49a6e0ac3eaff5c8002e316cfe90 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Dec 2004 21:31:32 +0000 Subject: r4135: improve a debug message (This used to be commit 4b45d3d2e86122dbe5bd258fc96ad674aba0d417) --- source4/lib/registry/common/reg_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 740d849db1..a93fa31836 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -222,7 +222,7 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char WERROR error; if(!parent) { - DEBUG(0, ("Invalid parent key specified")); + DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name)); return WERR_INVALID_PARAM; } -- cgit From a9fa37d6187eb0d0a074fec2ecffe2915b701188 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 10 Dec 2004 22:28:49 +0000 Subject: r4137: Make *_open_key take a registry_key instead of a hive (more efficient in some cases) (This used to be commit ddf7a331c58976f2c0b4a00390118f1acf60e3eb) --- source4/lib/registry/common/reg_interface.c | 10 +++------- source4/lib/registry/reg_backend_dir.c | 17 ++++++++-------- source4/lib/registry/reg_backend_gconf.c | 9 ++++++--- source4/lib/registry/reg_backend_ldb.c | 30 ++++++++++++++++++++--------- source4/lib/registry/reg_backend_rpc.c | 9 ++------- 5 files changed, 41 insertions(+), 34 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index a93fa31836..2382e4aa43 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -218,7 +218,6 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co */ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result) { - char *fullname; WERROR error; if(!parent) { @@ -257,15 +256,12 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char return WERR_NOT_SUPPORTED; } - - fullname = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)); - - error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); + error = parent->hive->functions->open_key(mem_ctx, parent, name, result); if(!W_ERROR_IS_OK(error)) return error; (*result)->hive = parent->hive; - (*result)->path = fullname; + (*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)); (*result)->hive = parent->hive; return WERR_OK; @@ -369,7 +365,7 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, if(key->hive->functions->get_subkey_by_name) { error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey); } else if(key->hive->functions->open_key) { - error = key->hive->functions->open_key(mem_ctx, key->hive, talloc_asprintf(mem_ctx, "%s\\%s", key->path, name), subkey); + error = key->hive->functions->open_key(mem_ctx, key, name, subkey); } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 5c3ed3c44c..c004be5a06 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -39,10 +39,10 @@ static WERROR reg_dir_del_key(struct registry_key *k) return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; } -static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **subkey) +static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, struct registry_key **subkey) { DIR *d; - char *fullpath; + char *fullpath, *unixpath; struct registry_key *ret; if(!name) { @@ -51,18 +51,19 @@ static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, con } - fullpath = talloc_asprintf(mem_ctx, "%s%s", h->location, name); - fullpath = reg_path_win2unix(fullpath); + fullpath = talloc_asprintf(mem_ctx, "%s/%s", (char *)p->backend_data, name); + unixpath = reg_path_win2unix(fullpath); - d = opendir(fullpath); + d = opendir(unixpath); if(!d) { - DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno))); + DEBUG(3,("Unable to open '%s': %s\n", unixpath, strerror(errno))); return WERR_BADFILE; } closedir(d); ret = talloc_p(mem_ctx, struct registry_key); - ret->hive = h; + ret->hive = p->hive; ret->path = fullpath; + ret->backend_data = unixpath; *subkey = ret; return WERR_OK; } @@ -89,7 +90,6 @@ static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, stat(thispath, &stbuf); if(S_ISDIR(stbuf.st_mode)) { - i++; if(i == idx) { (*key) = talloc_p(mem_ctx, struct registry_key); (*key)->name = e->d_name; @@ -99,6 +99,7 @@ static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, closedir(d); return WERR_OK; } + i++; } SAFE_FREE(thispath); diff --git a/source4/lib/registry/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c index 2fed2417b7..b53d0fedf5 100644 --- a/source4/lib/registry/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf.c @@ -42,15 +42,18 @@ static WERROR reg_open_gconf_hive(struct registry_hive *h, struct registry_key * return WERR_OK; } -static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) { struct registry_key *ret; char *fullpath; - fullpath = talloc_asprintf(mem_ctx, "/%s", reg_path_win2unix(talloc_strdup(mem_ctx, name))); + fullpath = talloc_asprintf(mem_ctx, "%s%s%s", + (char *)h->backend_data, + strlen((char *)h->backend_data) == 1?"":"/", + reg_path_win2unix(talloc_strdup(mem_ctx, name))); /* Check if key exists */ - if(!gconf_client_dir_exists((GConfClient *)h->backend_data, fullpath, NULL)) { + if(!gconf_client_dir_exists((GConfClient *)h->hive->backend_data, fullpath, NULL)) { return WERR_DEST_NOT_FOUND; } diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index e833299b7e..7804a68d3d 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -35,8 +35,15 @@ static int reg_close_ldb_key (void *data) struct ldb_key_data *kd = key->backend_data; struct ldb_context *c = key->hive->backend_data; - ldb_search_free(c, kd->subkeys); kd->subkeys = NULL; - ldb_search_free(c, kd->values); kd->values = NULL; + if (kd->subkeys) { + ldb_search_free(c, kd->subkeys); + kd->subkeys = NULL; + } + + if (kd->values) { + ldb_search_free(c, kd->values); + kd->values = NULL; + } return 0; } @@ -85,7 +92,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, /* Do a search if necessary */ if (kd->subkeys == NULL) { - kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL,&kd->subkeys); + kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &kd->subkeys); if(kd->subkey_count < 0) { DEBUG(0, ("Error getting subkeys for '%s': %s\n", kd->dn, ldb_errstring(c))); @@ -133,14 +140,17 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i return WERR_OK; } -static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) +static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) { - struct ldb_context *c = h->backend_data; + struct ldb_context *c = h->hive->backend_data; struct ldb_message **msg; char *ldap_path; int ret; - struct ldb_key_data *newkd; - ldap_path = reg_path_to_ldb(mem_ctx, name, NULL); + struct ldb_key_data *kd = h->backend_data, *newkd; + ldap_path = talloc_asprintf(mem_ctx, "%s%s%s", + reg_path_to_ldb(mem_ctx, name, NULL), + kd->dn?",":"", + kd->dn?kd->dn:""); ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); @@ -153,7 +163,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c *key = talloc_p(mem_ctx, struct registry_key); talloc_set_destructor(*key, reg_close_ldb_key); - (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')); + (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name); (*key)->backend_data = newkd = talloc_zero_p(*key, struct ldb_key_data); newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); @@ -165,6 +175,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) { struct ldb_context *c; + struct ldb_key_data *kd; if (!hive->location) return WERR_INVALID_PARAM; c = ldb_connect(hive->location, 0, NULL); @@ -179,7 +190,8 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) hive->root = talloc_zero_p(hive, struct registry_key); talloc_set_destructor (hive->root, reg_close_ldb_key); hive->root->name = talloc_strdup(hive->root, ""); - hive->root->backend_data = talloc_zero_p(hive->root, struct ldb_key_data); + hive->root->backend_data = kd = talloc_zero_p(hive->root, struct ldb_key_data); + kd->dn = talloc_strdup(hive->root, "key=root"); return WERR_OK; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 18563b2478..927ed7fcaa 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -155,7 +155,7 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) } #endif -static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) { struct rpc_key_data *mykeydata; struct winreg_OpenKey r; @@ -181,11 +181,6 @@ static WERROR rpc_open_rel_key(TALLOC_CTX *mem_ctx, struct registry_key *h, cons return r.out.result; } -static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const char *name, struct registry_key **key) -{ - return rpc_open_rel_key(mem_ctx, h->root, name, key); -} - static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) { struct rpc_key_data *mykeydata = parent->backend_data; @@ -258,7 +253,7 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key * r.in.key_name_len = r.out.key_name_len = 0; status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - return rpc_open_rel_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); + return rpc_open_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); } return r.out.result; -- cgit From f0eff2525b8df834765a7162007bc8b4565e9a58 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 10 Dec 2004 22:57:43 +0000 Subject: r4140: Get rid of close_hive (replace it with talloc destructors). (This used to be commit bcbfce7b0119538bab06801c97aa9c7d4bf3a6c6) --- source4/lib/registry/common/reg_interface.c | 27 +++++++++++++++------------ source4/lib/registry/reg_backend_ldb.c | 17 ++++++++++------- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 2382e4aa43..cd0b54e2dc 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -149,7 +149,8 @@ WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry /* Open a registry file/host/etc */ WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) { - struct registry_hive *ret; + struct registry_hive *rethive; + struct registry_key *retkey; struct reg_init_function_entry *entry; WERROR werr; @@ -164,28 +165,30 @@ WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, c return WERR_NOT_SUPPORTED; } - ret = talloc_p(parent_ctx, struct registry_hive); - ret->location = location?talloc_strdup(ret, location):NULL; - ret->functions = entry->hive_functions; - ret->backend_data = NULL; - ret->reg_ctx = parent_ctx; + rethive = talloc_p(parent_ctx, struct registry_hive); + rethive->location = location?talloc_strdup(rethive, location):NULL; + rethive->functions = entry->hive_functions; + rethive->backend_data = NULL; + rethive->reg_ctx = parent_ctx; - werr = entry->hive_functions->open_hive(ret, &ret->root); + werr = entry->hive_functions->open_hive(rethive, &retkey); + + rethive->root = retkey; if(!W_ERROR_IS_OK(werr)) { return werr; } - if(!ret->root) { + if(!retkey) { DEBUG(0, ("Backend %s didn't provide root key!\n", backend)); return WERR_GENERAL_FAILURE; } - ret->root->hive = ret; - ret->root->name = NULL; - ret->root->path = talloc_strdup(ret, ""); + retkey->hive = rethive; + retkey->name = NULL; + retkey->path = talloc_strdup(retkey, ""); - *root = ret->root; + *root = retkey; return WERR_OK; } diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 7804a68d3d..b20a56046d 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -29,6 +29,15 @@ struct ldb_key_data int subkey_count, value_count; }; +static int ldb_close_hive (void *_hive) +{ + struct registry_hive *hive = _hive; + ldb_close (hive->backend_data); + return 0; +} + + + static int reg_close_ldb_key (void *data) { struct registry_key *key = data; @@ -189,6 +198,7 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) hive->root = talloc_zero_p(hive, struct registry_key); talloc_set_destructor (hive->root, reg_close_ldb_key); + talloc_set_destructor (hive, ldb_close_hive); hive->root->name = talloc_strdup(hive->root, ""); hive->root->backend_data = kd = talloc_zero_p(hive->root, struct ldb_key_data); kd->dn = talloc_strdup(hive->root, "key=root"); @@ -240,18 +250,11 @@ static WERROR ldb_del_key (struct registry_key *key) return WERR_OK; } -static WERROR ldb_close_hive (struct registry_hive *hive) -{ - ldb_close (hive->backend_data); - return WERR_OK; -} - static struct hive_operations reg_backend_ldb = { .name = "ldb", .add_key = ldb_add_key, .del_key = ldb_del_key, .open_hive = ldb_open_hive, - .close_hive = ldb_close_hive, .open_key = ldb_open_key, .get_value_by_index = ldb_get_value_by_id, .get_subkey_by_index = ldb_get_subkey_by_id, -- cgit From 0bde7a2944fded24af8a9b19a3bb42015bbdd6bb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 10 Dec 2004 23:13:17 +0000 Subject: r4141: Fix crash bug in ldb backend (This used to be commit 5f64a60374486b9fc3d75786c3035a9017dd4d33) --- source4/lib/registry/common/reg_interface.c | 8 ++++---- source4/lib/registry/reg_backend_ldb.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index cd0b54e2dc..b7211d92a4 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -150,7 +150,7 @@ WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) { struct registry_hive *rethive; - struct registry_key *retkey; + struct registry_key *retkey = NULL; struct reg_init_function_entry *entry; WERROR werr; @@ -173,17 +173,17 @@ WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, c werr = entry->hive_functions->open_hive(rethive, &retkey); - rethive->root = retkey; - if(!W_ERROR_IS_OK(werr)) { return werr; } - + if(!retkey) { DEBUG(0, ("Backend %s didn't provide root key!\n", backend)); return WERR_GENERAL_FAILURE; } + rethive->root = retkey; + retkey->hive = rethive; retkey->name = NULL; retkey->path = talloc_strdup(retkey, ""); diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index b20a56046d..e848507634 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -196,12 +196,12 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) ldb_set_debug_stderr(c); hive->backend_data = c; - hive->root = talloc_zero_p(hive, struct registry_key); - talloc_set_destructor (hive->root, reg_close_ldb_key); + *k = talloc_zero_p(hive, struct registry_key); + talloc_set_destructor (*k, reg_close_ldb_key); talloc_set_destructor (hive, ldb_close_hive); - hive->root->name = talloc_strdup(hive->root, ""); - hive->root->backend_data = kd = talloc_zero_p(hive->root, struct ldb_key_data); - kd->dn = talloc_strdup(hive->root, "key=root"); + (*k)->name = talloc_strdup(*k, ""); + (*k)->backend_data = kd = talloc_zero_p(*k, struct ldb_key_data); + kd->dn = talloc_strdup(*k, "key=root"); return WERR_OK; -- cgit From 6cf13f4d72beee3df0432d0898c5981ce8bced43 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 11 Dec 2004 17:12:16 +0000 Subject: r4154: Add definitions for HKEY_PERFORMANCE_TEXT and HKEY_PERFORMANCE_NLSTEXT Hives and predefined keys (HKEY_*) are not necessarily the same thing. (This used to be commit 217e4e5841cfedb2b18dce3f89dd88ea4a36fe8f) --- source4/lib/registry/common/reg_interface.c | 20 ++++++++++---------- source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index b7211d92a4..ba65e570c4 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -74,7 +74,7 @@ BOOL reg_has_backend(const char *backend) } static struct { - uint32 hkey; + enum reg_predefined_key handle; const char *name; } hkey_names[] = { @@ -85,30 +85,30 @@ static struct { {HKEY_USERS, "HKEY_USERS" }, {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" }, {HKEY_DYN_DATA, "HKEY_DYN_DATA" }, - {HKEY_PT, "HKEY_PT" }, - {HKEY_PN, "HKEY_PN" }, + {HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" }, + {HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" }, { 0, NULL } }; -int reg_list_hives(TALLOC_CTX *mem_ctx, char ***hives, uint32_t **hkeys) +int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***hives, enum reg_predefined_key **hkeys) { int i; *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names)); - *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(hkey_names)); + *hkeys = talloc_array_p(mem_ctx, enum reg_predefined_key, ARRAY_SIZE(hkey_names)); for (i = 0; hkey_names[i].name; i++) { (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name); - (*hkeys)[i] = hkey_names[i].hkey; + (*hkeys)[i] = hkey_names[i].handle; } return i; } -const char *reg_get_hkey_name(uint32_t hkey) +const char *reg_get_hkey_name(enum reg_predefined_key hkey) { int i; for (i = 0; hkey_names[i].name; i++) { - if (hkey_names[i].hkey == hkey) return hkey_names[i].name; + if (hkey_names[i].handle == hkey) return hkey_names[i].name; } return NULL; @@ -119,7 +119,7 @@ WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, stru int i; for (i = 0; hkey_names[i].name; i++) { - if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].hkey, key); + if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].handle, key); } DEBUG(1, ("No hive with name '%s'\n", name)); @@ -134,7 +134,7 @@ WERROR reg_close (struct registry_context *ctx) return WERR_OK; } -WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry_key **key) +WERROR reg_get_hive(struct registry_context *ctx, enum reg_predefined_key hkey, struct registry_key **key) { WERROR ret = ctx->get_hive(ctx, hkey, key); diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index fc2954b6af..dfa85d636f 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -173,7 +173,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, error2 = error = WERR_OK; - for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++) { + for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) { struct registry_key *r1, *r2; error = reg_get_hive(h1, i, &r1); if (!W_ERROR_IS_OK(error)) { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 8ff68229eb..7adeeea731 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -123,7 +123,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) if (!h) { print_tree(0, root, fullpath, no_values); } else { - for(i = HKEY_CLASSES_ROOT; i < HKEY_PN; i++) { + for(i = HKEY_CLASSES_ROOT; i < HKEY_PERFORMANCE_NLSTEXT; i++) { error = reg_get_hive(h, i, &root); if (!W_ERROR_IS_OK(error)) { fprintf(stderr, "Skipping %s\n", reg_get_hkey_name(i)); -- cgit From 969e14eae941427cf36c71b5588d7dd8e1f3c615 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 11 Dec 2004 20:06:40 +0000 Subject: r4155: More destinction between hives and predefined keys (This used to be commit c37d6f3c581673d74e7ec6a644ab6a7d13a55535) --- source4/lib/registry/README | 15 ++++++- source4/lib/registry/common/reg_interface.c | 61 ++++++++++++++--------------- source4/lib/registry/reg_backend_rpc.c | 5 +-- source4/lib/registry/reg_samba.c | 19 +++++++-- source4/lib/registry/tools/regdiff.c | 8 ++-- source4/lib/registry/tools/regshell.c | 25 +----------- source4/lib/registry/tools/regtree.c | 4 +- 7 files changed, 67 insertions(+), 70 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/README b/source4/lib/registry/README index 757029cdc2..c91d361acd 100644 --- a/source4/lib/registry/README +++ b/source4/lib/registry/README @@ -1,6 +1,5 @@ This is the registry library. The registry is basically a bunch of hives -(HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc) that can be loaded from -different places. +that can be loaded from different places. The various registry backends provide support for loading/saving specific types of hives: @@ -28,3 +27,15 @@ registry:HKEY_CURRENT_USER = nt4:NTUSER.DAT registry:HKEY_LOCAL_MACHINE = ldb:tdb://registry.tdb WERR_NOT_SUPPORTED will be returned for all hives that haven't been set. + +On Windows the various registry hives are loaded from: + +HKEY_CURRENT_CONFIG: %SystemRoot%\System32\Config\System +HKEY_CURRENT_USER: %Profile%\NTUser.dat +HKEY_LOCAL_MACHINE\SAM: %SystemRoot%\System32\Config\Sam +HKEY_LOCAL_MACHINE\Security: %SystemRoot%\System32\Config\Security +HKEY_LOCAL_MACHINE\Software: %SystemRoot%\System32\Config\Software +HKEY_LOCAL_MACHINE\System: %SystemRoot%\System32\Config\System +HKEY_USERS\.DEFAULT: %SystemRoot%\System32\Config\Default +HKEY_LOCAL_MACHINE\HARDWARE: is autogenerated + diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index ba65e570c4..ee140e150f 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -74,9 +74,9 @@ BOOL reg_has_backend(const char *backend) } static struct { - enum reg_predefined_key handle; + uint32_t handle; const char *name; -} hkey_names[] = +} predef_names[] = { {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" }, {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" }, @@ -90,39 +90,39 @@ static struct { { 0, NULL } }; -int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***hives, enum reg_predefined_key **hkeys) +int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys) { int i; - *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names)); - *hkeys = talloc_array_p(mem_ctx, enum reg_predefined_key, ARRAY_SIZE(hkey_names)); + *predefs = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(predef_names)); + *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(predef_names)); - for (i = 0; hkey_names[i].name; i++) { - (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name); - (*hkeys)[i] = hkey_names[i].handle; + for (i = 0; predef_names[i].name; i++) { + (*predefs)[i] = talloc_strdup(mem_ctx, predef_names[i].name); + (*hkeys)[i] = predef_names[i].handle; } return i; } -const char *reg_get_hkey_name(enum reg_predefined_key hkey) +const char *reg_get_predef_name(uint32_t hkey) { int i; - for (i = 0; hkey_names[i].name; i++) { - if (hkey_names[i].handle == hkey) return hkey_names[i].name; + for (i = 0; predef_names[i].name; i++) { + if (predef_names[i].handle == hkey) return predef_names[i].name; } return NULL; } -WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, struct registry_key **key) +WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key) { int i; - for (i = 0; hkey_names[i].name; i++) { - if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].handle, key); + for (i = 0; predef_names[i].name; i++) { + if (!strcmp(predef_names[i].name, name)) return reg_get_predefined_key(ctx, predef_names[i].handle, key); } - DEBUG(1, ("No hive with name '%s'\n", name)); + DEBUG(1, ("No predefined key with name '%s'\n", name)); return WERR_BADFILE; } @@ -134,12 +134,12 @@ WERROR reg_close (struct registry_context *ctx) return WERR_OK; } -WERROR reg_get_hive(struct registry_context *ctx, enum reg_predefined_key hkey, struct registry_key **key) +WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key) { - WERROR ret = ctx->get_hive(ctx, hkey, key); + WERROR ret = ctx->get_predefined_key(ctx, hkey, key); if (W_ERROR_IS_OK(ret)) { - (*key)->name = talloc_strdup(*key, reg_get_hkey_name(hkey)); + (*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey)); (*key)->path = ""; } @@ -147,7 +147,7 @@ WERROR reg_get_hive(struct registry_context *ctx, enum reg_predefined_key hkey, } /* Open a registry file/host/etc */ -WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) +WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) { struct registry_hive *rethive; struct registry_key *retkey = NULL; @@ -169,7 +169,6 @@ WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, c rethive->location = location?talloc_strdup(rethive, location):NULL; rethive->functions = entry->hive_functions; rethive->backend_data = NULL; - rethive->reg_ctx = parent_ctx; werr = entry->hive_functions->open_hive(rethive, &retkey); @@ -193,26 +192,26 @@ WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, c return WERR_OK; } -/* Open a key by name (including the hive name!) */ +/* Open a key by name (including the predefined key name!) */ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) { - struct registry_key *hive; + struct registry_key *predef; WERROR error; - int hivelength; - char *hivename; + int predeflength; + char *predefname; - if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; - else hivelength = strlen(name); + if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name; + else predeflength = strlen(name); - hivename = strndup(name, hivelength); - error = reg_get_hive_by_name(handle, hivename, &hive); - SAFE_FREE(hivename); + predefname = strndup(name, predeflength); + error = reg_get_predefined_key_by_name(handle, predefname, &predef); + SAFE_FREE(predefname); if(!W_ERROR_IS_OK(error)) { return error; } - return reg_open_key(mem_ctx, hive, name, result); + return reg_open_key(mem_ctx, predef, name, result); } /* Open a key @@ -484,7 +483,7 @@ WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const cha else hivelength = strlen(name); hivename = strndup(name, hivelength); - error = reg_get_hive_by_name(handle, hivename, &hive); + error = reg_get_predefined_key_by_name(handle, hivename, &hive); SAFE_FREE(hivename); if(!W_ERROR_IS_OK(error)) return error; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 927ed7fcaa..78c45f6365 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -93,7 +93,7 @@ struct { static WERROR rpc_query_key(struct registry_key *k); -static WERROR rpc_get_hive (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k) +static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k) { int n; struct registry_hive *h; @@ -113,7 +113,6 @@ static WERROR rpc_get_hive (struct registry_context *ctx, uint32 hkey_type, stru h->functions = ®_backend_rpc; h->location = NULL; h->backend_data = ctx->backend_data; - h->reg_ctx = ctx; (*k) = h->root = talloc_p(h, struct registry_key); (*k)->hive = h; @@ -380,7 +379,7 @@ WERROR reg_open_remote (struct registry_context **ctx, const char *user, const c return ntstatus_to_werror(status); } - (*ctx)->get_hive = rpc_get_hive; + (*ctx)->get_predefined_key = rpc_get_predefined_key; talloc_set_destructor(*ctx, rpc_close); diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c index a19029524d..62973a14ab 100644 --- a/source4/lib/registry/reg_samba.c +++ b/source4/lib/registry/reg_samba.c @@ -23,12 +23,12 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY -static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, struct registry_key **k) +static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32 hkey, struct registry_key **k) { WERROR error; const char *conf; char *backend, *location; - const char *hivename = reg_get_hkey_name(hkey); + const char *hivename = reg_get_predef_name(hkey); *k = NULL; @@ -45,7 +45,18 @@ static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, str *location = '\0'; location++; } - + + /* FIXME: Different hive backend for HKEY_CLASSES_ROOT: merged view of HKEY_LOCAL_MACHINE\Software\Classes + * and HKEY_CURRENT_USER\Software\Classes */ + + /* FIXME: HKEY_CURRENT_CONFIG is an alias for HKEY_LOCAL_MACHINE\System\CurrentControlSet\Hardware Profiles\Current */ + + /* FIXME: HKEY_PERFORMANCE_DATA is dynamically generated */ + + /* FIXME: HKEY_LOCAL_MACHINE\Hardware is autogenerated */ + + /* FIXME: HKEY_LOCAL_MACHINE\Security\SAM is an alias for HKEY_LOCAL_MACHINE\SAM */ + error = reg_open_hive(ctx, backend, location, NULL, k); talloc_destroy(backend); @@ -56,7 +67,7 @@ static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, str WERROR reg_open_local (struct registry_context **ctx) { *ctx = talloc_p(NULL, struct registry_context); - (*ctx)->get_hive = reg_samba_get_hive; + (*ctx)->get_predefined_key = reg_samba_get_predef; return WERR_OK; } diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index dfa85d636f..8d88cafe59 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -175,15 +175,15 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) { struct registry_key *r1, *r2; - error = reg_get_hive(h1, i, &r1); + error = reg_get_predefined_key(h1, i, &r1); if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_hkey_name(i))); + DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i))); continue; } - error = reg_get_hive(h2, i, &r2); + error = reg_get_predefined_key(h2, i, &r2); if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_hkey_name(i))); + DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i))); continue; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 3fd9dab268..47d84c1f62 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -162,28 +162,6 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key * return NULL; } -static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) -{ - if (!cur->hive->reg_ctx) { - fprintf(stderr, "Only one hive loaded\n"); - return cur; - } - - if (argc == 1) { - printf("%s\n", cur->hive->root->name); - } else { - struct registry_key *newroot; - WERROR error = reg_get_hive_by_name(cur->hive->reg_ctx, argv[1], &newroot); - if (W_ERROR_IS_OK(error)) { - return newroot; - } else { - fprintf(stderr, "Can't switch to hive %s: %s\n", cur->hive->root->name, win_errstr(error)); - } - } - - return NULL; -} - static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { exit(0); @@ -199,7 +177,6 @@ struct { struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_key *, int argc, char **argv); } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, - {"ch", "hive", "Change current hive", cmd_hive }, {"info", "i", "Show detailed information of a key", cmd_info }, {"list", "ls", "List values/keys in current key", cmd_ls }, {"mkkey", "mkdir", "Make new key", cmd_mkkey }, @@ -407,7 +384,7 @@ static char **reg_completion(const char *text, int start, int end) if (h) { /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */ - reg_get_hive(h, HKEY_CLASSES_ROOT, &curkey); + reg_get_predefined_key(h, HKEY_CLASSES_ROOT, &curkey); } poptFreeContext(pc); diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 7adeeea731..a6beb2b484 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -124,9 +124,9 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) print_tree(0, root, fullpath, no_values); } else { for(i = HKEY_CLASSES_ROOT; i < HKEY_PERFORMANCE_NLSTEXT; i++) { - error = reg_get_hive(h, i, &root); + error = reg_get_predefined_key(h, i, &root); if (!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Skipping %s\n", reg_get_hkey_name(i)); + fprintf(stderr, "Skipping %s\n", reg_get_predef_name(i)); continue; } print_tree(0, root, fullpath, no_values); -- cgit From 47fa1d33e4a6b9aeaf06ad2c12d9744bdf967bb9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 13 Dec 2004 00:45:29 +0000 Subject: r4166: More small API fixes, keep registry structs as small as possible. Implement DelValue in the RPC server (This used to be commit f6b9ec89af934e837069fb26c0e3491fc78ebc12) --- source4/lib/registry/common/reg_interface.c | 13 ++++--------- source4/lib/registry/reg_backend_dir.c | 16 +--------------- source4/lib/registry/reg_backend_ldb.c | 2 +- source4/lib/registry/reg_backend_rpc.c | 1 - source4/lib/registry/reg_backend_w95.c | 1 - source4/lib/registry/tools/regpatch.c | 6 +----- source4/lib/registry/tools/regshell.c | 8 +------- 7 files changed, 8 insertions(+), 39 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index ee140e150f..79bb0b765c 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -281,8 +281,6 @@ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_NOT_SUPPORTED; } - (*val)->parent = key; - (*val)->hive = key->hive; return WERR_OK; } @@ -408,9 +406,6 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return error; - (*val)->parent = key; - (*val)->hive = key->hive; - return WERR_OK; } @@ -447,7 +442,7 @@ WERROR reg_key_del_recursive(struct registry_key *key) } if(W_ERROR_IS_OK(error)) { - error = reg_del_value(val); + error = reg_del_value(key, val->name); if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; @@ -564,13 +559,13 @@ WERROR reg_val_set(struct registry_key *key, const char *value, int type, void * -WERROR reg_del_value(struct registry_value *val) +WERROR reg_del_value(struct registry_key *key, const char *valname) { WERROR ret = WERR_OK; - if(!val->hive->functions->del_value) + if(!key->hive->functions->del_value) return WERR_NOT_SUPPORTED; - ret = val->hive->functions->del_value(val); + ret = key->hive->functions->del_value(key, valname); if(!W_ERROR_IS_OK(ret)) return ret; diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index c004be5a06..89f9280585 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -120,27 +120,13 @@ static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key) return WERR_OK; } -static WERROR reg_dir_set_value(struct registry_key *p, const char *name, int type, void *data, int len) -{ - /* FIXME */ - return WERR_NOT_SUPPORTED; -} - -static WERROR reg_dir_del_value(struct registry_value *v) -{ - /* FIXME*/ - return WERR_NOT_SUPPORTED; -} - static struct hive_operations reg_backend_dir = { .name = "dir", .open_hive = reg_dir_open, .open_key = reg_dir_open_key, .add_key = reg_dir_add_key, .del_key = reg_dir_del_key, - .get_subkey_by_index = reg_dir_key_by_index, - .set_value = reg_dir_set_value, - .del_value = reg_dir_del_value, + .get_subkey_by_index = reg_dir_key_by_index }; NTSTATUS registry_dir_init(void) diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index e848507634..ec8a6d9de3 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -144,7 +144,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i *value = talloc_p(mem_ctx, struct registry_value); (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*value)->backend_data = talloc_strdup(mem_ctx, kd->values[idx]->dn); + /* FIXME */ return WERR_OK; } diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 78c45f6365..16516d25b7 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -218,7 +218,6 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result) && r.out.length) { *value = talloc_p(mem_ctx, struct registry_value); - (*value)->parent = parent; (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); (*value)->data_type = type; (*value)->data_len = *r.out.length; diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index a94ad86c2c..957039dea3 100644 --- a/source4/lib/registry/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -332,7 +332,6 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i } *value = talloc_p(mem_ctx, struct registry_value); - (*value)->backend_data = curval; (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); (*value)->data_len = curval->data_len; diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index a4a4649c96..18589a9285 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -701,13 +701,9 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd while (cmd->val_count) { VAL_SPEC_LIST *val = cmd->val_spec_list; - struct registry_value *reg_val = NULL; if (val->type == REG_DELETE) { - error = reg_key_get_value_by_name( mem_ctx, tmp, val->name, ®_val); - if(W_ERROR_IS_OK(error)) { - error = reg_del_value(reg_val); - } + error = reg_del_value(tmp, val->name); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Error removing value '%s'\n", val->name)); } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 47d84c1f62..0a09708869 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -142,18 +142,12 @@ static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key * static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - struct registry_value *val; if(argc < 2) { fprintf(stderr, "Usage: rmval \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_key_get_value_by_name(mem_ctx, cur, argv[1], &val))) { - fprintf(stderr, "No such value '%s'\n", argv[1]); - return NULL; - } - - if(!W_ERROR_IS_OK(reg_del_value(val))) { + if(!W_ERROR_IS_OK(reg_del_value(cur, argv[1]))) { fprintf(stderr, "Error deleting value '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); -- cgit From 4c202a20fa7008264ad676ffb2238424bd27baf8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 13 Dec 2004 01:37:18 +0000 Subject: r4167: Fix CreateKey Support CreateKey in the RPC registry backend (This used to be commit ad8d9e6f73619332d93c38a1879233e199e8ba25) --- source4/lib/registry/reg_backend_rpc.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 16516d25b7..b14b67d609 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -259,7 +259,32 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key * static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) { - return WERR_NOT_SUPPORTED; + NTSTATUS status; + struct winreg_CreateKey r; + + init_winreg_String(&r.in.key, name); + init_winreg_String(&r.in.class, NULL); + + r.in.handle = parent->backend_data; + r.out.handle = talloc_p(mem_ctx, struct policy_handle); + r.in.options = 0; + r.in.access_mask = access_mask; + r.in.sec_desc = NULL; + + status = dcerpc_winreg_CreateKey((struct dcerpc_pipe *)(parent->hive->backend_data), mem_ctx, &r); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + if (W_ERROR_IS_OK(r.out.result)) { + *key = talloc_p(mem_ctx, struct registry_key); + (*key)->name = talloc_strdup(*key, name); + (*key)->backend_data = r.out.handle; + } + + return r.out.result; } static WERROR rpc_query_key(struct registry_key *k) -- cgit From 5bb1939e9e65e6b0c27310e412bfa94d67ee977e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 14 Dec 2004 06:09:04 +0000 Subject: r4197: Remove silly extra const. (This used to be commit fcbfa888defe4f904e0c4b4f723d53a03422ad80) --- source4/lib/crypto/md5.c | 2 +- source4/lib/crypto/md5.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/crypto/md5.c b/source4/lib/crypto/md5.c index 38ef3fdfbd..f59b35a0b8 100644 --- a/source4/lib/crypto/md5.c +++ b/source4/lib/crypto/md5.c @@ -58,7 +58,7 @@ void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(struct MD5Context *ctx, const uint8_t const *buf, uint_t len) +void MD5Update(struct MD5Context *ctx, const uint8_t *buf, uint_t len) { register uint32_t t; diff --git a/source4/lib/crypto/md5.h b/source4/lib/crypto/md5.h index a622cf232a..51aa5e4ca5 100644 --- a/source4/lib/crypto/md5.h +++ b/source4/lib/crypto/md5.h @@ -12,7 +12,7 @@ struct MD5Context { }; void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, const uint8_t const *buf, +void MD5Update(struct MD5Context *context, const uint8_t *buf, uint_t len); void MD5Final(uint8_t digest[16], struct MD5Context *context); -- cgit From 1a340869c43f9ce741e8a4bd28ea01ec63301df5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 14 Dec 2004 20:49:18 +0000 Subject: r4204: Arguments to reg_del_key more like the RPC for more efficient usage Fix small bug in regpatch Fix segfault in regshell cmdline completion Implement set_value and del_value in ldb backend (This used to be commit 8e2aa58abeafa78afe7dafb9723f5f365e756527) --- source4/lib/registry/common/reg_interface.c | 155 +--------------------------- source4/lib/registry/common/reg_util.c | 87 ++++++++++++++++ source4/lib/registry/reg_backend_dir.c | 11 +- source4/lib/registry/reg_backend_ldb.c | 62 ++++++++++- source4/lib/registry/reg_backend_rpc.c | 18 +--- source4/lib/registry/tools/regpatch.c | 16 +-- source4/lib/registry/tools/regshell.c | 15 +-- 7 files changed, 172 insertions(+), 192 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 79bb0b765c..c729945a26 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -192,28 +192,6 @@ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *lo return WERR_OK; } -/* Open a key by name (including the predefined key name!) */ -WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) -{ - struct registry_key *predef; - WERROR error; - int predeflength; - char *predefname; - - if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name; - else predeflength = strlen(name); - - predefname = strndup(name, predeflength); - error = reg_get_predefined_key_by_name(handle, predefname, &predef); - SAFE_FREE(predefname); - - if(!W_ERROR_IS_OK(error)) { - return error; - } - - return reg_open_key(mem_ctx, predef, name, result); -} - /* Open a key * First tries to use the open_key function from the backend * then falls back to get_subkey_by_name and later get_subkey_by_index @@ -409,123 +387,21 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_OK; } -WERROR reg_key_del(struct registry_key *key) +WERROR reg_key_del(struct registry_key *parent, const char *name) { WERROR error; - if(!key) return WERR_INVALID_PARAM; + if(!parent) return WERR_INVALID_PARAM; - if(!key->hive->functions->del_key) + if(!parent->hive->functions->del_key) return WERR_NOT_SUPPORTED; - error = key->hive->functions->del_key(key); + error = parent->hive->functions->del_key(parent, name); if(!W_ERROR_IS_OK(error)) return error; return WERR_OK; } -WERROR reg_key_del_recursive(struct registry_key *key) -{ - WERROR error = WERR_OK; - int i; - - TALLOC_CTX *mem_ctx = talloc_init("del_recursive"); - - /* Delete all values for specified key */ - for(i = 0; W_ERROR_IS_OK(error); i++) { - struct registry_value *val; - error = reg_key_get_value_by_index(mem_ctx, key, i, &val); - if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) - { - talloc_destroy(mem_ctx); - return error; - } - - if(W_ERROR_IS_OK(error)) { - error = reg_del_value(key, val->name); - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } - } - } - - error = WERR_OK; - - /* Delete all keys below this one */ - for(i = 0; W_ERROR_IS_OK(error); i++) { - struct registry_key *subkey; - - error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey); - if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } - - error = reg_key_del_recursive(subkey); - if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } - } - - talloc_destroy(mem_ctx); - return reg_key_del(key); -} - -WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name) -{ - struct registry_key *hive; - WERROR error; - int hivelength; - char *hivename; - - if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; - else hivelength = strlen(name); - - hivename = strndup(name, hivelength); - error = reg_get_predefined_key_by_name(handle, hivename, &hive); - SAFE_FREE(hivename); - - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_add_name_recursive(hive, name); -} - -WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) -{ - struct registry_key *cur, *prevcur = parent; - WERROR error = WERR_OK; - char *dups, *begin, *end; - TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); - - begin = dups = strdup(path); - - while(1) { - end = strchr(begin, '\\'); - if(end) *end = '\0'; - - error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur); - - /* Key is not there, add it */ - if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur); - if(!W_ERROR_IS_OK(error)) break; - } - - if(!W_ERROR_IS_OK(error)) { - if(end) *end = '\\'; - break; - } - - if(!end) { - error = WERR_OK; - break; - } - - *end = '\\'; - begin = end+1; - prevcur = cur; - } - SAFE_FREE(dups); - talloc_destroy(mem_ctx); - return error; -} - WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey) { WERROR error; @@ -547,7 +423,7 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const return WERR_OK; } -WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, uint32 type, void *data, int len) { /* A 'real' set function has preference */ if (key->hive->functions->set_value) @@ -577,27 +453,6 @@ WERROR reg_save (struct registry_context *ctx, const char *location) return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent) -{ - char *parent_name; - char *last; - struct registry_key *root = NULL; - WERROR error; - - parent_name = strdup(key->path); - last = strrchr(parent_name, '\\'); - - if(!last) { - SAFE_FREE(parent_name); - return WERR_FOOBAR; - } - *last = '\0'; - - error = reg_open_key(mem_ctx, root, parent_name, parent); - SAFE_FREE(parent_name); - return error; -} - WERROR reg_key_flush(struct registry_key *key) { if (!key) { diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 052ccc347b..1d1f770324 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -150,3 +150,90 @@ char *reg_path_unix2win(char *path) } return path; } + +/* Open a key by name (including the predefined key name!) */ +WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) +{ + struct registry_key *predef; + WERROR error; + int predeflength; + char *predefname; + + if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name; + else predeflength = strlen(name); + + predefname = strndup(name, predeflength); + error = reg_get_predefined_key_by_name(handle, predefname, &predef); + SAFE_FREE(predefname); + + if(!W_ERROR_IS_OK(error)) { + return error; + } + + if (strchr(name, '\\')) { + return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, result); + } else { + *result = predef; + return WERR_OK; + } +} + +static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name) +{ + char *parent_name; + WERROR error; + + if (strchr(path, '\\') == NULL) { + return WERR_FOOBAR; + } + + parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path); + + error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent); + if (!W_ERROR_IS_OK(error)) { + return error; + } + + *name = talloc_strdup(mem_ctx, strchr(path, '\\')+1); + + return WERR_OK; +} + +WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) +{ + struct registry_key *parent; + const char *n; + TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs"); + WERROR error; + + if (!strchr(path, '\\')) { + return WERR_FOOBAR; + } + + error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); + if (W_ERROR_IS_OK(error)) { + error = reg_key_del(parent, n); + } + + talloc_destroy(mem_ctx); + + return error; +} + +WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, SEC_DESC *sec_desc, struct registry_key **result) +{ + struct registry_key *parent; + const char *n; + WERROR error; + + if (!strchr(path, '\\')) { + return WERR_FOOBAR; + } + + error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); + if (W_ERROR_IS_OK(error)) { + error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result); + } + + return error; +} diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 89f9280585..41a0da58c0 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -34,9 +34,16 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, return WERR_INVALID_PARAM; } -static WERROR reg_dir_del_key(struct registry_key *k) +static WERROR reg_dir_del_key(struct registry_key *k, const char *name) { - return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; + char *child = talloc_asprintf(NULL, "%s/%s", (char *)k->backend_data, name); + WERROR ret; + + if (rmdir(child) == 0) ret = WERR_OK; else ret = WERR_GENERAL_FAILURE; + + talloc_destroy(child); + + return ret; } static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, struct registry_key **subkey) diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index ec8a6d9de3..7a63f4a530 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -235,12 +235,15 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con return WERR_OK; } -static WERROR ldb_del_key (struct registry_key *key) +static WERROR ldb_del_key (struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; + char *childdn = talloc_asprintf(NULL, "key=%s,%s", child, kd->dn); - ret = ldb_delete(key->hive->backend_data, kd->dn); + ret = ldb_delete(key->hive->backend_data, childdn); + + talloc_destroy(childdn); if (ret < 0) { DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); @@ -250,6 +253,59 @@ static WERROR ldb_del_key (struct registry_key *key) return WERR_OK; } +static WERROR ldb_del_value (struct registry_key *key, const char *child) +{ + int ret; + struct ldb_key_data *kd = key->backend_data; + char *childdn = talloc_asprintf(NULL, "value=%s,%s", child, kd->dn); + + ret = ldb_delete(key->hive->backend_data, childdn); + + talloc_destroy(childdn); + + if (ret < 0) { + DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data))); + return WERR_FOOBAR; + } + + return WERR_OK; +} + +static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len) +{ + struct ldb_context *ctx = parent->hive->backend_data; + struct ldb_message msg; + struct ldb_val val; + int ret; + char *type_s; + TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); + + ZERO_STRUCT(msg); + + msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "value=%s,", name)); + + ldb_msg_add_string(ctx, &msg, "value", talloc_strdup(mem_ctx, name)); + val.length = len; + val.data = data; + ldb_msg_add_value(ctx, &msg, "data", &val); + + type_s = talloc_asprintf(mem_ctx, "%u", type); + ldb_msg_add_string(ctx, &msg, "type", type_s); + + ret = ldb_add(ctx, &msg); + if (ret < 0) { + ret = ldb_modify(ctx, &msg); + if (ret < 0) { + DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); + talloc_destroy(mem_ctx); + return WERR_FOOBAR; + } + } + + talloc_destroy(mem_ctx); + return WERR_OK; +} + static struct hive_operations reg_backend_ldb = { .name = "ldb", .add_key = ldb_add_key, @@ -258,6 +314,8 @@ static struct hive_operations reg_backend_ldb = { .open_key = ldb_open_key, .get_value_by_index = ldb_get_value_by_id, .get_subkey_by_index = ldb_get_subkey_by_id, + .set_value = ldb_set_value, + .del_value = ldb_del_value, }; NTSTATUS registry_ldb_init(void) diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index b14b67d609..224a061762 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -315,27 +315,17 @@ static WERROR rpc_query_key(struct registry_key *k) return r.out.result; } -static WERROR rpc_del_key(struct registry_key *k) +static WERROR rpc_del_key(struct registry_key *parent, const char *name) { NTSTATUS status; - struct rpc_key_data *mykeydata = k->backend_data; + struct rpc_key_data *mykeydata = parent->backend_data; struct winreg_DeleteKey r; - struct registry_key *parent; - WERROR error; TALLOC_CTX *mem_ctx = talloc_init("del_key"); - error = reg_key_get_parent(mem_ctx, k, &parent); - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } - - mykeydata = parent->backend_data; - r.in.handle = &mykeydata->pol; - init_winreg_String(&r.in.key, k->name); + init_winreg_String(&r.in.key, name); - status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); talloc_destroy(mem_ctx); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 18589a9285..600c1f60e7 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -686,13 +686,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd /* If we found it, apply the other bits, else create such a key */ if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) { - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key)); - continue; - } - } else { + if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) { DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); continue; } @@ -730,13 +724,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd * Find the key if it exists, and delete it ... */ - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); - continue; - } - - error = reg_key_del_recursive(tmp); + error = reg_key_del_abs(r, cmd->key); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to delete key '%s'\n", cmd->key)); continue; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 0a09708869..6de8b25c9c 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -120,18 +120,12 @@ static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key * static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - struct registry_key *key; if(argc < 2) { fprintf(stderr, "Usage: rmkey \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) { - fprintf(stderr, "No such subkey '%s'\n", argv[1]); - return NULL; - } - - if(!W_ERROR_IS_OK(reg_key_del(key))) { + if(!W_ERROR_IS_OK(reg_key_del(cur, argv[1]))) { fprintf(stderr, "Error deleting '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted '%s'\n", argv[1]); @@ -259,9 +253,10 @@ static char **reg_complete_command(const char *text, int end) return matches; cleanup: - while (i >= 0) { - free(matches[i]); - i--; + count--; + while (count >= 0) { + free(matches[count]); + count--; } free(matches); return NULL; -- cgit From d8c3428b3bb10075cec3b37adbca54db634d3b00 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 15 Dec 2004 00:16:54 +0000 Subject: r4209: Fix several smaller bugs Add "predef" and "set" commands in regshell Some of the remote calls from a Windows box work now. (This used to be commit f3e05782804fe4b4942fa966f1b9650c64bc234d) --- source4/lib/registry/common/reg_interface.c | 9 ++- source4/lib/registry/common/reg_util.c | 67 ++++++++++++++++++--- source4/lib/registry/reg_backend_dir.c | 2 +- source4/lib/registry/reg_backend_ldb.c | 48 +++++++-------- source4/lib/registry/reg_backend_nt4.c | 7 ++- source4/lib/registry/reg_backend_rpc.c | 2 +- source4/lib/registry/tools/regshell.c | 92 ++++++++++++++++++++--------- 7 files changed, 160 insertions(+), 67 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index c729945a26..f5c3598721 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -348,9 +348,12 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { - return error; + break; } } + + if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + error = WERR_DEST_NOT_FOUND; } else { return WERR_NOT_SUPPORTED; } @@ -375,7 +378,7 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, } else { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_value_by_index(mem_ctx, key, i, val); - if(W_ERROR_IS_OK(error) && StrCaseCmp((*val)->name, name)) { + if(W_ERROR_IS_OK(error) && !strcmp((*val)->name, name)) { break; } } @@ -402,7 +405,7 @@ WERROR reg_key_del(struct registry_key *parent, const char *name) return WERR_OK; } -WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey) +WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey) { WERROR error; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 1d1f770324..68144fc56f 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -24,14 +24,27 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY +static const struct { + uint32 id; + const char *name; +} reg_value_types[] = { + { REG_SZ, "REG_SZ" }, + { REG_DWORD, "REG_DWORD" }, + { REG_BINARY, "REG_BINARY" }, + { REG_EXPAND_SZ, "REG_EXPAND_SZ" }, + { REG_NONE, "REG_NONE" }, + { 0, NULL } +}; + /* Return string description of registry value type */ const char *str_regtype(int type) { - switch(type) { - case REG_SZ: return "STRING"; - case REG_DWORD: return "DWORD"; - case REG_BINARY: return "BINARY"; + int i; + for (i = 0; reg_value_types[i].name; i++) { + if (reg_value_types[i].id == type) + return reg_value_types[i].name; } + return "Unknown"; } @@ -84,10 +97,48 @@ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); } -BOOL reg_val_set_string(struct registry_value *val, char *str) +BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value) { - /* FIXME */ - return False; + int i; + *value = talloc_p(mem_ctx, struct registry_value); + (*value)->data_type = -1; + + /* Find the correct type */ + for (i = 0; reg_value_types[i].name; i++) { + if (!strcmp(reg_value_types[i].name, type_str)) { + (*value)->data_type = reg_value_types[i].id; + break; + } + } + + if ((*value)->data_type == -1) + return False; + + /* Convert data appropriately */ + + switch ((*value)->data_type) + { + case REG_SZ: + case REG_EXPAND_SZ: + (*value)->data_blk = talloc_strdup(mem_ctx, data_str); + (*value)->data_len = strlen(data_str); + break; + case REG_DWORD: + (*value)->data_len = sizeof(uint32); + (*value)->data_blk = talloc_p(mem_ctx, uint32); + *((uint32 *)(*value)->data_blk) = atol(data_str); + break; + + case REG_NONE: + (*value)->data_len = 0; + (*value)->data_blk = NULL; + break; + + default: + case REG_BINARY: /* FIXME */ + return False; + } + return True; } WERROR reg_key_get_subkey_val(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *subname, const char *valname, struct registry_value **val) @@ -220,7 +271,7 @@ WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) return error; } -WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, SEC_DESC *sec_desc, struct registry_key **result) +WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, struct security_descriptor *sec_desc, struct registry_key **result) { struct registry_key *parent; const char *n; diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 41a0da58c0..4af219facb 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -22,7 +22,7 @@ #include "registry.h" #include "system/dir.h" -static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **result) +static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result) { char *path; int ret; diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 7a63f4a530..9b0b5759ce 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -56,18 +56,19 @@ static int reg_close_ldb_key (void *data) return 0; } -static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char *add) +static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, const char *path, const char *add) { char *ret = talloc_strdup(mem_ctx, ""); - char *mypath = strdup(path); - char *end = mypath, *begin; + char *mypath = talloc_strdup(mem_ctx, path); + char *begin; + struct ldb_key_data *kd = from->backend_data; if(add) ret = talloc_asprintf_append(ret, "%s", add); - while(end) { + while(mypath) { char *keyname; - begin = strrchr(end, '\\'); + begin = strrchr(mypath, '\\'); if(begin) keyname = begin + 1; else keyname = mypath; @@ -77,18 +78,13 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const char *path, const char * if(begin) { *begin = '\0'; - end = begin-1; } else { - end = NULL; + break; } } - SAFE_FREE(mypath); + ret = talloc_asprintf_append(ret, "%s", kd->dn); - ret[strlen(ret)-1] = '\0'; - - if(strlen(ret) == 0) return NULL; - return ret; } @@ -127,6 +123,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i struct ldb_context *c = k->hive->backend_data; struct ldb_message_element *el; struct ldb_key_data *kd = k->backend_data; + const struct ldb_val *val; /* Do the search if necessary */ if (kd->values == NULL) { @@ -144,7 +141,10 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i *value = talloc_p(mem_ctx, struct registry_value); (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); - /* FIXME */ + (*value)->data_type = ldb_msg_find_uint(kd->values[idx], "type", 0); + val = ldb_msg_find_ldb_val(kd->values[idx], "data"); + (*value)->data_blk = talloc_memdup(mem_ctx, val->data, val->length); + (*value)->data_len = val->length; return WERR_OK; } @@ -155,11 +155,9 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch struct ldb_message **msg; char *ldap_path; int ret; - struct ldb_key_data *kd = h->backend_data, *newkd; - ldap_path = talloc_asprintf(mem_ctx, "%s%s%s", - reg_path_to_ldb(mem_ctx, name, NULL), - kd->dn?",":"", - kd->dn?kd->dn:""); + struct ldb_key_data *newkd; + + ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL); ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); @@ -185,9 +183,12 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) { struct ldb_context *c; struct ldb_key_data *kd; + struct ldb_wrap *wrap; if (!hive->location) return WERR_INVALID_PARAM; - c = ldb_connect(hive->location, 0, NULL); + wrap = ldb_wrap_connect(hive, hive->location, 0, NULL); + + c = wrap->ldb; if(!c) { DEBUG(1, ("ldb_open_hive: %s\n", ldb_errstring(hive->backend_data))); @@ -201,13 +202,13 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) talloc_set_destructor (hive, ldb_close_hive); (*k)->name = talloc_strdup(*k, ""); (*k)->backend_data = kd = talloc_zero_p(*k, struct ldb_key_data); - kd->dn = talloc_strdup(*k, "key=root"); + kd->dn = talloc_strdup(*k, "hive="); return WERR_OK; } -static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sd, struct registry_key **newkey) +static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey) { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message msg; @@ -216,7 +217,7 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con ZERO_STRUCT(msg); - msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "key=%s,", name)); + msg.dn = reg_path_to_ldb(mem_ctx, parent, name, NULL); ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name)); @@ -276,13 +277,14 @@ static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message msg; struct ldb_val val; + struct ldb_key_data *kd = parent->backend_data; int ret; char *type_s; TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); ZERO_STRUCT(msg); - msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "value=%s,", name)); + msg.dn = talloc_asprintf(mem_ctx, "value=%s,%s", name, kd->dn); ldb_msg_add_string(ctx, &msg, "value", talloc_strdup(mem_ctx, name)); val.length = len; diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 117d8d1b81..5633156b20 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -64,7 +64,8 @@ marked with ???? the rest of the first 4kb page is not important... the "hbin"-Block ================ -I don't know what "hbin" stands for, but this block is always a multiple +hbin probably means hive-bin (what bin stands for I don't know) +This block is always a multiple of 4kb in size. Inside these hbin-blocks the different records are placed. The memory- @@ -419,7 +420,7 @@ typedef struct key_sec_desc_s { int state; int offset; SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ - SEC_DESC *sec_desc; + struct security_descriptor *sec_desc; } KEY_SEC_DESC; /* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ @@ -481,7 +482,7 @@ typedef struct regf_struct_s { int sk_count, sk_map_size; SK_MAP *sk_map; const char *owner_sid_str; - SEC_DESC *def_sec_desc; + struct security_descriptor *def_sec_desc; /* * These next pointers point to the blocks used to contain the * keys when we are preparing to write them to a file diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 224a061762..c5ed9b2c88 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -257,7 +257,7 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key * return r.out.result; } -static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *sec, struct registry_key **key) +static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key) { NTSTATUS status; struct winreg_CreateKey r; diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 6de8b25c9c..1dd0e04561 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -37,7 +37,7 @@ * exit */ -static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { time_t last_mod; printf("Name: %s\n", cur->name); @@ -49,19 +49,50 @@ static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_key *c return cur; } -static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_predef(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv) +{ + struct registry_key *ret = NULL; + if (argc < 2) { + fprintf(stderr, "Usage: predef predefined-key-name\n"); + } else if (!ctx) { + fprintf(stderr, "No full registry loaded, no predefined keys defined\n"); + } else { + WERROR error = reg_get_predefined_key_by_name(ctx, argv[1], &ret); + + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error opening predefined key %s: %s\n", argv[1], win_errstr(error)); + ret = NULL; + } + } + return ret; +} + +static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { printf("%s\n", cur->path); return cur; } -static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { - /* FIXME */ - return NULL; + if (argc < 4) { + fprintf(stderr, "Usage: set value-name type value\n"); + } else { + struct registry_value *val; + if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val)) { + WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data_blk, val->data_len); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error setting value: %s\n", win_errstr(error)); + return NULL; + } + } else { + fprintf(stderr, "Unable to interpret data\n"); + } + } + return cur; } -static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { struct registry_key *new = NULL; WERROR error; @@ -80,7 +111,7 @@ static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur return new; } -static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { int i; WERROR error; @@ -100,7 +131,7 @@ static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur return NULL; } -static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { struct registry_key *tmp; if(argc < 2) { @@ -113,12 +144,10 @@ static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key * return NULL; } - fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], cur->path); - return NULL; } -static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { if(argc < 2) { fprintf(stderr, "Usage: rmkey \n"); @@ -134,7 +163,7 @@ static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key * return NULL; } -static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { if(argc < 2) { fprintf(stderr, "Usage: rmval \n"); @@ -150,19 +179,19 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key * return NULL; } -static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { exit(0); return NULL; } -static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *, int, char **); +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int, char **); struct { const char *name; const char *alias; const char *help; - struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_key *, int argc, char **argv); + struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int argc, char **argv); } regshell_cmds[] = { {"ck", "cd", "Change current key", cmd_ck }, {"info", "i", "Show detailed information of a key", cmd_info }, @@ -174,10 +203,11 @@ struct { {"set", "update", "Update value", cmd_set }, {"help", "?", "Help", cmd_help }, {"exit", "quit", "Exit", cmd_exit }, + {"predef", "predefined", "Go to predefined key", cmd_predef }, {NULL } }; -static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) +static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv) { int i; printf("Available commands:\n"); @@ -187,7 +217,7 @@ static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *c return NULL; } -static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key *k, char *line) +static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *k, char *line) { int argc; char **argv = NULL; @@ -201,7 +231,7 @@ static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key for(i = 0; regshell_cmds[i].name; i++) { if(!strcmp(regshell_cmds[i].name, argv[0]) || (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) { - return regshell_cmds[i].handle(mem_ctx, k, argc, argv); + return regshell_cmds[i].handle(mem_ctx, ctx, k, argc, argv); } } @@ -214,7 +244,7 @@ static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key static struct registry_key *current_key = NULL; -static char **reg_complete_command(const char *text, int end) +static char **reg_complete_command(const char *text, int start, int end) { /* Complete command */ char **matches; @@ -262,23 +292,28 @@ cleanup: return NULL; } -static char **reg_complete_key(const char *text, int end) +static char **reg_complete_key(const char *text, int start, int end) { + struct registry_key *base; struct registry_key *subkey; int i, j = 1; int samelen = 0; int len; char **matches; + const char *base_n = ""; TALLOC_CTX *mem_ctx; + WERROR status; matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; matches[0] = NULL; + mem_ctx = talloc_init("completion"); + + base = current_key; len = strlen(text); - mem_ctx = talloc_init("completion"); for(i = 0; j < MAX_COMPLETIONS-1; i++) { - WERROR status = reg_key_get_subkey_by_index(mem_ctx, current_key, i, &subkey); + status = reg_key_get_subkey_by_index(mem_ctx, base, i, &subkey); if(W_ERROR_IS_OK(status)) { if(!strncmp(text, subkey->name, len)) { matches[j] = strdup(subkey->name); @@ -298,18 +333,19 @@ static char **reg_complete_key(const char *text, int end) return NULL; } } - talloc_destroy(mem_ctx); if (j == 1) { /* No matches at all */ SAFE_FREE(matches); + talloc_destroy(mem_ctx); return NULL; } if (j == 2) { /* Exact match */ - matches[0] = strdup(matches[1]); + asprintf(&matches[0], "%s%s", base_n, matches[1]); } else { - matches[0] = strndup(matches[1], samelen); + asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen)); } + talloc_destroy(mem_ctx); matches[j] = NULL; return matches; @@ -320,9 +356,9 @@ static char **reg_completion(const char *text, int start, int end) smb_readline_ca_char(' '); if (start == 0) { - return reg_complete_command(text, end); + return reg_complete_command(text, start, end); } else { - return reg_complete_key(text, end); + return reg_complete_key(text, start, end); } } @@ -395,7 +431,7 @@ static char **reg_completion(const char *text, int start, int end) break; if(line[0] != '\n') { - struct registry_key *new = process_cmd(mem_ctx, curkey, line); + struct registry_key *new = process_cmd(mem_ctx, h, curkey, line); if(new)curkey = new; } } -- cgit From efdf83f4a676d8c8faa66e3c073c72a0d649bde8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 15 Dec 2004 02:27:22 +0000 Subject: r4213: Store REG_SZ in UTF16, not the unix charset.. It is now possible to use the "Add..." button in the Security tab of the File Properties Dialog box. (This used to be commit 9fa25260d3f18dd0dd041477c48571b53d86f3c4) --- source4/lib/registry/common/reg_util.c | 10 ++++------ source4/lib/registry/reg_backend_nt4.c | 7 ------- 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 68144fc56f..3da875ca0b 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -57,11 +57,10 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) if(v->data_len == 0) return talloc_strdup(mem_ctx, ""); switch (v->data_type) { - case REG_SZ: - return talloc_strndup(mem_ctx, v->data_blk, v->data_len); - case REG_EXPAND_SZ: - return talloc_strndup(mem_ctx, v->data_blk, v->data_len); + case REG_SZ: + convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data_blk, v->data_len, (void **)&ret); + return ret; case REG_BINARY: ret = talloc(mem_ctx, v->data_len * 3 + 2); @@ -120,8 +119,7 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da { case REG_SZ: case REG_EXPAND_SZ: - (*value)->data_blk = talloc_strdup(mem_ctx, data_str); - (*value)->data_len = strlen(data_str); + (*value)->data_len = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), &(*value)->data_blk); break; case REG_DWORD: (*value)->data_len = sizeof(uint32); diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 5633156b20..6c48b9bd1b 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -935,13 +935,6 @@ static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR } - if(tmp->data_type == REG_SZ) { - char *ret; - dat_len = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, dtmp, dat_len, (void **)&ret); - dtmp = ret; - } - - tmp->data_blk = dtmp; tmp->data_len = dat_len; } -- cgit From b02c5abfb470575a67ced192b2913b5a1c73dd3e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Dec 2004 01:16:04 +0000 Subject: r4262: a sniff from kukks showed that the FILE_ATTRIBUTE_NORMAL handling in pvfs was not correct. This should fix a xcopy bug on OS/2. (This used to be commit 7251f1fcdd8980e9c49a58e665374025e07bb8d0) --- source4/lib/util_str.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 9fd6dd5356..82481cca26 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1120,6 +1120,7 @@ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) {'A', FILE_ATTRIBUTE_ARCHIVE}, {'H', FILE_ATTRIBUTE_HIDDEN}, {'S', FILE_ATTRIBUTE_SYSTEM}, + {'N', FILE_ATTRIBUTE_NORMAL}, {'R', FILE_ATTRIBUTE_READONLY}, {'d', FILE_ATTRIBUTE_DEVICE}, {'t', FILE_ATTRIBUTE_TEMPORARY}, -- cgit From ed42a64901ba0a7ad8cbaac582600688af1b7d72 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Dec 2004 04:38:43 +0000 Subject: r4263: added support for the trans2 RAW_SEARCH_EA_LIST information level. This is quite a strange level that we've never seen before, but is used by the os2 workplace shell. note w2k screws up this level when unicode is negotiated, so it only passes the RAW-SEARCH test when you force non-unicode (This used to be commit 25189b8fbf6515d573e3398dc9fca56505dc37b9) --- source4/lib/data_blob.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index a4506fee45..1551879933 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -160,3 +160,16 @@ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) return hex_string; } + +/* + useful for constructing data blobs in test suites, while + avoiding const warnings +*/ +DATA_BLOB data_blob_string_const(const char *str) +{ + DATA_BLOB blob; + blob.data = discard_const(str); + blob.length = strlen(str); + return blob; +} + -- cgit From 469fd3868b9538715cf8d8c845e68232b54d2fa6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Dec 2004 00:13:24 +0000 Subject: r4267: fixed the charset code to use the builtin_functions. Jelmer, please be more careful about testing new code. Your charsets register change completely broke charset handling on systems without iconv, and slowed every system down as the builtins were not being used at all. (This used to be commit 0022b4d24c7bb649fd69fffca04c022ea6b33634) --- source4/lib/iconv.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 045ed36320..181834d66a 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -67,8 +67,7 @@ static const struct charset_functions builtin_functions[] = { {"UTF8", utf8_pull, utf8_push}, {"UTF-8", utf8_pull, utf8_push}, {"ASCII", ascii_pull, ascii_push}, - {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, - {NULL, NULL, NULL} + {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} }; static struct charset_functions *charsets = NULL; @@ -161,10 +160,8 @@ static BOOL is_utf16(const char *name) smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) { smb_iconv_t ret; - struct charset_functions *from, *to; - - from = charsets; - to = charsets; + const struct charset_functions *from=NULL, *to=NULL; + int i; ret = (smb_iconv_t)talloc_named(NULL, sizeof(*ret), "iconv(%s,%s)", tocode, fromcode); @@ -180,14 +177,25 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) return ret; } - while (from) { - if (strcasecmp(from->name, fromcode) == 0) break; - from = from->next; + for (i=0;iname, tocode) == 0) break; - to = to->next; + if (from == NULL) { + for (from=charsets; from; from=from->next) { + if (strcasecmp(from->name, fromcode) == 0) break; + } + } + + if (to == NULL) { + for (to=charsets; to; to=to->next) { + if (strcasecmp(to->name, tocode) == 0) break; + } } #ifdef HAVE_NATIVE_ICONV -- cgit From cf4298874c01644eaedb8f80eec131ec5a220e08 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Dec 2004 10:56:29 +0000 Subject: r4281: fixed an ldb indexing bug in ldb found by volker. index entries were not always being removed on modify (This used to be commit 9c668e7b43dc2d82d3d639b64c53e887723ccba7) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 6 +++--- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 17 ++++++++++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 ++++ 3 files changed, 19 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index df0a436172..b0a1b0f89f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -746,8 +746,8 @@ int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) /* delete an index entry for one message element */ -static int ltdb_index_del1(struct ldb_module *module, const char *dn, - struct ldb_message_element *el, int v_idx) +int ltdb_index_del_value(struct ldb_module *module, const char *dn, + struct ldb_message_element *el, int v_idx) { struct ldb_context *ldb = module->ldb; struct ldb_message msg; @@ -826,7 +826,7 @@ int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) continue; } for (j=0;jelements[i].num_values;j++) { - ret = ltdb_index_del1(module, msg->dn, &msg->elements[i], j); + ret = ltdb_index_del_value(module, msg->dn, &msg->elements[i], j); if (ret == -1) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 6623fd0052..5bceab0f13 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -403,10 +403,11 @@ static int msg_add_element(struct ldb_context *ldb, /* delete all elements having a specified attribute name */ -static int msg_delete_attribute(struct ldb_context *ldb, +static int msg_delete_attribute(struct ldb_module *module, + struct ldb_context *ldb, struct ldb_message *msg, const char *name) { - unsigned int i, count=0; + unsigned int i, j, count=0; struct ldb_message_element *el2; el2 = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); @@ -419,6 +420,9 @@ static int msg_delete_attribute(struct ldb_context *ldb, if (ldb_attr_cmp(msg->elements[i].name, name) != 0) { el2[count++] = msg->elements[i]; } else { + for (j=0;jelements[i].num_values;j++) { + ltdb_index_del_value(module, msg->dn, &msg->elements[i], j); + } ldb_free(ldb, msg->elements[i].values); } } @@ -460,7 +464,7 @@ static int msg_delete_element(struct ldb_module *module, } el->num_values--; if (el->num_values == 0) { - return msg_delete_attribute(ldb, msg, name); + return msg_delete_attribute(module, ldb, msg, name); } return 0; } @@ -532,7 +536,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms case LDB_FLAG_MOD_REPLACE: /* replace all elements of this attribute name with the elements listed. The attribute not existing is not an error */ - msg_delete_attribute(ldb, &msg2, msg->elements[i].name); + msg_delete_attribute(module, ldb, &msg2, msg->elements[i].name); /* add the replacement element, if not empty */ if (msg->elements[i].num_values != 0 && @@ -545,7 +549,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms /* we could be being asked to delete all values or just some values */ if (msg->elements[i].num_values == 0) { - if (msg_delete_attribute(ldb, &msg2, + if (msg_delete_attribute(module, ldb, &msg2, msg->elements[i].name) != 0) { ltdb->last_err_string = "No such attribute"; goto failed; @@ -560,6 +564,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms ltdb->last_err_string = "No such attribute"; goto failed; } + if (ltdb_index_del_value(module, msg->dn, &msg->elements[i], j) != 0) { + goto failed; + } } break; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 2cc25b3152..05311346f4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -112,3 +112,7 @@ int ltdb_message_match(struct ldb_module *module, struct ldb_parse_tree *tree, const char *base, enum ldb_scope scope); + +int ltdb_index_del_value(struct ldb_module *module, const char *dn, + struct ldb_message_element *el, int v_idx); + -- cgit From 04e1d5f77cfba8dd69eccf510cf07bbc3df0ec2b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Dec 2004 10:58:36 +0000 Subject: r4282: removed a spurious error message now we remove index entries in the modify call (This used to be commit 58fcc326241e73cc8a122e6130b5ff0d6a3b9232) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index b0a1b0f89f..8d31a3a81f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -769,7 +769,6 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, if (ret == 0) { /* it wasn't indexed. Did we have an earlier error? If we did then its gone now */ - ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn_key %s was not indexed\n", dn_key); ldb_free(ldb, dn_key); return 0; } -- cgit From 616cf701281331bf0bcad56cbfd22ca22576e3d1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 21 Dec 2004 00:01:02 +0000 Subject: r4298: Update to credentials.h after feedback from Andrew Bartlett Move pack/unpack of values in ldb registry backend to seperate functions (This used to be commit ceb4e92735f6dae96bb0b9d98211c9808159e56a) --- source4/lib/registry/reg_backend_ldb.c | 59 ++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 9b0b5759ce..9435da5dd6 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -36,6 +36,32 @@ static int ldb_close_hive (void *_hive) return 0; } +static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32 *type, void **data, int *len) +{ + const struct ldb_val *val; + *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL)); + *type = ldb_msg_find_uint(msg, "type", 0); + val = ldb_msg_find_ldb_val(msg, "data"); + *data = talloc_memdup(mem_ctx, val->data, val->length); + *len = val->length; +} + +static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32 type, void *data, int len) +{ + struct ldb_val val; + struct ldb_message *msg = talloc_zero_p(mem_ctx, struct ldb_message); + char *type_s; + + ldb_msg_add_string(ctx, msg, "value", talloc_strdup(mem_ctx, name)); + val.length = len; + val.data = data; + ldb_msg_add_value(ctx, msg, "data", &val); + + type_s = talloc_asprintf(mem_ctx, "%u", type); + ldb_msg_add_string(ctx, msg, "type", type_s); + + return msg; +} static int reg_close_ldb_key (void *data) @@ -121,9 +147,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) { struct ldb_context *c = k->hive->backend_data; - struct ldb_message_element *el; struct ldb_key_data *kd = k->backend_data; - const struct ldb_val *val; /* Do the search if necessary */ if (kd->values == NULL) { @@ -136,15 +160,10 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i } if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS; - - el = ldb_msg_find_element(kd->values[idx], "value"); - + *value = talloc_p(mem_ctx, struct registry_value); - (*value)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*value)->data_type = ldb_msg_find_uint(kd->values[idx], "type", 0); - val = ldb_msg_find_ldb_val(kd->values[idx], "data"); - (*value)->data_blk = talloc_memdup(mem_ctx, val->data, val->length); - (*value)->data_len = val->length; + + reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data_blk, &(*value)->data_len); return WERR_OK; } @@ -275,28 +294,18 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len) { struct ldb_context *ctx = parent->hive->backend_data; - struct ldb_message msg; - struct ldb_val val; + struct ldb_message *msg; struct ldb_key_data *kd = parent->backend_data; int ret; - char *type_s; TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); - ZERO_STRUCT(msg); - - msg.dn = talloc_asprintf(mem_ctx, "value=%s,%s", name, kd->dn); + msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data, len); - ldb_msg_add_string(ctx, &msg, "value", talloc_strdup(mem_ctx, name)); - val.length = len; - val.data = data; - ldb_msg_add_value(ctx, &msg, "data", &val); + msg->dn = talloc_asprintf(mem_ctx, "value=%s,%s", name, kd->dn); - type_s = talloc_asprintf(mem_ctx, "%u", type); - ldb_msg_add_string(ctx, &msg, "type", type_s); - - ret = ldb_add(ctx, &msg); + ret = ldb_add(ctx, msg); if (ret < 0) { - ret = ldb_modify(ctx, &msg); + ret = ldb_modify(ctx, msg); if (ret < 0) { DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); talloc_destroy(mem_ctx); -- cgit From 9547649006770022bdcddcc319b81b555222f1c4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 21 Dec 2004 00:31:18 +0000 Subject: r4299: Store REG_SZ, REG_EXPAND_SZ and REG_DWORD values in human-readable (and human-editable) format in the ldb registry backend. (This used to be commit 6eafd055d1a7d45734a0112228e18ee59d1f7867) --- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/registry/reg_backend_ldb.c | 40 +++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 3da875ca0b..3a17369144 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -124,7 +124,7 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da case REG_DWORD: (*value)->data_len = sizeof(uint32); (*value)->data_blk = talloc_p(mem_ctx, uint32); - *((uint32 *)(*value)->data_blk) = atol(data_str); + *((uint32 *)(*value)->data_blk) = strtol(data_str, NULL, 0); break; case REG_NONE: diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 9435da5dd6..f7b743fd72 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -42,8 +42,25 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL)); *type = ldb_msg_find_uint(msg, "type", 0); val = ldb_msg_find_ldb_val(msg, "data"); - *data = talloc_memdup(mem_ctx, val->data, val->length); - *len = val->length; + + switch (*type) + { + case REG_SZ: + case REG_EXPAND_SZ: + *len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, data); + break; + + case REG_DWORD_LE: + *len = 4; + *data = talloc_p(mem_ctx, uint32); + SIVAL(*data, 0, strtol(val->data, NULL, 0)); + break; + + default: + *data = talloc_memdup(mem_ctx, val->data, val->length); + *len = val->length; + break; + } } static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32 type, void *data, int len) @@ -53,9 +70,22 @@ static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CT char *type_s; ldb_msg_add_string(ctx, msg, "value", talloc_strdup(mem_ctx, name)); - val.length = len; - val.data = data; - ldb_msg_add_value(ctx, msg, "data", &val); + + switch (type) { + case REG_SZ: + case REG_EXPAND_SZ: + val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, data, len, &val.data); + ldb_msg_add_value(ctx, msg, "data", &val); + break; + case REG_DWORD_LE: + ldb_msg_add_string(ctx, msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data, 0))); + break; + default: + val.length = len; + val.data = data; + ldb_msg_add_value(ctx, msg, "data", &val); + } + type_s = talloc_asprintf(mem_ctx, "%u", type); ldb_msg_add_string(ctx, msg, "type", type_s); -- cgit From 3e7c0e10cfe956692834b952cec9e5f0f4a980b4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Dec 2004 15:15:49 +0000 Subject: r4327: add usefull function if you don't want that the data will talloc_memdup()'ed metze (This used to be commit 1f01e370b192fc8fa51eb3a46e7b45c993aa9b80) --- source4/lib/data_blob.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 1551879933..18ecc2793a 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -173,3 +173,10 @@ DATA_BLOB data_blob_string_const(const char *str) return blob; } +DATA_BLOB data_blob_const(const void *p, size_t length) +{ + DATA_BLOB blob; + blob.data = discard_const(p); + blob.length = length; + return blob; +} -- cgit From b29b10e48ee351c19cb7a0e9766718fa1715f747 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 26 Dec 2004 17:30:27 +0000 Subject: r4366: Fix ldb_modify_internal: Adding values to an existing attribute you could end up with a corrupt data structure on disk, namely with two attribute structures for the same attribute name. Volker (This used to be commit 284044b5b20102894a8128f84ab41d59cfcc9285) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 45 +++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 5bceab0f13..179b205097 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -513,24 +513,51 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg->elements[i]; + struct ldb_message_element *el2; + struct ldb_val *vals; + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_ADD: /* add this element to the message. fail if it already exists */ - ret = find_element(&msg2, msg->elements[i].name); - if (ret != -1) { - for (j=0;jelements[i].num_values;j++) { - if (ldb_msg_find_val(&msg2.elements[ret], - &msg->elements[i].values[j])) { - ltdb->last_err_string = "Type or value exists"; - goto failed; - } + ret = find_element(&msg2, el->name); + + if (ret == -1) { + if (msg_add_element(ldb, &msg2, el) != 0) { + goto failed; + } + continue; + } + + el2 = &msg2.elements[ret]; + + /* An attribute with this name already exists, add all + * values if they don't already exist. */ + + for (j=0;jnum_values;j++) { + if (ldb_msg_find_val(el2, &el->values[j])) { + ltdb->last_err_string = + "Type or value exists"; + goto failed; } } - if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { + + vals = ldb_realloc_p(ldb, el2->values, struct ldb_val, + el2->num_values + el->num_values); + + if (vals == NULL) goto failed; + + for (j=0;jnum_values;j++) { + vals[el2->num_values + j] = + ldb_val_dup(ldb, &el->values[j]); } + + el2->values = vals; + el2->num_values += el->num_values; + break; case LDB_FLAG_MOD_REPLACE: -- cgit From b0e6ce645a433c8972eb131cbc4cf0aed3ce1055 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Dec 2004 22:41:38 +0000 Subject: r4371: Add "Create Key", "Delete Key" and "Delete Value" buttons. gregedit now can do the same things as regedt32 except for finding data and setting values. (and a few segfaults...) (This used to be commit ada16f31e4da919731767ce31000aa270f22ffd5) --- source4/lib/registry/reg_backend_ldb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index f7b743fd72..ffb9215cf0 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -237,12 +237,13 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) if (!hive->location) return WERR_INVALID_PARAM; wrap = ldb_wrap_connect(hive, hive->location, 0, NULL); - c = wrap->ldb; - - if(!c) { - DEBUG(1, ("ldb_open_hive: %s\n", ldb_errstring(hive->backend_data))); + if(!wrap) { + DEBUG(1, ("ldb_open_hive: unable to connect\n")); return WERR_FOOBAR; } + + c = wrap->ldb; + ldb_set_debug_stderr(c); hive->backend_data = c; -- cgit From dcff66281cc7da27b06d605af90fed74076da19f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 27 Dec 2004 00:32:13 +0000 Subject: r4373: Support setting values and fix a segfault (This used to be commit cdb6980cdcf4b093e98b3b025f784333d46ac957) --- source4/lib/registry/common/reg_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f5c3598721..e48fe38eb9 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -273,10 +273,10 @@ WERROR reg_key_num_subkeys(struct registry_key *key, int *count) if(key->hive->functions->get_subkey_by_index) { int i; WERROR error; - struct registry_key *dest; + struct registry_key *dest = NULL; TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); - for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_subkey_by_index(mem_ctx, key, i, &dest)); i++); + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++); talloc_destroy(mem_ctx); *count = i; -- cgit From f05bc12213477676967b5c1780c8cca61b262317 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 29 Dec 2004 12:28:35 +0000 Subject: r4390: Registry value and key names are case-insensitive Nicer menu layout in gregedit (This used to be commit 2948b9750d756880c3af7fb352f0a684a1fae9c9) --- source4/lib/registry/common/reg_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index e48fe38eb9..9b03a69f3f 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -119,7 +119,7 @@ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char * int i; for (i = 0; predef_names[i].name; i++) { - if (!strcmp(predef_names[i].name, name)) return reg_get_predefined_key(ctx, predef_names[i].handle, key); + if (!strcasecmp(predef_names[i].name, name)) return reg_get_predefined_key(ctx, predef_names[i].handle, key); } DEBUG(1, ("No predefined key with name '%s'\n", name)); @@ -347,7 +347,7 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, } else if(key->hive->functions->get_subkey_by_index) { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey); - if(W_ERROR_IS_OK(error) && !strcmp((*subkey)->name, name)) { + if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) { break; } } @@ -378,7 +378,7 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, } else { for(i = 0; W_ERROR_IS_OK(error); i++) { error = reg_key_get_value_by_index(mem_ctx, key, i, val); - if(W_ERROR_IS_OK(error) && !strcmp((*val)->name, name)) { + if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) { break; } } -- cgit From 91abe814d160c4aaf55ce989bacb9c115e159896 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 29 Dec 2004 22:25:46 +0000 Subject: r4397: Fix a bug where '(&(objectclass=domain)(!(objectclass=builtindomain)))' fell back to a full search. Volker (This used to be commit 55c9fbd4f4afdde30a0d92bfd31f5c9ebb98c59b) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 8d31a3a81f..01fa4be44b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -526,6 +526,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr return -1; } + ret = 0; if (ltdb_message_match(module, &msg, tree, base, scope) == 1) { ret = ltdb_add_attr_results(module, &msg, attrs, &count, res); } -- cgit From c5fa6f7516dca066359f73b1c4aba3e0d8a4c850 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Dec 2004 02:18:14 +0000 Subject: r4424: fixed a simple bug in the '|' handling in indexed ldb searches. I'm amazed we got along for so long with this bug! (This used to be commit 937159cf2c6ae08808bd10946fcdbd8741e1a560) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 01fa4be44b..eaf699be62 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -385,6 +385,7 @@ static int ltdb_index_dn_or(struct ldb_module *module, return -1; } dn_list_free(ldb, &list2); + ret = 1; } } -- cgit From 09c1b9cbe5175636bcf4b606edfd0022bd9cfd6b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Dec 2004 03:51:42 +0000 Subject: r4427: - added ldb_msg_*() functions for sorting, comparing and copying messages - added a ldb_msg_canonicalize() function that fixes a record to not have any duplicate elements - changed ldbedit to use ldb_msg_canonicalize(). This fixes a bug when you rename multiple elements in a record in one edit (This used to be commit f006e724400843419c8b6155cbeae1876983855e) --- source4/lib/ldb/common/ldb_msg.c | 134 +++++++++++++++++++++++++++++++++++++++ source4/lib/ldb/include/ldb.h | 12 ++++ source4/lib/ldb/tools/ldbedit.c | 7 ++ 3 files changed, 153 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 18859c86dd..3865e7afa9 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -227,6 +227,16 @@ int ldb_msg_element_compare(struct ldb_message_element *el1, return 0; } +/* + compare two ldb_message_element structures + comparing by element name +*/ +int ldb_msg_element_compare_name(struct ldb_message_element *el1, + struct ldb_message_element *el2) +{ + return ldb_attr_cmp(el1->name, el2->name); +} + /* convenience functions to return common types from a message these return the first value if the attribute is multi-valued @@ -305,3 +315,127 @@ const char *ldb_msg_find_string(const struct ldb_message *msg, } return v->data; } + + +/* + sort the elements of a message by name +*/ +void ldb_msg_sort_elements(struct ldb_message *msg) +{ + qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element), + (comparison_fn_t)ldb_msg_element_compare_name); +} + + +/* + free a message created using ldb_msg_copy +*/ +void ldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) +{ + int i, j; + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg->elements[i]; + for (j=0;jnum_values;j++) { + ldb_free(ldb, el->values[j].data); + } + if (el->values) ldb_free(ldb, el->values); + ldb_free(ldb, el->name); + } + if (msg->elements) ldb_free(ldb, msg->elements); + ldb_free(ldb, msg->dn); + ldb_free(ldb, msg); +} + +/* + copy a message, allocating new memory for all parts +*/ +struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, + const struct ldb_message *msg) +{ + struct ldb_message *msg2; + int i, j; + + msg2 = ldb_malloc_p(ldb, struct ldb_message); + if (msg2 == NULL) return NULL; + + msg2->elements = NULL; + msg2->num_elements = 0; + msg2->private_data = NULL; + + msg2->dn = ldb_strdup(ldb, msg->dn); + if (msg2->dn == NULL) goto failed; + + msg2->elements = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); + if (msg2->elements == NULL) goto failed; + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el1 = &msg->elements[i]; + struct ldb_message_element *el2 = &msg2->elements[i]; + + el2->flags = el1->flags; + el2->num_values = 0; + el2->values = NULL; + el2->name = ldb_strdup(ldb, el1->name); + if (el2->name == NULL) goto failed; + el2->values = ldb_malloc_array_p(ldb, struct ldb_val, el1->num_values); + for (j=0;jnum_values;j++) { + el2->values[j] = ldb_val_dup(ldb, &el1->values[j]); + if (el2->values[j].data == NULL && + el1->values[j].length != 0) { + goto failed; + } + el2->num_values++; + } + + msg2->num_elements++; + } + + return msg2; + +failed: + ldb_msg_free(ldb, msg2); + return NULL; +} + + +/* + canonicalise a message, merging elements of the same name +*/ +struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, + const struct ldb_message *msg) +{ + int i; + struct ldb_message *msg2; + + msg2 = ldb_msg_copy(ldb, msg); + if (msg2 == NULL) return NULL; + + ldb_msg_sort_elements(msg2); + + for (i=1;inum_elements;i++) { + struct ldb_message_element *el1 = &msg2->elements[i-1]; + struct ldb_message_element *el2 = &msg2->elements[i]; + if (ldb_msg_element_compare_name(el1, el2) == 0) { + el1->values = ldb_realloc_p(ldb, el1->values, struct ldb_val, + el1->num_values + el2->num_values); + if (el1->values == NULL) { + return NULL; + } + memcpy(el1->values + el1->num_values, + el2->values, + sizeof(struct ldb_val) * el2->num_values); + el1->num_values += el2->num_values; + ldb_free(ldb, el2->name); + ldb_free(ldb, el2->values); + if (i+1num_elements) { + memmove(el2, el2+1, sizeof(struct ldb_message_element) * + (msg2->num_elements - (i+1))); + } + msg2->num_elements--; + i--; + } + } + + return msg2; +} diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 03d0cc7a3b..9dff510417 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -293,6 +293,18 @@ double ldb_msg_find_double(const struct ldb_message *msg, const char *ldb_msg_find_string(const struct ldb_message *msg, const char *attr_name, const char *default_value); + +void ldb_msg_sort_elements(struct ldb_message *msg); + +void ldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg); + +struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, + const struct ldb_message *msg); + +struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, + const struct ldb_message *msg); + + struct ldb_val ldb_val_dup(struct ldb_context *ldb, const struct ldb_val *v); diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index f84d05440f..6cd6ef041b 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -69,6 +69,12 @@ static int modify_record(struct ldb_context *ldb, mod.num_elements = 0; mod.elements = NULL; + msg2 = ldb_msg_canonicalize(ldb, msg2); + if (msg2 == NULL) { + fprintf(stderr, "Failed to canonicalise msg2\n"); + return -1; + } + /* look in msg2 to find elements that need to be added or modified */ for (i=0;inum_elements;i++) { @@ -295,6 +301,7 @@ static void usage(void) printf(" -b basedn choose baseDN\n"); printf(" -a edit all records (expression 'objectclass=*')\n"); printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n"); + printf(" -v verbose mode)\n"); exit(1); } -- cgit From f80ce3ecb9f7ee2ccf5d71970f9c61ccc18e8c76 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Jan 2005 04:40:11 +0000 Subject: r4465: remove unused file (This used to be commit fee40e110d56c932aeff11178c120f3f4e19ddd2) --- source4/lib/talloctort.c | 69 ------------------------------------------------ 1 file changed, 69 deletions(-) delete mode 100644 source4/lib/talloctort.c (limited to 'source4/lib') diff --git a/source4/lib/talloctort.c b/source4/lib/talloctort.c deleted file mode 100644 index 9c10f4eed8..0000000000 --- a/source4/lib/talloctort.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba temporary memory allocation functions -- torturer - Copyright (C) 2001 by Martin Pool - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#error SAMBA4 clean up -#error this file should be (re)moved -#error and all unused stuff should go - -#include "includes.h" - -#define NCTX 10 -#define NOBJ 20 - -int main(void) -{ - int i; - TALLOC_CTX *ctx[NCTX]; - - for (i = 0; i < NCTX; i++) { - ctx[i] = talloc_init("torture(%d)", i); - } - - for (i = 0; i < NCTX; i++) { - int j; - for (j = 0; j < NOBJ; j++) { - char *p; - size_t size = 1<<(i/3+j); - - p = talloc(ctx[i], size); - if (!p) { - fprintf(stderr, - "failed to talloc %.0f bytes\n", - (double) size); - exit(1); - } - - memset(p, 'A' + j, size); - } - } - - for (i = 0; i < NCTX; i++) { - printf("talloc@%p %-40s %dkB\n", ctx[i], - talloc_pool_name(ctx[i]), - talloc_pool_size(ctx[i]) >> 10); - } - - printf("%s", talloc_describe_all(ctx[0])); - - for (i = NCTX - 1; i >= 0; i--) - talloc_destroy(ctx[i]); - - return 0; -} -- cgit From f9e507980e6a3340ae135e81d3106a836116d6b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Jan 2005 05:06:22 +0000 Subject: r4466: rather than defining "STANDALONE" for building tdb, ldb and talloc outside the tree, instead defined _SAMBA_BUILD_ inside the Samba build. This makes it easier to pull code out of Samba for external use. (This used to be commit 09e98c8745cca7ccb1ad7134c0c09b8e4c0f4f06) --- source4/lib/ldb/Makefile.ldb | 4 +- source4/lib/ldb/common/talloc.c | 997 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/include/talloc.h | 96 ++++ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 +- source4/lib/talloc.c | 9 +- source4/lib/tdb/common/spinlock.c | 6 +- source4/lib/tdb/common/tdb.c | 2 +- source4/lib/tdb/tools/tdbbackup.c | 2 +- source4/lib/tdb/tools/tdbdump.c | 2 +- source4/lib/tdb/tools/tdbtest.c | 2 +- source4/lib/tdb/tools/tdbtorture.c | 2 +- 11 files changed, 1107 insertions(+), 17 deletions(-) create mode 100644 source4/lib/ldb/common/talloc.c create mode 100644 source4/lib/ldb/include/talloc.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index a7c86b4e82..721ba5f407 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -11,7 +11,7 @@ endif TDBDIR=../tdb -CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -I$(TDBDIR)/include -DSTANDALONE=1 -DUSE_MMAP=1 $(LDAP_FLAGS) +CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -I$(TDBDIR)/include -DUSE_MMAP=1 $(LDAP_FLAGS) LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o @@ -21,7 +21,7 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_cache.o -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/talloc.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ common/ldb_alloc.o common/ldb_debug.o common/ldb_modules.o diff --git a/source4/lib/ldb/common/talloc.c b/source4/lib/ldb/common/talloc.c new file mode 100644 index 0000000000..7f50264801 --- /dev/null +++ b/source4/lib/ldb/common/talloc.c @@ -0,0 +1,997 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + + +#ifdef _SAMBA_BUILD_ +#include "includes.h" +#else +#include +#include +#include +#include +#include "talloc.h" +#endif + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC 0xe814ec4f +#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)(ptr)) +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static const void *null_context; + + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; +}; + +typedef int (*talloc_destructor_t)(void *); + +struct talloc_chunk { + struct talloc_chunk *next, *prev; + struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; + size_t size; + unsigned magic; + talloc_destructor_t destructor; + const char *name; +}; + +/* panic if we get a bad magic value */ +static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; + if (tc->magic != TALLOC_MAGIC) { + if (tc->magic == TALLOC_MAGIC_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } else { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + } + + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + return tc->parent; +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + context = null_context; + } + + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + + tc = malloc(sizeof(*tc)+size); + if (tc == NULL) return NULL; + + tc->size = size; + tc->magic = TALLOC_MAGIC; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (context) { + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); + + tc->parent = parent; + + if (parent->child) { + parent->child->parent = NULL; + } + + _TLIST_ADD(parent->child, tc); + } else { + tc->next = tc->prev = tc->parent = NULL; + } + + return (void *)(tc+1); +} + + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +void talloc_increase_ref_count(const void *ptr) +{ + talloc_reference(null_context, ptr); +} + +/* + helper for talloc_reference() +*/ +static int talloc_reference_destructor(void *ptr) +{ + struct talloc_reference_handle *handle = ptr; + struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); + if (tc1->destructor != (talloc_destructor_t)-1) { + tc1->destructor = NULL; + } + _TLIST_REMOVE(tc2->refs, handle); + talloc_free(handle); + return 0; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *talloc_reference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (ptr == NULL) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); + + if (handle == NULL) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (context == NULL) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if ((p==NULL && context==NULL) || p+1 == context) break; + } + if (h == NULL) { + return -1; + } + + talloc_set_destructor(h, NULL); + _TLIST_REMOVE(tc->refs, h); + talloc_free(h); + return 0; +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return talloc_free(ptr); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = new_p+1; + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + talloc_steal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = talloc_vasprintf(ptr, fmt, ap); + if (tc->name) { + talloc_set_name_const(tc->name, ".name"); + } +} + +/* + add a name to an existing pointer +*/ +void talloc_set_name(const void *ptr, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named(const void *context, size_t size, const char *fmt, ...) +{ + va_list ap; + void *ptr; + + ptr = _talloc(context, size); + if (ptr == NULL) return NULL; + + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + return ptr; +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = _talloc(context, size); + if (ptr == NULL) { + return NULL; + } + + talloc_set_name_const(ptr, name); + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +const char *talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (tc->name == TALLOC_MAGIC_REFERENCE) { + return ".reference"; + } + if (tc->name) { + return tc->name; + } + return "UNNAMED"; +} + +/* + this is for compatibility with older versions of talloc +*/ +void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + + ptr = _talloc(NULL, 0); + if (ptr == NULL) return NULL; + + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + return ptr; +} + + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +int talloc_free(void *ptr) +{ + struct talloc_chunk *tc; + + if (ptr == NULL) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->refs) { + talloc_reference_destructor(tc->refs); + return -1; + } + + if (tc->destructor) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = tc->child+1; + const void *new_parent = null_context; + if (tc->child->refs) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = p+1; + } + if (talloc_free(child) == -1) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = p+1; + } + talloc_steal(new_parent, child); + } + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->magic = TALLOC_MAGIC_FREE; + + free(tc); + return 0; +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + + /* size zero is equivalent to free() */ + if (size == 0) { + talloc_free(ptr); + return NULL; + } + + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + + /* realloc(NULL) is equavalent to malloc() */ + if (ptr == NULL) { + return talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (tc->refs) { + return NULL; + } + + /* by resetting magic we catch users of the old memory */ + tc->magic = TALLOC_MAGIC_FREE; + +#if ALWAYS_REALLOC + new_ptr = malloc(size + sizeof(*tc)); + if (new_ptr) { + memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + free(tc); + } +#else + new_ptr = realloc(tc, size + sizeof(*tc)); +#endif + if (!new_ptr) { + tc->magic = TALLOC_MAGIC; + return NULL; + } + + tc = new_ptr; + tc->magic = TALLOC_MAGIC; + if (tc->parent) { + tc->parent->child = new_ptr; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + tc->size = size; + talloc_set_name_const(tc+1, name); + + return (void *)(tc+1); +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred +*/ +void *talloc_steal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (!ptr) { + return NULL; + } + + if (new_ctx == NULL) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (new_ctx == NULL) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (tc == new_tc) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + +/* + return the total size of a talloc pool (subtree) +*/ +off_t talloc_total_size(const void *ptr) +{ + off_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + total = tc->size; + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(c+1); + } + return total; +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +off_t talloc_total_blocks(const void *ptr) +{ + off_t total = 0; + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(c+1); + } + return total; +} + +/* + return the number of external references to a pointer +*/ +static int talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + int ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth(const void *ptr, FILE *f, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *handle = (void *)(c+1); + const char *name2 = talloc_get_name(handle->ptr); + fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); + } else { + const char *name = talloc_get_name(c+1); + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1), + talloc_reference_count(c+1)); + talloc_report_depth(c+1, f, depth+1); + } + } + +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + talloc_report_depth(ptr, f, 1); +} + +/* + report on memory usage by all children of a pointer +*/ +void talloc_report(const void *ptr, FILE *f) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + tc = talloc_chunk_from_ptr(ptr); + + for (c=tc->child;c;c=c->next) { + fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", + talloc_get_name(c+1), + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1)); + } + +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); + } +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); + } +} + +/* + enable leak reporting on exit +*/ +void talloc_enable_leak_report(void) +{ + null_context = talloc_named_const(NULL, 0, "null_context"); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +void talloc_enable_leak_report_full(void) +{ + null_context = talloc_named_const(NULL, 0, "null_context"); + atexit(talloc_report_null_full); +} + +/* + talloc and zero memory. +*/ +void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + + +/* + memdup with a talloc. +*/ +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = talloc_named_const(t, size, name); + + if (newp) { + memcpy(newp, p, size); + } + + return newp; +} + +/* + strdup with a talloc +*/ +char *talloc_strdup(const void *t, const char *p) +{ + char *ret; + if (!p) { + return NULL; + } + ret = talloc_memdup(t, p, strlen(p) + 1); + if (ret) { + talloc_set_name_const(ret, ret); + } + return ret; +} + +/* + strndup with a talloc +*/ +char *talloc_strndup(const void *t, const char *p, size_t n) +{ + size_t len; + char *ret; + + for (len=0; p[len] && len= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + ptr = talloc_realloc(ctx, ptr, el_size * count); + if (ptr) { + talloc_set_name_const(ptr, name); + } + return ptr; +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} diff --git a/source4/lib/ldb/include/talloc.h b/source4/lib/ldb/include/talloc.h new file mode 100644 index 0000000000..ffb4c9f252 --- /dev/null +++ b/source4/lib/ldb/include/talloc.h @@ -0,0 +1,96 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#define _STRING_LINE_(s) #s +#define _STRING_LINE2_(s) _STRING_LINE_(s) +#define __LINESTR__ _STRING_LINE2_(__LINE__) +#define __location__ __FILE__ ":" __LINESTR__ + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) +#define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) +#define talloc_p(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_zero_p(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_array_p(ctx, type, count) (type *)talloc_zero_array(ctx, sizeof(type), count, __location__) +#define talloc_array_p(ctx, type, count) (type *)talloc_array(ctx, sizeof(type), count, __location__) +#define talloc_realloc_p(ctx, p, type, count) (type *)talloc_realloc_array(ctx, p, sizeof(type), count, __location__) +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_destroy(ctx) talloc_free(ctx) + +#define malloc_p(type) (type *)malloc(sizeof(type)) +#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) +#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) + +#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) +#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) + +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a1, a2) +#endif + + +/* The following definitions come from lib/talloc.c */ +void *_talloc(const void *context, size_t size); +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); +void talloc_increase_ref_count(const void *ptr); +void *talloc_reference(const void *context, const void *ptr); +int talloc_unlink(const void *context, void *ptr); +void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int talloc_free(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *talloc_steal(const void *new_ctx, const void *ptr); +off_t talloc_total_size(const void *ptr); +off_t talloc_total_blocks(const void *ptr); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +char *talloc_strdup(const void *t, const char *p); +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, + const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_ldb_alloc(void *context, void *ptr, size_t size); + +#endif + diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 05311346f4..7d6f35dc79 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -1,5 +1,5 @@ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #include "tdb.h" #endif diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 0b1f5b7cb5..7f50264801 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -27,17 +27,14 @@ */ -/* - if you need to build this outside of the Samba source tree then please define _STANDALONE_ -*/ -#ifdef _STANDALONE_ +#ifdef _SAMBA_BUILD_ +#include "includes.h" +#else #include #include #include #include #include "talloc.h" -#else -#include "includes.h" #endif /* use this to force every realloc to change the pointer, to stress test diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index 27481e221c..30bfd77962 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -27,7 +27,7 @@ #include #endif -#if STANDALONE +#ifndef _SAMBA_BUILD_ #include #include #include @@ -157,12 +157,12 @@ static inline int __spin_is_locked(spinlock_t *lock) * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. */ -#if defined(STANDALONE) +#ifndef _SAMBA_BUILD_ /* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ #define inline __inline -#endif /* STANDALONE */ +#endif /* _SAMBA_BUILD_ */ /* Returns 0 if the lock is acquired, EBUSY otherwise. */ static inline int __spin_trylock(spinlock_t *lock) diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index afe2ca1621..46b2499179 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -46,7 +46,7 @@ * right time. Probably too hard -- the process just doesn't know. */ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #if HAVE_CONFIG_H #include #endif diff --git a/source4/lib/tdb/tools/tdbbackup.c b/source4/lib/tdb/tools/tdbbackup.c index 1a0e1c1588..4cb6a8cfdd 100644 --- a/source4/lib/tdb/tools/tdbbackup.c +++ b/source4/lib/tdb/tools/tdbbackup.c @@ -41,7 +41,7 @@ */ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #if HAVE_CONFIG_H #include #endif diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index dbb647cbbf..dd018af6f5 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -18,7 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #include #include #include diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index 6c20a5dc77..f4854b5931 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -1,6 +1,6 @@ /* a test program for tdb - the trivial database */ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #include #include #include diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index e90a967138..890e25af50 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -2,7 +2,7 @@ writers - that stresses the locking code. Build with TDB_DEBUG=1 for best effect */ -#ifdef STANDALONE +#ifndef _SAMBA_BUILD_ #include #include #include -- cgit From 70067ef957d5ea10358ecec0ff7902e873a97521 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 1 Jan 2005 05:08:41 +0000 Subject: r4467: - tdb standalone build doesn't need -DSTANDALONE any more - fixed standalone build (This used to be commit ade0b71e4194f99d807d26276592bc041d46df7b) --- source4/lib/tdb/Makefile.tdb | 4 ++-- source4/lib/tdb/tools/tdbtorture.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.tdb b/source4/lib/tdb/Makefile.tdb index a863b0de8b..ee612bfb63 100644 --- a/source4/lib/tdb/Makefile.tdb +++ b/source4/lib/tdb/Makefile.tdb @@ -2,13 +2,13 @@ # Makefile for tdb directory # -CFLAGS = -DSTANDALONE -DTDB_DEBUG -g -DHAVE_MMAP=1 -Iinclude +CFLAGS = -DTDB_DEBUG -g -DHAVE_MMAP=1 -Iinclude CC = gcc PROGS = bin/tdbtest bin/tdbtool bin/tdbtorture TDB_OBJ = common/tdb.o common/spinlock.o -default: $(PROGS) +all: $(PROGS) bin/tdbtest: tools/tdbtest.o $(TDB_OBJ) $(CC) $(CFLAGS) -o bin/tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 890e25af50..bb2313369b 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -219,7 +219,7 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, if (getpid() == pids[0]) { for (i=0;i Date: Sun, 2 Jan 2005 04:21:32 +0000 Subject: r4472: improve the discard_const() macro for standalone build of talloc (This used to be commit 310cea15bf01343d9ab8ff7a166f0699c0507816) --- source4/lib/talloc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index 7f50264801..ce1a325ebd 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "talloc.h" #endif @@ -54,7 +55,11 @@ #endif #ifndef discard_const_p -#define discard_const_p(type, ptr) ((type *)(ptr)) +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#endif #endif /* this null_context is only used if talloc_enable_leak_report() or -- cgit From 65f96eba32b93ced0717c2639007bba59da55fa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 07:47:34 +0000 Subject: r4473: - moved talloc into its own lib/talloc/ area - added gcov flags to Makefile.talloc - expanded talloc testsuite to add a test for realloc with a child ptr - fixed a bug in talloc_realloc() with realloc of a ptr that has child ptrs (This used to be commit 98b5f73c1ba34d7576c5995069b485c1c5ede324) --- source4/lib/basic.mk | 3 +- source4/lib/ldb/common/talloc.c | 997 ---------------------------------- source4/lib/talloc.c | 1002 ---------------------------------- source4/lib/talloc/Makefile.talloc | 16 + source4/lib/talloc/config.m4 | 3 + source4/lib/talloc/config.mk | 23 + source4/lib/talloc/talloc.c | 1006 +++++++++++++++++++++++++++++++++++ source4/lib/talloc/talloc.h | 96 ++++ source4/lib/talloc/talloc_guide.txt | 492 +++++++++++++++++ source4/lib/talloc/testsuite.c | 785 +++++++++++++++++++++++++++ 10 files changed, 2422 insertions(+), 2001 deletions(-) delete mode 100644 source4/lib/ldb/common/talloc.c delete mode 100644 source4/lib/talloc.c create mode 100644 source4/lib/talloc/Makefile.talloc create mode 100644 source4/lib/talloc/config.m4 create mode 100644 source4/lib/talloc/config.mk create mode 100644 source4/lib/talloc/talloc.c create mode 100644 source4/lib/talloc/talloc.h create mode 100644 source4/lib/talloc/talloc_guide.txt create mode 100644 source4/lib/talloc/testsuite.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index e4275bea49..a14201d9be 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -56,7 +56,6 @@ ADD_OBJ_FILES = \ lib/data_blob.o \ lib/util.o \ lib/util_sock.o \ - lib/talloc.o \ lib/substitute.o \ lib/fsusage.o \ lib/ms_fnmatch.o \ @@ -71,6 +70,6 @@ ADD_OBJ_FILES = \ lib/db_wrap.o \ lib/gencache.o REQUIRED_SUBSYSTEMS = \ - LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO LIB_SECURITY EXT_LIB_DL + LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO LIB_SECURITY EXT_LIB_DL LIBTALLOC # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/ldb/common/talloc.c b/source4/lib/ldb/common/talloc.c deleted file mode 100644 index 7f50264801..0000000000 --- a/source4/lib/ldb/common/talloc.c +++ /dev/null @@ -1,997 +0,0 @@ -/* - Samba Unix SMB/CIFS implementation. - - Samba trivial allocation library - new interface - - NOTE: Please read talloc_guide.txt for full documentation - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - inspired by http://swapped.cc/halloc/ -*/ - - -#ifdef _SAMBA_BUILD_ -#include "includes.h" -#else -#include -#include -#include -#include -#include "talloc.h" -#endif - -/* use this to force every realloc to change the pointer, to stress test - code that might not cope */ -#define ALWAYS_REALLOC 0 - - -#define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 -#define TALLOC_MAGIC_REFERENCE ((const char *)1) - -/* by default we abort when given a bad pointer (such as when talloc_free() is called - on a pointer that came from malloc() */ -#ifndef TALLOC_ABORT -#define TALLOC_ABORT(reason) abort() -#endif - -#ifndef discard_const_p -#define discard_const_p(type, ptr) ((type *)(ptr)) -#endif - -/* this null_context is only used if talloc_enable_leak_report() or - talloc_enable_leak_report_full() is called, otherwise it remains - NULL -*/ -static const void *null_context; - - -struct talloc_reference_handle { - struct talloc_reference_handle *next, *prev; - void *ptr; -}; - -typedef int (*talloc_destructor_t)(void *); - -struct talloc_chunk { - struct talloc_chunk *next, *prev; - struct talloc_chunk *parent, *child; - struct talloc_reference_handle *refs; - size_t size; - unsigned magic; - talloc_destructor_t destructor; - const char *name; -}; - -/* panic if we get a bad magic value */ -static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) -{ - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - } - - return tc; -} - -/* hook into the front of the list */ -#define _TLIST_ADD(list, p) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - (list)->prev = (p); \ - (p)->next = (list); \ - (p)->prev = NULL; \ - (list) = (p); \ - }\ -} while (0) - -/* remove an element from a list - element doesn't have to be in list. */ -#define _TLIST_REMOVE(list, p) \ -do { \ - if ((p) == (list)) { \ - (list) = (p)->next; \ - if (list) (list)->prev = NULL; \ - } else { \ - if ((p)->prev) (p)->prev->next = (p)->next; \ - if ((p)->next) (p)->next->prev = (p)->prev; \ - } \ - if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ -} while (0) - - -/* - return the parent chunk of a pointer -*/ -static struct talloc_chunk *talloc_parent_chunk(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - while (tc->prev) tc=tc->prev; - return tc->parent; -} - -/* - Allocate a bit of memory as a child of an existing pointer -*/ -void *_talloc(const void *context, size_t size) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - context = null_context; - } - - if (size >= MAX_TALLOC_SIZE) { - return NULL; - } - - tc = malloc(sizeof(*tc)+size); - if (tc == NULL) return NULL; - - tc->size = size; - tc->magic = TALLOC_MAGIC; - tc->destructor = NULL; - tc->child = NULL; - tc->name = NULL; - tc->refs = NULL; - - if (context) { - struct talloc_chunk *parent = talloc_chunk_from_ptr(context); - - tc->parent = parent; - - if (parent->child) { - parent->child->parent = NULL; - } - - _TLIST_ADD(parent->child, tc); - } else { - tc->next = tc->prev = tc->parent = NULL; - } - - return (void *)(tc+1); -} - - -/* - setup a destructor to be called on free of a pointer - the destructor should return 0 on success, or -1 on failure. - if the destructor fails then the free is failed, and the memory can - be continued to be used -*/ -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->destructor = destructor; -} - -/* - increase the reference count on a piece of memory. -*/ -void talloc_increase_ref_count(const void *ptr) -{ - talloc_reference(null_context, ptr); -} - -/* - helper for talloc_reference() -*/ -static int talloc_reference_destructor(void *ptr) -{ - struct talloc_reference_handle *handle = ptr; - struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); - struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); - if (tc1->destructor != (talloc_destructor_t)-1) { - tc1->destructor = NULL; - } - _TLIST_REMOVE(tc2->refs, handle); - talloc_free(handle); - return 0; -} - -/* - make a secondary reference to a pointer, hanging off the given context. - the pointer remains valid until both the original caller and this given - context are freed. - - the major use for this is when two different structures need to reference the - same underlying data, and you want to be able to free the two instances separately, - and in either order -*/ -void *talloc_reference(const void *context, const void *ptr) -{ - struct talloc_chunk *tc; - struct talloc_reference_handle *handle; - if (ptr == NULL) return NULL; - - tc = talloc_chunk_from_ptr(ptr); - handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); - - if (handle == NULL) return NULL; - - /* note that we hang the destructor off the handle, not the - main context as that allows the caller to still setup their - own destructor on the context if they want to */ - talloc_set_destructor(handle, talloc_reference_destructor); - handle->ptr = discard_const_p(void, ptr); - _TLIST_ADD(tc->refs, handle); - return handle->ptr; -} - -/* - remove a secondary reference to a pointer. This undo's what - talloc_reference() has done. The context and pointer arguments - must match those given to a talloc_reference() -*/ -static int talloc_unreference(const void *context, const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - - if (context == NULL) { - context = null_context; - } - - for (h=tc->refs;h;h=h->next) { - struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; - } - if (h == NULL) { - return -1; - } - - talloc_set_destructor(h, NULL); - _TLIST_REMOVE(tc->refs, h); - talloc_free(h); - return 0; -} - -/* - remove a specific parent context from a pointer. This is a more - controlled varient of talloc_free() -*/ -int talloc_unlink(const void *context, void *ptr) -{ - struct talloc_chunk *tc_p, *new_p; - void *new_parent; - - if (ptr == NULL) { - return -1; - } - - if (context == NULL) { - context = null_context; - } - - if (talloc_unreference(context, ptr) == 0) { - return 0; - } - - if (context == NULL) { - if (talloc_parent_chunk(ptr) != NULL) { - return -1; - } - } else { - if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { - return -1; - } - } - - tc_p = talloc_chunk_from_ptr(ptr); - - if (tc_p->refs == NULL) { - return talloc_free(ptr); - } - - new_p = talloc_parent_chunk(tc_p->refs); - if (new_p) { - new_parent = new_p+1; - } else { - new_parent = NULL; - } - - if (talloc_unreference(new_parent, ptr) != 0) { - return -1; - } - - talloc_steal(new_parent, ptr); - - return 0; -} - -/* - add a name to an existing pointer - va_list version -*/ -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = talloc_vasprintf(ptr, fmt, ap); - if (tc->name) { - talloc_set_name_const(tc->name, ".name"); - } -} - -/* - add a name to an existing pointer -*/ -void talloc_set_name(const void *ptr, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); -} - -/* - more efficient way to add a name to a pointer - the name must point to a - true string constant -*/ -void talloc_set_name_const(const void *ptr, const char *name) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = name; -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named(const void *context, size_t size, const char *fmt, ...) -{ - va_list ap; - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) return NULL; - - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - return ptr; -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named_const(const void *context, size_t size, const char *name) -{ - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) { - return NULL; - } - - talloc_set_name_const(ptr, name); - - return ptr; -} - -/* - return the name of a talloc ptr, or "UNNAMED" -*/ -const char *talloc_get_name(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - if (tc->name == TALLOC_MAGIC_REFERENCE) { - return ".reference"; - } - if (tc->name) { - return tc->name; - } - return "UNNAMED"; -} - -/* - this is for compatibility with older versions of talloc -*/ -void *talloc_init(const char *fmt, ...) -{ - va_list ap; - void *ptr; - - ptr = _talloc(NULL, 0); - if (ptr == NULL) return NULL; - - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - return ptr; -} - - -/* - free a talloc pointer. This also frees all child pointers of this - pointer recursively - - return 0 if the memory is actually freed, otherwise -1. The memory - will not be freed if the ref_count is > 1 or the destructor (if - any) returns non-zero -*/ -int talloc_free(void *ptr) -{ - struct talloc_chunk *tc; - - if (ptr == NULL) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->refs) { - talloc_reference_destructor(tc->refs); - return -1; - } - - if (tc->destructor) { - talloc_destructor_t d = tc->destructor; - if (d == (talloc_destructor_t)-1) { - return -1; - } - tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { - tc->destructor = d; - return -1; - } - tc->destructor = NULL; - } - - while (tc->child) { - /* we need to work out who will own an abandoned child - if it cannot be freed. In priority order, the first - choice is owner of any remaining reference to this - pointer, the second choice is our parent, and the - final choice is the null context. */ - void *child = tc->child+1; - const void *new_parent = null_context; - if (tc->child->refs) { - struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; - } - if (talloc_free(child) == -1) { - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; - } - talloc_steal(new_parent, child); - } - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->magic = TALLOC_MAGIC_FREE; - - free(tc); - return 0; -} - - - -/* - A talloc version of realloc. The context argument is only used if - ptr is NULL -*/ -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) -{ - struct talloc_chunk *tc; - void *new_ptr; - - /* size zero is equivalent to free() */ - if (size == 0) { - talloc_free(ptr); - return NULL; - } - - if (size >= MAX_TALLOC_SIZE) { - return NULL; - } - - /* realloc(NULL) is equavalent to malloc() */ - if (ptr == NULL) { - return talloc_named_const(context, size, name); - } - - tc = talloc_chunk_from_ptr(ptr); - - /* don't allow realloc on referenced pointers */ - if (tc->refs) { - return NULL; - } - - /* by resetting magic we catch users of the old memory */ - tc->magic = TALLOC_MAGIC_FREE; - -#if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); - if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); - free(tc); - } -#else - new_ptr = realloc(tc, size + sizeof(*tc)); -#endif - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - return NULL; - } - - tc = new_ptr; - tc->magic = TALLOC_MAGIC; - if (tc->parent) { - tc->parent->child = new_ptr; - } - - if (tc->prev) { - tc->prev->next = tc; - } - if (tc->next) { - tc->next->prev = tc; - } - - tc->size = size; - talloc_set_name_const(tc+1, name); - - return (void *)(tc+1); -} - -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred -*/ -void *talloc_steal(const void *new_ctx, const void *ptr) -{ - struct talloc_chunk *tc, *new_tc; - - if (!ptr) { - return NULL; - } - - if (new_ctx == NULL) { - new_ctx = null_context; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (new_ctx == NULL) { - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = tc->next = tc->prev = NULL; - return discard_const_p(void, ptr); - } - - new_tc = talloc_chunk_from_ptr(new_ctx); - - if (tc == new_tc) { - return discard_const_p(void, ptr); - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = new_tc; - if (new_tc->child) new_tc->child->parent = NULL; - _TLIST_ADD(new_tc->child, tc); - - return discard_const_p(void, ptr); -} - -/* - return the total size of a talloc pool (subtree) -*/ -off_t talloc_total_size(const void *ptr) -{ - off_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(ptr); - - total = tc->size; - for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); - } - return total; -} - -/* - return the total number of blocks in a talloc pool (subtree) -*/ -off_t talloc_total_blocks(const void *ptr) -{ - off_t total = 0; - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - total++; - for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); - } - return total; -} - -/* - return the number of external references to a pointer -*/ -static int talloc_reference_count(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - int ret = 0; - - for (h=tc->refs;h;h=h->next) { - ret++; - } - return ret; -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -static void talloc_report_depth(const void *ptr, FILE *f, int depth) -{ - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); - const char *name2 = talloc_get_name(handle->ptr); - fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); - } else { - const char *name = talloc_get_name(c+1); - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); - } - } - -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_full(const void *ptr, FILE *f) -{ - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - talloc_report_depth(ptr, f, 1); -} - -/* - report on memory usage by all children of a pointer -*/ -void talloc_report(const void *ptr, FILE *f) -{ - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); - } - -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report(null_context, stderr); - } -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null_full(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report_full(null_context, stderr); - } -} - -/* - enable leak reporting on exit -*/ -void talloc_enable_leak_report(void) -{ - null_context = talloc_named_const(NULL, 0, "null_context"); - atexit(talloc_report_null); -} - -/* - enable full leak reporting on exit -*/ -void talloc_enable_leak_report_full(void) -{ - null_context = talloc_named_const(NULL, 0, "null_context"); - atexit(talloc_report_null_full); -} - -/* - talloc and zero memory. -*/ -void *_talloc_zero(const void *ctx, size_t size, const char *name) -{ - void *p = talloc_named_const(ctx, size, name); - - if (p) { - memset(p, '\0', size); - } - - return p; -} - - -/* - memdup with a talloc. -*/ -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) -{ - void *newp = talloc_named_const(t, size, name); - - if (newp) { - memcpy(newp, p, size); - } - - return newp; -} - -/* - strdup with a talloc -*/ -char *talloc_strdup(const void *t, const char *p) -{ - char *ret; - if (!p) { - return NULL; - } - ret = talloc_memdup(t, p, strlen(p) + 1); - if (ret) { - talloc_set_name_const(ret, ret); - } - return ret; -} - -/* - strndup with a talloc -*/ -char *talloc_strndup(const void *t, const char *p, size_t n) -{ - size_t len; - char *ret; - - for (len=0; p[len] && len= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return talloc_named_const(ctx, el_size * count, name); -} - -/* - alloc an zero array, checking for integer overflow in the array size -*/ -void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return _talloc_zero(ctx, el_size * count, name); -} - - -/* - realloc an array, checking for integer overflow in the array size -*/ -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - ptr = talloc_realloc(ctx, ptr, el_size * count); - if (ptr) { - talloc_set_name_const(ptr, name); - } - return ptr; -} - -/* - a function version of talloc_realloc(), so it can be passed as a function pointer - to libraries that want a realloc function (a realloc function encapsulates - all the basic capabilities of an allocation library, which is why this is useful) -*/ -void *talloc_realloc_fn(const void *context, void *ptr, size_t size) -{ - return _talloc_realloc(context, ptr, size, NULL); -} diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c deleted file mode 100644 index ce1a325ebd..0000000000 --- a/source4/lib/talloc.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* - Samba Unix SMB/CIFS implementation. - - Samba trivial allocation library - new interface - - NOTE: Please read talloc_guide.txt for full documentation - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - inspired by http://swapped.cc/halloc/ -*/ - - -#ifdef _SAMBA_BUILD_ -#include "includes.h" -#else -#include -#include -#include -#include -#include -#include "talloc.h" -#endif - -/* use this to force every realloc to change the pointer, to stress test - code that might not cope */ -#define ALWAYS_REALLOC 0 - - -#define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 -#define TALLOC_MAGIC_REFERENCE ((const char *)1) - -/* by default we abort when given a bad pointer (such as when talloc_free() is called - on a pointer that came from malloc() */ -#ifndef TALLOC_ABORT -#define TALLOC_ABORT(reason) abort() -#endif - -#ifndef discard_const_p -#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) -# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) -#else -# define discard_const_p(type, ptr) ((type *)(ptr)) -#endif -#endif - -/* this null_context is only used if talloc_enable_leak_report() or - talloc_enable_leak_report_full() is called, otherwise it remains - NULL -*/ -static const void *null_context; - - -struct talloc_reference_handle { - struct talloc_reference_handle *next, *prev; - void *ptr; -}; - -typedef int (*talloc_destructor_t)(void *); - -struct talloc_chunk { - struct talloc_chunk *next, *prev; - struct talloc_chunk *parent, *child; - struct talloc_reference_handle *refs; - size_t size; - unsigned magic; - talloc_destructor_t destructor; - const char *name; -}; - -/* panic if we get a bad magic value */ -static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) -{ - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - } - - return tc; -} - -/* hook into the front of the list */ -#define _TLIST_ADD(list, p) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - (list)->prev = (p); \ - (p)->next = (list); \ - (p)->prev = NULL; \ - (list) = (p); \ - }\ -} while (0) - -/* remove an element from a list - element doesn't have to be in list. */ -#define _TLIST_REMOVE(list, p) \ -do { \ - if ((p) == (list)) { \ - (list) = (p)->next; \ - if (list) (list)->prev = NULL; \ - } else { \ - if ((p)->prev) (p)->prev->next = (p)->next; \ - if ((p)->next) (p)->next->prev = (p)->prev; \ - } \ - if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ -} while (0) - - -/* - return the parent chunk of a pointer -*/ -static struct talloc_chunk *talloc_parent_chunk(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - while (tc->prev) tc=tc->prev; - return tc->parent; -} - -/* - Allocate a bit of memory as a child of an existing pointer -*/ -void *_talloc(const void *context, size_t size) -{ - struct talloc_chunk *tc; - - if (context == NULL) { - context = null_context; - } - - if (size >= MAX_TALLOC_SIZE) { - return NULL; - } - - tc = malloc(sizeof(*tc)+size); - if (tc == NULL) return NULL; - - tc->size = size; - tc->magic = TALLOC_MAGIC; - tc->destructor = NULL; - tc->child = NULL; - tc->name = NULL; - tc->refs = NULL; - - if (context) { - struct talloc_chunk *parent = talloc_chunk_from_ptr(context); - - tc->parent = parent; - - if (parent->child) { - parent->child->parent = NULL; - } - - _TLIST_ADD(parent->child, tc); - } else { - tc->next = tc->prev = tc->parent = NULL; - } - - return (void *)(tc+1); -} - - -/* - setup a destructor to be called on free of a pointer - the destructor should return 0 on success, or -1 on failure. - if the destructor fails then the free is failed, and the memory can - be continued to be used -*/ -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->destructor = destructor; -} - -/* - increase the reference count on a piece of memory. -*/ -void talloc_increase_ref_count(const void *ptr) -{ - talloc_reference(null_context, ptr); -} - -/* - helper for talloc_reference() -*/ -static int talloc_reference_destructor(void *ptr) -{ - struct talloc_reference_handle *handle = ptr; - struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); - struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); - if (tc1->destructor != (talloc_destructor_t)-1) { - tc1->destructor = NULL; - } - _TLIST_REMOVE(tc2->refs, handle); - talloc_free(handle); - return 0; -} - -/* - make a secondary reference to a pointer, hanging off the given context. - the pointer remains valid until both the original caller and this given - context are freed. - - the major use for this is when two different structures need to reference the - same underlying data, and you want to be able to free the two instances separately, - and in either order -*/ -void *talloc_reference(const void *context, const void *ptr) -{ - struct talloc_chunk *tc; - struct talloc_reference_handle *handle; - if (ptr == NULL) return NULL; - - tc = talloc_chunk_from_ptr(ptr); - handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); - - if (handle == NULL) return NULL; - - /* note that we hang the destructor off the handle, not the - main context as that allows the caller to still setup their - own destructor on the context if they want to */ - talloc_set_destructor(handle, talloc_reference_destructor); - handle->ptr = discard_const_p(void, ptr); - _TLIST_ADD(tc->refs, handle); - return handle->ptr; -} - -/* - remove a secondary reference to a pointer. This undo's what - talloc_reference() has done. The context and pointer arguments - must match those given to a talloc_reference() -*/ -static int talloc_unreference(const void *context, const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - - if (context == NULL) { - context = null_context; - } - - for (h=tc->refs;h;h=h->next) { - struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; - } - if (h == NULL) { - return -1; - } - - talloc_set_destructor(h, NULL); - _TLIST_REMOVE(tc->refs, h); - talloc_free(h); - return 0; -} - -/* - remove a specific parent context from a pointer. This is a more - controlled varient of talloc_free() -*/ -int talloc_unlink(const void *context, void *ptr) -{ - struct talloc_chunk *tc_p, *new_p; - void *new_parent; - - if (ptr == NULL) { - return -1; - } - - if (context == NULL) { - context = null_context; - } - - if (talloc_unreference(context, ptr) == 0) { - return 0; - } - - if (context == NULL) { - if (talloc_parent_chunk(ptr) != NULL) { - return -1; - } - } else { - if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { - return -1; - } - } - - tc_p = talloc_chunk_from_ptr(ptr); - - if (tc_p->refs == NULL) { - return talloc_free(ptr); - } - - new_p = talloc_parent_chunk(tc_p->refs); - if (new_p) { - new_parent = new_p+1; - } else { - new_parent = NULL; - } - - if (talloc_unreference(new_parent, ptr) != 0) { - return -1; - } - - talloc_steal(new_parent, ptr); - - return 0; -} - -/* - add a name to an existing pointer - va_list version -*/ -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = talloc_vasprintf(ptr, fmt, ap); - if (tc->name) { - talloc_set_name_const(tc->name, ".name"); - } -} - -/* - add a name to an existing pointer -*/ -void talloc_set_name(const void *ptr, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); -} - -/* - more efficient way to add a name to a pointer - the name must point to a - true string constant -*/ -void talloc_set_name_const(const void *ptr, const char *name) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = name; -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named(const void *context, size_t size, const char *fmt, ...) -{ - va_list ap; - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) return NULL; - - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - return ptr; -} - -/* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named_const(const void *context, size_t size, const char *name) -{ - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) { - return NULL; - } - - talloc_set_name_const(ptr, name); - - return ptr; -} - -/* - return the name of a talloc ptr, or "UNNAMED" -*/ -const char *talloc_get_name(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - if (tc->name == TALLOC_MAGIC_REFERENCE) { - return ".reference"; - } - if (tc->name) { - return tc->name; - } - return "UNNAMED"; -} - -/* - this is for compatibility with older versions of talloc -*/ -void *talloc_init(const char *fmt, ...) -{ - va_list ap; - void *ptr; - - ptr = _talloc(NULL, 0); - if (ptr == NULL) return NULL; - - va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); - va_end(ap); - - return ptr; -} - - -/* - free a talloc pointer. This also frees all child pointers of this - pointer recursively - - return 0 if the memory is actually freed, otherwise -1. The memory - will not be freed if the ref_count is > 1 or the destructor (if - any) returns non-zero -*/ -int talloc_free(void *ptr) -{ - struct talloc_chunk *tc; - - if (ptr == NULL) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->refs) { - talloc_reference_destructor(tc->refs); - return -1; - } - - if (tc->destructor) { - talloc_destructor_t d = tc->destructor; - if (d == (talloc_destructor_t)-1) { - return -1; - } - tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { - tc->destructor = d; - return -1; - } - tc->destructor = NULL; - } - - while (tc->child) { - /* we need to work out who will own an abandoned child - if it cannot be freed. In priority order, the first - choice is owner of any remaining reference to this - pointer, the second choice is our parent, and the - final choice is the null context. */ - void *child = tc->child+1; - const void *new_parent = null_context; - if (tc->child->refs) { - struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; - } - if (talloc_free(child) == -1) { - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; - } - talloc_steal(new_parent, child); - } - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->magic = TALLOC_MAGIC_FREE; - - free(tc); - return 0; -} - - - -/* - A talloc version of realloc. The context argument is only used if - ptr is NULL -*/ -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) -{ - struct talloc_chunk *tc; - void *new_ptr; - - /* size zero is equivalent to free() */ - if (size == 0) { - talloc_free(ptr); - return NULL; - } - - if (size >= MAX_TALLOC_SIZE) { - return NULL; - } - - /* realloc(NULL) is equavalent to malloc() */ - if (ptr == NULL) { - return talloc_named_const(context, size, name); - } - - tc = talloc_chunk_from_ptr(ptr); - - /* don't allow realloc on referenced pointers */ - if (tc->refs) { - return NULL; - } - - /* by resetting magic we catch users of the old memory */ - tc->magic = TALLOC_MAGIC_FREE; - -#if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); - if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); - free(tc); - } -#else - new_ptr = realloc(tc, size + sizeof(*tc)); -#endif - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - return NULL; - } - - tc = new_ptr; - tc->magic = TALLOC_MAGIC; - if (tc->parent) { - tc->parent->child = new_ptr; - } - - if (tc->prev) { - tc->prev->next = tc; - } - if (tc->next) { - tc->next->prev = tc; - } - - tc->size = size; - talloc_set_name_const(tc+1, name); - - return (void *)(tc+1); -} - -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred -*/ -void *talloc_steal(const void *new_ctx, const void *ptr) -{ - struct talloc_chunk *tc, *new_tc; - - if (!ptr) { - return NULL; - } - - if (new_ctx == NULL) { - new_ctx = null_context; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (new_ctx == NULL) { - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = tc->next = tc->prev = NULL; - return discard_const_p(void, ptr); - } - - new_tc = talloc_chunk_from_ptr(new_ctx); - - if (tc == new_tc) { - return discard_const_p(void, ptr); - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = new_tc; - if (new_tc->child) new_tc->child->parent = NULL; - _TLIST_ADD(new_tc->child, tc); - - return discard_const_p(void, ptr); -} - -/* - return the total size of a talloc pool (subtree) -*/ -off_t talloc_total_size(const void *ptr) -{ - off_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { - return 0; - } - - tc = talloc_chunk_from_ptr(ptr); - - total = tc->size; - for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); - } - return total; -} - -/* - return the total number of blocks in a talloc pool (subtree) -*/ -off_t talloc_total_blocks(const void *ptr) -{ - off_t total = 0; - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - total++; - for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); - } - return total; -} - -/* - return the number of external references to a pointer -*/ -static int talloc_reference_count(const void *ptr) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - struct talloc_reference_handle *h; - int ret = 0; - - for (h=tc->refs;h;h=h->next) { - ret++; - } - return ret; -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -static void talloc_report_depth(const void *ptr, FILE *f, int depth) -{ - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); - const char *name2 = talloc_get_name(handle->ptr); - fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); - } else { - const char *name = talloc_get_name(c+1); - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); - } - } - -} - -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_full(const void *ptr, FILE *f) -{ - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - talloc_report_depth(ptr, f, 1); -} - -/* - report on memory usage by all children of a pointer -*/ -void talloc_report(const void *ptr, FILE *f) -{ - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); - } - -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report(null_context, stderr); - } -} - -/* - report on any memory hanging off the null context -*/ -static void talloc_report_null_full(void) -{ - if (talloc_total_size(null_context) != 0) { - talloc_report_full(null_context, stderr); - } -} - -/* - enable leak reporting on exit -*/ -void talloc_enable_leak_report(void) -{ - null_context = talloc_named_const(NULL, 0, "null_context"); - atexit(talloc_report_null); -} - -/* - enable full leak reporting on exit -*/ -void talloc_enable_leak_report_full(void) -{ - null_context = talloc_named_const(NULL, 0, "null_context"); - atexit(talloc_report_null_full); -} - -/* - talloc and zero memory. -*/ -void *_talloc_zero(const void *ctx, size_t size, const char *name) -{ - void *p = talloc_named_const(ctx, size, name); - - if (p) { - memset(p, '\0', size); - } - - return p; -} - - -/* - memdup with a talloc. -*/ -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) -{ - void *newp = talloc_named_const(t, size, name); - - if (newp) { - memcpy(newp, p, size); - } - - return newp; -} - -/* - strdup with a talloc -*/ -char *talloc_strdup(const void *t, const char *p) -{ - char *ret; - if (!p) { - return NULL; - } - ret = talloc_memdup(t, p, strlen(p) + 1); - if (ret) { - talloc_set_name_const(ret, ret); - } - return ret; -} - -/* - strndup with a talloc -*/ -char *talloc_strndup(const void *t, const char *p, size_t n) -{ - size_t len; - char *ret; - - for (len=0; p[len] && len= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return talloc_named_const(ctx, el_size * count, name); -} - -/* - alloc an zero array, checking for integer overflow in the array size -*/ -void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - return _talloc_zero(ctx, el_size * count, name); -} - - -/* - realloc an array, checking for integer overflow in the array size -*/ -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - ptr = talloc_realloc(ctx, ptr, el_size * count); - if (ptr) { - talloc_set_name_const(ptr, name); - } - return ptr; -} - -/* - a function version of talloc_realloc(), so it can be passed as a function pointer - to libraries that want a realloc function (a realloc function encapsulates - all the basic capabilities of an allocation library, which is why this is useful) -*/ -void *talloc_realloc_fn(const void *context, void *ptr, size_t size) -{ - return _talloc_realloc(context, ptr, size, NULL); -} diff --git a/source4/lib/talloc/Makefile.talloc b/source4/lib/talloc/Makefile.talloc new file mode 100644 index 0000000000..88cb0e7159 --- /dev/null +++ b/source4/lib/talloc/Makefile.talloc @@ -0,0 +1,16 @@ +OPT = -g -ftest-coverage -fprofile-arcs +LIBS = -lgcov +#OPT = -g + +CFLAGS = $(OPT) -Wall + +all: testsuite + +testsuite: talloc.o testsuite.o + $(CC) $(CFLAGS) -o testsuite testsuite.o talloc.o $(LIBS) + +clean: + rm -f *~ *.o testsuite *.gc?? + +gcov: + gcov talloc.c diff --git a/source4/lib/talloc/config.m4 b/source4/lib/talloc/config.m4 new file mode 100644 index 0000000000..298c6691b9 --- /dev/null +++ b/source4/lib/talloc/config.m4 @@ -0,0 +1,3 @@ +if test x"$experimental" = x"yes"; then + SMB_LIBRARY_ENABLE(libtalloc,YES) +fi diff --git a/source4/lib/talloc/config.mk b/source4/lib/talloc/config.mk new file mode 100644 index 0000000000..2f38fe04ed --- /dev/null +++ b/source4/lib/talloc/config.mk @@ -0,0 +1,23 @@ +################################################ +# Start SUBSYSTEM LIBTALLOC +[SUBSYSTEM::LIBTALLOC] +INIT_OBJ_FILES = \ + lib/talloc/talloc.o +REQUIRED_SUBSYSTEMS = \ + LIBREPLACE +# +# End SUBSYSTEM LIBTALLOC +################################################ + +################################################ +# Start LIBRARY LIBTALLOC +[LIBRARY::libtalloc] +MAJOR_VERSION = 0 +MINOR_VERSION = 0 +RELEASE_VERSION = 1 +REQUIRED_SUBSYSTEMS = \ + LIBTALLOC +# +# End LIBRARY LIBTALLOC +################################################ + diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c new file mode 100644 index 0000000000..4666e28288 --- /dev/null +++ b/source4/lib/talloc/talloc.c @@ -0,0 +1,1006 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + + +#ifdef _SAMBA_BUILD_ +#include "includes.h" +#else +#include +#include +#include +#include +#include +#include "talloc.h" +#endif + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC 0xe814ec4f +#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#endif +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static const void *null_context; + + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; +}; + +typedef int (*talloc_destructor_t)(void *); + +struct talloc_chunk { + struct talloc_chunk *next, *prev; + struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; + size_t size; + unsigned magic; + talloc_destructor_t destructor; + const char *name; +}; + +/* panic if we get a bad magic value */ +static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; + if (tc->magic != TALLOC_MAGIC) { + if (tc->magic == TALLOC_MAGIC_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } else { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + } + + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + return tc->parent; +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + context = null_context; + } + + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + + tc = malloc(sizeof(*tc)+size); + if (tc == NULL) return NULL; + + tc->size = size; + tc->magic = TALLOC_MAGIC; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (context) { + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); + + tc->parent = parent; + + if (parent->child) { + parent->child->parent = NULL; + } + + _TLIST_ADD(parent->child, tc); + } else { + tc->next = tc->prev = tc->parent = NULL; + } + + return (void *)(tc+1); +} + + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +void talloc_increase_ref_count(const void *ptr) +{ + talloc_reference(null_context, ptr); +} + +/* + helper for talloc_reference() +*/ +static int talloc_reference_destructor(void *ptr) +{ + struct talloc_reference_handle *handle = ptr; + struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); + if (tc1->destructor != (talloc_destructor_t)-1) { + tc1->destructor = NULL; + } + _TLIST_REMOVE(tc2->refs, handle); + talloc_free(handle); + return 0; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *talloc_reference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (ptr == NULL) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = talloc_named_const(context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); + + if (handle == NULL) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (context == NULL) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if ((p==NULL && context==NULL) || p+1 == context) break; + } + if (h == NULL) { + return -1; + } + + talloc_set_destructor(h, NULL); + _TLIST_REMOVE(tc->refs, h); + talloc_free(h); + return 0; +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return talloc_free(ptr); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = new_p+1; + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + talloc_steal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = talloc_vasprintf(ptr, fmt, ap); + if (tc->name) { + talloc_set_name_const(tc->name, ".name"); + } +} + +/* + add a name to an existing pointer +*/ +void talloc_set_name(const void *ptr, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named(const void *context, size_t size, const char *fmt, ...) +{ + va_list ap; + void *ptr; + + ptr = _talloc(context, size); + if (ptr == NULL) return NULL; + + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + return ptr; +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = _talloc(context, size); + if (ptr == NULL) { + return NULL; + } + + talloc_set_name_const(ptr, name); + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +const char *talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (tc->name == TALLOC_MAGIC_REFERENCE) { + return ".reference"; + } + if (tc->name) { + return tc->name; + } + return "UNNAMED"; +} + +/* + this is for compatibility with older versions of talloc +*/ +void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + + ptr = _talloc(NULL, 0); + if (ptr == NULL) return NULL; + + va_start(ap, fmt); + talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + return ptr; +} + + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +int talloc_free(void *ptr) +{ + struct talloc_chunk *tc; + + if (ptr == NULL) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->refs) { + talloc_reference_destructor(tc->refs); + return -1; + } + + if (tc->destructor) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = tc->child+1; + const void *new_parent = null_context; + if (tc->child->refs) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = p+1; + } + if (talloc_free(child) == -1) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = p+1; + } + talloc_steal(new_parent, child); + } + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->magic = TALLOC_MAGIC_FREE; + + free(tc); + return 0; +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + + /* size zero is equivalent to free() */ + if (size == 0) { + talloc_free(ptr); + return NULL; + } + + if (size >= MAX_TALLOC_SIZE) { + return NULL; + } + + /* realloc(NULL) is equavalent to malloc() */ + if (ptr == NULL) { + return talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (tc->refs) { + return NULL; + } + + /* by resetting magic we catch users of the old memory */ + tc->magic = TALLOC_MAGIC_FREE; + +#if ALWAYS_REALLOC + new_ptr = malloc(size + sizeof(*tc)); + if (new_ptr) { + memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + free(tc); + } +#else + new_ptr = realloc(tc, size + sizeof(*tc)); +#endif + if (!new_ptr) { + tc->magic = TALLOC_MAGIC; + return NULL; + } + + tc = new_ptr; + tc->magic = TALLOC_MAGIC; + if (tc->parent) { + tc->parent->child = new_ptr; + } + if (tc->child) { + tc->child->parent = new_ptr; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + tc->size = size; + talloc_set_name_const(tc+1, name); + + return (void *)(tc+1); +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred +*/ +void *talloc_steal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (!ptr) { + return NULL; + } + + if (new_ctx == NULL) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (new_ctx == NULL) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (tc == new_tc) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + +/* + return the total size of a talloc pool (subtree) +*/ +off_t talloc_total_size(const void *ptr) +{ + off_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + total = tc->size; + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(c+1); + } + return total; +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +off_t talloc_total_blocks(const void *ptr) +{ + off_t total = 0; + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(c+1); + } + return total; +} + +/* + return the number of external references to a pointer +*/ +static int talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + int ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth(const void *ptr, FILE *f, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *handle = (void *)(c+1); + const char *name2 = talloc_get_name(handle->ptr); + fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); + } else { + const char *name = talloc_get_name(c+1); + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1), + talloc_reference_count(c+1)); + talloc_report_depth(c+1, f, depth+1); + } + } + +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + talloc_report_depth(ptr, f, 1); +} + +/* + report on memory usage by all children of a pointer +*/ +void talloc_report(const void *ptr, FILE *f) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(ptr), + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + + tc = talloc_chunk_from_ptr(ptr); + + for (c=tc->child;c;c=c->next) { + fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", + talloc_get_name(c+1), + (unsigned long)talloc_total_size(c+1), + (unsigned long)talloc_total_blocks(c+1)); + } + +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); + } +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); + } +} + +/* + enable leak reporting on exit +*/ +void talloc_enable_leak_report(void) +{ + null_context = talloc_named_const(NULL, 0, "null_context"); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +void talloc_enable_leak_report_full(void) +{ + null_context = talloc_named_const(NULL, 0, "null_context"); + atexit(talloc_report_null_full); +} + +/* + talloc and zero memory. +*/ +void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + + +/* + memdup with a talloc. +*/ +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = talloc_named_const(t, size, name); + + if (newp) { + memcpy(newp, p, size); + } + + return newp; +} + +/* + strdup with a talloc +*/ +char *talloc_strdup(const void *t, const char *p) +{ + char *ret; + if (!p) { + return NULL; + } + ret = talloc_memdup(t, p, strlen(p) + 1); + if (ret) { + talloc_set_name_const(ret, ret); + } + return ret; +} + +/* + strndup with a talloc +*/ +char *talloc_strndup(const void *t, const char *p, size_t n) +{ + size_t len; + char *ret; + + for (len=0; p[len] && len= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + ptr = talloc_realloc(ctx, ptr, el_size * count); + if (ptr) { + talloc_set_name_const(ptr, name); + } + return ptr; +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h new file mode 100644 index 0000000000..6ebba447aa --- /dev/null +++ b/source4/lib/talloc/talloc.h @@ -0,0 +1,96 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#define _STRING_LINE_(s) #s +#define _STRING_LINE2_(s) _STRING_LINE_(s) +#define __LINESTR__ _STRING_LINE2_(__LINE__) +#define __location__ __FILE__ ":" __LINESTR__ + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) +#define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) +#define talloc_p(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_zero_p(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_array_p(ctx, type, count) (type *)talloc_zero_array(ctx, sizeof(type), count, __location__) +#define talloc_array_p(ctx, type, count) (type *)talloc_array(ctx, sizeof(type), count, __location__) +#define talloc_realloc_p(ctx, p, type, count) (type *)talloc_realloc_array(ctx, p, sizeof(type), count, __location__) +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_destroy(ctx) talloc_free(ctx) + +#define malloc_p(type) (type *)malloc(sizeof(type)) +#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) +#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) + +#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) +#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) + +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a1, a2) +#endif + + +/* The following definitions come from lib/talloc.c */ +void *_talloc(const void *context, size_t size); +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); +void talloc_increase_ref_count(const void *ptr); +void *talloc_reference(const void *context, const void *ptr); +int talloc_unlink(const void *context, void *ptr); +void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int talloc_free(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *talloc_steal(const void *new_ctx, const void *ptr); +off_t talloc_total_size(const void *ptr); +off_t talloc_total_blocks(const void *ptr); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +char *talloc_strdup(const void *t, const char *p); +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, + const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); + +#endif + diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt new file mode 100644 index 0000000000..b3b148d476 --- /dev/null +++ b/source4/lib/talloc/talloc_guide.txt @@ -0,0 +1,492 @@ +Using talloc in Samba4 +---------------------- + +Andrew Tridgell +September 2004 + +The most current version of this document is available at + http://samba.org/ftp/unpacked/samba4/talloc_guide.txt + +If you are used to talloc from Samba3 then please read this carefully, +as talloc has changed a lot. + +The new talloc is a hierarchical, reference counted memory pool system +with destructors. Quite a mounthful really, but not too bad once you +get used to it. + +Perhaps the biggest change from Samba3 is that there is no distinction +between a "talloc context" and a "talloc pointer". Any pointer +returned from talloc() is itself a valid talloc context. This means +you can do this: + + struct foo *X = talloc_p(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + +and the pointer X->name would be a "child" of the talloc context "X" +which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx) +then it is all destroyed, whereas if you do talloc_free(X) then just X +and X->name are destroyed, and if you do talloc_free(X->name) then +just the name element of X is destroyed. + +If you think about this, then what this effectively gives you is an +n-ary tree, where you can free any part of the tree with +talloc_free(). + +If you find this confusing, then I suggest you run the LOCAL-TALLOC +smbtorture test to watch talloc in action. You may also like to add +your own tests to source/torture/local/talloc.c to clarify how some +particular situation is handled. + + +Performance +----------- + +All the additional features of talloc() over malloc() do come at a +price. We have a simple performance test in Samba4 that measures +talloc() versus malloc() performance, and it seems that talloc() is +about 10% slower than malloc() on my x86 Debian Linux box. For Samba, +the great reduction in code complexity that we get by using talloc +makes this worthwhile, especially as the total overhead of +talloc/malloc in Samba is already quite small. + + +talloc API +---------- + +The following is a complete guide to the talloc API. Read it all at +least twice. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc(const void *context, size_t size); + +The talloc() function is the core of the talloc library. It takes a +memory context, and returns a pointer to a new area of memory of the +given size. + +The returned pointer is itself a talloc context, so you can use it as +the context argument to more calls to talloc if you wish. + +The returned pointer is a "child" of the supplied context. This means +that if you talloc_free() the context then the new child disappears as +well. Alternatively you can free just the child. + +The context argument to talloc() can be NULL, in which case a new top +level context is created. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_p(const void *context, type); + +The talloc_p() macro is the equivalent of + + (type *)talloc(ctx, sizeof(type)) + +You should use it in preference to talloc() whenever possible, as it +provides additional type safety. It also automatically calls the +talloc_set_name_const() function with the name being a string holding +the name of the type. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_free(void *ptr); + +The talloc_free() function frees a piece of talloc memory, and all its +children. You can call talloc_free() on any pointer returned by +talloc(). + +The return value of talloc_free() indicates success or failure, with 0 +returned for success and -1 for failure. The only possible failure +condition is if the pointer had a destructor attached to it and the +destructor returned -1. See talloc_set_destructor() for details on +destructors. + +If this pointer has an additional parent when talloc_free() is called +then the memory is not actually released, but instead the most +recently established parent is destroyed. See talloc_reference() for +details on establishing additional parents. + +For more control on which parent is removed, see talloc_unlink() + +talloc_free() operates recursively on its children. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_reference(const void *context, const void *ptr); + +The talloc_reference() function makes "context" an additional parent +of "ptr". + +The return value of talloc_reference() is always the original pointer +"ptr", unless talloc ran out of memory in creating the reference in +which case it will return NULL (each additional reference consumes +around 48 bytes of memory on intel x86 platforms). + +If "ptr" is NULL, then the function is a no-op, and simply returns NULL. + +After creating a reference you can free it in one of the following +ways: + + - you can talloc_free() any parent of the original pointer. That + will reduce the number of parents of this pointer by 1, and will + cause this pointer to be freed if it runs out of parents. + + - you can talloc_free() the pointer itself. That will destroy the + most recently established parent to the pointer and leave the + pointer as a child of its current parent. + +For more control on which parent to remove, see talloc_unlink() + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_unlink(const void *context, const void *ptr); + +The talloc_unlink() function removes a specific parent from ptr. The +context passed must either be a context used in talloc_reference() +with this pointer, or must be a direct parent of ptr. + +Note that if the parent has already been removed using talloc_free() +then this function will fail and will return -1. Likewise, if "ptr" +is NULL, then the function will make no modifications and return -1. + +Usually you can just use talloc_free() instead of talloc_unlink(), but +sometimes it is useful to have the additional control on which parent +is removed. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + +The function talloc_set_destructor() sets the "destructor" for the +pointer "ptr". A destructor is a function that is called when the +memory used by a pointer is about to be released. The destructor +receives the pointer as an argument, and should return 0 for success +and -1 for failure. + +The destructor can do anything it wants to, including freeing other +pieces of memory. A common use for destructors is to clean up +operating system resources (such as open file descriptors) contained +in the structure the destructor is placed on. + +You can only place one destructor on a pointer. If you need more than +one destructor then you can create a zero-length child of the pointer +and place an additional destructor on that. + +To remove a destructor call talloc_set_destructor() with NULL for the +destructor. + +If your destructor attempts to talloc_free() the pointer that it is +the destructor for then talloc_free() will return -1 and the free will +be ignored. This would be a pointless operation anyway, as the +destructor is only called when the memory is just about to go away. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_increase_ref_count(const void *ptr); + +The talloc_increase_ref_count(ptr) function is exactly equivalent to: + + talloc_reference(NULL, ptr); + +You can use either syntax, depending on which you think is clearer in +your code. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name(const void *ptr, const char *fmt, ...); + +Each talloc pointer has a "name". The name is used principally for +debugging purposes, although it is also possible to set and get the +name on a pointer in as a way of "marking" pointers in your code. + +The main use for names on pointer is for "talloc reports". See +talloc_report() and talloc_report_full() for details. Also see +talloc_enable_leak_report() and talloc_enable_leak_report_full(). + +The talloc_set_name() function allocates memory as a child of the +pointer. It is logically equivalent to: + talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + +Note that multiple calls to talloc_set_name() will allocate more +memory without releasing the name. All of the memory is released when +the ptr is freed using talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_set_name_const(const void *ptr, const char *name); + +The function talloc_set_name_const() is just like talloc_set_name(), +but it takes a string constant, and is much faster. It is extensively +used by the "auto naming" macros, such as talloc_p(). + +This function does not allocate any memory. It just copies the +supplied pointer into the internal representation of the talloc +ptr. This means you must not pass a name pointer to memory that will +disappear before the ptr is freed with talloc_free(). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named(const void *context, size_t size, const char *fmt, ...); + +The talloc_named() function creates a named talloc pointer. It is +equivalent to: + + ptr = talloc(context, size); + talloc_set_name(ptr, fmt, ....); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_named_const(const void *context, size_t size, const char *name); + +This is equivalent to: + + ptr = talloc(context, size); + talloc_set_name_const(ptr, name); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +const char *talloc_get_name(const void *ptr); + +This returns the current name for the given talloc pointer. See +talloc_set_name() for details. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_init(const char *fmt, ...); + +This function creates a zero length named talloc context as a top +level context. It is equivalent to: + + talloc_named(NULL, 0, fmt, ...); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc(const void *context, void *ptr, size_t size); + +The talloc_realloc() function changes the size of a talloc +pointer. It has the following equivalences: + + talloc_realloc(context, NULL, size) ==> talloc(context, size); + talloc_realloc(context, ptr, 0) ==> talloc_free(ptr); + +The "context" argument is only used if "ptr" is not NULL, otherwise it +is ignored. + +talloc_realloc() returns the new pointer, or NULL on failure. The call +will fail either due to a lack of memory, or because the pointer has +more than one parent (see talloc_reference()). + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_steal(const void *new_ctx, const void *ptr); + +The talloc_steal() function changes the parent context of a talloc +pointer. It is typically used when the context that the pointer is +currently a child of is going to be freed and you wish to keep the +memory for a longer time. + +The talloc_steal() function returns the pointer that you pass it. It +does not have any failure modes. + +NOTE: It is possible to produce loops in the parent/child relationship +if you are not careful with talloc_steal(). No guarantees are provided +as to your sanity or the safety of your data if you do this. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +off_t talloc_total_size(const void *ptr); + +The talloc_total_size() function returns the total size in bytes used +by this pointer and all child pointers. Mostly useful for debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +off_t talloc_total_blocks(const void *ptr); + +The talloc_total_blocks() function returns the total memory block +count used by this pointer and all child pointers. Mostly useful for +debugging. + +Passing NULL is allowed, but it will only give a meaningful result if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report(const void *ptr, FILE *f); + +The talloc_report() function prints a summary report of all memory +used by ptr. One line of report is printed for each immediate child of +ptr, showing the total memory and number of blocks used by that child. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_report_full(const void *ptr, FILE *f); + +This provides a more detailed report than talloc_report(). It will +recursively print the ensire tree of memory referenced by the +pointer. References in the tree are shown by giving the name of the +pointer that is referenced. + +You can pass NULL for the pointer, in which case a report is printed +for the top level memory context, but only if +talloc_enable_leak_report() or talloc_enable_leak_report_full() has +been called. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report(void); + +This enables calling of talloc_report(NULL, stderr) when the program +exits. In Samba4 this is enabled by using the --leak-report command +line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical talloc report: + +talloc report on 'null_context' (total 267 bytes in 15 blocks) + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(UTF8,CP850) contains 42 bytes in 2 blocks + libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + iconv(CP850,UTF8) contains 42 bytes in 2 blocks + iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks + iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_leak_report_full(void); + +This enables calling of talloc_report_full(NULL, stderr) when the +program exits. In Samba4 this is enabled by using the +--leak-report-full command line option. + +For it to be useful, this function must be called before any other +talloc function as it establishes a "null context" that acts as the +top of the tree. If you don't call this function first then passing +NULL to talloc_report() or talloc_report_full() won't give you the +full tree printout. + +Here is a typical full report: + +full talloc report on 'root' (total 18 bytes in 8 blocks) + p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_zero(const void *ctx, size_t size); + +The talloc_zero() function is equivalent to: + + ptr = talloc(ctx, size); + if (ptr) memset(ptr, 0, size); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_memdup(const void *ctx, const void *p, size_t size); + +The talloc_memdup() function is equivalent to: + + ptr = talloc(ctx, size); + if (ptr) memcpy(ptr, p, size); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strdup(const void *ctx, const char *p); + +The talloc_strdup() function is equivalent to: + + ptr = talloc(ctx, strlen(p)+1); + if (ptr) memcpy(ptr, p, strlen(p)+1); + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_strndup(const void *t, const char *p, size_t n); + +The talloc_strndup() function is the talloc equivalent of the C +library function strndup() + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap); + +The talloc_vasprintf() function is the talloc equivalent of the C +library function vasprintf() + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf(const void *t, const char *fmt, ...); + +The talloc_asprintf() function is the talloc equivalent of the C +library function asprintf() + +This functions sets the name of the new pointer to the passed +string. This is equivalent to: + talloc_set_name_const(ptr, ptr) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +char *talloc_asprintf_append(char *s, const char *fmt, ...); + +The talloc_asprintf_append() function appends the given formatted +string to the given string. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_array_p(const void *ctx, type, uint_t count); + +The talloc_array_p() macro is equivalent to: + + (type *)talloc(ctx, sizeof(type) * count); + +except that it provides integer overflow protection for the multiply, +returning NULL if the multiply overflows. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_p(const void *ctx, void *ptr, type, uint_t count); + +The talloc_realloc_p() macro is equivalent to: + + (type *)talloc_realloc(ctx, ptr, sizeof(type) * count); + +except that it provides integer overflow protection for the multiply, +returning NULL if the multiply overflows. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size); + +This is a non-macro version of talloc_realloc(), which is useful +as libraries sometimes want a ralloc function pointer. A realloc() +implementation encapsulates the functionality of malloc(), free() and +realloc() in one call, which is why it is useful to be able to pass +around a single function pointer. + diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c new file mode 100644 index 0000000000..22444b1116 --- /dev/null +++ b/source4/lib/talloc/testsuite.c @@ -0,0 +1,785 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef _SAMBA_BUILD_ +#include "includes.h" +#else +#include +#include +#include +#include +#include +#include +#include "talloc.h" +#endif + +/* the test suite can be built standalone, or as part of Samba */ +#ifndef _SAMBA_BUILD_ +typedef enum {False=0,True=1} BOOL; + +static struct timeval timeval_current(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv; +} + +static double timeval_elapsed(struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return (tv2.tv_sec - tv->tv_sec) + + (tv2.tv_usec - tv->tv_usec)*1.0e-6; +} +#endif /* _SAMBA_BUILD_ */ + + +#define CHECK_SIZE(ptr, tsize) do { \ + if (talloc_total_size(ptr) != (tsize)) { \ + printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \ + #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize); \ + talloc_report_full(ptr, stdout); \ + return False; \ + } \ +} while (0) + +#define CHECK_BLOCKS(ptr, tblocks) do { \ + if (talloc_total_blocks(ptr) != (tblocks)) { \ + printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \ + #ptr, \ + (unsigned)talloc_total_blocks(ptr), \ + (unsigned)tblocks); \ + talloc_report_full(ptr, stdout); \ + return False; \ + } \ +} while (0) + + +/* + test references +*/ +static BOOL test_ref1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("TESTING SINGLE REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(p1, 1, "p2"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 2, "x2"); + talloc_named_const(p1, 3, "x3"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 2); + + printf("Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(r1, 1); + + printf("Freeing r1\n"); + talloc_free(r1); + talloc_report_full(NULL, stdout); + + printf("Testing NULL\n"); + if (talloc_reference(root, NULL)) { + return False; + } + + CHECK_BLOCKS(root, 1); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + +/* + test references +*/ +static BOOL test_ref2(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("TESTING DOUBLE REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 2); + + printf("Freeing ref\n"); + talloc_free(ref); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 4); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(r1, 1); + + printf("Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + +/* + test references +*/ +static BOOL test_ref3(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("TESTING PARENT REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(root, 1, "p2"); + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(p2, r1); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(p2, 2); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p2, 2); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + +/* + test references +*/ +static BOOL test_ref4(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("TESTING REFERRER REFERENCE FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 2); + + printf("Freeing r1\n"); + talloc_free(r1); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 5); + CHECK_BLOCKS(p2, 1); + + printf("Freeing p2\n"); + talloc_free(p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 4); + + printf("Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + + +/* + test references +*/ +static BOOL test_unlink1(void) +{ + void *root, *p1, *p2, *ref, *r1; + + printf("TESTING UNLINK\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + talloc_named_const(p1, 1, "x1"); + talloc_named_const(p1, 1, "x2"); + talloc_named_const(p1, 1, "x3"); + p2 = talloc_named_const(p1, 1, "p2"); + + r1 = talloc_named_const(p1, 1, "r1"); + ref = talloc_reference(r1, p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 7); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 2); + + printf("Unreferencing r1\n"); + talloc_unlink(r1, p2); + talloc_report_full(root, stdout); + + CHECK_BLOCKS(p1, 6); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(r1, 1); + + printf("Freeing p1\n"); + talloc_free(p1); + talloc_report_full(root, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + +static int fail_destructor(void *ptr) +{ + return -1; +} + +/* + miscellaneous tests to try to get a higher test coverage percentage +*/ +static BOOL test_misc(void) +{ + void *root, *p1; + char *p2; + double *d; + + printf("TESTING MISCELLANEOUS\n"); + + root = talloc(NULL, 0); + + p1 = talloc(root, 0x7fffffff); + if (p1) { + printf("failed: large talloc allowed\n"); + return False; + } + + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + talloc_free(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + talloc_unlink(NULL, p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + p2 = talloc_strdup(p1, "foo"); + if (talloc_unlink(root, p2) != -1) { + printf("failed: talloc_unlink() of non-reference context should return -1\n"); + return False; + } + if (talloc_unlink(p1, p2) != 0) { + printf("failed: talloc_unlink() of parent should succeed\n"); + return False; + } + talloc_free(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + + talloc_set_name(p1, "my name is %s", "foo"); + if (strcmp(talloc_get_name(p1), "my name is foo") != 0) { + printf("failed: wrong name after talloc_set_name\n"); + return False; + } + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + + talloc_set_name_const(p1, NULL); + if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) { + printf("failed: wrong name after talloc_set_name(NULL)\n"); + return False; + } + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + + + if (talloc_free(NULL) != -1) { + printf("talloc_free(NULL) should give -1\n"); + return False; + } + + talloc_set_destructor(p1, fail_destructor); + if (talloc_free(p1) != -1) { + printf("Failed destructor should cause talloc_free to fail\n"); + return False; + } + talloc_set_destructor(p1, NULL); + + talloc_report(root, stdout); + + + p2 = talloc_zero(p1, 20); + if (p2[19] != 0) { + printf("Failed to give zero memory\n"); + return False; + } + talloc_free(p2); + + if (talloc_strdup(root, NULL) != NULL) { + printf("failed: strdup on NULL should give NULL\n"); + return False; + } + + p2 = talloc_strndup(p1, "foo", 2); + if (strcmp("fo", p2) != 0) { + printf("failed: strndup doesn't work\n"); + return False; + } + p2 = talloc_asprintf_append(p2, "o%c", 'd'); + if (strcmp("food", p2) != 0) { + printf("failed: talloc_asprintf_append doesn't work\n"); + return False; + } + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 3); + + p2 = talloc_asprintf_append(NULL, "hello %s", "world"); + if (strcmp("hello world", p2) != 0) { + printf("failed: talloc_asprintf_append doesn't work\n"); + return False; + } + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 3); + talloc_free(p2); + + d = talloc_array_p(p1, double, 0x20000000); + if (d) { + printf("failed: integer overflow not detected\n"); + return False; + } + + d = talloc_realloc_p(p1, d, double, 0x20000000); + if (d) { + printf("failed: integer overflow not detected\n"); + return False; + } + + talloc_free(p1); + CHECK_BLOCKS(root, 1); + + p1 = talloc_named(root, 100, "%d bytes", 100); + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + talloc_unlink(root, p1); + + p1 = talloc_init("%d bytes", 200); + p2 = talloc_asprintf(p1, "my test '%s'", "string"); + CHECK_BLOCKS(p1, 3); + CHECK_SIZE(p2, 17); + CHECK_BLOCKS(root, 1); + talloc_unlink(NULL, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = talloc_named_const(root, 20, "p2"); + talloc_reference(p1, p2); + talloc_report_full(root, stdout); + talloc_unlink(root, p2); + talloc_report_full(root, stdout); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + talloc_unlink(p1, p2); + talloc_unlink(root, p1); + + p1 = talloc_named_const(root, 10, "p1"); + p2 = talloc_named_const(root, 20, "p2"); + talloc_reference(NULL, p2); + talloc_report_full(root, stdout); + talloc_unlink(root, p2); + talloc_report_full(root, stdout); + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + talloc_unlink(NULL, p2); + talloc_unlink(root, p1); + + /* Test that talloc_unlink is a no-op */ + + if (talloc_unlink(root, NULL) != -1) { + printf("failed: talloc_unlink(root, NULL) == -1\n"); + return False; + } + + talloc_report(root, stdout); + talloc_report(NULL, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + CHECK_SIZE(NULL, 0); + + talloc_enable_leak_report(); + talloc_enable_leak_report_full(); + + return True; +} + + +/* + test realloc +*/ +static BOOL test_realloc(void) +{ + void *root, *p1, *p2; + + printf("TESTING REALLOC\n"); + + root = talloc(NULL, 0); + + p1 = talloc(root, 10); + CHECK_SIZE(p1, 10); + + p1 = talloc_realloc(NULL, p1, 20); + CHECK_SIZE(p1, 20); + + talloc(p1, 0); + + p2 = talloc_realloc(p1, NULL, 30); + + talloc(p1, 0); + + p2 = talloc_realloc(p1, p2, 40); + + CHECK_SIZE(p2, 40); + CHECK_SIZE(root, 60); + CHECK_BLOCKS(p1, 4); + + p1 = talloc_realloc(NULL, p1, 20); + CHECK_SIZE(p1, 60); + + talloc_increase_ref_count(p2); + if (talloc_realloc(NULL, p2, 5) != NULL) { + printf("failed: talloc_realloc() on a referenced pointer should fail\n"); + return False; + } + CHECK_BLOCKS(p1, 4); + + talloc_realloc(NULL, p2, 0); + talloc_realloc(NULL, p2, 0); + CHECK_BLOCKS(p1, 3); + + if (talloc_realloc(NULL, p1, 0x7fffffff) != NULL) { + printf("failed: oversize talloc should fail\n"); + return False; + } + + talloc_realloc(NULL, p1, 0); + + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + + +/* + test realloc with a child +*/ +static BOOL test_realloc_child(void) +{ + void *root; + struct el1 { + int count; + struct el2 { + const char *name; + } **list; + } *el1; + struct el2 *el2; + + printf("TESTING REALLOC WITH CHILD\n"); + + root = talloc(NULL, 0); + + el1 = talloc_p(root, struct el1); + el1->list = talloc_p(el1, struct el2 *); + el1->list[0] = talloc_p(el1->list, struct el2); + el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); + + el2 = talloc_p(el1->list, struct el2); + + el1->list = talloc_realloc_p(el1, el1->list, struct el2 *, 2); + el1->list[1] = el2; + + talloc_free(root); + + return True; +} + +/* + test steal +*/ +static BOOL test_steal(void) +{ + void *root, *p1, *p2; + + printf("TESTING STEAL\n"); + + root = talloc(NULL, 0); + + p1 = talloc_array_p(root, char, 10); + CHECK_SIZE(p1, 10); + + p2 = talloc_realloc_p(root, NULL, char, 20); + CHECK_SIZE(p1, 10); + CHECK_SIZE(root, 30); + + if (talloc_steal(p1, NULL) != NULL) { + printf("failed: stealing NULL should give NULL\n"); + return False; + } + + if (talloc_steal(p1, p1) != p1) { + printf("failed: stealing to ourselves is a nop\n"); + return False; + } + CHECK_BLOCKS(root, 3); + CHECK_SIZE(root, 30); + + talloc_steal(NULL, p1); + talloc_steal(NULL, p2); + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(p1); + talloc_steal(root, p2); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 20); + + talloc_free(p2); + + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(root); + + p1 = talloc(NULL, 3); + CHECK_SIZE(NULL, 3); + talloc_free(p1); + + return True; +} + +/* + test ldb alloc fn +*/ +static BOOL test_ldb(void) +{ + void *root, *p1; + + printf("TESTING LDB\n"); + + root = talloc(NULL, 0); + + p1 = talloc_realloc_fn(root, NULL, 10); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 10); + p1 = talloc_realloc_fn(root, p1, 20); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 20); + p1 = talloc_realloc_fn(root, p1, 0); + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(root); + + + return True; +} + + +static BOOL test_unref_reparent(void) +{ + void *root, *p1, *p2, *c1; + + printf("TESTING UNREFERENCE AFTER PARENT FREED\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "orig parent"); + p2 = talloc_named_const(root, 1, "parent by reference"); + + c1 = talloc_named_const(p1, 1, "child"); + talloc_reference(p2, c1); + + talloc_free(p1); + talloc_unlink(p2, c1); + + CHECK_SIZE(root, 1); + + talloc_free(p2); + talloc_free(root); + + return True; +} + +/* + measure the speed of talloc versus malloc +*/ +static BOOL test_speed(void) +{ + void *ctx = talloc(NULL, 0); + unsigned count; + struct timeval tv; + + printf("MEASURING TALLOC VS MALLOC SPEED\n"); + + tv = timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + p1 = talloc(ctx, count); + p2 = talloc_strdup(p1, "foo bar"); + p3 = talloc(p1, 300); + talloc_free(p1); + count += 3; + } while (timeval_elapsed(&tv) < 5.0); + + printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + + talloc_free(ctx); + + tv = timeval_current(); + count = 0; + do { + void *p1, *p2, *p3; + p1 = malloc(count); + p2 = strdup("foo bar"); + p3 = malloc(300); + free(p1); + free(p2); + free(p3); + count += 3; + } while (timeval_elapsed(&tv) < 5.0); + + printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + + return True; +} + + +BOOL torture_local_talloc(void) +{ + BOOL ret = True; + + ret &= test_ref1(); + ret &= test_ref2(); + ret &= test_ref3(); + ret &= test_ref4(); + ret &= test_unlink1(); + ret &= test_misc(); + ret &= test_realloc(); + ret &= test_realloc_child(); + ret &= test_steal(); + ret &= test_unref_reparent(); + ret &= test_ldb(); + if (ret) { + ret &= test_speed(); + } + + return ret; +} + + + +#ifndef _SAMBA_BUILD_ + int main(void) +{ + if (!torture_local_talloc()) { + printf("ERROR: TESTSUIE FAILED\n"); + return -1; + } + return 0; +} +#endif -- cgit From 1a988ec9af7960616fb4661b20d86ff05146d836 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 07:49:29 +0000 Subject: r4474: - converted ldb to use talloc internally - added gcov flags to Makefile.ldb - expanded ldb test suite to get more coverage (This used to be commit 0ab98f50a7e0fe15347a99e5c29a6590a87729a0) --- source4/lib/ldb/Makefile.ldb | 28 ++- source4/lib/ldb/common/ldb_alloc.c | 176 ------------------ source4/lib/ldb/common/ldb_ldif.c | 52 +++--- source4/lib/ldb/common/ldb_modules.c | 33 ++-- source4/lib/ldb/common/ldb_msg.c | 54 +++--- source4/lib/ldb/common/ldb_parse.c | 119 +++++-------- source4/lib/ldb/common/ldb_utf8.c | 2 +- source4/lib/ldb/config.mk | 3 +- source4/lib/ldb/include/includes.h | 6 +- source4/lib/ldb/include/ldb.h | 46 +---- source4/lib/ldb/include/ldb_private.h | 10 +- source4/lib/ldb/include/talloc.h | 96 ---------- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 149 +++++----------- source4/lib/ldb/ldb_tdb/ldb_cache.c | 164 +++++++++-------- source4/lib/ldb/ldb_tdb/ldb_index.c | 327 +++++++++++++++++++--------------- source4/lib/ldb/ldb_tdb/ldb_match.c | 9 +- source4/lib/ldb/ldb_tdb/ldb_pack.c | 26 +-- source4/lib/ldb/ldb_tdb/ldb_search.c | 185 ++++++++----------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 200 +++++++++++---------- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 14 +- source4/lib/ldb/modules/skel.c | 8 +- source4/lib/ldb/modules/timestamps.c | 79 +++----- source4/lib/ldb/tests/test-generic.sh | 8 + source4/lib/ldb/tools/ldbadd.c | 4 +- source4/lib/ldb/tools/ldbedit.c | 28 +-- source4/lib/ldb/tools/ldbmodify.c | 8 +- source4/lib/ldb/tools/ldbsearch.c | 2 +- source4/lib/ldb/tools/ldbtest.c | 33 ++-- 28 files changed, 729 insertions(+), 1140 deletions(-) delete mode 100644 source4/lib/ldb/common/ldb_alloc.c delete mode 100644 source4/lib/ldb/include/talloc.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 721ba5f407..a472f949af 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -10,24 +10,33 @@ LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o endif TDBDIR=../tdb +TALLOCDIR=../talloc -CFLAGS=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. -I$(TDBDIR)/include -DUSE_MMAP=1 $(LDAP_FLAGS) -LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) +CFLAGS1=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ + -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. \ + -I$(TDBDIR)/include -I$(TALLOCDIR) -DUSE_MMAP=1 $(LDAP_FLAGS) +#GCOV_FLAGS = -ftest-coverage -fprofile-arcs +#GCOV_LIBS = -lgcov + +CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) + +LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(GCOV_LIBS) TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o +TALLOC_OBJ=$(TALLOCDIR)/talloc.o LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ ldb_tdb/ldb_cache.o -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/talloc.o \ +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ - common/ldb_alloc.o common/ldb_debug.o common/ldb_modules.o + common/ldb_debug.o common/ldb_modules.o MODULES_OBJ=modules/timestamps.o -OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) +OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a @@ -72,7 +81,7 @@ manpages: -man/build_manpages.sh clean: - rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) man/man?/*.[13] + rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] etags: etags */*.[ch] @@ -86,3 +95,10 @@ test-ldap: tests/test-ldap.sh test: test-tdb test-ldap + +gcov: + gcov -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov + gcov -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov + gcov -po common common/*.c 2| tee ldb_common.report.gcov + gcov -po modules modules/*.c 2| tee ldb_modules.report.gcov + gcov -po tools tools/*.c 2| tee ldb_tools.report.gcov diff --git a/source4/lib/ldb/common/ldb_alloc.c b/source4/lib/ldb/common/ldb_alloc.c deleted file mode 100644 index 7dc12b142e..0000000000 --- a/source4/lib/ldb/common/ldb_alloc.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb alloc - * - * Description: functions for memory allocation - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" - - -/* - this allows the user to choose their own allocation function -*/ -int ldb_set_alloc(struct ldb_context *ldb, - void *(*alloc)(const void *context, void *ptr, size_t size), - void *context) -{ - ldb->alloc_ops.alloc = alloc; - ldb->alloc_ops.context = context; - return 0; -} - -/* - this is the default memory allocation function -*/ -static void *ldb_default_alloc(const void *context, void *ptr, size_t size) -{ - /* by setting LDB_ALLOC_OFS to non-zero the test suite can - catch any places where we incorrectly use the libc alloc - funcitons directly */ -#define LDB_ALLOC_OFS 4 - /* we don't assume a modern realloc function */ - if (ptr == NULL) { - ptr = malloc(size+LDB_ALLOC_OFS); - if (ptr) return ((char *)ptr)+LDB_ALLOC_OFS; - return NULL; - } - if (size == 0) { - free(((char *)ptr)-LDB_ALLOC_OFS); - return NULL; - } - ptr = realloc(((char *)ptr)-LDB_ALLOC_OFS, size+LDB_ALLOC_OFS); - if (ptr) { - return ((char *)ptr)+LDB_ALLOC_OFS; - } - return NULL; -} - -/* - all memory allocation goes via this function -*/ -void *ldb_realloc(struct ldb_context *ldb, void *ptr, size_t size) -{ - if (!ldb->alloc_ops.alloc) { - ldb_set_alloc(ldb, ldb_default_alloc, NULL); - } - return ldb->alloc_ops.alloc(ldb->alloc_ops.context, ptr, size); -} - -void *ldb_malloc(struct ldb_context *ldb, size_t size) -{ - return ldb_realloc(ldb, NULL, size); -} - -void ldb_free(struct ldb_context *ldb, void *ptr) -{ - if (ptr != NULL) { - ldb_realloc(ldb, ptr, 0); - } -} - -void *ldb_strndup(struct ldb_context *ldb, const char *str, size_t maxlen) -{ - size_t len = strnlen(str, maxlen); - void *ret; - ret = ldb_realloc(ldb, NULL, len+1); - if (ret) { - memcpy(ret, str, len); - ((char *)ret)[len] = 0; - } - return ret; -} - -void *ldb_strdup(struct ldb_context *ldb, const char *str) -{ - size_t len = strlen(str); - void *ret; - ret = ldb_realloc(ldb, NULL, len+1); - if (ret) { - memcpy(ret, str, len+1); - } - return ret; -} - -/* - a ldb wrapper for asprintf(), using ldb_malloc() -*/ -int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) -{ - int len, len2; - va_list ap; - - *strp = NULL; - - va_start(ap, fmt); - len = vsnprintf(NULL, 0, fmt, ap); - va_end(ap); - if (len < 0) { - return len; - } - - *strp = ldb_malloc(ldb, len+1); - if (! *strp) { - return -1; - } - - va_start(ap, fmt); - len2 = vsnprintf(*strp, len+1, fmt, ap); - va_end(ap); - - if (len2 != len) { - /* buggy (or non-C99) vsnprintf function */ - ldb_free(ldb, *strp); - return -1; - } - - return len; -} - -/* - realloc an array, checking for integer overflow in the array size -*/ -void *ldb_realloc_array(struct ldb_context *ldb, - void *ptr, size_t el_size, unsigned count) -{ -#define MAX_MALLOC_SIZE 0x7fffffff - - if (count == 0 || - count >= MAX_MALLOC_SIZE/el_size) { - return NULL; - } - if (!ptr) { - return ldb_malloc(ldb, el_size * count); - } - return ldb_realloc(ldb, ptr, el_size * count); -} - diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 94e15805a6..d20a2a3553 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -97,7 +97,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) int bytes = (len*8 + 5)/6; char *out; - out = ldb_malloc(ldb, bytes+2); + out = talloc_array_p(ldb, char, bytes+2); if (!out) return NULL; for (i=0;imsg; + msg = ldif->msg; ret = fprintf_fn(private_data, "dn: %s\n", msg->dn); CHECK_RET; @@ -305,9 +305,9 @@ static char *next_chunk(struct ldb_context *ldb, if (chunk_size+1 >= alloc_size) { char *c2; alloc_size += 1024; - c2 = ldb_realloc_p(ldb, chunk, char, alloc_size); + c2 = talloc_realloc_p(ldb, chunk, char, alloc_size); if (!c2) { - ldb_free(ldb, chunk); + talloc_free(chunk); errno = ENOMEM; return NULL; } @@ -416,15 +416,7 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) */ void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif) { - struct ldb_message *msg = &ldif->msg; - unsigned int i; - for (i=0;inum_elements;i++) { - if (msg->elements[i].name) ldb_free(ldb, msg->elements[i].name); - if (msg->elements[i].values) ldb_free(ldb, msg->elements[i].values); - } - if (msg->elements) ldb_free(ldb, msg->elements); - if (msg->private_data) ldb_free(ldb, msg->private_data); - ldb_free(ldb, ldif); + talloc_free(ldif); } /* @@ -435,8 +427,8 @@ static int msg_add_empty(struct ldb_context *ldb, { struct ldb_message_element *el2, *el; - el2 = ldb_realloc_p(ldb, msg->elements, - struct ldb_message_element, msg->num_elements+1); + el2 = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!el2) { errno = ENOMEM; return -1; @@ -446,7 +438,7 @@ static int msg_add_empty(struct ldb_context *ldb, el = &msg->elements[msg->num_elements]; - el->name = ldb_strdup(ldb, name); + el->name = talloc_strdup(msg->elements, name); el->num_values = 0; el->values = NULL; el->flags = flags; @@ -476,11 +468,17 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, value.data = NULL; - ldif = ldb_malloc_p(ldb, struct ldb_ldif); + ldif = talloc_p(ldb, struct ldb_ldif); if (!ldif) return NULL; + ldif->msg = talloc_p(ldif, struct ldb_message); + if (ldif->msg == NULL) { + talloc_free(ldif); + return NULL; + } + ldif->changetype = LDB_CHANGETYPE_NONE; - msg = &ldif->msg; + msg = ldif->msg; msg->dn = NULL; msg->elements = NULL; @@ -558,8 +556,8 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, flags == el->flags) { /* its a continuation */ el->values = - ldb_realloc_p(ldb, el->values, - struct ldb_val, el->num_values+1); + talloc_realloc_p(msg->elements, el->values, + struct ldb_val, el->num_values+1); if (!el->values) { goto failed; } @@ -567,16 +565,16 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, el->num_values++; } else { /* its a new attribute */ - msg->elements = ldb_realloc_p(ldb, msg->elements, - struct ldb_message_element, - msg->num_elements+1); + msg->elements = talloc_realloc_p(ldif, msg->elements, + struct ldb_message_element, + msg->num_elements+1); if (!msg->elements) { goto failed; } el = &msg->elements[msg->num_elements]; el->flags = flags; - el->name = ldb_strdup(ldb, attr); - el->values = ldb_malloc_p(ldb, struct ldb_val); + el->name = talloc_strdup(msg->elements, attr); + el->values = talloc_p(msg->elements, struct ldb_val); if (!el->values || !el->name) { goto failed; } @@ -589,7 +587,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, return ldif; failed: - if (ldif) ldb_ldif_read_free(ldb, ldif); + talloc_free(ldif); return NULL; } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 71ec3fdc00..4f53535bc4 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -57,21 +57,19 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) pn = 0; if (options) { - for (i = 0; options[i] != NULL; i++) { - - if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) { - - p = q = ldb_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]); + if (strncmp(options[i], LDB_MODULE_PREFIX, + LDB_MODULE_PREFIX_LEN) == 0) { + p = q = talloc_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]); if (*q != ':') { - ldb_free(ldb, q); + talloc_free(q); return -1; } do { *p = '\0'; q = p + 1; pn++; - modules = ldb_realloc_array(ldb, modules, sizeof(char *), pn); + modules = talloc_realloc_p(ldb, modules, char *, pn); if (!modules) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); return -1; @@ -82,10 +80,12 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } } - if (!modules && strcmp("ldap", ldb->modules->ops->name)) { /* no modules in the options, look for @MODULES in the db (not for ldap) */ + if (!modules && strcmp("ldap", ldb->modules->ops->name)) { + /* no modules in the options, look for @MODULES in the + db (not for ldap) */ int ret, j, k; const char * const attrs[] = { "@MODULE" , NULL}; - struct ldb_message **msg; + struct ldb_message **msg = NULL; ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); if (ret == 0) { @@ -103,12 +103,12 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) for (j = 0; j < msg[0]->num_elements; j++) { for (k = 0; k < msg[0]->elements[j].num_values; k++) { pn++; - modules = ldb_realloc_array(ldb, modules, sizeof(char *), pn); + modules = talloc_realloc_p(ldb, modules, char *, pn); if (!modules) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); return -1; } - modules[pn - 1] = ldb_strndup(ldb, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length); + modules[pn - 1] = talloc_strndup(modules, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length); if (!modules[pn - 1]) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); return -1; @@ -116,13 +116,11 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } } } - ldb_search_free(ldb, msg); + talloc_free(msg); } if (modules) { - for (i = 0; i < pn; i++) { - if (strcmp(modules[i], "timestamps") == 0) { current = timestamps_module_init(ldb, options); if (!current) { @@ -274,10 +272,3 @@ const char *ldb_next_errstring(struct ldb_module *module) return module->next->ops->errstring(module->next); } -void ldb_next_cache_free(struct ldb_module *module) -{ - if (!module->next) { - return; - } - module->next->ops->cache_free(module->next); -} diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 3865e7afa9..89f8feb3c0 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -36,6 +36,13 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +/* + create a new ldb_message in a given memory context (NULL for top level) +*/ +struct ldb_message *ldb_msg_new(void *mem_ctx) +{ + return talloc_zero_p(mem_ctx, struct ldb_message); +} /* find an element in a message by attribute name @@ -88,7 +95,7 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, /* duplicate a ldb_val structure */ -struct ldb_val ldb_val_dup(struct ldb_context *ldb, +struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v) { struct ldb_val v2; @@ -100,7 +107,7 @@ struct ldb_val ldb_val_dup(struct ldb_context *ldb, /* the +1 is to cope with buggy C library routines like strndup that look one byte beyond */ - v2.data = ldb_malloc(ldb, v->length+1); + v2.data = talloc_array_p(mem_ctx, char, v->length+1); if (!v2.data) { v2.length = 0; return v2; @@ -119,8 +126,8 @@ int ldb_msg_add_empty(struct ldb_context *ldb, { struct ldb_message_element *els; - els = ldb_realloc_p(ldb, msg->elements, - struct ldb_message_element, msg->num_elements+1); + els = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!els) { errno = ENOMEM; return -1; @@ -129,7 +136,7 @@ int ldb_msg_add_empty(struct ldb_context *ldb, els[msg->num_elements].values = NULL; els[msg->num_elements].num_values = 0; els[msg->num_elements].flags = flags; - els[msg->num_elements].name = ldb_strdup(ldb, attr_name); + els[msg->num_elements].name = talloc_strdup(els, attr_name); if (!els[msg->num_elements].name) { return -1; } @@ -178,7 +185,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, return -1; } - vals = ldb_realloc_p(ldb, el->values, struct ldb_val, el->num_values+1); + vals = talloc_realloc_p(msg, el->values, struct ldb_val, el->num_values+1); if (!vals) { errno = ENOMEM; return -1; @@ -332,19 +339,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg) */ void ldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) { - int i, j; - - for (i=0;inum_elements;i++) { - struct ldb_message_element *el = &msg->elements[i]; - for (j=0;jnum_values;j++) { - ldb_free(ldb, el->values[j].data); - } - if (el->values) ldb_free(ldb, el->values); - ldb_free(ldb, el->name); - } - if (msg->elements) ldb_free(ldb, msg->elements); - ldb_free(ldb, msg->dn); - ldb_free(ldb, msg); + talloc_free(msg); } /* @@ -356,17 +351,17 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, struct ldb_message *msg2; int i, j; - msg2 = ldb_malloc_p(ldb, struct ldb_message); + msg2 = talloc_p(ldb, struct ldb_message); if (msg2 == NULL) return NULL; msg2->elements = NULL; msg2->num_elements = 0; msg2->private_data = NULL; - msg2->dn = ldb_strdup(ldb, msg->dn); + msg2->dn = talloc_strdup(msg2, msg->dn); if (msg2->dn == NULL) goto failed; - msg2->elements = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); + msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg->num_elements); if (msg2->elements == NULL) goto failed; for (i=0;inum_elements;i++) { @@ -376,15 +371,16 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, el2->flags = el1->flags; el2->num_values = 0; el2->values = NULL; - el2->name = ldb_strdup(ldb, el1->name); + el2->name = talloc_strdup(msg2->elements, el1->name); if (el2->name == NULL) goto failed; - el2->values = ldb_malloc_array_p(ldb, struct ldb_val, el1->num_values); + el2->values = talloc_array_p(msg2->elements, struct ldb_val, el1->num_values); for (j=0;jnum_values;j++) { el2->values[j] = ldb_val_dup(ldb, &el1->values[j]); if (el2->values[j].data == NULL && el1->values[j].length != 0) { goto failed; } + el2->values[j].data = talloc_steal(el2->values, el2->values[j].data); el2->num_values++; } @@ -394,7 +390,7 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, return msg2; failed: - ldb_msg_free(ldb, msg2); + talloc_free(msg2); return NULL; } @@ -417,8 +413,8 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, struct ldb_message_element *el1 = &msg2->elements[i-1]; struct ldb_message_element *el2 = &msg2->elements[i]; if (ldb_msg_element_compare_name(el1, el2) == 0) { - el1->values = ldb_realloc_p(ldb, el1->values, struct ldb_val, - el1->num_values + el2->num_values); + el1->values = talloc_realloc_p(msg2->elements, el1->values, struct ldb_val, + el1->num_values + el2->num_values); if (el1->values == NULL) { return NULL; } @@ -426,8 +422,8 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, el2->values, sizeof(struct ldb_val) * el2->num_values); el1->num_values += el2->num_values; - ldb_free(ldb, el2->name); - ldb_free(ldb, el2->values); + talloc_free(el2->name); + talloc_free(el2->values); if (i+1num_elements) { memmove(el2, el2+1, sizeof(struct ldb_message_element) * (msg2->num_elements - (i+1))); diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 1e00a05d55..6ee6f99253 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -65,7 +65,7 @@ a filter is defined by: /* return next token element. Caller frees */ -static char *ldb_parse_lex(struct ldb_context *ldb, const char **s, const char *sep) +static char *ldb_parse_lex(TALLOC_CTX *ctx, const char **s, const char *sep) { const char *p = *s; char *ret; @@ -81,7 +81,7 @@ static char *ldb_parse_lex(struct ldb_context *ldb, const char **s, const char * if (strchr(sep, *p)) { (*s) = p+1; - ret = ldb_strndup(ldb, p, 1); + ret = talloc_strndup(ctx, p, 1); if (!ret) { errno = ENOMEM; } @@ -96,7 +96,7 @@ static char *ldb_parse_lex(struct ldb_context *ldb, const char **s, const char * return NULL; } - ret = ldb_strndup(ldb, *s, p - *s); + ret = talloc_strndup(ctx, *s, p - *s); if (!ret) { errno = ENOMEM; } @@ -128,47 +128,46 @@ static const char *match_brace(const char *s) } -static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const char **s); +static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s); /* ::= */ -static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const char *s) +static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *ctx, const char *s) { char *eq, *val, *l; struct ldb_parse_tree *ret; - l = ldb_parse_lex(ldb, &s, LDB_ALL_SEP); + ret = talloc_p(ctx, struct ldb_parse_tree); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + l = ldb_parse_lex(ret, &s, LDB_ALL_SEP); if (!l) { + talloc_free(ret); return NULL; } if (strchr("()&|=", *l)) { - ldb_free(ldb, l); + talloc_free(ret); return NULL; } - eq = ldb_parse_lex(ldb, &s, LDB_ALL_SEP); + eq = ldb_parse_lex(ret, &s, LDB_ALL_SEP); if (!eq || strcmp(eq, "=") != 0) { - ldb_free(ldb, l); - if (eq) ldb_free(ldb, eq); + talloc_free(ret); return NULL; } - ldb_free(ldb, eq); + talloc_free(eq); - val = ldb_parse_lex(ldb, &s, ")"); + val = ldb_parse_lex(ret, &s, ")"); if (val && strchr("()&|", *val)) { - ldb_free(ldb, l); - if (val) ldb_free(ldb, val); + talloc_free(ret); return NULL; } - ret = ldb_malloc_p(ldb, struct ldb_parse_tree); - if (!ret) { - errno = ENOMEM; - return NULL; - } - ret->operation = LDB_OP_SIMPLE; ret->u.simple.attr = l; ret->u.simple.value.data = val; @@ -184,12 +183,12 @@ static struct ldb_parse_tree *ldb_parse_simple(struct ldb_context *ldb, const ch ::= '|' ::= | */ -static struct ldb_parse_tree *ldb_parse_filterlist(struct ldb_context *ldb, +static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, enum ldb_parse_op op, const char *s) { struct ldb_parse_tree *ret, *next; - ret = ldb_malloc_p(ldb, struct ldb_parse_tree); + ret = talloc_p(ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -197,31 +196,29 @@ static struct ldb_parse_tree *ldb_parse_filterlist(struct ldb_context *ldb, ret->operation = op; ret->u.list.num_elements = 1; - ret->u.list.elements = ldb_malloc_p(ldb, struct ldb_parse_tree *); + ret->u.list.elements = talloc_p(ret, struct ldb_parse_tree *); if (!ret->u.list.elements) { errno = ENOMEM; - ldb_free(ldb, ret); + talloc_free(ret); return NULL; } - ret->u.list.elements[0] = ldb_parse_filter(ldb, &s); + ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &s); if (!ret->u.list.elements[0]) { - ldb_free(ldb, ret->u.list.elements); - ldb_free(ldb, ret); + talloc_free(ret); return NULL; } while (isspace(*s)) s++; - while (*s && (next = ldb_parse_filter(ldb, &s))) { + while (*s && (next = ldb_parse_filter(ret->u.list.elements, &s))) { struct ldb_parse_tree **e; - e = ldb_realloc_p(ldb, ret->u.list.elements, - struct ldb_parse_tree *, - ret->u.list.num_elements+1); + e = talloc_realloc_p(ret, ret->u.list.elements, + struct ldb_parse_tree *, + ret->u.list.num_elements+1); if (!e) { errno = ENOMEM; - ldb_parse_tree_free(ldb, next); - ldb_parse_tree_free(ldb, ret); + talloc_free(ret); return NULL; } ret->u.list.elements = e; @@ -237,20 +234,20 @@ static struct ldb_parse_tree *ldb_parse_filterlist(struct ldb_context *ldb, /* ::= '!' */ -static struct ldb_parse_tree *ldb_parse_not(struct ldb_context *ldb, const char *s) +static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *ctx, const char *s) { struct ldb_parse_tree *ret; - ret = ldb_malloc_p(ldb, struct ldb_parse_tree); + ret = talloc_p(ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; } ret->operation = LDB_OP_NOT; - ret->u.not.child = ldb_parse_filter(ldb, &s); + ret->u.not.child = ldb_parse_filter(ret, &s); if (!ret->u.not.child) { - ldb_free(ldb, ret); + talloc_free(ret); return NULL; } @@ -261,49 +258,48 @@ static struct ldb_parse_tree *ldb_parse_not(struct ldb_context *ldb, const char parse a filtercomp ::= | | | */ -static struct ldb_parse_tree *ldb_parse_filtercomp(struct ldb_context *ldb, - const char *s) +static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *ctx, const char *s) { while (isspace(*s)) s++; switch (*s) { case '&': - return ldb_parse_filterlist(ldb, LDB_OP_AND, s+1); + return ldb_parse_filterlist(ctx, LDB_OP_AND, s+1); case '|': - return ldb_parse_filterlist(ldb, LDB_OP_OR, s+1); + return ldb_parse_filterlist(ctx, LDB_OP_OR, s+1); case '!': - return ldb_parse_not(ldb, s+1); + return ldb_parse_not(ctx, s+1); case '(': case ')': return NULL; } - return ldb_parse_simple(ldb, s); + return ldb_parse_simple(ctx, s); } /* ::= '(' ')' */ -static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const char **s) +static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s) { char *l, *s2; const char *p, *p2; struct ldb_parse_tree *ret; - l = ldb_parse_lex(ldb, s, LDB_ALL_SEP); + l = ldb_parse_lex(ctx, s, LDB_ALL_SEP); if (!l) { return NULL; } if (strcmp(l, "(") != 0) { - ldb_free(ldb, l); + talloc_free(l); return NULL; } - ldb_free(ldb, l); + talloc_free(l); p = match_brace(*s); if (!p) { @@ -311,14 +307,14 @@ static struct ldb_parse_tree *ldb_parse_filter(struct ldb_context *ldb, const ch } p2 = p + 1; - s2 = ldb_strndup(ldb, *s, p - *s); + s2 = talloc_strndup(ctx, *s, p - *s); if (!s2) { errno = ENOMEM; return NULL; } - ret = ldb_parse_filtercomp(ldb, s2); - ldb_free(ldb, s2); + ret = ldb_parse_filtercomp(ctx, s2); + talloc_free(s2); *s = p2; @@ -347,27 +343,6 @@ struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s) */ void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree) { - unsigned int i; - - switch (tree->operation) { - case LDB_OP_SIMPLE: - ldb_free(ldb, tree->u.simple.attr); - if (tree->u.simple.value.data) ldb_free(ldb, tree->u.simple.value.data); - break; - - case LDB_OP_AND: - case LDB_OP_OR: - for (i=0;iu.list.num_elements;i++) { - ldb_parse_tree_free(ldb, tree->u.list.elements[i]); - } - if (tree->u.list.elements) ldb_free(ldb, tree->u.list.elements); - break; - - case LDB_OP_NOT: - ldb_parse_tree_free(ldb, tree->u.not.child); - break; - } - - ldb_free(ldb, tree); + talloc_free(tree); } diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 01bd8eb9ac..577766d9f7 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -44,7 +44,7 @@ char *ldb_casefold(struct ldb_context *ldb, const char *s) { int i; - char *ret = ldb_strdup(ldb, s); + char *ret = talloc_strdup(ldb, s); if (!s) { errno = ENOMEM; return NULL; diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index a026ae1229..8a7a34f05b 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -48,11 +48,10 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_msg.o \ lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ - lib/ldb/common/ldb_alloc.o \ lib/ldb/common/ldb_debug.o \ lib/ldb/common/ldb_modules.o REQUIRED_SUBSYSTEMS = \ - LIBREPLACE + LIBREPLACE LIBTALLOC NOPROTO = YES # # End SUBSYSTEM LIBLDB diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 4926e1524a..66b984a87d 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -18,15 +18,15 @@ #include #include #include +#include #include "ldb.h" #include "ldb_private.h" +#include "talloc.h" -#ifdef HAVE_INTPTR_T +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) #define discard_const(ptr) ((void *)((intptr_t)(ptr))) #else #define discard_const(ptr) ((void *)(ptr)) #endif #define discard_const_p(type, ptr) ((type *)discard_const(ptr)) - - diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 9dff510417..7aa2b6f4cd 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -105,7 +105,7 @@ enum ldb_changetype { */ struct ldb_ldif { enum ldb_changetype changetype; - struct ldb_message msg; + struct ldb_message *msg; }; enum ldb_scope {LDB_SCOPE_DEFAULT=-1, @@ -123,16 +123,6 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_module; -/* - the user can optionally supply a allocator function. It is presumed - it will act like a modern realloc(), with a context ptr to allow - for pool allocators -*/ -struct ldb_alloc_ops { - void *(*alloc)(const void *context, void *ptr, size_t size); - void *context; -}; - /* debugging uses one of the following levels */ enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, LDB_DEBUG_WARNING, LDB_DEBUG_TRACE}; @@ -240,6 +230,9 @@ int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif int ldb_dn_cmp(const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); +/* create an empty message */ +struct ldb_message *ldb_msg_new(void *mem_ctx); + /* find an element within an message */ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, const char *attr_name); @@ -305,40 +298,11 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, const struct ldb_message *msg); -struct ldb_val ldb_val_dup(struct ldb_context *ldb, - const struct ldb_val *v); - -/* - this allows the user to choose their own allocation function - the allocation function should behave like a modern realloc() - function, which means that: - malloc(size) == alloc(context, NULL, size) - free(ptr) == alloc(context, ptr, 0) - realloc(ptr, size) == alloc(context, ptr, size) - The context argument is provided to allow for pool based allocators, - which often take a context argument -*/ -int ldb_set_alloc(struct ldb_context *ldb, - void *(*alloc)(const void *context, void *ptr, size_t size), - void *context); - -/* these are used as type safe versions of the ldb allocation functions */ -#define ldb_malloc_p(ldb, type) (type *)ldb_malloc(ldb, sizeof(type)) -#define ldb_malloc_array_p(ldb, type, count) (type *)ldb_realloc_array(ldb, NULL, sizeof(type), count) -#define ldb_realloc_p(ldb, p, type, count) (type *)ldb_realloc_array(ldb, p, sizeof(type), count) - -void *ldb_realloc(struct ldb_context *ldb, void *ptr, size_t size); -void *ldb_malloc(struct ldb_context *ldb, size_t size); -void ldb_free(struct ldb_context *ldb, void *ptr); -void *ldb_strndup(struct ldb_context *ldb, const char *str, size_t maxlen); -void *ldb_strdup(struct ldb_context *ldb, const char *str); -void *ldb_realloc_array(struct ldb_context *ldb, - void *ptr, size_t el_size, unsigned count); +struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v); #ifndef PRINTF_ATTRIBUTE #define PRINTF_ATTRIBUTE(a,b) #endif -int ldb_asprintf(struct ldb_context *ldb, char **strp, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); /* this allows the user to set a debug function for error reporting diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index a2171162ad..3d3b1ec0eb 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -66,10 +66,6 @@ struct ldb_module_ops { int (*named_lock)(struct ldb_module *, const char *); int (*named_unlock)(struct ldb_module *, const char *); const char * (*errstring)(struct ldb_module *); - - /* this is called when the alloc ops changes to ensure we - don't have any old allocated data in the context */ - void (*cache_free)(struct ldb_module *); }; /* the modules init function */ @@ -82,10 +78,7 @@ struct ldb_context { /* the operations provided by the backend */ struct ldb_module *modules; - /* memory allocation info */ - struct ldb_alloc_ops alloc_ops; - - /* memory allocation info */ + /* debugging operations */ struct ldb_debug_ops debug_ops; }; @@ -106,7 +99,6 @@ int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const c int ldb_next_named_lock(struct ldb_module *module, const char *lockname); int ldb_next_named_unlock(struct ldb_module *module, const char *lockname); const char *ldb_next_errstring(struct ldb_module *module); -void ldb_next_cache_free(struct ldb_module *module); /* The following definitions come from lib/ldb/common/util.c */ int ldb_list_find(const void *needle, diff --git a/source4/lib/ldb/include/talloc.h b/source4/lib/ldb/include/talloc.h deleted file mode 100644 index ffb4c9f252..0000000000 --- a/source4/lib/ldb/include/talloc.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef _TALLOC_H_ -#define _TALLOC_H_ -/* - Unix SMB/CIFS implementation. - Samba temporary memory allocation functions - - Copyright (C) Andrew Tridgell 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* this is only needed for compatibility with the old talloc */ -typedef void TALLOC_CTX; - -/* - this uses a little trick to allow __LINE__ to be stringified -*/ -#define _STRING_LINE_(s) #s -#define _STRING_LINE2_(s) _STRING_LINE_(s) -#define __LINESTR__ _STRING_LINE2_(__LINE__) -#define __location__ __FILE__ ":" __LINESTR__ - -/* useful macros for creating type checked pointers */ -#define talloc(ctx, size) talloc_named_const(ctx, size, __location__) -#define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) -#define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) -#define talloc_p(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) -#define talloc_zero_p(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define talloc_zero_array_p(ctx, type, count) (type *)talloc_zero_array(ctx, sizeof(type), count, __location__) -#define talloc_array_p(ctx, type, count) (type *)talloc_array(ctx, sizeof(type), count, __location__) -#define talloc_realloc_p(ctx, p, type, count) (type *)talloc_realloc_array(ctx, p, sizeof(type), count, __location__) -#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) - -#define talloc_destroy(ctx) talloc_free(ctx) - -#define malloc_p(type) (type *)malloc(sizeof(type)) -#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) -#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) - -#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) -#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) - -#ifndef PRINTF_ATTRIBUTE -#define PRINTF_ATTRIBUTE(a1, a2) -#endif - - -/* The following definitions come from lib/talloc.c */ -void *_talloc(const void *context, size_t size); -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); -void talloc_increase_ref_count(const void *ptr); -void *talloc_reference(const void *context, const void *ptr); -int talloc_unlink(const void *context, void *ptr); -void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -void talloc_set_name_const(const void *ptr, const char *name); -void *talloc_named(const void *context, size_t size, - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -void *talloc_named_const(const void *context, size_t size, const char *name); -const char *talloc_get_name(const void *ptr); -void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); -int talloc_free(void *ptr); -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -void *talloc_steal(const void *new_ctx, const void *ptr); -off_t talloc_total_size(const void *ptr); -off_t talloc_total_blocks(const void *ptr); -void talloc_report_full(const void *ptr, FILE *f); -void talloc_report(const void *ptr, FILE *f); -void talloc_enable_leak_report(void); -void talloc_enable_leak_report_full(void); -void *_talloc_zero(const void *ctx, size_t size, const char *name); -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); -char *talloc_strdup(const void *t, const char *p); -char *talloc_strndup(const void *t, const char *p, size_t n); -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append(char *s, - const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); -void *talloc_ldb_alloc(void *context, void *ptr, size_t size); - -#endif - diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index b9c3865acc..fee02da32f 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -72,26 +72,9 @@ static const char *lldb_option_find(const struct lldb_private *lldb, const char */ static int lldb_close(struct ldb_module *module) { - int i, ret = 0; struct ldb_context *ldb = module->ldb; - struct lldb_private *lldb = module->private_data; - - if (ldap_unbind(lldb->ldap) != LDAP_SUCCESS) { - ret = -1; - } - - ldb_set_alloc(ldb, NULL, NULL); - - if (lldb->options) { - for (i=0;lldb->options[i];i++) { - ldb_free(ldb, lldb->options[i]); - } - ldb_free(ldb, lldb->options); - } - ldb_free(ldb, lldb); - free(ldb); - - return ret; + talloc_free(ldb); + return 0; } /* @@ -99,18 +82,18 @@ static int lldb_close(struct ldb_module *module) */ static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn) { - struct ldb_context *ldb = module->ldb; struct lldb_private *lldb = module->private_data; int ret = 0; char *newrdn, *p; const char *parentdn = ""; + TALLOC_CTX *mem_ctx = talloc(lldb, 0); /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { return 0; } - newrdn = ldb_strdup(ldb, newdn); + newrdn = talloc_strdup(mem_ctx, newdn); if (!newrdn) { return -1; } @@ -122,11 +105,12 @@ static int lldb_rename(struct ldb_module *module, const char *olddn, const char } lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL); - ldb_free(ldb, newrdn); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } + talloc_free(mem_ctx); + return ret; } @@ -151,40 +135,12 @@ static int lldb_delete(struct ldb_module *module, const char *dn) return ret; } -/* - free a search message -*/ -static int lldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) -{ - unsigned int i, j; - ldb_free(ldb, msg->dn); - for (i=0;inum_elements;i++) { - ldb_free(ldb, msg->elements[i].name); - for (j=0;jelements[i].num_values;j++) { - if (msg->elements[i].values[j].data) { - ldb_free(ldb, msg->elements[i].values[j].data); - } - } - ldb_free(ldb, msg->elements[i].values); - } - if (msg->elements) ldb_free(ldb, msg->elements); - ldb_free(ldb, msg); - return 0; -} - /* free a search result */ static int lldb_search_free(struct ldb_module *module, struct ldb_message **res) { - struct ldb_context *ldb = module->ldb; - int i; - for (i=0;res[i];i++) { - if (lldb_msg_free(ldb, res[i]) != 0) { - return -1; - } - } - ldb_free(ldb, res); + talloc_free(res); return 0; } @@ -205,8 +161,8 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, return -1; } - el = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, - msg->num_elements + 1); + el = talloc_realloc_p(msg, msg->elements, struct ldb_message_element, + msg->num_elements + 1); if (!el) { errno = ENOMEM; return -1; @@ -216,7 +172,7 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, el = &msg->elements[msg->num_elements]; - el->name = ldb_strdup(ldb, attr); + el->name = talloc_strdup(msg->elements, attr); if (!el->name) { errno = ENOMEM; return -1; @@ -224,18 +180,17 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, el->flags = 0; el->num_values = 0; - el->values = ldb_malloc_array_p(ldb, struct ldb_val, count); + el->values = talloc_array_p(msg->elements, struct ldb_val, count); if (!el->values) { errno = ENOMEM; return -1; } for (i=0;ivalues[i].data = ldb_malloc(ldb, bval[i]->bv_len); + el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len); if (!el->values[i].data) { return -1; } - memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len); el->values[i].length = bval[i]->bv_len; el->num_values++; } @@ -275,7 +230,7 @@ static int lldb_search(struct ldb_module *module, const char *base, return count; } - (*res) = ldb_malloc_array_p(ldb, struct ldb_message *, count+1); + (*res) = talloc_array_p(lldb, struct ldb_message *, count+1); if (! *res) { ldap_msgfree(ldapres); errno = ENOMEM; @@ -299,7 +254,7 @@ static int lldb_search(struct ldb_module *module, const char *base, break; } - (*res)[msg_count] = ldb_malloc_p(ldb, struct ldb_message); + (*res)[msg_count] = talloc_p(*res, struct ldb_message); if (!(*res)[msg_count]) { goto failed; } @@ -310,7 +265,7 @@ static int lldb_search(struct ldb_module *module, const char *base, goto failed; } - (*res)[msg_count]->dn = ldb_strdup(ldb, dn); + (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn); ldap_memfree(dn); if (!(*res)[msg_count]->dn) { goto failed; @@ -350,28 +305,6 @@ failed: } -/* - free a set of mods from lldb_msg_to_mods() -*/ -static void lldb_mods_free(struct ldb_context *ldb, LDAPMod **mods) -{ - int i, j; - - if (!mods) return; - - for (i=0;mods[i];i++) { - if (mods[i]->mod_vals.modv_bvals) { - for (j=0;mods[i]->mod_vals.modv_bvals[j];j++) { - ldb_free(ldb, mods[i]->mod_vals.modv_bvals[j]); - } - ldb_free(ldb, mods[i]->mod_vals.modv_bvals); - } - ldb_free(ldb, mods[i]); - } - ldb_free(ldb, mods); -} - - /* convert a ldb_message structure to a list of LDAPMod structures ready for ldap_add() or ldap_modify() @@ -384,7 +317,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, int num_mods = 0; /* allocate maximum number of elements needed */ - mods = ldb_malloc_array_p(ldb, LDAPMod *, msg->num_elements+1); + mods = talloc_array_p(ldb, LDAPMod *, msg->num_elements+1); if (!mods) { errno = ENOMEM; return NULL; @@ -394,7 +327,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, for (i=0;inum_elements;i++) { const struct ldb_message_element *el = &msg->elements[i]; - mods[num_mods] = ldb_malloc_p(ldb, LDAPMod); + mods[num_mods] = talloc_p(ldb, LDAPMod); if (!mods[num_mods]) { goto failed; } @@ -414,15 +347,16 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, } } mods[num_mods]->mod_type = el->name; - mods[num_mods]->mod_vals.modv_bvals = ldb_malloc_array_p(ldb, - struct berval *, - 1+el->num_values); + mods[num_mods]->mod_vals.modv_bvals = talloc_array_p(mods[num_mods], + struct berval *, + 1+el->num_values); if (!mods[num_mods]->mod_vals.modv_bvals) { goto failed; } for (j=0;jnum_values;j++) { - mods[num_mods]->mod_vals.modv_bvals[j] = ldb_malloc_p(ldb, struct berval); + mods[num_mods]->mod_vals.modv_bvals[j] = talloc_p(mods[num_mods]->mod_vals.modv_bvals, + struct berval); if (!mods[num_mods]->mod_vals.modv_bvals[j]) { goto failed; } @@ -436,7 +370,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, return mods; failed: - lldb_mods_free(ldb, mods); + talloc_free(mods); return NULL; } @@ -463,7 +397,7 @@ static int lldb_add(struct ldb_module *module, const struct ldb_message *msg) ret = -1; } - lldb_mods_free(ldb, mods); + talloc_free(mods); return ret; } @@ -491,7 +425,7 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) ret = -1; } - lldb_mods_free(ldb, mods); + talloc_free(mods); return ret; } @@ -547,6 +481,13 @@ static const struct ldb_module_ops lldb_ops = { }; +static int lldb_destructor(void *p) +{ + struct lldb_private *lldb = p; + ldap_unbind(lldb->ldap); + return 0; +} + /* connect to the database */ @@ -558,15 +499,14 @@ struct ldb_context *lldb_connect(const char *url, struct lldb_private *lldb = NULL; int i, version = 3; - ldb = calloc(1, sizeof(struct ldb_context)); + ldb = talloc_p(NULL, struct ldb_context); if (!ldb) { errno = ENOMEM; goto failed; } - lldb = ldb_malloc_p(ldb, struct lldb_private); + lldb = talloc_p(ldb, struct lldb_private); if (!lldb) { - ldb_free(ldb, ldb); errno = ENOMEM; goto failed; } @@ -579,14 +519,15 @@ struct ldb_context *lldb_connect(const char *url, goto failed; } + talloc_set_destructor(lldb, lldb_destructor); + lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); if (lldb->last_rc != LDAP_SUCCESS) { goto failed; } - ldb->modules = ldb_malloc_p(ldb, struct ldb_module); + ldb->modules = talloc_p(ldb, struct ldb_module); if (!ldb->modules) { - ldb_free(ldb, ldb); errno = ENOMEM; goto failed; } @@ -600,14 +541,14 @@ struct ldb_context *lldb_connect(const char *url, on the caller keeping it around (it might be dynamic) */ for (i=0;options[i];i++) ; - lldb->options = ldb_malloc_array_p(ldb, char *, i+1); + lldb->options = talloc_array_p(lldb, char *, i+1); if (!lldb->options) { goto failed; } for (i=0;options[i];i++) { lldb->options[i+1] = NULL; - lldb->options[i] = ldb_strdup(ldb, options[i]); + lldb->options[i] = talloc_strdup(lldb->options, options[i]); if (!lldb->options[i]) { goto failed; } @@ -617,17 +558,7 @@ struct ldb_context *lldb_connect(const char *url, return ldb; failed: - if (lldb && lldb->options) { - for (i=0;lldb->options[i];i++) { - ldb_free(ldb, lldb->options[i]); - } - ldb_free(ldb, lldb->options); - } - if (lldb && lldb->ldap) { - ldap_unbind(lldb->ldap); - } - ldb_free(ldb, lldb); - if (ldb) free(ldb); + talloc_free(ldb); return NULL; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index a8eb9ae916..e7420c5f7a 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -42,9 +42,8 @@ */ static int ltdb_baseinfo_init(struct ldb_module *module) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - struct ldb_message msg; + struct ldb_message *msg; struct ldb_message_element el; struct ldb_val val; int ret; @@ -55,60 +54,61 @@ static int ltdb_baseinfo_init(struct ldb_module *module) ltdb->sequence_number = atof(initial_sequence_number); - msg.num_elements = 1; - msg.elements = ⪙ - msg.dn = ldb_strdup(ldb, LTDB_BASEINFO); - if (!msg.dn) { - errno = ENOMEM; - return -1; + msg = talloc_p(ltdb, struct ldb_message); + if (msg == NULL) { + goto failed; } - el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER); + + msg->num_elements = 1; + msg->elements = ⪙ + msg->dn = talloc_strdup(msg, LTDB_BASEINFO); + if (!msg->dn) { + goto failed; + } + el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER); if (!el.name) { - ldb_free(ldb, msg.dn); - errno = ENOMEM; - return -1; + goto failed; } el.values = &val; el.num_values = 1; el.flags = 0; - val.data = ldb_strdup(ldb, initial_sequence_number); + val.data = talloc_strdup(msg, initial_sequence_number); if (!val.data) { - ldb_free(ldb, el.name); - ldb_free(ldb, msg.dn); - errno = ENOMEM; - return -1; + goto failed; } val.length = 1; - ret = ltdb_store(module, &msg, TDB_INSERT); + ret = ltdb_store(module, msg, TDB_INSERT); - ldb_free(ldb, msg.dn); - ldb_free(ldb, el.name); - ldb_free(ldb, val.data); + talloc_free(msg); return ret; + +failed: + talloc_free(msg); + errno = ENOMEM; + return -1; } /* free any cache records */ -void ltdb_cache_free(struct ldb_module *module) +static void ltdb_cache_free(struct ldb_module *module) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - struct ldb_alloc_ops alloc = ldb->alloc_ops; - ldb->alloc_ops.alloc = NULL; ltdb->sequence_number = 0; - ltdb_search_dn1_free(module, <db->cache.baseinfo); - ltdb_search_dn1_free(module, <db->cache.indexlist); - ltdb_search_dn1_free(module, <db->cache.subclasses); - ltdb_search_dn1_free(module, <db->cache.attributes); - - ldb_free(ldb, ltdb->cache.last_attribute.name); - memset(<db->cache, 0, sizeof(ltdb->cache)); + talloc_free(ltdb->cache); + ltdb->cache = NULL; +} - ldb->alloc_ops = alloc; +/* + force a cache reload +*/ +int ltdb_cache_reload(struct ldb_module *module) +{ + ltdb_cache_free(module); + return ltdb_cache_load(module); } /* @@ -116,60 +116,78 @@ void ltdb_cache_free(struct ldb_module *module) */ int ltdb_cache_load(struct ldb_module *module) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; double seq; - struct ldb_alloc_ops alloc = ldb->alloc_ops; - ldb->alloc_ops.alloc = NULL; + if (ltdb->cache == NULL) { + ltdb->cache = talloc_zero_p(ltdb, struct ltdb_cache); + if (ltdb->cache == NULL) goto failed; + ltdb->cache->indexlist = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->subclasses = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->attributes = talloc_zero_p(ltdb->cache, struct ldb_message); + if (ltdb->cache->indexlist == NULL || + ltdb->cache->subclasses == NULL || + ltdb->cache->attributes == NULL) { + goto failed; + } + } - ltdb_search_dn1_free(module, <db->cache.baseinfo); + talloc_free(ltdb->cache->baseinfo); + ltdb->cache->baseinfo = talloc_p(ltdb->cache, struct ldb_message); + if (ltdb->cache->baseinfo == NULL) goto failed; - if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { + if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) == -1) { goto failed; } /* possibly initialise the baseinfo */ - if (!ltdb->cache.baseinfo.dn) { + if (!ltdb->cache->baseinfo->dn) { if (ltdb_baseinfo_init(module) != 0) { goto failed; } - if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { + if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) != 1) { goto failed; } } /* if the current internal sequence number is the same as the one in the database then assume the rest of the cache is OK */ - seq = ldb_msg_find_double(<db->cache.baseinfo, LTDB_SEQUENCE_NUMBER, 0); + seq = ldb_msg_find_double(ltdb->cache->baseinfo, LTDB_SEQUENCE_NUMBER, 0); if (seq == ltdb->sequence_number) { goto done; } ltdb->sequence_number = seq; - ldb_free(ldb, ltdb->cache.last_attribute.name); - memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute)); + talloc_free(ltdb->cache->last_attribute.name); + memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute)); - ltdb_search_dn1_free(module, <db->cache.indexlist); - ltdb_search_dn1_free(module, <db->cache.subclasses); - ltdb_search_dn1_free(module, <db->cache.attributes); + talloc_free(ltdb->cache->indexlist); + talloc_free(ltdb->cache->subclasses); + talloc_free(ltdb->cache->attributes); - if (ltdb_search_dn1(module, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { + ltdb->cache->indexlist = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->subclasses = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->attributes = talloc_zero_p(ltdb->cache, struct ldb_message); + if (ltdb->cache->indexlist == NULL || + ltdb->cache->subclasses == NULL || + ltdb->cache->attributes == NULL) { goto failed; } - if (ltdb_search_dn1(module, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { + + if (ltdb_search_dn1(module, LTDB_INDEXLIST, ltdb->cache->indexlist) == -1) { goto failed; } - if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { + if (ltdb_search_dn1(module, LTDB_SUBCLASSES, ltdb->cache->subclasses) == -1) { + goto failed; + } + if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, ltdb->cache->attributes) == -1) { goto failed; } done: - ldb->alloc_ops = alloc; return 0; failed: - ldb->alloc_ops = alloc; return -1; } @@ -181,33 +199,37 @@ int ltdb_increase_sequence_number(struct ldb_module *module) { struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - struct ldb_message msg; + struct ldb_message *msg; struct ldb_message_element el; struct ldb_val val; char *s = NULL; int ret; - ldb_asprintf(ldb, &s, "%.0f", ltdb->sequence_number+1); + s = talloc_asprintf(ldb, "%.0f", ltdb->sequence_number+1); if (!s) { errno = ENOMEM; return -1; } - msg.num_elements = 1; - msg.elements = ⪙ - msg.dn = ldb_strdup(ldb, LTDB_BASEINFO); - el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER); + msg = talloc_p(ltdb, struct ldb_message); + if (msg == NULL) { + errno = ENOMEM; + return -1; + } + + msg->num_elements = 1; + msg->elements = ⪙ + msg->dn = talloc_strdup(msg, LTDB_BASEINFO); + el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER); el.values = &val; el.num_values = 1; el.flags = LDB_FLAG_MOD_REPLACE; val.data = s; val.length = strlen(s); - ret = ltdb_modify_internal(module, &msg); + ret = ltdb_modify_internal(module, msg); - ldb_free(ldb, s); - ldb_free(ldb, msg.dn); - ldb_free(ldb, el.name); + talloc_free(msg); if (ret == 0) { ltdb->sequence_number += 1; @@ -223,7 +245,6 @@ int ltdb_increase_sequence_number(struct ldb_module *module) */ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; const char *attrs; const struct { @@ -238,11 +259,10 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) }; size_t len; int i, ret=0; - struct ldb_alloc_ops alloc = ldb->alloc_ops; - if (ltdb->cache.last_attribute.name && - ldb_attr_cmp(ltdb->cache.last_attribute.name, attr_name) == 0) { - return ltdb->cache.last_attribute.flags; + if (ltdb->cache->last_attribute.name && + ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) { + return ltdb->cache->last_attribute.flags; } /* objectclass is a special default case */ @@ -250,7 +270,7 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE; } - attrs = ldb_msg_find_string(<db->cache.attributes, attr_name, NULL); + attrs = ldb_msg_find_string(ltdb->cache->attributes, attr_name, NULL); if (!attrs) { return ret; @@ -270,14 +290,10 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) attrs += strspn(attrs, " ,"); } - ldb->alloc_ops.alloc = NULL; + talloc_free(ltdb->cache->last_attribute.name); - ldb_free(ldb, ltdb->cache.last_attribute.name); + ltdb->cache->last_attribute.name = talloc_strdup(ltdb->cache, attr_name); + ltdb->cache->last_attribute.flags = ret; - ltdb->cache.last_attribute.name = ldb_strdup(ldb, attr_name); - ltdb->cache.last_attribute.flags = ret; - - ldb->alloc_ops = alloc; - return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index eaf699be62..ff0cabb0d6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -43,18 +43,6 @@ struct dn_list { char **dn; }; -/* - free a struct dn_list -*/ -static void dn_list_free(struct ldb_context *ldb, struct dn_list *list) -{ - unsigned int i; - for (i=0;icount;i++) { - ldb_free(ldb, list->dn[i]); - } - ldb_free(ldb, list->dn); -} - /* return the dn key to be used for an index caller frees @@ -67,13 +55,13 @@ static char *ldb_dn_key(struct ldb_context *ldb, if (ldb_should_b64_encode(value)) { char *vstr = ldb_base64_encode(ldb, value->data, value->length); if (!vstr) return NULL; - ldb_asprintf(ldb, &ret, "%s:%s::%s", LTDB_INDEX, attr, vstr); - ldb_free(ldb, vstr); + ret = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr, vstr); + talloc_free(vstr); return ret; } - ldb_asprintf(ldb, &ret, "%s:%s:%.*s", LTDB_INDEX, attr, value->length, (char *)value->data); - return ret; + return talloc_asprintf(ldb, "%s:%s:%.*s", + LTDB_INDEX, attr, value->length, (char *)value->data); } /* @@ -118,7 +106,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module, char *dn = NULL; int ret; unsigned int i, j; - struct ldb_message msg; + struct ldb_message *msg; list->count = 0; list->dn = NULL; @@ -141,39 +129,43 @@ static int ltdb_index_dn_simple(struct ldb_module *module, dn = ldb_dn_key(ldb, tree->u.simple.attr, &tree->u.simple.value); if (!dn) return -1; - ret = ltdb_search_dn1(module, dn, &msg); - ldb_free(ldb, dn); + msg = talloc_p(list, struct ldb_message); + if (msg == NULL) { + return -1; + } + + ret = ltdb_search_dn1(module, dn, msg); + talloc_free(dn); if (ret == 0 || ret == -1) { return ret; } - for (i=0;inum_elements;i++) { struct ldb_message_element *el; - if (strcmp(msg.elements[i].name, LTDB_IDX) != 0) { + if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) { continue; } - el = &msg.elements[i]; + el = &msg->elements[i]; - list->dn = ldb_malloc_array_p(ldb, char *, el->num_values); + list->dn = talloc_array_p(list, char *, el->num_values); if (!list->dn) { break; } for (j=0;jnum_values;j++) { list->dn[list->count] = - ldb_strdup(ldb, (char *)el->values[j].data); + talloc_strdup(list->dn, (char *)el->values[j].data); if (!list->dn[list->count]) { - dn_list_free(ldb, list); - ltdb_search_dn1_free(module, &msg); + talloc_free(list); return -1; } list->count++; } } - ltdb_search_dn1_free(module, &msg); + talloc_free(msg); qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp); @@ -203,30 +195,34 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, ret = ltdb_index_dn_simple(module, tree, index_list, list); - for (i=0;icache.subclasses.num_elements;i++) { - struct ldb_message_element *el = <db->cache.subclasses.elements[i]; + for (i=0;icache->subclasses->num_elements;i++) { + struct ldb_message_element *el = <db->cache->subclasses->elements[i]; if (ldb_attr_cmp(el->name, target) == 0) { unsigned int j; for (j=0;jnum_values;j++) { struct ldb_parse_tree tree2; - struct dn_list list2; + struct dn_list *list2; tree2.operation = LDB_OP_SIMPLE; - tree2.u.simple.attr = ldb_strdup(ldb, LTDB_OBJECTCLASS); + tree2.u.simple.attr = talloc_strdup(list, LTDB_OBJECTCLASS); if (!tree2.u.simple.attr) { return -1; } tree2.u.simple.value = el->values[j]; + list2 = talloc_p(list, struct dn_list); + if (list2 == NULL) { + return -1; + } if (ltdb_index_dn_objectclass(module, &tree2, - index_list, &list2) == 1) { + index_list, list2) == 1) { if (list->count == 0) { - *list = list2; + *list = *list2; ret = 1; } else { - list_union(ldb, list, &list2); - dn_list_free(ldb, &list2); + list_union(ldb, list, list2); + talloc_free(list2); } } - ldb_free(ldb, tree2.u.simple.attr); + talloc_free(tree2.u.simple.attr); } } } @@ -257,35 +253,42 @@ static int ltdb_index_dn_leaf(struct ldb_module *module, static int list_intersect(struct ldb_context *ldb, struct dn_list *list, const struct dn_list *list2) { - struct dn_list list3; + struct dn_list *list3; unsigned int i; if (list->count == 0 || list2->count == 0) { /* 0 & X == 0 */ - dn_list_free(ldb, list); + talloc_free(list); return 0; } - list3.dn = ldb_malloc_array_p(ldb, char *, list->count); - if (!list3.dn) { - dn_list_free(ldb, list); + list3 = talloc_p(ldb, struct dn_list); + if (list3 == NULL) { return -1; } - list3.count = 0; + + list3->dn = talloc_array_p(list3, char *, list->count); + if (!list3->dn) { + talloc_free(list); + talloc_free(list3); + return -1; + } + list3->count = 0; for (i=0;icount;i++) { if (ldb_list_find(list->dn[i], list2->dn, list2->count, sizeof(char *), (comparison_fn_t)strcmp) != -1) { - list3.dn[list3.count] = list->dn[i]; - list3.count++; + list3->dn[list3->count] = talloc_steal(list3->dn, list->dn[i]); + list3->count++; } else { - ldb_free(ldb, list->dn[i]); + talloc_free(list->dn[i]); } } - ldb_free(ldb, list->dn); - list->dn = list3.dn; - list->count = list3.count; + talloc_free(list->dn); + list->dn = talloc_steal(list, list3->dn); + list->count = list3->count; + talloc_free(list3); return 0; } @@ -305,13 +308,13 @@ static int list_union(struct ldb_context *ldb, if (list->count == 0 && list2->count == 0) { /* 0 | 0 == 0 */ - dn_list_free(ldb, list); + talloc_free(list); return 0; } - d = ldb_realloc_p(ldb, list->dn, char *, list->count + list2->count); + d = talloc_realloc_p(list, list->dn, char *, list->count + list2->count); if (!d) { - dn_list_free(ldb, list); + talloc_free(list); return -1; } list->dn = d; @@ -319,9 +322,9 @@ static int list_union(struct ldb_context *ldb, for (i=0;icount;i++) { if (ldb_list_find(list2->dn[i], list->dn, count, sizeof(char *), (comparison_fn_t)strcmp) == -1) { - list->dn[list->count] = ldb_strdup(ldb, list2->dn[i]); + list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]); if (!list->dn[list->count]) { - dn_list_free(ldb, list); + talloc_free(list); return -1; } list->count++; @@ -358,39 +361,48 @@ static int ltdb_index_dn_or(struct ldb_module *module, list->count = 0; for (i=0;iu.list.num_elements;i++) { - struct dn_list list2; + struct dn_list *list2; int v; - v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, &list2); + + list2 = talloc_p(module, struct dn_list); + if (list2 == NULL) { + return -1; + } + + v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2); if (v == 0) { /* 0 || X == X */ if (ret == -1) { ret = 0; } + talloc_free(list2); continue; } if (v == -1) { /* 1 || X == 1 */ - dn_list_free(ldb, list); + talloc_free(list->dn); + talloc_free(list2); return -1; } if (ret == -1) { ret = 1; - *list = list2; + list->dn = talloc_steal(list, list2->dn); + list->count = list2->count; } else { - if (list_union(ldb, list, &list2) == -1) { - dn_list_free(ldb, &list2); + if (list_union(ldb, list, list2) == -1) { + talloc_free(list2); return -1; } - dn_list_free(ldb, &list2); ret = 1; } + talloc_free(list2); } if (list->count == 0) { - dn_list_free(ldb, list); + talloc_free(list); return 0; } @@ -434,33 +446,44 @@ static int ltdb_index_dn_and(struct ldb_module *module, list->count = 0; for (i=0;iu.list.num_elements;i++) { - struct dn_list list2; + struct dn_list *list2; int v; - v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, &list2); + + list2 = talloc_p(module, struct dn_list); + if (list2 == NULL) { + return -1; + } + + v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2); if (v == 0) { /* 0 && X == 0 */ - dn_list_free(ldb, list); + talloc_free(list->dn); + talloc_free(list2); return 0; } if (v == -1) { + talloc_free(list2); continue; } if (ret == -1) { ret = 1; - *list = list2; + talloc_free(list->dn); + list->dn = talloc_steal(list, list2->dn); + list->count = list2->count; } else { - if (list_intersect(ldb, list, &list2) == -1) { - dn_list_free(ldb, &list2); + if (list_intersect(ldb, list, list2) == -1) { + talloc_free(list2); return -1; } - dn_list_free(ldb, &list2); } + talloc_free(list2); + if (list->count == 0) { - if (list->dn) ldb_free(ldb, list->dn); + talloc_free(list->dn); return 0; } } @@ -514,24 +537,32 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr int count = 0; for (i=0;icount;i++) { - struct ldb_message msg; + struct ldb_message *msg; int ret; - ret = ltdb_search_dn1(module, dn_list->dn[i], &msg); + + msg = talloc_p(module, struct ldb_message); + if (msg == NULL) { + return -1; + } + + ret = ltdb_search_dn1(module, dn_list->dn[i], msg); if (ret == 0) { /* the record has disappeared? yes, this can happen */ + talloc_free(msg); continue; } if (ret == -1) { /* an internal error */ + talloc_free(msg); return -1; } ret = 0; - if (ltdb_message_match(module, &msg, tree, base, scope) == 1) { - ret = ltdb_add_attr_results(module, &msg, attrs, &count, res); + if (ltdb_message_match(module, msg, tree, base, scope) == 1) { + ret = ltdb_add_attr_results(module, msg, attrs, &count, res); } - ltdb_search_dn1_free(module, &msg); + talloc_free(msg); if (ret != 0) { return -1; } @@ -551,26 +582,31 @@ int ltdb_search_indexed(struct ldb_module *module, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - struct dn_list dn_list; + struct dn_list *dn_list; int ret; - if (ltdb->cache.indexlist.num_elements == 0) { + if (ltdb->cache->indexlist->num_elements == 0) { /* no index list? must do full search */ return -1; } - ret = ltdb_index_dn(module, tree, <db->cache.indexlist, &dn_list); + dn_list = talloc_p(module, struct dn_list); + if (dn_list == NULL) { + return -1; + } + + ret = ltdb_index_dn(module, tree, ltdb->cache->indexlist, dn_list); if (ret == 1) { /* we've got a candidate list - now filter by the full tree and extract the needed attributes */ - ret = ldb_index_filter(module, tree, base, scope, &dn_list, + ret = ldb_index_filter(module, tree, base, scope, dn_list, attrs, res); - dn_list_free(ldb, &dn_list); } + talloc_free(dn_list); + return ret; } @@ -585,19 +621,19 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, struct ldb_message_element *el2; /* add another entry */ - el2 = ldb_realloc_p(ldb, msg->elements, - struct ldb_message_element, msg->num_elements+1); + el2 = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, msg->num_elements+1); if (!el2) { return -1; } msg->elements = el2; - msg->elements[msg->num_elements].name = ldb_strdup(ldb, LTDB_IDX); + msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX); if (!msg->elements[msg->num_elements].name) { return -1; } msg->elements[msg->num_elements].num_values = 0; - msg->elements[msg->num_elements].values = ldb_malloc_p(ldb, struct ldb_val); + msg->elements[msg->num_elements].values = talloc_p(msg->elements, struct ldb_val); if (!msg->elements[msg->num_elements].values) { return -1; } @@ -630,9 +666,9 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, } } - v2 = ldb_realloc_p(ldb, msg->elements[idx].values, - struct ldb_val, - msg->elements[idx].num_values+1); + v2 = talloc_realloc_p(msg->elements, msg->elements[idx].values, + struct ldb_val, + msg->elements[idx].num_values+1); if (!v2) { return -1; } @@ -652,9 +688,9 @@ static int ltdb_index_add1(struct ldb_module *module, char *dn, struct ldb_message_element *el, int v_idx) { struct ldb_context *ldb = module->ldb; - struct ldb_message msg; + struct ldb_message *msg; char *dn_key; - int ret, added=0, added_dn=0; + int ret; unsigned int i; dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); @@ -662,52 +698,45 @@ static int ltdb_index_add1(struct ldb_module *module, char *dn, return -1; } - ret = ltdb_search_dn1(module, dn_key, &msg); + msg = talloc_p(dn_key, struct ldb_message); + if (msg == NULL) { + return -1; + } + + ret = ltdb_search_dn1(module, dn_key, msg); if (ret == -1) { - ldb_free(ldb, dn_key); + talloc_free(dn_key); return -1; } if (ret == 0) { - added_dn = 1; - msg.dn = ldb_strdup(ldb, dn_key); - if (!msg.dn) { - ldb_free(ldb, dn_key); + msg->dn = talloc_strdup(msg, dn_key); + if (!msg->dn) { + talloc_free(dn_key); errno = ENOMEM; return -1; } - msg.num_elements = 0; - msg.elements = NULL; - msg.private_data = NULL; + msg->num_elements = 0; + msg->elements = NULL; } - ldb_free(ldb, dn_key); - - for (i=0;inum_elements;i++) { + if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) { break; } } - if (i == msg.num_elements) { - added = 1; - ret = ltdb_index_add1_new(ldb, &msg, el, dn); + if (i == msg->num_elements) { + ret = ltdb_index_add1_new(ldb, msg, el, dn); } else { - ret = ltdb_index_add1_add(ldb, &msg, el, i, dn); + ret = ltdb_index_add1_add(ldb, msg, el, i, dn); } if (ret == 0) { - ret = ltdb_store(module, &msg, TDB_REPLACE); + ret = ltdb_store(module, msg, TDB_REPLACE); } - if (added) { - ldb_free(ldb, msg.elements[i].name); - } - if (added_dn) { - ldb_free(ldb, msg.dn); - } - - ltdb_search_dn1_free(module, &msg); + talloc_free(dn_key); return ret; } @@ -722,13 +751,13 @@ int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) int ret; unsigned int i, j; - if (ltdb->cache.indexlist.num_elements == 0) { + if (ltdb->cache->indexlist->num_elements == 0) { /* no indexed fields */ return 0; } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, + ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name, NULL, LTDB_IDXATTR); if (ret == -1) { continue; @@ -752,7 +781,7 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, struct ldb_message_element *el, int v_idx) { struct ldb_context *ldb = module->ldb; - struct ldb_message msg; + struct ldb_message *msg; char *dn_key; int ret, i; unsigned int j; @@ -762,44 +791,48 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, return -1; } - ret = ltdb_search_dn1(module, dn_key, &msg); + msg = talloc_p(dn_key, struct ldb_message); + if (msg == NULL) { + talloc_free(dn_key); + return -1; + } + + ret = ltdb_search_dn1(module, dn_key, msg); if (ret == -1) { - ldb_free(ldb, dn_key); + talloc_free(dn_key); return -1; } if (ret == 0) { /* it wasn't indexed. Did we have an earlier error? If we did then its gone now */ - ldb_free(ldb, dn_key); + talloc_free(dn_key); return 0; } - i = ldb_msg_find_idx(&msg, dn, &j, LTDB_IDX); + i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX); if (i == -1) { ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn %s not found in %s\n", dn, dn_key); /* it ain't there. hmmm */ - ltdb_search_dn1_free(module, &msg); - ldb_free(ldb, dn_key); + talloc_free(dn_key); return 0; } - if (j != msg.elements[i].num_values - 1) { - memmove(&msg.elements[i].values[j], - &msg.elements[i].values[j+1], - (msg.elements[i].num_values-(j+1)) * - sizeof(msg.elements[i].values[0])); + if (j != msg->elements[i].num_values - 1) { + memmove(&msg->elements[i].values[j], + &msg->elements[i].values[j+1], + (msg->elements[i].num_values-(j+1)) * + sizeof(msg->elements[i].values[0])); } - msg.elements[i].num_values--; + msg->elements[i].num_values--; - if (msg.elements[i].num_values == 0) { + if (msg->elements[i].num_values == 0) { ret = ltdb_delete_noindex(module, dn_key); } else { - ret = ltdb_store(module, &msg, TDB_REPLACE); + ret = ltdb_store(module, msg, TDB_REPLACE); } - ltdb_search_dn1_free(module, &msg); - ldb_free(ldb, dn_key); + talloc_free(dn_key); return ret; } @@ -815,13 +848,13 @@ int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) unsigned int i, j; /* find the list of indexed fields */ - if (ltdb->cache.indexlist.num_elements == 0) { + if (ltdb->cache->indexlist->num_elements == 0) { /* no indexed fields */ return 0; } for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(<db->cache.indexlist, msg->elements[i].name, + ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name, NULL, LTDB_IDXATTR); if (ret == -1) { continue; @@ -856,7 +889,7 @@ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, vo static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { struct ldb_module *module = state; - struct ldb_message msg; + struct ldb_message *msg; int ret; if (strncmp(key.dptr, "DN=@", 4) == 0 || @@ -864,18 +897,24 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return 0; } - ret = ltdb_unpack_data(module, &data, &msg); + msg = talloc_p(module, struct ldb_message); + if (msg == NULL) { + return -1; + } + + ret = ltdb_unpack_data(module, &data, msg); if (ret != 0) { + talloc_free(msg); return -1; } - if (!msg.dn) { - msg.dn = key.dptr+3; + if (!msg->dn) { + msg->dn = key.dptr+3; } - ret = ltdb_index_add(module, &msg); + ret = ltdb_index_add(module, msg); - ltdb_unpack_data_free(module, &msg); + talloc_free(msg); return ret; } @@ -888,9 +927,7 @@ int ltdb_reindex(struct ldb_module *module) struct ltdb_private *ltdb = module->private_data; int ret; - ltdb_cache_free(module); - - if (ltdb_cache_load(module) != 0) { + if (ltdb_cache_reload(module) != 0) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 4a51cfddf0..3bb63e2b5b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -93,13 +93,14 @@ static int ltdb_val_equal_wildcard_ci(struct ldb_module *module, s2 = ldb_casefold(ldb, v2->data); if (!s2) { + talloc_free(s1); return -1; } ret = fnmatch(s2, s1, 0); - ldb_free(ldb, s1); - ldb_free(ldb, s2); + talloc_free(s1); + talloc_free(s2); if (ret == 0) { return 1; @@ -149,8 +150,8 @@ static int ltdb_val_equal_objectclass(struct ldb_module *module, return 1; } - for (i=0;icache.subclasses.num_elements;i++) { - struct ldb_message_element *el = <db->cache.subclasses.elements[i]; + for (i=0;icache->subclasses->num_elements;i++) { + struct ldb_message_element *el = <db->cache->subclasses->elements[i]; if (ldb_attr_cmp(el->name, v2->data) == 0) { unsigned int j; for (j=0;jnum_values;j++) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 9515beeaa7..a548a4189b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -99,7 +99,7 @@ int ltdb_pack_data(struct ldb_module *module, } /* allocate it */ - data->dptr = ldb_malloc(ldb, size); + data->dptr = talloc_array_p(ldb, char, size); if (!data->dptr) { errno = ENOMEM; return -1; @@ -144,25 +144,14 @@ int ltdb_pack_data(struct ldb_module *module, void ltdb_unpack_data_free(struct ldb_module *module, struct ldb_message *message) { - struct ldb_context *ldb = module->ldb; - unsigned int i; - - for (i=0;inum_elements;i++) { - if (message->elements[i].values) ldb_free(ldb, message->elements[i].values); - } - if (message->elements) ldb_free(ldb, message->elements); + talloc_free(message->elements); } /* unpack a ldb message from a linear buffer in TDB_DATA - note that this does not fill in the class and key elements - - caller frees. Memory for the elements[] and values[] arrays are - malloced, but the memory for the elements is re-used from the - TDB_DATA data. This means the caller only has to free the elements - and values arrays. This can be done with ltdb_unpack_data_free() + Free with ltdb_unpack_data_free() */ int ltdb_unpack_data(struct ldb_module *module, const struct TDB_DATA *data, @@ -220,8 +209,7 @@ int ltdb_unpack_data(struct ldb_module *module, goto failed; } - message->elements = ldb_malloc_array_p(ldb, struct ldb_message_element, - message->num_elements); + message->elements = talloc_array_p(ldb, struct ldb_message_element, message->num_elements); if (!message->elements) { errno = ENOMEM; goto failed; @@ -247,9 +235,9 @@ int ltdb_unpack_data(struct ldb_module *module, message->elements[i].num_values = pull_uint32(p, 0); message->elements[i].values = NULL; if (message->elements[i].num_values != 0) { - message->elements[i].values = ldb_malloc_array_p(ldb, - struct ldb_val, - message->elements[i].num_values); + message->elements[i].values = talloc_array_p(message->elements, + struct ldb_val, + message->elements[i].num_values); if (!message->elements[i].values) { errno = ENOMEM; goto failed; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 27718a4c86..720188b74c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -38,25 +38,6 @@ #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" -/* - free a message that has all parts separately allocated -*/ -static void msg_free_all_parts(struct ldb_context *ldb, struct ldb_message *msg) -{ - unsigned int i, j; - ldb_free(ldb, msg->dn); - for (i=0;inum_elements;i++) { - ldb_free(ldb, msg->elements[i].name); - for (j=0;jelements[i].num_values;j++) { - ldb_free(ldb, msg->elements[i].values[j].data); - } - ldb_free(ldb, msg->elements[i].values); - } - ldb_free(ldb, msg->elements); - ldb_free(ldb, msg); -} - - /* add one element to a message */ @@ -66,7 +47,7 @@ static int msg_add_element(struct ldb_context *ldb, unsigned int i; struct ldb_message_element *e2, *elnew; - e2 = ldb_realloc_p(ldb, ret->elements, struct ldb_message_element, ret->num_elements+1); + e2 = talloc_realloc_p(ret, ret->elements, struct ldb_message_element, ret->num_elements+1); if (!e2) { return -1; } @@ -74,13 +55,13 @@ static int msg_add_element(struct ldb_context *ldb, elnew = &e2[ret->num_elements]; - elnew->name = ldb_strdup(ldb, el->name); + elnew->name = talloc_strdup(ret->elements, el->name); if (!elnew->name) { return -1; } if (el->num_values) { - elnew->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values); + elnew->values = talloc_array_p(ret->elements, struct ldb_val, el->num_values); if (!elnew->values) { return -1; } @@ -89,7 +70,7 @@ static int msg_add_element(struct ldb_context *ldb, } for (i=0;inum_values;i++) { - elnew->values[i] = ldb_val_dup(ldb, &el->values[i]); + elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]); if (elnew->values[i].length != el->values[i].length) { return -1; } @@ -136,24 +117,23 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, struct ldb_message *ret; int i; - ret = ldb_malloc_p(ldb, struct ldb_message); + ret = talloc_p(ldb, struct ldb_message); if (!ret) { return NULL; } - ret->dn = ldb_strdup(ldb, msg->dn); + ret->dn = talloc_strdup(ret, msg->dn); if (!ret->dn) { - ldb_free(ldb, ret); + talloc_free(ret); return NULL; } ret->num_elements = 0; ret->elements = NULL; - ret->private_data = NULL; if (!attrs) { if (msg_add_all_elements(module, ret, msg) != 0) { - msg_free_all_parts(ldb, ret); + talloc_free(ret); return NULL; } return ret; @@ -164,7 +144,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, if (strcmp(attrs[i], "*") == 0) { if (msg_add_all_elements(module, ret, msg) != 0) { - msg_free_all_parts(ldb, ret); + talloc_free(ret); return NULL; } continue; @@ -175,10 +155,9 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, struct ldb_val val; el2.flags = 0; - el2.name = ldb_strdup(ldb, "dn"); + el2.name = talloc_strdup(ret, "dn"); if (!el2.name) { - msg_free_all_parts(ldb, ret); - ldb_free(ldb, el2.name); + talloc_free(ret); return NULL; } el2.num_values = 1; @@ -187,11 +166,10 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, val.length = strlen(ret->dn); if (msg_add_element(ldb, ret, &el2) != 0) { - msg_free_all_parts(ldb, ret); - ldb_free(ldb, el2.name); + talloc_free(ret); return NULL; } - ldb_free(ldb, el2.name); + talloc_free(el2.name); continue; } @@ -200,7 +178,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, continue; } if (msg_add_element(ldb, ret, el) != 0) { - msg_free_all_parts(ldb, ret); + talloc_free(ret); return NULL; } } @@ -237,22 +215,6 @@ int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, } -/* - free the results of a ltdb_search_dn1 search -*/ -void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg) -{ - struct ldb_context *ldb = module->ldb; - unsigned int i; - ldb_free(ldb, msg->private_data); - for (i=0;inum_elements;i++) { - ldb_free(ldb, msg->elements[i].values); - } - ldb_free(ldb, msg->elements); - memset(msg, 0, sizeof(*msg)); -} - - /* search the database for a single simple dn, returning all attributes in a single message @@ -261,7 +223,6 @@ void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg) */ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; int ret; TDB_DATA tdb_key, tdb_data, tdb_data2; @@ -275,35 +236,32 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); if (!tdb_data.dptr) { return 0; } - tdb_data2.dptr = ldb_malloc(ldb, tdb_data.dsize); + tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize); + free(tdb_data.dptr); if (!tdb_data2.dptr) { - free(tdb_data.dptr); return -1; } - memcpy(tdb_data2.dptr, tdb_data.dptr, tdb_data.dsize); - free(tdb_data.dptr); tdb_data2.dsize = tdb_data.dsize; - msg->private_data = tdb_data2.dptr; msg->num_elements = 0; msg->elements = NULL; ret = ltdb_unpack_data(module, &tdb_data2, msg); if (ret == -1) { - ldb_free(ldb, tdb_data2.dptr); + talloc_free(tdb_data2.dptr); return -1; } if (!msg->dn) { - msg->dn = ldb_strdup(ldb, dn); + msg->dn = talloc_strdup(tdb_data2.dptr, dn); } if (!msg->dn) { - ldb_free(ldb, tdb_data2.dptr); + talloc_free(tdb_data2.dptr); return -1; } @@ -319,27 +277,35 @@ int ltdb_search_dn(struct ldb_module *module, char *dn, { struct ldb_context *ldb = module->ldb; int ret; - struct ldb_message msg, *msg2; + struct ldb_message *msg, *msg2; + + *res = talloc_array_p(ldb, struct ldb_message *, 2); + if (! *res) { + return -1; + } - ret = ltdb_search_dn1(module, dn, &msg); + msg = talloc_p(*res, struct ldb_message); + if (msg == NULL) { + talloc_free(*res); + *res = NULL; + return -1; + } + + ret = ltdb_search_dn1(module, dn, msg); if (ret != 1) { + talloc_free(*res); + *res = NULL; return ret; } - msg2 = ltdb_pull_attrs(module, &msg, attrs); + msg2 = ltdb_pull_attrs(module, msg, attrs); - ltdb_search_dn1_free(module, &msg); + talloc_free(msg); if (!msg2) { return -1; } - *res = ldb_malloc_array_p(ldb, struct ldb_message *, 2); - if (! *res) { - msg_free_all_parts(ldb, msg2); - return -1; - } - (*res)[0] = msg2; (*res)[1] = NULL; @@ -367,9 +333,9 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, } /* add to the results list */ - res2 = ldb_realloc_p(ldb, *res, struct ldb_message *, (*count)+2); + res2 = talloc_realloc_p(ldb, *res, struct ldb_message *, (*count)+2); if (!res2) { - msg_free_all_parts(ldb, msg2); + talloc_free(msg2); return -1; } @@ -404,7 +370,7 @@ struct ltdb_search_info { static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { struct ltdb_search_info *sinfo = state; - struct ldb_message msg; + struct ldb_message *msg; int ret; if (key.dsize < 4 || @@ -412,31 +378,37 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi return 0; } + msg = talloc_p(sinfo, struct ldb_message); + if (msg == NULL) { + return -1; + } + /* unpack the record */ - ret = ltdb_unpack_data(sinfo->module, &data, &msg); + ret = ltdb_unpack_data(sinfo->module, &data, msg); if (ret == -1) { sinfo->failures++; + talloc_free(msg); return 0; } - if (!msg.dn) { - msg.dn = key.dptr + 3; + if (!msg->dn) { + msg->dn = key.dptr + 3; } /* see if it matches the given expression */ - if (!ltdb_message_match(sinfo->module, &msg, sinfo->tree, - sinfo->base, sinfo->scope)) { - ltdb_unpack_data_free(sinfo->module, &msg); + if (!ltdb_message_match(sinfo->module, msg, sinfo->tree, + sinfo->base, sinfo->scope)) { + talloc_free(msg); return 0; } - ret = ltdb_add_attr_results(sinfo->module, &msg, sinfo->attrs, &sinfo->count, &sinfo->msgs); + ret = ltdb_add_attr_results(sinfo->module, msg, sinfo->attrs, &sinfo->count, &sinfo->msgs); if (ret == -1) { sinfo->failures++; } - ltdb_unpack_data_free(sinfo->module, &msg); + talloc_free(msg); return ret; } @@ -447,19 +419,11 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi */ int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - int i; ltdb->last_err_string = NULL; - if (!msgs) return 0; - - for (i=0;msgs[i];i++) { - msg_free_all_parts(ldb, msgs[i]); - } - - ldb_free(ldb, msgs); + talloc_free(msgs); return 0; } @@ -475,27 +439,36 @@ static int ltdb_search_full(struct ldb_module *module, const char * const attrs[], struct ldb_message ***res) { struct ltdb_private *ltdb = module->private_data; - int ret; - struct ltdb_search_info sinfo; + int ret, count; + struct ltdb_search_info *sinfo; + + sinfo = talloc_p(ltdb, struct ltdb_search_info); + if (sinfo == NULL) { + return -1; + } - sinfo.tree = tree; - sinfo.module = module; - sinfo.scope = scope; - sinfo.base = base; - sinfo.attrs = attrs; - sinfo.msgs = NULL; - sinfo.count = 0; - sinfo.failures = 0; + sinfo->tree = tree; + sinfo->module = module; + sinfo->scope = scope; + sinfo->base = base; + sinfo->attrs = attrs; + sinfo->msgs = NULL; + sinfo->count = 0; + sinfo->failures = 0; - ret = tdb_traverse(ltdb->tdb, search_func, &sinfo); + ret = tdb_traverse(ltdb->tdb, search_func, sinfo); if (ret == -1) { - ltdb_search_free(module, sinfo.msgs); + talloc_free(sinfo); return -1; } - *res = sinfo.msgs; - return sinfo.count; + *res = talloc_steal(ltdb, sinfo->msgs); + count = sinfo->count; + + talloc_free(sinfo); + + return count; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 179b205097..288633cb01 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -75,7 +75,7 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) if (strncmp(dn, prefix, strlen(prefix)) == 0 && (s = strchr(dn+strlen(prefix), ':'))) { char *attr_name, *attr_name_folded; - attr_name = ldb_strndup(ldb, dn+strlen(prefix), (s-(dn+strlen(prefix)))); + attr_name = talloc_strndup(ldb, dn+strlen(prefix), (s-(dn+strlen(prefix)))); if (!attr_name) { goto failed; } @@ -88,12 +88,12 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) if (!attr_name_folded) { goto failed; } - ldb_asprintf(ldb, &dn_folded, "%s:%s:%s", - prefix, attr_name_folded, - s+1); - ldb_free(ldb, attr_name_folded); + dn_folded = talloc_asprintf(ldb, "%s:%s:%s", + prefix, attr_name_folded, + s+1); + talloc_free(attr_name_folded); } - ldb_free(ldb, attr_name); + talloc_free(attr_name); } else { dn_folded = ldb_casefold(ldb, dn); } @@ -102,8 +102,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) goto failed; } - ldb_asprintf(ldb, &key_str, "DN=%s", dn_folded); - ldb_free(ldb, dn_folded); + key_str = talloc_asprintf(ldb, "DN=%s", dn_folded); + talloc_free(dn_folded); if (!key_str) { goto failed; @@ -126,7 +126,6 @@ failed: */ static int ltdb_lock(struct ldb_module *module, const char *lockname) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA key; int ret; @@ -142,7 +141,7 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) ret = tdb_chainlock(ltdb->tdb, key); - ldb_free(ldb, key.dptr); + talloc_free(key.dptr); return ret; } @@ -152,7 +151,6 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) */ static int ltdb_unlock(struct ldb_module *module, const char *lockname) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA key; @@ -167,7 +165,7 @@ static int ltdb_unlock(struct ldb_module *module, const char *lockname) tdb_chainunlock(ltdb->tdb, key); - ldb_free(ldb, key.dptr); + talloc_free(key.dptr); return 0; } @@ -199,7 +197,6 @@ static int ltdb_modified(struct ldb_module *module, const char *dn) */ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key, tdb_data; int ret; @@ -211,7 +208,7 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg ret = ltdb_pack_data(module, msg, &tdb_data); if (ret == -1) { - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); return -1; } @@ -226,8 +223,8 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg } done: - ldb_free(ldb, tdb_key.dptr); - ldb_free(ldb, tdb_data.dptr); + talloc_free(tdb_key.dptr); + talloc_free(tdb_data.dptr); return ret; } @@ -269,7 +266,6 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) */ int ltdb_delete_noindex(struct ldb_module *module, const char *dn) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key; int ret; @@ -280,7 +276,7 @@ int ltdb_delete_noindex(struct ldb_module *module, const char *dn) } ret = tdb_delete(ltdb->tdb, tdb_key); - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); return ret; } @@ -292,7 +288,7 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) { struct ltdb_private *ltdb = module->private_data; int ret; - struct ldb_message msg; + struct ldb_message *msg = NULL; ltdb->last_err_string = NULL; @@ -301,13 +297,17 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) } if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module, LDBLOCK); - return -1; + goto failed; + } + + msg = talloc_p(module, struct ldb_message); + if (msg == NULL) { + goto failed; } /* in case any attribute of the message was indexed, we need to fetch the old record */ - ret = ltdb_search_dn1(module, dn, &msg); + ret = ltdb_search_dn1(module, dn, msg); if (ret != 1) { /* not finding the old record is an error */ goto failed; @@ -315,23 +315,22 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) ret = ltdb_delete_noindex(module, dn); if (ret == -1) { - ltdb_search_dn1_free(module, &msg); goto failed; } /* remove any indexed attributes */ - ret = ltdb_index_del(module, &msg); - - ltdb_search_dn1_free(module, &msg); + ret = ltdb_index_del(module, msg); if (ret == 0) { ltdb_modified(module, dn); } + talloc_free(msg); ltdb_unlock(module, LDBLOCK); return ret; failed: + talloc_free(msg); ltdb_unlock(module, LDBLOCK); return -1; } @@ -369,8 +368,8 @@ static int msg_add_element(struct ldb_context *ldb, struct ldb_message_element *e2; unsigned int i; - e2 = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, - msg->num_elements+1); + e2 = talloc_realloc_p(msg, msg->elements, struct ldb_message_element, + msg->num_elements+1); if (!e2) { errno = ENOMEM; return -1; @@ -384,7 +383,7 @@ static int msg_add_element(struct ldb_context *ldb, e2->flags = el->flags; e2->values = NULL; if (el->num_values != 0) { - e2->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values); + e2->values = talloc_array_p(msg->elements, struct ldb_val, el->num_values); if (!e2->values) { errno = ENOMEM; return -1; @@ -407,30 +406,28 @@ static int msg_delete_attribute(struct ldb_module *module, struct ldb_context *ldb, struct ldb_message *msg, const char *name) { - unsigned int i, j, count=0; - struct ldb_message_element *el2; - - el2 = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements); - if (!el2) { - errno = ENOMEM; - return -1; - } + unsigned int i, j; for (i=0;inum_elements;i++) { - if (ldb_attr_cmp(msg->elements[i].name, name) != 0) { - el2[count++] = msg->elements[i]; - } else { + if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { for (j=0;jelements[i].num_values;j++) { ltdb_index_del_value(module, msg->dn, &msg->elements[i], j); } - ldb_free(ldb, msg->elements[i].values); + talloc_free(msg->elements[i].values); + if (msg->num_elements > (i+1)) { + memmove(&msg->elements[i], + &msg->elements[i+1], + sizeof(struct ldb_message_element)* + (msg->num_elements - (i+1))); + } + msg->num_elements--; + i--; + msg->elements = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, + msg->num_elements); } } - msg->num_elements = count; - ldb_free(ldb, msg->elements); - msg->elements = el2; - return 0; } @@ -486,7 +483,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key, tdb_data; - struct ldb_message msg2; + struct ldb_message *msg2; unsigned i, j; int ret; @@ -497,19 +494,25 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms tdb_data = tdb_fetch(ltdb->tdb, tdb_key); if (!tdb_data.dptr) { - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); + return -1; + } + + msg2 = talloc_p(tdb_key.dptr, struct ldb_message); + if (msg2 == NULL) { + talloc_free(tdb_key.dptr); return -1; } - ret = ltdb_unpack_data(module, &tdb_data, &msg2); + ret = ltdb_unpack_data(module, &tdb_data, msg2); if (ret == -1) { - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); free(tdb_data.dptr); return -1; } - if (!msg2.dn) { - msg2.dn = msg->dn; + if (!msg2->dn) { + msg2->dn = msg->dn; } for (i=0;inum_elements;i++) { @@ -522,16 +525,16 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms case LDB_FLAG_MOD_ADD: /* add this element to the message. fail if it already exists */ - ret = find_element(&msg2, el->name); + ret = find_element(msg2, el->name); if (ret == -1) { - if (msg_add_element(ldb, &msg2, el) != 0) { + if (msg_add_element(ldb, msg2, el) != 0) { goto failed; } continue; } - el2 = &msg2.elements[ret]; + el2 = &msg2->elements[ret]; /* An attribute with this name already exists, add all * values if they don't already exist. */ @@ -544,15 +547,15 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } } - vals = ldb_realloc_p(ldb, el2->values, struct ldb_val, - el2->num_values + el->num_values); + vals = talloc_realloc_p(msg2->elements, el2->values, struct ldb_val, + el2->num_values + el->num_values); if (vals == NULL) goto failed; for (j=0;jnum_values;j++) { vals[el2->num_values + j] = - ldb_val_dup(ldb, &el->values[j]); + ldb_val_dup(vals, &el->values[j]); } el2->values = vals; @@ -563,11 +566,11 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms case LDB_FLAG_MOD_REPLACE: /* replace all elements of this attribute name with the elements listed. The attribute not existing is not an error */ - msg_delete_attribute(module, ldb, &msg2, msg->elements[i].name); + msg_delete_attribute(module, ldb, msg2, msg->elements[i].name); /* add the replacement element, if not empty */ if (msg->elements[i].num_values != 0 && - msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) { + msg_add_element(ldb, msg2, &msg->elements[i]) != 0) { goto failed; } break; @@ -576,7 +579,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms /* we could be being asked to delete all values or just some values */ if (msg->elements[i].num_values == 0) { - if (msg_delete_attribute(module, ldb, &msg2, + if (msg_delete_attribute(module, ldb, msg2, msg->elements[i].name) != 0) { ltdb->last_err_string = "No such attribute"; goto failed; @@ -585,7 +588,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } for (j=0;jelements[i].num_values;j++) { if (msg_delete_element(module, - &msg2, + msg2, msg->elements[i].name, &msg->elements[i].values[j]) != 0) { ltdb->last_err_string = "No such attribute"; @@ -600,17 +603,15 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } /* we've made all the mods - save the modified record back into the database */ - ret = ltdb_store(module, &msg2, TDB_MODIFY); + ret = ltdb_store(module, msg2, TDB_MODIFY); - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(module, &msg2); return ret; failed: - ldb_free(ldb, tdb_key.dptr); + talloc_free(tdb_key.dptr); free(tdb_data.dptr); - ltdb_unpack_data_free(module, &msg2); return -1; } @@ -649,10 +650,9 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) */ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char *newdn) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; int ret; - struct ldb_message msg; + struct ldb_message *msg; const char *error_str; ltdb->last_err_string = NULL; @@ -661,28 +661,28 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char return -1; } + msg = talloc_p(module, struct ldb_message); + if (msg == NULL) { + goto failed; + } + /* in case any attribute of the message was indexed, we need to fetch the old record */ - ret = ltdb_search_dn1(module, olddn, &msg); + ret = ltdb_search_dn1(module, olddn, msg); if (ret != 1) { /* not finding the old record is an error */ goto failed; } - msg.dn = ldb_strdup(ldb,newdn); - if (!msg.dn) { - ltdb_search_dn1_free(module, &msg); + msg->dn = talloc_strdup(msg, newdn); + if (!msg->dn) { goto failed; } - ret = ltdb_add(module, &msg); + ret = ltdb_add(module, msg); if (ret == -1) { - ldb_free(ldb, msg.dn); - ltdb_search_dn1_free(module, &msg); goto failed; } - ldb_free(ldb, msg.dn); - ltdb_search_dn1_free(module, &msg); ret = ltdb_delete(module, olddn); error_str = ltdb->last_err_string; @@ -692,10 +692,13 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char ltdb->last_err_string = error_str; + talloc_free(msg); ltdb_unlock(module, LDBLOCK); return ret; + failed: + talloc_free(msg); ltdb_unlock(module, LDBLOCK); return -1; } @@ -706,18 +709,8 @@ failed: static int ltdb_close(struct ldb_module *module) { struct ldb_context *ldb = module->ldb; - struct ltdb_private *ltdb = module->private_data; - int ret; - - ltdb->last_err_string = NULL; - - ltdb_cache_free(module); - ldb_set_alloc(ldb, NULL, NULL); - - ret = tdb_close(ltdb->tdb); - ldb_free(ldb, ltdb); - free(ldb); - return ret; + talloc_free(ldb); + return 0; } @@ -745,11 +738,20 @@ static const struct ldb_module_ops ltdb_ops = { ltdb_rename, ltdb_lock, ltdb_unlock, - ltdb_errstring, - ltdb_cache_free + ltdb_errstring }; +/* + destroy the ltdb context +*/ +static int ltdb_destructor(void *p) +{ + struct ltdb_private *ltdb = p; + tdb_close(ltdb->tdb); + return 0; +} + /* connect to the database */ @@ -763,7 +765,7 @@ struct ldb_context *ltdb_connect(const char *url, TDB_CONTEXT *tdb; struct ldb_context *ldb; - ldb = calloc(1, sizeof(struct ldb_context)); + ldb = talloc_zero_p(NULL, struct ldb_context); if (!ldb) { errno = ENOMEM; return NULL; @@ -773,6 +775,7 @@ struct ldb_context *ltdb_connect(const char *url, if (strchr(url, ':')) { if (strncmp(url, "tdb://", 6) != 0) { errno = EINVAL; + talloc_free(ldb); return NULL; } path = url+6; @@ -791,14 +794,14 @@ struct ldb_context *ltdb_connect(const char *url, /* note that we use quite a large default hash size */ tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); if (!tdb) { - free(ldb); + talloc_free(ldb); return NULL; } - ltdb = ldb_malloc_p(ldb, struct ltdb_private); + ltdb = talloc_zero_p(ldb, struct ltdb_private); if (!ltdb) { tdb_close(tdb); - free(ldb); + talloc_free(ldb); errno = ENOMEM; return NULL; } @@ -806,12 +809,11 @@ struct ldb_context *ltdb_connect(const char *url, ltdb->tdb = tdb; ltdb->sequence_number = 0; - memset(<db->cache, 0, sizeof(ltdb->cache)); + talloc_set_destructor(ltdb, ltdb_destructor); - ldb->modules = ldb_malloc_p(ldb, struct ldb_module); + ldb->modules = talloc_p(ldb, struct ldb_module); if (!ldb->modules) { - tdb_close(tdb); - free(ldb); + talloc_free(ldb); errno = ENOMEM; return NULL; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 7d6f35dc79..49052550d0 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -13,17 +13,17 @@ struct ltdb_private { handling. It has plenty of digits of precision */ double sequence_number; - struct { - struct ldb_message baseinfo; - struct ldb_message indexlist; - struct ldb_message attributes; - struct ldb_message subclasses; + struct ltdb_cache { + struct ldb_message *baseinfo; + struct ldb_message *indexlist; + struct ldb_message *attributes; + struct ldb_message *subclasses; struct { char *name; int flags; } last_attribute; - } cache; + } *cache; /* error if an internal ldb+tdb error */ const char *last_err_string; @@ -51,7 +51,7 @@ struct ltdb_private { /* The following definitions come from lib/ldb/ldb_tdb/ldb_cache.c */ -void ltdb_cache_free(struct ldb_module *module); +int ltdb_cache_reload(struct ldb_module *module); int ltdb_cache_load(struct ldb_module *module); int ltdb_increase_sequence_number(struct ldb_module *module); int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name); diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 3581969c18..afafe1bbd9 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -98,11 +98,6 @@ static const char *skel_errstring(struct ldb_module *module) return ldb_next_errstring(module); } -static void skel_cache_free(struct ldb_module *module) -{ - ldb_next_cache_free(module); -} - static const struct ldb_module_ops skel_ops = { "skel", skel_close, @@ -114,8 +109,7 @@ static const struct ldb_module_ops skel_ops = { skel_rename_record, skel_named_lock, skel_named_unlock, - skel_errstring, - skel_cache_free + skel_errstring }; #ifdef HAVE_DLOPEN diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index fde87ef4a6..53c39e751e 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -57,7 +57,8 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message return ldb_next_search_free(module, res); } -static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) +static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr_name, const char *time_string, unsigned int flags) { struct ldb_val *values; char *name, *timestr; @@ -69,10 +70,11 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, co } } - msg->elements = ldb_realloc_array(ldb, msg->elements, sizeof(struct ldb_message_element), msg->num_elements + 1); - name = ldb_strdup(ldb, attr_name); - timestr = ldb_strdup(ldb, time_string); - values = ldb_malloc(ldb, sizeof(struct ldb_val)); + msg->elements = talloc_realloc_p(msg, msg->elements, + struct ldb_message_element, msg->num_elements + 1); + name = talloc_strdup(msg->elements, attr_name); + timestr = talloc_strdup(msg->elements, time_string); + values = talloc_p(msg->elements, struct ldb_val); if (!msg->elements || !name || !timestr || !values) { return -1; } @@ -89,19 +91,6 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, co return 0; } -static void free_elements(struct ldb_context *ldb, struct ldb_message *msg, int real_el_num) -{ - int i; - - for (i = real_el_num; i < msg->num_elements; i++) { - ldb_free(ldb, msg->elements[i].name); - ldb_free(ldb, msg->elements[i].values[0].data); - ldb_free(ldb, msg->elements[i].values); - } - ldb_free(ldb, msg->elements); - ldb_free(ldb, msg); -} - /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -120,25 +109,24 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes return -1; } - /* formatted like: 20040408072012.0Z */ - ldb_asprintf(module->ldb, ×tr, - "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - - if (!timestr) { + msg2 = talloc_p(module, struct ldb_message); + if (!msg2) { return -1; } - msg2 = ldb_malloc_p(module->ldb, struct ldb_message); - if (!msg2) { + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { return -1; } + msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -147,13 +135,11 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); - - ldb_free(module->ldb, timestr); } if (msg2) { ret = ldb_next_add_record(module, msg2); - free_elements(module->ldb, msg2, msg->num_elements); + talloc_free(msg2); } else { ret = ldb_next_add_record(module, msg); } @@ -179,38 +165,36 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return -1; } + msg2 = talloc_p(module, struct ldb_message); + if (!msg2) { + return -1; + } + /* formatted like: 20040408072012.0Z */ - ldb_asprintf(module->ldb, ×tr, + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - if (!timestr) { return -1; } - msg2 = ldb_malloc_p(module->ldb, struct ldb_message); - if (!msg2) { - return -1; - } msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = ldb_malloc_array_p(module->ldb, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); - - ldb_free(module->ldb, timestr); } if (msg2) { ret = ldb_next_modify_record(module, msg2); - free_elements(module->ldb, msg2, msg->num_elements); + talloc_free(msg2); } else { ret = ldb_next_modify_record(module, msg); } @@ -249,12 +233,6 @@ static const char *timestamps_errstring(struct ldb_module *module) return ldb_next_errstring(module); } -static void timestamps_cache_free(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_cache_free\n"); - ldb_next_cache_free(module); -} - static const struct ldb_module_ops timestamps_ops = { "timestamps", timestamps_close, @@ -266,8 +244,7 @@ static const struct ldb_module_ops timestamps_ops = { timestamps_rename_record, timestamps_lock, timestamps_unlock, - timestamps_errstring, - timestamps_cache_free + timestamps_errstring }; @@ -280,7 +257,7 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o { struct ldb_module *ctx; - ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + ctx = talloc_p(ldb, struct ldb_module); if (!ctx) return NULL; diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index c4647a7ba3..4fb54b6c3b 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -25,6 +25,14 @@ time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 echo "Adding index" $VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 +echo "testing indexed search" +$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 +$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham))' || exit 1 +$VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham))' || exit 1 +$VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' || exit 1 +$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 +$VALGRIND bin/ldbsearch '(&(uid=uham)(!(uid=uhamxx)))' || exit 1 + echo "Starting ldbtest indexed" time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 9d19a1db0a..d95036497a 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -66,10 +66,10 @@ static int process_file(struct ldb_context *ldb, FILE *f) break; } - ret = ldb_add(ldb, &ldif->msg); + ret = ldb_add(ldb, ldif->msg); if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", - ldb_errstring(ldb), ldif->msg.dn); + ldb_errstring(ldb), ldif->msg->dn); failures++; } else { count++; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 6cd6ef041b..66b684f4d5 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -48,7 +48,7 @@ static void ldif_write_msg(struct ldb_context *ldb, { struct ldb_ldif ldif; ldif.changetype = changetype; - ldif.msg = *msg; + ldif.msg = msg; ldb_ldif_write_file(ldb, f, &ldif); } @@ -60,14 +60,16 @@ static int modify_record(struct ldb_context *ldb, struct ldb_message *msg1, struct ldb_message *msg2) { - struct ldb_message mod; + struct ldb_message *mod; struct ldb_message_element *el; unsigned int i; int count = 0; - mod.dn = msg1->dn; - mod.num_elements = 0; - mod.elements = NULL; + mod = ldb_msg_new(ldb); + + mod->dn = msg1->dn; + mod->num_elements = 0; + mod->elements = NULL; msg2 = ldb_msg_canonicalize(ldb, msg2); if (msg2 == NULL) { @@ -84,7 +86,7 @@ static int modify_record(struct ldb_context *ldb, continue; } - if (ldb_msg_add(ldb, &mod, + if (ldb_msg_add(ldb, mod, &msg2->elements[i], el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { return -1; @@ -96,7 +98,7 @@ static int modify_record(struct ldb_context *ldb, for (i=0;inum_elements;i++) { el = ldb_msg_find_element(msg2, msg1->elements[i].name); if (!el) { - if (ldb_msg_add_empty(ldb, &mod, + if (ldb_msg_add_empty(ldb, mod, msg1->elements[i].name, LDB_FLAG_MOD_DELETE) != 0) { return -1; @@ -105,18 +107,18 @@ static int modify_record(struct ldb_context *ldb, } } - if (mod.num_elements == 0) { + if (mod->num_elements == 0) { return 0; } - if (ldb_modify(ldb, &mod) != 0) { + if (ldb_modify(ldb, mod) != 0) { fprintf(stderr, "failed to modify %s - %s\n", msg1->dn, ldb_errstring(ldb)); return -1; } if (verbose > 0) { - ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, &mod); + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod); } return count; @@ -205,7 +207,7 @@ static int save_ldif(struct ldb_context *ldb, fprintf(f, "# record %d\n", i+1); ldif.changetype = LDB_CHANGETYPE_NONE; - ldif.msg = *msgs[i]; + ldif.msg = msgs[i]; ldb_ldif_write_file(ldb, f, &ldif); } @@ -278,12 +280,12 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun } while ((ldif = ldb_ldif_read_file(ldb, f))) { - msgs2 = ldb_realloc_p(ldb, msgs2, struct ldb_message *, count2+1); + msgs2 = talloc_realloc_p(ldb, msgs2, struct ldb_message *, count2+1); if (!msgs2) { fprintf(stderr, "out of memory"); return -1; } - msgs2[count2++] = &ldif->msg; + msgs2[count2++] = ldif->msg; } fclose(f); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 5fabba57b7..3bdb946897 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -62,18 +62,18 @@ static int process_file(struct ldb_context *ldb, FILE *f) switch (ldif->changetype) { case LDB_CHANGETYPE_NONE: case LDB_CHANGETYPE_ADD: - ret = ldb_add(ldb, &ldif->msg); + ret = ldb_add(ldb, ldif->msg); break; case LDB_CHANGETYPE_DELETE: - ret = ldb_delete(ldb, ldif->msg.dn); + ret = ldb_delete(ldb, ldif->msg->dn); break; case LDB_CHANGETYPE_MODIFY: - ret = ldb_modify(ldb, &ldif->msg); + ret = ldb_modify(ldb, ldif->msg); break; } if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", - ldb_errstring(ldb), ldif->msg.dn); + ldb_errstring(ldb), ldif->msg->dn); failures++; } else { count++; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index fced589572..9041231faf 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -71,7 +71,7 @@ static int do_search(struct ldb_context *ldb, printf("# record %d\n", i+1); ldif.changetype = LDB_CHANGETYPE_NONE; - ldif.msg = *msgs[i]; + ldif.msg = msgs[i]; ldb_ldif_write_file(ldb, stdout, &ldif); } diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 645bc93fd3..01fa1b8ed7 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -130,7 +130,7 @@ static void add_records(struct ldb_context *ldb, free(name); free(msg.dn); free(vals[1][0].data); - ldb_free(ldb, vals[2][0].data); + talloc_free(vals[2][0].data); free(vals[3][0].data); free(vals[4][0].data); } @@ -288,7 +288,7 @@ be indexed */ static void start_test_index(struct ldb_context **ldb) { - struct ldb_message msg; + struct ldb_message *msg; struct ldb_message **res; int ret; @@ -296,24 +296,25 @@ static void start_test_index(struct ldb_context **ldb) ldb_delete(*ldb, "@INDEXLIST"); - memset(&msg, 0, sizeof(msg)); - msg.dn = strdup("@INDEXLIST"); - ldb_msg_add_string(*ldb, &msg, "@IDXATTR", strdup("uid")); + msg = ldb_msg_new(NULL); + + msg->dn = strdup("@INDEXLIST"); + ldb_msg_add_string(*ldb, msg, "@IDXATTR", strdup("uid")); - if (ldb_add(*ldb, &msg) != 0) { - printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); + if (ldb_add(*ldb, msg) != 0) { + printf("Add of %s failed - %s\n", msg->dn, ldb_errstring(*ldb)); exit(1); } - memset(&msg, 0, sizeof(msg)); - asprintf(&msg.dn, "cn=%s,%s", "test", base_dn); - ldb_msg_add_string(*ldb, &msg, "cn", strdup("test")); - ldb_msg_add_string(*ldb, &msg, "sn", strdup("test")); - ldb_msg_add_string(*ldb, &msg, "uid", strdup("test")); - ldb_msg_add_string(*ldb, &msg, "objectClass", strdup("OpenLDAPperson")); + memset(msg, 0, sizeof(*msg)); + asprintf(&msg->dn, "cn=%s,%s", "test", base_dn); + ldb_msg_add_string(*ldb, msg, "cn", strdup("test")); + ldb_msg_add_string(*ldb, msg, "sn", strdup("test")); + ldb_msg_add_string(*ldb, msg, "uid", strdup("test")); + ldb_msg_add_string(*ldb, msg, "objectClass", strdup("OpenLDAPperson")); - if (ldb_add(*ldb, &msg) != 0) { - printf("Add of %s failed - %s\n", msg.dn, ldb_errstring(*ldb)); + if (ldb_add(*ldb, msg) != 0) { + printf("Add of %s failed - %s\n", msg->dn, ldb_errstring(*ldb)); exit(1); } @@ -335,7 +336,7 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - if (ldb_delete(*ldb, msg.dn) != 0 || + if (ldb_delete(*ldb, msg->dn) != 0 || ldb_delete(*ldb, "@INDEXLIST") != 0) { printf("cleanup failed - %s\n", ldb_errstring(*ldb)); exit(1); -- cgit From 500d5523d2a83234d6bfbf264d78293426488bfc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 07:51:13 +0000 Subject: r4475: fixed smbd to work with the small changes in the ldb API (the most important change was in the ldb_msg_add_*() routines, which now use the msg as a context, and thus it needs to be a talloc ptr) (This used to be commit 1a4713bfd0e519f3eb7b3241121ff914a6eeef18) --- source4/lib/db_wrap.c | 1 + source4/lib/registry/reg_backend_ldb.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index e9055399ad..a9ca7e3e0a 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -92,6 +92,7 @@ struct ldb_wrap *ldb_wrap_connect(TALLOC_CTX *mem_ctx, talloc_free(w); return NULL; } + talloc_steal(w, w->ldb); talloc_set_destructor(w, ldb_wrap_destructor); ldb_set_debug(w->ldb, ldb_wrap_debug, NULL); diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index ffb9215cf0..e0d7b6e2cb 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -261,17 +261,17 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey) { struct ldb_context *ctx = parent->hive->backend_data; - struct ldb_message msg; + struct ldb_message *msg; struct ldb_key_data *newkd; int ret; - ZERO_STRUCT(msg); + msg = ldb_msg_new(mem_ctx); - msg.dn = reg_path_to_ldb(mem_ctx, parent, name, NULL); + msg->dn = reg_path_to_ldb(msg, parent, name, NULL); - ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name)); + ldb_msg_add_string(ctx, msg, "key", talloc_strdup(mem_ctx, name)); - ret = ldb_add(ctx, &msg); + ret = ldb_add(ctx, msg); if (ret < 0) { DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); return WERR_FOOBAR; @@ -281,7 +281,7 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con (*newkey)->name = talloc_strdup(mem_ctx, name); (*newkey)->backend_data = newkd = talloc_zero_p(*newkey, struct ldb_key_data); - newkd->dn = msg.dn; + newkd->dn = talloc_steal(newkd, msg->dn); return WERR_OK; } -- cgit From 62ffbdb9f1d9ded63f6d8623f14741145a2d6b47 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 08:53:58 +0000 Subject: r4476: added a little gcov howto for ldb (This used to be commit 5dc1995118c7d25adf89b6cc6156b1e6fc281e9b) --- source4/lib/ldb/README.gcov | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 source4/lib/ldb/README.gcov (limited to 'source4/lib') diff --git a/source4/lib/ldb/README.gcov b/source4/lib/ldb/README.gcov new file mode 100644 index 0000000000..02f090f69f --- /dev/null +++ b/source4/lib/ldb/README.gcov @@ -0,0 +1,33 @@ +Here is how to use gcov to test code coverage in ldb. + +Step 1: enable gcov support + + Edit Makefile.ldb and uncommend the two GCOV_ lines + +Step 2: build ldb + + make -sf Makefile.ldb clean all + +Step 3: run the test suite + make -sf Makefile.ldb test-tdb + +Step 4: produce the gcov report + make -sf Makefile.ldb gcov + +Step 5: read the summary reports + less *.report.gcov + +Step 6: examine the per-file reports + less ldb_tdb\#ldb_tdb.c.gcov + +You can also combine steps 2 to 4 like this: + + make -sf Makefile.ldb clean all test-tdb gcov + +Note that you should not expect 100% coverage, as some error paths +(such as memory allocation failures) are verr hard to trigger. There +are ways of working around this, but they are quite tricky (they +involve allocation wrappers that "fork and fail on malloc"). + +The lines to look for in the per-file reports are the ones starting +with "#####". Those are lines that are never executed. -- cgit From 09a76e204cf339862f8b0b45979d65cc34aa3c36 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 09:46:59 +0000 Subject: r4477: expanded the test suite to increase code coverage a lot (This used to be commit 4edbd1b18ee38e584cf844b64c7fcb2645921837) --- source4/lib/ldb/Makefile.ldb | 8 +++--- source4/lib/ldb/common/util.c | 51 ----------------------------------- source4/lib/ldb/include/ldb_private.h | 4 --- source4/lib/ldb/ldb_tdb/ldb_index.c | 51 +++++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_pack.c | 13 +-------- source4/lib/ldb/tests/test-generic.sh | 6 ++++- source4/lib/ldb/tests/test-index.ldif | 13 ++++++--- source4/lib/ldb/tests/test.ldif | 2 +- source4/lib/ldb/tools/ldbsearch.c | 2 +- 9 files changed, 73 insertions(+), 77 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index a472f949af..75c298241d 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -15,6 +15,8 @@ TALLOCDIR=../talloc CFLAGS1=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. \ -I$(TDBDIR)/include -I$(TALLOCDIR) -DUSE_MMAP=1 $(LDAP_FLAGS) + +# enable the following two lines to build with gcov code coverage support #GCOV_FLAGS = -ftest-coverage -fprofile-arcs #GCOV_LIBS = -lgcov @@ -99,6 +101,6 @@ test: test-tdb test-ldap gcov: gcov -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov gcov -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov - gcov -po common common/*.c 2| tee ldb_common.report.gcov - gcov -po modules modules/*.c 2| tee ldb_modules.report.gcov - gcov -po tools tools/*.c 2| tee ldb_tools.report.gcov + gcov -po common common/*.c 2| tee common.report.gcov + gcov -po modules modules/*.c 2| tee modules.report.gcov + gcov -po tools tools/*.c 2| tee tools.report.gcov diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index 0c9cf297c1..c2fd72acd1 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -37,57 +37,6 @@ #include "ldb/include/ldb_private.h" -/* - find an element in a list, using the given comparison function and - assuming that the list is already sorted using comp_fn - - return -1 if not found, or the index of the first occurance of needle if found -*/ -int ldb_list_find(const void *needle, - const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn) -{ - const char *base_p = base; - size_t min_i, max_i, test_i; - - if (nmemb == 0) { - return -1; - } - - min_i = 0; - max_i = nmemb-1; - - while (min_i < max_i) { - int r; - - test_i = (min_i + max_i) / 2; - r = comp_fn(needle, *(void * const *)(base_p + (size * test_i))); - if (r == 0) { - /* scan back for first element */ - while (test_i > 0 && - comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) { - test_i--; - } - return test_i; - } - if (r < 0) { - if (test_i == 0) { - return -1; - } - max_i = test_i - 1; - } - if (r > 0) { - min_i = test_i + 1; - } - } - - if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) { - return min_i; - } - - return -1; -} - - /* common code for parsing -o options in ldb tools */ diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 3d3b1ec0eb..426da5ccae 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -100,10 +100,6 @@ int ldb_next_named_lock(struct ldb_module *module, const char *lockname); int ldb_next_named_unlock(struct ldb_module *module, const char *lockname); const char *ldb_next_errstring(struct ldb_module *module); -/* The following definitions come from lib/ldb/common/util.c */ -int ldb_list_find(const void *needle, - const void *base, size_t nmemb, size_t size, comparison_fn_t comp_fn); - /* The following definitions come from lib/ldb/common/ldb_debug.c */ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index ff0cabb0d6..88ef997a03 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -38,6 +38,57 @@ #include "ldb/ldb_tdb/ldb_tdb.h" #include "ldb/include/ldb_parse.h" +/* + find an element in a list, using the given comparison function and + assuming that the list is already sorted using comp_fn + + return -1 if not found, or the index of the first occurance of needle if found +*/ +static int ldb_list_find(const void *needle, + const void *base, size_t nmemb, size_t size, + comparison_fn_t comp_fn) +{ + const char *base_p = base; + size_t min_i, max_i, test_i; + + if (nmemb == 0) { + return -1; + } + + min_i = 0; + max_i = nmemb-1; + + while (min_i < max_i) { + int r; + + test_i = (min_i + max_i) / 2; + r = comp_fn(needle, *(void * const *)(base_p + (size * test_i))); + if (r == 0) { + /* scan back for first element */ + while (test_i > 0 && + comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) { + test_i--; + } + return test_i; + } + if (r < 0) { + if (test_i == 0) { + return -1; + } + max_i = test_i - 1; + } + if (r > 0) { + min_i = test_i + 1; + } + } + + if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) { + return min_i; + } + + return -1; +} + struct dn_list { unsigned int count; char **dn; diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index a548a4189b..4c1241d0bd 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -138,16 +138,6 @@ int ltdb_pack_data(struct ldb_module *module, return 0; } -/* - free the memory allocated from a ltdb_unpack_data() -*/ -void ltdb_unpack_data_free(struct ldb_module *module, - struct ldb_message *message) -{ - talloc_free(message->elements); -} - - /* unpack a ldb message from a linear buffer in TDB_DATA @@ -267,7 +257,6 @@ int ltdb_unpack_data(struct ldb_module *module, return 0; failed: - ltdb_unpack_data_free(module, message); - + talloc_free(message->elements); return -1; } diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 4fb54b6c3b..2b2ab2e78a 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -27,11 +27,15 @@ $VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 echo "testing indexed search" $VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 +$VALGRIND bin/ldbsearch '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham))' || exit 1 $VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham))' || exit 1 $VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' || exit 1 $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 -$VALGRIND bin/ldbsearch '(&(uid=uham)(!(uid=uhamxx)))' || exit 1 +$VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 +$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 +$VALGRIND bin/ldbsearch '((' uid && exit 1 +$VALGRIND bin/ldbsearch 'dn=cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US' uid || exit 1 echo "Starting ldbtest indexed" time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index 6b2e921ebd..24ac408764 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -1,6 +1,11 @@ dn: @INDEXLIST @IDXATTR: uid -# it is much better not to index on objectclass if nearly -# all the records are the same class (the index is expensive -# to maintain, and doesn't really gain anything) -# @IDXATTR: objectclass +@IDXATTR: objectclass + +dn: @ATTRIBUTES +uid: CASE_INSENSITIVE WILDCARD + +dn: @SUBCLASSES +top: person +person: organizationalPerson +organizationalPerson: OpenLDAPperson diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif index 8d6c0c750e..7fe3a8ffd7 100644 --- a/source4/lib/ldb/tests/test.ldif +++ b/source4/lib/ldb/tests/test.ldif @@ -212,7 +212,7 @@ objectclass: OpenLDAPperson cn: Barbara Jensen cn: Babs Jensen sn:: IEplbnNlbiA= -uid: bjensen +uid:: YmplCW5zZW4 title: Mythical Manager, Research Systems postaladdress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann Arbor, MI 48103-4943 diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 9041231faf..5e0246d7a9 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -153,7 +153,7 @@ static int do_search(struct ldb_context *ldb, attrs = (const char * const *)(argv+1); } - ldb = ldb_connect(ldb_url, 0, options); + ldb = ldb_connect(ldb_url, LDB_FLG_RDONLY, options); if (!ldb) { perror("ldb_connect"); exit(1); -- cgit From f4b349127bdfe233476fe2efba961912f39a5cbd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 12:55:33 +0000 Subject: r4479: added the function talloc_autofree_context() which returns a talloc context that will automatically be freed on program exit. This is useful for reducing clutter in leak reports (This used to be commit cf73dda652e0a121901f22771104be6751c0fcb9) --- source4/lib/dcom/common/tables.c | 10 +++++++--- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/talloc/talloc.c | 21 +++++++++++++++++++++ source4/lib/talloc/talloc.h | 1 + source4/lib/talloc/talloc_guide.txt | 6 ++++++ 5 files changed, 36 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index 6b0d99cae3..faf67710e0 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -76,10 +76,13 @@ const void *dcom_proxy_vtable_by_iid(const struct GUID *iid) NTSTATUS dcom_register_interface(const void *_iface) { const struct dcom_interface *iface = _iface; - struct interface_list *l = talloc_zero_p(interfaces, struct interface_list); + struct interface_list *l; + + l = talloc_zero_p(interfaces?interfaces:talloc_autofree_context(), + struct interface_list); l->interface = *iface; - + DLIST_ADD(interfaces, l); return NT_STATUS_OK; @@ -88,7 +91,8 @@ NTSTATUS dcom_register_interface(const void *_iface) NTSTATUS dcom_register_class(const void *_class) { const struct dcom_class *class = _class; - struct class_list *l = talloc_zero_p(classes, struct class_list); + struct class_list *l = talloc_zero_p(classes?classes:talloc_autofree_context(), + struct class_list); l->class = *class; diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 9b03a69f3f..442b34bc13 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -44,7 +44,7 @@ NTSTATUS registry_register(const void *_hive_ops) return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = talloc_p(NULL, struct reg_init_function_entry); + entry = talloc_p(talloc_autofree_context(), struct reg_init_function_entry); entry->hive_functions = hive_ops; DLIST_ADD(backends, entry); diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 4666e28288..9e8868191f 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -67,6 +67,7 @@ NULL */ static const void *null_context; +static void *cleanup_context; struct talloc_reference_handle { @@ -1004,3 +1005,23 @@ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) { return _talloc_realloc(context, ptr, size, NULL); } + + +static void talloc_autofree(void) +{ + talloc_free(cleanup_context); + cleanup_context = NULL; +} + +/* + return a context which will be auto-freed on exit + this is useful for reducing the noise in leak reports +*/ +void *talloc_autofree_context(void) +{ + if (cleanup_context == NULL) { + cleanup_context = talloc_named_const(NULL, 0, "autofree_context"); + atexit(talloc_autofree); + } + return cleanup_context; +} diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 6ebba447aa..9e828f2f0d 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -91,6 +91,7 @@ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char * void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); void *talloc_realloc_fn(const void *context, void *ptr, size_t size); +void *talloc_autofree_context(void); #endif diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index b3b148d476..ce3c8bde68 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -490,3 +490,9 @@ implementation encapsulates the functionality of malloc(), free() and realloc() in one call, which is why it is useful to be able to pass around a single function pointer. +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_autofree_context(void); + +This is a handy utility function that returns a talloc context +which will be automatically freed on program exit. This can be used +to reduce the noise in memory leak reports. -- cgit From fe07db9ca736d130a77c673d5b716365a39f289e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 13:04:32 +0000 Subject: r4481: get rid of the last leak (This used to be commit 52de02b2c31eefac75ce0582ed8acae8007e7cc2) --- source4/lib/dcom/classes/simple.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c index e8b8730267..90dda6bc84 100644 --- a/source4/lib/dcom/classes/simple.c +++ b/source4/lib/dcom/classes/simple.c @@ -32,7 +32,9 @@ NTSTATUS dcom_simple_init(void) GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); - simple_class.class_object = dcom_new_local_ifacep(NULL, dcom_interface_by_iid(&iid), &simple_classobject, NULL); + simple_class.class_object = dcom_new_local_ifacep(talloc_autofree_context(), + dcom_interface_by_iid(&iid), + &simple_classobject, NULL); GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); return dcom_register_class(&simple_class); -- cgit From 3e5235a568777b5103612069e413cabe37b83c2b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 23:03:50 +0000 Subject: r4486: fixed some memory leaks in the new ldb code, by ensuring that memory is always allocated as a child of the right context (This used to be commit 1071712cf5951fa2e94f314bd7678cfa51b2dbcd) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 8 ++++---- source4/lib/ldb/ldb_tdb/ldb_pack.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index e7420c5f7a..037403d81e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -205,14 +205,14 @@ int ltdb_increase_sequence_number(struct ldb_module *module) char *s = NULL; int ret; - s = talloc_asprintf(ldb, "%.0f", ltdb->sequence_number+1); - if (!s) { + msg = talloc_p(ltdb, struct ldb_message); + if (msg == NULL) { errno = ENOMEM; return -1; } - msg = talloc_p(ltdb, struct ldb_message); - if (msg == NULL) { + s = talloc_asprintf(msg, "%.0f", ltdb->sequence_number+1); + if (!s) { errno = ENOMEM; return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 4c1241d0bd..501728fac5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -199,7 +199,7 @@ int ltdb_unpack_data(struct ldb_module *module, goto failed; } - message->elements = talloc_array_p(ldb, struct ldb_message_element, message->num_elements); + message->elements = talloc_array_p(message, struct ldb_message_element, message->num_elements); if (!message->elements) { errno = ENOMEM; goto failed; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 720188b74c..295c9578cc 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -306,7 +306,7 @@ int ltdb_search_dn(struct ldb_module *module, char *dn, return -1; } - (*res)[0] = msg2; + (*res)[0] = talloc_steal(*res, msg2); (*res)[1] = NULL; return 1; @@ -341,7 +341,7 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, (*res) = res2; - (*res)[*count] = msg2; + (*res)[*count] = talloc_steal(*res, msg2); (*res)[(*count)+1] = NULL; (*count)++; -- cgit From 7eeeb4a727f5cf96258674fb4048ad328927d513 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 23:09:11 +0000 Subject: r4488: removed an unused variable (This used to be commit 1dfc41c9a3b6418236a1f04b5cf3f9ef9e8b608e) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 037403d81e..ebdfdb7bed 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -197,7 +197,6 @@ failed: */ int ltdb_increase_sequence_number(struct ldb_module *module) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; struct ldb_message *msg; struct ldb_message_element el; -- cgit From 022bc635ef40827e778e08ee27cb8f16bf28c90b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 2 Jan 2005 23:48:07 +0000 Subject: r4493: change name of README.gcov so it doesn't get deleted by "make clean" :-) (This used to be commit 209ba7b889823f1badb0337412b2b9b34c5e23de) --- source4/lib/ldb/README.gcov | 33 --------------------------------- source4/lib/ldb/README_gcov.txt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 source4/lib/ldb/README.gcov create mode 100644 source4/lib/ldb/README_gcov.txt (limited to 'source4/lib') diff --git a/source4/lib/ldb/README.gcov b/source4/lib/ldb/README.gcov deleted file mode 100644 index 02f090f69f..0000000000 --- a/source4/lib/ldb/README.gcov +++ /dev/null @@ -1,33 +0,0 @@ -Here is how to use gcov to test code coverage in ldb. - -Step 1: enable gcov support - - Edit Makefile.ldb and uncommend the two GCOV_ lines - -Step 2: build ldb - - make -sf Makefile.ldb clean all - -Step 3: run the test suite - make -sf Makefile.ldb test-tdb - -Step 4: produce the gcov report - make -sf Makefile.ldb gcov - -Step 5: read the summary reports - less *.report.gcov - -Step 6: examine the per-file reports - less ldb_tdb\#ldb_tdb.c.gcov - -You can also combine steps 2 to 4 like this: - - make -sf Makefile.ldb clean all test-tdb gcov - -Note that you should not expect 100% coverage, as some error paths -(such as memory allocation failures) are verr hard to trigger. There -are ways of working around this, but they are quite tricky (they -involve allocation wrappers that "fork and fail on malloc"). - -The lines to look for in the per-file reports are the ones starting -with "#####". Those are lines that are never executed. diff --git a/source4/lib/ldb/README_gcov.txt b/source4/lib/ldb/README_gcov.txt new file mode 100644 index 0000000000..02f090f69f --- /dev/null +++ b/source4/lib/ldb/README_gcov.txt @@ -0,0 +1,33 @@ +Here is how to use gcov to test code coverage in ldb. + +Step 1: enable gcov support + + Edit Makefile.ldb and uncommend the two GCOV_ lines + +Step 2: build ldb + + make -sf Makefile.ldb clean all + +Step 3: run the test suite + make -sf Makefile.ldb test-tdb + +Step 4: produce the gcov report + make -sf Makefile.ldb gcov + +Step 5: read the summary reports + less *.report.gcov + +Step 6: examine the per-file reports + less ldb_tdb\#ldb_tdb.c.gcov + +You can also combine steps 2 to 4 like this: + + make -sf Makefile.ldb clean all test-tdb gcov + +Note that you should not expect 100% coverage, as some error paths +(such as memory allocation failures) are verr hard to trigger. There +are ways of working around this, but they are quite tricky (they +involve allocation wrappers that "fork and fail on malloc"). + +The lines to look for in the per-file reports are the ones starting +with "#####". Those are lines that are never executed. -- cgit From ab4e92ab21887430774fda380ccbb14a10cab2da Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 08:52:39 +0000 Subject: r4502: add an error reporting function (This used to be commit 985a58a16d04f3b92b4bbff86f6c466385f01321) --- source4/lib/ldb/modules/timestamps.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 53c39e751e..95a2ddc88e 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -230,6 +230,14 @@ static int timestamps_unlock(struct ldb_module *module, const char *lockname) static const char *timestamps_errstring(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); + if (data->error_string) { + char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + return ldb_next_errstring(module); } @@ -256,14 +264,22 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o #endif { struct ldb_module *ctx; + struct private_data *data; ctx = talloc_p(ldb, struct ldb_module); if (!ctx) return NULL; + data = talloc_p(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; - ctx->private_data = NULL; ctx->ops = ×tamps_ops; return ctx; -- cgit From 8164d2442868a2e8353ee2ae3d61f78aa9ccb226 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 08:59:00 +0000 Subject: r4503: add an error reporting function (fixes) (This used to be commit d11732f4f7f9bc535222aa7a6dd2f15cf5002a4d) --- source4/lib/ldb/modules/timestamps.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 95a2ddc88e..719aed19ba 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,6 +37,10 @@ #include "ldb/include/ldb_private.h" #include +struct private_data { + const char *error_string; +}; + static int timestamps_close(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); @@ -57,9 +61,10 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message return ldb_next_search_free(module, res); } -static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, +static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_val *values; char *name, *timestr; int i; @@ -94,6 +99,7 @@ static int add_time_element(struct ldb_context *ldb, struct ldb_message *msg, /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -131,10 +137,10 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes msg2->elements[i] = msg->elements[i]; } - add_time_element(module->ldb, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); } if (msg2) { @@ -150,6 +156,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes /* modify_record: change modifyTimestamp as well */ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -188,8 +195,8 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ msg2->elements[i] = msg->elements[i]; } - add_time_element(module->ldb, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); - add_time_element(module->ldb, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); } if (msg2) { @@ -229,9 +236,11 @@ static int timestamps_unlock(struct ldb_module *module, const char *lockname) /* return extended error information */ static const char *timestamps_errstring(struct ldb_module *module) { + struct private_data *data = (struct private_data *)module->private_data; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); if (data->error_string) { - char *error; + const char *error; error = data->error_string; data->error_string = NULL; -- cgit From b92afa3838ba14fbe66bb683949a7f3bce946faa Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jan 2005 14:05:47 +0000 Subject: r4505: Add a first very basic schema module To use it you should provide a schema.ldb file where the schema is stored and load the module in the ldb you want to have schema check activated more info soon. currently schema checks are performed only on new object creation not on modifications Simo. (This used to be commit b8bb62f14419efd434a344606fb3f753384761a0) --- source4/lib/ldb/Makefile.ldb | 2 +- source4/lib/ldb/common/ldb_modules.c | 4 +- source4/lib/ldb/config.mk | 9 + source4/lib/ldb/modules/schema.c | 489 +++++++++++++++++++++++++++++++++++ 4 files changed, 501 insertions(+), 3 deletions(-) create mode 100644 source4/lib/ldb/modules/schema.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 75c298241d..29d33007da 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -36,7 +36,7 @@ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ common/ldb_debug.o common/ldb_modules.o -MODULES_OBJ=modules/timestamps.o +MODULES_OBJ=modules/timestamps.o modules/schema.o OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 4f53535bc4..033717a62b 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -130,7 +130,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) DLIST_ADD(ldb->modules, current); continue; } -#if 0 + if (strcmp(modules[i], "schema") == 0) { current = schema_module_init(ldb, options); if (!current) { @@ -140,7 +140,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) DLIST_ADD(ldb->modules, current); continue; } -#endif + #ifdef HAVE_DLOPEN_DISABLED { void *handle; diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 8a7a34f05b..87ec89e5d3 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -7,6 +7,15 @@ INIT_OBJ_FILES = \ # End MODULE libldb_timestamps ################################################ +################################################ +# Start MODULE libldb_schema +[MODULE::libldb_schema] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/modules/schema.o +# End MODULE libldb_schema +################################################ + ################################################ # Start MODULE libldb_ldap [MODULE::libldb_ldap] diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c new file mode 100644 index 0000000000..f083eeb6e5 --- /dev/null +++ b/source4/lib/ldb/modules/schema.c @@ -0,0 +1,489 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb schema module + * + * Description: add schema check functionality + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + +struct attribute_syntax { + const char *name; + const char *syntax_id; +}; + +static struct attribute_syntax attrsyn[] = { + { "Object(DS-DN)", "2.5.5.1"}, + { "String(Object-Identifier)", "2.5.5.2"}, + { "", "2.5.5.3"}, + { "String(Teletex)", "2.5.5.4"}, + { "String(IA5)", "2.5.5.5"}, /* Also String(Printable) */ + { "String(Numeric)", "2.5.5.6"}, + { "Object(DN-Binary)", "2.5.5.7"}, /* Also Object(OR-Name) */ + { "Boolean", "2.5.5.8"}, + { "Integer", "2.5.5.9"}, /* Also Enumeration (3 types ?) ... */ + { "String(Octet)", "2.5.5.10"}, /* Also Object(Replica-Link) */ + { "String(UTC-Time)", "2.5.5.11"}, /* Also String(Generalized-Time) */ + { "String(Unicode)", "2.5.5.12"}, + { "Object(Presentation-Address)", "2.5.5.13"}, + { "Object(DN-String)", "2.5.5.14"}, /* Also Object(Access-Point) */ + { "String(NT-Sec-Desc))", "2.5.5.15"}, + { "LargeInteger", "2.5.5.16"}, /* Also Interval ... */ + { "String(Sid)", "2.5.5.17"} + }; + +#define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); + +struct private_data { + struct ldb_context *schema_db; + const char *error_string; +}; + +/* close */ +static int schema_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int schema_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int schema_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + +struct check_list { + int check; + char *name; +}; + +struct attr_list { + int syntax; + char *name; +}; + +struct objc_list { + int aux; + char *name; +}; + +struct schema_structures { + struct check_list *cl; + struct objc_list *ol; + struct attr_list *must; + struct attr_list *may; + int num_cl; + int num_objc; + int num_must; + int num_may; +}; + +/* add_record */ +static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + struct schema_structures *ss; + int i, j, k, l; + int ret; + + /* First implementation: + Build up a list of must and mays from each objectclass + Check all the musts are there and all the other attributes are mays + Throw an error in case a check fail + Free all structures and commit the change + */ + + ss = talloc_p(module, struct schema_structures); + if (!ss) { + return -1; + } + + ss->ol = NULL; + ss->num_cl = msg->num_elements; + ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); + SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); + for (i = 0, j = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + ss->num_objc = msg->elements[i].num_values; + ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0; k < ss->num_objc; k++) { + ss->ol[k].name = talloc_strndup(ss->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); + ss->ol[k].aux = 0; + } + } + + ss->cl[j].check = 0; + ss->cl[j].name = talloc_strdup(ss->cl, msg->elements[i].name); + SCHEMA_TALLOC_CHECK(ss, ss->cl[j].name, -1); + j++; + } + + /* find all other objectclasses recursively */ + ss->must = NULL; + ss->may = NULL; + ss->num_must = 0; + ss->num_may = 0; + for (i = 0; i < ss->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ss->ol[i].aux) { + int d; + ok = 1; + ss->num_objc -= 1; + for (d = i; d < ss->num_objc; d++) { + ss->ol[d] = ss->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_objc; c++) { + len = strlen(ss->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); + ss->ol[l + ss->num_objc].aux = is_aux; + l++; + } + } + ss->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ss->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_must; c++) { + len = strlen(ss->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); + l++; + } + } + ss->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ss->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_may; c++) { + len = strlen(ss->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); + l++; + } + } + ss->num_may += l; + } + } + } + + ldb_search_free(module->ldb, srch); + } + + /* now check all musts are present */ + for (i = 0; i < ss->num_must; i++) { + int found; + + found = 0; + for (j = 0; j < ss->num_cl; j++) { + if (strcasecmp(ss->must[i].name, ss->cl[j].name) == 0) { + ss->cl[j].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + /* TODO: set the error string */ + data->error_string = "Objectclass violation, a required attribute is missing"; + talloc_free(ss); + return -1; + } + } + + /* now check all others atribs are found in mays */ + for (i = 0; i < ss->num_cl; i++) { + + if ( ! ss->cl[i].check ) { + int found; + + found = 0; + for (j = 0; j < ss->num_may; j++) { + if (strcasecmp(ss->may[j].name, ss->cl[i].name) == 0) { + ss->cl[i].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + data->error_string = "Objectclass violation, an invalid attribute name was found"; + talloc_free(ss); + return -1; + } + } + } + + talloc_free(ss); + + return ldb_next_add_record(module, msg); +} + +/* modify_record */ +static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + return ldb_next_modify_record(module, msg); +} + +/* delete_record */ +static int schema_delete_record(struct ldb_module *module, const char *dn) +{ + struct private_data *data = (struct private_data *)module->private_data; + return ldb_next_delete_record(module, dn); +} + +/* rename_record */ +static int schema_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + return ldb_next_rename_record(module, olddn, newdn); +} + +static int schema_named_lock(struct ldb_module *module, const char *name) { + return ldb_next_named_lock(module, name); +} + +static int schema_named_unlock(struct ldb_module *module, const char *name) { + return ldb_next_named_unlock(module, name); +} + +/* return extended error information */ +static const char *schema_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static const struct ldb_module_ops schema_ops = { + "schema", + schema_close, + schema_search, + schema_search_free, + schema_add_record, + schema_modify_record, + schema_delete_record, + schema_rename_record, + schema_named_lock, + schema_named_unlock, + schema_errstring, +}; + +#define SCHEMA_PREFIX "schema:" +#define SCHEMA_PREFIX_LEN 7 + +#ifdef HAVE_DLOPEN_DISABLED +struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + char *db_url = NULL; + int i; + + ctx = talloc_p(ldb, struct ldb_module); + if (!ctx) { + return NULL; + } + + if (options) { + for (i = 0; options[i] != NULL; i++) { + if (strncmp(options[i], SCHEMA_PREFIX, SCHEMA_PREFIX_LEN) == 0) { + db_url = talloc_strdup(ctx, &options[i][SCHEMA_PREFIX_LEN]); + SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); + } + } + } + + if (!db_url) { /* search if it is defined in the calling ldb */ + int ret; + const char * attrs[] = { "@SCHEMADB", NULL }; + struct ldb_message **msgs; + + ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msgs); + if (ret == 0) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "Schema DB not found\n"); + ldb_search_free(ldb, msgs); + return NULL; + } else { + if (ret < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for schema db, bailing out!\n", ldb_errstring(ldb)); + ldb_search_free(ldb, msgs); + return NULL; + } + if (ret > 1) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); + ldb_search_free(ldb, msgs); + return NULL; + } + + db_url = talloc_strndup(ctx, msgs[0]->elements[0].values[0].data, msgs[0]->elements[0].values[0].length); + SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); + } + + ldb_search_free(ldb, msgs); + } + + data = talloc_p(ctx, struct private_data); + SCHEMA_TALLOC_CHECK(ctx, data, NULL); + + data->schema_db = ldb_connect(db_url, 0, NULL); + SCHEMA_TALLOC_CHECK(ctx, data->schema_db, NULL); + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &schema_ops; + + return ctx; +} -- cgit From bb71b37f702bc034a208060b599b384d47fb4fb9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 3 Jan 2005 14:38:05 +0000 Subject: r4506: fix compiler warnings metze (This used to be commit 1c6accd7cbf9ccb7f642b85200671b9d4fe23f47) --- source4/lib/ldb/modules/timestamps.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 719aed19ba..09679435f5 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -64,7 +64,6 @@ static int timestamps_search_free(struct ldb_module *module, struct ldb_message static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_val *values; char *name, *timestr; int i; @@ -99,7 +98,6 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int timestamps_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; @@ -156,7 +154,6 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes /* modify_record: change modifyTimestamp as well */ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message *msg2 = NULL; struct tm *tm; char *timestr; -- cgit From 8d8c21f8d0669b469b2540c3f9e91ca5d076db09 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 4 Jan 2005 15:18:50 +0000 Subject: r4513: add experimental modification attribute checking still not complete but works with add and replace, not tested with delete lot of duplicated code to remove (This used to be commit ea051f6cd39d0e729bb425eb08034a0eee0996dc) --- source4/lib/ldb/modules/schema.c | 452 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 451 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index f083eeb6e5..1f9017976e 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -136,6 +136,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } ss->ol = NULL; + ss->num_objc = 0; ss->num_cl = msg->num_elements; ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); @@ -306,7 +307,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } } - ldb_search_free(module->ldb, srch); + ldb_search_free(data->schema_db, srch); } /* now check all musts are present */ @@ -362,6 +363,455 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + struct schema_structures *ss, *ms; + int i, j, k, l; + int ret; + + /* First implementation: + Retrieve the ldap entry and get the objectclasses, + add msg contained objectclasses if any. + Build up a list of must and mays from each objectclass + Check all musts for the defined objectclass and it's specific + inheritance are there. + Check all other the attributes are mays or musts. + Throw an error in case a check fail. + Free all structures and commit the change. + */ + + ss = talloc_p(module, struct schema_structures); + if (!ss) { + return -1; + } + + ms = talloc_p(module, struct schema_structures); + SCHEMA_TALLOC_CHECK(ss, ms, -1); + + ms->ol = NULL; + ms->num_objc = 0; + ms->num_cl = msg->num_elements; + ms->cl = talloc_array_p(ms, struct check_list, ms->num_cl); + SCHEMA_TALLOC_CHECK(ss, ms->cl, -1); + for (i = 0, j = 0; i < msg->num_elements; i++) { + if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + ms->num_objc = msg->elements[i].num_values; + ms->ol = talloc_array_p(ms, struct objc_list, ms->num_objc); + SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); + for (k = 0; k < ms->num_objc; k++) { + ms->ol[k].name = talloc_strndup(ms->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->ol[k].name, -1); + ms->ol[k].aux = 0; + } + } + + ms->cl[j].check = 0; + ms->cl[j].name = talloc_strdup(ms->cl, msg->elements[i].name); + SCHEMA_TALLOC_CHECK(ss, ms->cl[j].name, -1); + j++; + } + + /* find all modify objectclasses recursively if any objectclass is being added */ + ms->must = NULL; + ms->may = NULL; + ms->num_must = 0; + ms->num_may = 0; + for (i = 0; i < ms->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ms->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ms->ol[i].aux) { + int d; + ok = 1; + ms->num_objc -= 1; + for (d = i; d < ms->num_objc; d++) { + ms->ol[d] = ms->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ms->ol = talloc_realloc_p(ms, ms->ol, struct objc_list, ms->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_objc; c++) { + len = strlen(ms->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->ol[l + ms->num_objc].name = talloc_strndup(ms->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->ol[l + ms->num_objc].name, -1); + ms->ol[l + ms->num_objc].aux = is_aux; + l++; + } + } + ms->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ms->must = talloc_realloc_p(ms, ms->must, struct attr_list, ms->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ms->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_must; c++) { + len = strlen(ms->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ms->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->must[l + ms->num_must].name = talloc_strndup(ms->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->must[l + ms->num_must].name, -1); + l++; + } + } + ms->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ms->may = talloc_realloc_p(ms, ms->may, struct attr_list, ms->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ms->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ms->num_may; c++) { + len = strlen(ms->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ms->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ms->may[l + ms->num_may].name = talloc_strndup(ms->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ms->may[l + ms->num_may].name, -1); + l++; + } + } + ms->num_may += l; + } + } + } + + ldb_search_free(data->schema_db, srch); + } + + /* now search for the original object objectclasses */ + + ss->ol = NULL; + ss->num_objc = 0; + + /* find all other objectclasses recursively */ + { + char *filter = talloc_asprintf(ss, "dn=%s", msg->dn); + const char *attrs[] = {"objectClass", NULL}; + + ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); + if (ret == 1) { + for (i = 0; i < msg->num_elements; i++) { + ss->num_objc = (*srch)->elements[i].num_values; + ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0; k < ss->num_objc; k++) { + ss->ol[k].name = talloc_strndup(ss->ol, (*srch)->elements[i].values[k].data, (*srch)->elements[i].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); + ss->ol[k].aux = 0; + } + } + ldb_search_free(module->ldb, srch); + } else { + ldb_search_free(module->ldb, srch); + return -1; + } + } + + ss->must = NULL; + ss->may = NULL; + ss->num_must = 0; + ss->num_may = 0; + for (i = 0; i < ss->num_objc; i++) { + char *filter; + + filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); + SCHEMA_TALLOC_CHECK(ss, filter, -1); + ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret == 0) { + int ok; + + ok = 0; + /* suppose auxiliary classess are not required */ + if (ss->ol[i].aux) { + int d; + ok = 1; + ss->num_objc -= 1; + for (d = i; d < ss->num_objc; d++) { + ss->ol[d] = ss->ol[d + 1]; + } + i -= 1; + } + if (!ok) { + /* Schema Violation: Object Class Description Not Found */ + data->error_string = "ObjectClass not found"; + talloc_free(ss); + return -1; + } + continue; + } else { + if (ret < 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + data->error_string = "Internal error. Error retrieving schema objectclass"; + talloc_free(ss); + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + data->error_string = "Internal error. Too many records searching for schema objectclass"; + talloc_free(ss); + return -1; + } + } + + /* Add inherited classes eliminating duplicates */ + /* fill in kust and may attribute lists */ + for (j = 0; j < (*srch)->num_elements; j++) { + int o, is_aux, is_class; + + is_aux = 0; + is_class = 0; + if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = 1; + is_class = 1; + } + if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + is_class = 1; + } + + if (is_class) { + o = (*srch)->elements[j].num_values; + ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); + SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); + for (k = 0, l = 0; k < o; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_objc; c++) { + len = strlen(ss->ol[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); + ss->ol[l + ss->num_objc].aux = is_aux; + l++; + } + } + ss->num_objc += l; + } else { + + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); + SCHEMA_TALLOC_CHECK(ss, ss->must, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_must; c++) { + len = strlen(ss->must[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); + l++; + } + } + ss->num_must += l; + } + + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + int m; + + m = (*srch)->elements[j].num_values; + + ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); + SCHEMA_TALLOC_CHECK(ss, ss->may, -1); + for (k = 0, l = 0; k < m; k++) { + int c, found, len; + + found = 0; + for (c = 0; c < ss->num_may; c++) { + len = strlen(ss->may[c].name); + if (len == (*srch)->elements[j].values[k].length) { + if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { + found = 1; + break; + } + } + } + if (!found) { + ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); + SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); + l++; + } + } + ss->num_may += l; + } + } + } + + ldb_search_free(data->schema_db, srch); + } + + /* now check all entries are present either as musts or mays of curent objectclasses */ + /* do not return errors there may be attirbutes defined in new objectclasses */ + /* just mark them as being proved valid attribs */ + for (i = 0; i < ms->num_cl; i++) { + int found; + + found = 0; + for (j = 0; j < ss->num_may; j++) { + if (strcasecmp(ss->may[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + found = 1; + break; + } + } + if ( ! found) { + for (j = 0; j < ss->num_must; j++) { + if (strcasecmp(ss->must[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + break; + } + } + } + } + + /* now check all new objectclasses musts are present */ + for (i = 0; i < ms->num_must; i++) { + int found; + + found = 0; + for (j = 0; j < ms->num_cl; j++) { + if (strcasecmp(ms->must[i].name, ms->cl[j].name) == 0) { + ms->cl[j].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + /* TODO: set the error string */ + data->error_string = "Objectclass violation, a required attribute is missing"; + talloc_free(ss); + return -1; + } + } + + /* now check all others atribs are found in mays */ + for (i = 0; i < ms->num_cl; i++) { + + if ( ! ms->cl[i].check ) { + int found; + + found = 0; + for (j = 0; j < ms->num_may; j++) { + if (strcasecmp(ms->may[j].name, ms->cl[i].name) == 0) { + ms->cl[i].check = 1; + found = 1; + break; + } + } + + if ( ! found ) { + data->error_string = "Objectclass violation, an invalid attribute name was found"; + talloc_free(ss); + return -1; + } + } + } + + talloc_free(ss); + return ldb_next_modify_record(module, msg); } -- cgit From cc55aef7c116d03ba2817625b0ba9edb378525e3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Jan 2005 02:32:43 +0000 Subject: r4547: - added talloc_new(ctx) macro that is a neater form of the common talloc(ctx, 0) call. - cleaned up some talloc usage in various files I'd like to get to the point that we have no calls to talloc(), at which point we will rename talloc_p() to talloc(), to encourage everyone to use the typesafe functions. (This used to be commit e6c81d7c9f8a6938947d3c1c8a971a0d6d50b67a) --- source4/lib/events.c | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/talloc/talloc.h | 1 + source4/lib/talloc/talloc_guide.txt | 9 +++++++++ source4/lib/talloc/testsuite.c | 4 ++-- 5 files changed, 14 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 0ca6b66598..9f28100a26 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -85,7 +85,7 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) /* start off with no events */ ZERO_STRUCTP(ev); - ev->events = talloc(ev, 0); + ev->events = talloc_new(ev); return ev; } diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index fee02da32f..bab3c86e16 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -86,7 +86,7 @@ static int lldb_rename(struct ldb_module *module, const char *olddn, const char int ret = 0; char *newrdn, *p; const char *parentdn = ""; - TALLOC_CTX *mem_ctx = talloc(lldb, 0); + TALLOC_CTX *mem_ctx = talloc_new(lldb); /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 9e828f2f0d..ee3e0be8eb 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -37,6 +37,7 @@ typedef void TALLOC_CTX; #define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) #define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) #define talloc_p(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) #define talloc_zero_p(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) #define talloc_zero_array_p(ctx, type, count) (type *)talloc_zero_array(ctx, sizeof(type), count, __location__) #define talloc_array_p(ctx, type, count) (type *)talloc_array(ctx, sizeof(type), count, __location__) diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index ce3c8bde68..aa37c60466 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -260,6 +260,15 @@ level context. It is equivalent to: talloc_named(NULL, 0, fmt, ...); +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_new(void *ctx); + +This is a utility macro that creates a new memory context hanging +off an exiting context, automatically naming it "talloc_new: __location__" +where __location__ is the source line it is called from. It is +particularly useful for creating a new temporary working context. + + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_realloc(const void *context, void *ptr, size_t size); diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 22444b1116..a3a448ef40 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -333,7 +333,7 @@ static BOOL test_misc(void) printf("TESTING MISCELLANEOUS\n"); - root = talloc(NULL, 0); + root = talloc_new(NULL); p1 = talloc(root, 0x7fffffff); if (p1) { @@ -515,7 +515,7 @@ static BOOL test_realloc(void) printf("TESTING REALLOC\n"); - root = talloc(NULL, 0); + root = talloc_new(NULL); p1 = talloc(root, 10); CHECK_SIZE(p1, 10); -- cgit From ddc10d4d37984246a6547e34a32d629c689c40d1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Jan 2005 03:06:58 +0000 Subject: r4549: got rid of a lot more uses of plain talloc(), instead using talloc_size() or talloc_array_p() where appropriate. also fixed a memory leak in pvfs_copy_file() (failed to free a memory context) (This used to be commit 89b74b53546e1570b11b3702f40bee58aed8c503) --- source4/lib/data_blob.c | 2 +- source4/lib/genrand.c | 2 +- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/registry/reg_backend_nt4.c | 2 +- source4/lib/talloc/talloc.h | 1 + source4/lib/talloc/testsuite.c | 18 +++++++++--------- source4/lib/util_str.c | 8 ++++---- 7 files changed, 18 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 18ecc2793a..deb8f55fce 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -37,7 +37,7 @@ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) if (p) { ret.data = talloc_memdup(NULL, p, length); } else { - ret.data = talloc(NULL, length); + ret.data = talloc_size(NULL, length); } if (ret.data == NULL) { ret.length = 0; diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index b4651dffe8..e11f37e0e9 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -268,7 +268,7 @@ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list size_t i; size_t list_len = strlen(list); - char *retstr = talloc(mem_ctx, len + 1); + char *retstr = talloc_array_p(mem_ctx, char, len + 1); if (!retstr) return NULL; generate_random_buffer((uint8_t *)retstr, len); diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 3a17369144..67c62fe5c8 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -63,7 +63,7 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) return ret; case REG_BINARY: - ret = talloc(mem_ctx, v->data_len * 3 + 2); + ret = talloc_array(mem_ctx, 3, v->data_len+1, "REG_BINARY"); asciip = ret; for (i=0; idata_len; i++) { int str_rem = v->data_len * 3 - (asciip - ret); diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 6c48b9bd1b..cd3be85a23 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -917,7 +917,7 @@ static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR if (dat_len&0x7FFFFFFF) { - char *dtmp = (char *)talloc(mem_ctx, dat_len&0x7FFFFFFF); + char *dtmp = talloc_size(mem_ctx, dat_len&0x7FFFFFFF); if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ char *dat_ptr = LOCN(regf->base, dat_off); diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index ee3e0be8eb..99a6b7a770 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -34,6 +34,7 @@ typedef void TALLOC_CTX; /* useful macros for creating type checked pointers */ #define talloc(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) #define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) #define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) #define talloc_p(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index a3a448ef40..ced3217105 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -335,7 +335,7 @@ static BOOL test_misc(void) root = talloc_new(NULL); - p1 = talloc(root, 0x7fffffff); + p1 = talloc_size(root, 0x7fffffff); if (p1) { printf("failed: large talloc allowed\n"); return False; @@ -517,7 +517,7 @@ static BOOL test_realloc(void) root = talloc_new(NULL); - p1 = talloc(root, 10); + p1 = talloc_size(root, 10); CHECK_SIZE(p1, 10); p1 = talloc_realloc(NULL, p1, 20); @@ -581,7 +581,7 @@ static BOOL test_realloc_child(void) printf("TESTING REALLOC WITH CHILD\n"); - root = talloc(NULL, 0); + root = talloc_new(NULL); el1 = talloc_p(root, struct el1); el1->list = talloc_p(el1, struct el2 *); @@ -607,7 +607,7 @@ static BOOL test_steal(void) printf("TESTING STEAL\n"); - root = talloc(NULL, 0); + root = talloc_new(NULL); p1 = talloc_array_p(root, char, 10); CHECK_SIZE(p1, 10); @@ -645,7 +645,7 @@ static BOOL test_steal(void) talloc_free(root); - p1 = talloc(NULL, 3); + p1 = talloc_new(NULL); CHECK_SIZE(NULL, 3); talloc_free(p1); @@ -661,7 +661,7 @@ static BOOL test_ldb(void) printf("TESTING LDB\n"); - root = talloc(NULL, 0); + root = talloc_new(NULL); p1 = talloc_realloc_fn(root, NULL, 10); CHECK_BLOCKS(root, 2); @@ -709,7 +709,7 @@ static BOOL test_unref_reparent(void) */ static BOOL test_speed(void) { - void *ctx = talloc(NULL, 0); + void *ctx = talloc_new(NULL); unsigned count; struct timeval tv; @@ -719,9 +719,9 @@ static BOOL test_speed(void) count = 0; do { void *p1, *p2, *p3; - p1 = talloc(ctx, count); + p1 = talloc_size(ctx, count); p2 = talloc_strdup(p1, "foo bar"); - p3 = talloc(p1, 300); + p3 = talloc_size(p1, 300); talloc_free(p1); count += 3; } while (timeval_elapsed(&tv) < 5.0); diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 82481cca26..b3ec27de74 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -669,7 +669,7 @@ char *strlower_talloc(TALLOC_CTX *ctx, const char *src) /* this takes advantage of the fact that upper/lower can't change the length of a character by more than 1 byte */ - dest = talloc(ctx, 2*(strlen(src))+1); + dest = talloc_size(ctx, 2*(strlen(src))+1); if (dest == NULL) { return NULL; } @@ -704,7 +704,7 @@ char *strupper_talloc(TALLOC_CTX *ctx, const char *src) /* this takes advantage of the fact that upper/lower can't change the length of a character by more than 1 byte */ - dest = talloc(ctx, 2*(strlen(src))+1); + dest = talloc_size(ctx, 2*(strlen(src))+1); if (dest == NULL) { return NULL; } @@ -1030,7 +1030,7 @@ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s) if (!s || !*s) { return talloc_strdup(mem_ctx, ""); } - ret = talloc(mem_ctx, strlen(s)+2); + ret = talloc_size(mem_ctx, strlen(s)+2); if (!ret) { return ret; } @@ -1133,7 +1133,7 @@ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) }; char *ret; - ret = talloc(mem_ctx, ARRAY_SIZE(attr_strs)+1); + ret = talloc_size(mem_ctx, ARRAY_SIZE(attr_strs)+1); if (!ret) { return NULL; } -- cgit From e159e42d8472f36f51e400e351fc43f2a7dc44f5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Jan 2005 03:20:56 +0000 Subject: r4550: talloc() is now typesafe. It is exactly equivalent to the old talloc_p() macro. Use talloc_size() if you want the old behaviour. I have kept talloc_p() as an alias for now. Once we change all calls to be plain talloc() then we can remove it. (This used to be commit 2011bbeb841fd6bfccf3d44a49f79203f7f55baa) --- source4/lib/talloc/talloc.c | 4 ++-- source4/lib/talloc/talloc.h | 4 ++-- source4/lib/talloc/talloc_guide.txt | 40 ++++++++++++++++++------------------- source4/lib/talloc/testsuite.c | 4 ++-- 4 files changed, 26 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 9e8868191f..bcadf40cfb 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -857,7 +857,7 @@ char *talloc_strndup(const void *t, const char *p, size_t n) for (len=0; p[len] && len talloc(context, size); + talloc_realloc(context, NULL, size) ==> talloc_size(context, size); talloc_realloc(context, ptr, 0) ==> talloc_free(ptr); The "context" argument is only used if "ptr" is not NULL, otherwise it @@ -407,7 +407,7 @@ void *talloc_zero(const void *ctx, size_t size); The talloc_zero() function is equivalent to: - ptr = talloc(ctx, size); + ptr = talloc_size(ctx, size); if (ptr) memset(ptr, 0, size); @@ -416,7 +416,7 @@ void *talloc_memdup(const void *ctx, const void *p, size_t size); The talloc_memdup() function is equivalent to: - ptr = talloc(ctx, size); + ptr = talloc_size(ctx, size); if (ptr) memcpy(ptr, p, size); @@ -425,7 +425,7 @@ char *talloc_strdup(const void *ctx, const char *p); The talloc_strdup() function is equivalent to: - ptr = talloc(ctx, strlen(p)+1); + ptr = talloc_size(ctx, strlen(p)+1); if (ptr) memcpy(ptr, p, strlen(p)+1); This functions sets the name of the new pointer to the passed @@ -473,7 +473,7 @@ void *talloc_array_p(const void *ctx, type, uint_t count); The talloc_array_p() macro is equivalent to: - (type *)talloc(ctx, sizeof(type) * count); + (type *)talloc_size(ctx, sizeof(type) * count); except that it provides integer overflow protection for the multiply, returning NULL if the multiply overflows. diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index ced3217105..d46964d9b6 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -523,11 +523,11 @@ static BOOL test_realloc(void) p1 = talloc_realloc(NULL, p1, 20); CHECK_SIZE(p1, 20); - talloc(p1, 0); + talloc_new(p1); p2 = talloc_realloc(p1, NULL, 30); - talloc(p1, 0); + talloc_new(p1); p2 = talloc_realloc(p1, p2, 40); -- cgit From 11ce2cfd70df264c5c91b4daaa9a01c5abc673b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Jan 2005 04:39:16 +0000 Subject: r4591: - converted the other _p talloc functions to not need _p - added #if TALLOC_DEPRECATED around the _p functions - fixes the code that broke from the above while doing this I fixed quite a number of places that were incorrectly using the non type-safe talloc functions to use the type safe ones. Some were even doing multiplies for array allocation, which is potentially unsafe. (This used to be commit 6e7754abd0c225527fb38363996a6e241b87b37e) --- source4/lib/charcnv.c | 2 +- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/talloc/talloc.c | 14 ++++------ source4/lib/talloc/talloc.h | 37 ++++++++++++++++++------- source4/lib/talloc/talloc_guide.txt | 49 +++++++++++++++++++--------------- source4/lib/talloc/testsuite.c | 20 +++++++------- 6 files changed, 72 insertions(+), 52 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 7e9750e948..d5727feb2c 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -229,7 +229,7 @@ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, outbuf = NULL; convert: destlen = 2 + (destlen*3); - ob = (char *)talloc_realloc(ctx, outbuf, destlen); + ob = talloc_realloc(ctx, outbuf, char, destlen); if (!ob) { DEBUG(0, ("convert_string_talloc: realloc failed!\n")); talloc_free(outbuf); diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 67c62fe5c8..ef46dd6174 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -63,7 +63,7 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) return ret; case REG_BINARY: - ret = talloc_array(mem_ctx, 3, v->data_len+1, "REG_BINARY"); + ret = talloc_array_size(mem_ctx, 3, v->data_len+1); asciip = ret; for (i=0; idata_len; i++) { int str_rem = v->data_len * 3 - (asciip - ret); diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index bcadf40cfb..6d11cb00e9 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -932,7 +932,7 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) } len = vsnprintf(NULL, 0, fmt, ap2); - s = talloc_realloc(NULL, s, s_len + len+1); + s = talloc_realloc(NULL, s, char, s_len + len+1); if (!s) return NULL; VA_COPY(ap2, ap); @@ -961,7 +961,7 @@ char *talloc_asprintf_append(char *s, const char *fmt, ...) /* alloc an array, checking for integer overflow in the array size */ -void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) { if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; @@ -972,7 +972,7 @@ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char * /* alloc an zero array, checking for integer overflow in the array size */ -void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) { if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; @@ -984,16 +984,12 @@ void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const c /* realloc an array, checking for integer overflow in the array size */ -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) { if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - ptr = talloc_realloc(ctx, ptr, el_size * count); - if (ptr) { - talloc_set_name_const(ptr, name); - } - return ptr; + return _talloc_realloc(ctx, ptr, el_size * count, name); } /* diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 747b1c6ba6..8169782441 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -32,17 +32,26 @@ typedef void TALLOC_CTX; #define __LINESTR__ _STRING_LINE2_(__LINE__) #define __location__ __FILE__ ":" __LINESTR__ +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + /* useful macros for creating type checked pointers */ #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) -#define talloc_p(ctx, type) talloc(ctx, type) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) -#define talloc_zero(ctx, size) _talloc_zero(ctx, size, __location__) -#define talloc_realloc(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + #define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) -#define talloc_zero_p(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define talloc_zero_array_p(ctx, type, count) (type *)talloc_zero_array(ctx, sizeof(type), count, __location__) -#define talloc_array_p(ctx, type, count) (type *)talloc_array(ctx, sizeof(type), count, __location__) -#define talloc_realloc_p(ctx, p, type, count) (type *)talloc_realloc_array(ctx, p, sizeof(type), count, __location__) + +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) + +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, __location__) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, __location__) +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) + +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, __location__) +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + #define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) #define talloc_destroy(ctx) talloc_free(ctx) @@ -54,6 +63,14 @@ typedef void TALLOC_CTX; #define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) #define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#endif + #ifndef PRINTF_ATTRIBUTE #define PRINTF_ATTRIBUTE(a1, a2) #endif @@ -89,9 +106,9 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIB char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index af6bdf0275..30b7f64d67 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -5,7 +5,7 @@ Andrew Tridgell September 2004 The most current version of this document is available at - http://samba.org/ftp/unpacked/samba4/talloc_guide.txt + http://samba.org/ftp/unpacked/samba4/source/lib/talloc/talloc_guide.txt If you are used to talloc from Samba3 then please read this carefully, as talloc has changed a lot. @@ -19,7 +19,7 @@ between a "talloc context" and a "talloc pointer". Any pointer returned from talloc() is itself a valid talloc context. This means you can do this: - struct foo *X = talloc_p(mem_ctx, struct foo); + struct foo *X = talloc(mem_ctx, struct foo); X->name = talloc_strdup(X, "foo"); and the pointer X->name would be a "child" of the talloc context "X" @@ -34,7 +34,7 @@ talloc_free(). If you find this confusing, then I suggest you run the LOCAL-TALLOC smbtorture test to watch talloc in action. You may also like to add -your own tests to source/torture/local/talloc.c to clarify how some +your own tests to source/lib/talloc/testsuite.c to clarify how some particular situation is handled. @@ -270,13 +270,13 @@ particularly useful for creating a new temporary working context. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_realloc(const void *context, void *ptr, size_t size); +(type *)talloc_realloc(const void *context, void *ptr, type, count); -The talloc_realloc() function changes the size of a talloc +The talloc_realloc() macro changes the size of a talloc pointer. It has the following equivalences: - talloc_realloc(context, NULL, size) ==> talloc_size(context, size); - talloc_realloc(context, ptr, 0) ==> talloc_free(ptr); + talloc_realloc(context, NULL, type, 1) ==> talloc(context, type); + talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); The "context" argument is only used if "ptr" is not NULL, otherwise it is ignored. @@ -286,6 +286,13 @@ will fail either due to a lack of memory, or because the pointer has more than one parent (see talloc_reference()). +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_realloc_size(const void *context, void *ptr, size_t size); + +the talloc_realloc_size() function is useful when the type is not +known so the typesafe talloc_realloc() cannot be used. + + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_steal(const void *new_ctx, const void *ptr); @@ -403,12 +410,18 @@ full talloc report on 'root' (total 18 bytes in 8 blocks) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_zero(const void *ctx, size_t size); +(type *)talloc_zero(const void *ctx, type); -The talloc_zero() function is equivalent to: +The talloc_zero() macro is equivalent to: - ptr = talloc_size(ctx, size); - if (ptr) memset(ptr, 0, size); + ptr = talloc(ctx, type); + if (ptr) memset(ptr, 0, sizeof(type)); + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_zero_size(const void *ctx, size_t size) + +The talloc_zero_size() function is useful when you don't have a known type =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -469,25 +482,19 @@ string to the given string. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_array_p(const void *ctx, type, uint_t count); +(type *)talloc_array(const void *ctx, type, uint_t count); -The talloc_array_p() macro is equivalent to: +The talloc_array() macro is equivalent to: (type *)talloc_size(ctx, sizeof(type) * count); except that it provides integer overflow protection for the multiply, returning NULL if the multiply overflows. - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_realloc_p(const void *ctx, void *ptr, type, uint_t count); - -The talloc_realloc_p() macro is equivalent to: +void *talloc_array_size(const void *ctx, size_t size, uint_t count); - (type *)talloc_realloc(ctx, ptr, sizeof(type) * count); - -except that it provides integer overflow protection for the multiply, -returning NULL if the multiply overflows. +The talloc_array_size() function is useful when the type is not known =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index d46964d9b6..e7934a10f3 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -398,7 +398,7 @@ static BOOL test_misc(void) talloc_report(root, stdout); - p2 = talloc_zero(p1, 20); + p2 = talloc_zero_size(p1, 20); if (p2[19] != 0) { printf("Failed to give zero memory\n"); return False; @@ -520,41 +520,41 @@ static BOOL test_realloc(void) p1 = talloc_size(root, 10); CHECK_SIZE(p1, 10); - p1 = talloc_realloc(NULL, p1, 20); + p1 = talloc_realloc_size(NULL, p1, 20); CHECK_SIZE(p1, 20); talloc_new(p1); - p2 = talloc_realloc(p1, NULL, 30); + p2 = talloc_realloc_size(p1, NULL, 30); talloc_new(p1); - p2 = talloc_realloc(p1, p2, 40); + p2 = talloc_realloc_size(p1, p2, 40); CHECK_SIZE(p2, 40); CHECK_SIZE(root, 60); CHECK_BLOCKS(p1, 4); - p1 = talloc_realloc(NULL, p1, 20); + p1 = talloc_realloc_size(NULL, p1, 20); CHECK_SIZE(p1, 60); talloc_increase_ref_count(p2); - if (talloc_realloc(NULL, p2, 5) != NULL) { + if (talloc_realloc_size(NULL, p2, 5) != NULL) { printf("failed: talloc_realloc() on a referenced pointer should fail\n"); return False; } CHECK_BLOCKS(p1, 4); - talloc_realloc(NULL, p2, 0); - talloc_realloc(NULL, p2, 0); + talloc_realloc_size(NULL, p2, 0); + talloc_realloc_size(NULL, p2, 0); CHECK_BLOCKS(p1, 3); - if (talloc_realloc(NULL, p1, 0x7fffffff) != NULL) { + if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) { printf("failed: oversize talloc should fail\n"); return False; } - talloc_realloc(NULL, p1, 0); + talloc_realloc_size(NULL, p1, 0); CHECK_BLOCKS(root, 1); CHECK_SIZE(root, 0); -- cgit From 8b1512fc9bf73ade637c9f04974d8c01797d7bdc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Jan 2005 04:45:11 +0000 Subject: r4592: fixed typo from talloc testsuite fixup for the new syntax (This used to be commit 1177200dd9392c088f5b009f55390ad31c367e5f) --- source4/lib/talloc/testsuite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index e7934a10f3..005474a2cc 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -645,7 +645,7 @@ static BOOL test_steal(void) talloc_free(root); - p1 = talloc_new(NULL); + p1 = talloc_size(NULL, 3); CHECK_SIZE(NULL, 3); talloc_free(p1); -- cgit From 35a2ced64a3c853289d7fa921e91724ce2998b79 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Jan 2005 04:47:58 +0000 Subject: r4593: don't use the _p function in the testsuite, as when built standalone it doesn't use TALLOC_DEPRECATED (This used to be commit 2fe0e2528f14627832942f6404a4b1be4b556c97) --- source4/lib/talloc/testsuite.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 005474a2cc..d93894b520 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -432,13 +432,13 @@ static BOOL test_misc(void) CHECK_BLOCKS(p1, 3); talloc_free(p2); - d = talloc_array_p(p1, double, 0x20000000); + d = talloc_array(p1, double, 0x20000000); if (d) { printf("failed: integer overflow not detected\n"); return False; } - d = talloc_realloc_p(p1, d, double, 0x20000000); + d = talloc_realloc(p1, d, double, 0x20000000); if (d) { printf("failed: integer overflow not detected\n"); return False; @@ -583,14 +583,14 @@ static BOOL test_realloc_child(void) root = talloc_new(NULL); - el1 = talloc_p(root, struct el1); - el1->list = talloc_p(el1, struct el2 *); - el1->list[0] = talloc_p(el1->list, struct el2); + el1 = talloc(root, struct el1); + el1->list = talloc(el1, struct el2 *); + el1->list[0] = talloc(el1->list, struct el2); el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); - el2 = talloc_p(el1->list, struct el2); + el2 = talloc(el1->list, struct el2); - el1->list = talloc_realloc_p(el1, el1->list, struct el2 *, 2); + el1->list = talloc_realloc(el1, el1->list, struct el2 *, 2); el1->list[1] = el2; talloc_free(root); @@ -609,10 +609,10 @@ static BOOL test_steal(void) root = talloc_new(NULL); - p1 = talloc_array_p(root, char, 10); + p1 = talloc_array(root, char, 10); CHECK_SIZE(p1, 10); - p2 = talloc_realloc_p(root, NULL, char, 20); + p2 = talloc_realloc(root, NULL, char, 20); CHECK_SIZE(p1, 10); CHECK_SIZE(root, 30); -- cgit From 1bdbd21eb23d5591f005da13f1868343a4395dbe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 9 Jan 2005 02:37:24 +0000 Subject: r4609: add a usefull data_blob_dup_talloc() macro metze (This used to be commit 11e006df1689d4b4b202bca640106fd789495284) --- source4/lib/talloc/talloc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 8169782441..5ac5888876 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -62,6 +62,7 @@ typedef void TALLOC_CTX; #define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) #define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) +#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) #if TALLOC_DEPRECATED -- cgit From 6836f5d0b167027908da9a08b9b219520997b563 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Jan 2005 08:34:05 +0000 Subject: r4616: the first phase in the addition of proper support for dcerpc_alter_context and multiple context_ids in the dcerpc client library. This stage does the following: - split "struct dcerpc_pipe" into two parts, the main part being "struct dcerpc_connection", which contains all the parts not dependent on the context, and "struct dcerpc_pipe" which has the context dependent part. This is similar to the layering in libcli_*() for SMB - disable the current dcerpc_alter code. I've used a #warning until i get the 2nd phase finished. I don't know how portable #warning is, but it won't be long before I add full alter context support anyway, so it won't last long - cleanup the allocation of dcerpc_pipe structures. The previous code was quite awkward. (This used to be commit 4004c69937be7e5dae56f9567ca607f982d395d3) --- source4/lib/dcom/common/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 09c5fd280c..02e1dea139 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -354,6 +354,8 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) oxid = iface->ox->oxid; iid = iface->interface->iid; +#warning "dcerpc_alter needed" +#if 0 if (iface->ox->pipe) { if (!GUID_equal(&iface->ox->pipe->syntax.uuid, &iid)) { iface->ox->pipe->syntax.uuid = iid; @@ -365,7 +367,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) *p = iface->ox->pipe; return NT_STATUS_OK; } - +#endif i = 0; do { status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]); -- cgit From e74b3ed6f195e66cb5fa0f387cea0f59fb66711b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Jan 2005 11:32:12 +0000 Subject: r4618: - tidied up the alter_context client code a bit - there is no alter_nak or alter_ack packet, its all done in an alter_response - auto-allocated the contex_ids - tried to fix up the dcom code to work again with alter_context. Jelmer, please take a look :) (This used to be commit dd1c54add8884376601f2f8a56c01bfb8add030c) --- source4/lib/dcom/common/main.c | 48 ++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 02e1dea139..b9f6127c6c 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -341,41 +341,54 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const return WERR_OK; } -NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) +NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding binding; struct GUID iid; HYPER_T oxid; NTSTATUS status; int i; + struct dcerpc_pipe *p; + TALLOC_CTX *tmp_ctx; + const char *uuid; + + tmp_ctx = talloc_new(NULL); - *p = NULL; + p = iface->ox->pipe; oxid = iface->ox->oxid; iid = iface->interface->iid; -#warning "dcerpc_alter needed" -#if 0 - if (iface->ox->pipe) { - if (!GUID_equal(&iface->ox->pipe->syntax.uuid, &iid)) { + uuid = GUID_string(tmp_ctx, &iid); + + if (p) { + if (!GUID_equal(&p->syntax.uuid, &iid)) { + struct dcerpc_pipe *p2; iface->ox->pipe->syntax.uuid = iid; - status = dcerpc_alter(iface->ox->pipe, iface->ctx); - if (NT_STATUS_IS_ERR(status)) { - return status; + status = dcerpc_secondary_context(p, &p2, uuid, 0); + if (NT_STATUS_IS_OK(status)) { + p = p2; } + } else { + p = talloc_reference(NULL, p); } - *p = iface->ox->pipe; - return NT_STATUS_OK; + *pp = p; + talloc_free(tmp_ctx); + return status; } -#endif + i = 0; do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]); - if (NT_STATUS_IS_ERR(status)) { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, + iface->ox->bindings.stringbindings[i]); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error parsing string binding")); } else { binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&iface->ox->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + status = dcerpc_pipe_connect_b(&p, &binding, + uuid, 0.0, + iface->ctx->domain, iface->ctx->user, + iface->ctx->password); } i++; @@ -383,12 +396,15 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); + talloc_free(tmp_ctx); return status; } DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); - *p = iface->ox->pipe; + *pp = p; + talloc_free(tmp_ctx); + return NT_STATUS_OK; } -- cgit From 1303f51099c2054c3966c6ba34490c5ffad85c13 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 9 Jan 2005 19:06:49 +0000 Subject: r4623: Convert values from UTF8 to UTF16 in gconf registry backend (caught by Andrew Bartlett) (This used to be commit da3c7712d234291f9c5a3c48daae02bdf0878bf0) --- source4/lib/registry/reg_backend_gconf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c index b53d0fedf5..47d8c760ab 100644 --- a/source4/lib/registry/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf.c @@ -72,6 +72,7 @@ static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, GConfValue *value; struct registry_value *newval; char *fullpath = p->backend_data; + const char *tmp; int i; cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL); @@ -92,8 +93,8 @@ static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, case GCONF_VALUE_STRING: newval->data_type = REG_SZ; - newval->data_blk = talloc_strdup(mem_ctx, gconf_value_get_string(value)); - newval->data_len = strlen(newval->data_blk); + tmp = gconf_value_get_string(value); + newval->data_len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, tmp, strlen(tmp), &(newval->data_blk)); break; case GCONF_VALUE_INT: @@ -149,7 +150,7 @@ static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p return WERR_OK; } -static WERROR gconf_set_value(struct registry_key *key, const char *valname, int type, void *data, int len) +static WERROR gconf_set_value(struct registry_key *key, const char *valname, uint32 type, void *data, int len) { GError *error = NULL; char *valpath; -- cgit From 1b1b678cc8c79dacc3b80de4f8203154d47c0345 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 9 Jan 2005 21:35:37 +0000 Subject: r4624: Several crash fixes for DCOM More work on the example class implementation (This used to be commit 1f8f4dd179d5aa0472c676d115dc2fc1749ce32d) --- source4/lib/dcom/classes/simple.c | 31 ++++++++++++++++++++++++++++--- source4/lib/dcom/common/main.c | 8 +++++++- source4/lib/dcom/common/tables.c | 5 +++++ source4/lib/dcom/config.mk | 1 + 4 files changed, 41 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c index 90dda6bc84..e5b5bf3f41 100644 --- a/source4/lib/dcom/classes/simple.c +++ b/source4/lib/dcom/classes/simple.c @@ -21,7 +21,25 @@ #include "includes.h" #include "lib/dcom/common/dcom.h" -static struct dcom_IClassFactory_vtable simple_classobject; +NTSTATUS simple_QueryInterface (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct QueryInterface *r) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS simple_CreateInstance (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct CreateInstance *r) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +/* Everything below this line should be autogenerated later on */ + +static struct dcom_IClassFactory_vtable simple_classobject = { + { simple_QueryInterface, NULL, NULL }, + simple_CreateInstance, + NULL, + NULL, + NULL +}; NTSTATUS dcom_simple_init(void) { @@ -32,10 +50,17 @@ NTSTATUS dcom_simple_init(void) GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); - simple_class.class_object = dcom_new_local_ifacep(talloc_autofree_context(), - dcom_interface_by_iid(&iid), + simple_class.class_object = dcom_new_local_ifacep( + talloc_autofree_context(), + &iid, &simple_classobject, NULL); + if (!simple_class.class_object) { + DEBUG(1, ("Unable to create class object for simple class\n")); + return NT_STATUS_FOOBAR; + } + GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); + return dcom_register_class(&simple_class); } diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index b9f6127c6c..48b5ec946b 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -549,9 +549,15 @@ HYPER_T dcom_get_current_oxid(void) return getpid(); } -struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct dcom_interface *iface, void *vtable, struct dcom_object *object) +struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct GUID *iid, void *vtable, struct dcom_object *object) { struct dcom_interface_p *ip = talloc_p(ctx, struct dcom_interface_p); + const struct dcom_interface *iface = dcom_interface_by_iid(iid); + + if (!iface) { + DEBUG (1, ("Unable to find interface with IID %s\n", GUID_string(ctx, iid))); + return NULL; + } ip->ctx = ctx; ip->interface = iface; diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index faf67710e0..8a764d0a65 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -77,7 +77,12 @@ NTSTATUS dcom_register_interface(const void *_iface) { const struct dcom_interface *iface = _iface; struct interface_list *l; + TALLOC_CTX *lcl_ctx = talloc_init("dcom_register_interface"); + DEBUG(5, ("Adding DCOM interface %s\n", GUID_string(lcl_ctx, &iface->iid))); + + talloc_destroy(lcl_ctx); + l = talloc_zero_p(interfaces?interfaces:talloc_autofree_context(), struct interface_list); diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index d599231525..ca280884ea 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -10,6 +10,7 @@ REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ [MODULE::DCOM_SIMPLE] SUBSYSTEM = LIBDCOM +REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM INIT_FUNCTION = dcom_simple_init INIT_OBJ_FILES = \ lib/dcom/classes/simple.o -- cgit From f6596e4ae77c0125a1362e483aa1aedb8cf489c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 10 Jan 2005 07:12:13 +0000 Subject: r4626: Jelmer, can you look at why this init is failing? It is preventing all tools from working (This used to be commit e59c5adf39c2c840a40a62485195167f80b9ef53) --- source4/lib/dcom/classes/simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c index e5b5bf3f41..13cf4616b2 100644 --- a/source4/lib/dcom/classes/simple.c +++ b/source4/lib/dcom/classes/simple.c @@ -57,7 +57,7 @@ NTSTATUS dcom_simple_init(void) if (!simple_class.class_object) { DEBUG(1, ("Unable to create class object for simple class\n")); - return NT_STATUS_FOOBAR; + return NT_STATUS_OK; } GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); -- cgit From 7b91c309b8275c407f86139beed588d14ca0bf11 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Jan 2005 22:52:01 +0000 Subject: r4657: This really should be made a structure, so we can't get it wrong, but in the meantime, get the declaration right... Andrew Bartlett (This used to be commit 1c65db94f03457335133210bda488e2e21209f9a) --- source4/lib/genrand.c | 60 ++++++++------------------------------------------- 1 file changed, 9 insertions(+), 51 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index e11f37e0e9..a9ab260385 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -24,7 +24,7 @@ #include "system/iconv.h" #include "lib/crypto/crypto.h" -static unsigned char hash[258]; +static unsigned char s_box[258]; static uint32 counter; static BOOL done_reseed = False; @@ -54,59 +54,15 @@ static void get_rand_reseed_data(int *reseed_data) } } -/**************************************************************** - Setup the seed. -*****************************************************************/ - -static void seed_random_stream(unsigned char *seedval, size_t seedlen) -{ - unsigned char j = 0; - size_t ind; - - for (ind = 0; ind < 256; ind++) - hash[ind] = (unsigned char)ind; - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; - - j += (hash[ind] + seedval[ind%seedlen]); - - tc = hash[ind]; - hash[ind] = hash[j]; - hash[j] = tc; - } - - hash[256] = 0; - hash[257] = 0; -} - /**************************************************************** Get datasize bytes worth of random data. *****************************************************************/ -static void get_random_stream(unsigned char *data, size_t datasize) +static void get_random_stream(uint8_t sbox[258], unsigned char *data, size_t datasize) { - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - size_t ind; - - for( ind = 0; ind < datasize; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = hash[t]; - } - - hash[256] = index_i; - hash[257] = index_j; + memset(data, '\0', datasize); + + arcfour_crypt_sbox(s_box, data, datasize); } /**************************************************************** @@ -147,6 +103,7 @@ static void do_filehash(const char *fname, unsigned char *the_hash) static int do_reseed(BOOL use_fd, int fd) { unsigned char seed_inbuf[40]; + DATA_BLOB seed_blob; uint32 v1, v2; struct timeval tval; pid_t mypid; int reseed_data = 0; @@ -187,7 +144,8 @@ static int do_reseed(BOOL use_fd, int fd) seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } - seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); + seed_blob = data_blob_const(seed_inbuf, sizeof(seed_inbuf)); + arcfour_init(s_box, &seed_blob); return -1; } @@ -231,7 +189,7 @@ void generate_random_buffer(uint8_t *out, int len) while(len > 0) { int copy_len = len > 16 ? 16 : len; - get_random_stream(md4_buf, sizeof(md4_buf)); + get_random_stream(s_box, md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; -- cgit From 4fc38af93b1b977fa2570c3df6897c6bd99f433b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Jan 2005 22:56:51 +0000 Subject: r4659: Revert -r 4657 committed by mistake, until I review and test the changes (which were to use the common ARCFOUR code for random number generation). Andrew Bartlett (This used to be commit 50b3f64a8d555941499f41a7f43819474b81d4b8) --- source4/lib/genrand.c | 60 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index a9ab260385..e11f37e0e9 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -24,7 +24,7 @@ #include "system/iconv.h" #include "lib/crypto/crypto.h" -static unsigned char s_box[258]; +static unsigned char hash[258]; static uint32 counter; static BOOL done_reseed = False; @@ -54,15 +54,59 @@ static void get_rand_reseed_data(int *reseed_data) } } +/**************************************************************** + Setup the seed. +*****************************************************************/ + +static void seed_random_stream(unsigned char *seedval, size_t seedlen) +{ + unsigned char j = 0; + size_t ind; + + for (ind = 0; ind < 256; ind++) + hash[ind] = (unsigned char)ind; + + for( ind = 0; ind < 256; ind++) { + unsigned char tc; + + j += (hash[ind] + seedval[ind%seedlen]); + + tc = hash[ind]; + hash[ind] = hash[j]; + hash[j] = tc; + } + + hash[256] = 0; + hash[257] = 0; +} + /**************************************************************** Get datasize bytes worth of random data. *****************************************************************/ -static void get_random_stream(uint8_t sbox[258], unsigned char *data, size_t datasize) +static void get_random_stream(unsigned char *data, size_t datasize) { - memset(data, '\0', datasize); - - arcfour_crypt_sbox(s_box, data, datasize); + unsigned char index_i = hash[256]; + unsigned char index_j = hash[257]; + size_t ind; + + for( ind = 0; ind < datasize; ind++) { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += hash[index_i]; + + tc = hash[index_i]; + hash[index_i] = hash[index_j]; + hash[index_j] = tc; + + t = hash[index_i] + hash[index_j]; + data[ind] = hash[t]; + } + + hash[256] = index_i; + hash[257] = index_j; } /**************************************************************** @@ -103,7 +147,6 @@ static void do_filehash(const char *fname, unsigned char *the_hash) static int do_reseed(BOOL use_fd, int fd) { unsigned char seed_inbuf[40]; - DATA_BLOB seed_blob; uint32 v1, v2; struct timeval tval; pid_t mypid; int reseed_data = 0; @@ -144,8 +187,7 @@ static int do_reseed(BOOL use_fd, int fd) seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } - seed_blob = data_blob_const(seed_inbuf, sizeof(seed_inbuf)); - arcfour_init(s_box, &seed_blob); + seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); return -1; } @@ -189,7 +231,7 @@ void generate_random_buffer(uint8_t *out, int len) while(len > 0) { int copy_len = len > 16 ? 16 : len; - get_random_stream(s_box, md4_buf, sizeof(md4_buf)); + get_random_stream(md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; -- cgit From a7a5c98e296763c541daac2e6175ead8ede34c64 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Jan 2005 03:07:53 +0000 Subject: r4669: a timeval_to_nttime() function as requested by abartlet. Andrew, its your responsibility to use/test this :-) (This used to be commit 2107b0cd7661a631952742bae241cb165b05c5f2) --- source4/lib/time.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 504b5d6ac3..92eb2dee5e 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -536,3 +536,13 @@ struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2) } return t; } + + +/* + convert a timeval to a NTTIME +*/ +NTTIME timeval_to_nttime(struct timeval *tv) +{ + double t1 = tv->tv_sec + (tv->tv_usec*1.0e-6); + return (t1 + TIME_FIXUP_CONSTANT) * 1.0e7; +} -- cgit From 097d568383606135bafe4f6dbc3b3055a02f86b5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Jan 2005 03:26:26 +0000 Subject: r4670: abartlet was worried about floating point precision with my first version - here is one based purely on 64 bit math (This used to be commit 1ff04b0dc3e680b6288622576bb373359a594c2f) --- source4/lib/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 92eb2dee5e..fd005215a1 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -543,6 +543,6 @@ struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2) */ NTTIME timeval_to_nttime(struct timeval *tv) { - double t1 = tv->tv_sec + (tv->tv_usec*1.0e-6); - return (t1 + TIME_FIXUP_CONSTANT) * 1.0e7; + return 10*(tv->tv_usec + + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); } -- cgit From cec158231b5618a9a93e478b6b60914305508086 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 11 Jan 2005 13:52:29 +0000 Subject: r4678: Add some const to LDB. Andrew Bartlett (This used to be commit d4da9fb1600dba5daca9acb83f528c8f5f42f0ce) --- source4/lib/ldb/common/ldb_msg.c | 2 +- source4/lib/ldb/include/ldb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 89f8feb3c0..416590f462 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -171,7 +171,7 @@ int ldb_msg_add(struct ldb_context *ldb, int ldb_msg_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, - struct ldb_val *val) + const struct ldb_val *val) { struct ldb_message_element *el; struct ldb_val *vals; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 7aa2b6f4cd..0bb8105c44 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -256,7 +256,7 @@ int ldb_msg_add(struct ldb_context *ldb, int ldb_msg_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, - struct ldb_val *val); + const struct ldb_val *val); int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, char *str); -- cgit From a249198d539685be5cb97e179e85ae00dbba8c83 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 11 Jan 2005 14:04:58 +0000 Subject: r4682: A LDB-based secrets implementation in Samba4. This uses LDB (a local secrets.ldb and the global samdb) to fill out the secrets from an LSA perspective. Some small changes to come, but the bulk of the work is now done. A re-provision is required after this change. Andrew Bartlett (This used to be commit ded33033521a6a1c7ea80758c5c5aeeebb182a51) --- source4/lib/util.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index ac5124840e..9341a011af 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -712,6 +712,21 @@ char *lib_path(TALLOC_CTX* mem_ctx, const char *name) return fname; } +/** + * @brief Returns an absolute path to a file in the Samba private directory. + * + * @param name File to find, relative to PRIVATEDIR. + * + * @retval Pointer to a talloc'ed string containing the full path. + **/ + +char *private_path(TALLOC_CTX* mem_ctx, const char *name) +{ + char *fname; + fname = talloc_asprintf(mem_ctx, "%s/%s", lp_private_dir(), name); + return fname; +} + /* return a path in the smbd.tmp directory, where all temporary file for smbd go. If NULL is passed for name then return the directory -- cgit From ffb8c82424a9d58a3dee1c42b7a64ab15711345b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Jan 2005 15:19:32 +0000 Subject: r4686: cerate a function to create a socket by specifying an socket_ops struct metze (This used to be commit 894f402b01c8d4e0bef9c29697b8d13e5b9ea150) --- source4/lib/socket/socket.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index c2865cd9f0..9be6faf084 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -32,27 +32,23 @@ static int socket_destructor(void *ptr) return 0; } -NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags) +NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops, struct socket_context **new_sock, uint32_t flags) { NTSTATUS status; - (*new_sock) = talloc_p(NULL, struct socket_context); + (*new_sock) = talloc(mem_ctx, struct socket_context); if (!(*new_sock)) { return NT_STATUS_NO_MEMORY; } - (*new_sock)->type = type; + (*new_sock)->type = ops->type; (*new_sock)->state = SOCKET_STATE_UNDEFINED; (*new_sock)->flags = flags; (*new_sock)->fd = -1; (*new_sock)->private_data = NULL; - (*new_sock)->ops = socket_getops_byname(name, type); - if (!(*new_sock)->ops) { - talloc_free(*new_sock); - return NT_STATUS_INVALID_PARAMETER; - } + (*new_sock)->ops = ops; status = (*new_sock)->ops->fn_init((*new_sock)); if (!NT_STATUS_IS_OK(status)) { @@ -73,6 +69,18 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co return NT_STATUS_OK; } +NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags) +{ + const struct socket_ops *ops; + + ops = socket_getops_byname(name, type); + if (!ops) { + return NT_STATUS_INVALID_PARAMETER; + } + + return socket_create_with_ops(NULL, ops, new_sock, flags); +} + void socket_destroy(struct socket_context *sock) { /* the close is handled by the destructor */ -- cgit From 0c440d6506db46fdc7a26f5ef2790b6f4644f6e5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Jan 2005 15:20:55 +0000 Subject: r4687: use struct type and location for easier finding metze (This used to be commit a88aac7a397972c52ca2fb192b58f2a172630a6e) --- source4/lib/talloc/talloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 5ac5888876..cf03ce5952 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -37,7 +37,7 @@ typedef void TALLOC_CTX; #endif /* useful macros for creating type checked pointers */ -#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type ": " __location__) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) #define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) -- cgit From 8ac3838d19d88842cf7c276637e9896b3cc1351b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Jan 2005 15:37:12 +0000 Subject: r4688: don't run male proto for lib/talloc/ metze (This used to be commit 4ab63d547903814318b74ea030bba9da0f36942f) --- source4/lib/talloc/config.mk | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc/config.mk b/source4/lib/talloc/config.mk index 2f38fe04ed..fe8f0e929f 100644 --- a/source4/lib/talloc/config.mk +++ b/source4/lib/talloc/config.mk @@ -5,6 +5,7 @@ INIT_OBJ_FILES = \ lib/talloc/talloc.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE +NOPROTO = YES # # End SUBSYSTEM LIBTALLOC ################################################ -- cgit From 90d65c2e85c8042391b8219eeaedd780e6eb3c7c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Jan 2005 15:38:25 +0000 Subject: r4689: - make talloc_report_depth() public - add talloc_parent() to return the parent context of a pointer these are very use full for debuging metze (This used to be commit 9b9501bc03ef8d4b53049f6b3531d06ed7ef7f89) --- source4/lib/talloc/talloc.c | 8 +++++++- source4/lib/talloc/talloc.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 6d11cb00e9..4c8cc31028 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -140,6 +140,12 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr) return tc->parent; } +void *talloc_parent(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return (void *)(tc+1); +} + /* Allocate a bit of memory as a child of an existing pointer */ @@ -695,7 +701,7 @@ static int talloc_reference_count(const void *ptr) /* report on memory usage by all children of a pointer, giving a full tree view */ -static void talloc_report_depth(const void *ptr, FILE *f, int depth) +void talloc_report_depth(const void *ptr, FILE *f, int depth) { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index cf03ce5952..3483bb9e71 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -89,6 +89,8 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); void *talloc_named_const(const void *context, size_t size, const char *name); const char *talloc_get_name(const void *ptr); +void talloc_report_depth(const void *ptr, FILE *f, int depth); +void *talloc_parent(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); int talloc_free(void *ptr); void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -- cgit From 4b73689468ebe2e25a22d73fecb1a035b2303efd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Jan 2005 11:45:43 +0000 Subject: r4711: - deprecate talloc_destroy() - expanded the talloc_realloc() test a little (I was concerned about a possible bug, which turned out to be an illusion) - don't enable gcov by default in Makefile.talloc (This used to be commit 4ec47cc1083c4cdb780e548177631c5914bf677a) --- source4/lib/talloc/Makefile.talloc | 6 +++--- source4/lib/talloc/talloc.h | 5 ++--- source4/lib/talloc/testsuite.c | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.talloc b/source4/lib/talloc/Makefile.talloc index 88cb0e7159..a19b4ce311 100644 --- a/source4/lib/talloc/Makefile.talloc +++ b/source4/lib/talloc/Makefile.talloc @@ -1,6 +1,6 @@ -OPT = -g -ftest-coverage -fprofile-arcs -LIBS = -lgcov -#OPT = -g +#OPT = -g -ftest-coverage -fprofile-arcs +#LIBS = -lgcov +OPT = -O CFLAGS = $(OPT) -Wall diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 3483bb9e71..607ca4ca47 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -4,7 +4,7 @@ Unix SMB/CIFS implementation. Samba temporary memory allocation functions - Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Tridgell 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 @@ -54,8 +54,6 @@ typedef void TALLOC_CTX; #define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) -#define talloc_destroy(ctx) talloc_free(ctx) - #define malloc_p(type) (type *)malloc(sizeof(type)) #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) #define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) @@ -70,6 +68,7 @@ typedef void TALLOC_CTX; #define talloc_p(ctx, type) talloc(ctx, type) #define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) #define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) #endif #ifndef PRINTF_ATTRIBUTE diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index d93894b520..bc1c18fdc1 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -575,7 +575,7 @@ static BOOL test_realloc_child(void) int count; struct el2 { const char *name; - } **list; + } **list, **list2, **list3; } *el1; struct el2 *el2; @@ -587,11 +587,22 @@ static BOOL test_realloc_child(void) el1->list = talloc(el1, struct el2 *); el1->list[0] = talloc(el1->list, struct el2); el1->list[0]->name = talloc_strdup(el1->list[0], "testing"); + + el1->list2 = talloc(el1, struct el2 *); + el1->list2[0] = talloc(el1->list2, struct el2); + el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2"); + + el1->list3 = talloc(el1, struct el2 *); + el1->list3[0] = talloc(el1->list3, struct el2); + el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2"); el2 = talloc(el1->list, struct el2); + el2 = talloc(el1->list2, struct el2); + el2 = talloc(el1->list3, struct el2); - el1->list = talloc_realloc(el1, el1->list, struct el2 *, 2); - el1->list[1] = el2; + el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100); + el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200); + el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300); talloc_free(root); -- cgit From a2f77f979d7271a9708ed06f43b00ffb10ec7f4c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 12 Jan 2005 16:00:01 +0000 Subject: r4714: move the ldb code to the new talloc interface (eg remove _p suffix) this helps standalone building of ldb renew the schema module split code into functions to improve readability and code reuse add and modify works correctly but we need a proper testsuite Simo (This used to be commit a681ae365ff1b5a2771b42ebd90336651ce1e513) --- source4/lib/ldb/common/ldb_ldif.c | 16 +- source4/lib/ldb/common/ldb_modules.c | 4 +- source4/lib/ldb/common/ldb_msg.c | 16 +- source4/lib/ldb/common/ldb_parse.c | 10 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 24 +- source4/lib/ldb/ldb_tdb/ldb_cache.c | 20 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 32 +- source4/lib/ldb/ldb_tdb/ldb_pack.c | 6 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 16 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 20 +- source4/lib/ldb/modules/schema.c | 799 ++++++++++++----------------------- source4/lib/ldb/modules/timestamps.c | 16 +- source4/lib/ldb/tools/ldbedit.c | 2 +- 13 files changed, 358 insertions(+), 623 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index d20a2a3553..546cf461f8 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -97,7 +97,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) int bytes = (len*8 + 5)/6; char *out; - out = talloc_array_p(ldb, char, bytes+2); + out = talloc_array(ldb, char, bytes+2); if (!out) return NULL; for (i=0;i= alloc_size) { char *c2; alloc_size += 1024; - c2 = talloc_realloc_p(ldb, chunk, char, alloc_size); + c2 = talloc_realloc(ldb, chunk, char, alloc_size); if (!c2) { talloc_free(chunk); errno = ENOMEM; @@ -427,7 +427,7 @@ static int msg_add_empty(struct ldb_context *ldb, { struct ldb_message_element *el2, *el; - el2 = talloc_realloc_p(msg, msg->elements, + el2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!el2) { errno = ENOMEM; @@ -468,10 +468,10 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, value.data = NULL; - ldif = talloc_p(ldb, struct ldb_ldif); + ldif = talloc(ldb, struct ldb_ldif); if (!ldif) return NULL; - ldif->msg = talloc_p(ldif, struct ldb_message); + ldif->msg = talloc(ldif, struct ldb_message); if (ldif->msg == NULL) { talloc_free(ldif); return NULL; @@ -556,7 +556,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, flags == el->flags) { /* its a continuation */ el->values = - talloc_realloc_p(msg->elements, el->values, + talloc_realloc(msg->elements, el->values, struct ldb_val, el->num_values+1); if (!el->values) { goto failed; @@ -565,7 +565,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, el->num_values++; } else { /* its a new attribute */ - msg->elements = talloc_realloc_p(ldif, msg->elements, + msg->elements = talloc_realloc(ldif, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!msg->elements) { @@ -574,7 +574,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, el = &msg->elements[msg->num_elements]; el->flags = flags; el->name = talloc_strdup(msg->elements, attr); - el->values = talloc_p(msg->elements, struct ldb_val); + el->values = talloc(msg->elements, struct ldb_val); if (!el->values || !el->name) { goto failed; } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 033717a62b..22d1ce112e 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -69,7 +69,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) *p = '\0'; q = p + 1; pn++; - modules = talloc_realloc_p(ldb, modules, char *, pn); + modules = talloc_realloc(ldb, modules, char *, pn); if (!modules) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); return -1; @@ -103,7 +103,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) for (j = 0; j < msg[0]->num_elements; j++) { for (k = 0; k < msg[0]->elements[j].num_values; k++) { pn++; - modules = talloc_realloc_p(ldb, modules, char *, pn); + modules = talloc_realloc(ldb, modules, char *, pn); if (!modules) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); return -1; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 416590f462..5ab2088744 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -41,7 +41,7 @@ */ struct ldb_message *ldb_msg_new(void *mem_ctx) { - return talloc_zero_p(mem_ctx, struct ldb_message); + return talloc_zero(mem_ctx, struct ldb_message); } /* @@ -107,7 +107,7 @@ struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, /* the +1 is to cope with buggy C library routines like strndup that look one byte beyond */ - v2.data = talloc_array_p(mem_ctx, char, v->length+1); + v2.data = talloc_array(mem_ctx, char, v->length+1); if (!v2.data) { v2.length = 0; return v2; @@ -126,7 +126,7 @@ int ldb_msg_add_empty(struct ldb_context *ldb, { struct ldb_message_element *els; - els = talloc_realloc_p(msg, msg->elements, + els = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!els) { errno = ENOMEM; @@ -185,7 +185,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, return -1; } - vals = talloc_realloc_p(msg, el->values, struct ldb_val, el->num_values+1); + vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1); if (!vals) { errno = ENOMEM; return -1; @@ -351,7 +351,7 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, struct ldb_message *msg2; int i, j; - msg2 = talloc_p(ldb, struct ldb_message); + msg2 = talloc(ldb, struct ldb_message); if (msg2 == NULL) return NULL; msg2->elements = NULL; @@ -361,7 +361,7 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, msg2->dn = talloc_strdup(msg2, msg->dn); if (msg2->dn == NULL) goto failed; - msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg->num_elements); + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg->num_elements); if (msg2->elements == NULL) goto failed; for (i=0;inum_elements;i++) { @@ -373,7 +373,7 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, el2->values = NULL; el2->name = talloc_strdup(msg2->elements, el1->name); if (el2->name == NULL) goto failed; - el2->values = talloc_array_p(msg2->elements, struct ldb_val, el1->num_values); + el2->values = talloc_array(msg2->elements, struct ldb_val, el1->num_values); for (j=0;jnum_values;j++) { el2->values[j] = ldb_val_dup(ldb, &el1->values[j]); if (el2->values[j].data == NULL && @@ -413,7 +413,7 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, struct ldb_message_element *el1 = &msg2->elements[i-1]; struct ldb_message_element *el2 = &msg2->elements[i]; if (ldb_msg_element_compare_name(el1, el2) == 0) { - el1->values = talloc_realloc_p(msg2->elements, el1->values, struct ldb_val, + el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val, el1->num_values + el2->num_values); if (el1->values == NULL) { return NULL; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 6ee6f99253..d9f7dbe524 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -138,7 +138,7 @@ static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *ctx, const char *s) char *eq, *val, *l; struct ldb_parse_tree *ret; - ret = talloc_p(ctx, struct ldb_parse_tree); + ret = talloc(ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -188,7 +188,7 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, { struct ldb_parse_tree *ret, *next; - ret = talloc_p(ctx, struct ldb_parse_tree); + ret = talloc(ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -196,7 +196,7 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, ret->operation = op; ret->u.list.num_elements = 1; - ret->u.list.elements = talloc_p(ret, struct ldb_parse_tree *); + ret->u.list.elements = talloc(ret, struct ldb_parse_tree *); if (!ret->u.list.elements) { errno = ENOMEM; talloc_free(ret); @@ -213,7 +213,7 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, while (*s && (next = ldb_parse_filter(ret->u.list.elements, &s))) { struct ldb_parse_tree **e; - e = talloc_realloc_p(ret, ret->u.list.elements, + e = talloc_realloc(ret, ret->u.list.elements, struct ldb_parse_tree *, ret->u.list.num_elements+1); if (!e) { @@ -238,7 +238,7 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *ctx, const char *s) { struct ldb_parse_tree *ret; - ret = talloc_p(ctx, struct ldb_parse_tree); + ret = talloc(ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index bab3c86e16..46ea1a9e33 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -161,7 +161,7 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, return -1; } - el = talloc_realloc_p(msg, msg->elements, struct ldb_message_element, + el = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements + 1); if (!el) { errno = ENOMEM; @@ -180,7 +180,7 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, el->flags = 0; el->num_values = 0; - el->values = talloc_array_p(msg->elements, struct ldb_val, count); + el->values = talloc_array(msg->elements, struct ldb_val, count); if (!el->values) { errno = ENOMEM; return -1; @@ -230,7 +230,7 @@ static int lldb_search(struct ldb_module *module, const char *base, return count; } - (*res) = talloc_array_p(lldb, struct ldb_message *, count+1); + (*res) = talloc_array(lldb, struct ldb_message *, count+1); if (! *res) { ldap_msgfree(ldapres); errno = ENOMEM; @@ -254,7 +254,7 @@ static int lldb_search(struct ldb_module *module, const char *base, break; } - (*res)[msg_count] = talloc_p(*res, struct ldb_message); + (*res)[msg_count] = talloc(*res, struct ldb_message); if (!(*res)[msg_count]) { goto failed; } @@ -317,7 +317,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, int num_mods = 0; /* allocate maximum number of elements needed */ - mods = talloc_array_p(ldb, LDAPMod *, msg->num_elements+1); + mods = talloc_array(ldb, LDAPMod *, msg->num_elements+1); if (!mods) { errno = ENOMEM; return NULL; @@ -327,7 +327,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, for (i=0;inum_elements;i++) { const struct ldb_message_element *el = &msg->elements[i]; - mods[num_mods] = talloc_p(ldb, LDAPMod); + mods[num_mods] = talloc(ldb, LDAPMod); if (!mods[num_mods]) { goto failed; } @@ -347,7 +347,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, } } mods[num_mods]->mod_type = el->name; - mods[num_mods]->mod_vals.modv_bvals = talloc_array_p(mods[num_mods], + mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], struct berval *, 1+el->num_values); if (!mods[num_mods]->mod_vals.modv_bvals) { @@ -355,7 +355,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, } for (j=0;jnum_values;j++) { - mods[num_mods]->mod_vals.modv_bvals[j] = talloc_p(mods[num_mods]->mod_vals.modv_bvals, + mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals, struct berval); if (!mods[num_mods]->mod_vals.modv_bvals[j]) { goto failed; @@ -499,13 +499,13 @@ struct ldb_context *lldb_connect(const char *url, struct lldb_private *lldb = NULL; int i, version = 3; - ldb = talloc_p(NULL, struct ldb_context); + ldb = talloc(NULL, struct ldb_context); if (!ldb) { errno = ENOMEM; goto failed; } - lldb = talloc_p(ldb, struct lldb_private); + lldb = talloc(ldb, struct lldb_private); if (!lldb) { errno = ENOMEM; goto failed; @@ -526,7 +526,7 @@ struct ldb_context *lldb_connect(const char *url, goto failed; } - ldb->modules = talloc_p(ldb, struct ldb_module); + ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { errno = ENOMEM; goto failed; @@ -541,7 +541,7 @@ struct ldb_context *lldb_connect(const char *url, on the caller keeping it around (it might be dynamic) */ for (i=0;options[i];i++) ; - lldb->options = talloc_array_p(lldb, char *, i+1); + lldb->options = talloc_array(lldb, char *, i+1); if (!lldb->options) { goto failed; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index ebdfdb7bed..8cc6616d52 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -54,7 +54,7 @@ static int ltdb_baseinfo_init(struct ldb_module *module) ltdb->sequence_number = atof(initial_sequence_number); - msg = talloc_p(ltdb, struct ldb_message); + msg = talloc(ltdb, struct ldb_message); if (msg == NULL) { goto failed; } @@ -120,11 +120,11 @@ int ltdb_cache_load(struct ldb_module *module) double seq; if (ltdb->cache == NULL) { - ltdb->cache = talloc_zero_p(ltdb, struct ltdb_cache); + ltdb->cache = talloc_zero(ltdb, struct ltdb_cache); if (ltdb->cache == NULL) goto failed; - ltdb->cache->indexlist = talloc_zero_p(ltdb->cache, struct ldb_message); - ltdb->cache->subclasses = talloc_zero_p(ltdb->cache, struct ldb_message); - ltdb->cache->attributes = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message); + ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message); + ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message); if (ltdb->cache->indexlist == NULL || ltdb->cache->subclasses == NULL || ltdb->cache->attributes == NULL) { @@ -133,7 +133,7 @@ int ltdb_cache_load(struct ldb_module *module) } talloc_free(ltdb->cache->baseinfo); - ltdb->cache->baseinfo = talloc_p(ltdb->cache, struct ldb_message); + ltdb->cache->baseinfo = talloc(ltdb->cache, struct ldb_message); if (ltdb->cache->baseinfo == NULL) goto failed; if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) == -1) { @@ -165,9 +165,9 @@ int ltdb_cache_load(struct ldb_module *module) talloc_free(ltdb->cache->subclasses); talloc_free(ltdb->cache->attributes); - ltdb->cache->indexlist = talloc_zero_p(ltdb->cache, struct ldb_message); - ltdb->cache->subclasses = talloc_zero_p(ltdb->cache, struct ldb_message); - ltdb->cache->attributes = talloc_zero_p(ltdb->cache, struct ldb_message); + ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message); + ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message); + ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message); if (ltdb->cache->indexlist == NULL || ltdb->cache->subclasses == NULL || ltdb->cache->attributes == NULL) { @@ -204,7 +204,7 @@ int ltdb_increase_sequence_number(struct ldb_module *module) char *s = NULL; int ret; - msg = talloc_p(ltdb, struct ldb_message); + msg = talloc(ltdb, struct ldb_message); if (msg == NULL) { errno = ENOMEM; return -1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 88ef997a03..af325f9203 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -180,7 +180,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module, dn = ldb_dn_key(ldb, tree->u.simple.attr, &tree->u.simple.value); if (!dn) return -1; - msg = talloc_p(list, struct ldb_message); + msg = talloc(list, struct ldb_message); if (msg == NULL) { return -1; } @@ -200,7 +200,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module, el = &msg->elements[i]; - list->dn = talloc_array_p(list, char *, el->num_values); + list->dn = talloc_array(list, char *, el->num_values); if (!list->dn) { break; } @@ -259,7 +259,7 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, return -1; } tree2.u.simple.value = el->values[j]; - list2 = talloc_p(list, struct dn_list); + list2 = talloc(list, struct dn_list); if (list2 == NULL) { return -1; } @@ -313,12 +313,12 @@ static int list_intersect(struct ldb_context *ldb, return 0; } - list3 = talloc_p(ldb, struct dn_list); + list3 = talloc(ldb, struct dn_list); if (list3 == NULL) { return -1; } - list3->dn = talloc_array_p(list3, char *, list->count); + list3->dn = talloc_array(list3, char *, list->count); if (!list3->dn) { talloc_free(list); talloc_free(list3); @@ -363,7 +363,7 @@ static int list_union(struct ldb_context *ldb, return 0; } - d = talloc_realloc_p(list, list->dn, char *, list->count + list2->count); + d = talloc_realloc(list, list->dn, char *, list->count + list2->count); if (!d) { talloc_free(list); return -1; @@ -415,7 +415,7 @@ static int ltdb_index_dn_or(struct ldb_module *module, struct dn_list *list2; int v; - list2 = talloc_p(module, struct dn_list); + list2 = talloc(module, struct dn_list); if (list2 == NULL) { return -1; } @@ -500,7 +500,7 @@ static int ltdb_index_dn_and(struct ldb_module *module, struct dn_list *list2; int v; - list2 = talloc_p(module, struct dn_list); + list2 = talloc(module, struct dn_list); if (list2 == NULL) { return -1; } @@ -591,7 +591,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr struct ldb_message *msg; int ret; - msg = talloc_p(module, struct ldb_message); + msg = talloc(module, struct ldb_message); if (msg == NULL) { return -1; } @@ -642,7 +642,7 @@ int ltdb_search_indexed(struct ldb_module *module, return -1; } - dn_list = talloc_p(module, struct dn_list); + dn_list = talloc(module, struct dn_list); if (dn_list == NULL) { return -1; } @@ -672,7 +672,7 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, struct ldb_message_element *el2; /* add another entry */ - el2 = talloc_realloc_p(msg, msg->elements, + el2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!el2) { return -1; @@ -684,7 +684,7 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, return -1; } msg->elements[msg->num_elements].num_values = 0; - msg->elements[msg->num_elements].values = talloc_p(msg->elements, struct ldb_val); + msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val); if (!msg->elements[msg->num_elements].values) { return -1; } @@ -717,7 +717,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, } } - v2 = talloc_realloc_p(msg->elements, msg->elements[idx].values, + v2 = talloc_realloc(msg->elements, msg->elements[idx].values, struct ldb_val, msg->elements[idx].num_values+1); if (!v2) { @@ -749,7 +749,7 @@ static int ltdb_index_add1(struct ldb_module *module, char *dn, return -1; } - msg = talloc_p(dn_key, struct ldb_message); + msg = talloc(dn_key, struct ldb_message); if (msg == NULL) { return -1; } @@ -842,7 +842,7 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, return -1; } - msg = talloc_p(dn_key, struct ldb_message); + msg = talloc(dn_key, struct ldb_message); if (msg == NULL) { talloc_free(dn_key); return -1; @@ -948,7 +948,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return 0; } - msg = talloc_p(module, struct ldb_message); + msg = talloc(module, struct ldb_message); if (msg == NULL) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 501728fac5..4433e16cb2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -99,7 +99,7 @@ int ltdb_pack_data(struct ldb_module *module, } /* allocate it */ - data->dptr = talloc_array_p(ldb, char, size); + data->dptr = talloc_array(ldb, char, size); if (!data->dptr) { errno = ENOMEM; return -1; @@ -199,7 +199,7 @@ int ltdb_unpack_data(struct ldb_module *module, goto failed; } - message->elements = talloc_array_p(message, struct ldb_message_element, message->num_elements); + message->elements = talloc_array(message, struct ldb_message_element, message->num_elements); if (!message->elements) { errno = ENOMEM; goto failed; @@ -225,7 +225,7 @@ int ltdb_unpack_data(struct ldb_module *module, message->elements[i].num_values = pull_uint32(p, 0); message->elements[i].values = NULL; if (message->elements[i].num_values != 0) { - message->elements[i].values = talloc_array_p(message->elements, + message->elements[i].values = talloc_array(message->elements, struct ldb_val, message->elements[i].num_values); if (!message->elements[i].values) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 295c9578cc..536d1ac005 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -47,7 +47,7 @@ static int msg_add_element(struct ldb_context *ldb, unsigned int i; struct ldb_message_element *e2, *elnew; - e2 = talloc_realloc_p(ret, ret->elements, struct ldb_message_element, ret->num_elements+1); + e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1); if (!e2) { return -1; } @@ -61,7 +61,7 @@ static int msg_add_element(struct ldb_context *ldb, } if (el->num_values) { - elnew->values = talloc_array_p(ret->elements, struct ldb_val, el->num_values); + elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values); if (!elnew->values) { return -1; } @@ -117,7 +117,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, struct ldb_message *ret; int i; - ret = talloc_p(ldb, struct ldb_message); + ret = talloc(ldb, struct ldb_message); if (!ret) { return NULL; } @@ -279,12 +279,12 @@ int ltdb_search_dn(struct ldb_module *module, char *dn, int ret; struct ldb_message *msg, *msg2; - *res = talloc_array_p(ldb, struct ldb_message *, 2); + *res = talloc_array(ldb, struct ldb_message *, 2); if (! *res) { return -1; } - msg = talloc_p(*res, struct ldb_message); + msg = talloc(*res, struct ldb_message); if (msg == NULL) { talloc_free(*res); *res = NULL; @@ -333,7 +333,7 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, } /* add to the results list */ - res2 = talloc_realloc_p(ldb, *res, struct ldb_message *, (*count)+2); + res2 = talloc_realloc(ldb, *res, struct ldb_message *, (*count)+2); if (!res2) { talloc_free(msg2); return -1; @@ -378,7 +378,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi return 0; } - msg = talloc_p(sinfo, struct ldb_message); + msg = talloc(sinfo, struct ldb_message); if (msg == NULL) { return -1; } @@ -442,7 +442,7 @@ static int ltdb_search_full(struct ldb_module *module, int ret, count; struct ltdb_search_info *sinfo; - sinfo = talloc_p(ltdb, struct ltdb_search_info); + sinfo = talloc(ltdb, struct ltdb_search_info); if (sinfo == NULL) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 288633cb01..b1de96986d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -300,7 +300,7 @@ static int ltdb_delete(struct ldb_module *module, const char *dn) goto failed; } - msg = talloc_p(module, struct ldb_message); + msg = talloc(module, struct ldb_message); if (msg == NULL) { goto failed; } @@ -368,7 +368,7 @@ static int msg_add_element(struct ldb_context *ldb, struct ldb_message_element *e2; unsigned int i; - e2 = talloc_realloc_p(msg, msg->elements, struct ldb_message_element, + e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements+1); if (!e2) { errno = ENOMEM; @@ -383,7 +383,7 @@ static int msg_add_element(struct ldb_context *ldb, e2->flags = el->flags; e2->values = NULL; if (el->num_values != 0) { - e2->values = talloc_array_p(msg->elements, struct ldb_val, el->num_values); + e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values); if (!e2->values) { errno = ENOMEM; return -1; @@ -422,7 +422,7 @@ static int msg_delete_attribute(struct ldb_module *module, } msg->num_elements--; i--; - msg->elements = talloc_realloc_p(msg, msg->elements, + msg->elements = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements); } @@ -498,7 +498,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms return -1; } - msg2 = talloc_p(tdb_key.dptr, struct ldb_message); + msg2 = talloc(tdb_key.dptr, struct ldb_message); if (msg2 == NULL) { talloc_free(tdb_key.dptr); return -1; @@ -547,7 +547,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } } - vals = talloc_realloc_p(msg2->elements, el2->values, struct ldb_val, + vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val, el2->num_values + el->num_values); if (vals == NULL) @@ -661,7 +661,7 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char return -1; } - msg = talloc_p(module, struct ldb_message); + msg = talloc(module, struct ldb_message); if (msg == NULL) { goto failed; } @@ -765,7 +765,7 @@ struct ldb_context *ltdb_connect(const char *url, TDB_CONTEXT *tdb; struct ldb_context *ldb; - ldb = talloc_zero_p(NULL, struct ldb_context); + ldb = talloc_zero(NULL, struct ldb_context); if (!ldb) { errno = ENOMEM; return NULL; @@ -798,7 +798,7 @@ struct ldb_context *ltdb_connect(const char *url, return NULL; } - ltdb = talloc_zero_p(ldb, struct ltdb_private); + ltdb = talloc_zero(ldb, struct ltdb_private); if (!ltdb) { tdb_close(tdb); talloc_free(ldb); @@ -811,7 +811,7 @@ struct ldb_context *ltdb_connect(const char *url, talloc_set_destructor(ltdb, ltdb_destructor); - ldb->modules = talloc_p(ldb, struct ldb_module); + ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { talloc_free(ldb); errno = ENOMEM; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1f9017976e..63d94eed81 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -63,6 +63,10 @@ static struct attribute_syntax attrsyn[] = { #define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); +#define SA_FLAG_RESET 0 +#define SA_FLAG_AUXCLASS 1 +#define SA_FLAG_CHECKED 2 + struct private_data { struct ldb_context *schema_db; const char *error_string; @@ -88,105 +92,177 @@ static int schema_search_free(struct ldb_module *module, struct ldb_message **re return ldb_next_search_free(module, res); } -struct check_list { - int check; - char *name; -}; - -struct attr_list { - int syntax; - char *name; -}; - -struct objc_list { - int aux; +struct attribute_list { + int flags; char *name; }; struct schema_structures { - struct check_list *cl; - struct objc_list *ol; - struct attr_list *must; - struct attr_list *may; - int num_cl; - int num_objc; - int num_must; - int num_may; + struct attribute_list *check_list; + struct attribute_list *objectclass_list; + struct attribute_list *must; + struct attribute_list *may; + int check_list_num; + int objectclass_list_num; + int must_num; + int may_num; }; -/* add_record */ -static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { - struct private_data *data = (struct private_data *)module->private_data; + char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); + const char *attrs[] = {"objectClass", NULL}; struct ldb_message **srch; - struct schema_structures *ss; - int i, j, k, l; - int ret; + int i, j, ret; + + schema_struct->objectclass_list = NULL; + schema_struct->objectclass_list_num = 0; + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); + if (ret == 1) { + for (i = 0; i < (*srch)->num_elements; i++) { + schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == 0) { + ldb_search_free(ldb, srch); + return -1; + } + for (j = 0; j < schema_struct->objectclass_list_num; j++) { + schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, + (*srch)->elements[i].values[j].data, + (*srch)->elements[i].values[j].length); + if (schema_struct->objectclass_list[j].name == 0) { + ldb_search_free(ldb, srch); + return -1; + } + schema_struct->objectclass_list[j].flags = SA_FLAG_RESET; + } + } + ldb_search_free(ldb, srch); + } else { + ldb_search_free(ldb, srch); + return -1; + } - /* First implementation: - Build up a list of must and mays from each objectclass - Check all the musts are there and all the other attributes are mays - Throw an error in case a check fail - Free all structures and commit the change - */ + return 0; +} - ss = talloc_p(module, struct schema_structures); - if (!ss) { +static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) +{ + int i, j, k; + + schema_struct->objectclass_list = NULL; + schema_struct->objectclass_list_num = 0; + schema_struct->check_list_num = msg->num_elements; + schema_struct->check_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->check_list_num); + if (schema_struct->check_list == 0) { return -1; } - - ss->ol = NULL; - ss->num_objc = 0; - ss->num_cl = msg->num_elements; - ss->cl = talloc_array_p(ss, struct check_list, ss->num_cl); - SCHEMA_TALLOC_CHECK(ss, ss->cl, -1); for (i = 0, j = 0; i < msg->num_elements; i++) { if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { - ss->num_objc = msg->elements[i].num_values; - ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0; k < ss->num_objc; k++) { - ss->ol[k].name = talloc_strndup(ss->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); - ss->ol[k].aux = 0; + schema_struct->objectclass_list_num = msg->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == 0) { + return -1; + } + for (k = 0; k < schema_struct->objectclass_list_num; k++) { + schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, + msg->elements[i].values[k].data, + msg->elements[i].values[k].length); + if (schema_struct->objectclass_list[k].name == 0) { + return -1; + } + schema_struct->objectclass_list[k].flags = SA_FLAG_RESET; } } - ss->cl[j].check = 0; - ss->cl[j].name = talloc_strdup(ss->cl, msg->elements[i].name); - SCHEMA_TALLOC_CHECK(ss, ss->cl[j].name, -1); + schema_struct->check_list[j].flags = SA_FLAG_RESET; + schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, + msg->elements[i].name); + if (schema_struct->check_list[j].name == 0) { + return -1; + } j++; } - /* find all other objectclasses recursively */ - ss->must = NULL; - ss->may = NULL; - ss->num_must = 0; - ss->num_may = 0; - for (i = 0; i < ss->num_objc; i++) { + return 0; +} + +static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) +{ + int i, j, vals; + + vals = el->num_values; + *list = talloc_realloc(mem_ctx, *list, struct attribute_list, *list_num + vals); + if (list == 0) { + return -1; + } + for (i = 0, j = 0; i < vals; i++) { + int c, found, len; + + found = 0; + for (c = 0; c < *list_num; c++) { + len = strlen((*list)[c].name); + if (len == el->values[i].length) { + if (strncasecmp((*list)[c].name, el->values[i].data, len) == 0) { + found = 1; + break; + } + } + } + if (!found) { + (*list)[j + *list_num].name = talloc_strndup(*list, el->values[i].data, el->values[i].length); + if ((*list)[j + *list_num].name == 0) { + return -1; + } + (*list)[j + *list_num].flags = flags; + j++; + } + } + *list_num += j; + + return 0; +} + +static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message **srch; + int i, j; + int ret; + + schema_struct->must = NULL; + schema_struct->may = NULL; + schema_struct->must_num = 0; + schema_struct->may_num = 0; + for (i = 0; i < schema_struct->objectclass_list_num; i++) { char *filter; - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); + SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); if (ret == 0) { int ok; ok = 0; - /* suppose auxiliary classess are not required */ - if (ss->ol[i].aux) { + /* suppose auxiliary classeschema_struct are not required */ + if (schema_struct->objectclass_list[i].flags & SA_FLAG_AUXCLASS) { int d; ok = 1; - ss->num_objc -= 1; - for (d = i; d < ss->num_objc; d++) { - ss->ol[d] = ss->ol[d + 1]; + schema_struct->objectclass_list_num -= 1; + for (d = i; d < schema_struct->objectclass_list_num; d++) { + schema_struct->objectclass_list[d] = schema_struct->objectclass_list[d + 1]; } i -= 1; } if (!ok) { /* Schema Violation: Object Class Description Not Found */ data->error_string = "ObjectClass not found"; - talloc_free(ss); return -1; } continue; @@ -194,13 +270,11 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if (ret < 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); return -1; } } @@ -208,12 +282,12 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* Add inherited classes eliminating duplicates */ /* fill in kust and may attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; + int is_aux, is_class; is_aux = 0; is_class = 0; if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; + is_aux = SA_FLAG_AUXCLASS; is_class = 1; } if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { @@ -221,103 +295,87 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if (is_class) { - o = (*srch)->elements[j].num_values; - ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_objc; c++) { - len = strlen(ss->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); - ss->ol[l + ss->num_objc].aux = is_aux; - l++; - } + if (add_attribute_uniq(&schema_struct->objectclass_list, + &schema_struct->objectclass_list_num, + is_aux, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_objc += l; } else { - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ss->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_must; c++) { - len = strlen(ss->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); - l++; - } + if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || + strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (add_attribute_uniq(&schema_struct->must, + &schema_struct->must_num, + SA_FLAG_RESET, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_must += l; } - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ss->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_may; c++) { - len = strlen(ss->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); - l++; - } + if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || + strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + + if (add_attribute_uniq(&schema_struct->may, + &schema_struct->may_num, + SA_FLAG_RESET, + &(*srch)->elements[j], + schema_struct) != 0) { + return -1; } - ss->num_may += l; } } } - ldb_search_free(data->schema_db, srch); + ldb_search_free(ldb, srch); + } + + return 0; +} + +/* add_record */ +static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct private_data *data = (struct private_data *)module->private_data; + struct schema_structures *entry_structs; + int i, j; + int ret; + + /* First implementation: + Build up a list of must and mays from each objectclass + Check all the musts are there and all the other attributes are mays + Throw an error in case a check fail + Free all structures and commit the change + */ + + entry_structs = talloc(module, struct schema_structures); + if (!entry_structs) { + return -1; + } + + ret = get_check_list(module, entry_structs, msg); + if (ret != 0) { + talloc_free(entry_structs); + return ret; + } + + /* find all other objectclasses recursively */ + ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now check all musts are present */ - for (i = 0; i < ss->num_must; i++) { + for (i = 0; i < entry_structs->must_num; i++) { int found; found = 0; - for (j = 0; j < ss->num_cl; j++) { - if (strcasecmp(ss->must[i].name, ss->cl[j].name) == 0) { - ss->cl[j].check = 1; + for (j = 0; j < entry_structs->check_list_num; j++) { + if (strcasecmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + entry_structs->check_list[j].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -325,22 +383,22 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if ( ! found ) { /* TODO: set the error string */ - data->error_string = "Objectclass violation, a required attribute is missing"; - talloc_free(ss); + data->error_string = "Objectclass violation, a required attribute is mischema_structing"; + talloc_free(entry_structs); return -1; } } /* now check all others atribs are found in mays */ - for (i = 0; i < ss->num_cl; i++) { + for (i = 0; i < entry_structs->check_list_num; i++) { - if ( ! ss->cl[i].check ) { + if (entry_structs->check_list[i].flags != SA_FLAG_CHECKED) { int found; found = 0; - for (j = 0; j < ss->num_may; j++) { - if (strcasecmp(ss->may[j].name, ss->cl[i].name) == 0) { - ss->cl[i].check = 1; + for (j = 0; j < entry_structs->may_num; j++) { + if (strcasecmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + entry_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -348,13 +406,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message if ( ! found ) { data->error_string = "Objectclass violation, an invalid attribute name was found"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } } - talloc_free(ss); + talloc_free(entry_structs); return ldb_next_add_record(module, msg); } @@ -363,9 +421,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; - struct ldb_message **srch; - struct schema_structures *ss, *ms; - int i, j, k, l; + struct schema_structures *entry_structs, *modify_structs; + int i, j; int ret; /* First implementation: @@ -379,387 +436,65 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ - ss = talloc_p(module, struct schema_structures); - if (!ss) { + /* allocate object structs */ + entry_structs = talloc(module, struct schema_structures); + if (!entry_structs) { return -1; } - ms = talloc_p(module, struct schema_structures); - SCHEMA_TALLOC_CHECK(ss, ms, -1); - - ms->ol = NULL; - ms->num_objc = 0; - ms->num_cl = msg->num_elements; - ms->cl = talloc_array_p(ms, struct check_list, ms->num_cl); - SCHEMA_TALLOC_CHECK(ss, ms->cl, -1); - for (i = 0, j = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { - ms->num_objc = msg->elements[i].num_values; - ms->ol = talloc_array_p(ms, struct objc_list, ms->num_objc); - SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); - for (k = 0; k < ms->num_objc; k++) { - ms->ol[k].name = talloc_strndup(ms->ol, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->ol[k].name, -1); - ms->ol[k].aux = 0; - } - } + /* allocate modification entry structs */ + modify_structs = talloc(entry_structs, struct schema_structures); + if (!modify_structs) { + talloc_free(entry_structs); + return -1; + } - ms->cl[j].check = 0; - ms->cl[j].name = talloc_strdup(ms->cl, msg->elements[i].name); - SCHEMA_TALLOC_CHECK(ss, ms->cl[j].name, -1); - j++; + /* get list of values to modify */ + ret = get_check_list(module, modify_structs, msg); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* find all modify objectclasses recursively if any objectclass is being added */ - ms->must = NULL; - ms->may = NULL; - ms->num_must = 0; - ms->num_may = 0; - for (i = 0; i < ms->num_objc; i++) { - char *filter; - - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ms->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classess are not required */ - if (ms->ol[i].aux) { - int d; - ok = 1; - ms->num_objc -= 1; - for (d = i; d < ms->num_objc; d++) { - ms->ol[d] = ms->ol[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - data->error_string = "ObjectClass not found"; - talloc_free(ss); - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); - return -1; - } - } - - /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ - for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; - - is_aux = 0; - is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; - is_class = 1; - } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { - is_class = 1; - } - - if (is_class) { - o = (*srch)->elements[j].num_values; - ms->ol = talloc_realloc_p(ms, ms->ol, struct objc_list, ms->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ms->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_objc; c++) { - len = strlen(ms->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->ol[l + ms->num_objc].name = talloc_strndup(ms->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->ol[l + ms->num_objc].name, -1); - ms->ol[l + ms->num_objc].aux = is_aux; - l++; - } - } - ms->num_objc += l; - } else { - - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ms->must = talloc_realloc_p(ms, ms->must, struct attr_list, ms->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ms->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_must; c++) { - len = strlen(ms->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ms->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->must[l + ms->num_must].name = talloc_strndup(ms->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->must[l + ms->num_must].name, -1); - l++; - } - } - ms->num_must += l; - } - - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ms->may = talloc_realloc_p(ms, ms->may, struct attr_list, ms->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ms->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ms->num_may; c++) { - len = strlen(ms->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ms->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ms->may[l + ms->num_may].name = talloc_strndup(ms->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ms->may[l + ms->num_may].name, -1); - l++; - } - } - ms->num_may += l; - } - } - } - - ldb_search_free(data->schema_db, srch); + ret = get_attr_list_recursive(module, data->schema_db, modify_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now search for the original object objectclasses */ - - ss->ol = NULL; - ss->num_objc = 0; - - /* find all other objectclasses recursively */ - { - char *filter = talloc_asprintf(ss, "dn=%s", msg->dn); - const char *attrs[] = {"objectClass", NULL}; - - ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret == 1) { - for (i = 0; i < msg->num_elements; i++) { - ss->num_objc = (*srch)->elements[i].num_values; - ss->ol = talloc_array_p(ss, struct objc_list, ss->num_objc); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0; k < ss->num_objc; k++) { - ss->ol[k].name = talloc_strndup(ss->ol, (*srch)->elements[i].values[k].data, (*srch)->elements[i].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[k].name, -1); - ss->ol[k].aux = 0; - } - } - ldb_search_free(module->ldb, srch); - } else { - ldb_search_free(module->ldb, srch); - return -1; - } + ret = get_object_objectclasses(module->ldb, msg->dn, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } - ss->must = NULL; - ss->may = NULL; - ss->num_must = 0; - ss->num_may = 0; - for (i = 0; i < ss->num_objc; i++) { - char *filter; - - filter = talloc_asprintf(ss, "lDAPDisplayName=%s", ss->ol[i].name); - SCHEMA_TALLOC_CHECK(ss, filter, -1); - ret = ldb_search(data->schema_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classess are not required */ - if (ss->ol[i].aux) { - int d; - ok = 1; - ss->num_objc -= 1; - for (d = i; d < ss->num_objc; d++) { - ss->ol[d] = ss->ol[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - data->error_string = "ObjectClass not found"; - talloc_free(ss); - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - data->error_string = "Internal error. Error retrieving schema objectclass"; - talloc_free(ss); - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - data->error_string = "Internal error. Too many records searching for schema objectclass"; - talloc_free(ss); - return -1; - } - } - - /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ - for (j = 0; j < (*srch)->num_elements; j++) { - int o, is_aux, is_class; - - is_aux = 0; - is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = 1; - is_class = 1; - } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { - is_class = 1; - } - - if (is_class) { - o = (*srch)->elements[j].num_values; - ss->ol = talloc_realloc_p(ss, ss->ol, struct objc_list, ss->num_objc + o); - SCHEMA_TALLOC_CHECK(ss, ss->ol, -1); - for (k = 0, l = 0; k < o; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_objc; c++) { - len = strlen(ss->ol[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->ol[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->ol[l + ss->num_objc].name = talloc_strndup(ss->ol, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->ol[l + ss->num_objc].name, -1); - ss->ol[l + ss->num_objc].aux = is_aux; - l++; - } - } - ss->num_objc += l; - } else { - - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->must = talloc_realloc_p(ss, ss->must, struct attr_list, ss->num_must + m); - SCHEMA_TALLOC_CHECK(ss, ss->must, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_must; c++) { - len = strlen(ss->must[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->must[c].name, (*srch)->elements[j].values[k].data, len) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->must[l + ss->num_must].name = talloc_strndup(ss->must, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->must[l + ss->num_must].name, -1); - l++; - } - } - ss->num_must += l; - } - - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - int m; - - m = (*srch)->elements[j].num_values; - - ss->may = talloc_realloc_p(ss, ss->may, struct attr_list, ss->num_may + m); - SCHEMA_TALLOC_CHECK(ss, ss->may, -1); - for (k = 0, l = 0; k < m; k++) { - int c, found, len; - - found = 0; - for (c = 0; c < ss->num_may; c++) { - len = strlen(ss->may[c].name); - if (len == (*srch)->elements[j].values[k].length) { - if (strncasecmp(ss->may[c].name, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length) == 0) { - found = 1; - break; - } - } - } - if (!found) { - ss->may[l + ss->num_may].name = talloc_strndup(ss->may, (*srch)->elements[j].values[k].data, (*srch)->elements[j].values[k].length); - SCHEMA_TALLOC_CHECK(ss, ss->may[l + ss->num_may].name, -1); - l++; - } - } - ss->num_may += l; - } - } - } - - ldb_search_free(data->schema_db, srch); + /* find all other objectclasses recursively */ + ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + if (ret != 0) { + talloc_free(entry_structs); + return ret; } /* now check all entries are present either as musts or mays of curent objectclasses */ /* do not return errors there may be attirbutes defined in new objectclasses */ /* just mark them as being proved valid attribs */ - for (i = 0; i < ms->num_cl; i++) { + for (i = 0; i < modify_structs->check_list_num; i++) { int found; found = 0; - for (j = 0; j < ss->num_may; j++) { - if (strcasecmp(ss->may[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < entry_structs->may_num; j++) { + if (strcasecmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } } if ( ! found) { - for (j = 0; j < ss->num_must; j++) { - if (strcasecmp(ss->must[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < entry_structs->must_num; j++) { + if (strcasecmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; break; } } @@ -767,13 +502,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* now check all new objectclasses musts are present */ - for (i = 0; i < ms->num_must; i++) { + for (i = 0; i < modify_structs->must_num; i++) { int found; found = 0; - for (j = 0; j < ms->num_cl; j++) { - if (strcasecmp(ms->must[i].name, ms->cl[j].name) == 0) { - ms->cl[j].check = 1; + for (j = 0; j < modify_structs->check_list_num; j++) { + if (strcasecmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + modify_structs->check_list[j].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -782,21 +517,21 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess if ( ! found ) { /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is missing"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } /* now check all others atribs are found in mays */ - for (i = 0; i < ms->num_cl; i++) { + for (i = 0; i < modify_structs->check_list_num; i++) { - if ( ! ms->cl[i].check ) { + if (modify_structs->check_list[i].flags != SA_FLAG_CHECKED) { int found; found = 0; - for (j = 0; j < ms->num_may; j++) { - if (strcasecmp(ms->may[j].name, ms->cl[i].name) == 0) { - ms->cl[i].check = 1; + for (j = 0; j < modify_structs->may_num; j++) { + if (strcasecmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags = SA_FLAG_CHECKED; found = 1; break; } @@ -804,13 +539,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess if ( ! found ) { data->error_string = "Objectclass violation, an invalid attribute name was found"; - talloc_free(ss); + talloc_free(entry_structs); return -1; } } } - talloc_free(ss); + talloc_free(entry_structs); return ldb_next_modify_record(module, msg); } @@ -818,7 +553,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess /* delete_record */ static int schema_delete_record(struct ldb_module *module, const char *dn) { - struct private_data *data = (struct private_data *)module->private_data; +/* struct private_data *data = (struct private_data *)module->private_data; */ return ldb_next_delete_record(module, dn); } @@ -880,7 +615,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio char *db_url = NULL; int i; - ctx = talloc_p(ldb, struct ldb_module); + ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } @@ -923,7 +658,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ldb_search_free(ldb, msgs); } - data = talloc_p(ctx, struct private_data); + data = talloc(ctx, struct private_data); SCHEMA_TALLOC_CHECK(ctx, data, NULL); data->schema_db = ldb_connect(db_url, 0, NULL); diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 09679435f5..4066d231cd 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -74,11 +74,11 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, } } - msg->elements = talloc_realloc_p(msg, msg->elements, + msg->elements = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements + 1); name = talloc_strdup(msg->elements, attr_name); timestr = talloc_strdup(msg->elements, time_string); - values = talloc_p(msg->elements, struct ldb_val); + values = talloc(msg->elements, struct ldb_val); if (!msg->elements || !name || !timestr || !values) { return -1; } @@ -113,7 +113,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes return -1; } - msg2 = talloc_p(module, struct ldb_message); + msg2 = talloc(module, struct ldb_message); if (!msg2) { return -1; } @@ -130,7 +130,7 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -169,7 +169,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return -1; } - msg2 = talloc_p(module, struct ldb_message); + msg2 = talloc(module, struct ldb_message); if (!msg2) { return -1; } @@ -187,7 +187,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ msg2->dn = msg->dn; msg2->num_elements = msg->num_elements; msg2->private_data = msg->private_data; - msg2->elements = talloc_array_p(msg2, struct ldb_message_element, msg2->num_elements); + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); for (i = 0; i < msg2->num_elements; i++) { msg2->elements[i] = msg->elements[i]; } @@ -272,11 +272,11 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o struct ldb_module *ctx; struct private_data *data; - ctx = talloc_p(ldb, struct ldb_module); + ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc_p(ctx, struct private_data); + data = talloc(ctx, struct private_data); if (!data) { talloc_free(ctx); return NULL; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 66b684f4d5..4c38ea6803 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -280,7 +280,7 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun } while ((ldif = ldb_ldif_read_file(ldb, f))) { - msgs2 = talloc_realloc_p(ldb, msgs2, struct ldb_message *, count2+1); + msgs2 = talloc_realloc(ldb, msgs2, struct ldb_message *, count2+1); if (!msgs2) { fprintf(stderr, "out of memory"); return -1; -- cgit From c710c0671fad507b07cbc2094244fe6f2f909955 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Jan 2005 22:30:54 +0000 Subject: r4718: don't use the deprecated __va_copy() unless va_copy() is unavailable (This used to be commit 603ef69be075821e3ffe2084bb5cfb0bc9cce180) --- source4/lib/snprintf.c | 2 ++ source4/lib/talloc/talloc.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c index 3b04228c42..dbfb046c3d 100644 --- a/source4/lib/snprintf.c +++ b/source4/lib/snprintf.c @@ -83,6 +83,8 @@ #ifndef VA_COPY #ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#elif defined(HAVE___VA_COPY) #define VA_COPY(dest, src) __va_copy(dest, src) #else #define VA_COPY(dest, src) (dest) = (src) diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 4c8cc31028..e05b196592 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -873,6 +873,8 @@ char *talloc_strndup(const void *t, const char *p, size_t n) #ifndef VA_COPY #ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#elif defined(HAVE___VA_COPY) #define VA_COPY(dest, src) __va_copy(dest, src) #else #define VA_COPY(dest, src) (dest) = (src) -- cgit From 449590367c209c69dbfc2d1cb030fcd0833f99c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Jan 2005 22:33:28 +0000 Subject: r4719: snprintf.c is used outside of samba, so don't use our special types (This used to be commit 8033ef6b710df3b5bb2a249db97986b7d4c2e018) --- source4/lib/snprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c index dbfb046c3d..adfd3c4d78 100644 --- a/source4/lib/snprintf.c +++ b/source4/lib/snprintf.c @@ -221,7 +221,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args } break; case DP_S_MIN: - if (isdigit((uint8_t)ch)) { + if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { @@ -241,7 +241,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args } break; case DP_S_MAX: - if (isdigit((uint8_t)ch)) { + if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); -- cgit From cfc10f2a83b7c6190742498f1027256215cd0b31 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Jan 2005 01:21:56 +0000 Subject: r4727: add a reference to the event context to that the destructor don't double free the registered events when the event context is first in the talloc_free() hierarchie fixes a bug with process_model_thread and the talloc_steal(conn, ev) metze (This used to be commit 05c3d1c4a6a6350cc8b5fb2ee8201ae6feed3d3d) --- source4/lib/messaging/messaging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 6975f45c8e..84c9adc874 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -514,7 +514,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id fde.flags = EVENT_FD_READ; fde.handler = messaging_listen_handler; - msg->event.ev = ev; + msg->event.ev = talloc_reference(msg,ev); msg->event.fde = event_add_fd(ev, &fde); talloc_set_destructor(msg, messaging_destructor); -- cgit From 9f676afe3ab19bb0502e6dca45fe0039a2ec285b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Jan 2005 02:54:53 +0000 Subject: r4744: until we decide what to do about attribute aliasing (see my recent samba-technical posting), this is an interim solution that makes us work pretty much like w2k3 does. (This used to be commit 789325145651f2f6fc8716aa4bced83a2eb31994) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 536d1ac005..f813841edb 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -150,12 +150,13 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, continue; } - if (ldb_attr_cmp(attrs[i], "dn") == 0) { + if (ldb_attr_cmp(attrs[i], "dn") == 0 || + ldb_attr_cmp(attrs[i], "distinguishedName") == 0) { struct ldb_message_element el2; struct ldb_val val; el2.flags = 0; - el2.name = talloc_strdup(ret, "dn"); + el2.name = talloc_strdup(ret, attrs[i]); if (!el2.name) { talloc_free(ret); return NULL; @@ -501,7 +502,8 @@ int ltdb_search(struct ldb_module *module, const char *base, } if (tree->operation == LDB_OP_SIMPLE && - ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 && + (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 || + ldb_attr_cmp(tree->u.simple.attr, "distinguishedName") == 0) && !ltdb_has_wildcard(module, tree->u.simple.attr, &tree->u.simple.value)) { /* yay! its a nice simple one */ ret = ltdb_search_dn(module, tree->u.simple.value.data, attrs, res); -- cgit From 21aafc3536cb8a172805f0dd5d23b100f1ecb493 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Jan 2005 10:28:08 +0000 Subject: r4753: added the ability for the generic socket library to handle async connect(). This required a small API change (the addition of a socket_connect_complete() method) (This used to be commit b787dd166f5cca82b3710802eefb41e0a8851fc3) --- source4/lib/socket/socket.c | 8 ++++++++ source4/lib/socket/socket.h | 4 ++++ source4/lib/socket/socket_ipv4.c | 44 +++++++++++++++++++++++++++++++--------- source4/lib/socket/socket_ipv6.c | 39 ++++++++++++++++++++++++++--------- source4/lib/socket/socket_unix.c | 39 ++++++++++++++++++++++++++--------- 5 files changed, 104 insertions(+), 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 9be6faf084..cc43348e79 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -107,6 +107,14 @@ NTSTATUS socket_connect(struct socket_context *sock, return sock->ops->fn_connect(sock, my_address, my_port, server_address, server_port, flags); } +NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags) +{ + if (!sock->ops->fn_connect_complete) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return sock->ops->fn_connect_complete(sock, flags); +} + NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) { if (sock->type != SOCKET_TYPE_STREAM) { diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 7a8d335962..7dd8c0ae17 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -39,6 +39,10 @@ struct socket_ops { const char *server_address, int server_port, uint32_t flags); + /* complete a non-blocking connect */ + NTSTATUS (*fn_connect_complete)(struct socket_context *sock, + uint32_t flags); + /* server ops */ NTSTATUS (*fn_listen)(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 88570512a4..7cf2b73e4e 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -1,7 +1,10 @@ /* Unix SMB/CIFS implementation. + Socket IPv4 functions + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Andrew Tridgell 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 @@ -36,6 +39,34 @@ static void ipv4_tcp_close(struct socket_context *sock) close(sock->fd); } +static NTSTATUS ipv4_tcp_connect_complete(struct socket_context *sock, uint32_t flags) +{ + int error=0, ret; + socklen_t len = sizeof(error); + + /* check for any errors that may have occurred - this is needed + for non-blocking connect */ + ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + if (error != 0) { + return map_nt_error_from_unix(error); + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + + static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, const char *my_address, int my_port, const char *srv_address, int srv_port, @@ -79,18 +110,10 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, return map_nt_error_from_unix(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { - ret = set_blocking(sock->fd, False); - if (ret == -1) { - return map_nt_error_from_unix(errno); - } - } - - sock->state = SOCKET_STATE_CLIENT_CONNECTED; - - return NT_STATUS_OK; + return ipv4_tcp_connect_complete(sock, flags); } + static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) @@ -315,6 +338,7 @@ static const struct socket_ops ipv4_tcp_ops = { .fn_init = ipv4_tcp_init, .fn_connect = ipv4_tcp_connect, + .fn_connect_complete = ipv4_tcp_connect_complete, .fn_listen = ipv4_tcp_listen, .fn_accept = ipv4_tcp_accept, .fn_recv = ipv4_tcp_recv, diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 1685f17572..35b4037ff4 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -50,6 +50,33 @@ static void ipv6_tcp_close(struct socket_context *sock) close(sock->fd); } +static NTSTATUS ipv6_tcp_connect_complete(struct socket_context *sock, uint32_t flags) +{ + int error=0, ret; + socklen_t len = sizeof(error); + + /* check for any errors that may have occurred - this is needed + for non-blocking connect */ + ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + if (error != 0) { + return map_nt_error_from_unix(error); + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, const char *my_address, int my_port, const char *srv_address, int srv_port, @@ -87,16 +114,7 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, return map_nt_error_from_unix(errno); } - if (!(flags & SOCKET_FLAG_BLOCK)) { - ret = set_blocking(sock->fd, False); - if (ret == -1) { - return map_nt_error_from_unix(errno); - } - } - - sock->state = SOCKET_STATE_CLIENT_CONNECTED; - - return NT_STATUS_OK; + return ipv6_tcp_connect_complete(sock, flags); } static NTSTATUS ipv6_tcp_listen(struct socket_context *sock, @@ -333,6 +351,7 @@ static const struct socket_ops ipv6_tcp_ops = { .fn_init = ipv6_tcp_init, .fn_connect = ipv6_tcp_connect, + .fn_connect_complete = ipv6_tcp_connect_complete, .fn_listen = ipv6_tcp_listen, .fn_accept = ipv6_tcp_accept, .fn_recv = ipv6_tcp_recv, diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index e35453e6e0..60a4b9ec48 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -50,6 +50,33 @@ static void unixdom_close(struct socket_context *sock) close(sock->fd); } +static NTSTATUS unixdom_connect_complete(struct socket_context *sock, uint32_t flags) +{ + int error=0, ret; + socklen_t len = sizeof(error); + + /* check for any errors that may have occurred - this is needed + for non-blocking connect */ + ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + if (error != 0) { + return map_nt_error_from_unix(error); + } + + if (!(flags & SOCKET_FLAG_BLOCK)) { + ret = set_blocking(sock->fd, False); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + } + + sock->state = SOCKET_STATE_CLIENT_CONNECTED; + + return NT_STATUS_OK; +} + static NTSTATUS unixdom_connect(struct socket_context *sock, const char *my_address, int my_port, const char *srv_address, int srv_port, @@ -66,21 +93,12 @@ static NTSTATUS unixdom_connect(struct socket_context *sock, srv_addr.sun_family = AF_UNIX; strncpy(srv_addr.sun_path, srv_address, sizeof(srv_addr.sun_path)); - if (!(flags & SOCKET_FLAG_BLOCK)) { - ret = set_blocking(sock->fd, False); - if (ret == -1) { - return NT_STATUS_INVALID_PARAMETER; - } - } - ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (ret == -1) { return unixdom_error(errno); } - sock->state = SOCKET_STATE_CLIENT_CONNECTED; - - return NT_STATUS_OK; + return unixdom_connect_complete(sock, flags); } static NTSTATUS unixdom_listen(struct socket_context *sock, @@ -252,6 +270,7 @@ static const struct socket_ops unixdom_ops = { .fn_init = unixdom_init, .fn_connect = unixdom_connect, + .fn_connect_complete = unixdom_connect_complete, .fn_listen = unixdom_listen, .fn_accept = unixdom_accept, .fn_recv = unixdom_recv, -- cgit From d327eb01bdc5ae196ece3707510629d95a8857b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 15 Jan 2005 10:31:33 +0000 Subject: r4756: a slight tidy up in the events code (This used to be commit d2f76c3671df0b0232982e2fbfd5c049c9fb674f) --- source4/lib/events.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 9f28100a26..54ec4ef927 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -79,12 +79,9 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) { struct event_context *ev; - ev = talloc_p(mem_ctx, struct event_context); + ev = talloc_zero(mem_ctx, struct event_context); if (!ev) return NULL; - /* start off with no events */ - ZERO_STRUCTP(ev); - ev->events = talloc_new(ev); return ev; -- cgit From a7bbb190d9845a74c21369ca32eb8446982477db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 15 Jan 2005 17:24:42 +0000 Subject: r4759: use ldb_attr_cmp() to compare attribute names check required attributes are not deleted on modify operation if the objectclass is deleted then deny the operation if orphan atributes are left behind (This used to be commit 8c11038d67c495f8d5f06cf1fdfe976088864b45) --- source4/lib/ldb/modules/schema.c | 85 ++++++++++++++++++++++-------------- source4/lib/ldb/modules/timestamps.c | 2 +- 2 files changed, 53 insertions(+), 34 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 63d94eed81..85f57fc2eb 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -63,9 +63,14 @@ static struct attribute_syntax attrsyn[] = { #define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); -#define SA_FLAG_RESET 0 -#define SA_FLAG_AUXCLASS 1 -#define SA_FLAG_CHECKED 2 +#define SCHEMA_FLAG_RESET 0 +#define SCHEMA_FLAG_MOD_MASK 0x03 +#define SCHEMA_FLAG_MOD_ADD 0x01 +#define SCHEMA_FLAG_MOD_REPLACE 0x02 +#define SCHEMA_FLAG_MOD_DELETE 0x03 +#define SCHEMA_FLAG_AUXCLASS 0x10 +#define SCHEMA_FLAG_CHECKED 0x20 + struct private_data { struct ldb_context *schema_db; @@ -136,7 +141,7 @@ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, str ldb_search_free(ldb, srch); return -1; } - schema_struct->objectclass_list[j].flags = SA_FLAG_RESET; + schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; } } ldb_search_free(ldb, srch); @@ -162,7 +167,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, "objectclass") == 0) { + if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { schema_struct->objectclass_list_num = msg->elements[i].num_values; schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, @@ -177,11 +182,11 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s if (schema_struct->objectclass_list[k].name == 0) { return -1; } - schema_struct->objectclass_list[k].flags = SA_FLAG_RESET; + schema_struct->objectclass_list[k].flags = msg->elements[i].flags; } } - schema_struct->check_list[j].flags = SA_FLAG_RESET; + schema_struct->check_list[j].flags = msg->elements[i].flags; schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, msg->elements[i].name); if (schema_struct->check_list[j].name == 0) { @@ -243,6 +248,9 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context for (i = 0; i < schema_struct->objectclass_list_num; i++) { char *filter; + if ((schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + continue; + } filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); @@ -251,7 +259,7 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context ok = 0; /* suppose auxiliary classeschema_struct are not required */ - if (schema_struct->objectclass_list[i].flags & SA_FLAG_AUXCLASS) { + if (schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_AUXCLASS) { int d; ok = 1; schema_struct->objectclass_list_num -= 1; @@ -286,11 +294,11 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context is_aux = 0; is_class = 0; - if (strcasecmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = SA_FLAG_AUXCLASS; + if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + is_aux = SCHEMA_FLAG_AUXCLASS; is_class = 1; } - if (strcasecmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -304,23 +312,23 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } else { - if (strcasecmp((*srch)->elements[j].name, "mustContain") == 0 || - strcasecmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(&schema_struct->must, &schema_struct->must_num, - SA_FLAG_RESET, + SCHEMA_FLAG_RESET, &(*srch)->elements[j], schema_struct) != 0) { return -1; } } - if (strcasecmp((*srch)->elements[j].name, "mayContain") == 0 || - strcasecmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(&schema_struct->may, &schema_struct->may_num, - SA_FLAG_RESET, + SCHEMA_FLAG_RESET, &(*srch)->elements[j], schema_struct) != 0) { return -1; @@ -374,8 +382,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->check_list_num; j++) { - if (strcasecmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { - entry_structs->check_list[j].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -392,13 +400,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* now check all others atribs are found in mays */ for (i = 0; i < entry_structs->check_list_num; i++) { - if (entry_structs->check_list[i].flags != SA_FLAG_CHECKED) { + if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { int found; found = 0; for (j = 0; j < entry_structs->may_num; j++) { - if (strcasecmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { - entry_structs->check_list[i].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -484,17 +492,22 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess int found; found = 0; - for (j = 0; j < entry_structs->may_num; j++) { - if (strcasecmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + for (j = 0; j < entry_structs->must_num; j++) { + if (ldb_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } } if ( ! found) { - for (j = 0; j < entry_structs->must_num; j++) { - if (strcasecmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + for (j = 0; j < entry_structs->may_num; j++) { + if (ldb_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; break; } } @@ -507,8 +520,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->check_list_num; j++) { - if (strcasecmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { - modify_structs->check_list[j].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + modify_structs->check_list[j].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } @@ -525,13 +543,14 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess /* now check all others atribs are found in mays */ for (i = 0; i < modify_structs->check_list_num; i++) { - if (modify_structs->check_list[i].flags != SA_FLAG_CHECKED) { + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && + (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { int found; found = 0; for (j = 0; j < modify_structs->may_num; j++) { - if (strcasecmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags = SA_FLAG_CHECKED; + if (ldb_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 4066d231cd..1deeeb218b 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -69,7 +69,7 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, int i; for (i = 0; i < msg->num_elements; i++) { - if (strcasecmp(msg->elements[i].name, attr_name) == 0) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { return 0; } } -- cgit From 1e233e90535188aec8f74b8c30f9f9695ef30f87 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 10:48:46 +0000 Subject: r4775: use schema_attr_cmp wrapper to check for the special dn/distinguishedName case alias (This used to be commit 18cd6cb67404830b8a5d28fa4106dadb275a5222) --- source4/lib/ldb/modules/schema.c | 92 +++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 35 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 85f57fc2eb..114c7f44aa 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -77,26 +77,6 @@ struct private_data { const char *error_string; }; -/* close */ -static int schema_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - -/* search */ -static int schema_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - return ldb_next_search(module, base, scope, expression, attrs, res); -} - -/* search_free */ -static int schema_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - struct attribute_list { int flags; char *name; @@ -113,6 +93,30 @@ struct schema_structures { int may_num; }; +/* This function embedds the knowledge of aliased names. + Currently it handles only dn vs distinguishedNAme as a special case as AD + only have this special alias case, in future we should read the schema + to find out which names have an alias and check for them */ +static int schema_attr_cmp(const char *attr1, const char *attr2) +{ + int ret; + + ret = ldb_attr_cmp(attr1, attr2); + if (ret != 0) { + if (tolower(*attr1) == 'd' && tolower(*attr2) == 'd') { + if ((ldb_attr_cmp("dn", attr1) == 0) && + (ldb_attr_cmp("distinguishedName", attr2) == 0)) { + return 0; + } + if ((ldb_attr_cmp("dn", attr2) == 0) && + (ldb_attr_cmp("distinguishedName", attr1) == 0)) { + return 0; + } + } + } + return ret; +} + static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); @@ -167,7 +171,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { - if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { schema_struct->objectclass_list_num = msg->elements[i].num_values; schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, @@ -294,11 +298,11 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context is_aux = 0; is_class = 0; - if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { is_aux = SCHEMA_FLAG_AUXCLASS; is_class = 1; } - if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -312,8 +316,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } else { - if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || - ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(&schema_struct->must, &schema_struct->must_num, SCHEMA_FLAG_RESET, @@ -323,8 +327,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } } - if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || - ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(&schema_struct->may, &schema_struct->may_num, @@ -343,6 +347,26 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context return 0; } +/* close */ +static int schema_close(struct ldb_module *module) +{ + return ldb_next_close(module); +} + +/* search */ +static int schema_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +/* search_free */ +static int schema_search_free(struct ldb_module *module, struct ldb_message **res) +{ + return ldb_next_search_free(module, res); +} + /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -382,7 +406,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->check_list_num; j++) { - if (ldb_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { + if (schema_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; found = 1; break; @@ -390,7 +414,6 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { - /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is mischema_structing"; talloc_free(entry_structs); return -1; @@ -405,7 +428,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message found = 0; for (j = 0; j < entry_structs->may_num; j++) { - if (ldb_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; found = 1; break; @@ -493,7 +516,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < entry_structs->must_num; j++) { - if (ldb_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); @@ -506,7 +529,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found) { for (j = 0; j < entry_structs->may_num; j++) { - if (ldb_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; break; } @@ -520,7 +543,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->check_list_num; j++) { - if (ldb_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { + if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); @@ -533,7 +556,6 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { - /* TODO: set the error string */ data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; @@ -549,7 +571,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess found = 0; for (j = 0; j < modify_structs->may_num; j++) { - if (ldb_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { + if (schema_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; found = 1; break; -- cgit From 5dbebbe2add359da8c416634e3ec2d8e2569478a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2005 20:48:53 +0000 Subject: r4781: the tolower() in schema.c is a premature optimisation. I suspect the "distinguishedName" checking in that module is incorrect and should be removed, but meanwhile, lets not make it slow down the compile of every other module. (This used to be commit 6534ce650bef7405e0926c9b75b185943429ed18) --- source4/lib/ldb/modules/schema.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 114c7f44aa..7a772d87aa 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include struct attribute_syntax { const char *name; @@ -103,15 +104,13 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) ret = ldb_attr_cmp(attr1, attr2); if (ret != 0) { - if (tolower(*attr1) == 'd' && tolower(*attr2) == 'd') { - if ((ldb_attr_cmp("dn", attr1) == 0) && - (ldb_attr_cmp("distinguishedName", attr2) == 0)) { - return 0; - } - if ((ldb_attr_cmp("dn", attr2) == 0) && - (ldb_attr_cmp("distinguishedName", attr1) == 0)) { - return 0; - } + if ((ldb_attr_cmp("dn", attr1) == 0) && + (ldb_attr_cmp("distinguishedName", attr2) == 0)) { + return 0; + } + if ((ldb_attr_cmp("dn", attr2) == 0) && + (ldb_attr_cmp("distinguishedName", attr1) == 0)) { + return 0; } } return ret; -- cgit From 63f79d11b802bebe105eccd385fab452e4a68e39 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 22:30:38 +0000 Subject: r4784: finally make schema module use a single ldb add the new test-schema test (This used to be commit 42a20f6fa4073fc5ea1ca6254137a4ef53caee01) --- source4/lib/ldb/Makefile.ldb | 6 +- source4/lib/ldb/modules/schema.c | 65 +-- source4/lib/ldb/tests/schema-add-test.ldif | 66 +++ source4/lib/ldb/tests/schema-mod-test.ldif | 25 ++ source4/lib/ldb/tests/schema.ldif | 634 +++++++++++++++++++++++++++++ source4/lib/ldb/tests/test-schema.sh | 20 + 6 files changed, 764 insertions(+), 52 deletions(-) create mode 100644 source4/lib/ldb/tests/schema-add-test.ldif create mode 100644 source4/lib/ldb/tests/schema-mod-test.ldif create mode 100644 source4/lib/ldb/tests/schema.ldif create mode 100755 source4/lib/ldb/tests/test-schema.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 29d33007da..791a345f72 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -96,7 +96,11 @@ test-ldap: @echo "STARTING LDAP BACKEND TEST" tests/test-ldap.sh -test: test-tdb test-ldap +test-schema: + @echo "STARTING SCHEMA MODULE TEST" + tests/test-schema.sh + +test: test-tdb test-ldap test-schema gcov: gcov -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 7a772d87aa..97cc26a0dd 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -32,6 +32,7 @@ * Author: Simo Sorce */ +#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" @@ -74,7 +75,6 @@ static struct attribute_syntax attrsyn[] = { struct private_data { - struct ldb_context *schema_db; const char *error_string; }; @@ -273,6 +273,7 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } if (!ok) { /* Schema Violation: Object Class Description Not Found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Objectclass %s not found.\n", schema_struct->objectclass_list[i].name); data->error_string = "ObjectClass not found"; return -1; } @@ -280,11 +281,13 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } else { if (ret < 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); data->error_string = "Internal error. Error retrieving schema objectclass"; return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); data->error_string = "Internal error. Too many records searching for schema objectclass"; return -1; } @@ -393,7 +396,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + ret = get_attr_list_recursive(module, module->ldb, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -413,7 +416,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { - data->error_string = "Objectclass violation, a required attribute is mischema_structing"; + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", entry_structs->must[i].name); + data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } @@ -435,6 +439,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", entry_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -487,7 +492,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* find all modify objectclasses recursively if any objectclass is being added */ - ret = get_attr_list_recursive(module, data->schema_db, modify_structs); + ret = get_attr_list_recursive(module, module->ldb, modify_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -501,7 +506,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, data->schema_db, entry_structs); + ret = get_attr_list_recursive(module, module->ldb, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -517,6 +522,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess for (j = 0; j < entry_structs->must_num; j++) { if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->check_list[i].name); data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); return -1; @@ -544,6 +550,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess for (j = 0; j < modify_structs->check_list_num; j++) { if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation: trying to delete a required attribute"; talloc_free(entry_structs); return -1; @@ -555,6 +562,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; @@ -578,6 +586,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } if ( ! found ) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", modify_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -641,9 +650,6 @@ static const struct ldb_module_ops schema_ops = { schema_errstring, }; -#define SCHEMA_PREFIX "schema:" -#define SCHEMA_PREFIX_LEN 7 - #ifdef HAVE_DLOPEN_DISABLED struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) #else @@ -652,58 +658,15 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio { struct ldb_module *ctx; struct private_data *data; - char *db_url = NULL; - int i; ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } - if (options) { - for (i = 0; options[i] != NULL; i++) { - if (strncmp(options[i], SCHEMA_PREFIX, SCHEMA_PREFIX_LEN) == 0) { - db_url = talloc_strdup(ctx, &options[i][SCHEMA_PREFIX_LEN]); - SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); - } - } - } - - if (!db_url) { /* search if it is defined in the calling ldb */ - int ret; - const char * attrs[] = { "@SCHEMADB", NULL }; - struct ldb_message **msgs; - - ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", (const char * const *)attrs, &msgs); - if (ret == 0) { - ldb_debug(ldb, LDB_DEBUG_TRACE, "Schema DB not found\n"); - ldb_search_free(ldb, msgs); - return NULL; - } else { - if (ret < 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for schema db, bailing out!\n", ldb_errstring(ldb)); - ldb_search_free(ldb, msgs); - return NULL; - } - if (ret > 1) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); - ldb_search_free(ldb, msgs); - return NULL; - } - - db_url = talloc_strndup(ctx, msgs[0]->elements[0].values[0].data, msgs[0]->elements[0].values[0].length); - SCHEMA_TALLOC_CHECK(ctx, db_url, NULL); - } - - ldb_search_free(ldb, msgs); - } - data = talloc(ctx, struct private_data); SCHEMA_TALLOC_CHECK(ctx, data, NULL); - data->schema_db = ldb_connect(db_url, 0, NULL); - SCHEMA_TALLOC_CHECK(ctx, data->schema_db, NULL); - data->error_string = NULL; ctx->private_data = data; ctx->ldb = ldb; diff --git a/source4/lib/ldb/tests/schema-add-test.ldif b/source4/lib/ldb/tests/schema-add-test.ldif new file mode 100644 index 0000000000..997b801d84 --- /dev/null +++ b/source4/lib/ldb/tests/schema-add-test.ldif @@ -0,0 +1,66 @@ +dn: CN=Users,DC=schema,DC=test +objectClass: top +objectClass: container +cn: Users +description: Default container for upgraded user accounts +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +uSNChanged: 1 +showInAdvancedViewOnly: FALSE +name: Users +objectGUID: b847056a-9934-d87b-8a1a-99fabe0863c8 +systemFlags: 0x8c000000 +objectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +nTSecurityDescriptor: foo + +dn: CN=Administrator,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: user +cn: Administrator +description: Built-in account for administering the computer/domain +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +memberOf: CN=Group Policy Creator Owners,CN=Users,DC=schema,DC=test +memberOf: CN=Domain Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Enterprise Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Schema Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Administrators,CN=Builtin,DC=schema,DC=test +uSNChanged: 1 +name: Administrator +objectGUID: 6c02f98c-46c6-aa38-5f13-a510cac04e6c +userAccountControl: 0x10200 +badPwdCount: 0 +codePage: 0 +countryCode: 0 +badPasswordTime: 0 +lastLogoff: 0 +lastLogon: 0 +pwdLastSet: 0 +primaryGroupID: 513 +objectSid: S-1-5-21-43662522-77495566-38969261-500 +adminCount: 1 +accountExpires: -1 +logonCount: 0 +sAMAccountName: Administrator +sAMAccountType: 0x30000000 +objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +unicodePwd: samba +nTSecurityDescriptor: foo + +dn: CN=Test,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: test +cn: Test +description: This is a test +objectCategory: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +nTSecurityDescriptor: foo +instanceType: 4 + diff --git a/source4/lib/ldb/tests/schema-mod-test.ldif b/source4/lib/ldb/tests/schema-mod-test.ldif new file mode 100644 index 0000000000..8e36de7bf5 --- /dev/null +++ b/source4/lib/ldb/tests/schema-mod-test.ldif @@ -0,0 +1,25 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +replace: description +description: this test must not fail + +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: description +# this test must not fail + +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: description +description: this test must not fail + +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: foo +foo: this test must fail + +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: nTSecurityDescriptor +# this test must fail + diff --git a/source4/lib/ldb/tests/schema.ldif b/source4/lib/ldb/tests/schema.ldif new file mode 100644 index 0000000000..2661ae30c5 --- /dev/null +++ b/source4/lib/ldb/tests/schema.ldif @@ -0,0 +1,634 @@ +dn: @INDEXLIST +@IDXATTR: name +@IDXATTR: sAMAccountName +@IDXATTR: objectSid +@IDXATTR: objectClass +@IDXATTR: member +@IDXATTR: unixID +@IDXATTR: unixName +@IDXATTR: privilege + +dn: @ATTRIBUTES +realm: CASE_INSENSITIVE +userPrincipalName: CASE_INSENSITIVE +servicePrincipalName: CASE_INSENSITIVE +name: CASE_INSENSITIVE WILDCARD +dn: CASE_INSENSITIVE WILDCARD +sAMAccountName: CASE_INSENSITIVE WILDCARD +objectClass: CASE_INSENSITIVE +unicodePwd: HIDDEN +ntPwdHash: HIDDEN +ntPwdHistory: HIDDEN +lmPwdHash: HIDDEN +lmPwdHistory: HIDDEN +createTimestamp: HIDDEN +modifyTimestamp: HIDDEN + +dn: @SUBCLASSES +top: domain +top: person +top: group +domain: domainDNS +domain: builtinDomain +person: organizationalPerson +organizationalPerson: user +user: computer +template: userTemplate +template: groupTemplate + +dn: @MODULES +@MODULE: timestamps +@MODULE: schema + +# Top, Schema, Configuration, schema, test +dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Top +distinguishedName: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175509.0Z +whenChanged: 20050116175509.0Z +uSNCreated: 1437 +subClassOf: top +governsID: 2.5.6.0 +mayContain: msDS-ObjectReferenceBL +rDNAttID: cn +uSNChanged: 1437 +showInAdvancedViewOnly: TRUE +adminDisplayName: Top +adminDescription: Top +objectClassCategory: 2 +lDAPDisplayName: top +name: Top +objectGUID: 8b12f9c3-008f-2b4f-b32b-dddd2e396ea8 +schemaIDGUID: dafbc8ff-64e9-d2cb-4569-4ba91d60aa83 +systemOnly: TRUE +systemPossSuperiors: lostAndFound +systemMayContain: url +systemMayContain: wWWHomePage +systemMayContain: whenCreated +systemMayContain: whenChanged +systemMayContain: wellKnownObjects +systemMayContain: wbemPath +systemMayContain: uSNSource +systemMayContain: uSNLastObjRem +systemMayContain: USNIntersite +systemMayContain: uSNDSALastObjRemoved +systemMayContain: uSNCreated +systemMayContain: uSNChanged +systemMayContain: systemFlags +systemMayContain: subSchemaSubEntry +systemMayContain: subRefs +systemMayContain: structuralObjectClass +systemMayContain: siteObjectBL +systemMayContain: serverReferenceBL +systemMayContain: sDRightsEffective +systemMayContain: revision +systemMayContain: repsTo +systemMayContain: repsFrom +systemMayContain: directReports +systemMayContain: replUpToDateVector +systemMayContain: replPropertyMetaData +systemMayContain: name +systemMayContain: queryPolicyBL +systemMayContain: proxyAddresses +systemMayContain: proxiedObjectName +systemMayContain: possibleInferiors +systemMayContain: partialAttributeSet +systemMayContain: partialAttributeDeletionList +systemMayContain: otherWellKnownObjects +systemMayContain: objectVersion +systemMayContain: objectGUID +systemMayContain: distinguishedName +systemMayContain: nonSecurityMemberBL +systemMayContain: netbootSCPBL +systemMayContain: ownerBL +systemMayContain: msDS-ReplValueMetaData +systemMayContain: msDS-ReplAttributeMetaData +systemMayContain: msDS-NonMembersBL +systemMayContain: msDS-NCReplOutboundNeighbors +systemMayContain: msDS-NCReplInboundNeighbors +systemMayContain: msDS-NCReplCursors +systemMayContain: msDS-TasksForAzRoleBL +systemMayContain: msDS-TasksForAzTaskBL +systemMayContain: msDS-OperationsForAzRoleBL +systemMayContain: msDS-OperationsForAzTaskBL +systemMayContain: msDS-MembersForAzRoleBL +systemMayContain: msDs-masteredBy +systemMayContain: mS-DS-ConsistencyGuid +systemMayContain: mS-DS-ConsistencyChildCount +systemMayContain: msDS-Approx-Immed-Subordinates +systemMayContain: msCOM-PartitionSetLink +systemMayContain: msCOM-UserLink +systemMayContain: modifyTimeStamp +systemMayContain: masteredBy +systemMayContain: managedObjects +systemMayContain: lastKnownParent +systemMayContain: isPrivilegeHolder +systemMayContain: memberOf +systemMayContain: isDeleted +systemMayContain: isCriticalSystemObject +systemMayContain: showInAdvancedViewOnly +systemMayContain: fSMORoleOwner +systemMayContain: fRSMemberReferenceBL +systemMayContain: frsComputerReferenceBL +systemMayContain: fromEntry +systemMayContain: flags +systemMayContain: extensionName +systemMayContain: dSASignature +systemMayContain: dSCorePropagationData +systemMayContain: displayNamePrintable +systemMayContain: displayName +systemMayContain: description +systemMayContain: createTimeStamp +systemMayContain: cn +systemMayContain: canonicalName +systemMayContain: bridgeheadServerListBL +systemMayContain: allowedChildClassesEffective +systemMayContain: allowedChildClasses +systemMayContain: allowedAttributesEffective +systemMayContain: allowedAttributes +systemMayContain: adminDisplayName +systemMayContain: adminDescription +systemMustContain: objectClass +systemMustContain: objectCategory +systemMustContain: nTSecurityDescriptor +systemMustContain: instanceType +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,${BASEDN} +defaultObjectCategory: CN=Top,CN=Schema,CN=Configuration,${BASEDN} + +# Container, Schema, Configuration, schema, test +dn: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Container +distinguishedName: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1113 +subClassOf: top +governsID: 1.2.840.113556.1.3.23 +mayContain: msDS-ObjectReference +rDNAttID: cn +uSNChanged: 1114 +showInAdvancedViewOnly: TRUE +adminDisplayName: Container +adminDescription: Container +objectClassCategory: 1 +lDAPDisplayName: container +name: Container +objectGUID: 48a16bf7-0128-6605-ad1a-9f5ab97b0b62 +schemaIDGUID: 3f619f8c-f7d6-6b1b-8674-b4f91b0e3755 +systemOnly: FALSE +systemPossSuperiors: msDS-AzScope +systemPossSuperiors: msDS-AzApplication +systemPossSuperiors: msDS-AzAdminManager +systemPossSuperiors: subnet +systemPossSuperiors: server +systemPossSuperiors: nTDSService +systemPossSuperiors: domainDNS +systemPossSuperiors: organization +systemPossSuperiors: configuration +systemPossSuperiors: container +systemPossSuperiors: organizationalUnit +systemMayContain: schemaVersion +systemMayContain: defaultClassStore +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Class-Schema, Schema, Configuration, schema, test +dn: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Class-Schema +distinguishedName: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175530.0Z +whenChanged: 20050116175530.0Z +uSNCreated: 673 +subClassOf: top +governsID: 1.2.840.113556.1.3.13 +rDNAttID: cn +uSNChanged: 674 +showInAdvancedViewOnly: TRUE +adminDisplayName: Class-Schema +adminDescription: Class-Schema +objectClassCategory: 1 +lDAPDisplayName: classSchema +name: Class-Schema +objectGUID: 63151723-143e-98ab-2e14-f6df3e9c8458 +schemaIDGUID: 44cd522f-747f-e071-ff4b-b8beddfaae75 +systemOnly: FALSE +systemPossSuperiors: dMD +systemMayContain: systemPossSuperiors +systemMayContain: systemOnly +systemMayContain: systemMustContain +systemMayContain: systemMayContain +systemMayContain: systemAuxiliaryClass +systemMayContain: schemaFlagsEx +systemMayContain: rDNAttID +systemMayContain: possSuperiors +systemMayContain: mustContain +systemMayContain: msDs-Schema-Extensions +systemMayContain: msDS-IntId +systemMayContain: mayContain +systemMayContain: lDAPDisplayName +systemMayContain: isDefunct +systemMayContain: defaultSecurityDescriptor +systemMayContain: defaultHidingValue +systemMayContain: classDisplayName +systemMayContain: auxiliaryClass +systemMustContain: subClassOf +systemMustContain: schemaIDGUID +systemMustContain: objectClassCategory +systemMustContain: governsID +systemMustContain: defaultObjectCategory +systemMustContain: cn +defaultSecurityDescriptor: D:S: +systemFlags: 134217744 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Person, Schema, Configuration, schema, test +dn: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Person +distinguishedName: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1093 +subClassOf: top +governsID: 2.5.6.6 +mayContain: attributeCertificateAttribute +rDNAttID: cn +uSNChanged: 1094 +showInAdvancedViewOnly: TRUE +adminDisplayName: Person +adminDescription: Person +objectClassCategory: 0 +lDAPDisplayName: person +name: Person +objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 +schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: container +systemMayContain: userPassword +systemMayContain: telephoneNumber +systemMayContain: sn +systemMayContain: serialNumber +systemMayContain: seeAlso +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Organizational-Person, Schema, Configuration, schema, test +dn: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Organizational-Person +distinguishedName: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175533.0Z +whenChanged: 20050116175533.0Z +uSNCreated: 795 +subClassOf: person +governsID: 2.5.6.7 +mayContain: houseIdentifier +mayContain: msExchHouseIdentifier +mayContain: homePostalAddress +rDNAttID: cn +uSNChanged: 796 +showInAdvancedViewOnly: TRUE +adminDisplayName: Organizational-Person +adminDescription: Organizational-Person +objectClassCategory: 0 +lDAPDisplayName: organizationalPerson +name: Organizational-Person +objectGUID: 91aaede0-136e-c1a0-9ac0-5ddd606a0cfc +schemaIDGUID: 6f71a564-de69-3971-c169-528d111a9f27 +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: organization +systemPossSuperiors: container +systemMayContain: x121Address +systemMayContain: comment +systemMayContain: title +systemMayContain: co +systemMayContain: primaryTelexNumber +systemMayContain: telexNumber +systemMayContain: teletexTerminalIdentifier +systemMayContain: street +systemMayContain: st +systemMayContain: registeredAddress +systemMayContain: preferredDeliveryMethod +systemMayContain: postalCode +systemMayContain: postalAddress +systemMayContain: postOfficeBox +systemMayContain: thumbnailPhoto +systemMayContain: physicalDeliveryOfficeName +systemMayContain: pager +systemMayContain: otherPager +systemMayContain: otherTelephone +systemMayContain: mobile +systemMayContain: otherMobile +systemMayContain: primaryInternationalISDNNumber +systemMayContain: ipPhone +systemMayContain: otherIpPhone +systemMayContain: otherHomePhone +systemMayContain: homePhone +systemMayContain: otherFacsimileTelephoneNumber +systemMayContain: personalTitle +systemMayContain: middleName +systemMayContain: otherMailbox +systemMayContain: ou +systemMayContain: o +systemMayContain: mhsORAddress +systemMayContain: msDS-AllowedToDelegateTo +systemMayContain: manager +systemMayContain: thumbnailLogo +systemMayContain: l +systemMayContain: internationalISDNNumber +systemMayContain: initials +systemMayContain: givenName +systemMayContain: generationQualifier +systemMayContain: facsimileTelephoneNumber +systemMayContain: employeeID +systemMayContain: mail +systemMayContain: division +systemMayContain: destinationIndicator +systemMayContain: department +systemMayContain: c +systemMayContain: countryCode +systemMayContain: company +systemMayContain: assistant +systemMayContain: streetAddress +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# User, Schema, Configuration, schema, test +dn: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: User +distinguishedName: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175549.0Z +whenChanged: 20050116175549.0Z +uSNCreated: 1442 +subClassOf: organizationalPerson +governsID: 1.2.840.113556.1.5.9 +mayContain: x500uniqueIdentifier +mayContain: userSMIMECertificate +mayContain: userPKCS12 +mayContain: uid +mayContain: secretary +mayContain: roomNumber +mayContain: preferredLanguage +mayContain: photo +mayContain: labeledURI +mayContain: jpegPhoto +mayContain: homePostalAddress +mayContain: givenName +mayContain: employeeType +mayContain: employeeNumber +mayContain: displayName +mayContain: departmentNumber +mayContain: carLicense +mayContain: audio +rDNAttID: cn +uSNChanged: 1442 +showInAdvancedViewOnly: TRUE +adminDisplayName: User +adminDescription: User +objectClassCategory: 1 +lDAPDisplayName: user +name: User +objectGUID: 2cc46512-6733-eb01-ce05-213403264ea4 +schemaIDGUID: e8a42693-9d99-2091-5554-eef0548c0b65 +systemOnly: FALSE +systemPossSuperiors: builtinDomain +systemPossSuperiors: organizationalUnit +systemPossSuperiors: domainDNS +systemMayContain: pager +systemMayContain: o +systemMayContain: mobile +systemMayContain: manager +systemMayContain: mail +systemMayContain: initials +systemMayContain: homePhone +systemMayContain: businessCategory +systemMayContain: userCertificate +systemMayContain: userWorkstations +systemMayContain: userSharedFolderOther +systemMayContain: userSharedFolder +systemMayContain: userPrincipalName +systemMayContain: userParameters +systemMayContain: userAccountControl +systemMayContain: unicodePwd +systemMayContain: terminalServer +systemMayContain: servicePrincipalName +systemMayContain: scriptPath +systemMayContain: pwdLastSet +systemMayContain: profilePath +systemMayContain: primaryGroupID +systemMayContain: preferredOU +systemMayContain: otherLoginWorkstations +systemMayContain: operatorCount +systemMayContain: ntPwdHistory +systemMayContain: networkAddress +systemMayContain: msRASSavedFramedRoute +systemMayContain: msRASSavedFramedIPAddress +systemMayContain: msRASSavedCallbackNumber +systemMayContain: msRADIUSServiceType +systemMayContain: msRADIUSFramedRoute +systemMayContain: msRADIUSFramedIPAddress +systemMayContain: msRADIUSCallbackNumber +systemMayContain: msNPSavedCallingStationID +systemMayContain: msNPCallingStationID +systemMayContain: msNPAllowDialin +systemMayContain: mSMQSignCertificatesMig +systemMayContain: mSMQSignCertificates +systemMayContain: mSMQDigestsMig +systemMayContain: mSMQDigests +systemMayContain: msIIS-FTPRoot +systemMayContain: msIIS-FTPDir +systemMayContain: msDS-User-Account-Control-Computed +systemMayContain: msDS-Site-Affinity +systemMayContain: mS-DS-CreatorSID +systemMayContain: msDS-Cached-Membership-Time-Stamp +systemMayContain: msDS-Cached-Membership +systemMayContain: msDRM-IdentityCertificate +systemMayContain: msCOM-UserPartitionSetLink +systemMayContain: maxStorage +systemMayContain: logonWorkstation +systemMayContain: logonHours +systemMayContain: logonCount +systemMayContain: lockoutTime +systemMayContain: localeID +systemMayContain: lmPwdHistory +systemMayContain: lastLogonTimestamp +systemMayContain: lastLogon +systemMayContain: lastLogoff +systemMayContain: homeDrive +systemMayContain: homeDirectory +systemMayContain: groupsToIgnore +systemMayContain: groupPriority +systemMayContain: groupMembershipSAM +systemMayContain: dynamicLDAPServer +systemMayContain: desktopProfile +systemMayContain: defaultClassStore +systemMayContain: dBCSPwd +systemMayContain: controlAccessRights +systemMayContain: codePage +systemMayContain: badPwdCount +systemMayContain: badPasswordTime +systemMayContain: adminCount +systemMayContain: aCSPolicyName +systemMayContain: accountExpires +systemAuxiliaryClass: securityPrincipal +systemAuxiliaryClass: mailRecipient +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a54-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a56-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;RPWP;77B5B886-944A-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B2-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B3-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;;RS)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;;RS)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;;RS)(A;;RC;;;AU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;;AU)(OA;;RP;77B5B886-944A-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;E45795B3-9455-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;AU)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)(OA;;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;;RS)(OA;;RPWP;bf967a7f-0de6-11d0-a285-00aa003049e2;;CA)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(OA;;WPRP;6db69a1c-9422-11d1-aebd-0000f80367c1;;S-1-5-32-561) +systemFlags: 16 +defaultHidingValue: FALSE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Security-Principal, Schema, Configuration, schema, test +dn: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Security-Principal +distinguishedName: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175546.0Z +whenChanged: 20050116175546.0Z +uSNCreated: 1406 +subClassOf: top +governsID: 1.2.840.113556.1.5.6 +rDNAttID: cn +uSNChanged: 1406 +showInAdvancedViewOnly: TRUE +adminDisplayName: Security-Principal +adminDescription: Security-Principal +objectClassCategory: 3 +lDAPDisplayName: securityPrincipal +name: Security-Principal +objectGUID: d1a6ae33-f6d5-197f-93d6-923d07d64c1a +schemaIDGUID: eb3adbfa-fb52-71a6-054f-b077e32c73f1 +systemOnly: FALSE +systemMayContain: supplementalCredentials +systemMayContain: sIDHistory +systemMayContain: securityIdentifier +systemMayContain: sAMAccountType +systemMayContain: rid +systemMayContain: tokenGroupsNoGCAcceptable +systemMayContain: tokenGroupsGlobalAndUniversal +systemMayContain: tokenGroups +systemMayContain: nTSecurityDescriptor +systemMayContain: msDS-KeyVersionNumber +systemMayContain: altSecurityIdentities +systemMayContain: accountNameHistory +systemMustContain: sAMAccountName +systemMustContain: objectSid +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Mail-Recipient, Schema, Configuration, schema, test +dn: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Mail-Recipient +distinguishedName: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175550.0Z +whenChanged: 20050116175550.0Z +uSNCreated: 1222 +subClassOf: top +governsID: 1.2.840.113556.1.3.46 +mayContain: userSMIMECertificate +mayContain: secretary +mayContain: msExchLabeledURI +mayContain: msExchAssistantName +mayContain: labeledURI +rDNAttID: cn +uSNChanged: 1222 +showInAdvancedViewOnly: TRUE +adminDisplayName: Mail-Recipient +adminDescription: Mail-Recipient +objectClassCategory: 3 +lDAPDisplayName: mailRecipient +name: Mail-Recipient +objectGUID: 79f6fa6e-c08d-5c1f-47ff-6b33be595f50 +schemaIDGUID: bcdded89-7f72-0166-da62-08647c98fcf9 +systemOnly: FALSE +systemPossSuperiors: container +systemMayContain: userCertificate +systemMayContain: userCert +systemMayContain: textEncodedORAddress +systemMayContain: telephoneNumber +systemMayContain: showInAddressBook +systemMayContain: legacyExchangeDN +systemMayContain: garbageCollPeriod +systemMayContain: info +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Test, Schema, Configuration, schema, test +dn: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Test +distinguishedName: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1093 +subClassOf: top +governsID: 2.5.6.6 +mayContain: test +rDNAttID: cn +uSNChanged: 1094 +showInAdvancedViewOnly: TRUE +adminDisplayName: Test +adminDescription: Test +objectClassCategory: 0 +lDAPDisplayName: test +name: Test +objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 +schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: container +systemMayContain: description +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + diff --git a/source4/lib/ldb/tests/test-schema.sh b/source4/lib/ldb/tests/test-schema.sh new file mode 100755 index 0000000000..5423c7eff9 --- /dev/null +++ b/source4/lib/ldb/tests/test-schema.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +export LDB_URL="tdb://schema.ldb" + +rm -f schema.ldb + +echo "LDB_URL: $LDB_URL" + +echo "Adding schema" +$VALGRIND bin/ldbadd tests/schema.ldif || exit 1 + +echo "Adding few test elements (no failure expected here)" +$VALGRIND bin/ldbadd tests/schema-add-test.ldif || exit 1 + +echo "Modifying elements (2 failures expected here)" +$VALGRIND bin/ldbmodify tests/schema-mod-test.ldif + +echo "Showing modified record" +$VALGRIND bin/ldbsearch '(cn=Test)' || exit 1 + -- cgit From 9f3d73430828bdc94ae59cb2db1c3ba79c710ab4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 16 Jan 2005 22:41:43 +0000 Subject: r4786: forgot to commit the exclusion for schema checking against our control entries (This used to be commit e895fcf4a33aeaf228d8b4b367c4e768506275bb) --- source4/lib/ldb/modules/schema.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 97cc26a0dd..a56e71ef7a 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -384,6 +384,10 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message Free all structures and commit the change */ + if (msg->dn[0] == '@') { /* do not check on our control entries */ + return ldb_next_add_record(module, msg); + } + entry_structs = talloc(module, struct schema_structures); if (!entry_structs) { return -1; @@ -471,6 +475,10 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ + if (msg->dn[0] == '@') { /* do not check on our control entries */ + return ldb_next_modify_record(module, msg); + } + /* allocate object structs */ entry_structs = talloc(module, struct schema_structures); if (!entry_structs) { -- cgit From 7b79694eadc288592729567c3caa7c70f6662760 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 16 Jan 2005 23:21:52 +0000 Subject: r4790: added type checking helper macros in talloc. These take advantage of the type names that talloc already keeps around for pointers, and allows the user to type check void* private pointers. It can also be used to implement polymorphism in C, as I'm sure someone would have pointed out to me sooner or later :-) (This used to be commit c283e1a3efac3a92e29a35856e20eb61ef4c221e) --- source4/lib/talloc/talloc.c | 19 ++++++++++++++ source4/lib/talloc/talloc.h | 14 ++++++---- source4/lib/talloc/talloc_guide.txt | 32 +++++++++++++++++++++++ source4/lib/talloc/testsuite.c | 51 ++++++++++++++++++++++++++++++++++--- 4 files changed, 107 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index e05b196592..f6f7e899d1 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -424,6 +424,23 @@ const char *talloc_get_name(const void *ptr) return "UNNAMED"; } + +/* + check if a pointer has the given name. If it does, return the pointer, + otherwise return NULL +*/ +void *talloc_check_name(const void *ptr, const char *name) +{ + const char *pname; + if (ptr == NULL) return NULL; + pname = talloc_get_name(ptr); + if (pname == name || strcmp(pname, name) == 0) { + return discard_const_p(void, ptr); + } + return NULL; +} + + /* this is for compatibility with older versions of talloc */ @@ -1029,3 +1046,5 @@ void *talloc_autofree_context(void) } return cleanup_context; } + + diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 607ca4ca47..0a98881054 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -37,7 +37,7 @@ typedef void TALLOC_CTX; #endif /* useful macros for creating type checked pointers */ -#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type ": " __location__) +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) #define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) @@ -45,11 +45,11 @@ typedef void TALLOC_CTX; #define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) #define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) -#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, __location__) -#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, __location__) +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) #define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) -#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, __location__) +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) #define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) #define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) @@ -62,6 +62,9 @@ typedef void TALLOC_CTX; #define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) #define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) + #if TALLOC_DEPRECATED #define talloc_zero_p(ctx, type) talloc_zero(ctx, type) @@ -76,7 +79,7 @@ typedef void TALLOC_CTX; #endif -/* The following definitions come from lib/talloc.c */ +/* The following definitions come from talloc.c */ void *_talloc(const void *context, size_t size); void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); void talloc_increase_ref_count(const void *ptr); @@ -88,6 +91,7 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); void *talloc_named_const(const void *context, size_t size, const char *name); const char *talloc_get_name(const void *ptr); +void *talloc_check_name(const void *ptr, const char *name); void talloc_report_depth(const void *ptr, FILE *f, int depth); void *talloc_parent(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 30b7f64d67..927bd366fd 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -512,3 +512,35 @@ void *talloc_autofree_context(void); This is a handy utility function that returns a talloc context which will be automatically freed on program exit. This can be used to reduce the noise in memory leak reports. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_check_name(const void *ptr, const char *name); + +This function checks if a pointer has the specified name. If it does +then the pointer is returned. It it doesn't then NULL is returned. + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_get_type(const void *ptr, type); + +This macro allows you to do type checking on talloc pointers. It is +particularly useful for void* private pointers. It is equivalent to +this: + + (type *)talloc_check_name(ptr, #type) + + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_set_type(const void *ptr, type); + +This macro allows you to force the name of a pointer to be a +particular type. This can be used in conjunction with +talloc_get_type() to do type checking on void* pointers. + +It is equivalent to this: + talloc_set_name_const(ptr, #type) + + + + diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index bc1c18fdc1..4a1074e045 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -609,6 +609,48 @@ static BOOL test_realloc_child(void) return True; } + +/* + test type checking +*/ +static BOOL test_type(void) +{ + void *root; + struct el1 { + int count; + }; + struct el2 { + int count; + }; + struct el1 *el1; + + printf("TESTING talloc type checking\n"); + + root = talloc_new(NULL); + + el1 = talloc(root, struct el1); + + el1->count = 1; + + if (talloc_get_type(el1, struct el1) != el1) { + printf("type check failed on el1\n"); + return False; + } + if (talloc_get_type(el1, struct el2) != NULL) { + printf("type check failed on el1 with el2\n"); + return False; + } + talloc_set_type(el1, struct el2); + if (talloc_get_type(el1, struct el2) != el1) { + printf("type set failed on el1 with el2\n"); + return False; + } + + talloc_free(root); + + return True; +} + /* test steal */ @@ -664,13 +706,13 @@ static BOOL test_steal(void) } /* - test ldb alloc fn + test talloc_realloc_fn */ -static BOOL test_ldb(void) +static BOOL test_realloc_fn(void) { void *root, *p1; - printf("TESTING LDB\n"); + printf("TESTING talloc_realloc_fn\n"); root = talloc_new(NULL); @@ -774,7 +816,8 @@ BOOL torture_local_talloc(void) ret &= test_realloc_child(); ret &= test_steal(); ret &= test_unref_reparent(); - ret &= test_ldb(); + ret &= test_realloc_fn(); + ret &= test_type(); if (ret) { ret &= test_speed(); } -- cgit From 6717dcca765e5286a36d89eebc5da2d167bcbef2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Jan 2005 02:52:10 +0000 Subject: r4793: minor doc updates (This used to be commit ad1af519eb1a138e44cc94676f845b8ba65e3371) --- source4/lib/talloc/talloc_guide.txt | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 927bd366fd..eae6c5e564 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -32,10 +32,9 @@ If you think about this, then what this effectively gives you is an n-ary tree, where you can free any part of the tree with talloc_free(). -If you find this confusing, then I suggest you run the LOCAL-TALLOC -smbtorture test to watch talloc in action. You may also like to add -your own tests to source/lib/talloc/testsuite.c to clarify how some -particular situation is handled. +If you find this confusing, then I suggest you run the testsuite to +watch talloc in action. You may also like to add your own tests to +testsuite.c to clarify how some particular situation is handled. Performance @@ -74,6 +73,7 @@ well. Alternatively you can free just the child. The context argument to talloc() can be NULL, in which case a new top level context is created. + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_size(const void *context, size_t size); @@ -81,12 +81,6 @@ The function talloc_size() should be used when you don't have a convenient type to pass to talloc(). Unlike talloc(), it is not type safe (as it returns a void *), so you are on your own for type checking. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -void *talloc_p(const void *context, type); - -talloc_p() is a alias for talloc(). It only exists as a backwards -compatibity macro for code from the bad old days when talloc() was not -type safe. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- int talloc_free(void *ptr); @@ -491,10 +485,13 @@ The talloc_array() macro is equivalent to: except that it provides integer overflow protection for the multiply, returning NULL if the multiply overflows. + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_array_size(const void *ctx, size_t size, uint_t count); -The talloc_array_size() function is useful when the type is not known +The talloc_array_size() function is useful when the type is not +known. It operates in the same way as talloc_array(), but takes a size +instead of a type. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -506,6 +503,7 @@ implementation encapsulates the functionality of malloc(), free() and realloc() in one call, which is why it is useful to be able to pass around a single function pointer. + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_autofree_context(void); @@ -540,7 +538,3 @@ talloc_get_type() to do type checking on void* pointers. It is equivalent to this: talloc_set_name_const(ptr, #type) - - - - -- cgit From ec6f6aeda18f905ba58a86f61b8eabf306ed22e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Jan 2005 11:54:22 +0000 Subject: r4801: remove the two bogus ctype.h includes (This used to be commit b221c3dbb9a7af88f917562b6f907fd0617eb05f) --- source4/lib/ldb/modules/schema.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index a56e71ef7a..912c8657d2 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -32,11 +32,9 @@ * Author: Simo Sorce */ -#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include struct attribute_syntax { const char *name; -- cgit From 8451b2658ca0f44f2683bf8045a9232a4a8c9660 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 18 Jan 2005 09:30:43 +0000 Subject: r4817: ccache was being made ineffective on all the build farm machines because the version number was being auto-updated and included in all C files. With this change it is only included where needed. (This used to be commit 520cff73c6dc62ba1050cf7ca5145d50b5f2bb4e) --- source4/lib/cmdline/popt_common.c | 1 + source4/lib/fault.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index c7bd35cbab..e440611ee4 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "version.h" #include "dynconfig.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/fault.c b/source4/lib/fault.c index ac2d4109fd..d90281f950 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "version.h" #include "system/wait.h" static void (*cont_fn)(void *); -- cgit From 07837b499f3c349744b5545c8277f5c193e8ef26 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 18 Jan 2005 10:06:37 +0000 Subject: r4818: missed version.h here (This used to be commit 03953803519e5284b4092db12c6279370456c857) --- source4/lib/version.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/version.c b/source4/lib/version.c index 99f836c2d5..fb5ed3ce05 100644 --- a/source4/lib/version.c +++ b/source4/lib/version.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "version.h" const char *samba_version_string(void) { -- cgit From 8783aa8ea57c3a6989e0722d5184e98d543352d4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 19 Jan 2005 03:20:20 +0000 Subject: r4831: added udp support to our generic sockets library. I decided to incorporate the udp support into the socket_ipv4.c backend (and later in socket_ipv6.c) rather than doing a separate backend, as so much of the code is shareable. Basically this adds a socket_sendto() and a socket_recvfrom() call and not much all. For udp servers, I decided to keep the call as socket_listen(), even though dgram servers don't actually call listen(). This keeps the API consistent. I also added a simple local sockets testsuite in smbtorture, LOCAL-SOCKET (This used to be commit 9f12a45a05c5c447fb4ec18c8dd28f70e90e32a5) --- source4/lib/socket/socket.c | 69 ++++++++++----- source4/lib/socket/socket.h | 15 +++- source4/lib/socket/socket_ipv4.c | 186 +++++++++++++++++++++++++++++---------- source4/lib/socket/socket_ipv6.c | 7 +- source4/lib/socket/socket_unix.c | 9 +- 5 files changed, 208 insertions(+), 78 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index cc43348e79..97176ea150 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -32,7 +32,9 @@ static int socket_destructor(void *ptr) return 0; } -NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops, struct socket_context **new_sock, uint32_t flags) +static NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops, + struct socket_context **new_sock, + enum socket_type type, uint32_t flags) { NTSTATUS status; @@ -41,7 +43,7 @@ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *op return NT_STATUS_NO_MEMORY; } - (*new_sock)->type = ops->type; + (*new_sock)->type = type; (*new_sock)->state = SOCKET_STATE_UNDEFINED; (*new_sock)->flags = flags; @@ -60,6 +62,7 @@ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *op send calls on non-blocking sockets will randomly recv/send less data than requested */ if (!(flags & SOCKET_FLAG_BLOCK) && + type == SOCKET_TYPE_STREAM && lp_parm_bool(-1, "socket", "testnonblock", False)) { (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK; } @@ -69,7 +72,8 @@ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *op return NT_STATUS_OK; } -NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags) +NTSTATUS socket_create(const char *name, enum socket_type type, + struct socket_context **new_sock, uint32_t flags) { const struct socket_ops *ops; @@ -78,7 +82,7 @@ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_co return NT_STATUS_INVALID_PARAMETER; } - return socket_create_with_ops(NULL, ops, new_sock, flags); + return socket_create_with_ops(NULL, ops, new_sock, type, flags); } void socket_destroy(struct socket_context *sock) @@ -92,10 +96,6 @@ NTSTATUS socket_connect(struct socket_context *sock, const char *server_address, int server_port, uint32_t flags) { - if (sock->type != SOCKET_TYPE_STREAM) { - return NT_STATUS_INVALID_PARAMETER; - } - if (sock->state != SOCKET_STATE_UNDEFINED) { return NT_STATUS_INVALID_PARAMETER; } @@ -117,10 +117,6 @@ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags) NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) { - if (sock->type != SOCKET_TYPE_STREAM) { - return NT_STATUS_INVALID_PARAMETER; - } - if (sock->state != SOCKET_STATE_UNDEFINED) { return NT_STATUS_INVALID_PARAMETER; } @@ -160,10 +156,6 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags) { - if (sock->type != SOCKET_TYPE_STREAM) { - return NT_STATUS_INVALID_PARAMETER; - } - if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED) { return NT_STATUS_INVALID_PARAMETER; @@ -184,13 +176,25 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, return sock->ops->fn_recv(sock, buf, wantlen, nread, flags); } -NTSTATUS socket_send(struct socket_context *sock, - const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags, + const char **src_addr, int *src_port) { - if (sock->type != SOCKET_TYPE_STREAM) { + if (sock->type != SOCKET_TYPE_DGRAM) { return NT_STATUS_INVALID_PARAMETER; } + if (!sock->ops->fn_recvfrom) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->fn_recvfrom(sock, buf, wantlen, nread, flags, + src_addr, src_port); +} + +NTSTATUS socket_send(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) +{ if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED) { return NT_STATUS_INVALID_PARAMETER; @@ -213,6 +217,27 @@ NTSTATUS socket_send(struct socket_context *sock, return sock->ops->fn_send(sock, blob, sendlen, flags); } + +NTSTATUS socket_sendto(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, + const char *dest_addr, int dest_port) +{ + if (sock->type != SOCKET_TYPE_DGRAM) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (sock->state == SOCKET_STATE_CLIENT_CONNECTED || + sock->state == SOCKET_STATE_SERVER_CONNECTED) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!sock->ops->fn_sendto) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return sock->ops->fn_sendto(sock, blob, sendlen, flags, dest_addr, dest_port); +} + NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) { if (!sock->ops->fn_set_option) { @@ -302,7 +327,7 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type { if (strcmp("ip", name) == 0 || strcmp("ipv4", name) == 0) { - return socket_ipv4_ops(); + return socket_ipv4_ops(type); } #if HAVE_SOCKET_IPV6 @@ -311,12 +336,12 @@ const struct socket_ops *socket_getops_byname(const char *name, enum socket_type DEBUG(3, ("IPv6 support was disabled in smb.conf")); return NULL; } - return socket_ipv6_ops(); + return socket_ipv6_ops(type); } #endif if (strcmp("unix", name) == 0) { - return socket_unixdom_ops(); + return socket_unixdom_ops(type); } return NULL; diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 7dd8c0ae17..162a05cb40 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -24,12 +24,12 @@ struct socket_context; enum socket_type { - SOCKET_TYPE_STREAM + SOCKET_TYPE_STREAM, + SOCKET_TYPE_DGRAM }; struct socket_ops { const char *name; - enum socket_type type; NTSTATUS (*fn_init)(struct socket_context *sock); @@ -50,9 +50,16 @@ struct socket_ops { /* general ops */ NTSTATUS (*fn_recv)(struct socket_context *sock, void *buf, - size_t wantlen, size_t *nread, uint32_t flags); + size_t wantlen, size_t *nread, uint32_t flags); NTSTATUS (*fn_send)(struct socket_context *sock, - const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); + + NTSTATUS (*fn_sendto)(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, + const char *dest_addr, int dest_port); + NTSTATUS (*fn_recvfrom)(struct socket_context *sock, + void *buf, size_t wantlen, size_t *nread, uint32_t flags, + const char **src_addr, int *src_port); void (*fn_close)(struct socket_context *sock); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 7cf2b73e4e..d6b6bf7be4 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -24,9 +24,22 @@ #include "includes.h" #include "system/network.h" -static NTSTATUS ipv4_tcp_init(struct socket_context *sock) +static NTSTATUS ipv4_init(struct socket_context *sock) { - sock->fd = socket(PF_INET, SOCK_STREAM, 0); + int type; + + switch (sock->type) { + case SOCKET_TYPE_STREAM: + type = SOCK_STREAM; + break; + case SOCKET_TYPE_DGRAM: + type = SOCK_DGRAM; + break; + default: + return NT_STATUS_INVALID_PARAMETER; + } + + sock->fd = socket(PF_INET, type, 0); if (sock->fd == -1) { return map_nt_error_from_unix(errno); } @@ -34,12 +47,12 @@ static NTSTATUS ipv4_tcp_init(struct socket_context *sock) return NT_STATUS_OK; } -static void ipv4_tcp_close(struct socket_context *sock) +static void ipv4_close(struct socket_context *sock) { close(sock->fd); } -static NTSTATUS ipv4_tcp_connect_complete(struct socket_context *sock, uint32_t flags) +static NTSTATUS ipv4_connect_complete(struct socket_context *sock, uint32_t flags) { int error=0, ret; socklen_t len = sizeof(error); @@ -67,7 +80,7 @@ static NTSTATUS ipv4_tcp_connect_complete(struct socket_context *sock, uint32_t } -static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, +static NTSTATUS ipv4_connect(struct socket_context *sock, const char *my_address, int my_port, const char *srv_address, int srv_port, uint32_t flags) @@ -110,13 +123,17 @@ static NTSTATUS ipv4_tcp_connect(struct socket_context *sock, return map_nt_error_from_unix(errno); } - return ipv4_tcp_connect_complete(sock, flags); + return ipv4_connect_complete(sock, flags); } -static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, - const char *my_address, int port, - int queue_size, uint32_t flags) +/* + note that for simplicity of the API, socket_listen() is also + use for DGRAM sockets, but in reality only a bind() is done +*/ +static NTSTATUS ipv4_listen(struct socket_context *sock, + const char *my_address, int port, + int queue_size, uint32_t flags) { struct sockaddr_in my_addr; struct ipv4_addr ip_addr; @@ -137,9 +154,11 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, return map_nt_error_from_unix(errno); } - ret = listen(sock->fd, queue_size); - if (ret == -1) { - return map_nt_error_from_unix(errno); + if (sock->type == SOCKET_TYPE_STREAM) { + ret = listen(sock->fd, queue_size); + if (ret == -1) { + return map_nt_error_from_unix(errno); + } } if (!(flags & SOCKET_FLAG_BLOCK)) { @@ -154,12 +173,16 @@ static NTSTATUS ipv4_tcp_listen(struct socket_context *sock, return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_context **new_sock) +static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context **new_sock) { struct sockaddr_in cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); int new_fd; + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { return map_nt_error_from_unix(errno); @@ -198,7 +221,7 @@ static NTSTATUS ipv4_tcp_accept(struct socket_context *sock, struct socket_conte return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, void *buf, +static NTSTATUS ipv4_recv(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags) { ssize_t gotlen; @@ -227,7 +250,49 @@ static NTSTATUS ipv4_tcp_recv(struct socket_context *sock, void *buf, return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_send(struct socket_context *sock, + +static NTSTATUS ipv4_recvfrom(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags, + const char **src_addr, int *src_port) +{ + ssize_t gotlen; + int flgs = 0; + struct sockaddr_in from_addr; + socklen_t from_len = sizeof(from_addr); + const char *addr; + + if (flags & SOCKET_FLAG_PEEK) { + flgs |= MSG_PEEK; + } + + if (flags & SOCKET_FLAG_BLOCK) { + flgs |= MSG_WAITALL; + } + + *nread = 0; + + gotlen = recvfrom(sock->fd, buf, wantlen, flgs, + (struct sockaddr *)&from_addr, &from_len); + if (gotlen == 0) { + return NT_STATUS_END_OF_FILE; + } else if (gotlen == -1) { + return map_nt_error_from_unix(errno); + } + + addr = inet_ntoa(from_addr.sin_addr); + if (addr == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + *src_addr = talloc_strdup(sock, addr); + NT_STATUS_HAVE_NO_MEMORY(*src_addr); + *src_port = ntohs(from_addr.sin_port); + + *nread = gotlen; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv4_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { ssize_t len; @@ -245,13 +310,44 @@ static NTSTATUS ipv4_tcp_send(struct socket_context *sock, return NT_STATUS_OK; } -static NTSTATUS ipv4_tcp_set_option(struct socket_context *sock, const char *option, const char *val) +static NTSTATUS ipv4_sendto(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, + const char *dest_addr, int dest_port) +{ + ssize_t len; + int flgs = 0; + struct sockaddr_in srv_addr; + struct ipv4_addr addr; + + ZERO_STRUCT(srv_addr); +#ifdef HAVE_SOCK_SIN_LEN + srv_addr.sin_len = sizeof(srv_addr); +#endif + addr = interpret_addr2(dest_addr); + srv_addr.sin_addr.s_addr = addr.addr; + srv_addr.sin_port = htons(dest_port); + srv_addr.sin_family = PF_INET; + + *sendlen = 0; + + len = sendto(sock->fd, blob->data, blob->length, flgs, + (struct sockaddr *)&srv_addr, sizeof(srv_addr)); + if (len == -1) { + return map_nt_error_from_unix(errno); + } + + *sendlen = len; + + return NT_STATUS_OK; +} + +static NTSTATUS ipv4_set_option(struct socket_context *sock, const char *option, const char *val) { set_socket_options(sock->fd, option); return NT_STATUS_OK; } -static char *ipv4_tcp_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static char *ipv4_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct sockaddr_in peer_addr; socklen_t len = sizeof(peer_addr); @@ -271,7 +367,7 @@ static char *ipv4_tcp_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem return talloc_strdup(mem_ctx, he->h_name); } -static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static char *ipv4_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct sockaddr_in peer_addr; socklen_t len = sizeof(peer_addr); @@ -285,7 +381,7 @@ static char *ipv4_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem return talloc_strdup(mem_ctx, inet_ntoa(peer_addr.sin_addr)); } -static int ipv4_tcp_get_peer_port(struct socket_context *sock) +static int ipv4_get_peer_port(struct socket_context *sock) { struct sockaddr_in peer_addr; socklen_t len = sizeof(peer_addr); @@ -299,7 +395,7 @@ static int ipv4_tcp_get_peer_port(struct socket_context *sock) return ntohs(peer_addr.sin_port); } -static char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) +static char *ipv4_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct sockaddr_in my_addr; socklen_t len = sizeof(my_addr); @@ -313,7 +409,7 @@ static char *ipv4_tcp_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_c return talloc_strdup(mem_ctx, inet_ntoa(my_addr.sin_addr)); } -static int ipv4_tcp_get_my_port(struct socket_context *sock) +static int ipv4_get_my_port(struct socket_context *sock) { struct sockaddr_in my_addr; socklen_t len = sizeof(my_addr); @@ -327,36 +423,36 @@ static int ipv4_tcp_get_my_port(struct socket_context *sock) return ntohs(my_addr.sin_port); } -static int ipv4_tcp_get_fd(struct socket_context *sock) +static int ipv4_get_fd(struct socket_context *sock) { return sock->fd; } -static const struct socket_ops ipv4_tcp_ops = { +static const struct socket_ops ipv4_ops = { .name = "ipv4", - .type = SOCKET_TYPE_STREAM, - - .fn_init = ipv4_tcp_init, - .fn_connect = ipv4_tcp_connect, - .fn_connect_complete = ipv4_tcp_connect_complete, - .fn_listen = ipv4_tcp_listen, - .fn_accept = ipv4_tcp_accept, - .fn_recv = ipv4_tcp_recv, - .fn_send = ipv4_tcp_send, - .fn_close = ipv4_tcp_close, - - .fn_set_option = ipv4_tcp_set_option, - - .fn_get_peer_name = ipv4_tcp_get_peer_name, - .fn_get_peer_addr = ipv4_tcp_get_peer_addr, - .fn_get_peer_port = ipv4_tcp_get_peer_port, - .fn_get_my_addr = ipv4_tcp_get_my_addr, - .fn_get_my_port = ipv4_tcp_get_my_port, - - .fn_get_fd = ipv4_tcp_get_fd + .fn_init = ipv4_init, + .fn_connect = ipv4_connect, + .fn_connect_complete = ipv4_connect_complete, + .fn_listen = ipv4_listen, + .fn_accept = ipv4_accept, + .fn_recv = ipv4_recv, + .fn_recvfrom = ipv4_recvfrom, + .fn_send = ipv4_send, + .fn_sendto = ipv4_sendto, + .fn_close = ipv4_close, + + .fn_set_option = ipv4_set_option, + + .fn_get_peer_name = ipv4_get_peer_name, + .fn_get_peer_addr = ipv4_get_peer_addr, + .fn_get_peer_port = ipv4_get_peer_port, + .fn_get_my_addr = ipv4_get_my_addr, + .fn_get_my_port = ipv4_get_my_port, + + .fn_get_fd = ipv4_get_fd }; -const struct socket_ops *socket_ipv4_ops(void) +const struct socket_ops *socket_ipv4_ops(enum socket_type type) { - return &ipv4_tcp_ops; + return &ipv4_ops; } diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 35b4037ff4..27e452b14e 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -347,8 +347,6 @@ static int ipv6_tcp_get_fd(struct socket_context *sock) static const struct socket_ops ipv6_tcp_ops = { .name = "ipv6", - .type = SOCKET_TYPE_STREAM, - .fn_init = ipv6_tcp_init, .fn_connect = ipv6_tcp_connect, .fn_connect_complete = ipv6_tcp_connect_complete, @@ -369,7 +367,10 @@ static const struct socket_ops ipv6_tcp_ops = { .fn_get_fd = ipv6_tcp_get_fd }; -const struct socket_ops *socket_ipv6_ops(void) +const struct socket_ops *socket_ipv6_ops(enum socket_type type) { + if (type != SOCKET_TYPE_STREAM) { + return NULL; + } return &ipv6_tcp_ops; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 60a4b9ec48..bdd68f9d9d 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -4,7 +4,7 @@ unix domain socket functions Copyright (C) Stefan Metzmacher 2004 - Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Tridgell 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 @@ -266,8 +266,6 @@ static int unixdom_get_fd(struct socket_context *sock) static const struct socket_ops unixdom_ops = { .name = "unix", - .type = SOCKET_TYPE_STREAM, - .fn_init = unixdom_init, .fn_connect = unixdom_connect, .fn_connect_complete = unixdom_connect_complete, @@ -288,7 +286,10 @@ static const struct socket_ops unixdom_ops = { .fn_get_fd = unixdom_get_fd }; -const struct socket_ops *socket_unixdom_ops(void) +const struct socket_ops *socket_unixdom_ops(enum socket_type type) { + if (type != SOCKET_TYPE_STREAM) { + return NULL; + } return &unixdom_ops; } -- cgit From f19049c9c9fcf891c638c56c13071d09a3a46c54 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 13:54:10 +0000 Subject: r4844: - Remove the unused attrsyn structure - Change 0 to NULL when checking allocations - Introduce the schema_attr_cmp hepler function - Do not allow auxiliary classes to be missing - Try to ease code readability and try to get main code out of loops when possibile. (This used to be commit a30f647b8abe6b77ef73018f58af2f8a11689b91) --- source4/lib/ldb/modules/schema.c | 339 +++++++++++++++++++-------------------- 1 file changed, 164 insertions(+), 175 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 912c8657d2..b396ae0459 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -36,33 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -struct attribute_syntax { - const char *name; - const char *syntax_id; -}; - -static struct attribute_syntax attrsyn[] = { - { "Object(DS-DN)", "2.5.5.1"}, - { "String(Object-Identifier)", "2.5.5.2"}, - { "", "2.5.5.3"}, - { "String(Teletex)", "2.5.5.4"}, - { "String(IA5)", "2.5.5.5"}, /* Also String(Printable) */ - { "String(Numeric)", "2.5.5.6"}, - { "Object(DN-Binary)", "2.5.5.7"}, /* Also Object(OR-Name) */ - { "Boolean", "2.5.5.8"}, - { "Integer", "2.5.5.9"}, /* Also Enumeration (3 types ?) ... */ - { "String(Octet)", "2.5.5.10"}, /* Also Object(Replica-Link) */ - { "String(UTC-Time)", "2.5.5.11"}, /* Also String(Generalized-Time) */ - { "String(Unicode)", "2.5.5.12"}, - { "Object(Presentation-Address)", "2.5.5.13"}, - { "Object(DN-String)", "2.5.5.14"}, /* Also Object(Access-Point) */ - { "String(NT-Sec-Desc))", "2.5.5.15"}, - { "LargeInteger", "2.5.5.16"}, /* Also Interval ... */ - { "String(Sid)", "2.5.5.17"} - }; - -#define SCHEMA_TALLOC_CHECK(root, mem, ret) do { if (!mem) { talloc_free(root); return ret;} } while(0); - #define SCHEMA_FLAG_RESET 0 #define SCHEMA_FLAG_MOD_MASK 0x03 #define SCHEMA_FLAG_MOD_ADD 0x01 @@ -114,6 +87,18 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } +struct attribute_list *schema_find_attribute(struct attribute_list *list, int attr_num, const char *attr_name) +{ + unsigned int i; + for (i = 0; i < attr_num; i++) { + if (ldb_attr_cmp(list[i].name, attr_name) == 0) { + return &list[i]; + } + } + return NULL; +} + +/* get objectclasses of dn */ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) { char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); @@ -124,36 +109,39 @@ static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, str schema_struct->objectclass_list = NULL; schema_struct->objectclass_list_num = 0; ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret == 1) { - for (i = 0; i < (*srch)->num_elements; i++) { - schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == 0) { + if (ret != 1) { + ldb_search_free(ldb, srch); + return -1; + } + + for (i = 0; i < (*srch)->num_elements; i++) { + schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; + schema_struct->objectclass_list = talloc_array(schema_struct, + struct attribute_list, + schema_struct->objectclass_list_num); + if (schema_struct->objectclass_list == NULL) { + ldb_search_free(ldb, srch); + return -1; + } + for (j = 0; j < schema_struct->objectclass_list_num; j++) { + schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, + (*srch)->elements[i].values[j].data, + (*srch)->elements[i].values[j].length); + if (schema_struct->objectclass_list[j].name == NULL) { ldb_search_free(ldb, srch); return -1; } - for (j = 0; j < schema_struct->objectclass_list_num; j++) { - schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, - (*srch)->elements[i].values[j].data, - (*srch)->elements[i].values[j].length); - if (schema_struct->objectclass_list[j].name == 0) { - ldb_search_free(ldb, srch); - return -1; - } - schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; - } + schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; } - ldb_search_free(ldb, srch); - } else { - ldb_search_free(ldb, srch); - return -1; } + ldb_search_free(ldb, srch); return 0; } +/* get all the attributes and objectclasses found in msg and put them in schema_structure + attributes go in the check_list structure for later checking + objectclasses go in the objectclass_list structure */ static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) { int i, j, k; @@ -164,7 +152,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->check_list = talloc_array(schema_struct, struct attribute_list, schema_struct->check_list_num); - if (schema_struct->check_list == 0) { + if (schema_struct->check_list == NULL) { return -1; } for (i = 0, j = 0; i < msg->num_elements; i++) { @@ -173,14 +161,14 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->objectclass_list = talloc_array(schema_struct, struct attribute_list, schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == 0) { + if (schema_struct->objectclass_list == NULL) { return -1; } for (k = 0; k < schema_struct->objectclass_list_num; k++) { schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, msg->elements[i].values[k].data, msg->elements[i].values[k].length); - if (schema_struct->objectclass_list[k].name == 0) { + if (schema_struct->objectclass_list[k].name == NULL) { return -1; } schema_struct->objectclass_list[k].flags = msg->elements[i].flags; @@ -190,7 +178,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s schema_struct->check_list[j].flags = msg->elements[i].flags; schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, msg->elements[i].name); - if (schema_struct->check_list[j].name == 0) { + if (schema_struct->check_list[j].name == NULL) { return -1; } j++; @@ -199,6 +187,7 @@ static int get_check_list(struct ldb_module *module, struct schema_structures *s return 0; } +/* add all attributes in el avoiding duplicates in attribute_list */ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) { int i, j, vals; @@ -235,6 +224,9 @@ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int f return 0; } + +/* we need to get all attributes referenced by the entry objectclasses, + recursively get parent objectlasses attributes */ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) { struct private_data *data = (struct private_data *)module->private_data; @@ -253,46 +245,27 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context continue; } filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); - SCHEMA_TALLOC_CHECK(schema_struct, filter, -1); + if (filter == NULL) { + return -1; + } + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); - if (ret == 0) { - int ok; - - ok = 0; - /* suppose auxiliary classeschema_struct are not required */ - if (schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_AUXCLASS) { - int d; - ok = 1; - schema_struct->objectclass_list_num -= 1; - for (d = i; d < schema_struct->objectclass_list_num; d++) { - schema_struct->objectclass_list[d] = schema_struct->objectclass_list[d + 1]; - } - i -= 1; - } - if (!ok) { - /* Schema Violation: Object Class Description Not Found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Objectclass %s not found.\n", schema_struct->objectclass_list[i].name); - data->error_string = "ObjectClass not found"; - return -1; - } - continue; - } else { - if (ret < 0) { - /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); - data->error_string = "Internal error. Error retrieving schema objectclass"; - return -1; - } - if (ret > 1) { - /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); - data->error_string = "Internal error. Too many records searching for schema objectclass"; - return -1; - } + + if (ret <= 0) { + /* Schema DB Error: Error occurred retrieving Object Class Description */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + data->error_string = "Internal error. Error retrieving schema objectclass"; + return -1; + } + if (ret > 1) { + /* Schema DB Error: Too Many Records */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + data->error_string = "Internal error. Too many records searching for schema objectclass"; + return -1; } /* Add inherited classes eliminating duplicates */ - /* fill in kust and may attribute lists */ + /* fill in required and optional attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { int is_aux, is_class; @@ -372,12 +345,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message { struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; - int i, j; + unsigned int i; int ret; /* First implementation: - Build up a list of must and mays from each objectclass - Check all the musts are there and all the other attributes are mays + Build up a list of required and optional attributes from each objectclass + Check all the required attributes are present and all the other attributes + are optional attributes Throw an error in case a check fail Free all structures and commit the change */ @@ -404,44 +378,43 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return ret; } - /* now check all musts are present */ + /* now check all required attributes are present */ for (i = 0; i < entry_structs->must_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->check_list_num; j++) { - if (schema_attr_cmp(entry_structs->must[i].name, entry_structs->check_list[j].name) == 0) { - entry_structs->check_list[j].flags = SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(entry_structs->check_list, + entry_structs->check_list_num, + entry_structs->must[i].name); + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The required attribute %s is missing.\n", + entry_structs->must[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", entry_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } + + /* mark the attribute as checked */ + attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are found in mays */ + /* now check all others atribs are at least optional */ for (i = 0; i < entry_structs->check_list_num; i++) { if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->may_num; j++) { - if (schema_attr_cmp(entry_structs->may[j].name, entry_structs->check_list[i].name) == 0) { - entry_structs->check_list[i].flags = SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(entry_structs->may, + entry_structs->may_num, + entry_structs->check_list[i].name); + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The attribute %s is not referenced by any objectclass.\n", + entry_structs->check_list[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", entry_structs->check_list[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; @@ -459,16 +432,16 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess { struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs, *modify_structs; - int i, j; + unsigned int i; int ret; /* First implementation: Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. - Build up a list of must and mays from each objectclass - Check all musts for the defined objectclass and it's specific - inheritance are there. - Check all other the attributes are mays or musts. + Build up a list of required and optional attributes from each objectclass + Check all required one for the defined objectclass and all its parent + objectclasses. + Check all other the attributes are optional or required. Throw an error in case a check fail. Free all structures and commit the change. */ @@ -478,13 +451,13 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* allocate object structs */ - entry_structs = talloc(module, struct schema_structures); + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; } /* allocate modification entry structs */ - modify_structs = talloc(entry_structs, struct schema_structures); + modify_structs = talloc_zero(entry_structs, struct schema_structures); if (!modify_structs) { talloc_free(entry_structs); return -1; @@ -518,85 +491,98 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return ret; } - /* now check all entries are present either as musts or mays of curent objectclasses */ - /* do not return errors there may be attirbutes defined in new objectclasses */ - /* just mark them as being proved valid attribs */ + /* now check all entries are present either as required or optional atributes of entry objectclasses */ + /* if they are required and we are going to delete them then throw an error */ + /* just mark them if being proved valid attribs */ for (i = 0; i < modify_structs->check_list_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < entry_structs->must_num; j++) { - if (schema_attr_cmp(entry_structs->must[j].name, modify_structs->check_list[i].name) == 0) { - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->check_list[i].name); - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } + attr = schema_find_attribute(entry_structs->must, + entry_structs->must_num, + modify_structs->check_list[i].name); + + if (attr == NULL) { /* not found */ + + attr = schema_find_attribute(entry_structs->may, + entry_structs->may_num, + modify_structs->check_list[i].name); + + if (attr != NULL) { /* found*/ modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; } + + break; /* not found, go on */ } - if ( ! found) { - for (j = 0; j < entry_structs->may_num; j++) { - if (schema_attr_cmp(entry_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - break; - } - } + + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + modify_structs->check_list[i].name); + + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; } + + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; } - /* now check all new objectclasses musts are present */ + /* now check all new objectclasses required attributes are present */ for (i = 0; i < modify_structs->must_num; i++) { - int found; + struct attribute_list *attr; - found = 0; - for (j = 0; j < modify_structs->check_list_num; j++) { - if (schema_attr_cmp(modify_structs->must[i].name, modify_structs->check_list[j].name) == 0) { - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Trying to delete the required attribute %s.\n", modify_structs->must[i].name); - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - modify_structs->check_list[j].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } + attr = schema_find_attribute(modify_structs->check_list, + modify_structs->check_list_num, + modify_structs->must[i].name); + + + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The required attribute %s is missing.\n", + modify_structs->must[i].name); - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The required attribute %s is missing.\n", modify_structs->must[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } + + if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + modify_structs->must[i].name); + + data->error_string = "Objectclass violation: trying to delete a required attribute"; + talloc_free(entry_structs); + return -1; + } + + attr->flags |= SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are found in mays */ + /* now check all others attributes are at least optional */ for (i = 0; i < modify_structs->check_list_num; i++) { if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { - int found; + struct attribute_list *attr; + + attr = schema_find_attribute(modify_structs->may, + modify_structs->may_num, + modify_structs->check_list[i].name); - found = 0; - for (j = 0; j < modify_structs->may_num; j++) { - if (schema_attr_cmp(modify_structs->may[j].name, modify_structs->check_list[i].name) == 0) { - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - found = 1; - break; - } - } - if ( ! found ) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", modify_structs->check_list[i].name); + if (attr == NULL) { /* not found */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "The attribute %s is not referenced by any objectclass.\n", + modify_structs->check_list[i].name); + data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; } + + modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; + } } @@ -671,7 +657,10 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio } data = talloc(ctx, struct private_data); - SCHEMA_TALLOC_CHECK(ctx, data, NULL); + if (data == NULL) { + talloc_free(ctx); + return NULL; + } data->error_string = NULL; ctx->private_data = data; -- cgit From 23f92c16349a3142012e54afc3854c469f32a165 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 22:26:14 +0000 Subject: r4859: changed a numbe rof things: - Try to no tcopy memory if not necessary - let the searches hang around until we finish the operation - greatly simplify the modify operation still todo: - check attributes syntax - check objectclasses type, we cannot allow to add a new structural objectclass to an exixting entry unless the existing one is a parent - more tests (This used to be commit c6257379e094881987cd11e05502129b2ce1c5a0) --- source4/lib/ldb/modules/schema.c | 394 +++++++++++++++------------------------ 1 file changed, 150 insertions(+), 244 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index b396ae0459..b16849c2fe 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -37,32 +37,39 @@ #include "ldb/include/ldb_private.h" #define SCHEMA_FLAG_RESET 0 -#define SCHEMA_FLAG_MOD_MASK 0x03 -#define SCHEMA_FLAG_MOD_ADD 0x01 -#define SCHEMA_FLAG_MOD_REPLACE 0x02 -#define SCHEMA_FLAG_MOD_DELETE 0x03 -#define SCHEMA_FLAG_AUXCLASS 0x10 -#define SCHEMA_FLAG_CHECKED 0x20 - +#define SCHEMA_FLAG_MOD_MASK 0x003 +#define SCHEMA_FLAG_MOD_ADD 0x001 +#define SCHEMA_FLAG_MOD_REPLACE 0x002 +#define SCHEMA_FLAG_MOD_DELETE 0x003 +#define SCHEMA_FLAG_AUXILIARY 0x010 +#define SCHEMA_FLAG_ABSTRACT 0x020 +#define SCHEMA_FLAG_STRUCTURAL 0x040 +#define SCHEMA_FLAG_CHECKED 0x100 + + +/* TODO: check attributes syntaxes + check there's only one structrual class (or a chain of structural classes) +*/ struct private_data { const char *error_string; }; -struct attribute_list { +struct schema_attribute { int flags; char *name; }; +struct schema_attribute_list { + struct schema_attribute *attr; + int num; +}; + struct schema_structures { - struct attribute_list *check_list; - struct attribute_list *objectclass_list; - struct attribute_list *must; - struct attribute_list *may; - int check_list_num; - int objectclass_list_num; - int must_num; - int may_num; + struct schema_attribute_list entry_attrs; + struct schema_attribute_list objectclasses; + struct schema_attribute_list required_attrs; + struct schema_attribute_list optional_attrs; }; /* This function embedds the knowledge of aliased names. @@ -87,139 +94,114 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } -struct attribute_list *schema_find_attribute(struct attribute_list *list, int attr_num, const char *attr_name) +struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; - for (i = 0; i < attr_num; i++) { - if (ldb_attr_cmp(list[i].name, attr_name) == 0) { - return &list[i]; + for (i = 0; i < list->num; i++) { + if (ldb_attr_cmp(list->attr[i].name, attr_name) == 0) { + return &(list->attr[i]); } } return NULL; } -/* get objectclasses of dn */ -static int get_object_objectclasses(struct ldb_context *ldb, const char *dn, struct schema_structures *schema_struct) +/* get all the attributes and objectclasses found in msg and put them in schema_structure + attributes go in the entry_attrs structure for later checking + objectclasses go in the objectclasses structure */ +static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg) { - char *filter = talloc_asprintf(schema_struct, "dn=%s", dn); - const char *attrs[] = {"objectClass", NULL}; - struct ldb_message **srch; - int i, j, ret; + int i, j, k, l; - schema_struct->objectclass_list = NULL; - schema_struct->objectclass_list_num = 0; - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, attrs, &srch); - if (ret != 1) { - ldb_search_free(ldb, srch); + ss->entry_attrs.attr = talloc_realloc(ss, ss->entry_attrs.attr, + struct schema_attribute, + ss->entry_attrs.num + msg->num_elements); + if (ss->entry_attrs.attr == NULL) { return -1; } - for (i = 0; i < (*srch)->num_elements; i++) { - schema_struct->objectclass_list_num = (*srch)->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == NULL) { - ldb_search_free(ldb, srch); - return -1; - } - for (j = 0; j < schema_struct->objectclass_list_num; j++) { - schema_struct->objectclass_list[j].name = talloc_strndup(schema_struct->objectclass_list, - (*srch)->elements[i].values[j].data, - (*srch)->elements[i].values[j].length); - if (schema_struct->objectclass_list[j].name == NULL) { - ldb_search_free(ldb, srch); + for (i = 0, j = ss->entry_attrs.num; i < msg->num_elements; i++) { + + if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + + ss->objectclasses.attr = talloc_realloc(ss, ss->objectclasses.attr, + struct schema_attribute, + ss->objectclasses.num + msg->elements[i].num_values); + if (ss->objectclasses.attr == NULL) { return -1; } - schema_struct->objectclass_list[j].flags = SCHEMA_FLAG_RESET; + + for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { + ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; + ss->objectclasses.attr[l].flags = msg->elements[i].flags; + l++; + } + ss->objectclasses.num += msg->elements[i].num_values; } + + ss->entry_attrs.attr[j].flags = msg->elements[i].flags; + ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, + msg->elements[i].name); + if (ss->entry_attrs.attr[j].name == NULL) { + return -1; + } + j++; } - ldb_search_free(ldb, srch); + ss->entry_attrs.num += msg->num_elements; return 0; } -/* get all the attributes and objectclasses found in msg and put them in schema_structure - attributes go in the check_list structure for later checking - objectclasses go in the objectclass_list structure */ -static int get_check_list(struct ldb_module *module, struct schema_structures *schema_struct, const struct ldb_message *msg) +static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct schema_structures *ss) { - int i, j, k; - - schema_struct->objectclass_list = NULL; - schema_struct->objectclass_list_num = 0; - schema_struct->check_list_num = msg->num_elements; - schema_struct->check_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->check_list_num); - if (schema_struct->check_list == NULL) { - return -1; + char *filter = talloc_asprintf(ss, "dn=%s", dn); + struct ldb_message **srch; + int ret; + + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret != 1) { + return ret; } - for (i = 0, j = 0; i < msg->num_elements; i++) { - if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { - schema_struct->objectclass_list_num = msg->elements[i].num_values; - schema_struct->objectclass_list = talloc_array(schema_struct, - struct attribute_list, - schema_struct->objectclass_list_num); - if (schema_struct->objectclass_list == NULL) { - return -1; - } - for (k = 0; k < schema_struct->objectclass_list_num; k++) { - schema_struct->objectclass_list[k].name = talloc_strndup(schema_struct->objectclass_list, - msg->elements[i].values[k].data, - msg->elements[i].values[k].length); - if (schema_struct->objectclass_list[k].name == NULL) { - return -1; - } - schema_struct->objectclass_list[k].flags = msg->elements[i].flags; - } - } + talloc_steal(ss, srch); - schema_struct->check_list[j].flags = msg->elements[i].flags; - schema_struct->check_list[j].name = talloc_strdup(schema_struct->check_list, - msg->elements[i].name); - if (schema_struct->check_list[j].name == NULL) { - return -1; - } - j++; + ret = get_msg_attributes(ss, *srch); + if (ret != 0) { + ldb_search_free(ldb, srch); + return ret; } return 0; } -/* add all attributes in el avoiding duplicates in attribute_list */ -static int add_attribute_uniq(struct attribute_list **list, int *list_num, int flags, struct ldb_message_element *el, void *mem_ctx) +/* add all attributes in el avoiding duplicates in schema_attribute_list */ +static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, int flags, struct ldb_message_element *el) { int i, j, vals; vals = el->num_values; - *list = talloc_realloc(mem_ctx, *list, struct attribute_list, *list_num + vals); - if (list == 0) { + list->attr = talloc_realloc(mem_ctx, list->attr, struct schema_attribute, list->num + vals); + if (list->attr == NULL) { return -1; } for (i = 0, j = 0; i < vals; i++) { int c, found, len; found = 0; - for (c = 0; c < *list_num; c++) { - len = strlen((*list)[c].name); + for (c = 0; c < list->num; c++) { + len = strlen(list->attr[c].name); if (len == el->values[i].length) { - if (strncasecmp((*list)[c].name, el->values[i].data, len) == 0) { + if (schema_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { found = 1; break; } } } if (!found) { - (*list)[j + *list_num].name = talloc_strndup(*list, el->values[i].data, el->values[i].length); - if ((*list)[j + *list_num].name == 0) { - return -1; - } - (*list)[j + *list_num].flags = flags; + list->attr[j + list->num].name = el->values[i].data; + list->attr[j + list->num].flags = flags; j++; } } - *list_num += j; + list->num += j; return 0; } @@ -227,52 +209,52 @@ static int add_attribute_uniq(struct attribute_list **list, int *list_num, int f /* we need to get all attributes referenced by the entry objectclasses, recursively get parent objectlasses attributes */ -static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context *ldb, struct schema_structures *schema_struct) +static int get_attr_list_recursive(struct ldb_module *module, struct schema_structures *schema_struct) { struct private_data *data = (struct private_data *)module->private_data; struct ldb_message **srch; int i, j; int ret; - schema_struct->must = NULL; - schema_struct->may = NULL; - schema_struct->must_num = 0; - schema_struct->may_num = 0; - for (i = 0; i < schema_struct->objectclass_list_num; i++) { + for (i = 0; i < schema_struct->objectclasses.num; i++) { char *filter; - if ((schema_struct->objectclass_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { + if ((schema_struct->objectclasses.attr[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { continue; } - filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclass_list[i].name); + filter = talloc_asprintf(schema_struct, "lDAPDisplayName=%s", schema_struct->objectclasses.attr[i].name); if (filter == NULL) { return -1; } - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + if (ret != 1) { + return ret; + } + talloc_steal(schema_struct, srch); if (ret <= 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); data->error_string = "Internal error. Error retrieving schema objectclass"; return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclass_list[i].name); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); data->error_string = "Internal error. Too many records searching for schema objectclass"; return -1; } /* Add inherited classes eliminating duplicates */ - /* fill in required and optional attribute lists */ + /* fill in required_attrs and optional_attrs attribute lists */ for (j = 0; j < (*srch)->num_elements; j++) { int is_aux, is_class; is_aux = 0; is_class = 0; if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { - is_aux = SCHEMA_FLAG_AUXCLASS; + is_aux = SCHEMA_FLAG_AUXILIARY; is_class = 1; } if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { @@ -280,22 +262,20 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context } if (is_class) { - if (add_attribute_uniq(&schema_struct->objectclass_list, - &schema_struct->objectclass_list_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->objectclasses, is_aux, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } else { if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { - if (add_attribute_uniq(&schema_struct->must, - &schema_struct->must_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->required_attrs, SCHEMA_FLAG_RESET, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } @@ -303,18 +283,15 @@ static int get_attr_list_recursive(struct ldb_module *module, struct ldb_context if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { - if (add_attribute_uniq(&schema_struct->may, - &schema_struct->may_num, + if (add_attribute_uniq(schema_struct, + &schema_struct->optional_attrs, SCHEMA_FLAG_RESET, - &(*srch)->elements[j], - schema_struct) != 0) { + &(*srch)->elements[j]) != 0) { return -1; } } } } - - ldb_search_free(ldb, srch); } return 0; @@ -349,9 +326,9 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message int ret; /* First implementation: - Build up a list of required and optional attributes from each objectclass - Check all the required attributes are present and all the other attributes - are optional attributes + Build up a list of required_attrs and optional_attrs attributes from each objectclass + Check all the required_attrs attributes are present and all the other attributes + are optional_attrs attributes Throw an error in case a check fail Free all structures and commit the change */ @@ -360,36 +337,34 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return ldb_next_add_record(module, msg); } - entry_structs = talloc(module, struct schema_structures); + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; } - ret = get_check_list(module, entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, module->ldb, entry_structs); + ret = get_attr_list_recursive(module, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now check all required attributes are present */ - for (i = 0; i < entry_structs->must_num; i++) { - struct attribute_list *attr; + /* now check all required_attrs attributes are present */ + for (i = 0; i < entry_structs->required_attrs.num; i++) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->check_list, - entry_structs->check_list_num, - entry_structs->must[i].name); + attr = schema_find_attribute(&entry_structs->entry_attrs, + entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "The required attribute %s is missing.\n", - entry_structs->must[i].name); + "The required_attrs attribute %s is missing.\n", + entry_structs->required_attrs.attr[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); @@ -400,20 +375,19 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others atribs are at least optional */ - for (i = 0; i < entry_structs->check_list_num; i++) { + /* now check all others atribs are at least optional_attrs */ + for (i = 0; i < entry_structs->entry_attrs.num; i++) { - if (entry_structs->check_list[i].flags != SCHEMA_FLAG_CHECKED) { - struct attribute_list *attr; + if (entry_structs->entry_attrs.attr[i].flags != SCHEMA_FLAG_CHECKED) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->may, - entry_structs->may_num, - entry_structs->check_list[i].name); + attr = schema_find_attribute(&entry_structs->optional_attrs, + entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", - entry_structs->check_list[i].name); + entry_structs->entry_attrs.attr[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); @@ -431,17 +405,17 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { struct private_data *data = (struct private_data *)module->private_data; - struct schema_structures *entry_structs, *modify_structs; + struct schema_structures *entry_structs; unsigned int i; int ret; /* First implementation: Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. - Build up a list of required and optional attributes from each objectclass - Check all required one for the defined objectclass and all its parent + Build up a list of required_attrs and optional_attrs attributes from each objectclass + Check all required_attrs one for the defined objectclass and all its parent objectclasses. - Check all other the attributes are optional or required. + Check all other the attributes are optional_attrs or required_attrs. Throw an error in case a check fail. Free all structures and commit the change. */ @@ -456,133 +430,65 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return -1; } - /* allocate modification entry structs */ - modify_structs = talloc_zero(entry_structs, struct schema_structures); - if (!modify_structs) { - talloc_free(entry_structs); - return -1; - } - - /* get list of values to modify */ - ret = get_check_list(module, modify_structs, msg); - if (ret != 0) { - talloc_free(entry_structs); - return ret; - } - - /* find all modify objectclasses recursively if any objectclass is being added */ - ret = get_attr_list_recursive(module, module->ldb, modify_structs); + /* now search for the stored entry objectclasses and attributes*/ + ret = get_entry_attributes(module->ldb, msg->dn, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now search for the original object objectclasses */ - ret = get_object_objectclasses(module->ldb, msg->dn, entry_structs); + /* get list of values to modify */ + ret = get_msg_attributes(entry_structs, msg); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* find all other objectclasses recursively */ - ret = get_attr_list_recursive(module, module->ldb, entry_structs); + ret = get_attr_list_recursive(module, entry_structs); if (ret != 0) { talloc_free(entry_structs); return ret; } - /* now check all entries are present either as required or optional atributes of entry objectclasses */ - /* if they are required and we are going to delete them then throw an error */ - /* just mark them if being proved valid attribs */ - for (i = 0; i < modify_structs->check_list_num; i++) { - struct attribute_list *attr; + /* now check all required_attrs attributes are present */ + for (i = 0; i < entry_structs->required_attrs.num; i++) { + struct schema_attribute *attr; - attr = schema_find_attribute(entry_structs->must, - entry_structs->must_num, - modify_structs->check_list[i].name); + attr = schema_find_attribute(&entry_structs->entry_attrs, + entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - - attr = schema_find_attribute(entry_structs->may, - entry_structs->may_num, - modify_structs->check_list[i].name); - - if (attr != NULL) { /* found*/ - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } - - break; /* not found, go on */ - } - - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - modify_structs->check_list[i].name); - - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } - - /* now check all new objectclasses required attributes are present */ - for (i = 0; i < modify_structs->must_num; i++) { - struct attribute_list *attr; - - attr = schema_find_attribute(modify_structs->check_list, - modify_structs->check_list_num, - modify_structs->must[i].name); - - - if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "The required attribute %s is missing.\n", - modify_structs->must[i].name); + "The required_attrs attribute %s is missing.\n", + entry_structs->required_attrs.attr[i].name); data->error_string = "Objectclass violation, a required attribute is missing"; talloc_free(entry_structs); return -1; } - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) == SCHEMA_FLAG_MOD_DELETE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - modify_structs->must[i].name); - - data->error_string = "Objectclass violation: trying to delete a required attribute"; - talloc_free(entry_structs); - return -1; - } - - attr->flags |= SCHEMA_FLAG_CHECKED; + /* mark the attribute as checked */ + attr->flags = SCHEMA_FLAG_CHECKED; } - /* now check all others attributes are at least optional */ - for (i = 0; i < modify_structs->check_list_num; i++) { - - if ((modify_structs->check_list[i].flags & SCHEMA_FLAG_CHECKED) == 0 && - (modify_structs->check_list[i].flags & SCHEMA_FLAG_MOD_MASK) != SCHEMA_FLAG_MOD_DELETE) { - struct attribute_list *attr; + /* now check all others atribs are at least optional_attrs */ + for (i = 0; i < entry_structs->entry_attrs.num; i++) { - attr = schema_find_attribute(modify_structs->may, - modify_structs->may_num, - modify_structs->check_list[i].name); + if (entry_structs->entry_attrs.attr[i].flags != SCHEMA_FLAG_CHECKED) { + struct schema_attribute *attr; + attr = schema_find_attribute(&entry_structs->optional_attrs, + entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "The attribute %s is not referenced by any objectclass.\n", - modify_structs->check_list[i].name); + entry_structs->entry_attrs.attr[i].name); data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); return -1; } - - modify_structs->check_list[i].flags |= SCHEMA_FLAG_CHECKED; - } } -- cgit From bc2ae4e4cd96311a028486cac78960142e9b41c5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 19 Jan 2005 22:56:14 +0000 Subject: r4862: - better structure schema tests - fix check for deletion of required attributes on modify removed by mistake with the previous commits (This used to be commit 0315159daf157b64ef3452372dd74199600e24b8) --- source4/lib/ldb/modules/schema.c | 16 +- source4/lib/ldb/tests/schema-add-test.ldif | 66 --- source4/lib/ldb/tests/schema-mod-test.ldif | 25 - .../ldb/tests/schema-tests/schema-add-test.ldif | 66 +++ .../ldb/tests/schema-tests/schema-mod-test-1.ldif | 5 + .../ldb/tests/schema-tests/schema-mod-test-2.ldif | 5 + .../ldb/tests/schema-tests/schema-mod-test-3.ldif | 5 + .../ldb/tests/schema-tests/schema-mod-test-4.ldif | 5 + .../ldb/tests/schema-tests/schema-mod-test-5.ldif | 5 + source4/lib/ldb/tests/schema-tests/schema.ldif | 634 +++++++++++++++++++++ source4/lib/ldb/tests/schema.ldif | 634 --------------------- source4/lib/ldb/tests/test-schema.sh | 19 +- 12 files changed, 754 insertions(+), 731 deletions(-) delete mode 100644 source4/lib/ldb/tests/schema-add-test.ldif delete mode 100644 source4/lib/ldb/tests/schema-mod-test.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-add-test.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-mod-test-1.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-mod-test-2.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-mod-test-3.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-mod-test-4.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema-mod-test-5.ldif create mode 100644 source4/lib/ldb/tests/schema-tests/schema.ldif delete mode 100644 source4/lib/ldb/tests/schema.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index b16849c2fe..86dc617d99 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -371,6 +371,18 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } + /* check we are not trying to delete a required attribute */ + /* TODO: consider multivalued attrs */ + if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + attr->name); + + data->error_string = "Objectclass violation, a required attribute cannot be removed"; + talloc_free(entry_structs); + return -1; + } + /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -413,9 +425,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Retrieve the ldap entry and get the objectclasses, add msg contained objectclasses if any. Build up a list of required_attrs and optional_attrs attributes from each objectclass - Check all required_attrs one for the defined objectclass and all its parent - objectclasses. - Check all other the attributes are optional_attrs or required_attrs. + Check all the attributes are optional_attrs or required_attrs. Throw an error in case a check fail. Free all structures and commit the change. */ diff --git a/source4/lib/ldb/tests/schema-add-test.ldif b/source4/lib/ldb/tests/schema-add-test.ldif deleted file mode 100644 index 997b801d84..0000000000 --- a/source4/lib/ldb/tests/schema-add-test.ldif +++ /dev/null @@ -1,66 +0,0 @@ -dn: CN=Users,DC=schema,DC=test -objectClass: top -objectClass: container -cn: Users -description: Default container for upgraded user accounts -instanceType: 4 -whenCreated: 20050116175504.0Z -whenChanged: 20050116175504.0Z -uSNCreated: 1 -uSNChanged: 1 -showInAdvancedViewOnly: FALSE -name: Users -objectGUID: b847056a-9934-d87b-8a1a-99fabe0863c8 -systemFlags: 0x8c000000 -objectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test -isCriticalSystemObject: TRUE -nTSecurityDescriptor: foo - -dn: CN=Administrator,CN=Users,DC=schema,DC=test -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: user -cn: Administrator -description: Built-in account for administering the computer/domain -instanceType: 4 -whenCreated: 20050116175504.0Z -whenChanged: 20050116175504.0Z -uSNCreated: 1 -memberOf: CN=Group Policy Creator Owners,CN=Users,DC=schema,DC=test -memberOf: CN=Domain Admins,CN=Users,DC=schema,DC=test -memberOf: CN=Enterprise Admins,CN=Users,DC=schema,DC=test -memberOf: CN=Schema Admins,CN=Users,DC=schema,DC=test -memberOf: CN=Administrators,CN=Builtin,DC=schema,DC=test -uSNChanged: 1 -name: Administrator -objectGUID: 6c02f98c-46c6-aa38-5f13-a510cac04e6c -userAccountControl: 0x10200 -badPwdCount: 0 -codePage: 0 -countryCode: 0 -badPasswordTime: 0 -lastLogoff: 0 -lastLogon: 0 -pwdLastSet: 0 -primaryGroupID: 513 -objectSid: S-1-5-21-43662522-77495566-38969261-500 -adminCount: 1 -accountExpires: -1 -logonCount: 0 -sAMAccountName: Administrator -sAMAccountType: 0x30000000 -objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test -isCriticalSystemObject: TRUE -unicodePwd: samba -nTSecurityDescriptor: foo - -dn: CN=Test,CN=Users,DC=schema,DC=test -objectClass: top -objectClass: test -cn: Test -description: This is a test -objectCategory: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test -nTSecurityDescriptor: foo -instanceType: 4 - diff --git a/source4/lib/ldb/tests/schema-mod-test.ldif b/source4/lib/ldb/tests/schema-mod-test.ldif deleted file mode 100644 index 8e36de7bf5..0000000000 --- a/source4/lib/ldb/tests/schema-mod-test.ldif +++ /dev/null @@ -1,25 +0,0 @@ -dn: CN=Test,CN=Users,DC=schema,DC=test -changetype: modify -replace: description -description: this test must not fail - -dn: CN=Test,CN=Users,DC=schema,DC=test -changetype: modify -delete: description -# this test must not fail - -dn: CN=Test,CN=Users,DC=schema,DC=test -changetype: modify -add: description -description: this test must not fail - -dn: CN=Test,CN=Users,DC=schema,DC=test -changetype: modify -add: foo -foo: this test must fail - -dn: CN=Test,CN=Users,DC=schema,DC=test -changetype: modify -delete: nTSecurityDescriptor -# this test must fail - diff --git a/source4/lib/ldb/tests/schema-tests/schema-add-test.ldif b/source4/lib/ldb/tests/schema-tests/schema-add-test.ldif new file mode 100644 index 0000000000..997b801d84 --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-add-test.ldif @@ -0,0 +1,66 @@ +dn: CN=Users,DC=schema,DC=test +objectClass: top +objectClass: container +cn: Users +description: Default container for upgraded user accounts +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +uSNChanged: 1 +showInAdvancedViewOnly: FALSE +name: Users +objectGUID: b847056a-9934-d87b-8a1a-99fabe0863c8 +systemFlags: 0x8c000000 +objectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +nTSecurityDescriptor: foo + +dn: CN=Administrator,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: person +objectClass: organizationalPerson +objectClass: user +cn: Administrator +description: Built-in account for administering the computer/domain +instanceType: 4 +whenCreated: 20050116175504.0Z +whenChanged: 20050116175504.0Z +uSNCreated: 1 +memberOf: CN=Group Policy Creator Owners,CN=Users,DC=schema,DC=test +memberOf: CN=Domain Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Enterprise Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Schema Admins,CN=Users,DC=schema,DC=test +memberOf: CN=Administrators,CN=Builtin,DC=schema,DC=test +uSNChanged: 1 +name: Administrator +objectGUID: 6c02f98c-46c6-aa38-5f13-a510cac04e6c +userAccountControl: 0x10200 +badPwdCount: 0 +codePage: 0 +countryCode: 0 +badPasswordTime: 0 +lastLogoff: 0 +lastLogon: 0 +pwdLastSet: 0 +primaryGroupID: 513 +objectSid: S-1-5-21-43662522-77495566-38969261-500 +adminCount: 1 +accountExpires: -1 +logonCount: 0 +sAMAccountName: Administrator +sAMAccountType: 0x30000000 +objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +isCriticalSystemObject: TRUE +unicodePwd: samba +nTSecurityDescriptor: foo + +dn: CN=Test,CN=Users,DC=schema,DC=test +objectClass: top +objectClass: test +cn: Test +description: This is a test +objectCategory: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +nTSecurityDescriptor: foo +instanceType: 4 + diff --git a/source4/lib/ldb/tests/schema-tests/schema-mod-test-1.ldif b/source4/lib/ldb/tests/schema-tests/schema-mod-test-1.ldif new file mode 100644 index 0000000000..b976724485 --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-mod-test-1.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +replace: description +description: this test must not fail + diff --git a/source4/lib/ldb/tests/schema-tests/schema-mod-test-2.ldif b/source4/lib/ldb/tests/schema-tests/schema-mod-test-2.ldif new file mode 100644 index 0000000000..fa193af683 --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-mod-test-2.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: description +# this test must not fail + diff --git a/source4/lib/ldb/tests/schema-tests/schema-mod-test-3.ldif b/source4/lib/ldb/tests/schema-tests/schema-mod-test-3.ldif new file mode 100644 index 0000000000..8ab7798f9c --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-mod-test-3.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: description +description: this test must not fail + diff --git a/source4/lib/ldb/tests/schema-tests/schema-mod-test-4.ldif b/source4/lib/ldb/tests/schema-tests/schema-mod-test-4.ldif new file mode 100644 index 0000000000..cbf0e60bbe --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-mod-test-4.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +add: foo +foo: this test must fail + diff --git a/source4/lib/ldb/tests/schema-tests/schema-mod-test-5.ldif b/source4/lib/ldb/tests/schema-tests/schema-mod-test-5.ldif new file mode 100644 index 0000000000..bc64e9edb6 --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema-mod-test-5.ldif @@ -0,0 +1,5 @@ +dn: CN=Test,CN=Users,DC=schema,DC=test +changetype: modify +delete: nTSecurityDescriptor +# this test must fail + diff --git a/source4/lib/ldb/tests/schema-tests/schema.ldif b/source4/lib/ldb/tests/schema-tests/schema.ldif new file mode 100644 index 0000000000..2661ae30c5 --- /dev/null +++ b/source4/lib/ldb/tests/schema-tests/schema.ldif @@ -0,0 +1,634 @@ +dn: @INDEXLIST +@IDXATTR: name +@IDXATTR: sAMAccountName +@IDXATTR: objectSid +@IDXATTR: objectClass +@IDXATTR: member +@IDXATTR: unixID +@IDXATTR: unixName +@IDXATTR: privilege + +dn: @ATTRIBUTES +realm: CASE_INSENSITIVE +userPrincipalName: CASE_INSENSITIVE +servicePrincipalName: CASE_INSENSITIVE +name: CASE_INSENSITIVE WILDCARD +dn: CASE_INSENSITIVE WILDCARD +sAMAccountName: CASE_INSENSITIVE WILDCARD +objectClass: CASE_INSENSITIVE +unicodePwd: HIDDEN +ntPwdHash: HIDDEN +ntPwdHistory: HIDDEN +lmPwdHash: HIDDEN +lmPwdHistory: HIDDEN +createTimestamp: HIDDEN +modifyTimestamp: HIDDEN + +dn: @SUBCLASSES +top: domain +top: person +top: group +domain: domainDNS +domain: builtinDomain +person: organizationalPerson +organizationalPerson: user +user: computer +template: userTemplate +template: groupTemplate + +dn: @MODULES +@MODULE: timestamps +@MODULE: schema + +# Top, Schema, Configuration, schema, test +dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Top +distinguishedName: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175509.0Z +whenChanged: 20050116175509.0Z +uSNCreated: 1437 +subClassOf: top +governsID: 2.5.6.0 +mayContain: msDS-ObjectReferenceBL +rDNAttID: cn +uSNChanged: 1437 +showInAdvancedViewOnly: TRUE +adminDisplayName: Top +adminDescription: Top +objectClassCategory: 2 +lDAPDisplayName: top +name: Top +objectGUID: 8b12f9c3-008f-2b4f-b32b-dddd2e396ea8 +schemaIDGUID: dafbc8ff-64e9-d2cb-4569-4ba91d60aa83 +systemOnly: TRUE +systemPossSuperiors: lostAndFound +systemMayContain: url +systemMayContain: wWWHomePage +systemMayContain: whenCreated +systemMayContain: whenChanged +systemMayContain: wellKnownObjects +systemMayContain: wbemPath +systemMayContain: uSNSource +systemMayContain: uSNLastObjRem +systemMayContain: USNIntersite +systemMayContain: uSNDSALastObjRemoved +systemMayContain: uSNCreated +systemMayContain: uSNChanged +systemMayContain: systemFlags +systemMayContain: subSchemaSubEntry +systemMayContain: subRefs +systemMayContain: structuralObjectClass +systemMayContain: siteObjectBL +systemMayContain: serverReferenceBL +systemMayContain: sDRightsEffective +systemMayContain: revision +systemMayContain: repsTo +systemMayContain: repsFrom +systemMayContain: directReports +systemMayContain: replUpToDateVector +systemMayContain: replPropertyMetaData +systemMayContain: name +systemMayContain: queryPolicyBL +systemMayContain: proxyAddresses +systemMayContain: proxiedObjectName +systemMayContain: possibleInferiors +systemMayContain: partialAttributeSet +systemMayContain: partialAttributeDeletionList +systemMayContain: otherWellKnownObjects +systemMayContain: objectVersion +systemMayContain: objectGUID +systemMayContain: distinguishedName +systemMayContain: nonSecurityMemberBL +systemMayContain: netbootSCPBL +systemMayContain: ownerBL +systemMayContain: msDS-ReplValueMetaData +systemMayContain: msDS-ReplAttributeMetaData +systemMayContain: msDS-NonMembersBL +systemMayContain: msDS-NCReplOutboundNeighbors +systemMayContain: msDS-NCReplInboundNeighbors +systemMayContain: msDS-NCReplCursors +systemMayContain: msDS-TasksForAzRoleBL +systemMayContain: msDS-TasksForAzTaskBL +systemMayContain: msDS-OperationsForAzRoleBL +systemMayContain: msDS-OperationsForAzTaskBL +systemMayContain: msDS-MembersForAzRoleBL +systemMayContain: msDs-masteredBy +systemMayContain: mS-DS-ConsistencyGuid +systemMayContain: mS-DS-ConsistencyChildCount +systemMayContain: msDS-Approx-Immed-Subordinates +systemMayContain: msCOM-PartitionSetLink +systemMayContain: msCOM-UserLink +systemMayContain: modifyTimeStamp +systemMayContain: masteredBy +systemMayContain: managedObjects +systemMayContain: lastKnownParent +systemMayContain: isPrivilegeHolder +systemMayContain: memberOf +systemMayContain: isDeleted +systemMayContain: isCriticalSystemObject +systemMayContain: showInAdvancedViewOnly +systemMayContain: fSMORoleOwner +systemMayContain: fRSMemberReferenceBL +systemMayContain: frsComputerReferenceBL +systemMayContain: fromEntry +systemMayContain: flags +systemMayContain: extensionName +systemMayContain: dSASignature +systemMayContain: dSCorePropagationData +systemMayContain: displayNamePrintable +systemMayContain: displayName +systemMayContain: description +systemMayContain: createTimeStamp +systemMayContain: cn +systemMayContain: canonicalName +systemMayContain: bridgeheadServerListBL +systemMayContain: allowedChildClassesEffective +systemMayContain: allowedChildClasses +systemMayContain: allowedAttributesEffective +systemMayContain: allowedAttributes +systemMayContain: adminDisplayName +systemMayContain: adminDescription +systemMustContain: objectClass +systemMustContain: objectCategory +systemMustContain: nTSecurityDescriptor +systemMustContain: instanceType +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,${BASEDN} +defaultObjectCategory: CN=Top,CN=Schema,CN=Configuration,${BASEDN} + +# Container, Schema, Configuration, schema, test +dn: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Container +distinguishedName: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1113 +subClassOf: top +governsID: 1.2.840.113556.1.3.23 +mayContain: msDS-ObjectReference +rDNAttID: cn +uSNChanged: 1114 +showInAdvancedViewOnly: TRUE +adminDisplayName: Container +adminDescription: Container +objectClassCategory: 1 +lDAPDisplayName: container +name: Container +objectGUID: 48a16bf7-0128-6605-ad1a-9f5ab97b0b62 +schemaIDGUID: 3f619f8c-f7d6-6b1b-8674-b4f91b0e3755 +systemOnly: FALSE +systemPossSuperiors: msDS-AzScope +systemPossSuperiors: msDS-AzApplication +systemPossSuperiors: msDS-AzAdminManager +systemPossSuperiors: subnet +systemPossSuperiors: server +systemPossSuperiors: nTDSService +systemPossSuperiors: domainDNS +systemPossSuperiors: organization +systemPossSuperiors: configuration +systemPossSuperiors: container +systemPossSuperiors: organizationalUnit +systemMayContain: schemaVersion +systemMayContain: defaultClassStore +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Class-Schema, Schema, Configuration, schema, test +dn: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Class-Schema +distinguishedName: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175530.0Z +whenChanged: 20050116175530.0Z +uSNCreated: 673 +subClassOf: top +governsID: 1.2.840.113556.1.3.13 +rDNAttID: cn +uSNChanged: 674 +showInAdvancedViewOnly: TRUE +adminDisplayName: Class-Schema +adminDescription: Class-Schema +objectClassCategory: 1 +lDAPDisplayName: classSchema +name: Class-Schema +objectGUID: 63151723-143e-98ab-2e14-f6df3e9c8458 +schemaIDGUID: 44cd522f-747f-e071-ff4b-b8beddfaae75 +systemOnly: FALSE +systemPossSuperiors: dMD +systemMayContain: systemPossSuperiors +systemMayContain: systemOnly +systemMayContain: systemMustContain +systemMayContain: systemMayContain +systemMayContain: systemAuxiliaryClass +systemMayContain: schemaFlagsEx +systemMayContain: rDNAttID +systemMayContain: possSuperiors +systemMayContain: mustContain +systemMayContain: msDs-Schema-Extensions +systemMayContain: msDS-IntId +systemMayContain: mayContain +systemMayContain: lDAPDisplayName +systemMayContain: isDefunct +systemMayContain: defaultSecurityDescriptor +systemMayContain: defaultHidingValue +systemMayContain: classDisplayName +systemMayContain: auxiliaryClass +systemMustContain: subClassOf +systemMustContain: schemaIDGUID +systemMustContain: objectClassCategory +systemMustContain: governsID +systemMustContain: defaultObjectCategory +systemMustContain: cn +defaultSecurityDescriptor: D:S: +systemFlags: 134217744 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Person, Schema, Configuration, schema, test +dn: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Person +distinguishedName: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1093 +subClassOf: top +governsID: 2.5.6.6 +mayContain: attributeCertificateAttribute +rDNAttID: cn +uSNChanged: 1094 +showInAdvancedViewOnly: TRUE +adminDisplayName: Person +adminDescription: Person +objectClassCategory: 0 +lDAPDisplayName: person +name: Person +objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 +schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: container +systemMayContain: userPassword +systemMayContain: telephoneNumber +systemMayContain: sn +systemMayContain: serialNumber +systemMayContain: seeAlso +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Organizational-Person, Schema, Configuration, schema, test +dn: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Organizational-Person +distinguishedName: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175533.0Z +whenChanged: 20050116175533.0Z +uSNCreated: 795 +subClassOf: person +governsID: 2.5.6.7 +mayContain: houseIdentifier +mayContain: msExchHouseIdentifier +mayContain: homePostalAddress +rDNAttID: cn +uSNChanged: 796 +showInAdvancedViewOnly: TRUE +adminDisplayName: Organizational-Person +adminDescription: Organizational-Person +objectClassCategory: 0 +lDAPDisplayName: organizationalPerson +name: Organizational-Person +objectGUID: 91aaede0-136e-c1a0-9ac0-5ddd606a0cfc +schemaIDGUID: 6f71a564-de69-3971-c169-528d111a9f27 +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: organization +systemPossSuperiors: container +systemMayContain: x121Address +systemMayContain: comment +systemMayContain: title +systemMayContain: co +systemMayContain: primaryTelexNumber +systemMayContain: telexNumber +systemMayContain: teletexTerminalIdentifier +systemMayContain: street +systemMayContain: st +systemMayContain: registeredAddress +systemMayContain: preferredDeliveryMethod +systemMayContain: postalCode +systemMayContain: postalAddress +systemMayContain: postOfficeBox +systemMayContain: thumbnailPhoto +systemMayContain: physicalDeliveryOfficeName +systemMayContain: pager +systemMayContain: otherPager +systemMayContain: otherTelephone +systemMayContain: mobile +systemMayContain: otherMobile +systemMayContain: primaryInternationalISDNNumber +systemMayContain: ipPhone +systemMayContain: otherIpPhone +systemMayContain: otherHomePhone +systemMayContain: homePhone +systemMayContain: otherFacsimileTelephoneNumber +systemMayContain: personalTitle +systemMayContain: middleName +systemMayContain: otherMailbox +systemMayContain: ou +systemMayContain: o +systemMayContain: mhsORAddress +systemMayContain: msDS-AllowedToDelegateTo +systemMayContain: manager +systemMayContain: thumbnailLogo +systemMayContain: l +systemMayContain: internationalISDNNumber +systemMayContain: initials +systemMayContain: givenName +systemMayContain: generationQualifier +systemMayContain: facsimileTelephoneNumber +systemMayContain: employeeID +systemMayContain: mail +systemMayContain: division +systemMayContain: destinationIndicator +systemMayContain: department +systemMayContain: c +systemMayContain: countryCode +systemMayContain: company +systemMayContain: assistant +systemMayContain: streetAddress +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# User, Schema, Configuration, schema, test +dn: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: User +distinguishedName: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175549.0Z +whenChanged: 20050116175549.0Z +uSNCreated: 1442 +subClassOf: organizationalPerson +governsID: 1.2.840.113556.1.5.9 +mayContain: x500uniqueIdentifier +mayContain: userSMIMECertificate +mayContain: userPKCS12 +mayContain: uid +mayContain: secretary +mayContain: roomNumber +mayContain: preferredLanguage +mayContain: photo +mayContain: labeledURI +mayContain: jpegPhoto +mayContain: homePostalAddress +mayContain: givenName +mayContain: employeeType +mayContain: employeeNumber +mayContain: displayName +mayContain: departmentNumber +mayContain: carLicense +mayContain: audio +rDNAttID: cn +uSNChanged: 1442 +showInAdvancedViewOnly: TRUE +adminDisplayName: User +adminDescription: User +objectClassCategory: 1 +lDAPDisplayName: user +name: User +objectGUID: 2cc46512-6733-eb01-ce05-213403264ea4 +schemaIDGUID: e8a42693-9d99-2091-5554-eef0548c0b65 +systemOnly: FALSE +systemPossSuperiors: builtinDomain +systemPossSuperiors: organizationalUnit +systemPossSuperiors: domainDNS +systemMayContain: pager +systemMayContain: o +systemMayContain: mobile +systemMayContain: manager +systemMayContain: mail +systemMayContain: initials +systemMayContain: homePhone +systemMayContain: businessCategory +systemMayContain: userCertificate +systemMayContain: userWorkstations +systemMayContain: userSharedFolderOther +systemMayContain: userSharedFolder +systemMayContain: userPrincipalName +systemMayContain: userParameters +systemMayContain: userAccountControl +systemMayContain: unicodePwd +systemMayContain: terminalServer +systemMayContain: servicePrincipalName +systemMayContain: scriptPath +systemMayContain: pwdLastSet +systemMayContain: profilePath +systemMayContain: primaryGroupID +systemMayContain: preferredOU +systemMayContain: otherLoginWorkstations +systemMayContain: operatorCount +systemMayContain: ntPwdHistory +systemMayContain: networkAddress +systemMayContain: msRASSavedFramedRoute +systemMayContain: msRASSavedFramedIPAddress +systemMayContain: msRASSavedCallbackNumber +systemMayContain: msRADIUSServiceType +systemMayContain: msRADIUSFramedRoute +systemMayContain: msRADIUSFramedIPAddress +systemMayContain: msRADIUSCallbackNumber +systemMayContain: msNPSavedCallingStationID +systemMayContain: msNPCallingStationID +systemMayContain: msNPAllowDialin +systemMayContain: mSMQSignCertificatesMig +systemMayContain: mSMQSignCertificates +systemMayContain: mSMQDigestsMig +systemMayContain: mSMQDigests +systemMayContain: msIIS-FTPRoot +systemMayContain: msIIS-FTPDir +systemMayContain: msDS-User-Account-Control-Computed +systemMayContain: msDS-Site-Affinity +systemMayContain: mS-DS-CreatorSID +systemMayContain: msDS-Cached-Membership-Time-Stamp +systemMayContain: msDS-Cached-Membership +systemMayContain: msDRM-IdentityCertificate +systemMayContain: msCOM-UserPartitionSetLink +systemMayContain: maxStorage +systemMayContain: logonWorkstation +systemMayContain: logonHours +systemMayContain: logonCount +systemMayContain: lockoutTime +systemMayContain: localeID +systemMayContain: lmPwdHistory +systemMayContain: lastLogonTimestamp +systemMayContain: lastLogon +systemMayContain: lastLogoff +systemMayContain: homeDrive +systemMayContain: homeDirectory +systemMayContain: groupsToIgnore +systemMayContain: groupPriority +systemMayContain: groupMembershipSAM +systemMayContain: dynamicLDAPServer +systemMayContain: desktopProfile +systemMayContain: defaultClassStore +systemMayContain: dBCSPwd +systemMayContain: controlAccessRights +systemMayContain: codePage +systemMayContain: badPwdCount +systemMayContain: badPasswordTime +systemMayContain: adminCount +systemMayContain: aCSPolicyName +systemMayContain: accountExpires +systemAuxiliaryClass: securityPrincipal +systemAuxiliaryClass: mailRecipient +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a54-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a56-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;RPWP;77B5B886-944A-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B2-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B3-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;;RS)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;;RS)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;;RS)(A;;RC;;;AU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;;AU)(OA;;RP;77B5B886-944A-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;E45795B3-9455-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;AU)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)(OA;;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;;RS)(OA;;RPWP;bf967a7f-0de6-11d0-a285-00aa003049e2;;CA)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(OA;;WPRP;6db69a1c-9422-11d1-aebd-0000f80367c1;;S-1-5-32-561) +systemFlags: 16 +defaultHidingValue: FALSE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Security-Principal, Schema, Configuration, schema, test +dn: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Security-Principal +distinguishedName: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175546.0Z +whenChanged: 20050116175546.0Z +uSNCreated: 1406 +subClassOf: top +governsID: 1.2.840.113556.1.5.6 +rDNAttID: cn +uSNChanged: 1406 +showInAdvancedViewOnly: TRUE +adminDisplayName: Security-Principal +adminDescription: Security-Principal +objectClassCategory: 3 +lDAPDisplayName: securityPrincipal +name: Security-Principal +objectGUID: d1a6ae33-f6d5-197f-93d6-923d07d64c1a +schemaIDGUID: eb3adbfa-fb52-71a6-054f-b077e32c73f1 +systemOnly: FALSE +systemMayContain: supplementalCredentials +systemMayContain: sIDHistory +systemMayContain: securityIdentifier +systemMayContain: sAMAccountType +systemMayContain: rid +systemMayContain: tokenGroupsNoGCAcceptable +systemMayContain: tokenGroupsGlobalAndUniversal +systemMayContain: tokenGroups +systemMayContain: nTSecurityDescriptor +systemMayContain: msDS-KeyVersionNumber +systemMayContain: altSecurityIdentities +systemMayContain: accountNameHistory +systemMustContain: sAMAccountName +systemMustContain: objectSid +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Mail-Recipient, Schema, Configuration, schema, test +dn: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Mail-Recipient +distinguishedName: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175550.0Z +whenChanged: 20050116175550.0Z +uSNCreated: 1222 +subClassOf: top +governsID: 1.2.840.113556.1.3.46 +mayContain: userSMIMECertificate +mayContain: secretary +mayContain: msExchLabeledURI +mayContain: msExchAssistantName +mayContain: labeledURI +rDNAttID: cn +uSNChanged: 1222 +showInAdvancedViewOnly: TRUE +adminDisplayName: Mail-Recipient +adminDescription: Mail-Recipient +objectClassCategory: 3 +lDAPDisplayName: mailRecipient +name: Mail-Recipient +objectGUID: 79f6fa6e-c08d-5c1f-47ff-6b33be595f50 +schemaIDGUID: bcdded89-7f72-0166-da62-08647c98fcf9 +systemOnly: FALSE +systemPossSuperiors: container +systemMayContain: userCertificate +systemMayContain: userCert +systemMayContain: textEncodedORAddress +systemMayContain: telephoneNumber +systemMayContain: showInAddressBook +systemMayContain: legacyExchangeDN +systemMayContain: garbageCollPeriod +systemMayContain: info +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test + +# Test, Schema, Configuration, schema, test +dn: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +objectClass: top +objectClass: classSchema +cn: Test +distinguishedName: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +instanceType: 4 +whenCreated: 20050116175540.0Z +whenChanged: 20050116175540.0Z +uSNCreated: 1093 +subClassOf: top +governsID: 2.5.6.6 +mayContain: test +rDNAttID: cn +uSNChanged: 1094 +showInAdvancedViewOnly: TRUE +adminDisplayName: Test +adminDescription: Test +objectClassCategory: 0 +lDAPDisplayName: test +name: Test +objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 +schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a +systemOnly: FALSE +systemPossSuperiors: organizationalUnit +systemPossSuperiors: container +systemMayContain: description +systemMustContain: cn +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test +defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test + diff --git a/source4/lib/ldb/tests/schema.ldif b/source4/lib/ldb/tests/schema.ldif deleted file mode 100644 index 2661ae30c5..0000000000 --- a/source4/lib/ldb/tests/schema.ldif +++ /dev/null @@ -1,634 +0,0 @@ -dn: @INDEXLIST -@IDXATTR: name -@IDXATTR: sAMAccountName -@IDXATTR: objectSid -@IDXATTR: objectClass -@IDXATTR: member -@IDXATTR: unixID -@IDXATTR: unixName -@IDXATTR: privilege - -dn: @ATTRIBUTES -realm: CASE_INSENSITIVE -userPrincipalName: CASE_INSENSITIVE -servicePrincipalName: CASE_INSENSITIVE -name: CASE_INSENSITIVE WILDCARD -dn: CASE_INSENSITIVE WILDCARD -sAMAccountName: CASE_INSENSITIVE WILDCARD -objectClass: CASE_INSENSITIVE -unicodePwd: HIDDEN -ntPwdHash: HIDDEN -ntPwdHistory: HIDDEN -lmPwdHash: HIDDEN -lmPwdHistory: HIDDEN -createTimestamp: HIDDEN -modifyTimestamp: HIDDEN - -dn: @SUBCLASSES -top: domain -top: person -top: group -domain: domainDNS -domain: builtinDomain -person: organizationalPerson -organizationalPerson: user -user: computer -template: userTemplate -template: groupTemplate - -dn: @MODULES -@MODULE: timestamps -@MODULE: schema - -# Top, Schema, Configuration, schema, test -dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Top -distinguishedName: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175509.0Z -whenChanged: 20050116175509.0Z -uSNCreated: 1437 -subClassOf: top -governsID: 2.5.6.0 -mayContain: msDS-ObjectReferenceBL -rDNAttID: cn -uSNChanged: 1437 -showInAdvancedViewOnly: TRUE -adminDisplayName: Top -adminDescription: Top -objectClassCategory: 2 -lDAPDisplayName: top -name: Top -objectGUID: 8b12f9c3-008f-2b4f-b32b-dddd2e396ea8 -schemaIDGUID: dafbc8ff-64e9-d2cb-4569-4ba91d60aa83 -systemOnly: TRUE -systemPossSuperiors: lostAndFound -systemMayContain: url -systemMayContain: wWWHomePage -systemMayContain: whenCreated -systemMayContain: whenChanged -systemMayContain: wellKnownObjects -systemMayContain: wbemPath -systemMayContain: uSNSource -systemMayContain: uSNLastObjRem -systemMayContain: USNIntersite -systemMayContain: uSNDSALastObjRemoved -systemMayContain: uSNCreated -systemMayContain: uSNChanged -systemMayContain: systemFlags -systemMayContain: subSchemaSubEntry -systemMayContain: subRefs -systemMayContain: structuralObjectClass -systemMayContain: siteObjectBL -systemMayContain: serverReferenceBL -systemMayContain: sDRightsEffective -systemMayContain: revision -systemMayContain: repsTo -systemMayContain: repsFrom -systemMayContain: directReports -systemMayContain: replUpToDateVector -systemMayContain: replPropertyMetaData -systemMayContain: name -systemMayContain: queryPolicyBL -systemMayContain: proxyAddresses -systemMayContain: proxiedObjectName -systemMayContain: possibleInferiors -systemMayContain: partialAttributeSet -systemMayContain: partialAttributeDeletionList -systemMayContain: otherWellKnownObjects -systemMayContain: objectVersion -systemMayContain: objectGUID -systemMayContain: distinguishedName -systemMayContain: nonSecurityMemberBL -systemMayContain: netbootSCPBL -systemMayContain: ownerBL -systemMayContain: msDS-ReplValueMetaData -systemMayContain: msDS-ReplAttributeMetaData -systemMayContain: msDS-NonMembersBL -systemMayContain: msDS-NCReplOutboundNeighbors -systemMayContain: msDS-NCReplInboundNeighbors -systemMayContain: msDS-NCReplCursors -systemMayContain: msDS-TasksForAzRoleBL -systemMayContain: msDS-TasksForAzTaskBL -systemMayContain: msDS-OperationsForAzRoleBL -systemMayContain: msDS-OperationsForAzTaskBL -systemMayContain: msDS-MembersForAzRoleBL -systemMayContain: msDs-masteredBy -systemMayContain: mS-DS-ConsistencyGuid -systemMayContain: mS-DS-ConsistencyChildCount -systemMayContain: msDS-Approx-Immed-Subordinates -systemMayContain: msCOM-PartitionSetLink -systemMayContain: msCOM-UserLink -systemMayContain: modifyTimeStamp -systemMayContain: masteredBy -systemMayContain: managedObjects -systemMayContain: lastKnownParent -systemMayContain: isPrivilegeHolder -systemMayContain: memberOf -systemMayContain: isDeleted -systemMayContain: isCriticalSystemObject -systemMayContain: showInAdvancedViewOnly -systemMayContain: fSMORoleOwner -systemMayContain: fRSMemberReferenceBL -systemMayContain: frsComputerReferenceBL -systemMayContain: fromEntry -systemMayContain: flags -systemMayContain: extensionName -systemMayContain: dSASignature -systemMayContain: dSCorePropagationData -systemMayContain: displayNamePrintable -systemMayContain: displayName -systemMayContain: description -systemMayContain: createTimeStamp -systemMayContain: cn -systemMayContain: canonicalName -systemMayContain: bridgeheadServerListBL -systemMayContain: allowedChildClassesEffective -systemMayContain: allowedChildClasses -systemMayContain: allowedAttributesEffective -systemMayContain: allowedAttributes -systemMayContain: adminDisplayName -systemMayContain: adminDescription -systemMustContain: objectClass -systemMustContain: objectCategory -systemMustContain: nTSecurityDescriptor -systemMustContain: instanceType -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,${BASEDN} -defaultObjectCategory: CN=Top,CN=Schema,CN=Configuration,${BASEDN} - -# Container, Schema, Configuration, schema, test -dn: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Container -distinguishedName: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1113 -subClassOf: top -governsID: 1.2.840.113556.1.3.23 -mayContain: msDS-ObjectReference -rDNAttID: cn -uSNChanged: 1114 -showInAdvancedViewOnly: TRUE -adminDisplayName: Container -adminDescription: Container -objectClassCategory: 1 -lDAPDisplayName: container -name: Container -objectGUID: 48a16bf7-0128-6605-ad1a-9f5ab97b0b62 -schemaIDGUID: 3f619f8c-f7d6-6b1b-8674-b4f91b0e3755 -systemOnly: FALSE -systemPossSuperiors: msDS-AzScope -systemPossSuperiors: msDS-AzApplication -systemPossSuperiors: msDS-AzAdminManager -systemPossSuperiors: subnet -systemPossSuperiors: server -systemPossSuperiors: nTDSService -systemPossSuperiors: domainDNS -systemPossSuperiors: organization -systemPossSuperiors: configuration -systemPossSuperiors: container -systemPossSuperiors: organizationalUnit -systemMayContain: schemaVersion -systemMayContain: defaultClassStore -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Class-Schema, Schema, Configuration, schema, test -dn: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Class-Schema -distinguishedName: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175530.0Z -whenChanged: 20050116175530.0Z -uSNCreated: 673 -subClassOf: top -governsID: 1.2.840.113556.1.3.13 -rDNAttID: cn -uSNChanged: 674 -showInAdvancedViewOnly: TRUE -adminDisplayName: Class-Schema -adminDescription: Class-Schema -objectClassCategory: 1 -lDAPDisplayName: classSchema -name: Class-Schema -objectGUID: 63151723-143e-98ab-2e14-f6df3e9c8458 -schemaIDGUID: 44cd522f-747f-e071-ff4b-b8beddfaae75 -systemOnly: FALSE -systemPossSuperiors: dMD -systemMayContain: systemPossSuperiors -systemMayContain: systemOnly -systemMayContain: systemMustContain -systemMayContain: systemMayContain -systemMayContain: systemAuxiliaryClass -systemMayContain: schemaFlagsEx -systemMayContain: rDNAttID -systemMayContain: possSuperiors -systemMayContain: mustContain -systemMayContain: msDs-Schema-Extensions -systemMayContain: msDS-IntId -systemMayContain: mayContain -systemMayContain: lDAPDisplayName -systemMayContain: isDefunct -systemMayContain: defaultSecurityDescriptor -systemMayContain: defaultHidingValue -systemMayContain: classDisplayName -systemMayContain: auxiliaryClass -systemMustContain: subClassOf -systemMustContain: schemaIDGUID -systemMustContain: objectClassCategory -systemMustContain: governsID -systemMustContain: defaultObjectCategory -systemMustContain: cn -defaultSecurityDescriptor: D:S: -systemFlags: 134217744 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Person, Schema, Configuration, schema, test -dn: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Person -distinguishedName: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1093 -subClassOf: top -governsID: 2.5.6.6 -mayContain: attributeCertificateAttribute -rDNAttID: cn -uSNChanged: 1094 -showInAdvancedViewOnly: TRUE -adminDisplayName: Person -adminDescription: Person -objectClassCategory: 0 -lDAPDisplayName: person -name: Person -objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 -schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: container -systemMayContain: userPassword -systemMayContain: telephoneNumber -systemMayContain: sn -systemMayContain: serialNumber -systemMayContain: seeAlso -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Organizational-Person, Schema, Configuration, schema, test -dn: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Organizational-Person -distinguishedName: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175533.0Z -whenChanged: 20050116175533.0Z -uSNCreated: 795 -subClassOf: person -governsID: 2.5.6.7 -mayContain: houseIdentifier -mayContain: msExchHouseIdentifier -mayContain: homePostalAddress -rDNAttID: cn -uSNChanged: 796 -showInAdvancedViewOnly: TRUE -adminDisplayName: Organizational-Person -adminDescription: Organizational-Person -objectClassCategory: 0 -lDAPDisplayName: organizationalPerson -name: Organizational-Person -objectGUID: 91aaede0-136e-c1a0-9ac0-5ddd606a0cfc -schemaIDGUID: 6f71a564-de69-3971-c169-528d111a9f27 -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: organization -systemPossSuperiors: container -systemMayContain: x121Address -systemMayContain: comment -systemMayContain: title -systemMayContain: co -systemMayContain: primaryTelexNumber -systemMayContain: telexNumber -systemMayContain: teletexTerminalIdentifier -systemMayContain: street -systemMayContain: st -systemMayContain: registeredAddress -systemMayContain: preferredDeliveryMethod -systemMayContain: postalCode -systemMayContain: postalAddress -systemMayContain: postOfficeBox -systemMayContain: thumbnailPhoto -systemMayContain: physicalDeliveryOfficeName -systemMayContain: pager -systemMayContain: otherPager -systemMayContain: otherTelephone -systemMayContain: mobile -systemMayContain: otherMobile -systemMayContain: primaryInternationalISDNNumber -systemMayContain: ipPhone -systemMayContain: otherIpPhone -systemMayContain: otherHomePhone -systemMayContain: homePhone -systemMayContain: otherFacsimileTelephoneNumber -systemMayContain: personalTitle -systemMayContain: middleName -systemMayContain: otherMailbox -systemMayContain: ou -systemMayContain: o -systemMayContain: mhsORAddress -systemMayContain: msDS-AllowedToDelegateTo -systemMayContain: manager -systemMayContain: thumbnailLogo -systemMayContain: l -systemMayContain: internationalISDNNumber -systemMayContain: initials -systemMayContain: givenName -systemMayContain: generationQualifier -systemMayContain: facsimileTelephoneNumber -systemMayContain: employeeID -systemMayContain: mail -systemMayContain: division -systemMayContain: destinationIndicator -systemMayContain: department -systemMayContain: c -systemMayContain: countryCode -systemMayContain: company -systemMayContain: assistant -systemMayContain: streetAddress -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# User, Schema, Configuration, schema, test -dn: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: User -distinguishedName: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175549.0Z -whenChanged: 20050116175549.0Z -uSNCreated: 1442 -subClassOf: organizationalPerson -governsID: 1.2.840.113556.1.5.9 -mayContain: x500uniqueIdentifier -mayContain: userSMIMECertificate -mayContain: userPKCS12 -mayContain: uid -mayContain: secretary -mayContain: roomNumber -mayContain: preferredLanguage -mayContain: photo -mayContain: labeledURI -mayContain: jpegPhoto -mayContain: homePostalAddress -mayContain: givenName -mayContain: employeeType -mayContain: employeeNumber -mayContain: displayName -mayContain: departmentNumber -mayContain: carLicense -mayContain: audio -rDNAttID: cn -uSNChanged: 1442 -showInAdvancedViewOnly: TRUE -adminDisplayName: User -adminDescription: User -objectClassCategory: 1 -lDAPDisplayName: user -name: User -objectGUID: 2cc46512-6733-eb01-ce05-213403264ea4 -schemaIDGUID: e8a42693-9d99-2091-5554-eef0548c0b65 -systemOnly: FALSE -systemPossSuperiors: builtinDomain -systemPossSuperiors: organizationalUnit -systemPossSuperiors: domainDNS -systemMayContain: pager -systemMayContain: o -systemMayContain: mobile -systemMayContain: manager -systemMayContain: mail -systemMayContain: initials -systemMayContain: homePhone -systemMayContain: businessCategory -systemMayContain: userCertificate -systemMayContain: userWorkstations -systemMayContain: userSharedFolderOther -systemMayContain: userSharedFolder -systemMayContain: userPrincipalName -systemMayContain: userParameters -systemMayContain: userAccountControl -systemMayContain: unicodePwd -systemMayContain: terminalServer -systemMayContain: servicePrincipalName -systemMayContain: scriptPath -systemMayContain: pwdLastSet -systemMayContain: profilePath -systemMayContain: primaryGroupID -systemMayContain: preferredOU -systemMayContain: otherLoginWorkstations -systemMayContain: operatorCount -systemMayContain: ntPwdHistory -systemMayContain: networkAddress -systemMayContain: msRASSavedFramedRoute -systemMayContain: msRASSavedFramedIPAddress -systemMayContain: msRASSavedCallbackNumber -systemMayContain: msRADIUSServiceType -systemMayContain: msRADIUSFramedRoute -systemMayContain: msRADIUSFramedIPAddress -systemMayContain: msRADIUSCallbackNumber -systemMayContain: msNPSavedCallingStationID -systemMayContain: msNPCallingStationID -systemMayContain: msNPAllowDialin -systemMayContain: mSMQSignCertificatesMig -systemMayContain: mSMQSignCertificates -systemMayContain: mSMQDigestsMig -systemMayContain: mSMQDigests -systemMayContain: msIIS-FTPRoot -systemMayContain: msIIS-FTPDir -systemMayContain: msDS-User-Account-Control-Computed -systemMayContain: msDS-Site-Affinity -systemMayContain: mS-DS-CreatorSID -systemMayContain: msDS-Cached-Membership-Time-Stamp -systemMayContain: msDS-Cached-Membership -systemMayContain: msDRM-IdentityCertificate -systemMayContain: msCOM-UserPartitionSetLink -systemMayContain: maxStorage -systemMayContain: logonWorkstation -systemMayContain: logonHours -systemMayContain: logonCount -systemMayContain: lockoutTime -systemMayContain: localeID -systemMayContain: lmPwdHistory -systemMayContain: lastLogonTimestamp -systemMayContain: lastLogon -systemMayContain: lastLogoff -systemMayContain: homeDrive -systemMayContain: homeDirectory -systemMayContain: groupsToIgnore -systemMayContain: groupPriority -systemMayContain: groupMembershipSAM -systemMayContain: dynamicLDAPServer -systemMayContain: desktopProfile -systemMayContain: defaultClassStore -systemMayContain: dBCSPwd -systemMayContain: controlAccessRights -systemMayContain: codePage -systemMayContain: badPwdCount -systemMayContain: badPasswordTime -systemMayContain: adminCount -systemMayContain: aCSPolicyName -systemMayContain: accountExpires -systemAuxiliaryClass: securityPrincipal -systemAuxiliaryClass: mailRecipient -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a54-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a56-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;RPWP;77B5B886-944A-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B2-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B3-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;;RS)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;;RS)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;;RS)(A;;RC;;;AU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;;AU)(OA;;RP;77B5B886-944A-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;E45795B3-9455-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;AU)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)(OA;;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;;RS)(OA;;RPWP;bf967a7f-0de6-11d0-a285-00aa003049e2;;CA)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(OA;;WPRP;6db69a1c-9422-11d1-aebd-0000f80367c1;;S-1-5-32-561) -systemFlags: 16 -defaultHidingValue: FALSE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Security-Principal, Schema, Configuration, schema, test -dn: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Security-Principal -distinguishedName: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175546.0Z -whenChanged: 20050116175546.0Z -uSNCreated: 1406 -subClassOf: top -governsID: 1.2.840.113556.1.5.6 -rDNAttID: cn -uSNChanged: 1406 -showInAdvancedViewOnly: TRUE -adminDisplayName: Security-Principal -adminDescription: Security-Principal -objectClassCategory: 3 -lDAPDisplayName: securityPrincipal -name: Security-Principal -objectGUID: d1a6ae33-f6d5-197f-93d6-923d07d64c1a -schemaIDGUID: eb3adbfa-fb52-71a6-054f-b077e32c73f1 -systemOnly: FALSE -systemMayContain: supplementalCredentials -systemMayContain: sIDHistory -systemMayContain: securityIdentifier -systemMayContain: sAMAccountType -systemMayContain: rid -systemMayContain: tokenGroupsNoGCAcceptable -systemMayContain: tokenGroupsGlobalAndUniversal -systemMayContain: tokenGroups -systemMayContain: nTSecurityDescriptor -systemMayContain: msDS-KeyVersionNumber -systemMayContain: altSecurityIdentities -systemMayContain: accountNameHistory -systemMustContain: sAMAccountName -systemMustContain: objectSid -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Mail-Recipient, Schema, Configuration, schema, test -dn: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Mail-Recipient -distinguishedName: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175550.0Z -whenChanged: 20050116175550.0Z -uSNCreated: 1222 -subClassOf: top -governsID: 1.2.840.113556.1.3.46 -mayContain: userSMIMECertificate -mayContain: secretary -mayContain: msExchLabeledURI -mayContain: msExchAssistantName -mayContain: labeledURI -rDNAttID: cn -uSNChanged: 1222 -showInAdvancedViewOnly: TRUE -adminDisplayName: Mail-Recipient -adminDescription: Mail-Recipient -objectClassCategory: 3 -lDAPDisplayName: mailRecipient -name: Mail-Recipient -objectGUID: 79f6fa6e-c08d-5c1f-47ff-6b33be595f50 -schemaIDGUID: bcdded89-7f72-0166-da62-08647c98fcf9 -systemOnly: FALSE -systemPossSuperiors: container -systemMayContain: userCertificate -systemMayContain: userCert -systemMayContain: textEncodedORAddress -systemMayContain: telephoneNumber -systemMayContain: showInAddressBook -systemMayContain: legacyExchangeDN -systemMayContain: garbageCollPeriod -systemMayContain: info -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Test, Schema, Configuration, schema, test -dn: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Test -distinguishedName: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1093 -subClassOf: top -governsID: 2.5.6.6 -mayContain: test -rDNAttID: cn -uSNChanged: 1094 -showInAdvancedViewOnly: TRUE -adminDisplayName: Test -adminDescription: Test -objectClassCategory: 0 -lDAPDisplayName: test -name: Test -objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 -schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: container -systemMayContain: description -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - diff --git a/source4/lib/ldb/tests/test-schema.sh b/source4/lib/ldb/tests/test-schema.sh index 5423c7eff9..08595a0a9c 100755 --- a/source4/lib/ldb/tests/test-schema.sh +++ b/source4/lib/ldb/tests/test-schema.sh @@ -7,13 +7,26 @@ rm -f schema.ldb echo "LDB_URL: $LDB_URL" echo "Adding schema" -$VALGRIND bin/ldbadd tests/schema.ldif || exit 1 +$VALGRIND bin/ldbadd tests/schema-tests/schema.ldif || exit 1 echo "Adding few test elements (no failure expected here)" -$VALGRIND bin/ldbadd tests/schema-add-test.ldif || exit 1 +$VALGRIND bin/ldbadd tests/schema-tests/schema-add-test.ldif || exit 1 echo "Modifying elements (2 failures expected here)" -$VALGRIND bin/ldbmodify tests/schema-mod-test.ldif + +$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-1.ldif || exit 1 +$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-2.ldif || exit 1 +$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-3.ldif || exit 1 +$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-4.ldif +if [ "$?" == "0" ]; then + echo "test failed!" + exit 1 +fi +$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-5.ldif +if [ "$?" == "0" ]; then + echo "test failed!" + exit 1 +fi echo "Showing modified record" $VALGRIND bin/ldbsearch '(cn=Test)' || exit 1 -- cgit From b808d49cd5e72c5c3560a334fdfefe40f3da721f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 20 Jan 2005 00:46:04 +0000 Subject: r4863: schema_find_attribute() should be static (This used to be commit e7262dccce1ccc563fad48023c733c1d13929b4b) --- source4/lib/ldb/modules/schema.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 86dc617d99..2921bdc68b 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -94,7 +94,7 @@ static int schema_attr_cmp(const char *attr1, const char *attr2) return ret; } -struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) +static struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; for (i = 0; i < list->num; i++) { -- cgit From 6f0aef31cdfa9b486d1f2e0f097e071830f5600d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 21 Jan 2005 13:13:24 +0000 Subject: r4898: - removed the unused wins_srv_*() code - expanded the generic async name resolver to try multiple methods - added wins resolutions to the list of methods tried - fixed up the random trn id generation to use the good random generator (This used to be commit 266fd2751c01808e5a18d4094032af50554ceb7a) --- source4/lib/basic.mk | 1 - source4/lib/genrand.c | 16 ++- source4/lib/system.c | 31 ----- source4/lib/wins_srv.c | 362 ------------------------------------------------- 4 files changed, 13 insertions(+), 397 deletions(-) delete mode 100644 source4/lib/wins_srv.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index a14201d9be..ec6071e726 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -48,7 +48,6 @@ ADD_OBJ_FILES = \ lib/username.o \ lib/dprintf.o \ lib/xfile.o \ - lib/wins_srv.o \ lib/util_str.o \ lib/util_strlist.o \ lib/util_unistr.o \ diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index e11f37e0e9..aab42864e0 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -192,10 +192,9 @@ static int do_reseed(BOOL use_fd, int fd) return -1; } -/******************************************************************* +/* Interface to the (hopefully) good crypto random number generator. -********************************************************************/ - +*/ void generate_random_buffer(uint8_t *out, int len) { static int urand_fd = -1; @@ -239,6 +238,17 @@ void generate_random_buffer(uint8_t *out, int len) } } +/* + generate a single random uint32_t +*/ +uint32_t generate_random(void) +{ + uint8_t v[4]; + generate_random_buffer(v, 4); + return IVAL(v, 0); +} + + /* very basic password quality checker */ diff --git a/source4/lib/system.c b/source4/lib/system.c index 9fa71c449a..b23529f5fe 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -181,37 +181,6 @@ struct hostent *sys_gethostbyname(const char *name) } -/************************************************************************** - Wrapper for random(). -****************************************************************************/ - -long sys_random(void) -{ -#if defined(HAVE_RANDOM) - return (long)random(); -#elif defined(HAVE_RAND) - return (long)rand(); -#else - DEBUG(0,("Error - no random function available !\n")); - exit(1); -#endif -} - -/************************************************************************** - Wrapper for srandom(). -****************************************************************************/ - -void sys_srandom(uint_t seed) -{ -#if defined(HAVE_SRANDOM) - srandom(seed); -#elif defined(HAVE_SRAND) - srand(seed); -#else - DEBUG(0,("Error - no srandom function available !\n")); - exit(1); -#endif -} /************************************************************************** Wrappers for dlopen, dlsym, dlclose. diff --git a/source4/lib/wins_srv.c b/source4/lib/wins_srv.c deleted file mode 100644 index 0338db8b3d..0000000000 --- a/source4/lib/wins_srv.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba wins server helper functions - Copyright (C) Andrew Tridgell 1992-2002 - Copyright (C) Christopher R. Hertel 2000 - Copyright (C) Tim Potter 2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "system/time.h" - -/* - This is pretty much a complete rewrite of the earlier code. The main - aim of the rewrite is to add support for having multiple wins server - lists, so Samba can register with multiple groups of wins servers - and each group has a failover list of wins servers. - - Central to the way it all works is the idea of a wins server - 'tag'. A wins tag is a label for a group of wins servers. For - example if you use - - wins server = fred:192.168.2.10 mary:192.168.3.199 fred:192.168.2.61 - - then you would have two groups of wins servers, one tagged with the - name 'fred' and the other with the name 'mary'. I would usually - recommend using interface names instead of 'fred' and 'mary' but - they can be any alpha string. - - Now, how does it all work. Well, nmbd needs to register each of its - IPs with each of its names once with each group of wins servers. So - it tries registering with the first one mentioned in the list, then - if that fails it marks that WINS server dead and moves onto the next - one. - - In the client code things are a bit different. As each of the groups - of wins servers is a separate name space we need to try each of the - groups until we either succeed or we run out of wins servers to - try. If we get a negative response from a wins server then that - means the name doesn't exist in that group, so we give up on that - group and move to the next group. If we don't get a response at all - then maybe the wins server is down, in which case we need to - failover to the next one for that group. - - confused yet? (tridge) -*/ - -/* how long a server is marked dead for */ -#define DEATH_TIME 600 - -/* The list of dead wins servers is stored in gencache.tdb. Each server is - marked dead from the point of view of a given source address. We keep a - separate dead list for each src address to cope with multiple interfaces - that are not routable to each other. - */ - -#define WINS_SRV_FMT "WINS_SRV_DEAD/%s,%s" /* wins_ip,src_ip */ - -static char *wins_srv_keystr(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) -{ - char *keystr; - - if (asprintf(&keystr, WINS_SRV_FMT, sys_inet_ntoa(wins_ip), - sys_inet_ntoa(src_ip)) == -1) { - DEBUG(0, ("wins_srv_is_dead: malloc error\n")); - return NULL; - } - - return keystr; -} - -/* - see if an ip is on the dead list -*/ - -BOOL wins_srv_is_dead(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) -{ - char *keystr = wins_srv_keystr(wins_ip, src_ip); - BOOL result; - - /* If the key exists then the WINS server has been marked as dead */ - - result = gencache_get(keystr, NULL, NULL); - SAFE_FREE(keystr); - - DEBUG(4, ("wins_srv_is_dead: %s is %s\n", sys_inet_ntoa(wins_ip), - result ? "dead" : "alive")); - - return result; -} - - -/* - mark a wins server as being alive (for the moment) -*/ -void wins_srv_alive(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) -{ - char *keystr = wins_srv_keystr(wins_ip, src_ip); - - gencache_del(keystr); - SAFE_FREE(keystr); - - DEBUG(4, ("wins_srv_alive: marking wins server %s alive\n", - sys_inet_ntoa(wins_ip))); -} - -/* - mark a wins server as temporarily dead -*/ -void wins_srv_died(struct ipv4_addr wins_ip, struct ipv4_addr src_ip) -{ - char *keystr; - - if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip)) - return; - - keystr = wins_srv_keystr(wins_ip, src_ip); - - gencache_set(keystr, "DOWN", time(NULL) + DEATH_TIME); - - SAFE_FREE(keystr); - - DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n", - sys_inet_ntoa(wins_ip), DEATH_TIME, sys_inet_ntoa(src_ip))); -} - -/* - return the total number of wins servers, dead or not -*/ -uint_t wins_srv_count(void) -{ - const char **list; - int count = 0; - - if (lp_wins_support()) { - /* simple - just talk to ourselves */ - return 1; - } - - list = lp_wins_server_list(); - for (count=0; list && list[count]; count++) - /* nop */ ; - - return count; -} - -/* an internal convenience structure for an IP with a short string tag - attached */ -struct tagged_ip { - fstring tag; - struct ipv4_addr ip; -}; - -/* - parse an IP string that might be in tagged format - the result is a tagged_ip structure containing the tag - and the ip in in_addr format. If there is no tag then - use the tag '*' -*/ -static void parse_ip(TALLOC_CTX *mem_ctx, struct tagged_ip *ip, const char *str) -{ - char *s = strchr(str, ':'); - if (!s) { - fstrcpy(ip->tag, "*"); - ip->ip = interpret_addr2(str); - return; - } - - ip->ip = interpret_addr2(s+1); - fstrcpy(ip->tag, str); - s = strchr(ip->tag, ':'); - if (s) *s = 0; -} - - - -/* - return the list of wins server tags. A 'tag' is used to distinguish - wins server as either belonging to the same name space or a separate - name space. Usually you would setup your 'wins server' option to - list one or more wins server per interface and use the interface - name as your tag, but you are free to use any tag you like. -*/ -char **wins_srv_tags(void) -{ - char **ret = NULL; - int count=0, i, j; - const char **list; - TALLOC_CTX *mem_ctx; - - if (lp_wins_support()) { - /* give the caller something to chew on. This makes - the rest of the logic simpler (ie. less special cases) */ - ret = malloc_array_p(char *, 2); - if (!ret) return NULL; - ret[0] = strdup("*"); - ret[1] = NULL; - return ret; - } - - list = lp_wins_server_list(); - if (!list) - return NULL; - - mem_ctx = talloc_init("wins_ssrv_tags"); - if (!mem_ctx) { - return NULL; - } - /* yes, this is O(n^2) but n is very small */ - for (i=0;list[i];i++) { - struct tagged_ip t_ip; - - parse_ip(mem_ctx, &t_ip, list[i]); - - /* see if we already have it */ - for (j=0;j Date: Sun, 23 Jan 2005 11:49:15 +0000 Subject: r4943: Smplified the events handling code a lot. The first source of complexity was that events didn't automatically cleanup themselves. This was because the events code was written before we had talloc destructors, so you needed to call event_remove_XX() to clean the event out of the event lists from every piece of code that used events. I have now added automatic event destructors, which in turn allowed me to simplify a lot of the calling code. The 2nd source of complexity was caused by the ref_count, which was needed to cope with event handlers destroying events while handling them, which meant the linked lists became invalid, so the ref_count ws used to mark events for later destruction. The new system is much simpler. I now have a ev->destruction_count, which is incremented in all event destructors. The event dispatch code checks for changes to this and handles it. (This used to be commit a3c7417cfeab429ffb22d5546b205818f531a7b4) --- source4/lib/events.c | 170 +++++++++++++++++++------------------- source4/lib/messaging/messaging.c | 21 +---- 2 files changed, 89 insertions(+), 102 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 54ec4ef927..6f0bdb4fdd 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -104,8 +104,7 @@ static void calc_maxfd(struct event_context *ev) struct fd_event *e; ev->maxfd = 0; for (e=ev->fd_events; e; e=e->next) { - if (e->ref_count && - e->fd > ev->maxfd) { + if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } } @@ -117,7 +116,8 @@ static void calc_maxfd(struct event_context *ev) this is used by modules that need to call on the events of a lower module */ -struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2) +struct event_context *event_context_merge(struct event_context *ev, + struct event_context *ev2) { DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *); DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *); @@ -136,29 +136,42 @@ struct event_context *event_context_merge(struct event_context *ev, struct event return ev; } +/* to mark the ev->maxfd invalid + * this means we need to recalculate it + */ +#define EVENT_INVALID_MAXFD (-1) + + +static int event_fd_destructor(void *ptr) +{ + struct fd_event *fde = talloc_get_type(ptr, struct fd_event); + if (fde->event_ctx->maxfd == fde->fd) { + fde->event_ctx->maxfd = EVENT_INVALID_MAXFD; + } + DLIST_REMOVE(fde->event_ctx->fd_events, fde); + fde->event_ctx->destruction_count++; + return 0; +} /* add a fd based event return NULL on failure (memory allocation error) */ -struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) +struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0) { - e = talloc_memdup(ev->events, e, sizeof(*e)); + struct fd_event *e = talloc(ev->events, struct fd_event); if (!e) return NULL; + *e = *e0; DLIST_ADD(ev->fd_events, e); - e->ref_count = 1; + e->event_ctx = ev; if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } + talloc_set_destructor(e, event_fd_destructor); return e; } -/* to mark the ev->maxfd invalid - * this means we need to recalculate it - */ -#define EVENT_INVALID_MAXFD (-1) - /* remove a fd based event the event to remove is matched by looking at the handler @@ -167,16 +180,8 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) */ BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1) { - struct fd_event *e; - for (e=ev->fd_events; e; e=e->next) { - if (e->ref_count && - e->fd == e1->fd && - e->handler == e1->handler) { - e->ref_count--; - return True; - } - } - return False; + talloc_free(e1); + return True; } /* @@ -184,10 +189,13 @@ BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1) */ void event_remove_fd_all(struct event_context *ev, int fd) { - struct fd_event *e; - for (e=ev->fd_events; e; e=e->next) { - if (e->ref_count && e->fd == fd) { - e->ref_count--; + struct fd_event *e = ev->fd_events; + /* be careful to cope with extra reference counts on events */ + while (e) { + if (talloc_free(ev->fd_events) == 0) { + e = ev->fd_events; + } else { + e = e->next; } } } @@ -197,26 +205,35 @@ void event_remove_fd_all(struct event_context *ev, int fd) */ void event_remove_fd_all_handler(struct event_context *ev, void *handler) { - struct fd_event *e; - for (e=ev->fd_events; e; e=e->next) { - if (e->ref_count && - handler == (void *)e->handler) { - e->ref_count--; + struct fd_event *e, *next; + for (e=ev->fd_events; e; e=next) { + next = e->next; + if (handler == (void *)e->handler) { + talloc_free(e); } } } +static int event_timed_destructor(void *ptr) +{ + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + DLIST_REMOVE(te->event_ctx->timed_events, te); + te->event_ctx->destruction_count++; + return 0; +} /* add a timed event return NULL on failure (memory allocation error) */ -struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) +struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0) { - e = talloc_memdup(ev->events, e, sizeof(*e)); + struct timed_event *e = talloc(ev->events, struct timed_event); if (!e) return NULL; - e->ref_count = 1; + *e = *e0; + e->event_ctx = ev; DLIST_ADD(ev->timed_events, e); + talloc_set_destructor(e, event_timed_destructor); return e; } @@ -224,28 +241,32 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event remove a timed event return False on failure (event not found) */ -BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) +BOOL event_remove_timed(struct event_context *ev, struct timed_event *e) { - struct timed_event *e; - for (e=ev->timed_events; e; e=e->next) { - if (e->ref_count && e == e1) { - e->ref_count--; - return True; - } - } - return False; + talloc_free(e); + return True; +} + +static int event_loop_destructor(void *ptr) +{ + struct loop_event *le = talloc_get_type(ptr, struct loop_event); + DLIST_REMOVE(le->event_ctx->loop_events, le); + le->event_ctx->destruction_count++; + return 0; } /* add a loop event return NULL on failure (memory allocation error) */ -struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e) +struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0) { - e = talloc_memdup(ev->events, e, sizeof(*e)); + struct loop_event *e = talloc(ev->events, struct loop_event); if (!e) return NULL; - e->ref_count = 1; + *e = *e0; + e->event_ctx = ev; DLIST_ADD(ev->loop_events, e); + talloc_set_destructor(e, event_loop_destructor); return e; } @@ -254,17 +275,10 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e the event to remove is matched only on the handler function return False on failure (memory allocation error) */ -BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1) +BOOL event_remove_loop(struct event_context *ev, struct loop_event *e) { - struct loop_event *e; - for (e=ev->loop_events; e; e=e->next) { - if (e->ref_count && - e->handler == e1->handler) { - e->ref_count--; - return True; - } - } - return False; + talloc_free(e); + return True; } @@ -288,6 +302,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *te; int selrtn; struct timeval tval, t; + uint32_t destruction_count = ev->destruction_count; t = timeval_current(); @@ -295,14 +310,8 @@ int event_loop_once(struct event_context *ev) event to remove itself */ for (le=ev->loop_events;le;) { struct loop_event *next = le->next; - if (le->ref_count == 0) { - DLIST_REMOVE(ev->loop_events, le); - talloc_free(le); - } else { - le->ref_count++; - le->handler(ev, le, t); - le->ref_count--; - } + le->handler(ev, le, t); + if (destruction_count != ev->destruction_count) break; le = next; } @@ -312,19 +321,11 @@ int event_loop_once(struct event_context *ev) /* setup any fd events */ for (fe=ev->fd_events; fe; ) { struct fd_event *next = fe->next; - if (fe->ref_count == 0) { - DLIST_REMOVE(ev->fd_events, fe); - if (ev->maxfd == fe->fd) { - ev->maxfd = EVENT_INVALID_MAXFD; - } - talloc_free(fe); - } else { - if (fe->flags & EVENT_FD_READ) { - FD_SET(fe->fd, &r_fds); - } - if (fe->flags & EVENT_FD_WRITE) { - FD_SET(fe->fd, &w_fds); - } + if (fe->flags & EVENT_FD_READ) { + FD_SET(fe->fd, &r_fds); + } + if (fe->flags & EVENT_FD_WRITE) { + FD_SET(fe->fd, &w_fds); } fe = next; } @@ -379,10 +380,11 @@ int event_loop_once(struct event_context *ev) uint16_t flags = 0; if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (fe->ref_count && flags) { - fe->ref_count++; + if (flags) { fe->handler(ev, fe, t, flags); - fe->ref_count--; + if (destruction_count != ev->destruction_count) { + break; + } } } } @@ -391,13 +393,11 @@ int event_loop_once(struct event_context *ev) /* call any timed events that are now due */ for (te=ev->timed_events;te;) { struct timed_event *next = te->next; - if (te->ref_count == 0) { - DLIST_REMOVE(ev->timed_events, te); - talloc_free(te); - } else if (timeval_compare(&te->next_event, &t) >= 0) { - te->ref_count++; + if (timeval_compare(&te->next_event, &t) >= 0) { te->handler(ev, te, t); - te->ref_count--; + if (destruction_count != ev->destruction_count) { + break; + } if (timeval_compare(&te->next_event, &t) >= 0) { /* the handler didn't set a time for the next event - remove the event */ diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 84c9adc874..beceb342c9 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -188,17 +188,6 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd } } -/* - destroy a messaging record -*/ -static int rec_destructor(void *ptr) -{ - struct messaging_rec *rec = ptr; - struct messaging_context *msg = rec->msg; - event_remove_fd(msg->event.ev, rec->fde); - return 0; -} - /* handle a new incoming connection */ @@ -233,7 +222,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * rec->fde = event_add_fd(msg->event.ev, &fde2); - talloc_set_destructor(rec, rec_destructor); + talloc_steal(rec, rec->fde); } /* @@ -370,8 +359,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve fde.handler = messaging_send_handler; rec->fde = event_add_fd(msg->event.ev, &fde); - - talloc_set_destructor(rec, rec_destructor); + talloc_steal(rec, rec->fde); messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); } @@ -435,8 +423,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t fde.handler = messaging_send_handler; rec->fde = event_add_fd(msg->event.ev, &fde); - - talloc_set_destructor(rec, rec_destructor); + talloc_steal(rec, rec->fde); messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); @@ -464,7 +451,6 @@ NTSTATUS messaging_send_ptr(struct messaging_context *msg, servid_t server, static int messaging_destructor(void *ptr) { struct messaging_context *msg = ptr; - event_remove_fd(msg->event.ev, msg->event.fde); unlink(msg->path); return 0; } @@ -516,6 +502,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id msg->event.ev = talloc_reference(msg,ev); msg->event.fde = event_add_fd(ev, &fde); + talloc_steal(msg, msg->event.fde); talloc_set_destructor(msg, messaging_destructor); -- cgit From 6c14b0133dede38294a812be7f5f5bd5ec3d498b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 23 Jan 2005 12:17:45 +0000 Subject: r4944: every event_add_*() caller was having to call talloc_steal() to take control of the event, so instead build that into the function. If you pass NULL as mem_ctx then it leaves it as a child of the events structure. (This used to be commit 7f981b9ed96f39027cbfd500f41e0c2be64cbb50) --- source4/lib/events.c | 18 +++++++++++++++--- source4/lib/messaging/messaging.c | 15 +++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 6f0bdb4fdd..a484295d8b 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -157,7 +157,8 @@ static int event_fd_destructor(void *ptr) add a fd based event return NULL on failure (memory allocation error) */ -struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0) +struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, + TALLOC_CTX *mem_ctx) { struct fd_event *e = talloc(ev->events, struct fd_event); if (!e) return NULL; @@ -168,6 +169,9 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0) ev->maxfd = e->fd; } talloc_set_destructor(e, event_fd_destructor); + if (mem_ctx) { + talloc_steal(mem_ctx, e); + } return e; } @@ -226,7 +230,8 @@ static int event_timed_destructor(void *ptr) add a timed event return NULL on failure (memory allocation error) */ -struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0) +struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0, + TALLOC_CTX *mem_ctx) { struct timed_event *e = talloc(ev->events, struct timed_event); if (!e) return NULL; @@ -234,6 +239,9 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event e->event_ctx = ev; DLIST_ADD(ev->timed_events, e); talloc_set_destructor(e, event_timed_destructor); + if (mem_ctx) { + talloc_steal(mem_ctx, e); + } return e; } @@ -259,7 +267,8 @@ static int event_loop_destructor(void *ptr) add a loop event return NULL on failure (memory allocation error) */ -struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0) +struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0, + TALLOC_CTX *mem_ctx) { struct loop_event *e = talloc(ev->events, struct loop_event); if (!e) return NULL; @@ -267,6 +276,9 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e e->event_ctx = ev; DLIST_ADD(ev->loop_events, e); talloc_set_destructor(e, event_loop_destructor); + if (mem_ctx) { + talloc_steal(mem_ctx, e); + } return e; } diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index beceb342c9..ca7682f5d2 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -220,9 +220,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * fde2.flags = EVENT_FD_READ; fde2.handler = messaging_recv_handler; - rec->fde = event_add_fd(msg->event.ev, &fde2); - - talloc_steal(rec, rec->fde); + rec->fde = event_add_fd(msg->event.ev, &fde2, rec); } /* @@ -358,8 +356,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve fde.flags = EVENT_FD_WRITE; fde.handler = messaging_send_handler; - rec->fde = event_add_fd(msg->event.ev, &fde); - talloc_steal(rec, rec->fde); + rec->fde = event_add_fd(msg->event.ev, &fde, rec); messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); } @@ -408,7 +405,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF); te.handler = messaging_backoff_handler; te.private = rec; - event_add_timed(msg->event.ev, &te); + event_add_timed(msg->event.ev, &te, rec); return NT_STATUS_OK; } @@ -422,8 +419,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t fde.flags = EVENT_FD_WRITE; fde.handler = messaging_send_handler; - rec->fde = event_add_fd(msg->event.ev, &fde); - talloc_steal(rec, rec->fde); + rec->fde = event_add_fd(msg->event.ev, &fde, rec); messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); @@ -501,8 +497,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id fde.handler = messaging_listen_handler; msg->event.ev = talloc_reference(msg,ev); - msg->event.fde = event_add_fd(ev, &fde); - talloc_steal(msg, msg->event.fde); + msg->event.fde = event_add_fd(ev, &fde, msg); talloc_set_destructor(msg, messaging_destructor); -- cgit From af4ce4805ce1504fc8869ead032eabb72fca77a0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 24 Jan 2005 01:51:45 +0000 Subject: r4954: we don't need the separate event_remove_*() calls any more, as you now remove an event by calling talloc_free(). (This used to be commit 8f19b6886cc58a56d52aecfc83a175197061e533) --- source4/lib/events.c | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index a484295d8b..d32a1344e0 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -55,7 +55,7 @@ 'struct event_context' that you use in all subsequent calls. After that you can add/remove events that you are interested in - using event_add_*() and event_remove_*(). + using event_add_*() and talloc_free() Finally, you call event_loop_wait() to block waiting for one of the events to occor. In normal operation event_loop_wait() will loop @@ -176,18 +176,6 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, } -/* - remove a fd based event - the event to remove is matched by looking at the handler - function and the file descriptor - return False on failure (event not found) -*/ -BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1) -{ - talloc_free(e1); - return True; -} - /* remove all fd based events that match a specified fd */ @@ -245,16 +233,6 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event return e; } -/* - remove a timed event - return False on failure (event not found) -*/ -BOOL event_remove_timed(struct event_context *ev, struct timed_event *e) -{ - talloc_free(e); - return True; -} - static int event_loop_destructor(void *ptr) { struct loop_event *le = talloc_get_type(ptr, struct loop_event); @@ -282,18 +260,6 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e return e; } -/* - remove a loop event - the event to remove is matched only on the handler function - return False on failure (memory allocation error) -*/ -BOOL event_remove_loop(struct event_context *ev, struct loop_event *e) -{ - talloc_free(e); - return True; -} - - /* tell the event loop to exit with the specified code */ @@ -413,7 +379,7 @@ int event_loop_once(struct event_context *ev) if (timeval_compare(&te->next_event, &t) >= 0) { /* the handler didn't set a time for the next event - remove the event */ - event_remove_timed(ev, te); + talloc_free(te); } } te = next; -- cgit From 3dd17f128831e09c230a8d56e34495d3b31dbacb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 27 Jan 2005 06:16:59 +0000 Subject: r5034: - added a type mapping function in pidl, so the type names in our IDL files don't need to match the type names in the generated headers - with this type mapping we no longer need definitions for the deprecated "int32", "uint8" etc form of types. We can now force everyone to use the standard types int32_t, uint8_t etc. - fixed all the code that used the deprecated types - converted the IDL types "int64" and "uint64" to "dlong" and "udlong". These are the 4 byte aligned 64 bit integers that Microsoft internally define as two 32 bit integers in a structure. After discussions with Ronnie Sahlberg we decided that calling these "int64" was confusing, as it implied a true 8 byte aligned type - fixed all the cases where we incorrectly used things like "NTTIME_hyper" in our C code. The generated API now uses a NTTIME for those. The fact that it is hyper-aligned on the wire is not relevant to the API, and should remain just a IDL property (This used to be commit f86521677d7ff16bdc4815f9524e5286026f10f3) --- source4/lib/dcom/common/dcom.h | 4 ++-- source4/lib/dcom/common/main.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index d8e3797c73..0bc4a256f1 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -34,12 +34,12 @@ struct dcom_context struct dcom_object_exporter *prev, *next; struct STRINGARRAY resolver_address; struct DUALSTRINGARRAY bindings; - HYPER_T oxid; + uint64_t oxid; struct dcerpc_pipe *pipe; struct dcom_object { struct dcom_object *prev, *next; - HYPER_T oid; + uint64_t oid; void *private_data; } *objects; } *oxids; diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 48b5ec946b..219c06a665 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -116,7 +116,7 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user return WERR_OK; } -static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) { struct dcom_object_exporter *m; @@ -345,7 +345,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding binding; struct GUID iid; - HYPER_T oxid; + uint64_t oxid; NTSTATUS status; int i; struct dcerpc_pipe *p; @@ -408,7 +408,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) return NT_STATUS_OK; } -struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T oid) +struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, uint64_t oid) { struct dcom_object *o; @@ -544,7 +544,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface return NT_STATUS_NOT_SUPPORTED; } -HYPER_T dcom_get_current_oxid(void) +uint64_t dcom_get_current_oxid(void) { return getpid(); } -- cgit From 759da3b915e2006d4c87b5ace47f399accd9ce91 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 27 Jan 2005 07:08:20 +0000 Subject: r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the large commit. I thought this was worthwhile to get done for consistency. (This used to be commit ec32b22ed5ec224f6324f5e069d15e92e38e15c0) --- source4/lib/data_blob.c | 2 +- source4/lib/db_wrap.c | 4 ++-- source4/lib/dcom/common/main.c | 20 +++++++++---------- source4/lib/dcom/common/tables.c | 6 +++--- source4/lib/genrand.c | 2 +- source4/lib/idtree.c | 4 ++-- source4/lib/messaging/messaging.c | 8 ++++---- source4/lib/ms_fnmatch.c | 2 +- source4/lib/netif/interface.c | 2 +- source4/lib/registry/common/reg_interface.c | 18 ++++++++--------- source4/lib/registry/common/reg_util.c | 6 +++--- source4/lib/registry/reg_backend_dir.c | 8 ++++---- source4/lib/registry/reg_backend_gconf.c | 14 +++++++------- source4/lib/registry/reg_backend_ldb.c | 30 ++++++++++++++--------------- source4/lib/registry/reg_backend_nt4.c | 6 +++--- source4/lib/registry/reg_backend_rpc.c | 24 +++++++++++------------ source4/lib/registry/reg_backend_w95.c | 12 ++++++------ source4/lib/registry/reg_samba.c | 4 ++-- source4/lib/registry/tools/regdiff.c | 8 ++++---- source4/lib/registry/tools/regshell.c | 8 ++++---- source4/lib/registry/tools/regtree.c | 4 ++-- source4/lib/socket/socket_ipv4.c | 2 +- source4/lib/socket/socket_ipv6.c | 2 +- source4/lib/socket/socket_unix.c | 2 +- source4/lib/unix_privs.c | 2 +- source4/lib/util_sock.c | 2 +- source4/lib/util_str.c | 2 +- source4/lib/util_unistr.c | 2 +- 28 files changed, 103 insertions(+), 103 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index deb8f55fce..284db4518f 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -150,7 +150,7 @@ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) int i; char *hex_string; - hex_string = talloc_array_p(mem_ctx, char, (blob->length*2)+1); + hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); if (!hex_string) { return NULL; } diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index a9ca7e3e0a..854f772717 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -80,7 +80,7 @@ struct ldb_wrap *ldb_wrap_connect(TALLOC_CTX *mem_ctx, } } - w = talloc_p(mem_ctx, struct ldb_wrap); + w = talloc(mem_ctx, struct ldb_wrap); if (w == NULL) { return NULL; } @@ -151,7 +151,7 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, } } - w = talloc_p(mem_ctx, struct tdb_wrap); + w = talloc(mem_ctx, struct tdb_wrap); if (w == NULL) { return NULL; } diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 219c06a665..01906501f1 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -71,10 +71,10 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * DCERPC_IREMOTEACTIVATION_VERSION, ctx->domain, ctx->user, ctx->password); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return status; } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); ZERO_STRUCT(bd); bd.host = server; @@ -106,7 +106,7 @@ static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe * WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user, const char *pass) { - *ctx = talloc_p(NULL, struct dcom_context); + *ctx = talloc(NULL, struct dcom_context); (*ctx)->oxids = NULL; (*ctx)->domain = talloc_strdup(*ctx, domain); (*ctx)->user = talloc_strdup(*ctx, user); @@ -128,7 +128,7 @@ static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *c /* Add oxid mapping if we couldn't find one */ if (!m) { - m = talloc_zero_p(ctx, struct dcom_object_exporter); + m = talloc_zero(ctx, struct dcom_object_exporter); m->oxid = oxid; DLIST_ADD(ctx->oxids, m); } @@ -169,7 +169,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c r.in.protseq = protseq; r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; - r.out.ifaces = talloc_array_p(ctx, struct pMInterfacePointer, num_ifaces); + r.out.ifaces = talloc_array(ctx, struct pMInterfacePointer, num_ifaces); r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); @@ -186,7 +186,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c return r.out.hr; } - *ip = talloc_array_p(ctx, struct dcom_interface_p *, num_ifaces); + *ip = talloc_array(ctx, struct dcom_interface_p *, num_ifaces); for (i = 0; i < num_ifaces; i++) { results[i] = r.out.results[i]; (*ip)[i] = NULL; @@ -419,7 +419,7 @@ struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, uint64_t } if (o == NULL) { - o = talloc_zero_p(ox, struct dcom_object); + o = talloc_zero(ox, struct dcom_object); o->oid = oid; DLIST_ADD(ox->objects, o); } @@ -435,7 +435,7 @@ NTSTATUS dcom_OBJREF_from_ifacep(struct dcom_context *ctx, struct OBJREF *o, str NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) { - struct dcom_interface_p *p = talloc_p(ctx, struct dcom_interface_p); + struct dcom_interface_p *p = talloc(ctx, struct dcom_interface_p); p->ctx = ctx; p->interface = dcom_interface_by_iid(&o->iid); @@ -502,7 +502,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", p->ox->oxid)); - m = talloc_zero_p(p->ctx, struct dcom_oxid_mapping); + m = talloc_zero(p->ctx, struct dcom_oxid_mapping); m->oxid = oxid; i = 0; @@ -551,7 +551,7 @@ uint64_t dcom_get_current_oxid(void) struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct GUID *iid, void *vtable, struct dcom_object *object) { - struct dcom_interface_p *ip = talloc_p(ctx, struct dcom_interface_p); + struct dcom_interface_p *ip = talloc(ctx, struct dcom_interface_p); const struct dcom_interface *iface = dcom_interface_by_iid(iid); if (!iface) { diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index 8a764d0a65..cd7e0867ee 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -81,9 +81,9 @@ NTSTATUS dcom_register_interface(const void *_iface) DEBUG(5, ("Adding DCOM interface %s\n", GUID_string(lcl_ctx, &iface->iid))); - talloc_destroy(lcl_ctx); + talloc_free(lcl_ctx); - l = talloc_zero_p(interfaces?interfaces:talloc_autofree_context(), + l = talloc_zero(interfaces?interfaces:talloc_autofree_context(), struct interface_list); l->interface = *iface; @@ -96,7 +96,7 @@ NTSTATUS dcom_register_interface(const void *_iface) NTSTATUS dcom_register_class(const void *_class) { const struct dcom_class *class = _class; - struct class_list *l = talloc_zero_p(classes?classes:talloc_autofree_context(), + struct class_list *l = talloc_zero(classes?classes:talloc_autofree_context(), struct class_list); l->class = *class; diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index aab42864e0..0f1d02b710 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -278,7 +278,7 @@ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list size_t i; size_t list_len = strlen(list); - char *retstr = talloc_array_p(mem_ctx, char, len + 1); + char *retstr = talloc_array(mem_ctx, char, len + 1); if (!retstr) return NULL; generate_random_buffer((uint8_t *)retstr, len); diff --git a/source4/lib/idtree.c b/source4/lib/idtree.c index c4370a812d..82c1cdd42a 100644 --- a/source4/lib/idtree.c +++ b/source4/lib/idtree.c @@ -87,7 +87,7 @@ static void free_layer(struct idr_context *idp, struct idr_layer *p) static int idr_pre_get(struct idr_context *idp) { while (idp->id_free_cnt < IDR_FREE_MAX) { - struct idr_layer *new = talloc_zero_p(idp, struct idr_layer); + struct idr_layer *new = talloc_zero(idp, struct idr_layer); if(new == NULL) return (0); free_layer(idp, new); @@ -313,7 +313,7 @@ static int _idr_remove(struct idr_context *idp, int id) */ struct idr_context *idr_init(TALLOC_CTX *mem_ctx) { - return talloc_zero_p(mem_ctx, struct idr_context); + return talloc_zero(mem_ctx, struct idr_context); } /* diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index ca7682f5d2..e2e8161111 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -199,7 +199,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * NTSTATUS status; struct fd_event fde2; - rec = talloc_p(msg, struct messaging_rec); + rec = talloc(msg, struct messaging_rec); if (rec == NULL) { smb_panic("Unable to allocate messaging_rec"); } @@ -232,7 +232,7 @@ void messaging_register(struct messaging_context *msg, void *private, { struct dispatch_fn *d; - d = talloc_p(msg, struct dispatch_fn); + d = talloc(msg, struct dispatch_fn); d->msg_type = msg_type; d->private = private; d->fn = fn; @@ -371,7 +371,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t NTSTATUS status; struct fd_event fde; - rec = talloc_p(msg, struct messaging_rec); + rec = talloc(msg, struct messaging_rec); if (rec == NULL) { return NT_STATUS_NO_MEMORY; } @@ -460,7 +460,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id NTSTATUS status; struct fd_event fde; - msg = talloc_p(mem_ctx, struct messaging_context); + msg = talloc(mem_ctx, struct messaging_context); if (msg == NULL) { return NULL; } diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index 386dac4ea3..c405d2ff30 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -198,7 +198,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot if (pattern[i] == '*' || pattern[i] == '<') count++; } - max_n = talloc_array_p(NULL, struct max_n, count); + max_n = talloc_array(NULL, struct max_n, count); if (!max_n) { return -1; } diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index c73a2e3d7b..9075d4f3ac 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -241,7 +241,7 @@ void load_interfaces(void) } exit: - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); } diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 442b34bc13..8385cef108 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -44,7 +44,7 @@ NTSTATUS registry_register(const void *_hive_ops) return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = talloc_p(talloc_autofree_context(), struct reg_init_function_entry); + entry = talloc(talloc_autofree_context(), struct reg_init_function_entry); entry->hive_functions = hive_ops; DLIST_ADD(backends, entry); @@ -93,8 +93,8 @@ static struct { int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys) { int i; - *predefs = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(predef_names)); - *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(predef_names)); + *predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(predef_names)); + *hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(predef_names)); for (i = 0; predef_names[i].name; i++) { (*predefs)[i] = talloc_strdup(mem_ctx, predef_names[i].name); @@ -129,7 +129,7 @@ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char * WERROR reg_close (struct registry_context *ctx) { - talloc_destroy(ctx); + talloc_free(ctx); return WERR_OK; } @@ -165,7 +165,7 @@ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *lo return WERR_NOT_SUPPORTED; } - rethive = talloc_p(parent_ctx, struct registry_hive); + rethive = talloc(parent_ctx, struct registry_hive); rethive->location = location?talloc_strdup(rethive, location):NULL; rethive->functions = entry->hive_functions; rethive->backend_data = NULL; @@ -277,7 +277,7 @@ WERROR reg_key_num_subkeys(struct registry_key *key, int *count) TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); *count = i; if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK; @@ -303,7 +303,7 @@ WERROR reg_key_num_values(struct registry_key *key, int *count) TALLOC_CTX *mem_ctx = talloc_init("num_subkeys"); for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); *count = i; if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK; @@ -490,7 +490,7 @@ WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint i++; } while (W_ERROR_IS_OK(error)); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return WERR_OK; } @@ -517,7 +517,7 @@ WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint i++; } while (W_ERROR_IS_OK(error)); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return WERR_OK; } diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index ef46dd6174..b11b24151e 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -99,7 +99,7 @@ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value) { int i; - *value = talloc_p(mem_ctx, struct registry_value); + *value = talloc(mem_ctx, struct registry_value); (*value)->data_type = -1; /* Find the correct type */ @@ -123,7 +123,7 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da break; case REG_DWORD: (*value)->data_len = sizeof(uint32); - (*value)->data_blk = talloc_p(mem_ctx, uint32); + (*value)->data_blk = talloc(mem_ctx, uint32); *((uint32 *)(*value)->data_blk) = strtol(data_str, NULL, 0); break; @@ -264,7 +264,7 @@ WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) error = reg_key_del(parent, n); } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return error; } diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 4af219facb..bac0f43c20 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -41,7 +41,7 @@ static WERROR reg_dir_del_key(struct registry_key *k, const char *name) if (rmdir(child) == 0) ret = WERR_OK; else ret = WERR_GENERAL_FAILURE; - talloc_destroy(child); + talloc_free(child); return ret; } @@ -67,7 +67,7 @@ static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, cons return WERR_BADFILE; } closedir(d); - ret = talloc_p(mem_ctx, struct registry_key); + ret = talloc(mem_ctx, struct registry_key); ret->hive = p->hive; ret->path = fullpath; ret->backend_data = unixpath; @@ -98,7 +98,7 @@ static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, if(S_ISDIR(stbuf.st_mode)) { if(i == idx) { - (*key) = talloc_p(mem_ctx, struct registry_key); + (*key) = talloc(mem_ctx, struct registry_key); (*key)->name = e->d_name; (*key)->path = NULL; (*key)->backend_data = talloc_strdup(mem_ctx, thispath); @@ -122,7 +122,7 @@ static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key) { if(!h->location) return WERR_INVALID_PARAM; - *key = talloc_p(h, struct registry_key); + *key = talloc(h, struct registry_key); (*key)->backend_data = talloc_strdup(*key, h->location); return WERR_OK; } diff --git a/source4/lib/registry/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c index 47d8c760ab..a912a42e55 100644 --- a/source4/lib/registry/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf.c @@ -35,7 +35,7 @@ static WERROR reg_open_gconf_hive(struct registry_hive *h, struct registry_key * h->backend_data = (void *)gconf_client_get_default(); if(!h->backend_data) return WERR_FOOBAR; - *k = talloc_p(h, struct registry_key); + *k = talloc(h, struct registry_key); (*k)->name = talloc_strdup(*k, ""); (*k)->path = talloc_strdup(*k, ""); (*k)->backend_data = talloc_strdup(*k, "/"); @@ -57,7 +57,7 @@ static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_key *h, const return WERR_DEST_NOT_FOUND; } - ret = talloc_p(mem_ctx, struct registry_key); + ret = talloc(mem_ctx, struct registry_key); ret->backend_data = fullpath; *key = ret; @@ -83,7 +83,7 @@ static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, entry = cur->data; value = gconf_entry_get_value(entry); - newval = talloc_p(mem_ctx, struct registry_value); + newval = talloc(mem_ctx, struct registry_value); newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1); if(value) { switch(value->type) { @@ -99,20 +99,20 @@ static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, case GCONF_VALUE_INT: newval->data_type = REG_DWORD; - newval->data_blk = talloc_p(mem_ctx, long); + newval->data_blk = talloc(mem_ctx, long); *((long *)newval->data_blk) = gconf_value_get_int(value); newval->data_len = sizeof(long); break; case GCONF_VALUE_FLOAT: - newval->data_blk = talloc_p(mem_ctx, double); + newval->data_blk = talloc(mem_ctx, double); newval->data_type = REG_BINARY; *((double *)newval->data_blk) = gconf_value_get_float(value); newval->data_len = sizeof(double); break; case GCONF_VALUE_BOOL: - newval->data_blk = talloc_p(mem_ctx, BOOL); + newval->data_blk = talloc(mem_ctx, BOOL); newval->data_type = REG_BINARY; *((BOOL *)newval->data_blk) = gconf_value_get_bool(value); newval->data_len = sizeof(BOOL); @@ -142,7 +142,7 @@ static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p if(!cur) return WERR_NO_MORE_ITEMS; - *sub = talloc_p(mem_ctx, struct registry_key); + *sub = talloc(mem_ctx, struct registry_key); (*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1); (*sub)->backend_data = talloc_strdup(mem_ctx, cur->data); diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index e0d7b6e2cb..930ea9642e 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -52,7 +52,7 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c case REG_DWORD_LE: *len = 4; - *data = talloc_p(mem_ctx, uint32); + *data = talloc(mem_ctx, uint32); SIVAL(*data, 0, strtol(val->data, NULL, 0)); break; @@ -66,7 +66,7 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32 type, void *data, int len) { struct ldb_val val; - struct ldb_message *msg = talloc_zero_p(mem_ctx, struct ldb_message); + struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message); char *type_s; ldb_msg_add_string(ctx, msg, "value", talloc_strdup(mem_ctx, name)); @@ -165,10 +165,10 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, el = ldb_msg_find_element(kd->subkeys[idx], "key"); - *subkey = talloc_p(mem_ctx, struct registry_key); + *subkey = talloc(mem_ctx, struct registry_key); talloc_set_destructor(*subkey, reg_close_ldb_key); (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); - (*subkey)->backend_data = newkd = talloc_zero_p(*subkey, struct ldb_key_data); + (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data); newkd->dn = talloc_strdup(mem_ctx, kd->subkeys[idx]->dn); return WERR_OK; @@ -191,7 +191,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS; - *value = talloc_p(mem_ctx, struct registry_value); + *value = talloc(mem_ctx, struct registry_value); reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data_blk, &(*value)->data_len); @@ -217,10 +217,10 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch return WERR_FOOBAR; } - *key = talloc_p(mem_ctx, struct registry_key); + *key = talloc(mem_ctx, struct registry_key); talloc_set_destructor(*key, reg_close_ldb_key); (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name); - (*key)->backend_data = newkd = talloc_zero_p(*key, struct ldb_key_data); + (*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data); newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); ldb_search_free(c, msg); @@ -247,11 +247,11 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) ldb_set_debug_stderr(c); hive->backend_data = c; - *k = talloc_zero_p(hive, struct registry_key); + *k = talloc_zero(hive, struct registry_key); talloc_set_destructor (*k, reg_close_ldb_key); talloc_set_destructor (hive, ldb_close_hive); (*k)->name = talloc_strdup(*k, ""); - (*k)->backend_data = kd = talloc_zero_p(*k, struct ldb_key_data); + (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data); kd->dn = talloc_strdup(*k, "hive="); @@ -277,10 +277,10 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con return WERR_FOOBAR; } - *newkey = talloc_zero_p(mem_ctx, struct registry_key); + *newkey = talloc_zero(mem_ctx, struct registry_key); (*newkey)->name = talloc_strdup(mem_ctx, name); - (*newkey)->backend_data = newkd = talloc_zero_p(*newkey, struct ldb_key_data); + (*newkey)->backend_data = newkd = talloc_zero(*newkey, struct ldb_key_data); newkd->dn = talloc_steal(newkd, msg->dn); return WERR_OK; @@ -294,7 +294,7 @@ static WERROR ldb_del_key (struct registry_key *key, const char *child) ret = ldb_delete(key->hive->backend_data, childdn); - talloc_destroy(childdn); + talloc_free(childdn); if (ret < 0) { DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); @@ -312,7 +312,7 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) ret = ldb_delete(key->hive->backend_data, childdn); - talloc_destroy(childdn); + talloc_free(childdn); if (ret < 0) { DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data))); @@ -339,12 +339,12 @@ static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint ret = ldb_modify(ctx, msg); if (ret < 0) { DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return WERR_FOOBAR; } } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return WERR_OK; } diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index cd3be85a23..88033a8a8b 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -902,7 +902,7 @@ static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ dat_off = IVAL(&vk_hdr->dat_off,0); - tmp = talloc_p(mem_ctx, struct registry_value); + tmp = talloc(mem_ctx, struct registry_value); tmp->data_type = dat_type; if (flag & FLAG_HAS_NAME) { @@ -1070,7 +1070,7 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk return WERR_GENERAL_FAILURE; } - tmp = talloc_p(mem_ctx, struct registry_key); + tmp = talloc(mem_ctx, struct registry_key); tmp->name = talloc_strdup(mem_ctx, key_name); tmp->backend_data = nk_hdr; @@ -1574,7 +1574,7 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) uint_t regf_id, hbin_id; HBIN_HDR *hbin_hdr; - regf = (REGF *)talloc_p(h, REGF); + regf = (REGF *)talloc(h, REGF); memset(regf, 0, sizeof(REGF)); regf->owner_sid_str = NULL; /* FIXME: Fill in */ h->backend_data = regf; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index c5ed9b2c88..d2809f644a 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -109,14 +109,14 @@ static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32 hkey_ return WERR_NO_MORE_ITEMS; } - h = talloc_p(ctx, struct registry_hive); + h = talloc(ctx, struct registry_hive); h->functions = ®_backend_rpc; h->location = NULL; h->backend_data = ctx->backend_data; - (*k) = h->root = talloc_p(h, struct registry_key); + (*k) = h->root = talloc(h, struct registry_key); (*k)->hive = h; - (*k)->backend_data = mykeydata = talloc_p(*k, struct rpc_key_data); + (*k)->backend_data = mykeydata = talloc(*k, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol)); @@ -135,7 +135,7 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) struct winreg_OpenKey r; struct rpc_key_data *mykeydata; - k->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); + k->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; @@ -159,10 +159,10 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch struct rpc_key_data *mykeydata; struct winreg_OpenKey r; - *key = talloc_p(mem_ctx, struct registry_key); + *key = talloc(mem_ctx, struct registry_key); (*key)->name = talloc_strdup(mem_ctx, name); - (*key)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); + (*key)->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; @@ -217,7 +217,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result) && r.out.length) { - *value = talloc_p(mem_ctx, struct registry_value); + *value = talloc(mem_ctx, struct registry_value); (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); (*value)->data_type = type; (*value)->data_len = *r.out.length; @@ -266,7 +266,7 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, cons init_winreg_String(&r.in.class, NULL); r.in.handle = parent->backend_data; - r.out.handle = talloc_p(mem_ctx, struct policy_handle); + r.out.handle = talloc(mem_ctx, struct policy_handle); r.in.options = 0; r.in.access_mask = access_mask; r.in.sec_desc = NULL; @@ -279,7 +279,7 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, cons } if (W_ERROR_IS_OK(r.out.result)) { - *key = talloc_p(mem_ctx, struct registry_key); + *key = talloc(mem_ctx, struct registry_key); (*key)->name = talloc_strdup(*key, name); (*key)->backend_data = r.out.handle; } @@ -298,7 +298,7 @@ static WERROR rpc_query_key(struct registry_key *k) r.in.handle = &mykeydata->pol; status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); @@ -327,7 +327,7 @@ static WERROR rpc_del_key(struct registry_key *parent, const char *name) status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return r.out.result; } @@ -374,7 +374,7 @@ WERROR reg_open_remote (struct registry_context **ctx, const char *user, const c NTSTATUS status; struct dcerpc_pipe *p; - *ctx = talloc_p(NULL, struct registry_context); + *ctx = talloc(NULL, struct registry_context); /* Default to local smbd if no connection is specified */ if (!location) { diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index 957039dea3..ff02f4d12b 100644 --- a/source4/lib/registry/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -187,7 +187,7 @@ static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) DWORD i; DWORD offset; - creg = talloc_p(h, CREG); + creg = talloc(h, CREG); memset(creg, 0, sizeof(CREG)); h->backend_data = creg; @@ -234,7 +234,7 @@ static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) } #endif - creg->rgdb_keys = talloc_array_p(h, RGDB_KEY **, creg->creg_hdr->num_rgdb); + creg->rgdb_keys = talloc_array(h, RGDB_KEY **, creg->creg_hdr->num_rgdb); offset = 0; DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); @@ -250,7 +250,7 @@ static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) } - creg->rgdb_keys[i] = talloc_array_p(h, RGDB_KEY *, rgdb_hdr->max_id+1); + creg->rgdb_keys[i] = talloc_array(h, RGDB_KEY *, rgdb_hdr->max_id+1); memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); parse_rgdb_block(creg, rgdb_hdr); @@ -259,7 +259,7 @@ static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) } /* First element in rgkn should be root key */ - *root = talloc_p(h, struct registry_key); + *root = talloc(h, struct registry_key); (*root)->name = NULL; (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); @@ -288,7 +288,7 @@ static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id)); return WERR_FOOBAR; } - *key = talloc_p(mem_ctx, struct registry_key); + *key = talloc(mem_ctx, struct registry_key); (*key)->backend_data = child; (*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len); return WERR_OK; @@ -331,7 +331,7 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len; } - *value = talloc_p(mem_ctx, struct registry_value); + *value = talloc(mem_ctx, struct registry_value); (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); (*value)->data_len = curval->data_len; diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c index 62973a14ab..a81b9e5a42 100644 --- a/source4/lib/registry/reg_samba.c +++ b/source4/lib/registry/reg_samba.c @@ -59,14 +59,14 @@ static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32 hkey, s error = reg_open_hive(ctx, backend, location, NULL, k); - talloc_destroy(backend); + talloc_free(backend); return error; } WERROR reg_open_local (struct registry_context **ctx) { - *ctx = talloc_p(NULL, struct registry_context); + *ctx = talloc(NULL, struct registry_context); (*ctx)->get_predefined_key = reg_samba_get_predef; return WERR_OK; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 8d88cafe59..ceae3a427e 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -41,7 +41,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, } } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); @@ -60,7 +60,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, writediff(t2, t1, out); } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); @@ -82,7 +82,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, } } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); @@ -101,7 +101,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, } } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 1dd0e04561..ac7dbca49b 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -329,14 +329,14 @@ static char **reg_complete_key(const char *text, int start, int end) break; } else { printf("Error creating completion list: %s\n", win_errstr(status)); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return NULL; } } if (j == 1) { /* No matches at all */ SAFE_FREE(matches); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return NULL; } @@ -345,7 +345,7 @@ static char **reg_complete_key(const char *text, int start, int end) } else { asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen)); } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); matches[j] = NULL; return matches; @@ -435,7 +435,7 @@ static char **reg_completion(const char *text, int start, int end) if(new)curkey = new; } } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return 0; } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index a6beb2b484..f061f33bd3 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -47,7 +47,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) { print_tree(l+1, subkey, fullpath, novals); } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", p->path, win_errstr(error))); @@ -62,7 +62,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) desc = reg_val_description(mem_ctx, value); printf("%s\n", desc); } - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error))); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index d6b6bf7be4..aaa5ce0fa2 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -202,7 +202,7 @@ static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context * * --metze */ - (*new_sock) = talloc_p(NULL, struct socket_context); + (*new_sock) = talloc(NULL, struct socket_context); if (!(*new_sock)) { close(new_fd); return NT_STATUS_NO_MEMORY; diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 27e452b14e..1dd7fe8e9d 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -179,7 +179,7 @@ static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_conte * --metze */ - (*new_sock) = talloc_p(NULL, struct socket_context); + (*new_sock) = talloc(NULL, struct socket_context); if (!(*new_sock)) { close(new_fd); return NT_STATUS_NO_MEMORY; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index bdd68f9d9d..e23aa0d97e 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -162,7 +162,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, } } - (*new_sock) = talloc_p(NULL, struct socket_context); + (*new_sock) = talloc(NULL, struct socket_context); if (!(*new_sock)) { close(new_fd); return NT_STATUS_NO_MEMORY; diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c index c65f490aeb..a57f4359d3 100644 --- a/source4/lib/unix_privs.c +++ b/source4/lib/unix_privs.c @@ -57,7 +57,7 @@ static int privileges_destructor(void *ptr) void *root_privileges(void) { struct saved_state *s; - s = talloc_p(NULL, struct saved_state); + s = talloc(NULL, struct saved_state); if (!s) return NULL; s->uid = geteuid(); if (s->uid != 0) { diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 876698535b..7fe42f7ffc 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -428,7 +428,7 @@ int open_udp_socket(const char *host, int port) sock_out.sin_port = htons(port); sock_out.sin_family = PF_INET; - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) { close(res); diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index b3ec27de74..d9c4e30d6a 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -1057,7 +1057,7 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx, { char *dup_str = talloc_strdup(mem_ctx, str); - *strings = talloc_realloc_p(mem_ctx, + *strings = talloc_realloc(mem_ctx, *strings, const char *, ((*num)+1)); diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index bd4aea7c41..e589e6493a 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -41,7 +41,7 @@ static void load_case_tables(void) } upcase_table = map_file(lib_path(mem_ctx, "upcase.dat"), 0x20000); lowcase_table = map_file(lib_path(mem_ctx, "lowcase.dat"), 0x20000); - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); if (upcase_table == NULL) { upcase_table = (void *)-1; } -- cgit From d534e83c57feac9ebe115c565b5476d0f5160b7b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Jan 2005 11:23:31 +0000 Subject: r5052: minor formatting fix (This used to be commit 4337901c1b38aaaf6cc09641ad51ff28e591b1f4) --- source4/lib/netif/interface.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 9075d4f3ac..4f22095f7a 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -187,10 +187,10 @@ void load_interfaces(void) ptr = lp_interfaces(); mem_ctx = talloc_init("load_interfaces"); - if (!mem_ctx) { - DEBUG(2,("no memory to load interfaces \n")); + if (!mem_ctx) { + DEBUG(2,("no memory to load interfaces \n")); return; - } + } allones_ip = interpret_addr2("255.255.255.255"); loopback_ip = interpret_addr2("127.0.0.1"); @@ -330,7 +330,6 @@ struct ipv4_addr *iface_n_bcast(int n) return NULL; } - /* these 3 functions return the ip/bcast/nmask for the interface most appropriate for the given ip address. If they can't find an appropriate interface they return the requested field of the -- cgit From 99ecf2d95325e7b6143596760dbc2780ba246dc6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 28 Jan 2005 11:25:01 +0000 Subject: r5053: - fix up the library dependencies so that tools that need nbt don't need to pull in the whole dcerpc subsystem - moved smbencrypt.c code into libcli/auth/ (This used to be commit 3351c636af23ad88649e84f4cb88fc1167d5c654) --- source4/lib/basic.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index ec6071e726..af1420c685 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -69,6 +69,6 @@ ADD_OBJ_FILES = \ lib/db_wrap.o \ lib/gencache.o REQUIRED_SUBSYSTEMS = \ - LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO LIB_SECURITY EXT_LIB_DL LIBTALLOC + LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC # End SUBSYSTEM LIBBASIC ############################## -- cgit From ea2209e3db4dc1a6d455e01d5339b0b981c361b1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 29 Jan 2005 04:04:38 +0000 Subject: r5092: Add a bit more const - moving it further into the LDB layer. Andrew Bartlett (This used to be commit ffad9b22be595279b247fa72d51145830fecbb06) --- source4/lib/ldb/common/ldb_msg.c | 4 ++-- source4/lib/ldb/include/ldb.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 5ab2088744..3ef25e566f 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -202,11 +202,11 @@ int ldb_msg_add_value(struct ldb_context *ldb, add a string element to a message */ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, - const char *attr_name, char *str) + const char *attr_name, const char *str) { struct ldb_val val; - val.data = str; + val.data = discard_const_p(char, str); val.length = strlen(str); return ldb_msg_add_value(ldb, msg, attr_name, &val); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 0bb8105c44..310000b244 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -258,7 +258,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, const char *attr_name, const struct ldb_val *val); int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, - const char *attr_name, char *str); + const char *attr_name, const char *str); /* compare two message elements - return 0 on match */ int ldb_msg_element_compare(struct ldb_message_element *el1, -- cgit From 51ad25e8ea0d75ea444de8607c84992157e56d43 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 29 Jan 2005 04:11:04 +0000 Subject: r5093: Make debugs less confusing when a 0 NTTIME is printed. Andrew Bartlett (This used to be commit 9493c47b1833a4a7781303f8139f1636f86bf126) --- source4/lib/time.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index fd005215a1..e214179b6c 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -346,7 +346,11 @@ char *timestring(TALLOC_CTX *mem_ctx, time_t t) */ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) { - time_t t = nt_time_to_unix(nt); + time_t t; + if (nt == 0) { + return "NTTIME(0)"; + } + t = nt_time_to_unix(nt); return timestring(mem_ctx, t); } -- cgit From 55d4d36993293fee914a009f1d8f05810e347f2b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 00:54:57 +0000 Subject: r5102: This is a major simplification of the logic for controlling top level servers in smbd. The old code still contained a fairly bit of legacy from the time when smbd was only handling SMB connection. The new code gets rid of all of the smb_server specific code in smbd/, and creates a much simpler infrastructures for new server code. Major changes include: - simplified the process model code a lot. - got rid of the top level server and service structures completely. The top level context is now the event_context. This got rid of service.h and server.h completely (they were the most confusing parts of the old code) - added service_stream.[ch] for the helper functions that are specific to stream type services (services that handle streams, and use a logically separate process per connection) - got rid of the builtin idle_handler code in the service logic, as none of the servers were using it, and it can easily be handled by a server in future by adding its own timed_event to the event context. - fixed some major memory leaks in the rpc server code. - added registration of servers, rather than hard coding our list of possible servers. This allows for servers as modules in the future. - temporarily disabled the winbind code until I add the helper functions for that type of server - added error checking on service startup. If a configured server fails to startup then smbd doesn't startup. - cleaned up the command line handling in smbd, removing unused options (This used to be commit cf6a46c3cbde7b1eb1b86bd3882b953a2de3a42e) --- source4/lib/messaging/messaging.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index e2e8161111..09d30027b0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -33,7 +33,7 @@ #define MESSAGING_BACKOFF 250000 struct messaging_context { - servid_t server_id; + uint32_t server_id; struct socket_context *sock; char *path; struct dispatch_fn *dispatch; @@ -51,7 +51,7 @@ struct dispatch_fn { uint32_t msg_type; void *private; void (*fn)(struct messaging_context *msg, void *private, - uint32_t msg_type, servid_t server_id, DATA_BLOB *data); + uint32_t msg_type, uint32_t server_id, DATA_BLOB *data); }; /* an individual message */ @@ -64,8 +64,8 @@ struct messaging_rec { struct { uint32_t version; uint32_t msg_type; - servid_t from; - servid_t to; + uint32_t from; + uint32_t to; uint32_t length; } header; @@ -78,7 +78,7 @@ struct messaging_rec { A useful function for testing the message system. */ static void ping_message(struct messaging_context *msg, void *private, - uint32_t msg_type, servid_t src, DATA_BLOB *data) + uint32_t msg_type, uint32_t src, DATA_BLOB *data) { DEBUG(1,("INFO: Received PING message from server %u [%.*s]\n", (uint_t)src, data->length, data->data?(const char *)data->data:"")); @@ -88,7 +88,7 @@ static void ping_message(struct messaging_context *msg, void *private, /* return the path to a messaging socket */ -static char *messaging_path(TALLOC_CTX *mem_ctx, servid_t server_id) +static char *messaging_path(TALLOC_CTX *mem_ctx, uint32_t server_id) { char *name = talloc_asprintf(mem_ctx, "messaging/msg.%u", (unsigned)server_id); char *ret; @@ -228,7 +228,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * */ void messaging_register(struct messaging_context *msg, void *private, uint32_t msg_type, - void (*fn)(struct messaging_context *, void *, uint32_t, servid_t, DATA_BLOB *)) + void (*fn)(struct messaging_context *, void *, uint32_t, uint32_t, DATA_BLOB *)) { struct dispatch_fn *d; @@ -365,7 +365,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve /* Send a message to a particular server */ -NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t msg_type, DATA_BLOB *data) +NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t msg_type, DATA_BLOB *data) { struct messaging_rec *rec; NTSTATUS status; @@ -429,7 +429,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t /* Send a message to a particular server, with the message containing a single pointer */ -NTSTATUS messaging_send_ptr(struct messaging_context *msg, servid_t server, +NTSTATUS messaging_send_ptr(struct messaging_context *msg, uint32_t server, uint32_t msg_type, void *ptr) { DATA_BLOB blob; @@ -454,7 +454,7 @@ static int messaging_destructor(void *ptr) /* create the listening socket and setup the dispatcher */ -struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id, struct event_context *ev) +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id, struct event_context *ev) { struct messaging_context *msg; NTSTATUS status; @@ -496,7 +496,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id fde.flags = EVENT_FD_READ; fde.handler = messaging_listen_handler; - msg->event.ev = talloc_reference(msg,ev); + msg->event.ev = talloc_reference(msg, ev); msg->event.fde = event_add_fd(ev, &fde, msg); talloc_set_destructor(msg, messaging_destructor); -- cgit From 1447b9a8c135ddc8d369be9ab970a4cccf4ecf0e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 02:55:30 +0000 Subject: r5104: - added support for task based servers. These are servers that within themselves are run as a single process, but run as a child of the main process when smbd is run in the standard model, and run as part of the main process when in the single mode. - rewrote the winbind template code to use the new task services. Also fixed the packet queueing - got rid of event_context_merge() as it is no longer needed (This used to be commit 339964a596689278d2138cff05d7d444798a3504) --- source4/lib/events.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index d32a1344e0..c09d9b5030 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -110,32 +110,6 @@ static void calc_maxfd(struct event_context *ev) } } -/* - move the event structures from ev2 into ev, upping the reference - count on ev. The event context ev2 is then destroyed. - - this is used by modules that need to call on the events of a lower module -*/ -struct event_context *event_context_merge(struct event_context *ev, - struct event_context *ev2) -{ - DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *); - DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *); - DLIST_CONCATENATE(ev->loop_events, ev2->loop_events, struct loop_event *); - - ev2->fd_events = NULL; - ev2->timed_events = NULL; - ev2->loop_events = NULL; - - talloc_steal(ev->events, ev2->events); - - event_context_destroy(ev2); - - calc_maxfd(ev); - - return ev; -} - /* to mark the ev->maxfd invalid * this means we need to recalculate it */ -- cgit From 791426317cd00355f2199e049949ee877c94d229 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 07:07:11 +0000 Subject: r5105: removed some unused events functions. These are no longer needed as destructors are used to remove pending socket events (This used to be commit ce62105434ab02e94e38897409c3512905c48f02) --- source4/lib/events.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index c09d9b5030..98c2b9cfa8 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -150,36 +150,6 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, } -/* - remove all fd based events that match a specified fd -*/ -void event_remove_fd_all(struct event_context *ev, int fd) -{ - struct fd_event *e = ev->fd_events; - /* be careful to cope with extra reference counts on events */ - while (e) { - if (talloc_free(ev->fd_events) == 0) { - e = ev->fd_events; - } else { - e = e->next; - } - } -} - -/* - remove all fd based events that match a specified handler -*/ -void event_remove_fd_all_handler(struct event_context *ev, void *handler) -{ - struct fd_event *e, *next; - for (e=ev->fd_events; e; e=next) { - next = e->next; - if (handler == (void *)e->handler) { - talloc_free(e); - } - } -} - static int event_timed_destructor(void *ptr) { struct timed_event *te = talloc_get_type(ptr, struct timed_event); -- cgit From 003fbe7f6472ed433bc5495b422f3e6d5278da17 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 07:08:08 +0000 Subject: r5106: removed a bunch of unused socket functions. We still need open_socket_out() as its used by the ldap client code (uggh) (This used to be commit 95d9766be8b08b7ca52c24d4ed3313e147edb159) --- source4/lib/util_sock.c | 374 +----------------------------------------------- 1 file changed, 1 insertion(+), 373 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 7fe42f7ffc..1859aef4d7 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -23,16 +23,6 @@ #include "system/network.h" -/**************************************************************************** - Determine if a file descriptor is in fact a socket. -****************************************************************************/ -BOOL is_a_socket(int fd) -{ - int v,l; - l = sizeof(int); - return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0; -} - enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; typedef struct smb_socket_option { @@ -79,28 +69,10 @@ static const smb_socket_option socket_options[] = { #endif {NULL,0,0,0,0}}; -/**************************************************************************** - Print socket options. -****************************************************************************/ - -static void print_socket_options(int s) -{ - int value, vlen = 4; - const smb_socket_option *p = &socket_options[0]; - - for (; p->name != NULL; p++) { - if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) { - DEBUG(5,("Could not test socket option %s.\n", p->name)); - } else { - DEBUG(5,("socket option %s = %d\n",p->name,value)); - } - } - } /**************************************************************************** Set user socket options. ****************************************************************************/ - void set_socket_options(int fd, const char *options) { fstring tok; @@ -148,43 +120,12 @@ void set_socket_options(int fd, const char *options) if (ret != 0) DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); } - - print_socket_options(fd); -} - -/**************************************************************************** - Read from a socket. -****************************************************************************/ - -ssize_t read_udp_socket(int fd, char *buf, size_t len, - struct ipv4_addr *from_addr, int *from_port) -{ - ssize_t ret; - struct sockaddr_in sock; - socklen_t socklen = sizeof(sock); - - ret = recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen); - if (ret <= 0) { - DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); - return 0; - } - - if (from_addr) { - from_addr->addr = sock.sin_addr.s_addr; - } - if (from_port) { - *from_port = ntohs(sock.sin_port); - } - - return ret; } - /**************************************************************************** Check the timeout. ****************************************************************************/ - static BOOL timeout_until(struct timeval *timeout, const struct timeval *endtime) { @@ -206,7 +147,6 @@ static BOOL timeout_until(struct timeval *timeout, /**************************************************************************** Read data from the client, reading exactly N bytes, with timeout. ****************************************************************************/ - ssize_t read_data_until(int fd,char *buffer,size_t N, const struct timeval *endtime) { @@ -247,10 +187,10 @@ ssize_t read_data_until(int fd,char *buffer,size_t N, return (ssize_t)total; } + /**************************************************************************** Write data to a fd with timeout. ****************************************************************************/ - ssize_t write_data_until(int fd,char *buffer,size_t N, const struct timeval *endtime) { @@ -290,50 +230,6 @@ ssize_t write_data_until(int fd,char *buffer,size_t N, } -/**************************************************************************** - Open a socket of the specified type, port, and address for incoming data. -****************************************************************************/ -int open_socket_in( int type, int port, int dlevel, uint32_t socket_addr, BOOL rebind ) -{ - struct sockaddr_in sock; - int res; - - memset( (char *)&sock, '\0', sizeof(sock) ); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = htons( port ); - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = socket_addr; - - res = socket( AF_INET, type, 0 ); - if( res == -1 ) { - DEBUG(0,("open_socket_in(): socket() call failed: %s\n", strerror(errno))); - return -1; - } - - /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */ - { - int val = rebind ? 1 : 0; - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif - } - - /* now we've got a socket - we need to bind it */ - if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) { - DEBUG(0,("bind failed on port %d - %s\n", port, strerror(errno))); - close( res ); - return( -1 ); - } - - DEBUG( 10, ( "bind succeeded on port %d\n", port ) ); - - return( res ); - } - /**************************************************************************** create an outgoing socket. timeout is in milliseconds. @@ -401,271 +297,3 @@ connect_again: return res; } -/* - open a connected UDP socket to host on port -*/ -int open_udp_socket(const char *host, int port) -{ - int type = SOCK_DGRAM; - struct sockaddr_in sock_out; - int res; - struct ipv4_addr addr; - TALLOC_CTX *mem_ctx; - - mem_ctx = talloc_init("open_udp_socket"); - if (!mem_ctx) { - return -1; - } - addr = interpret_addr2(host); - - res = socket(PF_INET, type, 0); - if (res == -1) { - return -1; - } - - memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)&addr); - sock_out.sin_port = htons(port); - sock_out.sin_family = PF_INET; - - talloc_free(mem_ctx); - - if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) { - close(res); - return -1; - } - - return res; -} - - -/******************************************************************* - matchname - determine if host name matches IP address. Used to - confirm a hostname lookup to prevent spoof attacks - ******************************************************************/ -static BOOL matchname(char *remotehost, struct ipv4_addr addr) -{ - struct hostent *hp; - int i; - - if ((hp = sys_gethostbyname(remotehost)) == 0) { - DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n", remotehost)); - return False; - } - - /* - * Make sure that gethostbyname() returns the "correct" host name. - * Unfortunately, gethostbyname("localhost") sometimes yields - * "localhost.domain". Since the latter host name comes from the - * local DNS, we just have to trust it (all bets are off if the local - * DNS is perverted). We always check the address list, though. - */ - - if (strcasecmp(remotehost, hp->h_name) - && strcasecmp(remotehost, "localhost")) { - DEBUG(0,("host name/name mismatch: %s != %s\n", - remotehost, hp->h_name)); - return False; - } - - /* Look up the host address in the address list we just got. */ - for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0) - return True; - } - - /* - * The host name does not map to the original host address. Perhaps - * someone has compromised a name server. More likely someone botched - * it, but that could be dangerous, too. - */ - - DEBUG(0,("host name/address mismatch: %s != %s\n", - sys_inet_ntoa(addr), hp->h_name)); - return False; -} - - -/******************************************************************* - return the DNS name of the remote end of a socket - ******************************************************************/ -char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) -{ - char *name_buf; - struct hostent *hp; - struct ipv4_addr addr; - char *p; - - /* reverse lookups can be *very* expensive, and in many - situations won't work because many networks don't link dhcp - with dns. To avoid the delay we avoid the lookup if - possible */ - if (!lp_hostname_lookups() && (force_lookup == False)) { - return get_socket_addr(mem_ctx, fd); - } - - p = get_socket_addr(mem_ctx, fd); - - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - if (fd == -1) return name_buf; - - addr = interpret_addr2(p); - - /* Look up the remote host name. */ - if ((hp = gethostbyaddr((char *)&addr.addr, sizeof(addr.addr), AF_INET)) == 0) { - DEBUG(1,("Gethostbyaddr failed for %s\n",p)); - name_buf = talloc_strdup(mem_ctx, p); - } else { - name_buf = talloc_strdup(mem_ctx, (char *)hp->h_name); - if (!matchname(name_buf, addr)) { - DEBUG(0,("Matchname failed on %s %s\n",name_buf,p)); - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - } - } - - alpha_strcpy(name_buf, name_buf, "_-.", strlen(name_buf)+1); - if (strstr(name_buf,"..")) { - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - } - - return name_buf; -} - -/******************************************************************* - return the IP addr of the remote end of a socket as a string - ******************************************************************/ -char *get_socket_addr(TALLOC_CTX *mem_ctx, int fd) -{ - struct sockaddr sa; - struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); - - if (fd == -1 || getpeername(fd, &sa, &length) == -1) { - return talloc_strdup(mem_ctx, "0.0.0.0"); - } - - return talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr)); -} - - - -/******************************************************************* -this is like socketpair but uses tcp. It is used by the Samba -regression test code -The function guarantees that nobody else can attach to the socket, -or if they do that this function fails and the socket gets closed -returns 0 on success, -1 on failure -the resulting file descriptors are symmetrical - ******************************************************************/ -static int socketpair_tcp(int fd[2]) -{ - int listener; - struct sockaddr_in sock; - struct sockaddr_in sock2; - socklen_t socklen = sizeof(sock); - int connect_done = 0; - - fd[0] = fd[1] = listener = -1; - - memset(&sock, 0, sizeof(sock)); - - if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; - - memset(&sock2, 0, sizeof(sock2)); -#ifdef HAVE_SOCK_SIN_LEN - sock2.sin_len = sizeof(sock2); -#endif - sock2.sin_family = PF_INET; - - bind(listener, (struct sockaddr *)&sock2, sizeof(sock2)); - - if (listen(listener, 1) != 0) goto failed; - - if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed; - - if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; - - set_blocking(fd[1], 0); - - sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) { - if (errno != EINPROGRESS) goto failed; - } else { - connect_done = 1; - } - - if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed; - - close(listener); - if (connect_done == 0) { - if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0 - && errno != EISCONN) goto failed; - } - - set_blocking(fd[1], 1); - - /* all OK! */ - return 0; - - failed: - if (fd[0] != -1) close(fd[0]); - if (fd[1] != -1) close(fd[1]); - if (listener != -1) close(listener); - return -1; -} - - -/******************************************************************* -run a program on a local tcp socket, this is used to launch smbd -when regression testing -the return value is a socket which is attached to a subprocess -running "prog". stdin and stdout are attached. stderr is left -attached to the original stderr - ******************************************************************/ -int sock_exec(const char *prog) -{ - int fd[2]; - if (socketpair_tcp(fd) != 0) { - DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno))); - return -1; - } - if (fork() == 0) { - close(fd[0]); - close(0); - close(1); - dup(fd[1]); - dup(fd[1]); - exit(system(prog)); - } - close(fd[1]); - return fd[0]; -} - - -/* - determine if a packet is pending for receive on a socket -*/ -BOOL socket_pending(int fd) -{ - fd_set fds; - int selrtn; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - - /* immediate timeout */ - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - /* yes, this is supposed to be a normal select not a sys_select() */ - selrtn = select(fd+1,&fds,NULL,NULL,&timeout); - - if (selrtn == 1) { - /* the fd is readable */ - return True; - } - - return False; -} -- cgit From a0ab1f7afda62964d480af9dc26e60a38d1350e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 07:22:16 +0000 Subject: r5107: moved the horrible ldap socket code, and the even worse asn1-tied-to-blocking-sockets code into the ldap client and torture suite, and out of the generic libs, so nobody else is tempted to use it for any new code. (This used to be commit 39d1ced21baeca40d1fca62ba65243ca8f15757e) --- source4/lib/util_sock.c | 175 ------------------------------------------------ 1 file changed, 175 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 1859aef4d7..b2f949ebe5 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -122,178 +122,3 @@ void set_socket_options(int fd, const char *options) } } - -/**************************************************************************** - Check the timeout. -****************************************************************************/ -static BOOL timeout_until(struct timeval *timeout, - const struct timeval *endtime) -{ - struct timeval now; - - GetTimeOfDay(&now); - - if ((now.tv_sec > endtime->tv_sec) || - ((now.tv_sec == endtime->tv_sec) && - (now.tv_usec > endtime->tv_usec))) - return False; - - timeout->tv_sec = endtime->tv_sec - now.tv_sec; - timeout->tv_usec = endtime->tv_usec - now.tv_usec; - return True; -} - - -/**************************************************************************** - Read data from the client, reading exactly N bytes, with timeout. -****************************************************************************/ -ssize_t read_data_until(int fd,char *buffer,size_t N, - const struct timeval *endtime) -{ - ssize_t ret; - size_t total=0; - - while (total < N) { - - if (endtime != NULL) { - fd_set r_fds; - struct timeval timeout; - int res; - - FD_ZERO(&r_fds); - FD_SET(fd, &r_fds); - - if (!timeout_until(&timeout, endtime)) - return -1; - - res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout); - if (res <= 0) - return -1; - } - - ret = sys_read(fd,buffer + total,N - total); - - if (ret == 0) { - DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); - return 0; - } - - if (ret == -1) { - DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); - return -1; - } - total += ret; - } - return (ssize_t)total; -} - - -/**************************************************************************** - Write data to a fd with timeout. -****************************************************************************/ -ssize_t write_data_until(int fd,char *buffer,size_t N, - const struct timeval *endtime) -{ - size_t total=0; - ssize_t ret; - - while (total < N) { - - if (endtime != NULL) { - fd_set w_fds; - struct timeval timeout; - int res; - - FD_ZERO(&w_fds); - FD_SET(fd, &w_fds); - - if (!timeout_until(&timeout, endtime)) - return -1; - - res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout); - if (res <= 0) - return -1; - } - - ret = sys_write(fd,buffer + total,N - total); - - if (ret == -1) { - DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); - return -1; - } - if (ret == 0) - return total; - - total += ret; - } - return (ssize_t)total; -} - - - -/**************************************************************************** - create an outgoing socket. timeout is in milliseconds. - **************************************************************************/ -int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout) -{ - struct sockaddr_in sock_out; - int res,ret; - int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout) / connect_loop; - - /* create a socket to write to */ - res = socket(PF_INET, type, 0); - if (res == -1) - { DEBUG(0,("socket error\n")); return -1; } - - if (type != SOCK_STREAM) return(res); - - memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); - - sock_out.sin_port = htons( port ); - sock_out.sin_family = PF_INET; - - /* set it non-blocking */ - set_blocking(res,False); - - DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port)); - - /* and connect it to the destination */ -connect_again: - ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && loops--) { - msleep(connect_loop); - goto connect_again; - } - - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port)); - close(res); - return -1; - } - -#ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; - } -#endif - - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - sys_inet_ntoa(*addr),port,strerror(errno))); - close(res); - return -1; - } - - /* set it blocking again */ - set_blocking(res,True); - - return res; -} - -- cgit From c7ded5ab0accc54a28df4d43cb923e6c808ff347 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 10:24:36 +0000 Subject: r5108: the beginnings of a nbtd server for Samba4. Currently just displays the packets it receives, but it at least shows how the server structure will work. To implement it I extended the libcli/nbt/ library to allow for an incoming packet handler to be registered. That allows the nbt client library to be used for low level processing of the nbtd server packets. Other changes: - made the socket library always set SO_REUSEADDR when binding to an interface, to ensure that restarts of a server don't have to wait for a couple of minutes. - made the nbt port configurable. Defaults to 137, but other ports will be useful for testing. (This used to be commit 2fedca6adfd4df9e85cc86896dfa79630777a917) --- source4/lib/socket/socket_ipv4.c | 2 ++ source4/lib/socket/socket_ipv6.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index aaa5ce0fa2..09a4b4a73a 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -139,6 +139,8 @@ static NTSTATUS ipv4_listen(struct socket_context *sock, struct ipv4_addr ip_addr; int ret; + socket_set_option(sock, "SO_REUSEADDR=1", NULL); + ip_addr = interpret_addr2(my_address); ZERO_STRUCT(my_addr); diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 1dd7fe8e9d..f5cd756259 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -125,6 +125,8 @@ static NTSTATUS ipv6_tcp_listen(struct socket_context *sock, struct in6_addr ip_addr; int ret; + socket_set_option(sock, "SO_REUSEADDR=1", NULL); + ip_addr = interpret_addr6(my_address); ZERO_STRUCT(my_addr); -- cgit From 414f6c80b22b128c25d947d62f6b5d1ec13091b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Jan 2005 01:57:58 +0000 Subject: r5114: the nbtd task can now act as a basic B-node server. It registers its names on the network and answers name queries. Lots of details are still missing, but at least this now means you don't need a Samba3 nmbd to use Samba4. missing pieces include: - name registrations should be "shout 3 times, then demand" - no WINS server yet - no master browser code (This used to be commit d7d31fdc6670f026f96b50e51a4de19f0b920e5b) --- source4/lib/netif/interface.c | 14 ++++ source4/lib/util_strlist.c | 168 ------------------------------------------ 2 files changed, 14 insertions(+), 168 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 4f22095f7a..bf1e147e02 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -330,6 +330,20 @@ struct ipv4_addr *iface_n_bcast(int n) return NULL; } +/**************************************************************************** + return netmask of the Nth interface + **************************************************************************/ +struct ipv4_addr *iface_n_netmask(int n) +{ + struct interface *i; + + for (i=local_interfaces;i && n;i=i->next) + n--; + + if (i) return &i->nmask; + return NULL; +} + /* these 3 functions return the ip/bcast/nmask for the interface most appropriate for the given ip address. If they can't find an appropriate interface they return the requested field of the diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 33f824dcf8..d945c78472 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -152,173 +152,5 @@ void str_list_free(char ***list) SAFE_FREE(*list); } -BOOL str_list_substitute(char **list, const char *pattern, const char *insert) -{ - char *p, *s, *t; - ssize_t ls, lp, li, ld, i, d; - - if (!list) - return False; - if (!pattern) - return False; - if (!insert) - return False; - - lp = (ssize_t)strlen(pattern); - li = (ssize_t)strlen(insert); - ld = li -lp; - - while (*list) { - s = *list; - ls = (ssize_t)strlen(s); - - while ((p = strstr(s, pattern))) { - t = *list; - d = p -t; - if (ld) { - t = (char *) malloc(ls +ld +1); - if (!t) { - DEBUG(0,("str_list_substitute: Unable to allocate memory")); - return False; - } - memcpy(t, *list, d); - memcpy(t +d +li, p +lp, ls -d -lp +1); - SAFE_FREE(*list); - *list = t; - ls += ld; - s = t +d +li; - } - - for (i = 0; i < li; i++) { - switch (insert[i]) { - case '`': - case '"': - case '\'': - case ';': - case '$': - case '%': - case '\r': - case '\n': - t[d +i] = '_'; - break; - default: - t[d +i] = insert[i]; - } - } - } - - list++; - } - - return True; -} -#define IPSTR_LIST_SEP "," - -/** - * Add ip string representation to ipstr list. Used also - * as part of @function ipstr_list_make - * - * @param ipstr_list pointer to string containing ip list; - * MUST BE already allocated and IS reallocated if necessary - * @param ipstr_size pointer to current size of ipstr_list (might be changed - * as a result of reallocation) - * @param ip IP address which is to be added to list - * @return pointer to string appended with new ip and possibly - * reallocated to new length - **/ - -char* ipstr_list_add(char** ipstr_list, const struct ipv4_addr *ip) -{ - char* new_ipstr = NULL; - - /* arguments checking */ - if (!ipstr_list || !ip) return NULL; - - /* attempt to convert ip to a string and append colon separator to it */ - if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,sys_inet_ntoa(*ip)); - SAFE_FREE(*ipstr_list); - } else { - asprintf(&new_ipstr, "%s", sys_inet_ntoa(*ip)); - } - *ipstr_list = new_ipstr; - return *ipstr_list; -} - -/** - * Allocate and initialise an ipstr list using ip adresses - * passed as arguments. - * - * @param ipstr_list pointer to string meant to be allocated and set - * @param ip_list array of ip addresses to place in the list - * @param ip_count number of addresses stored in ip_list - * @return pointer to allocated ip string - **/ - -char* ipstr_list_make(char** ipstr_list, const struct ipv4_addr* ip_list, int ip_count) -{ - int i; - - /* arguments checking */ - if (!ip_list && !ipstr_list) return 0; - - *ipstr_list = NULL; - - /* process ip addresses given as arguments */ - for (i = 0; i < ip_count; i++) - *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]); - - return (*ipstr_list); -} - - -/** - * Parse given ip string list into array of ip addresses - * (as in_addr structures) - * - * @param ipstr ip string list to be parsed - * @param ip_list pointer to array of ip addresses which is - * allocated by this function and must be freed by caller - * @return number of succesfully parsed addresses - **/ - -int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list) -{ - fstring token_str; - int count; - - if (!ipstr_list || !ip_list) return 0; - - for (*ip_list = NULL, count = 0; - next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); - count++) { - - struct ipv4_addr addr; - - /* convert single token to ip address */ - if ( (addr.addr = sys_inet_addr(token_str)) == INADDR_NONE ) - break; - - /* prepare place for another in_addr structure */ - *ip_list = realloc_p(*ip_list, struct ipv4_addr, count + 1); - if (!*ip_list) return -1; - - (*ip_list)[count] = addr; - } - - return count; -} - - -/** - * Safely free ip string list - * - * @param ipstr_list ip string list to be freed - **/ - -void ipstr_list_free(char* ipstr_list) -{ - SAFE_FREE(ipstr_list); -} -- cgit From 784dde73bc2f59108c6f5123b9206851b97afc32 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Jan 2005 04:51:50 +0000 Subject: r5119: fflush after talloc reports to ensure they are fully on disk when using tee (This used to be commit e73e49aaa64f6f976918f087cf196b00eecc3eb2) --- source4/lib/talloc/talloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index f6f7e899d1..291ee5a8bf 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -757,6 +757,7 @@ void talloc_report_full(const void *ptr, FILE *f) (unsigned long)talloc_total_blocks(ptr)); talloc_report_depth(ptr, f, 1); + fflush(f); } /* @@ -784,7 +785,7 @@ void talloc_report(const void *ptr, FILE *f) (unsigned long)talloc_total_size(c+1), (unsigned long)talloc_total_blocks(c+1)); } - + fflush(f); } /* -- cgit From 58d6c73e946d11574a6220f37887e1cdfe05f525 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Jan 2005 08:18:52 +0000 Subject: r5123: fixed a bug in the timed events handling. It was possible for a timed event handler to trigger a free that could cause a timer to be triggered twice. This changs fixes it properly by marking timer events to be removed using a zero next_event time. I also changed the default timeout for events.c to be infinite, so if there are no events to handle then smbd will sit forever doing nothing. That allows it to be swapped out completely when idle. (This used to be commit 0f1fb7017ee441cbebcad45900435adb57ca1760) --- source4/lib/events.c | 29 ++++++++++++++++++----------- source4/lib/time.c | 8 ++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 98c2b9cfa8..3263be08f1 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -221,7 +221,7 @@ int event_loop_once(struct event_context *ev) fd_set r_fds, w_fds; struct fd_event *fe; struct loop_event *le; - struct timed_event *te; + struct timed_event *te, *te_next; int selrtn; struct timeval tval, t; uint32_t destruction_count = ev->destruction_count; @@ -253,13 +253,24 @@ int event_loop_once(struct event_context *ev) } /* start with a reasonable max timeout */ - tval.tv_sec = 600; + tval.tv_sec = 0; tval.tv_usec = 0; /* work out the right timeout for all timed events */ - for (te=ev->timed_events;te;te=te->next) { - struct timeval tv = timeval_diff(&te->next_event, &t); - tval = timeval_min(&tv, &tval); + for (te=ev->timed_events;te;te=te_next) { + struct timeval tv; + te_next = te->next; + if (timeval_is_zero(&te->next_event)) { + talloc_free(te); + continue; + } + + tv = timeval_diff(&te->next_event, &t); + if (timeval_is_zero(&tval)) { + tval = tv; + } else { + tval = timeval_min(&tv, &tval); + } } /* only do a select() if there're fd_events @@ -316,18 +327,14 @@ int event_loop_once(struct event_context *ev) for (te=ev->timed_events;te;) { struct timed_event *next = te->next; if (timeval_compare(&te->next_event, &t) >= 0) { + te->next_event = timeval_zero(); te->handler(ev, te, t); if (destruction_count != ev->destruction_count) { break; } - if (timeval_compare(&te->next_event, &t) >= 0) { - /* the handler didn't set a time for the - next event - remove the event */ - talloc_free(te); - } } te = next; - } + } return 0; } diff --git a/source4/lib/time.c b/source4/lib/time.c index e214179b6c..7a4059f646 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -401,6 +401,14 @@ struct timeval timeval_zero(void) return tv; } +/* + return True if a timeval is zero +*/ +BOOL timeval_is_zero(struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + /* return a timeval for the current time */ -- cgit From 547d54a6debc390391d5fc4269d43f2d1f3443cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Jan 2005 09:53:21 +0000 Subject: r5129: make sure we don't spin chewing CPU time due to my last change (This used to be commit 69e97ad9c397261cd6edb6f7504021942f16c0ec) --- source4/lib/events.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 3263be08f1..166cbe4509 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -290,7 +290,11 @@ int event_loop_once(struct event_context *ev) * sys_select() with something in the events * structure - for now just use select() */ - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + if (timeval_is_zero(&tval)) { + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, NULL); + } else { + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); + } t = timeval_current(); -- cgit From 73a0b6ea476ee19bb814c3257daca7c116d42872 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 31 Jan 2005 15:58:54 +0000 Subject: r5134: - fix types to always use _t types - add #include "system/filesys.h" where needed metze (This used to be commit 6bb07a0ed8a4baaeaa1d63bde8ce773364860fd2) --- source4/lib/registry/common/reg_interface.c | 6 +++--- source4/lib/registry/common/reg_util.c | 10 +++++----- source4/lib/registry/reg_backend_nt4.c | 1 + source4/lib/registry/reg_backend_w95.c | 1 + source4/lib/registry/tools/regpatch.c | 1 + 5 files changed, 11 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 8385cef108..42bf8f9389 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -426,7 +426,7 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const return WERR_OK; } -WERROR reg_val_set(struct registry_key *key, const char *value, uint32 type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, void *data, int len) { /* A 'real' set function has preference */ if (key->hive->functions->set_value) @@ -470,7 +470,7 @@ WERROR reg_key_flush(struct registry_key *key) return WERR_OK; } -WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint32 *max_subkeysize) +WERROR reg_key_subkeysizes(struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize) { int i = 0; struct registry_key *subkey; @@ -495,7 +495,7 @@ WERROR reg_key_subkeysizes(struct registry_key *key, uint32 *max_subkeylen, uint return WERR_OK; } -WERROR reg_key_valuesizes(struct registry_key *key, uint32 *max_valnamelen, uint32 *max_valbufsize) +WERROR reg_key_valuesizes(struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize) { int i = 0; struct registry_value *value; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index b11b24151e..d4fdc59d70 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -25,7 +25,7 @@ #define DBGC_CLASS DBGC_REGISTRY static const struct { - uint32 id; + uint32_t id; const char *name; } reg_value_types[] = { { REG_SZ, "REG_SZ" }, @@ -122,9 +122,9 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da (*value)->data_len = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), &(*value)->data_blk); break; case REG_DWORD: - (*value)->data_len = sizeof(uint32); - (*value)->data_blk = talloc(mem_ctx, uint32); - *((uint32 *)(*value)->data_blk) = strtol(data_str, NULL, 0); + (*value)->data_len = sizeof(uint32_t); + (*value)->data_blk = talloc(mem_ctx, uint32_t); + *((uint32_t *)(*value)->data_blk) = strtol(data_str, NULL, 0); break; case REG_NONE: @@ -269,7 +269,7 @@ WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) return error; } -WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, struct security_descriptor *sec_desc, struct registry_key **result) +WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **result) { struct registry_key *parent; const char *n; diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 88033a8a8b..d700070cde 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -306,6 +306,7 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, #include "includes.h" #include "registry.h" +#include "system/filesys.h" #include "system/shmem.h" #define REG_KEY_LIST_SIZE 10 diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index ff02f4d12b..45b6105801 100644 --- a/source4/lib/registry/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -21,6 +21,7 @@ #include "includes.h" #include "registry.h" +#include "system/filesys.h" #include "system/shmem.h" /** diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 600c1f60e7..ee7568cc0f 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -24,6 +24,7 @@ #include "dynconfig.h" #include "registry.h" #include "lib/cmdline/popt_common.h" +#include "system/filesys.h" /* * Routines to parse a REGEDIT4 file -- cgit From 2cb711f39f80adbe7375c809c57106ac8e71d5d8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 31 Jan 2005 16:01:22 +0000 Subject: r5135: I prepare a clean up in includes.h metze (This used to be commit 670e088e94468a5311353dbbaa7e34d200999313) --- source4/lib/cmdline/popt_common.c | 3 ++- source4/lib/cmdline/readline.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index e440611ee4..0445877e7a 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -23,6 +23,7 @@ #include "includes.h" #include "version.h" #include "dynconfig.h" +#include "system/filesys.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" @@ -403,7 +404,7 @@ static void popt_common_credentials_callback(poptContext con, snprintf(cmdline_auth_info.username, sizeof(cmdline_auth_info.username), "%s$", lp_netbios_name()); pstrcpy(cmdline_auth_info.password,opt_password); - SAFE_FREE(opt_password); + free(opt_password); cmdline_auth_info.got_pass = True; pstrcpy(cmdline_auth_info.domain, lp_workgroup()); diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 83d476b0d1..8836759f70 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -21,6 +21,8 @@ #include "includes.h" +#include + #ifdef HAVE_LIBREADLINE # ifdef HAVE_READLINE_READLINE_H # include -- cgit From dd0d8b2a89309302e94c3fec1c06ce769a1fec60 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 31 Jan 2005 16:36:57 +0000 Subject: r5142: fix compiler warning metze (This used to be commit d8aeb69ea85cc0df89e213482c446eb8e793bc86) --- source4/lib/talloc/testsuite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 4a1074e045..967874917d 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -641,7 +641,7 @@ static BOOL test_type(void) return False; } talloc_set_type(el1, struct el2); - if (talloc_get_type(el1, struct el2) != el1) { + if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) { printf("type set failed on el1 with el2\n"); return False; } -- cgit From 852228e8c67f2dc29a8402ae94998f562878c15f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 31 Jan 2005 16:46:48 +0000 Subject: r5143: don't generate prototypes for lib/tdb/ metze (This used to be commit 1c48c30aaf58d069cdba2f59b5c012bc4bdd3efc) --- source4/lib/tdb/config.mk | 1 + source4/lib/tdb/include/tdb.h | 2 ++ source4/lib/tdb/include/tdbutil.h | 10 +++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 96c2c590cb..2b2a595fca 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -6,6 +6,7 @@ INIT_OBJ_FILES = \ ADD_OBJ_FILES = \ lib/tdb/common/tdbutil.o \ lib/tdb/common/spinlock.o +NOPROTO=YES REQUIRED_SUBSYSTEMS = \ LIBREPLACE # diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 416333f0b0..f53503a1d6 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -141,6 +141,8 @@ void tdb_unlockall(TDB_CONTEXT *tdb); void tdb_set_lock_alarm(sig_atomic_t *palarm); int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key); /* Debug functions. Not used in production. */ void tdb_dump_all(TDB_CONTEXT *tdb); diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index 01473446a1..cfa83bd937 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -32,6 +32,14 @@ typedef struct keys_node TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); void tdb_search_list_free(TDB_LIST_NODE*); - +int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *oldval, int32_t change_val); +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout); +void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval); +int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr); +int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v); +int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state); +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags); +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr); #endif /* __TDBUTIL_H__ */ -- cgit From 96f02f7403a94e0b674e57cfd50f91cf763c7c5c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Feb 2005 10:24:47 +0000 Subject: r5170: fixed a bug handling events that have already timed out - they were being treated as events that never time out, so they happened on the next other event (This used to be commit 2eefe4f8dea4a9060f229417777435133c684a0c) --- source4/lib/events.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 166cbe4509..ebfa164885 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -223,7 +223,7 @@ int event_loop_once(struct event_context *ev) struct loop_event *le; struct timed_event *te, *te_next; int selrtn; - struct timeval tval, t; + struct timeval tval, t, *tvalp=NULL; uint32_t destruction_count = ev->destruction_count; t = timeval_current(); @@ -264,13 +264,13 @@ int event_loop_once(struct event_context *ev) talloc_free(te); continue; } - tv = timeval_diff(&te->next_event, &t); - if (timeval_is_zero(&tval)) { + if (tvalp == NULL) { tval = tv; } else { tval = timeval_min(&tv, &tval); } + tvalp = &tval; } /* only do a select() if there're fd_events @@ -290,11 +290,7 @@ int event_loop_once(struct event_context *ev) * sys_select() with something in the events * structure - for now just use select() */ - if (timeval_is_zero(&tval)) { - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, NULL); - } else { - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval); - } + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); t = timeval_current(); -- cgit From 66170ef8b36b499aa5b44ef10c1bd362a50f2636 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 02:35:52 +0000 Subject: r5185: make all the events data structures private to events.c. This will make it possible to add optimisations to the events code such as keeping the next timed event in a sorted list, and using epoll for file descriptor events. I also removed the loop events code, as it wasn't being used anywhere, and changed timed events to always be one-shot (as adding a new timed event in the event handler is so easy to do if needed) (This used to be commit d7b4b6de51342a65bf46fce772d313f92f8d73d3) --- source4/lib/basic.mk | 10 ++- source4/lib/events.c | 185 +++++++++++++++++++------------------- source4/lib/messaging/messaging.c | 76 ++++++---------- 3 files changed, 128 insertions(+), 143 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index af1420c685..dda79f50ad 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -32,6 +32,15 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBCRYPTO ############################## +############################## +# Start SUBSYSTEM LIBEVENTS +[SUBSYSTEM::LIBEVENTS] +NOPROTO = YES +INIT_OBJ_FILES = lib/events.o +REQUIRED_SUBSYSTEMS = LIBTALLOC +# End SUBSYSTEM LIBEVENTS +############################## + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -62,7 +71,6 @@ ADD_OBJ_FILES = \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/mutex.o \ - lib/events.o \ lib/server_mutex.o \ lib/idtree.o \ lib/unix_privs.o \ diff --git a/source4/lib/events.c b/source4/lib/events.c index ebfa164885..b2e0404e34 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -26,7 +26,7 @@ register one of the possible event types and implement that event somewhere else. - There are 4 types of event handling that are handled in this module: + There are 2 types of event handling that are handled in this module: 1) a file descriptor becoming readable or writeable. This is mostly used for network sockets, but can be used for any type of file @@ -41,15 +41,6 @@ like. When they are called the handler can choose to set the time for the next event. If next_event is not set then the event is removed. - 3) an event that happens every time through the select loop. These - sorts of events should be very fast, as they will occur a - lot. Mostly used for things like destroying a talloc context or - checking a signal flag. - - 4) an event triggered by a signal. These can be one shot or - repeated. You can have more than one handler registered for a - single signal if you want to. - To setup a set of events you first need to create a event_context structure using the function event_context_init(); This returns a 'struct event_context' that you use in all subsequent calls. @@ -59,8 +50,7 @@ Finally, you call event_loop_wait() to block waiting for one of the events to occor. In normal operation event_loop_wait() will loop - forever, unless you call event_loop_exit() from inside one of your - handler functions. + forever. */ @@ -70,6 +60,46 @@ #include "dlinklist.h" #include "events.h" + +/* + please read the comments in events.c before modifying +*/ + + +struct event_context { + /* list of filedescriptor events */ + struct fd_event { + struct event_context *event_ctx; + struct fd_event *next, *prev; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + void *private; + } *fd_events; + + /* list of timed events */ + struct timed_event { + struct event_context *event_ctx; + struct timed_event *next, *prev; + struct timeval next_event; + event_timed_handler_t handler; + void *private; + } *timed_events; + + /* the maximum file descriptor number in fd_events */ + int maxfd; + + /* information for exiting from the event loop */ + int exit_code; + + /* this is changed by the destructors for any event type. It + is used to detect event destruction by event handlers, + which means the code that is calling all event handles + needs to assume that the linked list is no longer valid + */ + uint32_t destruction_count; +}; + /* create a event_context structure. This must be the first events call, and all subsequent calls pass this event_context as the first @@ -82,20 +112,9 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) ev = talloc_zero(mem_ctx, struct event_context); if (!ev) return NULL; - ev->events = talloc_new(ev); - return ev; } -/* - destroy an events context, also destroying any remaining events -*/ -void event_context_destroy(struct event_context *ev) -{ - talloc_free(ev); -} - - /* recalculate the maxfd */ @@ -131,17 +150,25 @@ static int event_fd_destructor(void *ptr) add a fd based event return NULL on failure (memory allocation error) */ -struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, - TALLOC_CTX *mem_ctx) +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private) { - struct fd_event *e = talloc(ev->events, struct fd_event); + struct fd_event *e = talloc(ev, struct fd_event); if (!e) return NULL; - *e = *e0; - DLIST_ADD(ev->fd_events, e); + e->event_ctx = ev; + e->fd = fd; + e->flags = flags; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->fd_events, e); + if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } + talloc_set_destructor(e, event_fd_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); @@ -150,69 +177,58 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, } -static int event_timed_destructor(void *ptr) +/* + return the fd event flags +*/ +uint16_t event_fd_flags(struct fd_event *fde) { - struct timed_event *te = talloc_get_type(ptr, struct timed_event); - DLIST_REMOVE(te->event_ctx->timed_events, te); - te->event_ctx->destruction_count++; - return 0; + return fde->flags; } /* - add a timed event - return NULL on failure (memory allocation error) + set the fd event flags */ -struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0, - TALLOC_CTX *mem_ctx) +void event_fd_setflags(struct fd_event *fde, uint16_t flags) { - struct timed_event *e = talloc(ev->events, struct timed_event); - if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->timed_events, e); - talloc_set_destructor(e, event_timed_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); - } - return e; + fde->flags = flags; } -static int event_loop_destructor(void *ptr) +/* + destroy a timed event +*/ +static int event_timed_destructor(void *ptr) { - struct loop_event *le = talloc_get_type(ptr, struct loop_event); - DLIST_REMOVE(le->event_ctx->loop_events, le); - le->event_ctx->destruction_count++; + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + DLIST_REMOVE(te->event_ctx->timed_events, te); + te->event_ctx->destruction_count++; return 0; } /* - add a loop event + add a timed event return NULL on failure (memory allocation error) */ -struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0, - TALLOC_CTX *mem_ctx) +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private) { - struct loop_event *e = talloc(ev->events, struct loop_event); + struct timed_event *e = talloc(ev, struct timed_event); if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->loop_events, e); - talloc_set_destructor(e, event_loop_destructor); + + e->event_ctx = ev; + e->next_event = next_event; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->timed_events, e); + talloc_set_destructor(e, event_timed_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); } return e; } -/* - tell the event loop to exit with the specified code -*/ -void event_loop_exit(struct event_context *ev, int code) -{ - ev->exit.exit_now = True; - ev->exit.code = code; -} - /* do a single event loop using the events defined in ev this function */ @@ -220,23 +236,11 @@ int event_loop_once(struct event_context *ev) { fd_set r_fds, w_fds; struct fd_event *fe; - struct loop_event *le; struct timed_event *te, *te_next; int selrtn; - struct timeval tval, t, *tvalp=NULL; + struct timeval tval, t, *tvalp; uint32_t destruction_count = ev->destruction_count; - t = timeval_current(); - - /* the loop events are called on each loop. Be careful to allow the - event to remove itself */ - for (le=ev->loop_events;le;) { - struct loop_event *next = le->next; - le->handler(ev, le, t); - if (destruction_count != ev->destruction_count) break; - le = next; - } - FD_ZERO(&r_fds); FD_ZERO(&w_fds); @@ -252,9 +256,8 @@ int event_loop_once(struct event_context *ev) fe = next; } - /* start with a reasonable max timeout */ - tval.tv_sec = 0; - tval.tv_usec = 0; + tvalp = NULL; + t = timeval_current(); /* work out the right timeout for all timed events */ for (te=ev->timed_events;te;te=te_next) { @@ -301,7 +304,7 @@ int event_loop_once(struct event_context *ev) the event, so this must be a bug. This is a fatal error. */ DEBUG(0,("EBADF on event_loop_once - exiting\n")); - ev->exit.code = EBADF; + ev->exit_code = EBADF; return -1; } @@ -314,7 +317,7 @@ int event_loop_once(struct event_context *ev) if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (flags) { - fe->handler(ev, fe, t, flags); + fe->handler(ev, fe, t, flags, fe->private); if (destruction_count != ev->destruction_count) { break; } @@ -328,7 +331,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (timeval_compare(&te->next_event, &t) >= 0) { te->next_event = timeval_zero(); - te->handler(ev, te, t); + te->handler(ev, te, t, te->private); if (destruction_count != ev->destruction_count) { break; } @@ -348,16 +351,14 @@ int event_loop_once(struct event_context *ev) */ int event_loop_wait(struct event_context *ev) { - ZERO_STRUCT(ev->exit); + ev->exit_code = 0; ev->maxfd = EVENT_INVALID_MAXFD; - ev->exit.exit_now = False; - - while (ev->fd_events && !ev->exit.exit_now) { + while (ev->fd_events && ev->exit_code == 0) { if (event_loop_once(ev) != 0) { break; } } - return ev->exit.code; + return ev->exit_code; } diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 09d30027b0..53b6f434f0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -122,9 +122,9 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r handle IO for a single message */ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_rec *rec = fde->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); struct messaging_context *msg = rec->msg; NTSTATUS status; @@ -192,12 +192,12 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd handle a new incoming connection */ static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_context *msg = fde->private; + struct messaging_context *msg = talloc_get_type(private, + struct messaging_context); struct messaging_rec *rec; NTSTATUS status; - struct fd_event fde2; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { @@ -210,17 +210,12 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * } talloc_steal(rec, rec->sock); - rec->msg = msg; - rec->ndone = 0; + rec->msg = msg; + rec->ndone = 0; rec->header.length = 0; - rec->path = msg->path; - - fde2.private = rec; - fde2.fd = socket_get_fd(rec->sock); - fde2.flags = EVENT_FD_READ; - fde2.handler = messaging_recv_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde2, rec); + rec->path = msg->path; + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_READ, messaging_recv_handler, rec); } /* @@ -262,9 +257,9 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void handle IO for sending a message */ static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_rec *rec = fde->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); NTSTATUS status; if (rec->ndone < sizeof(rec->header)) { @@ -330,17 +325,18 @@ static NTSTATUS try_connect(struct messaging_rec *rec) when the servers listen queue is full we use this to backoff the message */ static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, - struct timeval t) + struct timeval t, void *private) { - struct messaging_rec *rec = te->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); struct messaging_context *msg = rec->msg; NTSTATUS status; - struct fd_event fde; status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff again */ - te->next_event = timeval_add(&t, 0, MESSAGING_BACKOFF); + event_add_timed(msg->event.ev, rec, + timeval_add(&t, 0, MESSAGING_BACKOFF), + messaging_backoff_handler, rec); return; } @@ -351,14 +347,8 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve return; } - fde.private = rec; - fde.fd = socket_get_fd(rec->sock); - fde.flags = EVENT_FD_WRITE; - fde.handler = messaging_send_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde, rec); - - messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); } @@ -369,7 +359,6 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t { struct messaging_rec *rec; NTSTATUS status; - struct fd_event fde; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { @@ -401,11 +390,9 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff on this message - the servers listen queue is full */ - struct timed_event te; - te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF); - te.handler = messaging_backoff_handler; - te.private = rec; - event_add_timed(msg->event.ev, &te, rec); + event_add_timed(msg->event.ev, rec, + timeval_current_ofs(0, MESSAGING_BACKOFF), + messaging_backoff_handler, rec); return NT_STATUS_OK; } @@ -414,14 +401,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t return status; } - fde.private = rec; - fde.fd = socket_get_fd(rec->sock); - fde.flags = EVENT_FD_WRITE; - fde.handler = messaging_send_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde, rec); - - messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); return NT_STATUS_OK; } @@ -458,7 +439,6 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id { struct messaging_context *msg; NTSTATUS status; - struct fd_event fde; msg = talloc(mem_ctx, struct messaging_context); if (msg == NULL) { @@ -491,13 +471,9 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id return NULL; } - fde.private = msg; - fde.fd = socket_get_fd(msg->sock); - fde.flags = EVENT_FD_READ; - fde.handler = messaging_listen_handler; - msg->event.ev = talloc_reference(msg, ev); - msg->event.fde = event_add_fd(ev, &fde, msg); + msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock), + EVENT_FD_READ, messaging_listen_handler, msg); talloc_set_destructor(msg, messaging_destructor); -- cgit From dd638d3e53be51fa77af77f5c94d33b23c26ef22 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 04:02:48 +0000 Subject: r5187: ordered the timed events in the events code, which makes processing events much more efficient (no linked lists need to be traversed, so large numbers of timers are no problem) (This used to be commit b45b9436d78b0ad288b27a1023579bb566ca6202) --- source4/lib/events.c | 142 +++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 77 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index b2e0404e34..10d15d8111 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -200,7 +200,6 @@ static int event_timed_destructor(void *ptr) { struct timed_event *te = talloc_get_type(ptr, struct timed_event); DLIST_REMOVE(te->event_ctx->timed_events, te); - te->event_ctx->destruction_count++; return 0; } @@ -213,19 +212,32 @@ struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ct event_timed_handler_t handler, void *private) { - struct timed_event *e = talloc(ev, struct timed_event); - if (!e) return NULL; + struct timed_event *te, *e; + + e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); + if (e == NULL) return NULL; e->event_ctx = ev; e->next_event = next_event; e->handler = handler; e->private = private; - DLIST_ADD(ev->timed_events, e); - talloc_set_destructor(e, event_timed_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); + /* keep the list ordered */ + if (ev->timed_events == NULL || + timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { + DLIST_ADD(ev->timed_events, e); + } else { + for (te=ev->timed_events;te && te->next;te=te->next) { + if (!timeval_is_zero(&te->next_event) && + timeval_compare(&te->next_event, &e->next_event) < 0) { + break; + } + } + DLIST_ADD_AFTER(ev->timed_events, e, te); } + + talloc_set_destructor(e, event_timed_destructor); + return e; } @@ -236,9 +248,8 @@ int event_loop_once(struct event_context *ev) { fd_set r_fds, w_fds; struct fd_event *fe; - struct timed_event *te, *te_next; int selrtn; - struct timeval tval, t, *tvalp; + struct timeval tval, *tvalp; uint32_t destruction_count = ev->destruction_count; FD_ZERO(&r_fds); @@ -257,88 +268,65 @@ int event_loop_once(struct event_context *ev) } tvalp = NULL; - t = timeval_current(); /* work out the right timeout for all timed events */ - for (te=ev->timed_events;te;te=te_next) { - struct timeval tv; - te_next = te->next; - if (timeval_is_zero(&te->next_event)) { - talloc_free(te); - continue; - } - tv = timeval_diff(&te->next_event, &t); - if (tvalp == NULL) { - tval = tv; - } else { - tval = timeval_min(&tv, &tval); - } + if (ev->timed_events) { + struct timeval t = timeval_current(); + tval = timeval_diff(&ev->timed_events->next_event, &t); tvalp = &tval; } - /* only do a select() if there're fd_events - * otherwise we would block for a the time in tval, - * and if there're no fd_events present anymore we want to - * leave the event loop directly - */ - if (ev->fd_events) { - /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(ev); - } + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } - /* TODO: - * we don't use sys_select() as it isn't thread - * safe. We need to replace the magic pipe handling in - * sys_select() with something in the events - * structure - for now just use select() - */ - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); - t = timeval_current(); + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("ERROR: EBADF on event_loop_once\n")); + ev->exit_code = EBADF; + return -1; + } - if (selrtn == -1 && errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - DEBUG(0,("EBADF on event_loop_once - exiting\n")); - ev->exit_code = EBADF; - return -1; + if (selrtn == 0) { + struct timeval t = timeval_current(); + struct timed_event *te = ev->timed_events; + + te->next_event = timeval_zero(); + + te->handler(ev, te, t, te->private); + + /* note the care taken to prevent referencing a event + that could have been freed by the handler */ + if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { + talloc_free(ev->timed_events); } - - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { - uint16_t flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (flags) { - fe->handler(ev, fe, t, flags, fe->private); - if (destruction_count != ev->destruction_count) { - break; - } + } + + if (selrtn > 0) { + struct timeval t = timeval_current(); + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16_t flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (flags) { + fe->handler(ev, fe, t, flags, fe->private); + if (destruction_count != ev->destruction_count) { + break; } } } } - /* call any timed events that are now due */ - for (te=ev->timed_events;te;) { - struct timed_event *next = te->next; - if (timeval_compare(&te->next_event, &t) >= 0) { - te->next_event = timeval_zero(); - te->handler(ev, te, t, te->private); - if (destruction_count != ev->destruction_count) { - break; - } - } - te = next; - } - return 0; } -- cgit From df9d1a3709bdfe793ae124b0303fccc0b558f180 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 04:03:28 +0000 Subject: r5189: fixed a double free bug in the ltdb indexing code (This used to be commit 7be0bc93bd6757e52fd10bd3d3b3d1a8f5221452) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index af325f9203..c7dc9f1345 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -209,7 +209,6 @@ static int ltdb_index_dn_simple(struct ldb_module *module, list->dn[list->count] = talloc_strdup(list->dn, (char *)el->values[j].data); if (!list->dn[list->count]) { - talloc_free(list); return -1; } list->count++; @@ -309,7 +308,6 @@ static int list_intersect(struct ldb_context *ldb, if (list->count == 0 || list2->count == 0) { /* 0 & X == 0 */ - talloc_free(list); return 0; } @@ -320,7 +318,6 @@ static int list_intersect(struct ldb_context *ldb, list3->dn = talloc_array(list3, char *, list->count); if (!list3->dn) { - talloc_free(list); talloc_free(list3); return -1; } @@ -359,13 +356,11 @@ static int list_union(struct ldb_context *ldb, if (list->count == 0 && list2->count == 0) { /* 0 | 0 == 0 */ - talloc_free(list); return 0; } d = talloc_realloc(list, list->dn, char *, list->count + list2->count); if (!d) { - talloc_free(list); return -1; } list->dn = d; @@ -375,7 +370,6 @@ static int list_union(struct ldb_context *ldb, sizeof(char *), (comparison_fn_t)strcmp) == -1) { list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]); if (!list->dn[list->count]) { - talloc_free(list); return -1; } list->count++; @@ -453,7 +447,6 @@ static int ltdb_index_dn_or(struct ldb_module *module, } if (list->count == 0) { - talloc_free(list); return 0; } -- cgit From 6e0a56f73b7f75e45d97a574cf6fd1fc4f4bff9b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 08:24:08 +0000 Subject: r5194: added support for using epoll instead of select() on systems that have it. epoll is much more scalable than select(), but only exists on some systems (such as Linux with the 2.6.x kernel). The code detects any epoll system call failures at runtime and falls back to select() if there is a problem, so it should be safe to compile this on a 2.6 kernel and run it on a 2.4.x kernel. The speedup is quite large. It gains 20% in packet rate in the BENCH-NBT test, on top of another 20% gain from the better timer handling I added earlier. The really big gain will be when we are dealing with large numbers of file descriptors. With epoll we can handle hundreds of file descriptors all O(1), whereas with select it is O(n). (This used to be commit 26aa1aa69377e43da2942a42d137b95801e9fa1a) --- source4/lib/events.c | 268 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 220 insertions(+), 48 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index 10d15d8111..a478fc8a41 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -38,8 +38,8 @@ 2) a timed event. You can register an event that happens at a specific time. You can register as many of these as you - like. When they are called the handler can choose to set the time - for the next event. If next_event is not set then the event is removed. + like. They are single shot - add a new timed event in the event + handler to get another event. To setup a set of events you first need to create a event_context structure using the function event_context_init(); This returns a @@ -60,11 +60,14 @@ #include "dlinklist.h" #include "events.h" +/* use epoll if it is available */ +#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) +#define WITH_EPOLL 1 +#endif -/* - please read the comments in events.c before modifying -*/ - +#if WITH_EPOLL +#include +#endif struct event_context { /* list of filedescriptor events */ @@ -92,14 +95,21 @@ struct event_context { /* information for exiting from the event loop */ int exit_code; - /* this is changed by the destructors for any event type. It - is used to detect event destruction by event handlers, - which means the code that is calling all event handles - needs to assume that the linked list is no longer valid + /* this is changed by the destructors for the fd event + type. It is used to detect event destruction by event + handlers, which means the code that is calling the event + handler needs to assume that the linked list is no longer + valid */ uint32_t destruction_count; + +#if WITH_EPOLL + /* when using epoll this is the handle from epoll_create */ + int epoll_fd; +#endif }; + /* create a event_context structure. This must be the first events call, and all subsequent calls pass this event_context as the first @@ -112,9 +122,14 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) ev = talloc_zero(mem_ctx, struct event_context); if (!ev) return NULL; +#if WITH_EPOLL + ev->epoll_fd = epoll_create(64); +#endif + return ev; } + /* recalculate the maxfd */ @@ -129,20 +144,64 @@ static void calc_maxfd(struct event_context *ev) } } + /* to mark the ev->maxfd invalid * this means we need to recalculate it */ #define EVENT_INVALID_MAXFD (-1) +#if WITH_EPOLL +/* + called when a epoll call fails, and we should fallback + to using select +*/ +static void epoll_fallback_to_select(struct event_context *ev, const char *reason) +{ + DEBUG(0,("%s - using select() - %s\n", reason, strerror(errno))); + close(ev->epoll_fd); + ev->epoll_fd = -1; +} +#endif + + +#if WITH_EPOLL +/* + map from EVENT_FD_* to EPOLLIN/EPOLLOUT +*/ +static uint32_t epoll_map_flags(uint16_t flags) +{ + uint32_t ret = 0; + if (flags & EVENT_FD_READ) ret |= EPOLLIN; + if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT; + return ret; +} +#endif + +/* + destroy an fd_event +*/ static int event_fd_destructor(void *ptr) { struct fd_event *fde = talloc_get_type(ptr, struct fd_event); - if (fde->event_ctx->maxfd == fde->fd) { - fde->event_ctx->maxfd = EVENT_INVALID_MAXFD; + struct event_context *ev = fde->event_ctx; + + if (ev->maxfd == fde->fd) { + ev->maxfd = EVENT_INVALID_MAXFD; } - DLIST_REMOVE(fde->event_ctx->fd_events, fde); - fde->event_ctx->destruction_count++; + DLIST_REMOVE(ev->fd_events, fde); + ev->destruction_count++; +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(fde->flags); + event.data.ptr = fde; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_DEL failed"); + } + } +#endif return 0; } @@ -173,6 +232,19 @@ struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, if (mem_ctx) { talloc_steal(mem_ctx, e); } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = e; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); + } + } +#endif + return e; } @@ -182,7 +254,7 @@ struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, */ uint16_t event_fd_flags(struct fd_event *fde) { - return fde->flags; + return fde?fde->flags:0; } /* @@ -190,7 +262,23 @@ uint16_t event_fd_flags(struct fd_event *fde) */ void event_fd_setflags(struct fd_event *fde, uint16_t flags) { - fde->flags = flags; +#if WITH_EPOLL + struct event_context *ev; + if (fde == NULL) return; + ev = fde->event_ctx; + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = fde; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); + } + } +#endif + if (fde) { + fde->flags = flags; + } } /* @@ -242,16 +330,93 @@ struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ct } /* - do a single event loop using the events defined in ev this function + a timer has gone off - call it */ -int event_loop_once(struct event_context *ev) +static void event_loop_timer(struct event_context *ev) +{ + struct timeval t = timeval_current(); + struct timed_event *te = ev->timed_events; + + te->next_event = timeval_zero(); + + te->handler(ev, te, t, te->private); + + /* note the care taken to prevent referencing a event + that could have been freed by the handler */ + if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { + talloc_free(ev->timed_events); + } +} + +#if WITH_EPOLL +/* + event loop handling using epoll +*/ +static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) +{ + int ret, i; + const int maxevents = 8; + struct epoll_event events[maxevents]; + uint32_t destruction_count = ev->destruction_count; + int timeout = -1; + struct timeval t; + + if (tvalp) { + timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); + } + + ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); + + if (ret == -1) { + epoll_fallback_to_select(ev, "epoll_wait() failed"); + return -1; + } + + if (ret == 0 && tvalp) { + event_loop_timer(ev); + return 0; + } + + t = timeval_current(); + + for (i=0;ihandler(ev, fde, t, flags, fde->private); + if (destruction_count != ev->destruction_count) { + break; + } + } + } + + return 0; +} +#endif + +/* + event loop handling using select() +*/ +static int event_loop_select(struct event_context *ev, struct timeval *tvalp) { fd_set r_fds, w_fds; - struct fd_event *fe; int selrtn; - struct timeval tval, *tvalp; uint32_t destruction_count = ev->destruction_count; + struct fd_event *fe; + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } + FD_ZERO(&r_fds); FD_ZERO(&w_fds); @@ -267,20 +432,6 @@ int event_loop_once(struct event_context *ev) fe = next; } - tvalp = NULL; - - /* work out the right timeout for all timed events */ - if (ev->timed_events) { - struct timeval t = timeval_current(); - tval = timeval_diff(&ev->timed_events->next_event, &t); - tvalp = &tval; - } - - /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(ev); - } - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); if (selrtn == -1 && errno == EBADF) { @@ -293,22 +444,12 @@ int event_loop_once(struct event_context *ev) ev->exit_code = EBADF; return -1; } - - if (selrtn == 0) { - struct timeval t = timeval_current(); - struct timed_event *te = ev->timed_events; - - te->next_event = timeval_zero(); - te->handler(ev, te, t, te->private); - - /* note the care taken to prevent referencing a event - that could have been freed by the handler */ - if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { - talloc_free(ev->timed_events); - } + if (selrtn == 0 && tvalp) { + event_loop_timer(ev); + return 0; } - + if (selrtn > 0) { struct timeval t = timeval_current(); /* at least one file descriptor is ready - check @@ -328,6 +469,37 @@ int event_loop_once(struct event_context *ev) } return 0; +} + +/* + do a single event loop using the events defined in ev this function +*/ +int event_loop_once(struct event_context *ev) +{ + struct timeval tval, *tvalp; + + tvalp = NULL; + + /* work out the right timeout for all timed events */ + if (ev->timed_events) { + struct timeval t = timeval_current(); + tval = timeval_diff(&ev->timed_events->next_event, &t); + tvalp = &tval; + if (timeval_is_zero(tvalp)) { + event_loop_timer(ev); + return 0; + } + } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + if (event_loop_epoll(ev, tvalp) == 0) { + return 0; + } + } +#endif + + return event_loop_select(ev, tvalp); } /* -- cgit From 0798d54b4fc28be881e2c4012663b1461bc85ba7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 11:25:52 +0000 Subject: r5195: most events don't need the time of the event, so save a gettimeofday() call and just use timeval_current() when its actually needed (This used to be commit 236403cc4dc2924ed6a898acae0bb44cc1688dcc) --- source4/lib/events.c | 12 ++++-------- source4/lib/messaging/messaging.c | 6 +++--- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events.c b/source4/lib/events.c index a478fc8a41..4907a60f01 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -359,7 +359,6 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) struct epoll_event events[maxevents]; uint32_t destruction_count = ev->destruction_count; int timeout = -1; - struct timeval t; if (tvalp) { timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); @@ -367,7 +366,7 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); - if (ret == -1) { + if (ret == -1 && errno != EINTR) { epoll_fallback_to_select(ev, "epoll_wait() failed"); return -1; } @@ -377,8 +376,6 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) return 0; } - t = timeval_current(); - for (i=0;ihandler(ev, fde, t, flags, fde->private); + fde->handler(ev, fde, flags, fde->private); if (destruction_count != ev->destruction_count) { break; } @@ -451,7 +448,6 @@ static int event_loop_select(struct event_context *ev, struct timeval *tvalp) } if (selrtn > 0) { - struct timeval t = timeval_current(); /* at least one file descriptor is ready - check which ones and call the handler, being careful to allow the handler to remove itself when called */ @@ -460,7 +456,7 @@ static int event_loop_select(struct event_context *ev, struct timeval *tvalp) if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (flags) { - fe->handler(ev, fe, t, flags, fe->private); + fe->handler(ev, fe, flags, fe->private); if (destruction_count != ev->destruction_count) { break; } @@ -472,7 +468,7 @@ static int event_loop_select(struct event_context *ev, struct timeval *tvalp) } /* - do a single event loop using the events defined in ev this function + do a single event loop using the events defined in ev */ int event_loop_once(struct event_context *ev) { diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 53b6f434f0..24205e5151 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -122,7 +122,7 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r handle IO for a single message */ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags, void *private) + uint16_t flags, void *private) { struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); struct messaging_context *msg = rec->msg; @@ -192,7 +192,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd handle a new incoming connection */ static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags, void *private) + uint16_t flags, void *private) { struct messaging_context *msg = talloc_get_type(private, struct messaging_context); @@ -257,7 +257,7 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void handle IO for sending a message */ static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags, void *private) + uint16_t flags, void *private) { struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); NTSTATUS status; -- cgit From 131dc76d56df40b3511c47e54f15412a25b491f8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 11:56:03 +0000 Subject: r5197: moved events code to lib/events/ (suggestion from metze) (This used to be commit 7f54c8a339f36aa43c9340be70ab7f0067593ef2) --- source4/lib/basic.mk | 9 - source4/lib/events.c | 520 -------------------------------------- source4/lib/events/config.m4 | 2 + source4/lib/events/config.mk | 8 + source4/lib/events/events.c | 520 ++++++++++++++++++++++++++++++++++++++ source4/lib/events/events.h | 63 +++++ source4/lib/messaging/messaging.c | 2 +- 7 files changed, 594 insertions(+), 530 deletions(-) delete mode 100644 source4/lib/events.c create mode 100644 source4/lib/events/config.m4 create mode 100644 source4/lib/events/config.mk create mode 100644 source4/lib/events/events.c create mode 100644 source4/lib/events/events.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index dda79f50ad..5f9a60e114 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -32,15 +32,6 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBCRYPTO ############################## -############################## -# Start SUBSYSTEM LIBEVENTS -[SUBSYSTEM::LIBEVENTS] -NOPROTO = YES -INIT_OBJ_FILES = lib/events.o -REQUIRED_SUBSYSTEMS = LIBTALLOC -# End SUBSYSTEM LIBEVENTS -############################## - ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] diff --git a/source4/lib/events.c b/source4/lib/events.c deleted file mode 100644 index 4907a60f01..0000000000 --- a/source4/lib/events.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - Unix SMB/CIFS implementation. - main select loop and event handling - Copyright (C) Andrew Tridgell 2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - PLEASE READ THIS BEFORE MODIFYING! - - This module is a general abstraction for the main select loop and - event handling. Do not ever put any localised hacks in here, instead - register one of the possible event types and implement that event - somewhere else. - - There are 2 types of event handling that are handled in this module: - - 1) a file descriptor becoming readable or writeable. This is mostly - used for network sockets, but can be used for any type of file - descriptor. You may only register one handler for each file - descriptor/io combination or you will get unpredictable results - (this means that you can have a handler for read events, and a - separate handler for write events, but not two handlers that are - both handling read events) - - 2) a timed event. You can register an event that happens at a - specific time. You can register as many of these as you - like. They are single shot - add a new timed event in the event - handler to get another event. - - To setup a set of events you first need to create a event_context - structure using the function event_context_init(); This returns a - 'struct event_context' that you use in all subsequent calls. - - After that you can add/remove events that you are interested in - using event_add_*() and talloc_free() - - Finally, you call event_loop_wait() to block waiting for one of the - events to occor. In normal operation event_loop_wait() will loop - forever. - -*/ - -#include "includes.h" -#include "system/time.h" -#include "system/select.h" -#include "dlinklist.h" -#include "events.h" - -/* use epoll if it is available */ -#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) -#define WITH_EPOLL 1 -#endif - -#if WITH_EPOLL -#include -#endif - -struct event_context { - /* list of filedescriptor events */ - struct fd_event { - struct event_context *event_ctx; - struct fd_event *next, *prev; - int fd; - uint16_t flags; /* see EVENT_FD_* flags */ - event_fd_handler_t handler; - void *private; - } *fd_events; - - /* list of timed events */ - struct timed_event { - struct event_context *event_ctx; - struct timed_event *next, *prev; - struct timeval next_event; - event_timed_handler_t handler; - void *private; - } *timed_events; - - /* the maximum file descriptor number in fd_events */ - int maxfd; - - /* information for exiting from the event loop */ - int exit_code; - - /* this is changed by the destructors for the fd event - type. It is used to detect event destruction by event - handlers, which means the code that is calling the event - handler needs to assume that the linked list is no longer - valid - */ - uint32_t destruction_count; - -#if WITH_EPOLL - /* when using epoll this is the handle from epoll_create */ - int epoll_fd; -#endif -}; - - -/* - create a event_context structure. This must be the first events - call, and all subsequent calls pass this event_context as the first - element. Event handlers also receive this as their first argument. -*/ -struct event_context *event_context_init(TALLOC_CTX *mem_ctx) -{ - struct event_context *ev; - - ev = talloc_zero(mem_ctx, struct event_context); - if (!ev) return NULL; - -#if WITH_EPOLL - ev->epoll_fd = epoll_create(64); -#endif - - return ev; -} - - -/* - recalculate the maxfd -*/ -static void calc_maxfd(struct event_context *ev) -{ - struct fd_event *e; - ev->maxfd = 0; - for (e=ev->fd_events; e; e=e->next) { - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; - } - } -} - - -/* to mark the ev->maxfd invalid - * this means we need to recalculate it - */ -#define EVENT_INVALID_MAXFD (-1) - - -#if WITH_EPOLL -/* - called when a epoll call fails, and we should fallback - to using select -*/ -static void epoll_fallback_to_select(struct event_context *ev, const char *reason) -{ - DEBUG(0,("%s - using select() - %s\n", reason, strerror(errno))); - close(ev->epoll_fd); - ev->epoll_fd = -1; -} -#endif - - -#if WITH_EPOLL -/* - map from EVENT_FD_* to EPOLLIN/EPOLLOUT -*/ -static uint32_t epoll_map_flags(uint16_t flags) -{ - uint32_t ret = 0; - if (flags & EVENT_FD_READ) ret |= EPOLLIN; - if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT; - return ret; -} -#endif - -/* - destroy an fd_event -*/ -static int event_fd_destructor(void *ptr) -{ - struct fd_event *fde = talloc_get_type(ptr, struct fd_event); - struct event_context *ev = fde->event_ctx; - - if (ev->maxfd == fde->fd) { - ev->maxfd = EVENT_INVALID_MAXFD; - } - DLIST_REMOVE(ev->fd_events, fde); - ev->destruction_count++; -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(fde->flags); - event.data.ptr = fde; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_DEL failed"); - } - } -#endif - return 0; -} - -/* - add a fd based event - return NULL on failure (memory allocation error) -*/ -struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, event_fd_handler_t handler, - void *private) -{ - struct fd_event *e = talloc(ev, struct fd_event); - if (!e) return NULL; - - e->event_ctx = ev; - e->fd = fd; - e->flags = flags; - e->handler = handler; - e->private = private; - - DLIST_ADD(ev->fd_events, e); - - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; - } - - talloc_set_destructor(e, event_fd_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); - } - -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(flags); - event.data.ptr = e; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); - } - } -#endif - - return e; -} - - -/* - return the fd event flags -*/ -uint16_t event_fd_flags(struct fd_event *fde) -{ - return fde?fde->flags:0; -} - -/* - set the fd event flags -*/ -void event_fd_setflags(struct fd_event *fde, uint16_t flags) -{ -#if WITH_EPOLL - struct event_context *ev; - if (fde == NULL) return; - ev = fde->event_ctx; - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(flags); - event.data.ptr = fde; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); - } - } -#endif - if (fde) { - fde->flags = flags; - } -} - -/* - destroy a timed event -*/ -static int event_timed_destructor(void *ptr) -{ - struct timed_event *te = talloc_get_type(ptr, struct timed_event); - DLIST_REMOVE(te->event_ctx->timed_events, te); - return 0; -} - -/* - add a timed event - return NULL on failure (memory allocation error) -*/ -struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, - struct timeval next_event, - event_timed_handler_t handler, - void *private) -{ - struct timed_event *te, *e; - - e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); - if (e == NULL) return NULL; - - e->event_ctx = ev; - e->next_event = next_event; - e->handler = handler; - e->private = private; - - /* keep the list ordered */ - if (ev->timed_events == NULL || - timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { - DLIST_ADD(ev->timed_events, e); - } else { - for (te=ev->timed_events;te && te->next;te=te->next) { - if (!timeval_is_zero(&te->next_event) && - timeval_compare(&te->next_event, &e->next_event) < 0) { - break; - } - } - DLIST_ADD_AFTER(ev->timed_events, e, te); - } - - talloc_set_destructor(e, event_timed_destructor); - - return e; -} - -/* - a timer has gone off - call it -*/ -static void event_loop_timer(struct event_context *ev) -{ - struct timeval t = timeval_current(); - struct timed_event *te = ev->timed_events; - - te->next_event = timeval_zero(); - - te->handler(ev, te, t, te->private); - - /* note the care taken to prevent referencing a event - that could have been freed by the handler */ - if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { - talloc_free(ev->timed_events); - } -} - -#if WITH_EPOLL -/* - event loop handling using epoll -*/ -static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) -{ - int ret, i; - const int maxevents = 8; - struct epoll_event events[maxevents]; - uint32_t destruction_count = ev->destruction_count; - int timeout = -1; - - if (tvalp) { - timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); - } - - ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); - - if (ret == -1 && errno != EINTR) { - epoll_fallback_to_select(ev, "epoll_wait() failed"); - return -1; - } - - if (ret == 0 && tvalp) { - event_loop_timer(ev); - return 0; - } - - for (i=0;ihandler(ev, fde, flags, fde->private); - if (destruction_count != ev->destruction_count) { - break; - } - } - } - - return 0; -} -#endif - -/* - event loop handling using select() -*/ -static int event_loop_select(struct event_context *ev, struct timeval *tvalp) -{ - fd_set r_fds, w_fds; - int selrtn; - uint32_t destruction_count = ev->destruction_count; - struct fd_event *fe; - - /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(ev); - } - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - - /* setup any fd events */ - for (fe=ev->fd_events; fe; ) { - struct fd_event *next = fe->next; - if (fe->flags & EVENT_FD_READ) { - FD_SET(fe->fd, &r_fds); - } - if (fe->flags & EVENT_FD_WRITE) { - FD_SET(fe->fd, &w_fds); - } - fe = next; - } - - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); - - if (selrtn == -1 && errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - DEBUG(0,("ERROR: EBADF on event_loop_once\n")); - ev->exit_code = EBADF; - return -1; - } - - if (selrtn == 0 && tvalp) { - event_loop_timer(ev); - return 0; - } - - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { - uint16_t flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (flags) { - fe->handler(ev, fe, flags, fe->private); - if (destruction_count != ev->destruction_count) { - break; - } - } - } - } - - return 0; -} - -/* - do a single event loop using the events defined in ev -*/ -int event_loop_once(struct event_context *ev) -{ - struct timeval tval, *tvalp; - - tvalp = NULL; - - /* work out the right timeout for all timed events */ - if (ev->timed_events) { - struct timeval t = timeval_current(); - tval = timeval_diff(&ev->timed_events->next_event, &t); - tvalp = &tval; - if (timeval_is_zero(tvalp)) { - event_loop_timer(ev); - return 0; - } - } - -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - if (event_loop_epoll(ev, tvalp) == 0) { - return 0; - } - } -#endif - - return event_loop_select(ev, tvalp); -} - -/* - go into an event loop using the events defined in ev this function - will return with the specified code if one of the handlers calls - event_loop_exit() - - also return (with code 0) if all fd events are removed -*/ -int event_loop_wait(struct event_context *ev) -{ - ev->exit_code = 0; - ev->maxfd = EVENT_INVALID_MAXFD; - - while (ev->fd_events && ev->exit_code == 0) { - if (event_loop_once(ev) != 0) { - break; - } - } - - return ev->exit_code; -} diff --git a/source4/lib/events/config.m4 b/source4/lib/events/config.m4 new file mode 100644 index 0000000000..6e4095d5b8 --- /dev/null +++ b/source4/lib/events/config.m4 @@ -0,0 +1,2 @@ +AC_CHECK_HEADERS(sys/epoll.h) +AC_CHECK_FUNCS(epoll_create) diff --git a/source4/lib/events/config.mk b/source4/lib/events/config.mk new file mode 100644 index 0000000000..c6f66b1c51 --- /dev/null +++ b/source4/lib/events/config.mk @@ -0,0 +1,8 @@ +############################## +# Start SUBSYSTEM LIBEVENTS +[SUBSYSTEM::LIBEVENTS] +NOPROTO = YES +INIT_OBJ_FILES = lib/events/events.o +REQUIRED_SUBSYSTEMS = LIBTALLOC +# End SUBSYSTEM LIBEVENTS +############################## diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c new file mode 100644 index 0000000000..a852df68eb --- /dev/null +++ b/source4/lib/events/events.c @@ -0,0 +1,520 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 2 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. They are single shot - add a new timed event in the event + handler to get another event. + + To setup a set of events you first need to create a event_context + structure using the function event_context_init(); This returns a + 'struct event_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using event_add_*() and talloc_free() + + Finally, you call event_loop_wait() to block waiting for one of the + events to occor. In normal operation event_loop_wait() will loop + forever. + +*/ + +#include "includes.h" +#include "system/time.h" +#include "system/select.h" +#include "dlinklist.h" +#include "lib/events/events.h" + +/* use epoll if it is available */ +#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) +#define WITH_EPOLL 1 +#endif + +#if WITH_EPOLL +#include +#endif + +struct event_context { + /* list of filedescriptor events */ + struct fd_event { + struct event_context *event_ctx; + struct fd_event *next, *prev; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + void *private; + } *fd_events; + + /* list of timed events */ + struct timed_event { + struct event_context *event_ctx; + struct timed_event *next, *prev; + struct timeval next_event; + event_timed_handler_t handler; + void *private; + } *timed_events; + + /* the maximum file descriptor number in fd_events */ + int maxfd; + + /* information for exiting from the event loop */ + int exit_code; + + /* this is changed by the destructors for the fd event + type. It is used to detect event destruction by event + handlers, which means the code that is calling the event + handler needs to assume that the linked list is no longer + valid + */ + uint32_t destruction_count; + +#if WITH_EPOLL + /* when using epoll this is the handle from epoll_create */ + int epoll_fd; +#endif +}; + + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct event_context *event_context_init(TALLOC_CTX *mem_ctx) +{ + struct event_context *ev; + + ev = talloc_zero(mem_ctx, struct event_context); + if (!ev) return NULL; + +#if WITH_EPOLL + ev->epoll_fd = epoll_create(64); +#endif + + return ev; +} + + +/* + recalculate the maxfd +*/ +static void calc_maxfd(struct event_context *ev) +{ + struct fd_event *e; + ev->maxfd = 0; + for (e=ev->fd_events; e; e=e->next) { + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + } +} + + +/* to mark the ev->maxfd invalid + * this means we need to recalculate it + */ +#define EVENT_INVALID_MAXFD (-1) + + +#if WITH_EPOLL +/* + called when a epoll call fails, and we should fallback + to using select +*/ +static void epoll_fallback_to_select(struct event_context *ev, const char *reason) +{ + DEBUG(0,("%s - using select() - %s\n", reason, strerror(errno))); + close(ev->epoll_fd); + ev->epoll_fd = -1; +} +#endif + + +#if WITH_EPOLL +/* + map from EVENT_FD_* to EPOLLIN/EPOLLOUT +*/ +static uint32_t epoll_map_flags(uint16_t flags) +{ + uint32_t ret = 0; + if (flags & EVENT_FD_READ) ret |= EPOLLIN; + if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT; + return ret; +} +#endif + +/* + destroy an fd_event +*/ +static int event_fd_destructor(void *ptr) +{ + struct fd_event *fde = talloc_get_type(ptr, struct fd_event); + struct event_context *ev = fde->event_ctx; + + if (ev->maxfd == fde->fd) { + ev->maxfd = EVENT_INVALID_MAXFD; + } + DLIST_REMOVE(ev->fd_events, fde); + ev->destruction_count++; +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(fde->flags); + event.data.ptr = fde; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_DEL failed"); + } + } +#endif + return 0; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private) +{ + struct fd_event *e = talloc(ev, struct fd_event); + if (!e) return NULL; + + e->event_ctx = ev; + e->fd = fd; + e->flags = flags; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->fd_events, e); + + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + + talloc_set_destructor(e, event_fd_destructor); + if (mem_ctx) { + talloc_steal(mem_ctx, e); + } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = e; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); + } + } +#endif + + return e; +} + + +/* + return the fd event flags +*/ +uint16_t event_fd_flags(struct fd_event *fde) +{ + return fde?fde->flags:0; +} + +/* + set the fd event flags +*/ +void event_fd_setflags(struct fd_event *fde, uint16_t flags) +{ +#if WITH_EPOLL + struct event_context *ev; + if (fde == NULL) return; + ev = fde->event_ctx; + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = fde; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); + } + } +#endif + if (fde) { + fde->flags = flags; + } +} + +/* + destroy a timed event +*/ +static int event_timed_destructor(void *ptr) +{ + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + DLIST_REMOVE(te->event_ctx->timed_events, te); + return 0; +} + +/* + add a timed event + return NULL on failure (memory allocation error) +*/ +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private) +{ + struct timed_event *te, *e; + + e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); + if (e == NULL) return NULL; + + e->event_ctx = ev; + e->next_event = next_event; + e->handler = handler; + e->private = private; + + /* keep the list ordered */ + if (ev->timed_events == NULL || + timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { + DLIST_ADD(ev->timed_events, e); + } else { + for (te=ev->timed_events;te && te->next;te=te->next) { + if (!timeval_is_zero(&te->next_event) && + timeval_compare(&te->next_event, &e->next_event) < 0) { + break; + } + } + DLIST_ADD_AFTER(ev->timed_events, e, te); + } + + talloc_set_destructor(e, event_timed_destructor); + + return e; +} + +/* + a timer has gone off - call it +*/ +static void event_loop_timer(struct event_context *ev) +{ + struct timeval t = timeval_current(); + struct timed_event *te = ev->timed_events; + + te->next_event = timeval_zero(); + + te->handler(ev, te, t, te->private); + + /* note the care taken to prevent referencing a event + that could have been freed by the handler */ + if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { + talloc_free(ev->timed_events); + } +} + +#if WITH_EPOLL +/* + event loop handling using epoll +*/ +static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) +{ + int ret, i; + const int maxevents = 8; + struct epoll_event events[maxevents]; + uint32_t destruction_count = ev->destruction_count; + int timeout = -1; + + if (tvalp) { + timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); + } + + ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); + + if (ret == -1 && errno != EINTR) { + epoll_fallback_to_select(ev, "epoll_wait() failed"); + return -1; + } + + if (ret == 0 && tvalp) { + event_loop_timer(ev); + return 0; + } + + for (i=0;ihandler(ev, fde, flags, fde->private); + if (destruction_count != ev->destruction_count) { + break; + } + } + } + + return 0; +} +#endif + +/* + event loop handling using select() +*/ +static int event_loop_select(struct event_context *ev, struct timeval *tvalp) +{ + fd_set r_fds, w_fds; + int selrtn; + uint32_t destruction_count = ev->destruction_count; + struct fd_event *fe; + + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } + + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); + + /* setup any fd events */ + for (fe=ev->fd_events; fe; ) { + struct fd_event *next = fe->next; + if (fe->flags & EVENT_FD_READ) { + FD_SET(fe->fd, &r_fds); + } + if (fe->flags & EVENT_FD_WRITE) { + FD_SET(fe->fd, &w_fds); + } + fe = next; + } + + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("ERROR: EBADF on event_loop_once\n")); + ev->exit_code = EBADF; + return -1; + } + + if (selrtn == 0 && tvalp) { + event_loop_timer(ev); + return 0; + } + + if (selrtn > 0) { + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16_t flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (flags) { + fe->handler(ev, fe, flags, fe->private); + if (destruction_count != ev->destruction_count) { + break; + } + } + } + } + + return 0; +} + +/* + do a single event loop using the events defined in ev +*/ +int event_loop_once(struct event_context *ev) +{ + struct timeval tval, *tvalp; + + tvalp = NULL; + + /* work out the right timeout for all timed events */ + if (ev->timed_events) { + struct timeval t = timeval_current(); + tval = timeval_diff(&ev->timed_events->next_event, &t); + tvalp = &tval; + if (timeval_is_zero(tvalp)) { + event_loop_timer(ev); + return 0; + } + } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + if (event_loop_epoll(ev, tvalp) == 0) { + return 0; + } + } +#endif + + return event_loop_select(ev, tvalp); +} + +/* + go into an event loop using the events defined in ev this function + will return with the specified code if one of the handlers calls + event_loop_exit() + + also return (with code 0) if all fd events are removed +*/ +int event_loop_wait(struct event_context *ev) +{ + ev->exit_code = 0; + ev->maxfd = EVENT_INVALID_MAXFD; + + while (ev->fd_events && ev->exit_code == 0) { + if (event_loop_once(ev) != 0) { + break; + } + } + + return ev->exit_code; +} diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h new file mode 100644 index 0000000000..e3973c3c48 --- /dev/null +++ b/source4/lib/events/events.h @@ -0,0 +1,63 @@ +/* + Unix SMB/CIFS implementation. + + generalised event loop handling + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct event_context; +struct fd_event; +struct timed_event; + +/* event handler types */ +typedef void (*event_fd_handler_t)(struct event_context *, struct fd_event *, + uint16_t , void *); +typedef void (*event_timed_handler_t)(struct event_context *, struct timed_event *, + struct timeval , void *); + +struct event_context *event_context_init(TALLOC_CTX *mem_ctx); + +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private); + +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private); + +int event_loop_once(struct event_context *ev); +int event_loop_wait(struct event_context *ev); + +uint16_t event_fd_flags(struct fd_event *fde); +void event_fd_setflags(struct fd_event *fde, uint16_t flags); + +/* bits for file descriptor event flags */ +#define EVENT_FD_READ 1 +#define EVENT_FD_WRITE 2 + +#define EVENT_FD_WRITEABLE(fde) \ + event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_WRITE) +#define EVENT_FD_READABLE(fde) \ + event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_READ) + +#define EVENT_FD_NOT_WRITEABLE(fde) \ + event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE) +#define EVENT_FD_NOT_READABLE(fde) \ + event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE) + diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 24205e5151..aab13ba8af 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -21,7 +21,7 @@ */ #include "includes.h" -#include "events.h" +#include "lib/events/events.h" #include "system/time.h" #include "messages.h" #include "dlinklist.h" -- cgit From e6b8c811cac0730c16e685d04ee41fce036fd51c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 3 Feb 2005 12:26:28 +0000 Subject: r5198: don't consider failure to remove an epoll event as enough reason to fallback to select(). This can happen in too many situations. (This used to be commit 2d7242f2ec945c1e5fbc6f256265471f60ac8cd9) --- source4/lib/events/events.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index a852df68eb..3a15172d95 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -158,7 +158,7 @@ static void calc_maxfd(struct event_context *ev) */ static void epoll_fallback_to_select(struct event_context *ev, const char *reason) { - DEBUG(0,("%s - using select() - %s\n", reason, strerror(errno))); + DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno))); close(ev->epoll_fd); ev->epoll_fd = -1; } @@ -197,9 +197,7 @@ static int event_fd_destructor(void *ptr) ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_DEL failed"); - } + epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); } #endif return 0; -- cgit From 10c211f2afc45e7a75f024c946a5c8232d7efd6b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 3 Feb 2005 13:00:16 +0000 Subject: r5199: fix some minor configure bugs metze (This used to be commit 274ef2a206aa00b3155adc27f5b7e35d3fa52bf6) --- source4/lib/cmdline/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index a242e2c5e5..e2121d1f14 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -72,7 +72,7 @@ AC_CHECK_LIB(readline, rl_completion_matches, TMP_LIBCMDLINE_OBJS="lib/cmdline/readline.o lib/cmdline/popt_common.o" TMP_LIBCMDLINE_LIBS="$TERMLIBS" -SMB_EXT_LIB(READLINE, [$TERMLIBS]) +SMB_EXT_LIB(READLINE, [${TMP_LIBCMDLINE_LIBS}]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], -- cgit From 567b7a90f6c968bbe09115bb38da9c781c669a50 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 4 Feb 2005 02:35:13 +0000 Subject: r5217: avoid epoll_ctl() if the event flags are already set correctly (This used to be commit d89b493aaf690ceb107bd62df75f1bba82284f90) --- source4/lib/events/events.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 3a15172d95..23026166a2 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -262,7 +262,10 @@ void event_fd_setflags(struct fd_event *fde, uint16_t flags) { #if WITH_EPOLL struct event_context *ev; - if (fde == NULL) return; + if (fde == NULL || + fde->flags == flags) { + return; + } ev = fde->event_ctx; if (ev->epoll_fd != -1) { struct epoll_event event; -- cgit From db4ba6e6909b4cf80b2b18f1a0d34b613de4be25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 4 Feb 2005 04:58:48 +0000 Subject: r5221: replace the str_list_*() code with new code based on talloc(). This is a precursor to adding the wins client code in the nbt server. (This used to be commit e8e499755ab667015740b35a7787134ebe852954) --- source4/lib/util_strlist.c | 190 +++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 111 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index d945c78472..c6ccad907b 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -1,9 +1,7 @@ /* Unix SMB/CIFS implementation. - Copyright (C) Andrew Tridgell 1992-2004 - Copyright (C) Simo Sorce 2001-2002 - Copyright (C) Martin Pool 2003 + Copyright (C) Andrew Tridgell 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 @@ -21,136 +19,106 @@ */ #include "includes.h" -#include "system/network.h" -/** - List of Strings manipulation functions -**/ +/* + build a null terminated list of strings from a input string and a + separator list. The sepatator list must contain characters less than + or equal to 0x2f for this to work correctly on multi-byte strings +*/ +char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + int num_elements = 0; + char **ret = NULL; -#define S_LIST_ABS 16 /* List Allocation Block Size */ + if (sep == NULL) { + sep = LIST_SEP; + } -char **str_list_make(const char *string, const char *sep) -{ - char **list, **rlist; - const char *str; - char *s; - int num, lsize; - pstring tok; - - if (!string || !*string) - return NULL; - s = strdup(string); - if (!s) { - DEBUG(0,("str_list_make: Unable to allocate memory")); + ret = talloc_realloc(mem_ctx, NULL, char *, 1); + if (ret == NULL) { return NULL; } - if (!sep) sep = LIST_SEP; - - num = lsize = 0; - list = NULL; - - str = s; - while (next_token(&str, tok, sep, sizeof(tok))) { - if (num == lsize) { - lsize += S_LIST_ABS; - rlist = realloc_p(list, char *, lsize + 1); - if (!rlist) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - str_list_free(&list); - SAFE_FREE(s); - return NULL; - } else - list = rlist; - memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1))); - } + + while (string && *string) { + size_t len = strcspn(string, sep); + char **ret2; - list[num] = strdup(tok); - if (!list[num]) { - DEBUG(0,("str_list_make: Unable to allocate memory")); - str_list_free(&list); - SAFE_FREE(s); + if (len == 0) { + string += strspn(string, sep); + continue; + } + + ret2 = talloc_realloc(mem_ctx, ret, char *, num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); return NULL; } - - num++; + ret = ret2; + + ret[num_elements] = talloc_strndup(ret, string, len); + if (ret[num_elements] == NULL) { + talloc_free(ret); + return NULL; + } + + num_elements++; + string += len; } - - SAFE_FREE(s); - return list; + + ret[num_elements] = NULL; + + return ret; } -BOOL str_list_copy(char ***dest, const char **src) +/* + return the number of elements in a string list +*/ +size_t str_list_length(const char **list) { - char **list, **rlist; - int num, lsize; - - *dest = NULL; - if (!src) - return False; - - num = lsize = 0; - list = NULL; - - while (src[num]) { - if (num == lsize) { - lsize += S_LIST_ABS; - rlist = realloc_p(list, char *, lsize + 1); - if (!rlist) { - DEBUG(0,("str_list_copy: Unable to re-allocate memory")); - str_list_free(&list); - return False; - } else - list = rlist; - memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1))); - } - - list[num] = strdup(src[num]); - if (!list[num]) { - DEBUG(0,("str_list_copy: Unable to allocate memory")); - str_list_free(&list); - return False; - } + size_t ret; + for (ret=0;list && list[ret];ret++) /* noop */ ; + return ret; +} + - num++; +/* + copy a string list +*/ +char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) +{ + int i; + char **ret = talloc_array(mem_ctx, char *, str_list_length(list)+1); + if (ret == NULL) return NULL; + + for (i=0;list && list[i];i++) { + ret[i] = talloc_strdup(ret, list[i]); + if (ret[i] == NULL) { + talloc_free(ret); + return NULL; + } } - - *dest = list; - return True; + ret[i] = NULL; + return ret; } -/** +/* Return true if all the elements of the list match exactly. - **/ -BOOL str_list_compare(char **list1, char **list2) + */ +BOOL str_list_equal(const char **list1, const char **list2) { - int num; + int i; - if (!list1 || !list2) + if (list1 == NULL || list2 == NULL) { return (list1 == list2); + } - for (num = 0; list1[num]; num++) { - if (!list2[num]) - return False; - if (!strcsequal(list1[num], list2[num])) + for (i=0;list1[i] && list2[i];i++) { + if (strcmp(list1[i], list2[i]) != 0) { return False; + } + } + if (list1[i] || list2[i]) { + return False; } - if (list2[num]) - return False; /* if list2 has more elements than list1 fail */ - return True; } - -void str_list_free(char ***list) -{ - char **tlist; - - if (!list || !*list) - return; - tlist = *list; - for(; *tlist; tlist++) - SAFE_FREE(*tlist); - SAFE_FREE(*list); -} - - - -- cgit From 480ee7243c06aff088c6ad7c2fd122f87c58f42d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 5 Feb 2005 23:10:31 +0000 Subject: r5240: Don't return WERR_OK when no values were found (reported by Matt Cobb) (This used to be commit f2e6d71584672e9bf0eaa7176d76781a30d317d1) --- source4/lib/registry/common/reg_interface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 42bf8f9389..407d0d3345 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -384,10 +384,10 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, } } - if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) - return error; - - return WERR_OK; + if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + return WERR_DEST_NOT_FOUND; + + return error; } WERROR reg_key_del(struct registry_key *parent, const char *name) -- cgit From 579d40052ca988a67f5eb64343948bf1b2c07175 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 8 Feb 2005 01:01:22 +0000 Subject: r5273: fixed another bug in the code that keeps timed events sorted. Hopefully it really works now :-) (This used to be commit 34e1a3ad7849df913584074ec406c2fcc40212fc) --- source4/lib/events/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 23026166a2..cf165c99dc 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -317,8 +317,8 @@ struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ct DLIST_ADD(ev->timed_events, e); } else { for (te=ev->timed_events;te && te->next;te=te->next) { - if (!timeval_is_zero(&te->next_event) && - timeval_compare(&te->next_event, &e->next_event) < 0) { + if (!timeval_is_zero(&te->next->next_event) && + timeval_compare(&te->next->next_event, &e->next_event) < 0) { break; } } -- cgit From f6f70999ca355072aa582545f0b72ca7c91df0a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 8 Feb 2005 01:02:56 +0000 Subject: r5274: fixed some const warnings by making the str_list_ functions return "const char **" (This used to be commit 4165f2163530c7d2ffbea2922fbfe942eee85e7a) --- source4/lib/util_strlist.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index c6ccad907b..71f634f71a 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -25,30 +25,30 @@ separator list. The sepatator list must contain characters less than or equal to 0x2f for this to work correctly on multi-byte strings */ -char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) { int num_elements = 0; - char **ret = NULL; + const char **ret = NULL; if (sep == NULL) { sep = LIST_SEP; } - ret = talloc_realloc(mem_ctx, NULL, char *, 1); + ret = talloc_realloc(mem_ctx, NULL, const char *, 1); if (ret == NULL) { return NULL; } while (string && *string) { size_t len = strcspn(string, sep); - char **ret2; + const char **ret2; if (len == 0) { string += strspn(string, sep); continue; } - ret2 = talloc_realloc(mem_ctx, ret, char *, num_elements+2); + ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); if (ret2 == NULL) { talloc_free(ret); return NULL; @@ -84,10 +84,10 @@ size_t str_list_length(const char **list) /* copy a string list */ -char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) +const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) { int i; - char **ret = talloc_array(mem_ctx, char *, str_list_length(list)+1); + const char **ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); if (ret == NULL) return NULL; for (i=0;list && list[i];i++) { -- cgit From efd042e9792a96cc1eefe8a120047249a00fc974 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 9 Feb 2005 13:51:14 +0000 Subject: r5284: this is needed on my server +/* this #undef is needed on my SuSE 9.2 Box with glibc-devel-2.3.3-118 */ +#undef u32 as sys/epoll.h has this: typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; metze (This used to be commit b4928f3ea8f6530317dfa76593cf93e6acd4337a) --- source4/lib/events/events.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index cf165c99dc..408fe8c6f1 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -66,6 +66,8 @@ #endif #if WITH_EPOLL +/* this #undef is needed on my SuSE 9.2 Box with glibc-devel-2.3.3-118 */ +#undef u32 #include #endif -- cgit From 22adab2004d56918b40fff0f0716d8a889c9f007 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 03:16:33 +0000 Subject: r5292: ensure we cleanup the epoll_fd on event context destruction (This used to be commit e820fca5062026810c5bd4827941f34c19a5e847) --- source4/lib/events/events.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 408fe8c6f1..64cf8f41bf 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -112,6 +112,21 @@ struct event_context { }; +/* + destroy an event context +*/ +static int event_context_destructor(void *ptr) +{ +#if WITH_EPOLL + struct event_context *ev = talloc_get_type(ptr, struct event_context); + if (ev->epoll_fd != -1) { + close(ev->epoll_fd); + ev->epoll_fd = -1; + } +#endif + return 0; +} + /* create a event_context structure. This must be the first events call, and all subsequent calls pass this event_context as the first @@ -128,6 +143,8 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) ev->epoll_fd = epoll_create(64); #endif + talloc_set_destructor(ev, event_context_destructor); + return ev; } -- cgit From b9bb7f596de51496c18580863efbb8ac17c78970 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 03:22:47 +0000 Subject: r5294: - added a separate NBT-WINS test for WINS operations (register, refresh, release and query) - change the iface_n_*() functions to return a "const char *" instead of a "struct ipv4_addr" I think that in general we should move towards "const char *" for all IP addresses, as this makes IPv6 much easier, and is also easier to debug. Andrew, when you get a chance, could you fix some of the auth code to use strings for IPs ? - return a NTSTATUS error on bad name queries and node status instead of using rcode. This makes the calling code simpler. - added low level name release code in libcli/nbt/ - use a real IP in the register and wins nbt torture tests, as w2k3 WINS server silently rejects some operations that don't come from the IP being used (eg. it says "yes" to a release, but does not in fact release the name) (This used to be commit bb1ab11d8e0ea0bd9ae34aebeb565d36fe4b495f) --- source4/lib/netif/interface.c | 59 +++++++++++-------------------------------- 1 file changed, 15 insertions(+), 44 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index bf1e147e02..31354e359a 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -1,7 +1,9 @@ /* Unix SMB/CIFS implementation. + multiple interface handling - Copyright (C) Andrew Tridgell 1992-1998 + + Copyright (C) Andrew Tridgell 1992-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 @@ -275,20 +277,6 @@ BOOL ismyip(struct ipv4_addr ip) return False; } -/**************************************************************************** - check if a packet is from a local (known) net - **************************************************************************/ -BOOL is_local_net(struct ipv4_addr from) -{ - struct interface *i; - for (i=local_interfaces;i;i=i->next) { - if((from.addr & i->nmask.addr) == - (i->ip.addr & i->nmask.addr)) - return True; - } - return False; -} - /**************************************************************************** how many interfaces do we have **************************************************************************/ @@ -305,65 +293,48 @@ int iface_count(void) /**************************************************************************** return IP of the Nth interface **************************************************************************/ -struct ipv4_addr *iface_n_ip(int n) +const char *iface_n_ip(int n) { struct interface *i; for (i=local_interfaces;i && n;i=i->next) n--; - if (i) return &i->ip; + if (i) { + return sys_inet_ntoa(i->ip); + } return NULL; } /**************************************************************************** return bcast of the Nth interface **************************************************************************/ -struct ipv4_addr *iface_n_bcast(int n) +const char *iface_n_bcast(int n) { struct interface *i; for (i=local_interfaces;i && n;i=i->next) n--; - if (i) return &i->bcast; + if (i) { + return sys_inet_ntoa(i->bcast); + } return NULL; } /**************************************************************************** return netmask of the Nth interface **************************************************************************/ -struct ipv4_addr *iface_n_netmask(int n) +const char *iface_n_netmask(int n) { struct interface *i; for (i=local_interfaces;i && n;i=i->next) n--; - if (i) return &i->nmask; + if (i) { + return sys_inet_ntoa(i->nmask); + } return NULL; } -/* these 3 functions return the ip/bcast/nmask for the interface - most appropriate for the given ip address. If they can't find - an appropriate interface they return the requested field of the - first known interface. */ - -struct ipv4_addr *iface_ip(struct ipv4_addr ip) -{ - struct in_addr in; - struct interface *i; - in.s_addr = ip.addr; - i = iface_find(in, True); - return(i ? &i->ip : &local_interfaces->ip); -} - -/* - return True if a IP is directly reachable on one of our interfaces -*/ -BOOL iface_local(struct ipv4_addr ip) -{ - struct in_addr in; - in.s_addr = ip.addr; - return iface_find(in, True) ? True : False; -} -- cgit From fedf0b0d91fdf2a6ae0ef47acd4047f662bd3374 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 03:48:43 +0000 Subject: r5296: - only include the tdb headers where they are needed - removed the u32 hack in events.c as I think this was only needed as tdb.h defines u32. Metze, can you check that this hack is indeed no longer needed on your suse system? (This used to be commit 6f79432fe656164d4770dbce114a30dda5e7bf9a) --- source4/lib/db_wrap.c | 1 + source4/lib/events/events.c | 2 -- source4/lib/gencache.c | 1 + source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 +++- source4/lib/tdb/common/spinlock.c | 2 +- source4/lib/tdb/common/tdb.c | 2 +- source4/lib/tdb/common/tdbutil.c | 1 + source4/lib/tdb/include/tdb.h | 2 ++ source4/lib/tdb/include/tdbutil.h | 2 ++ source4/lib/tdb/tools/tdbdump.c | 1 + source4/lib/tdb/tools/tdbtest.c | 1 + source4/lib/tdb/tools/tdbtorture.c | 1 + 12 files changed, 15 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 854f772717..6028159377 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -29,6 +29,7 @@ #include "includes.h" #include "dlinklist.h" +#include "lib/tdb/include/tdb.h" #include "lib/ldb/include/ldb.h" static struct ldb_wrap *ldb_list; diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 64cf8f41bf..140e3ff067 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -66,8 +66,6 @@ #endif #if WITH_EPOLL -/* this #undef is needed on my SuSE 9.2 Box with glibc-devel-2.3.3-118 */ -#undef u32 #include #endif diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 160367cfe9..8688683e8d 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -22,6 +22,7 @@ */ #include "includes.h" +#include "lib/tdb/include/tdbutil.h" #include "system/time.h" #undef DBGC_CLASS diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 49052550d0..0c644ffe5e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -1,5 +1,7 @@ -#ifndef _SAMBA_BUILD_ +#ifdef _SAMBA_BUILD_ +#include "lib/tdb/include/tdb.h" +#else #include "tdb.h" #endif diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index 30bfd77962..001f0c3bc1 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -38,11 +38,11 @@ #include #include #include "tdb.h" -#include "spinlock.h" #define DEBUG #else #include "includes.h" +#include "lib/tdb/include/tdb.h" #endif #ifdef USE_SPINLOCKS diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 46b2499179..134ee8a4ea 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -63,9 +63,9 @@ #include #include #include "tdb.h" -#include "spinlock.h" #else #include "includes.h" +#include "lib/tdb/include/tdb.h" #include "system/time.h" #include "system/shmem.h" #include "system/filesys.h" diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index b5187162cf..02a1d66cbe 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "lib/tdb/include/tdbutil.h" #include "system/glob.h" #include "system/wait.h" #include "dlinklist.h" diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index f53503a1d6..1de5517d91 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -154,4 +154,6 @@ extern TDB_DATA tdb_null; } #endif +#include "spinlock.h" + #endif /* tdb.h */ diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index cfa83bd937..80d93b7984 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -21,6 +21,8 @@ #ifndef __TDBUTIL_H__ #define __TDBUTIL_H__ +#include "tdb.h" + /* single node of a list returned by tdb_search_keys */ typedef struct keys_node diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index dd018af6f5..8aa573ca9b 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -37,6 +37,7 @@ #else #include "includes.h" +#include "lib/tdb/include/tdb.h" #include "system/iconv.h" #endif diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index f4854b5931..0a2185d6b8 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -16,6 +16,7 @@ #else #include "includes.h" +#include "lib/tdb/include/tdb.h" #endif diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index bb2313369b..63b3b0d381 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -21,6 +21,7 @@ #else #include "includes.h" +#include "lib/tdb/include/tdb.h" #include "system/time.h" #include "system/wait.h" -- cgit From e3aae721a7d5c8130448d67feb3a9200e14393ac Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:06:41 +0000 Subject: r5297: ensure pstring is not in the generated prototypes (This used to be commit b4103d9f2b809408572521f385d4e7a5ba412169) --- source4/lib/charcnv.c | 5 ----- source4/lib/util.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index d5727feb2c..4cf5d00465 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -508,11 +508,6 @@ size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, i return src_len; } -ssize_t pull_ucs2_pstring(char *dest, const void *src) -{ - return pull_ucs2(dest, src, sizeof(pstring), -1, STR_TERMINATE); -} - /** * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc * diff --git a/source4/lib/util.c b/source4/lib/util.c index 9341a011af..dba2dbfe87 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -310,7 +310,7 @@ BOOL get_myfullname(char *my_name) Get my own domain name. ****************************************************************************/ -BOOL get_mydomname(fstring my_domname) +BOOL get_mydomname(char *my_domname) { pstring hostname; char *p; -- cgit From e82aad1ce39a6b7a2e51b9e2cb494d74ec70e158 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:09:35 +0000 Subject: r5298: - got rid of pstring.h from includes.h. This at least makes it a bit less likely that anyone will use pstring for new code - got rid of winbind_client.h from includes.h. This one triggered a huge change, as winbind_client.h was including system/filesys.h and defining the old uint32 and uint16 types, as well as its own pstring and fstring. (This used to be commit 9db6c79e902ec538108d6b7d3324039aabe1704f) --- source4/lib/charcnv.c | 1 + source4/lib/cmdline/popt_common.h | 1 + source4/lib/cmdline/readline.c | 1 + source4/lib/dcom/common/main.c | 7 ++++--- source4/lib/debug.c | 1 + source4/lib/events/events.c | 1 + source4/lib/fault.c | 1 + source4/lib/gencache.c | 1 + source4/lib/genrand.c | 5 +++-- source4/lib/iconv.c | 1 + source4/lib/ldb/ldb_tdb/ldb_tdb.h | 1 + source4/lib/ldb/tools/ldbadd.c | 4 ++++ source4/lib/ldb/tools/ldbdel.c | 4 ++++ source4/lib/ldb/tools/ldbedit.c | 4 ++++ source4/lib/ldb/tools/ldbmodify.c | 4 ++++ source4/lib/ldb/tools/ldbrename.c | 4 ++++ source4/lib/ldb/tools/ldbsearch.c | 4 ++++ source4/lib/ldb/tools/ldbtest.c | 4 ++++ source4/lib/messaging/messaging.c | 1 + source4/lib/pidfile.c | 2 ++ source4/lib/registry/reg_backend_dir.c | 1 + source4/lib/registry/reg_backend_ldb.c | 8 ++++---- source4/lib/registry/reg_backend_rpc.c | 6 +++--- source4/lib/registry/reg_samba.c | 2 +- source4/lib/select.c | 1 + source4/lib/socket/socket.c | 1 + source4/lib/socket/socket_ipv4.c | 1 + source4/lib/socket/socket_ipv6.c | 1 + source4/lib/socket/socket_unix.c | 1 + source4/lib/system.c | 1 + source4/lib/tdb/common/spinlock.c | 1 + source4/lib/tdb/common/tdbutil.c | 2 ++ source4/lib/tdb/tools/tdbdump.c | 1 + source4/lib/tdb/tools/tdbtorture.c | 1 + source4/lib/unix_privs.c | 1 + source4/lib/username.c | 1 + source4/lib/util.c | 1 + source4/lib/util_file.c | 1 + source4/lib/util_sock.c | 1 + source4/lib/util_str.c | 1 + 40 files changed, 73 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index 4cf5d00465..ea0fcd8d32 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -22,6 +22,7 @@ */ #include "includes.h" #include "system/iconv.h" +#include "pstring.h" /** * @file diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index 06560d2be5..d6ae43d083 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -22,6 +22,7 @@ #define _POPT_COMMON_H #include "popt.h" +#include "pstring.h" /* Common popt structures */ extern struct poptOption popt_common_samba[]; diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 8836759f70..4970638d41 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "pstring.h" #include diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 01906501f1..a8324606f1 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/filesys.h" #include "dlinklist.h" #include "librpc/gen_ndr/ndr_epmapper.h" #include "librpc/gen_ndr/ndr_remact.h" @@ -145,7 +146,7 @@ WERROR dcom_ping(struct dcom_context *ctx) static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; struct dcerpc_pipe *p; struct dcom_object_exporter *m; NTSTATUS status; @@ -268,7 +269,7 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid struct DUALSTRINGARRAY dualstring; NTSTATUS status; struct pMInterfacePointer pm; - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { @@ -498,7 +499,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface if (!m) { struct dcerpc_pipe *po; struct ResolveOxid r; - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", p->ox->oxid)); diff --git a/source4/lib/debug.c b/source4/lib/debug.c index f1e9cec38e..ab012a98aa 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/filesys.h" #include "dynconfig.h" /* this global variable determines what messages are printed */ diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 140e3ff067..3460627399 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -57,6 +57,7 @@ #include "includes.h" #include "system/time.h" #include "system/select.h" +#include "system/filesys.h" #include "dlinklist.h" #include "lib/events/events.h" diff --git a/source4/lib/fault.c b/source4/lib/fault.c index d90281f950..9f1e3f44bc 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -21,6 +21,7 @@ #include "includes.h" #include "version.h" #include "system/wait.h" +#include "system/filesys.h" static void (*cont_fn)(void *); diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 8688683e8d..1a6159942d 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -24,6 +24,7 @@ #include "includes.h" #include "lib/tdb/include/tdbutil.h" #include "system/time.h" +#include "system/filesys.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_TDB diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 0f1d02b710..e3df9f9d90 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -22,10 +22,11 @@ #include "includes.h" #include "system/iconv.h" +#include "system/filesys.h" #include "lib/crypto/crypto.h" static unsigned char hash[258]; -static uint32 counter; +static uint32_t counter; static BOOL done_reseed = False; static void (*reseed_callback)(int *newseed); @@ -147,7 +148,7 @@ static void do_filehash(const char *fname, unsigned char *the_hash) static int do_reseed(BOOL use_fd, int fd) { unsigned char seed_inbuf[40]; - uint32 v1, v2; struct timeval tval; pid_t mypid; + uint32_t v1, v2; struct timeval tval; pid_t mypid; int reseed_data = 0; if (use_fd) { diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c index 181834d66a..df590444e5 100644 --- a/source4/lib/iconv.c +++ b/source4/lib/iconv.c @@ -22,6 +22,7 @@ #include "includes.h" #include "dlinklist.h" #include "system/iconv.h" +#include "system/filesys.h" /** diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 0c644ffe5e..4c2fc52f7c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -1,5 +1,6 @@ #ifdef _SAMBA_BUILD_ +#include "system/filesys.h" #include "lib/tdb/include/tdb.h" #else #include "tdb.h" diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index d95036497a..927debc65e 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static int failures; static void usage(void) diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 29d3b39730..2241a0b823 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) { int ret, i, total=0; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 4c38ea6803..20cb7da810 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static int verbose; /* diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 3bdb946897..97dec1050e 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static int failures; static void usage(void) diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 3ee001cf23..ba870b0a45 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -38,6 +38,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static void usage(void) { printf("Usage: ldbrename [] \n"); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 5e0246d7a9..f764b28557 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static void usage(void) { printf("Usage: ldbsearch \n"); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 01fa1b8ed7..67630d4458 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + static const char *ldb_url; static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index aab13ba8af..df0216617d 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -22,6 +22,7 @@ #include "includes.h" #include "lib/events/events.h" +#include "system/filesys.h" #include "system/time.h" #include "messages.h" #include "dlinklist.h" diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index f8041a2005..ff05c0606e 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -21,6 +21,8 @@ */ #include "includes.h" +#include "pstring.h" +#include "system/filesys.h" #ifndef O_NONBLOCK #define O_NONBLOCK diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index bac0f43c20..68f02d1745 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -21,6 +21,7 @@ #include "includes.h" #include "registry.h" #include "system/dir.h" +#include "system/filesys.h" static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result) { diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 930ea9642e..c7b7bf587f 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -36,7 +36,7 @@ static int ldb_close_hive (void *_hive) return 0; } -static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32 *type, void **data, int *len) +static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32_t *type, void **data, int *len) { const struct ldb_val *val; *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL)); @@ -52,7 +52,7 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c case REG_DWORD_LE: *len = 4; - *data = talloc(mem_ctx, uint32); + *data = talloc(mem_ctx, uint32_t); SIVAL(*data, 0, strtol(val->data, NULL, 0)); break; @@ -63,7 +63,7 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c } } -static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32 type, void *data, int len) +static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, void *data, int len) { struct ldb_val val; struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message); @@ -322,7 +322,7 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) return WERR_OK; } -static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len) +static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32_t type, void *data, int len) { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message *msg; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index d2809f644a..2302416554 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -78,7 +78,7 @@ struct rpc_key_data { }; struct { - uint32 hkey; + uint32_t hkey; WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); } known_hives[] = { { HKEY_LOCAL_MACHINE, open_HKLM }, @@ -93,7 +93,7 @@ struct { static WERROR rpc_query_key(struct registry_key *k); -static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k) +static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hkey_type, struct registry_key **k) { int n; struct registry_hive *h; @@ -185,7 +185,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p struct rpc_key_data *mykeydata = parent->backend_data; WERROR error; struct winreg_EnumValue r; - uint32 type, len1, zero = 0; + uint32_t type, len1, zero = 0; NTSTATUS status; uint8_t buf8; uint16_t buf16; diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c index a81b9e5a42..7188109daa 100644 --- a/source4/lib/registry/reg_samba.c +++ b/source4/lib/registry/reg_samba.c @@ -23,7 +23,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_REGISTRY -static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32 hkey, struct registry_key **k) +static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, struct registry_key **k) { WERROR error; const char *conf; diff --git a/source4/lib/select.c b/source4/lib/select.c index 5d7e4a0ad2..bed02304cc 100644 --- a/source4/lib/select.c +++ b/source4/lib/select.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "system/filesys.h" /* This is here because it allows us to avoid a nasty race in signal handling. We need to guarantee that when we get a signal we get out of a select immediately diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 97176ea150..109a7cadc0 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "system/filesys.h" /* auto-close sockets on free diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 09a4b4a73a..2a212fbc94 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/network.h" +#include "system/filesys.h" static NTSTATUS ipv4_init(struct socket_context *sock) { diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index f5cd756259..d7241d9b38 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/network.h" +#include "system/filesys.h" static struct in6_addr interpret_addr6(const char *name) { diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index e23aa0d97e..2bcce0eb11 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/network.h" +#include "system/filesys.h" diff --git a/source4/lib/system.c b/source4/lib/system.c index b23529f5fe..eb3799c7ca 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -23,6 +23,7 @@ #include "system/network.h" #include "system/wait.h" #include "system/filesys.h" +#include "pstring.h" /* The idea is that this file will eventually have wrappers around all diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c index 001f0c3bc1..232cd8dfc6 100644 --- a/source4/lib/tdb/common/spinlock.c +++ b/source4/lib/tdb/common/spinlock.c @@ -43,6 +43,7 @@ #else #include "includes.h" #include "lib/tdb/include/tdb.h" +#include "system/filesys.h" #endif #ifdef USE_SPINLOCKS diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 02a1d66cbe..e3c5641054 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -22,7 +22,9 @@ #include "lib/tdb/include/tdbutil.h" #include "system/glob.h" #include "system/wait.h" +#include "system/filesys.h" #include "dlinklist.h" +#include "pstring.h" /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 8aa573ca9b..774093dbc0 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -39,6 +39,7 @@ #include "includes.h" #include "lib/tdb/include/tdb.h" #include "system/iconv.h" +#include "system/filesys.h" #endif diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 63b3b0d381..7e8e77952c 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -24,6 +24,7 @@ #include "lib/tdb/include/tdb.h" #include "system/time.h" #include "system/wait.h" +#include "system/filesys.h" #endif diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c index a57f4359d3..b59657b7d5 100644 --- a/source4/lib/unix_privs.c +++ b/source4/lib/unix_privs.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/passwd.h" +#include "system/filesys.h" /* there are times when smbd needs to temporarily gain root privileges diff --git a/source4/lib/username.c b/source4/lib/username.c index 1c8e5aa2bb..55965a7980 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "pstring.h" /***************************************************************** Splits passed user or group name to domain and user/group name parts diff --git a/source4/lib/util.c b/source4/lib/util.c index dba2dbfe87..af41a20aa5 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -26,6 +26,7 @@ #include "dynconfig.h" #include "system/network.h" #include "system/iconv.h" +#include "system/filesys.h" /**************************************************************************n Find a suitable temporary directory. The result should be copied immediately diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 2b2fe2b2af..6d234b571c 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -20,6 +20,7 @@ #include "includes.h" #include "system/shmem.h" +#include "system/filesys.h" /************************************************************************* gets a line out of a file. diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index b2f949ebe5..d60fbb3451 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/network.h" +#include "pstring.h" enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index d9c4e30d6a..dc39da50c7 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/iconv.h" +#include "pstring.h" /** * @file -- cgit From ec15008ec703b44ff3073bf074eda8adc8c5d00c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:15:37 +0000 Subject: r5299: fixed an include ordering problem (This used to be commit 483b7af1fd6e3caa1db2f6b31ac6165d29ea7512) --- source4/lib/unix_privs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c index b59657b7d5..5cc7d5f26e 100644 --- a/source4/lib/unix_privs.c +++ b/source4/lib/unix_privs.c @@ -21,8 +21,8 @@ */ #include "includes.h" -#include "system/passwd.h" #include "system/filesys.h" +#include "system/passwd.h" /* there are times when smbd needs to temporarily gain root privileges -- cgit From 8674eaa5cc9b1ddeb65f05527a5b539f15e4afcb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:22:53 +0000 Subject: r5300: more uint32 and system/filesys.h build fixes when developer mode is enabled (This used to be commit 93931b1a741a3722c311ada80c4c9d3d670f91b2) --- source4/lib/tdb/tools/tdbtest.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index 0a2185d6b8..e55d08f840 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -16,6 +16,7 @@ #else #include "includes.h" +#include "system/filesys.h" #include "lib/tdb/include/tdb.h" #endif -- cgit From 35537c1255e9508b77fd9d9def1ac96e423bee46 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 06:36:30 +0000 Subject: r5302: fixed a compilation problem on solaris caused by the recent include changes (This used to be commit e7e015f79b10c353848a17f31c91a0593790a560) --- source4/lib/util.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index af41a20aa5..d95924670f 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -44,16 +44,15 @@ const char *tmpdir(void) /******************************************************************* Check if a file exists - call vfs_file_exist for samba files. ********************************************************************/ -BOOL file_exist(const char *fname, struct stat *sbuf) +BOOL file_exist(const char *fname) { struct stat st; - if (!sbuf) - sbuf = &st; - - if (stat(fname,sbuf) != 0) - return(False); - return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode))); + if (stat(fname, &st) != 0) { + return False; + } + + return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode))); } /******************************************************************* @@ -74,18 +73,16 @@ time_t file_modtime(const char *fname) Check if a directory exists. ********************************************************************/ -BOOL directory_exist(const char *dname,struct stat *st) +BOOL directory_exist(const char *dname) { - struct stat st2; + struct stat st; BOOL ret; - if (!st) - st = &st2; - - if (stat(dname,st) != 0) - return(False); + if (stat(dname,&st) != 0) { + return False; + } - ret = S_ISDIR(st->st_mode); + ret = S_ISDIR(st.st_mode); if(!ret) errno = ENOTDIR; return ret; @@ -687,7 +684,7 @@ char *lock_path(TALLOC_CTX* mem_ctx, const char *name) dname = talloc_strdup(mem_ctx, lp_lockdir()); trim_string(dname,"","/"); - if (!directory_exist(dname,NULL)) { + if (!directory_exist(dname)) { mkdir(dname,0755); } @@ -738,7 +735,7 @@ char *smbd_tmp_path(TALLOC_CTX *mem_ctx, const char *name) char *fname, *dname; dname = lock_path(mem_ctx, "smbd.tmp"); - if (!directory_exist(dname,NULL)) { + if (!directory_exist(dname)) { mkdir(dname,0755); } -- cgit From 8fb475f626c61b977d6dcd3b20b3495fd9d0b95d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 06:45:13 +0000 Subject: r5303: fixed build of gconf registry backend (This used to be commit b4993c738ba7ce38de4eaf6270db60f8cd551cdd) --- source4/lib/registry/reg_backend_gconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c index a912a42e55..9986f6f71a 100644 --- a/source4/lib/registry/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf.c @@ -150,7 +150,7 @@ static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p return WERR_OK; } -static WERROR gconf_set_value(struct registry_key *key, const char *valname, uint32 type, void *data, int len) +static WERROR gconf_set_value(struct registry_key *key, const char *valname, uint32_t type, void *data, int len) { GError *error = NULL; char *valpath; -- cgit From bed7c9ec32b7d4083ba4ed2abbf3b6126bee7a25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 06:59:29 +0000 Subject: r5304: removed lib/socket/socket.h from includes.h (This used to be commit b902ea546d2d1327b23f40ddaeeaa8e7e3662454) --- source4/lib/messaging/messaging.c | 1 + source4/lib/socket/access.c | 1 + source4/lib/socket/config.mk | 4 ++++ source4/lib/socket/socket.c | 5 +++++ source4/lib/socket/socket.h | 35 +++++++++++++++++++++++++++++++++++ source4/lib/socket/socket_ipv4.c | 1 + source4/lib/socket/socket_ipv6.c | 1 + source4/lib/socket/socket_unix.c | 2 ++ 8 files changed, 50 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index df0216617d..8127e7e8fc 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -26,6 +26,7 @@ #include "system/time.h" #include "messages.h" #include "dlinklist.h" +#include "lib/socket/socket.h" /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c index c90bf203dd..a64444d41c 100644 --- a/source4/lib/socket/access.c +++ b/source4/lib/socket/access.c @@ -34,6 +34,7 @@ #include "includes.h" #include "system/network.h" #include "system/iconv.h" +#include "lib/socket/socket.h" #define FAIL (-1) #define ALLONES ((uint32_t)0xFFFFFFFF) diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 6217fbc079..e4719c3f67 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -5,6 +5,7 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv4.o +NOPROTO=YES # End MODULE socket_ipv4 ################################################ @@ -14,6 +15,7 @@ INIT_OBJ_FILES = \ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv6.o +NOPROTO=YES # End MODULE socket_ipv6 ################################################ @@ -23,6 +25,7 @@ INIT_OBJ_FILES = \ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_unix.o +NOPROTO=YES # End MODULE socket_unix ################################################ @@ -33,5 +36,6 @@ INIT_OBJ_FILES = \ lib/socket/socket.o ADD_OBJ_FILES = \ lib/socket/access.o +NOPROTO=YES # End SUBSYSTEM SOCKET ################################################ diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 109a7cadc0..ddc2097f42 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include "lib/socket/socket.h" #include "system/filesys.h" /* @@ -326,6 +327,10 @@ NTSTATUS socket_dup(struct socket_context *sock) const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) { + extern const struct socket_ops *socket_ipv4_ops(enum socket_type ); + extern const struct socket_ops *socket_ipv6_ops(enum socket_type ); + extern const struct socket_ops *socket_unixdom_ops(enum socket_type ); + if (strcmp("ip", name) == 0 || strcmp("ipv4", name) == 0) { return socket_ipv4_ops(type); diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 162a05cb40..b1fae9ac56 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -103,4 +103,39 @@ struct socket_context { const struct socket_ops *ops; }; + +/* prototypes */ +NTSTATUS socket_create(const char *name, enum socket_type type, + struct socket_context **new_sock, uint32_t flags); +void socket_destroy(struct socket_context *sock); +NTSTATUS socket_connect(struct socket_context *sock, + const char *my_address, int my_port, + const char *server_address, int server_port, + uint32_t flags); +NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags); +NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags); +NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock); +NTSTATUS socket_recv(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags); +NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, uint32_t flags, + const char **src_addr, int *src_port); +NTSTATUS socket_send(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags); +NTSTATUS socket_sendto(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, + const char *dest_addr, int dest_port); +NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val); +char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx); +char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); +int socket_get_peer_port(struct socket_context *sock); +char *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); +int socket_get_my_port(struct socket_context *sock); +int socket_get_fd(struct socket_context *sock); +NTSTATUS socket_dup(struct socket_context *sock); +const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type); +BOOL socket_check_access(struct socket_context *sock, + const char *service_name, + const char **allow_list, const char **deny_list); + #endif /* _SAMBA_SOCKET_H */ diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 2a212fbc94..4f8b1e6dd6 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -24,6 +24,7 @@ #include "includes.h" #include "system/network.h" #include "system/filesys.h" +#include "lib/socket/socket.h" static NTSTATUS ipv4_init(struct socket_context *sock) { diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index d7241d9b38..2384e60550 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -20,6 +20,7 @@ */ #include "includes.h" +#include "lib/socket/socket.h" #include "system/network.h" #include "system/filesys.h" diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 2bcce0eb11..7cf12db4b2 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -22,6 +22,8 @@ */ #include "includes.h" +#include "lib/socket/socket.h" +#include "lib/socket/socket.h" #include "system/network.h" #include "system/filesys.h" -- cgit From 6aa6dce3f7c4303d184b3098fbf4619e49a27e45 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 07:18:00 +0000 Subject: r5306: removed all the unused mutex functions from mutex.c. When (if?) we decide to reinstate the mutex code for the threads process model, I'd like to do it a little differently. At least this gets it out of includes.h for now. (This used to be commit cfee0fb02e10add22b6c436bdfa95d1a8f5f3def) --- source4/lib/mutex.c | 92 +---------------------------------------------------- 1 file changed, 1 insertion(+), 91 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/mutex.c b/source4/lib/mutex.c index 25ea3c55ee..480ba92cc0 100644 --- a/source4/lib/mutex.c +++ b/source4/lib/mutex.c @@ -19,99 +19,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" +#include "mutex.h" -static smb_mutex_t mutex_list[MUTEX_MAX]; - /* the registered mutex handlers */ static struct { const char *name; struct mutex_ops ops; } mutex_handlers; -int smb_mutex_lock_by_id(enum mutex_id id, const char *name) -{ - return smb_mutex_lock(&mutex_list[id], name); -} - -int smb_mutex_unlock_by_id(enum mutex_id id, const char *name) -{ - return smb_mutex_unlock(&mutex_list[id], name); -} - -int smb_mutex_init(smb_mutex_t *mutex, const char *name) -{ - if (mutex_handlers.ops.mutex_init) { - return mutex_handlers.ops.mutex_init(mutex, name); - } - return 0; -} - -int smb_mutex_destroy(smb_mutex_t *mutex, const char *name) -{ - if (mutex_handlers.ops.mutex_destroy) { - return mutex_handlers.ops.mutex_destroy(mutex, name); - } - return 0; -} - -int smb_mutex_lock(smb_mutex_t *mutex, const char *name) -{ - if (mutex_handlers.ops.mutex_lock) { - return mutex_handlers.ops.mutex_lock(mutex, name); - } - return 0; -} - -int smb_mutex_unlock(smb_mutex_t *mutex, const char *name) -{ - if (mutex_handlers.ops.mutex_unlock) { - return mutex_handlers.ops.mutex_unlock(mutex, name); - } - return 0; -} - /* read/write lock routines */ -int smb_rwlock_init(smb_rwlock_t *rwlock, const char *name) -{ - if (mutex_handlers.ops.rwlock_init) { - return mutex_handlers.ops.rwlock_init(rwlock, name); - } - return 0; -} - -int smb_rwlock_destroy(smb_rwlock_t *rwlock, const char *name) -{ - if (mutex_handlers.ops.rwlock_destroy) { - return mutex_handlers.ops.rwlock_destroy(rwlock, name); - } - return 0; -} - -int smb_rwlock_lock_write(smb_rwlock_t *rwlock, const char *name) -{ - if (mutex_handlers.ops.rwlock_lock_write) { - return mutex_handlers.ops.rwlock_lock_write(rwlock, name); - } - return 0; -} - -int smb_rwlock_lock_read(smb_rwlock_t *rwlock, const char *name) -{ - if (mutex_handlers.ops.rwlock_lock_read) { - return mutex_handlers.ops.rwlock_lock_read(rwlock, name); - } - return 0; -} - -int smb_rwlock_unlock(smb_rwlock_t *rwlock, const char *name) -{ - if (mutex_handlers.ops.rwlock_unlock) { - return mutex_handlers.ops.rwlock_unlock(rwlock, name); - } - return 0; -} - /* register a set of mutex/rwlock handlers. @@ -129,13 +46,6 @@ BOOL register_mutex_handlers(const char *name, struct mutex_ops *ops) mutex_handlers.name = name; mutex_handlers.ops = *ops; - if (mutex_handlers.ops.mutex_init) { - enum mutex_id id; - for (id=0; id < MUTEX_MAX; id++) { - mutex_handlers.ops.mutex_init(&mutex_list[id], "mutex_list"); - } - } - DEBUG(2,("mutex handler '%s' registered\n", name)); return True; } -- cgit From a5bd1ccadab723c531963c219a1ac2b6b0c8b845 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 07:22:25 +0000 Subject: r5307: removed db_wrap.h from includes.h (This used to be commit 826baec7b348814a7bbdcdbec8c8526514f25da1) --- source4/lib/db_wrap.c | 1 + source4/lib/gencache.c | 1 + source4/lib/registry/reg_backend_ldb.c | 1 + 3 files changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 6028159377..0ec1e378e6 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -31,6 +31,7 @@ #include "dlinklist.h" #include "lib/tdb/include/tdb.h" #include "lib/ldb/include/ldb.h" +#include "db_wrap.h" static struct ldb_wrap *ldb_list; static struct tdb_wrap *tdb_list; diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 1a6159942d..b6d62977ad 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -25,6 +25,7 @@ #include "lib/tdb/include/tdbutil.h" #include "system/time.h" #include "system/filesys.h" +#include "db_wrap.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_TDB diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index c7b7bf587f..9f44f92888 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -21,6 +21,7 @@ #include "includes.h" #include "registry.h" #include "lib/ldb/include/ldb.h" +#include "db_wrap.h" struct ldb_key_data { -- cgit From 75ddf59ea110117578acd3a7b889549bfb40473c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 07:39:14 +0000 Subject: r5308: trimmed back a lot of the old macros from smb_macros.h (This used to be commit bf43c9bdcf9e654d123f6a2b29feb9189ca9e561) --- source4/lib/netif/interface.c | 5 +++-- source4/lib/pidfile.c | 2 +- source4/lib/util.c | 6 ++---- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 31354e359a..2d90df43cf 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -272,8 +272,9 @@ BOOL interfaces_changed(void) BOOL ismyip(struct ipv4_addr ip) { struct interface *i; - for (i=local_interfaces;i;i=i->next) - if (ipv4_equal(i->ip,ip)) return True; + for (i=local_interfaces;i;i=i->next) { + if (i->ip.addr == ip.addr) return True; + } return False; } diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index ff05c0606e..b1866ee6af 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -44,7 +44,7 @@ pid_t pidfile_pid(const char *name) return 0; } - ZERO_ARRAY(pidstr); + ZERO_STRUCT(pidstr); if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) { goto noproc; diff --git a/source4/lib/util.c b/source4/lib/util.c index d95924670f..93559d9518 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -410,7 +410,7 @@ uint32_t interpret_addr(const char *str) DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str)); return 0; } - putip((char *)&res,(char *)hp->h_addr); + memcpy((char *)&res,(char *)hp->h_addr, 4); } if (res == (uint32_t)-1) @@ -436,9 +436,7 @@ struct ipv4_addr interpret_addr2(const char *str) BOOL is_zero_ip(struct ipv4_addr ip) { - uint32_t a; - putip((char *)&a,(char *)&ip); - return(a == 0); + return ip.addr == 0; } /******************************************************************* -- cgit From c8ca613e935b44488435a269957a68b48d2af90f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Feb 2005 10:15:56 +0000 Subject: r5330: Remove #include from includes.h. Add #include "system/time.h" back (it was removed in some of these places because the definitions were provided by on tridge's platform.) Andrew Bartlett (This used to be commit 34b1da730304bed7fee5bae7cbde7fbccecb6af5) --- source4/lib/ldb/tools/ldbtest.c | 1 + source4/lib/tdb/tools/tdbtest.c | 1 + 2 files changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 67630d4458..a166447aae 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -38,6 +38,7 @@ #ifdef _SAMBA_BUILD_ #include "system/filesys.h" +#include "system/time.h" #endif static const char *ldb_url; diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index e55d08f840..4f7f7faafc 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -17,6 +17,7 @@ #include "includes.h" #include "system/filesys.h" +#include "system/time.h" #include "lib/tdb/include/tdb.h" #endif -- cgit From ff4797a9e4b01fe8cc9421e911371677433d070c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 12 Feb 2005 11:30:33 +0000 Subject: r5357: added ldb_msg_add_fmt(), for creating formatted ldb record values (This used to be commit 18fb48204f4c0e22ea7e61575b3f174f30ff035c) --- source4/lib/ldb/common/ldb_msg.c | 22 ++++++++++++++++++++++ source4/lib/ldb/include/ldb.h | 2 ++ 2 files changed, 24 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 3ef25e566f..b145565a84 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -212,6 +212,28 @@ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, return ldb_msg_add_value(ldb, msg, attr_name, &val); } +/* + add a printf formatted element to a message +*/ +int ldb_msg_add_fmt(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) +{ + struct ldb_val val; + va_list ap; + char *str; + + va_start(ap, fmt); + str = talloc_vasprintf(msg, fmt, ap); + va_end(ap); + + if (str == NULL) return -1; + + val.data = str; + val.length = strlen(str); + + return ldb_msg_add_value(ldb, msg, attr_name, &val); +} + /* compare two ldb_message_element structures assumes case senistive comparison diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 310000b244..c6f96f6dea 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -259,6 +259,8 @@ int ldb_msg_add_value(struct ldb_context *ldb, const struct ldb_val *val); int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, const char *str); +int ldb_msg_add_fmt(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); /* compare two message elements - return 0 on match */ int ldb_msg_element_compare(struct ldb_message_element *el1, -- cgit From e199f4cef2bac3b244d08d445421975313229283 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 12 Feb 2005 11:33:42 +0000 Subject: r5358: - added initial WINS server code. It passes most of the NBT-WINS test, but doesn't yet do secure server WACK responses - added a ldap_string_to_time() function, for converting a LDAP formatted time to a time_t (This used to be commit 9aa3313b3f93e47e3f93028e072f6a23b3c22385) --- source4/lib/time.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 7a4059f646..67397e953a 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -292,9 +292,9 @@ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) return buf; } -/*************************************************************************** -return a LDAP time string - ***************************************************************************/ +/* + return a LDAP time string +*/ char *ldap_timestring(TALLOC_CTX *mem_ctx, time_t t) { struct tm *tm = gmtime(&t); @@ -311,6 +311,28 @@ char *ldap_timestring(TALLOC_CTX *mem_ctx, time_t t) tm->tm_sec); } + +/* + convert a LDAP time string to a time_t. Return 0 if unable to convert +*/ +time_t ldap_string_to_time(const char *s) +{ + struct tm tm; + + if (s == NULL) return 0; + + ZERO_STRUCT(tm); + if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return 0; + } + tm.tm_year -= 1900; + tm.tm_mon -= 1; + + return timegm(&tm); +} + /**************************************************************************** Return the date and time as a string ****************************************************************************/ -- cgit From cc336df026db5b613c2416163a5167bfe57fb810 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 13 Feb 2005 08:52:12 +0000 Subject: r5370: epoll gives more precise event bits like EPOLLHUP instead of just EPOLLIN. We need to map these to "read" events for the events code to work on errors like connection refused (thanks to vl for noticing this bug) (This used to be commit 7c379590b4ca808eddef5c3ac15db25cefc5215b) --- source4/lib/events/events.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 3460627399..9783603759 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -404,7 +404,8 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) epoll_fallback_to_select(ev, "epoll_wait() gave bad data"); return -1; } - if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ; + if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)) + flags |= EVENT_FD_READ; if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE; if (flags) { fde->handler(ev, fde, flags, fde->private); -- cgit From e40da81aa4c279240c5ae3f1810fb9cedc15765d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 13 Feb 2005 11:32:11 +0000 Subject: r5373: prepare infrastructure for maing different events implementations possible metze (This used to be commit dd77ec754b811feb147458d76fa16833767dccea) --- source4/lib/events/config.mk | 2 +- source4/lib/events/events.c | 540 ----------------------------------- source4/lib/events/events_standard.c | 540 +++++++++++++++++++++++++++++++++++ 3 files changed, 541 insertions(+), 541 deletions(-) delete mode 100644 source4/lib/events/events.c create mode 100644 source4/lib/events/events_standard.c (limited to 'source4/lib') diff --git a/source4/lib/events/config.mk b/source4/lib/events/config.mk index c6f66b1c51..e1f9f589a1 100644 --- a/source4/lib/events/config.mk +++ b/source4/lib/events/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM LIBEVENTS [SUBSYSTEM::LIBEVENTS] NOPROTO = YES -INIT_OBJ_FILES = lib/events/events.o +INIT_OBJ_FILES = lib/events/events_standard.o REQUIRED_SUBSYSTEMS = LIBTALLOC # End SUBSYSTEM LIBEVENTS ############################## diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c deleted file mode 100644 index 9783603759..0000000000 --- a/source4/lib/events/events.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - Unix SMB/CIFS implementation. - main select loop and event handling - Copyright (C) Andrew Tridgell 2003 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - PLEASE READ THIS BEFORE MODIFYING! - - This module is a general abstraction for the main select loop and - event handling. Do not ever put any localised hacks in here, instead - register one of the possible event types and implement that event - somewhere else. - - There are 2 types of event handling that are handled in this module: - - 1) a file descriptor becoming readable or writeable. This is mostly - used for network sockets, but can be used for any type of file - descriptor. You may only register one handler for each file - descriptor/io combination or you will get unpredictable results - (this means that you can have a handler for read events, and a - separate handler for write events, but not two handlers that are - both handling read events) - - 2) a timed event. You can register an event that happens at a - specific time. You can register as many of these as you - like. They are single shot - add a new timed event in the event - handler to get another event. - - To setup a set of events you first need to create a event_context - structure using the function event_context_init(); This returns a - 'struct event_context' that you use in all subsequent calls. - - After that you can add/remove events that you are interested in - using event_add_*() and talloc_free() - - Finally, you call event_loop_wait() to block waiting for one of the - events to occor. In normal operation event_loop_wait() will loop - forever. - -*/ - -#include "includes.h" -#include "system/time.h" -#include "system/select.h" -#include "system/filesys.h" -#include "dlinklist.h" -#include "lib/events/events.h" - -/* use epoll if it is available */ -#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) -#define WITH_EPOLL 1 -#endif - -#if WITH_EPOLL -#include -#endif - -struct event_context { - /* list of filedescriptor events */ - struct fd_event { - struct event_context *event_ctx; - struct fd_event *next, *prev; - int fd; - uint16_t flags; /* see EVENT_FD_* flags */ - event_fd_handler_t handler; - void *private; - } *fd_events; - - /* list of timed events */ - struct timed_event { - struct event_context *event_ctx; - struct timed_event *next, *prev; - struct timeval next_event; - event_timed_handler_t handler; - void *private; - } *timed_events; - - /* the maximum file descriptor number in fd_events */ - int maxfd; - - /* information for exiting from the event loop */ - int exit_code; - - /* this is changed by the destructors for the fd event - type. It is used to detect event destruction by event - handlers, which means the code that is calling the event - handler needs to assume that the linked list is no longer - valid - */ - uint32_t destruction_count; - -#if WITH_EPOLL - /* when using epoll this is the handle from epoll_create */ - int epoll_fd; -#endif -}; - - -/* - destroy an event context -*/ -static int event_context_destructor(void *ptr) -{ -#if WITH_EPOLL - struct event_context *ev = talloc_get_type(ptr, struct event_context); - if (ev->epoll_fd != -1) { - close(ev->epoll_fd); - ev->epoll_fd = -1; - } -#endif - return 0; -} - -/* - create a event_context structure. This must be the first events - call, and all subsequent calls pass this event_context as the first - element. Event handlers also receive this as their first argument. -*/ -struct event_context *event_context_init(TALLOC_CTX *mem_ctx) -{ - struct event_context *ev; - - ev = talloc_zero(mem_ctx, struct event_context); - if (!ev) return NULL; - -#if WITH_EPOLL - ev->epoll_fd = epoll_create(64); -#endif - - talloc_set_destructor(ev, event_context_destructor); - - return ev; -} - - -/* - recalculate the maxfd -*/ -static void calc_maxfd(struct event_context *ev) -{ - struct fd_event *e; - ev->maxfd = 0; - for (e=ev->fd_events; e; e=e->next) { - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; - } - } -} - - -/* to mark the ev->maxfd invalid - * this means we need to recalculate it - */ -#define EVENT_INVALID_MAXFD (-1) - - -#if WITH_EPOLL -/* - called when a epoll call fails, and we should fallback - to using select -*/ -static void epoll_fallback_to_select(struct event_context *ev, const char *reason) -{ - DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno))); - close(ev->epoll_fd); - ev->epoll_fd = -1; -} -#endif - - -#if WITH_EPOLL -/* - map from EVENT_FD_* to EPOLLIN/EPOLLOUT -*/ -static uint32_t epoll_map_flags(uint16_t flags) -{ - uint32_t ret = 0; - if (flags & EVENT_FD_READ) ret |= EPOLLIN; - if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT; - return ret; -} -#endif - -/* - destroy an fd_event -*/ -static int event_fd_destructor(void *ptr) -{ - struct fd_event *fde = talloc_get_type(ptr, struct fd_event); - struct event_context *ev = fde->event_ctx; - - if (ev->maxfd == fde->fd) { - ev->maxfd = EVENT_INVALID_MAXFD; - } - DLIST_REMOVE(ev->fd_events, fde); - ev->destruction_count++; -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(fde->flags); - event.data.ptr = fde; - epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); - } -#endif - return 0; -} - -/* - add a fd based event - return NULL on failure (memory allocation error) -*/ -struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, event_fd_handler_t handler, - void *private) -{ - struct fd_event *e = talloc(ev, struct fd_event); - if (!e) return NULL; - - e->event_ctx = ev; - e->fd = fd; - e->flags = flags; - e->handler = handler; - e->private = private; - - DLIST_ADD(ev->fd_events, e); - - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; - } - - talloc_set_destructor(e, event_fd_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); - } - -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(flags); - event.data.ptr = e; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); - } - } -#endif - - return e; -} - - -/* - return the fd event flags -*/ -uint16_t event_fd_flags(struct fd_event *fde) -{ - return fde?fde->flags:0; -} - -/* - set the fd event flags -*/ -void event_fd_setflags(struct fd_event *fde, uint16_t flags) -{ -#if WITH_EPOLL - struct event_context *ev; - if (fde == NULL || - fde->flags == flags) { - return; - } - ev = fde->event_ctx; - if (ev->epoll_fd != -1) { - struct epoll_event event; - ZERO_STRUCT(event); - event.events = epoll_map_flags(flags); - event.data.ptr = fde; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { - epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); - } - } -#endif - if (fde) { - fde->flags = flags; - } -} - -/* - destroy a timed event -*/ -static int event_timed_destructor(void *ptr) -{ - struct timed_event *te = talloc_get_type(ptr, struct timed_event); - DLIST_REMOVE(te->event_ctx->timed_events, te); - return 0; -} - -/* - add a timed event - return NULL on failure (memory allocation error) -*/ -struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, - struct timeval next_event, - event_timed_handler_t handler, - void *private) -{ - struct timed_event *te, *e; - - e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); - if (e == NULL) return NULL; - - e->event_ctx = ev; - e->next_event = next_event; - e->handler = handler; - e->private = private; - - /* keep the list ordered */ - if (ev->timed_events == NULL || - timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { - DLIST_ADD(ev->timed_events, e); - } else { - for (te=ev->timed_events;te && te->next;te=te->next) { - if (!timeval_is_zero(&te->next->next_event) && - timeval_compare(&te->next->next_event, &e->next_event) < 0) { - break; - } - } - DLIST_ADD_AFTER(ev->timed_events, e, te); - } - - talloc_set_destructor(e, event_timed_destructor); - - return e; -} - -/* - a timer has gone off - call it -*/ -static void event_loop_timer(struct event_context *ev) -{ - struct timeval t = timeval_current(); - struct timed_event *te = ev->timed_events; - - te->next_event = timeval_zero(); - - te->handler(ev, te, t, te->private); - - /* note the care taken to prevent referencing a event - that could have been freed by the handler */ - if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { - talloc_free(ev->timed_events); - } -} - -#if WITH_EPOLL -/* - event loop handling using epoll -*/ -static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) -{ - int ret, i; - const int maxevents = 8; - struct epoll_event events[maxevents]; - uint32_t destruction_count = ev->destruction_count; - int timeout = -1; - - if (tvalp) { - timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); - } - - ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); - - if (ret == -1 && errno != EINTR) { - epoll_fallback_to_select(ev, "epoll_wait() failed"); - return -1; - } - - if (ret == 0 && tvalp) { - event_loop_timer(ev); - return 0; - } - - for (i=0;ihandler(ev, fde, flags, fde->private); - if (destruction_count != ev->destruction_count) { - break; - } - } - } - - return 0; -} -#endif - -/* - event loop handling using select() -*/ -static int event_loop_select(struct event_context *ev, struct timeval *tvalp) -{ - fd_set r_fds, w_fds; - int selrtn; - uint32_t destruction_count = ev->destruction_count; - struct fd_event *fe; - - /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { - calc_maxfd(ev); - } - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - - /* setup any fd events */ - for (fe=ev->fd_events; fe; ) { - struct fd_event *next = fe->next; - if (fe->flags & EVENT_FD_READ) { - FD_SET(fe->fd, &r_fds); - } - if (fe->flags & EVENT_FD_WRITE) { - FD_SET(fe->fd, &w_fds); - } - fe = next; - } - - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); - - if (selrtn == -1 && errno == EBADF) { - /* the socket is dead! this should never - happen as the socket should have first been - made readable and that should have removed - the event, so this must be a bug. This is a - fatal error. */ - DEBUG(0,("ERROR: EBADF on event_loop_once\n")); - ev->exit_code = EBADF; - return -1; - } - - if (selrtn == 0 && tvalp) { - event_loop_timer(ev); - return 0; - } - - if (selrtn > 0) { - /* at least one file descriptor is ready - check - which ones and call the handler, being careful to allow - the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { - uint16_t flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; - if (flags) { - fe->handler(ev, fe, flags, fe->private); - if (destruction_count != ev->destruction_count) { - break; - } - } - } - } - - return 0; -} - -/* - do a single event loop using the events defined in ev -*/ -int event_loop_once(struct event_context *ev) -{ - struct timeval tval, *tvalp; - - tvalp = NULL; - - /* work out the right timeout for all timed events */ - if (ev->timed_events) { - struct timeval t = timeval_current(); - tval = timeval_diff(&ev->timed_events->next_event, &t); - tvalp = &tval; - if (timeval_is_zero(tvalp)) { - event_loop_timer(ev); - return 0; - } - } - -#if WITH_EPOLL - if (ev->epoll_fd != -1) { - if (event_loop_epoll(ev, tvalp) == 0) { - return 0; - } - } -#endif - - return event_loop_select(ev, tvalp); -} - -/* - go into an event loop using the events defined in ev this function - will return with the specified code if one of the handlers calls - event_loop_exit() - - also return (with code 0) if all fd events are removed -*/ -int event_loop_wait(struct event_context *ev) -{ - ev->exit_code = 0; - ev->maxfd = EVENT_INVALID_MAXFD; - - while (ev->fd_events && ev->exit_code == 0) { - if (event_loop_once(ev) != 0) { - break; - } - } - - return ev->exit_code; -} diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c new file mode 100644 index 0000000000..9783603759 --- /dev/null +++ b/source4/lib/events/events_standard.c @@ -0,0 +1,540 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 2 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. They are single shot - add a new timed event in the event + handler to get another event. + + To setup a set of events you first need to create a event_context + structure using the function event_context_init(); This returns a + 'struct event_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using event_add_*() and talloc_free() + + Finally, you call event_loop_wait() to block waiting for one of the + events to occor. In normal operation event_loop_wait() will loop + forever. + +*/ + +#include "includes.h" +#include "system/time.h" +#include "system/select.h" +#include "system/filesys.h" +#include "dlinklist.h" +#include "lib/events/events.h" + +/* use epoll if it is available */ +#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) +#define WITH_EPOLL 1 +#endif + +#if WITH_EPOLL +#include +#endif + +struct event_context { + /* list of filedescriptor events */ + struct fd_event { + struct event_context *event_ctx; + struct fd_event *next, *prev; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + void *private; + } *fd_events; + + /* list of timed events */ + struct timed_event { + struct event_context *event_ctx; + struct timed_event *next, *prev; + struct timeval next_event; + event_timed_handler_t handler; + void *private; + } *timed_events; + + /* the maximum file descriptor number in fd_events */ + int maxfd; + + /* information for exiting from the event loop */ + int exit_code; + + /* this is changed by the destructors for the fd event + type. It is used to detect event destruction by event + handlers, which means the code that is calling the event + handler needs to assume that the linked list is no longer + valid + */ + uint32_t destruction_count; + +#if WITH_EPOLL + /* when using epoll this is the handle from epoll_create */ + int epoll_fd; +#endif +}; + + +/* + destroy an event context +*/ +static int event_context_destructor(void *ptr) +{ +#if WITH_EPOLL + struct event_context *ev = talloc_get_type(ptr, struct event_context); + if (ev->epoll_fd != -1) { + close(ev->epoll_fd); + ev->epoll_fd = -1; + } +#endif + return 0; +} + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct event_context *event_context_init(TALLOC_CTX *mem_ctx) +{ + struct event_context *ev; + + ev = talloc_zero(mem_ctx, struct event_context); + if (!ev) return NULL; + +#if WITH_EPOLL + ev->epoll_fd = epoll_create(64); +#endif + + talloc_set_destructor(ev, event_context_destructor); + + return ev; +} + + +/* + recalculate the maxfd +*/ +static void calc_maxfd(struct event_context *ev) +{ + struct fd_event *e; + ev->maxfd = 0; + for (e=ev->fd_events; e; e=e->next) { + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + } +} + + +/* to mark the ev->maxfd invalid + * this means we need to recalculate it + */ +#define EVENT_INVALID_MAXFD (-1) + + +#if WITH_EPOLL +/* + called when a epoll call fails, and we should fallback + to using select +*/ +static void epoll_fallback_to_select(struct event_context *ev, const char *reason) +{ + DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno))); + close(ev->epoll_fd); + ev->epoll_fd = -1; +} +#endif + + +#if WITH_EPOLL +/* + map from EVENT_FD_* to EPOLLIN/EPOLLOUT +*/ +static uint32_t epoll_map_flags(uint16_t flags) +{ + uint32_t ret = 0; + if (flags & EVENT_FD_READ) ret |= EPOLLIN; + if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT; + return ret; +} +#endif + +/* + destroy an fd_event +*/ +static int event_fd_destructor(void *ptr) +{ + struct fd_event *fde = talloc_get_type(ptr, struct fd_event); + struct event_context *ev = fde->event_ctx; + + if (ev->maxfd == fde->fd) { + ev->maxfd = EVENT_INVALID_MAXFD; + } + DLIST_REMOVE(ev->fd_events, fde); + ev->destruction_count++; +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(fde->flags); + event.data.ptr = fde; + epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); + } +#endif + return 0; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private) +{ + struct fd_event *e = talloc(ev, struct fd_event); + if (!e) return NULL; + + e->event_ctx = ev; + e->fd = fd; + e->flags = flags; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->fd_events, e); + + if (e->fd > ev->maxfd) { + ev->maxfd = e->fd; + } + + talloc_set_destructor(e, event_fd_destructor); + if (mem_ctx) { + talloc_steal(mem_ctx, e); + } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = e; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); + } + } +#endif + + return e; +} + + +/* + return the fd event flags +*/ +uint16_t event_fd_flags(struct fd_event *fde) +{ + return fde?fde->flags:0; +} + +/* + set the fd event flags +*/ +void event_fd_setflags(struct fd_event *fde, uint16_t flags) +{ +#if WITH_EPOLL + struct event_context *ev; + if (fde == NULL || + fde->flags == flags) { + return; + } + ev = fde->event_ctx; + if (ev->epoll_fd != -1) { + struct epoll_event event; + ZERO_STRUCT(event); + event.events = epoll_map_flags(flags); + event.data.ptr = fde; + if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { + epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); + } + } +#endif + if (fde) { + fde->flags = flags; + } +} + +/* + destroy a timed event +*/ +static int event_timed_destructor(void *ptr) +{ + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + DLIST_REMOVE(te->event_ctx->timed_events, te); + return 0; +} + +/* + add a timed event + return NULL on failure (memory allocation error) +*/ +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private) +{ + struct timed_event *te, *e; + + e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); + if (e == NULL) return NULL; + + e->event_ctx = ev; + e->next_event = next_event; + e->handler = handler; + e->private = private; + + /* keep the list ordered */ + if (ev->timed_events == NULL || + timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { + DLIST_ADD(ev->timed_events, e); + } else { + for (te=ev->timed_events;te && te->next;te=te->next) { + if (!timeval_is_zero(&te->next->next_event) && + timeval_compare(&te->next->next_event, &e->next_event) < 0) { + break; + } + } + DLIST_ADD_AFTER(ev->timed_events, e, te); + } + + talloc_set_destructor(e, event_timed_destructor); + + return e; +} + +/* + a timer has gone off - call it +*/ +static void event_loop_timer(struct event_context *ev) +{ + struct timeval t = timeval_current(); + struct timed_event *te = ev->timed_events; + + te->next_event = timeval_zero(); + + te->handler(ev, te, t, te->private); + + /* note the care taken to prevent referencing a event + that could have been freed by the handler */ + if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { + talloc_free(ev->timed_events); + } +} + +#if WITH_EPOLL +/* + event loop handling using epoll +*/ +static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) +{ + int ret, i; + const int maxevents = 8; + struct epoll_event events[maxevents]; + uint32_t destruction_count = ev->destruction_count; + int timeout = -1; + + if (tvalp) { + timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); + } + + ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); + + if (ret == -1 && errno != EINTR) { + epoll_fallback_to_select(ev, "epoll_wait() failed"); + return -1; + } + + if (ret == 0 && tvalp) { + event_loop_timer(ev); + return 0; + } + + for (i=0;ihandler(ev, fde, flags, fde->private); + if (destruction_count != ev->destruction_count) { + break; + } + } + } + + return 0; +} +#endif + +/* + event loop handling using select() +*/ +static int event_loop_select(struct event_context *ev, struct timeval *tvalp) +{ + fd_set r_fds, w_fds; + int selrtn; + uint32_t destruction_count = ev->destruction_count; + struct fd_event *fe; + + /* we maybe need to recalculate the maxfd */ + if (ev->maxfd == EVENT_INVALID_MAXFD) { + calc_maxfd(ev); + } + + FD_ZERO(&r_fds); + FD_ZERO(&w_fds); + + /* setup any fd events */ + for (fe=ev->fd_events; fe; ) { + struct fd_event *next = fe->next; + if (fe->flags & EVENT_FD_READ) { + FD_SET(fe->fd, &r_fds); + } + if (fe->flags & EVENT_FD_WRITE) { + FD_SET(fe->fd, &w_fds); + } + fe = next; + } + + selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + + if (selrtn == -1 && errno == EBADF) { + /* the socket is dead! this should never + happen as the socket should have first been + made readable and that should have removed + the event, so this must be a bug. This is a + fatal error. */ + DEBUG(0,("ERROR: EBADF on event_loop_once\n")); + ev->exit_code = EBADF; + return -1; + } + + if (selrtn == 0 && tvalp) { + event_loop_timer(ev); + return 0; + } + + if (selrtn > 0) { + /* at least one file descriptor is ready - check + which ones and call the handler, being careful to allow + the handler to remove itself when called */ + for (fe=ev->fd_events; fe; fe=fe->next) { + uint16_t flags = 0; + if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + if (flags) { + fe->handler(ev, fe, flags, fe->private); + if (destruction_count != ev->destruction_count) { + break; + } + } + } + } + + return 0; +} + +/* + do a single event loop using the events defined in ev +*/ +int event_loop_once(struct event_context *ev) +{ + struct timeval tval, *tvalp; + + tvalp = NULL; + + /* work out the right timeout for all timed events */ + if (ev->timed_events) { + struct timeval t = timeval_current(); + tval = timeval_diff(&ev->timed_events->next_event, &t); + tvalp = &tval; + if (timeval_is_zero(tvalp)) { + event_loop_timer(ev); + return 0; + } + } + +#if WITH_EPOLL + if (ev->epoll_fd != -1) { + if (event_loop_epoll(ev, tvalp) == 0) { + return 0; + } + } +#endif + + return event_loop_select(ev, tvalp); +} + +/* + go into an event loop using the events defined in ev this function + will return with the specified code if one of the handlers calls + event_loop_exit() + + also return (with code 0) if all fd events are removed +*/ +int event_loop_wait(struct event_context *ev) +{ + ev->exit_code = 0; + ev->maxfd = EVENT_INVALID_MAXFD; + + while (ev->fd_events && ev->exit_code == 0) { + if (event_loop_once(ev) != 0) { + break; + } + } + + return ev->exit_code; +} -- cgit From 5a88d5211ba0f6b1d09cdd92489b34d0e603716b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 13 Feb 2005 12:27:57 +0000 Subject: r5374: - changed the dn key code in the ldb tdb backend to correctly honor the case sensitive/insensitive flags on sections of a dn. So if a dn is made up of 4 attributes, and 2 of those are case insensitive and 2 are case sensitive, then all the attribute names are uppercases, but only the values of the case insensitive attributes are uppercased when forming the tdb key. - added code to canonicalise the dn, removing leading and trailing spaces from attribute names and values - when the @ATTRIBUTES record changes, fix the dn keys of any records that should now have new dn keys due to changes in the case sensitivity of the record I really did this to allow me to make the WINS database properly case insensitive, but it is also the correct general fix for ldb, as it matches the LDAP specification (and w2k LDAP server behaviour) (This used to be commit 0f034dc5636d182a1d9207ad662b3fc8df7ca3e4) --- source4/lib/ldb/include/ldb.h | 9 ++-- source4/lib/ldb/ldb_tdb/ldb_index.c | 10 ++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 81 ++++++++++++++++++++++++++++++++- source4/lib/ldb/tests/test-attribs.ldif | 2 + 4 files changed, 96 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index c6f96f6dea..09b4cbf84a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -140,6 +140,11 @@ struct ldb_debug_ops { #define LDB_FLG_RDONLY 1 +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a,b) +#endif + + /* connect to a database. The URL can either be one of the following forms ldb://path @@ -302,10 +307,6 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v); -#ifndef PRINTF_ATTRIBUTE -#define PRINTF_ATTRIBUTE(a,b) -#endif - /* this allows the user to set a debug function for error reporting */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index c7dc9f1345..1cf1b5c531 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -935,6 +935,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * struct ldb_module *module = state; struct ldb_message *msg; int ret; + TDB_DATA key2; if (strncmp(key.dptr, "DN=@", 4) == 0 || strncmp(key.dptr, "DN=", 3) != 0) { @@ -952,6 +953,15 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return -1; } + /* check if the DN key has changed, perhaps due to the + case insensitivity of an element changing */ + key2 = ltdb_key(module, msg->dn); + if (strcmp(key2.dptr, key.dptr) != 0) { + tdb_delete(tdb, key); + tdb_store(tdb, key2, data, 0); + } + talloc_free(key2.dptr); + if (!msg->dn) { msg->dn = key.dptr+3; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index b1de96986d..07a9fa8866 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -42,6 +42,82 @@ #define LDBLOCK "INT_LDBLOCK" + +/* + casefold a dn. We need to uppercase the attribute names, and the + attribute values of case insensitive attributes. We also need to remove + extraneous spaces between elements +*/ +static char *ltdb_dn_fold(struct ldb_module *module, const char *dn) +{ + const char *dn_orig = dn; + struct ldb_context *ldb = module->ldb; + TALLOC_CTX *tmp_ctx = talloc_new(ldb); + char *ret; + size_t len; + + ret = talloc_strdup(tmp_ctx, ""); + if (ret == NULL) goto failed; + + while ((len = strcspn(dn, ",")) > 0) { + char *p = strchr(dn, '='); + char *attr, *value; + int flags; + + if (p == NULL || (p-dn) > len) goto failed; + + attr = talloc_strndup(tmp_ctx, dn, p-dn); + if (attr == NULL) goto failed; + + /* trim spaces from the attribute name */ + while (' ' == *attr) attr++; + while (' ' == attr[strlen(attr)-1]) { + attr[strlen(attr)-1] = 0; + } + if (*attr == 0) goto failed; + + value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn)); + if (value == NULL) goto failed; + + /* trim spaces from the value */ + while (' ' == *value) value++; + while (' ' == value[strlen(value)-1]) { + value[strlen(value)-1] = 0; + } + if (*value == 0) goto failed; + + flags = ltdb_attribute_flags(module, attr); + + attr = ldb_casefold(ldb, attr); + if (attr == NULL) goto failed; + talloc_steal(tmp_ctx, attr); + + if (flags & LTDB_FLAG_CASE_INSENSITIVE) { + value = ldb_casefold(ldb, value); + if (value == NULL) goto failed; + talloc_steal(tmp_ctx, value); + } + + if (dn[len] == ',') { + ret = talloc_asprintf_append(ret, "%s=%s,", attr, value); + } else { + ret = talloc_asprintf_append(ret, "%s=%s", attr, value); + } + if (ret == NULL) goto failed; + + dn += len; + if (*dn == ',') dn++; + } + + talloc_steal(ldb, ret); + talloc_free(tmp_ctx); + return ret; + +failed: + talloc_free(tmp_ctx); + return ldb_casefold(ldb, dn_orig); +} + /* form a TDB_DATA for a record key caller frees @@ -65,7 +141,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) there are 3 cases dealt with in this code: - 1) if the dn doesn't start with @INDEX: then uppercase whole dn + 1) if the dn doesn't start with @INDEX: then uppercase the attribute + names and the attributes values of case insensitive attributes 2) if the dn starts with @INDEX:attr and 'attr' is a case insensitive attribute then uppercase whole dn 3) if the dn starts with @INDEX:attr and 'attr' is a case sensitive @@ -95,7 +172,7 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) } talloc_free(attr_name); } else { - dn_folded = ldb_casefold(ldb, dn); + dn_folded = ltdb_dn_fold(module, dn); } if (!dn_folded) { diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif index bfa51b05fa..4bfb1ebd65 100644 --- a/source4/lib/ldb/tests/test-attribs.ldif +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -1,5 +1,7 @@ dn: @ATTRIBUTES uid: CASE_INSENSITIVE WILDCARD +cn: CASE_INSENSITIVE +ou: CASE_INSENSITIVE dn: CASE_INSENSITIVE dn: @SUBCLASSES -- cgit From 352de700cadbb2c4e5b5e9ddc375e9de847e2193 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 14 Feb 2005 09:15:24 +0000 Subject: r5392: added "secure" WINS server processing. Send a WACK on name registrations from anyone who isn't a current owner, then query the owner addresses to see if they still want it. (This used to be commit 8dc2a028d3ca0115d3173df435d926d7b6a4d5d5) --- source4/lib/util_strlist.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 71f634f71a..0b78e9f69e 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -122,3 +122,54 @@ BOOL str_list_equal(const char **list1, const char **list2) } return True; } + + +/* + add an entry to a string list +*/ +const char **str_list_add(const char **list, const char *s) +{ + size_t len = str_list_length(list); + const char **ret; + + ret = talloc_realloc(NULL, list, const char *, len+2); + if (ret == NULL) return NULL; + + ret[len] = talloc_strdup(ret, s); + if (ret[len] == NULL) return NULL; + + ret[len+1] = NULL; + + return ret; +} + +/* + remove an entry from a string list +*/ +void str_list_remove(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcmp(list[i], s) == 0) break; + } + if (!list[i]) return; + + for (;list[i];i++) { + list[i] = list[i+1]; + } +} + + +/* + return True if a string is in a list +*/ +BOOL str_list_check(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcmp(list[i], s) == 0) return True; + } + return False; +} -- cgit From c29141f10bba7024fb2630b3e4c7f658bbf472be Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 14 Feb 2005 09:43:36 +0000 Subject: r5393: trigger timed events not to early, better do it a bit to late metze (This used to be commit 67bf637e9a44202061fd71c92142f835ba76da89) --- source4/lib/events/events_standard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 9783603759..77797eec64 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -380,7 +380,8 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) int timeout = -1; if (tvalp) { - timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000); + /* it's better to trigger timed events a bit later than to early */ + timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); } ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); -- cgit From 4d980e56c48e07468496809169aa289f60672562 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 15 Feb 2005 02:24:57 +0000 Subject: r5401: using talloc_array() is neater here (This used to be commit b35ee83536e01c000aace2f4764f6727efd63170) --- source4/lib/util_strlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 0b78e9f69e..3b949f6eef 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -34,7 +34,7 @@ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char * sep = LIST_SEP; } - ret = talloc_realloc(mem_ctx, NULL, const char *, 1); + ret = talloc_array(mem_ctx, const char *, 1); if (ret == NULL) { return NULL; } -- cgit From 6d17fc3b3e09b15c4a0fa4595ca8d60f426f0243 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Feb 2005 10:36:59 +0000 Subject: r5407: - this patch makes samba's event loop code more generic and makes using other implementations possible. This will be mostly usefull for client apps which have there own event loop and want to use our client libs - add a example plugin for liboop (see http://liboop.org) NOTE: this just compiles and is completly untested and is commited only as example metze (This used to be commit b3d0a410efe856e3bcf127f00c31905f5a23cc04) --- source4/lib/events/config.mk | 3 +- source4/lib/events/events.c | 155 +++++++++++++++ source4/lib/events/events.h | 15 +- source4/lib/events/events_internal.h | 80 ++++++++ source4/lib/events/events_liboop.c | 273 ++++++++++++++++++++++++++ source4/lib/events/events_standard.c | 366 +++++++++++++++++------------------ 6 files changed, 701 insertions(+), 191 deletions(-) create mode 100644 source4/lib/events/events.c create mode 100644 source4/lib/events/events_internal.h create mode 100644 source4/lib/events/events_liboop.c (limited to 'source4/lib') diff --git a/source4/lib/events/config.mk b/source4/lib/events/config.mk index e1f9f589a1..4fe0856f88 100644 --- a/source4/lib/events/config.mk +++ b/source4/lib/events/config.mk @@ -2,7 +2,8 @@ # Start SUBSYSTEM LIBEVENTS [SUBSYSTEM::LIBEVENTS] NOPROTO = YES -INIT_OBJ_FILES = lib/events/events_standard.o +INIT_OBJ_FILES = lib/events/events.o +ADD_OBJ_FILES = lib/events/events_standard.o REQUIRED_SUBSYSTEMS = LIBTALLOC # End SUBSYSTEM LIBEVENTS ############################## diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c new file mode 100644 index 0000000000..83b013f366 --- /dev/null +++ b/source4/lib/events/events.c @@ -0,0 +1,155 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 2 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. They are single shot - add a new timed event in the event + handler to get another event. + + To setup a set of events you first need to create a event_context + structure using the function event_context_init(); This returns a + 'struct event_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using event_add_*() and talloc_free() + + Finally, you call event_loop_wait_once() to block waiting for one of the + events to occor or event_loop_wait() which will loop + forever. + +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "lib/events/events_internal.h" + +/* + create a event_context structure for a specific implemementation. + This must be the first events call, and all subsequent calls pass + this event_context as the first element. Event handlers also + receive this as their first argument. + + This function is for allowing third-party-applications to hook in gluecode + to their own event loop code, so that they can make async usage of our client libs + + NOTE: use event_context_init() inside of samba! +*/ +struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx, const struct event_ops *ops, void *private_data) +{ + struct event_context *ev; + int ret; + + ev = talloc_zero(mem_ctx, struct event_context); + if (!ev) return NULL; + + ev->ops = ops; + + ret = ev->ops->context_init(ev, private_data); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + + return ev; +} + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct event_context *event_context_init(TALLOC_CTX *mem_ctx) +{ + const struct event_ops *ops = event_standard_get_ops(); + return event_context_init_ops(mem_ctx, ops, NULL); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private_data) +{ + return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data); +} + +/* + return the fd event flags +*/ +uint16_t event_get_fd_flags(struct fd_event *fde) +{ + return fde->event_ctx->ops->get_fd_flags(fde); +} + +/* + set the fd event flags +*/ +void event_set_fd_flags(struct fd_event *fde, uint16_t flags) +{ + fde->event_ctx->ops->set_fd_flags(fde, flags); +} + +/* + add a timed event + return NULL on failure +*/ +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private_data) +{ + return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data); +} + +/* + do a single event loop using the events defined in ev +*/ +int event_loop_once(struct event_context *ev) +{ + return ev->ops->loop_once(ev); +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +int event_loop_wait(struct event_context *ev) +{ + return ev->ops->loop_wait(ev); +} diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h index e3973c3c48..6994f6a124 100644 --- a/source4/lib/events/events.h +++ b/source4/lib/events/events.h @@ -21,6 +21,7 @@ */ struct event_context; +struct event_ops; struct fd_event; struct timed_event; @@ -31,6 +32,7 @@ typedef void (*event_timed_handler_t)(struct event_context *, struct timed_event struct timeval , void *); struct event_context *event_context_init(TALLOC_CTX *mem_ctx); +struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx, const struct event_ops *ops, void *private_data); struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, int fd, uint16_t flags, event_fd_handler_t handler, @@ -44,20 +46,19 @@ struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ct int event_loop_once(struct event_context *ev); int event_loop_wait(struct event_context *ev); -uint16_t event_fd_flags(struct fd_event *fde); -void event_fd_setflags(struct fd_event *fde, uint16_t flags); +uint16_t event_get_fd_flags(struct fd_event *fde); +void event_set_fd_flags(struct fd_event *fde, uint16_t flags); /* bits for file descriptor event flags */ #define EVENT_FD_READ 1 #define EVENT_FD_WRITE 2 #define EVENT_FD_WRITEABLE(fde) \ - event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_WRITE) + event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE) #define EVENT_FD_READABLE(fde) \ - event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_READ) + event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ) #define EVENT_FD_NOT_WRITEABLE(fde) \ - event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE) + event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) #define EVENT_FD_NOT_READABLE(fde) \ - event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE) - + event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) diff --git a/source4/lib/events/events_internal.h b/source4/lib/events/events_internal.h new file mode 100644 index 0000000000..9fc5a2065f --- /dev/null +++ b/source4/lib/events/events_internal.h @@ -0,0 +1,80 @@ +/* + Unix SMB/CIFS implementation. + + generalised event loop handling + + Internal structs + + Copyright (C) Stefan Metzmacher 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct event_ops { + /* conntext init */ + int (*context_init)(struct event_context *ev, void *private_data); + + /* fd_event functions */ + struct fd_event *(*add_fd)(struct event_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + event_fd_handler_t handler, + void *private_data); + uint16_t (*get_fd_flags)(struct fd_event *fde); + void (*set_fd_flags)(struct fd_event *fde, uint16_t flags); + + /* timed_event functions */ + struct timed_event *(*add_timed)(struct event_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private_data); + + /* loop functions */ + int (*loop_once)(struct event_context *ev); + int (*loop_wait)(struct event_context *ev); +}; + +struct fd_event { + struct fd_event *prev, *next; + struct event_context *event_ctx; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is private for the events_ops implementation */ + void *additional_data; +}; + +struct timed_event { + struct timed_event *prev, *next; + struct event_context *event_ctx; + struct timeval next_event; + event_timed_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is private for the events_ops implementation */ + void *additional_data; +}; + +struct event_context { + /* the specific events implementation */ + const struct event_ops *ops; + /* this is private for the events_ops implementation */ + void *additional_data; +}; + +const struct event_ops *event_standard_get_ops(void); diff --git a/source4/lib/events/events_liboop.c b/source4/lib/events/events_liboop.c new file mode 100644 index 0000000000..ad7c43cd4e --- /dev/null +++ b/source4/lib/events/events_liboop.c @@ -0,0 +1,273 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + wrapper for http://liboop.org/ + + Copyright (C) Stefan Metzmacher 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* NOTE: this code compiles fine, but is completly *UNTESTED* + and is only commited as example +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "lib/events/events_internal.h" + +#include + +static int oop_event_context_destructor(void *ptr) +{ + struct event_context *ev = talloc_get_type(ptr, struct event_context); + oop_source_sys *oop_sys = ev->additional_data; + + oop_sys_delete(oop_sys); + + return 0; +} + +/* + create a oop_event_context structure. +*/ +static int oop_event_context_init(struct event_context *ev, void *private_data) +{ + oop_source_sys *oop_sys = private_data; + + if (!oop_sys) { + oop_sys = oop_sys_new(); + if (!oop_sys) { + return -1; + } + + talloc_set_destructor(ev, oop_event_context_destructor); + } + + ev->additional_data = oop_sys; + + return 0; +} + +static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr) +{ + struct fd_event *fde = ptr; + + if (fd != fde->fd) return OOP_ERROR; + + switch(oop_type) { + case OOP_READ: + fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data); + return OOP_CONTINUE; + case OOP_WRITE: + fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data); + return OOP_CONTINUE; + case OOP_EXCEPTION: + return OOP_ERROR; + case OOP_NUM_EVENTS: + return OOP_ERROR; + } + + return OOP_ERROR; +} + +/* + destroy an fd_event +*/ +static int oop_event_fd_destructor(void *ptr) +{ + struct fd_event *fde = talloc_get_type(ptr, struct fd_event); + struct event_context *ev = fde->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + if (fde->flags & EVENT_FD_READ) + oop->cancel_fd(oop, fde->fd, OOP_READ); + if (fde->flags & EVENT_FD_WRITE) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + return 0; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct fd_event *oop_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + event_fd_handler_t handler, + void *private_data) +{ + struct fd_event *fde; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event); + if (!fde) return NULL; + + fde->event_ctx = ev; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->private_data = private_data; + fde->additional_data = NULL; + + if (fde->flags & EVENT_FD_READ) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + if (fde->flags & EVENT_FD_WRITE) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + talloc_set_destructor(fde, oop_event_fd_destructor); + + return fde; +} + +/* + return the fd event flags +*/ +static uint16_t oop_event_get_fd_flags(struct fd_event *fde) +{ + if (!fde) return 0; + + return fde->flags; +} + +/* + set the fd event flags +*/ +static void oop_event_set_fd_flags(struct fd_event *fde, uint16_t flags) +{ + oop_source_sys *oop_sys; + oop_source *oop; + + if (!fde) return; + + oop_sys = fde->event_ctx->additional_data; + oop = oop_sys_source(oop_sys); + + if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ))) + oop->cancel_fd(oop, fde->fd, OOP_READ); + + if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ)) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + + if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE))) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE)) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + fde->flags = flags; +} + +static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr) +{ + struct timed_event *te = ptr; + + te->handler(te->event_ctx, te, t, te->private_data); + + return OOP_CONTINUE; +} + +/* + destroy a timed event +*/ +static int oop_event_timed_destructor(void *ptr) +{ + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + struct event_context *ev = te->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); + + return 0; +} + +/* + add a timed event + return NULL on failure (memory allocation error) +*/ +static struct timed_event *oop_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private_data) +{ + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + struct timed_event *te; + + te = talloc(mem_ctx?mem_ctx:ev, struct timed_event); + if (te == NULL) return NULL; + + te->event_ctx = ev; + te->next_event = next_event; + te->handler = handler; + te->private_data = private_data; + te->additional_data = NULL; + + oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); + + talloc_set_destructor(te, oop_event_timed_destructor); + + return te; +} + +/* + do a single event loop using the events defined in ev +*/ +static int oop_event_loop_once(struct event_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run_once(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +static int oop_event_loop_wait(struct event_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +static const struct event_ops events_oop_ops = { + .context_init = oop_event_context_init, + .add_fd = oop_event_add_fd, + .get_fd_flags = oop_event_get_fd_flags, + .set_fd_flags = oop_event_set_fd_flags, + .add_timed = oop_event_add_timed, + .loop_once = oop_event_loop_once, + .loop_wait = oop_event_loop_wait, +}; + +const struct event_ops *events_oop_get_ops(void) +{ + return &events_oop_ops; +} diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 77797eec64..96f938c78e 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. main select loop and event handling - Copyright (C) Andrew Tridgell 2003 + Copyright (C) Andrew Tridgell 2003-2005 + Copyright (C) Stefan Metzmacher 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 @@ -19,47 +20,19 @@ */ /* - PLEASE READ THIS BEFORE MODIFYING! - - This module is a general abstraction for the main select loop and - event handling. Do not ever put any localised hacks in here, instead - register one of the possible event types and implement that event - somewhere else. - - There are 2 types of event handling that are handled in this module: - - 1) a file descriptor becoming readable or writeable. This is mostly - used for network sockets, but can be used for any type of file - descriptor. You may only register one handler for each file - descriptor/io combination or you will get unpredictable results - (this means that you can have a handler for read events, and a - separate handler for write events, but not two handlers that are - both handling read events) - - 2) a timed event. You can register an event that happens at a - specific time. You can register as many of these as you - like. They are single shot - add a new timed event in the event - handler to get another event. - - To setup a set of events you first need to create a event_context - structure using the function event_context_init(); This returns a - 'struct event_context' that you use in all subsequent calls. - - After that you can add/remove events that you are interested in - using event_add_*() and talloc_free() - - Finally, you call event_loop_wait() to block waiting for one of the - events to occor. In normal operation event_loop_wait() will loop - forever. + This is SAMBA's default event loop code + - we try to use epoll if configure detected support for it + otherwise we use select() + - if epoll is broken on the system or the kernel doesn't support it + at runtime we fallback to select() */ #include "includes.h" -#include "system/time.h" -#include "system/select.h" #include "system/filesys.h" #include "dlinklist.h" #include "lib/events/events.h" +#include "lib/events/events_internal.h" /* use epoll if it is available */ #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H) @@ -70,25 +43,12 @@ #include #endif -struct event_context { +struct std_event_context { /* list of filedescriptor events */ - struct fd_event { - struct event_context *event_ctx; - struct fd_event *next, *prev; - int fd; - uint16_t flags; /* see EVENT_FD_* flags */ - event_fd_handler_t handler; - void *private; - } *fd_events; + struct fd_event *fd_events; /* list of timed events */ - struct timed_event { - struct event_context *event_ctx; - struct timed_event *next, *prev; - struct timeval next_event; - event_timed_handler_t handler; - void *private; - } *timed_events; + struct timed_event *timed_events; /* the maximum file descriptor number in fd_events */ int maxfd; @@ -110,54 +70,57 @@ struct event_context { #endif }; - /* destroy an event context */ -static int event_context_destructor(void *ptr) +static int std_event_context_destructor(void *ptr) { #if WITH_EPOLL struct event_context *ev = talloc_get_type(ptr, struct event_context); - if (ev->epoll_fd != -1) { - close(ev->epoll_fd); - ev->epoll_fd = -1; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); + if (std_ev->epoll_fd != -1) { + close(std_ev->epoll_fd); + std_ev->epoll_fd = -1; } #endif return 0; } /* - create a event_context structure. This must be the first events - call, and all subsequent calls pass this event_context as the first - element. Event handlers also receive this as their first argument. + create a std_event_context structure. */ -struct event_context *event_context_init(TALLOC_CTX *mem_ctx) +static int std_event_context_init(struct event_context *ev, void *privata_data) { - struct event_context *ev; + struct std_event_context *std_ev; - ev = talloc_zero(mem_ctx, struct event_context); - if (!ev) return NULL; + std_ev = talloc_zero(ev, struct std_event_context); + if (!std_ev) return -1; #if WITH_EPOLL - ev->epoll_fd = epoll_create(64); + std_ev->epoll_fd = epoll_create(64); #endif - talloc_set_destructor(ev, event_context_destructor); + ev->additional_data = std_ev; - return ev; -} + talloc_set_destructor(ev, std_event_context_destructor); + return 0; +} /* recalculate the maxfd */ static void calc_maxfd(struct event_context *ev) { - struct fd_event *e; - ev->maxfd = 0; - for (e=ev->fd_events; e; e=e->next) { - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); + struct fd_event *fde; + + std_ev->maxfd = 0; + for (fde = std_ev->fd_events; fde; fde = fde->next) { + if (fde->fd > std_ev->maxfd) { + std_ev->maxfd = fde->fd; } } } @@ -176,9 +139,11 @@ static void calc_maxfd(struct event_context *ev) */ static void epoll_fallback_to_select(struct event_context *ev, const char *reason) { + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno))); - close(ev->epoll_fd); - ev->epoll_fd = -1; + close(std_ev->epoll_fd); + std_ev->epoll_fd = -1; } #endif @@ -199,23 +164,25 @@ static uint32_t epoll_map_flags(uint16_t flags) /* destroy an fd_event */ -static int event_fd_destructor(void *ptr) +static int std_event_fd_destructor(void *ptr) { struct fd_event *fde = talloc_get_type(ptr, struct fd_event); struct event_context *ev = fde->event_ctx; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); - if (ev->maxfd == fde->fd) { - ev->maxfd = EVENT_INVALID_MAXFD; + if (std_ev->maxfd == fde->fd) { + std_ev->maxfd = EVENT_INVALID_MAXFD; } - DLIST_REMOVE(ev->fd_events, fde); - ev->destruction_count++; + DLIST_REMOVE(std_ev->fd_events, fde); + std_ev->destruction_count++; #if WITH_EPOLL - if (ev->epoll_fd != -1) { + if (std_ev->epoll_fd != -1) { struct epoll_event event; ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; - epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); + epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); } #endif return 0; @@ -225,50 +192,53 @@ static int event_fd_destructor(void *ptr) add a fd based event return NULL on failure (memory allocation error) */ -struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, - int fd, uint16_t flags, event_fd_handler_t handler, - void *private) +static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + event_fd_handler_t handler, + void *private_data) { - struct fd_event *e = talloc(ev, struct fd_event); - if (!e) return NULL; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); + struct fd_event *fde; - e->event_ctx = ev; - e->fd = fd; - e->flags = flags; - e->handler = handler; - e->private = private; + fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event); + if (!fde) return NULL; - DLIST_ADD(ev->fd_events, e); + fde->event_ctx = ev; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->private_data = private_data; + fde->additional_data = NULL; - if (e->fd > ev->maxfd) { - ev->maxfd = e->fd; - } + DLIST_ADD(std_ev->fd_events, fde); - talloc_set_destructor(e, event_fd_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); + if (fde->fd > std_ev->maxfd) { + std_ev->maxfd = fde->fd; } + talloc_set_destructor(fde, std_event_fd_destructor); + #if WITH_EPOLL - if (ev->epoll_fd != -1) { + if (std_ev->epoll_fd != -1) { struct epoll_event event; ZERO_STRUCT(event); event.events = epoll_map_flags(flags); - event.data.ptr = e; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) { + event.data.ptr = fde; + if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) { epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed"); } } #endif - return e; + return fde; } /* return the fd event flags */ -uint16_t event_fd_flags(struct fd_event *fde) +static uint16_t std_event_get_fd_flags(struct fd_event *fde) { return fde?fde->flags:0; } @@ -276,21 +246,23 @@ uint16_t event_fd_flags(struct fd_event *fde) /* set the fd event flags */ -void event_fd_setflags(struct fd_event *fde, uint16_t flags) +static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags) { #if WITH_EPOLL struct event_context *ev; + struct std_event_context *std_ev; if (fde == NULL || fde->flags == flags) { return; } ev = fde->event_ctx; - if (ev->epoll_fd != -1) { + std_ev = talloc_get_type(ev->additional_data, struct std_event_context); + if (std_ev->epoll_fd != -1) { struct epoll_event event; ZERO_STRUCT(event); event.events = epoll_map_flags(flags); event.data.ptr = fde; - if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { + if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed"); } } @@ -303,10 +275,12 @@ void event_fd_setflags(struct fd_event *fde, uint16_t flags) /* destroy a timed event */ -static int event_timed_destructor(void *ptr) +static int std_event_timed_destructor(void *ptr) { struct timed_event *te = talloc_get_type(ptr, struct timed_event); - DLIST_REMOVE(te->event_ctx->timed_events, te); + struct std_event_context *std_ev = talloc_get_type(te->event_ctx->additional_data, + struct std_event_context); + DLIST_REMOVE(std_ev->timed_events, te); return 0; } @@ -314,56 +288,63 @@ static int event_timed_destructor(void *ptr) add a timed event return NULL on failure (memory allocation error) */ -struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, - struct timeval next_event, - event_timed_handler_t handler, - void *private) +static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private_data) { - struct timed_event *te, *e; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); + struct timed_event *te, *last_te, *cur_te; - e = talloc(mem_ctx?mem_ctx:ev, struct timed_event); - if (e == NULL) return NULL; + te = talloc(mem_ctx?mem_ctx:ev, struct timed_event); + if (te == NULL) return NULL; - e->event_ctx = ev; - e->next_event = next_event; - e->handler = handler; - e->private = private; + te->event_ctx = ev; + te->next_event = next_event; + te->handler = handler; + te->private_data = private_data; + te->additional_data = NULL; /* keep the list ordered */ - if (ev->timed_events == NULL || - timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) { - DLIST_ADD(ev->timed_events, e); - } else { - for (te=ev->timed_events;te && te->next;te=te->next) { - if (!timeval_is_zero(&te->next->next_event) && - timeval_compare(&te->next->next_event, &e->next_event) < 0) { - break; - } + last_te = NULL; + for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) { + /* if the new event comes before the current one break */ + if (!timeval_is_zero(&cur_te->next_event) && + timeval_compare(&cur_te->next_event, &te->next_event) < 0) { + break; } - DLIST_ADD_AFTER(ev->timed_events, e, te); + + last_te = cur_te; } - talloc_set_destructor(e, event_timed_destructor); + DLIST_ADD_AFTER(std_ev->timed_events, te, last_te); + + talloc_set_destructor(te, std_event_timed_destructor); - return e; + return te; } /* a timer has gone off - call it */ -static void event_loop_timer(struct event_context *ev) +static void std_event_loop_timer(struct event_context *ev) { + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); struct timeval t = timeval_current(); - struct timed_event *te = ev->timed_events; + struct timed_event *te = std_ev->timed_events; te->next_event = timeval_zero(); - te->handler(ev, te, t, te->private); + te->handler(ev, te, t, te->private_data); /* note the care taken to prevent referencing a event that could have been freed by the handler */ - if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) { - talloc_free(ev->timed_events); + if (std_ev->timed_events) { + if (timeval_is_zero(&std_ev->timed_events->next_event)) { + talloc_free(te); + } } } @@ -371,12 +352,14 @@ static void event_loop_timer(struct event_context *ev) /* event loop handling using epoll */ -static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) +static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp) { + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); int ret, i; const int maxevents = 8; struct epoll_event events[maxevents]; - uint32_t destruction_count = ev->destruction_count; + uint32_t destruction_count = std_ev->destruction_count; int timeout = -1; if (tvalp) { @@ -384,7 +367,7 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); } - ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout); + ret = epoll_wait(std_ev->epoll_fd, events, maxevents, timeout); if (ret == -1 && errno != EINTR) { epoll_fallback_to_select(ev, "epoll_wait() failed"); @@ -392,7 +375,7 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) } if (ret == 0 && tvalp) { - event_loop_timer(ev); + std_event_loop_timer(ev); return 0; } @@ -409,8 +392,8 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) flags |= EVENT_FD_READ; if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE; if (flags) { - fde->handler(ev, fde, flags, fde->private); - if (destruction_count != ev->destruction_count) { + fde->handler(ev, fde, flags, fde->private_data); + if (destruction_count != std_ev->destruction_count) { break; } } @@ -423,48 +406,48 @@ static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp) /* event loop handling using select() */ -static int event_loop_select(struct event_context *ev, struct timeval *tvalp) +static int std_event_loop_select(struct event_context *ev, struct timeval *tvalp) { + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); fd_set r_fds, w_fds; + struct fd_event *fde; int selrtn; - uint32_t destruction_count = ev->destruction_count; - struct fd_event *fe; + uint32_t destruction_count = std_ev->destruction_count; /* we maybe need to recalculate the maxfd */ - if (ev->maxfd == EVENT_INVALID_MAXFD) { + if (std_ev->maxfd == EVENT_INVALID_MAXFD) { calc_maxfd(ev); } - + FD_ZERO(&r_fds); FD_ZERO(&w_fds); /* setup any fd events */ - for (fe=ev->fd_events; fe; ) { - struct fd_event *next = fe->next; - if (fe->flags & EVENT_FD_READ) { - FD_SET(fe->fd, &r_fds); + for (fde = std_ev->fd_events; fde; fde = fde->next) { + if (fde->flags & EVENT_FD_READ) { + FD_SET(fde->fd, &r_fds); } - if (fe->flags & EVENT_FD_WRITE) { - FD_SET(fe->fd, &w_fds); + if (fde->flags & EVENT_FD_WRITE) { + FD_SET(fde->fd, &w_fds); } - fe = next; } - selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); - + selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + if (selrtn == -1 && errno == EBADF) { /* the socket is dead! this should never happen as the socket should have first been made readable and that should have removed the event, so this must be a bug. This is a fatal error. */ - DEBUG(0,("ERROR: EBADF on event_loop_once\n")); - ev->exit_code = EBADF; + DEBUG(0,("ERROR: EBADF on std_event_loop_once\n")); + std_ev->exit_code = EBADF; return -1; } if (selrtn == 0 && tvalp) { - event_loop_timer(ev); + std_event_loop_timer(ev); return 0; } @@ -472,13 +455,14 @@ static int event_loop_select(struct event_context *ev, struct timeval *tvalp) /* at least one file descriptor is ready - check which ones and call the handler, being careful to allow the handler to remove itself when called */ - for (fe=ev->fd_events; fe; fe=fe->next) { + for (fde = std_ev->fd_events; fde; fde = fde->next) { uint16_t flags = 0; - if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; - if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; + + if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ; + if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (flags) { - fe->handler(ev, fe, flags, fe->private); - if (destruction_count != ev->destruction_count) { + fde->handler(ev, fde, flags, fde->private_data); + if (destruction_count != std_ev->destruction_count) { break; } } @@ -491,51 +475,67 @@ static int event_loop_select(struct event_context *ev, struct timeval *tvalp) /* do a single event loop using the events defined in ev */ -int event_loop_once(struct event_context *ev) +static int std_event_loop_once(struct event_context *ev) { + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); struct timeval tval, *tvalp; tvalp = NULL; - + /* work out the right timeout for all timed events */ - if (ev->timed_events) { + if (std_ev->timed_events) { struct timeval t = timeval_current(); - tval = timeval_diff(&ev->timed_events->next_event, &t); + + tval = timeval_diff(&std_ev->timed_events->next_event, &t); tvalp = &tval; if (timeval_is_zero(tvalp)) { - event_loop_timer(ev); + std_event_loop_timer(ev); return 0; } } #if WITH_EPOLL - if (ev->epoll_fd != -1) { - if (event_loop_epoll(ev, tvalp) == 0) { + if (std_ev->epoll_fd != -1) { + if (std_event_loop_epoll(ev, tvalp) == 0) { return 0; } } #endif - return event_loop_select(ev, tvalp); + return std_event_loop_select(ev, tvalp); } /* - go into an event loop using the events defined in ev this function - will return with the specified code if one of the handlers calls - event_loop_exit() - - also return (with code 0) if all fd events are removed + return on failure or (with 0) if all fd events are removed */ -int event_loop_wait(struct event_context *ev) +static int std_event_loop_wait(struct event_context *ev) { - ev->exit_code = 0; - ev->maxfd = EVENT_INVALID_MAXFD; + struct std_event_context *std_ev = talloc_get_type(ev->additional_data, + struct std_event_context); + std_ev->exit_code = 0; + std_ev->maxfd = EVENT_INVALID_MAXFD; - while (ev->fd_events && ev->exit_code == 0) { - if (event_loop_once(ev) != 0) { + while (std_ev->fd_events && std_ev->exit_code == 0) { + if (std_event_loop_once(ev) != 0) { break; } } - return ev->exit_code; + return std_ev->exit_code; +} + +static const struct event_ops std_event_ops = { + .context_init = std_event_context_init, + .add_fd = std_event_add_fd, + .get_fd_flags = std_event_get_fd_flags, + .set_fd_flags = std_event_set_fd_flags, + .add_timed = std_event_add_timed, + .loop_once = std_event_loop_once, + .loop_wait = std_event_loop_wait, +}; + +const struct event_ops *event_standard_get_ops(void) +{ + return &std_event_ops; } -- cgit From 4c7c38e930805b84789cfb2472776d6939fc23f6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 16 Feb 2005 01:48:11 +0000 Subject: r5411: make network interface selection a bit saner - if we have no configured network interfaces, then don't start nbtd (when I add dynamic interface loading this will change to a delay until a network interface comes up) - choose the best interface by netmask for torture tests that need a specific IP (such as the WINS test). Added iface_best_ip() for that. - if specific interfaces are chosen in smb.conf, then keep that ordering, and default to the first one listed (This used to be commit 4d08c114079ef6d1d10a96195046fe43631aefa2) --- source4/lib/netif/interface.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 2d90df43cf..78f4456cd8 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -94,7 +94,7 @@ static void add_interface(struct in_addr ip, struct in_addr nmask) iface->nmask = tov4(nmask); iface->bcast.addr = MKBCADDR(iface->ip.addr, iface->nmask.addr); - DLIST_ADD(local_interfaces, iface); + DLIST_ADD_END(local_interfaces, iface, struct interface *); DEBUG(2,("added interface ip=%s ",sys_inet_ntoa(iface->ip))); DEBUG(2,("bcast=%s ",sys_inet_ntoa(iface->bcast))); @@ -339,3 +339,18 @@ const char *iface_n_netmask(int n) return NULL; } +/* + return the local IP address that best matches a destination IP, or + our first interface if none match +*/ +const char *iface_best_ip(const char *dest) +{ + struct interface *iface; + struct in_addr ip; + ip.s_addr = interpret_addr(dest); + iface = iface_find(ip, True); + if (iface) { + return sys_inet_ntoa(iface->ip); + } + return iface_n_ip(0); +} -- cgit From c52fb55903fc68dd6e9d13f618277b2c12e17aa6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 17 Feb 2005 23:11:26 +0000 Subject: r5437: Allow Samba4 to be compiled by tcc (www.tinycc.org). It still crashes when linking though. (This used to be commit 2e1e8db6dc877eb32b51cfc3d9c8f463d14530ec) --- source4/lib/events/events_standard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 96f938c78e..76c8c4768a 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -357,8 +357,8 @@ static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp) struct std_event_context *std_ev = talloc_get_type(ev->additional_data, struct std_event_context); int ret, i; - const int maxevents = 8; - struct epoll_event events[maxevents]; +#define MAXEVENTS 8 + struct epoll_event events[MAXEVENTS]; uint32_t destruction_count = std_ev->destruction_count; int timeout = -1; @@ -367,7 +367,7 @@ static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp) timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); } - ret = epoll_wait(std_ev->epoll_fd, events, maxevents, timeout); + ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout); if (ret == -1 && errno != EINTR) { epoll_fallback_to_select(ev, "epoll_wait() failed"); -- cgit From 80d3047333fceb3805ccd10a08cdf95021f57ff4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Feb 2005 14:30:49 +0000 Subject: r5490: The big (D)COM commit! :-) Contains most of the changes described in the DCOM paper in lorikeet. This is the result of 1.5 months work (mainly figuring out how things *really* work) at the end of 2004. In general: - Clearer distinction between COM and DCOM. DCOM is now merely the glue between DCE/RPC+ORPC and COM. COM can also work without DCOM now. This makes the code a lot clearer. - Clearer distinction between NDR and DCOM. Before, NDR had a couple of "if"s to cope with DCOM, which are now gone. - Use "real" arguments rather then structures for function arguments in COM, mainly because most of these calls are local so packing/unpacking data for every call is too much overhead (both speed- and code-wise) - Support several mechanisms to load class objects: - from memory (e.g. part of the current executable, registered at start-up) - from shared object files - remotely - Most things are now also named COM rather then DCOM because that's what it really is. After an object is created, it no longer matters whether it was created locally or remotely. There is a very simple example class that contains both a class factory and a class that implements the IStream interface. It can be tested (locally only, remotely is broken at the moment) by running the COM-SIMPLE smbtorture test. Still to-do: - Autogenerate parts of the class implementation code (using the coclass definitions in IDL) - Test server-side - Implement some of the common classes, add definitions for common interfaces. (This used to be commit 71fd3e5c3aac5f0002001ab29d2248e6c6842d6f) --- source4/lib/com/classes/simple.c | 116 ++++++++++++++++++++++++++++++++++++ source4/lib/com/com.h | 30 ++++++++++ source4/lib/com/config.mk | 10 ++++ source4/lib/com/main.c | 85 +++++++++++++++++++++++++++ source4/lib/com/rot.c | 34 +++++++++++ source4/lib/com/tables.c | 107 +++++++++++++++++++++++++++++++++ source4/lib/dcom/classes/simple.c | 66 --------------------- source4/lib/dcom/common/dcom.h | 33 ++--------- source4/lib/dcom/common/main.c | 120 ++++---------------------------------- source4/lib/dcom/common/rot.c | 34 ----------- source4/lib/dcom/common/tables.c | 107 --------------------------------- source4/lib/dcom/config.mk | 26 ++++----- 12 files changed, 411 insertions(+), 357 deletions(-) create mode 100644 source4/lib/com/classes/simple.c create mode 100644 source4/lib/com/com.h create mode 100644 source4/lib/com/config.mk create mode 100644 source4/lib/com/main.c create mode 100644 source4/lib/com/rot.c create mode 100644 source4/lib/com/tables.c delete mode 100644 source4/lib/dcom/classes/simple.c delete mode 100644 source4/lib/dcom/common/rot.c delete mode 100644 source4/lib/dcom/common/tables.c (limited to 'source4/lib') diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c new file mode 100644 index 0000000000..2c72d56f94 --- /dev/null +++ b/source4/lib/com/classes/simple.c @@ -0,0 +1,116 @@ +/* + Unix SMB/CIFS implementation. + Simple class + Copyright (C) 2004-2005 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/com/com.h" +#include "librpc/gen_ndr/com_dcom.h" + + +static WERROR simple_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +{ + *iun = d; + return WERR_OK; +} + +static uint32_t simple_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static uint32_t simple_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static WERROR simple_Read (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *pv, uint32_t num_requested, uint32_t *num_readx, uint32_t num_read) +{ + printf("%d bytes are being read\n", num_read); + return WERR_OK; +} + +static WERROR simple_Write (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *data, uint32_t num_requested, uint32_t num_written) +{ + printf("%d bytes are being written\n", num_requested); + return WERR_OK; +} + +static struct IStream_vtable simple_istream_vtable = { + simple_QueryInterface, + simple_AddRef, + simple_Release, + simple_Read, + simple_Write +}; + +static WERROR simpleclass_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +{ + /* FIXME: Return WERR_IFACE_NOT_SUPPORTED if IID != IID_IUNKNOWN and IID != IID_CLASSFACTORY */ + *iun = d; + return WERR_OK; +} + +static WERROR simpleclass_CreateInstance (struct IClassFactory *d, TALLOC_CTX *mem_ctx, struct IUnknown *iunk, struct GUID *iid, struct IUnknown **ppv) +{ + struct IStream *ret; + /* FIXME: Check whether IID == ISTREAM_IID */ + ret = talloc(mem_ctx, struct IStream); + ret->ctx = NULL; + ret->vtable = &simple_istream_vtable; + ret->object_data = NULL; + + *ppv = ret; + + return WERR_OK; +} + +static uint32_t simpleclass_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static uint32_t simpleclass_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +/* Everything below this line should be autogenerated later on */ +static struct IClassFactory_vtable simple_classobject_vtable = { + simpleclass_QueryInterface, + simpleclass_AddRef, + simpleclass_Release, + simpleclass_CreateInstance, + NULL, + NULL, + NULL +}; + +NTSTATUS com_simple_init(void) +{ + struct GUID clsid; + struct IUnknown *class_object = talloc(talloc_autofree_context(), struct IUnknown); + + class_object->ctx = NULL; + class_object->object_data = NULL; + class_object->vtable = (struct IUnknown_vtable *)&simple_classobject_vtable; + + GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &clsid); + + return com_register_running_class(&clsid, "Samba.Simple", class_object); +} diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h new file mode 100644 index 0000000000..be7dcde5b5 --- /dev/null +++ b/source4/lib/com/com.h @@ -0,0 +1,30 @@ +/* + Unix SMB/CIFS implementation. + COM standard objects + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _COM_H /* _COM_H */ +#define _COM_H + +struct com_context +{ +}; + +typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid); + +#endif /* _COM_H */ diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk new file mode 100644 index 0000000000..006ea212c1 --- /dev/null +++ b/source4/lib/com/config.mk @@ -0,0 +1,10 @@ +[SUBSYSTEM::LIBCOM] +INIT_OBJ_FILES = \ + lib/com/tables.o \ + lib/com/rot.o \ + lib/com/main.o + +[MODULE::com_simple] +SUBSYSTEM = LIBCOM +INIT_OBJ_FILES = lib/com/classes/simple.o +INIT_FUNCTION = com_simple_init diff --git a/source4/lib/com/main.c b/source4/lib/com/main.c new file mode 100644 index 0000000000..378c3738b9 --- /dev/null +++ b/source4/lib/com/main.c @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + Main COM functionality + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "lib/com/com.h" +#include "librpc/gen_ndr/com_dcom.h" + +WERROR com_init(struct com_context **ctx) +{ + *ctx = talloc(NULL, struct com_context); + return WERR_OK; +} + +WERROR com_create_object(struct com_context *ctx, struct GUID *clsid, int num_ifaces, struct GUID *iid, struct IUnknown **ip, WERROR *results) +{ + struct IUnknown *iunk = NULL; + struct IClassFactory *factory; + WERROR error; + int i; + struct GUID classfact_iid; + + GUID_from_string(DCERPC_ICLASSFACTORY_UUID, &classfact_iid); + + /* Obtain class object */ + error = com_get_class_object(ctx, clsid, &classfact_iid, (struct IUnknown **)&factory); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); + return error; + } + + /* Run IClassFactory::CreateInstance() */ + error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, &iunk); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", win_errstr(error))); + return error; + } + + if (!iunk) { + DEBUG(0, ("IClassFactory_CreateInstance returned success but result pointer is still NULL!\n")); + return WERR_GENERAL_FAILURE; + } + + /* Release class object */ + IUnknown_Release(factory, ctx); + + error = WERR_OK; + + /* Do one or more QueryInterface calls */ + for (i = 0; i < num_ifaces; i++) { + results[i] = IUnknown_QueryInterface(iunk, ctx, &iid[i], &ip[i]); + if (!W_ERROR_IS_OK(results[i])) error = results[i]; + } + + return error; +} + +WERROR com_get_class_object(struct com_context *ctx, struct GUID *clsid, struct GUID *iid, struct IUnknown **ip) +{ + struct IUnknown *iu; + + iu = com_class_by_clsid(ctx, clsid); + if (!iu) { + return WERR_CLASS_NOT_REGISTERED; + } + + return IUnknown_QueryInterface(iu, ctx, iid, ip); +} diff --git a/source4/lib/com/rot.c b/source4/lib/com/rot.c new file mode 100644 index 0000000000..34a5671f5b --- /dev/null +++ b/source4/lib/com/rot.c @@ -0,0 +1,34 @@ +/* + Unix SMB/CIFS implementation. + + Running object table functions + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) +{ + /* FIXME: Call the local ROT and do a + * rot_get_interface_pointer call */ + + /* FIXME: Perhaps have a local (thread-local) table with + * local DCOM objects so that not every DCOM call requires a lookup + * to the ROT? */ + return NULL; +} diff --git a/source4/lib/com/tables.c b/source4/lib/com/tables.c new file mode 100644 index 0000000000..cf63e7e9a2 --- /dev/null +++ b/source4/lib/com/tables.c @@ -0,0 +1,107 @@ +/* + Unix SMB/CIFS implementation. + COM class tables + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" + +/* Specific implementation of one or more interfaces */ +struct com_class +{ + const char *progid; + struct GUID clsid; + + struct IUnknown *class_object; + struct com_class *prev, *next; +} * running_classes = NULL; + +static struct IUnknown *get_com_class_running(const struct GUID *clsid) +{ + struct com_class *c = running_classes; + + while(c) { + + if (GUID_equal(clsid, &c->clsid)) { + return c->class_object; + } + + c = c->next; + } + + return NULL; +} + +static struct IUnknown *get_com_class_so(TALLOC_CTX *mem_ctx, const struct GUID *clsid) +{ + char *mod_name; + char *clsid_str; + void *mod; + get_class_object_function f; + + clsid_str = GUID_string(mem_ctx, clsid); + mod_name = talloc_asprintf(mem_ctx, "%s.so", clsid_str); + talloc_free(clsid_str); + + mod = sys_dlopen(mod_name, 0); + + if (!mod) { + return NULL; + } + + f = sys_dlsym(mod, "get_class_object"); + + if (!f) { + return NULL; + } + + return f(clsid); +} + +struct IUnknown *com_class_by_clsid(struct com_context *ctx, const struct GUID *clsid) +{ + struct IUnknown *c; + + /* Check list of running COM classes first */ + c = get_com_class_running(clsid); + + if (c != NULL) { + return c; + } + + c = get_com_class_so(ctx, clsid); + + if (c != NULL) { + return c; + } + + return NULL; +} + +NTSTATUS com_register_running_class(struct GUID *clsid, const char *progid, struct IUnknown *p) +{ + struct com_class *l = talloc_zero(running_classes?running_classes:talloc_autofree_context(), struct com_class); + + l->clsid = *clsid; + l->progid = talloc_strdup(l, progid); + l->class_object = p; + + DLIST_ADD(running_classes, l); + + return NT_STATUS_OK; +} diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c deleted file mode 100644 index 13cf4616b2..0000000000 --- a/source4/lib/dcom/classes/simple.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Simple class - Copyright (C) 2004 Jelmer Vernooij - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/dcom/common/dcom.h" - -NTSTATUS simple_QueryInterface (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct QueryInterface *r) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -static NTSTATUS simple_CreateInstance (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct CreateInstance *r) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -/* Everything below this line should be autogenerated later on */ - -static struct dcom_IClassFactory_vtable simple_classobject = { - { simple_QueryInterface, NULL, NULL }, - simple_CreateInstance, - NULL, - NULL, - NULL -}; - -NTSTATUS dcom_simple_init(void) -{ - struct GUID iid; - struct dcom_class simple_class = { - "Samba.Simple", - }; - - GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); - - simple_class.class_object = dcom_new_local_ifacep( - talloc_autofree_context(), - &iid, - &simple_classobject, NULL); - - if (!simple_class.class_object) { - DEBUG(1, ("Unable to create class object for simple class\n")); - return NT_STATUS_OK; - } - - GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); - - return dcom_register_class(&simple_class); -} diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 0bc4a256f1..dd21bb9d29 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. DCOM standard objects - Copyright (C) Jelmer Vernooij 2004. + Copyright (C) Jelmer Vernooij 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 @@ -23,11 +23,6 @@ #include "librpc/ndr/ndr_dcom.h" -struct IUnknown_AddRef; -struct IUnknown_Release; -struct IUnknown_QueryInterface; -struct dcom_interface_p; - struct dcom_context { struct dcom_object_exporter { @@ -49,34 +44,16 @@ struct dcom_context uint32_t dcerpc_flags; }; -/* Specific implementation of one or more interfaces */ -struct dcom_class -{ - const char *prog_id; - struct GUID clsid; - - /* IUnknown */ - struct dcom_interface_p *class_object; -}; - -struct dcom_interface -{ - struct GUID iid; - int num_methods; - struct GUID base_iid; - const void *proxy_vtable; -}; - struct dcom_interface_p { - struct dcom_context *ctx; - const struct dcom_interface *interface; + struct com_context *ctx; + const struct com_interface *interface; const void *vtable; /* Points to one of the available implementations */ struct GUID ipid; - struct dcom_object *object; + struct com_object *object; int objref_flags; int orpc_flags; - struct dcom_object_exporter *ox; + struct com_object_exporter *ox; uint32_t private_references; }; diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index a8324606f1..315912ba3c 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -117,7 +117,7 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user return WERR_OK; } -static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) +struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) { struct dcom_object_exporter *m; @@ -144,7 +144,7 @@ WERROR dcom_ping(struct dcom_context *ctx) return WERR_OK; } -static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +static WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; struct dcerpc_pipe *p; @@ -154,6 +154,10 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c struct DUALSTRINGARRAY dualstring; int i; + if (!server) { + return com_create_object(ctx, clsid, num_ifaces, iid, ip, results); + } + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); @@ -208,60 +212,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c return WERR_OK; } -WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) -{ - struct dcom_interface_p *factory, *iunk = NULL; - struct QueryInterface qr; - struct Release rr; - struct CreateInstance cr; - WERROR error; - int i; - NTSTATUS status; - - if (server != NULL) { - return dcom_create_object_remote(ctx, clsid, server, num_ifaces, iid, ip, results); - } - - /* Obtain class object */ - error = dcom_get_class_object(ctx, clsid, server, iid, &factory); - if (!W_ERROR_IS_OK(error)) { - DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); - return error; - } - - dcom_OBJREF_from_ifacep(ctx, &cr.in.pUnknown->obj, factory); - - GUID_from_string(DCERPC_ICLASSFACTORY_UUID, cr.in.iid); - - /* Run IClassFactory::CreateInstance() */ - status = dcom_IClassFactory_CreateInstance(factory, ctx, &cr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - /* Release class object */ - status = dcom_IUnknown_Release(factory, ctx, &rr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(3, ("Error freeing class factory: %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - /* Do one or more QueryInterface calls */ - for (i = 0; i < num_ifaces; i++) { - qr.in.iid = &iid[i]; - status = dcom_IUnknown_QueryInterface(iunk, ctx, &qr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(4, ("Error obtaining interface %s : %s\n", GUID_string(NULL, &iid[i]), nt_errstr(status))); - return ntstatus_to_werror(status); - } - results[i] = qr.out.result; - } - - return WERR_OK; -} - -WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) { struct dcom_object_exporter *m; struct RemoteActivation r; @@ -271,6 +222,10 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid struct pMInterfacePointer pm; uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + if (!server) { + return com_get_class_object(ctx, clsid, iid, ip); + } + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); @@ -312,36 +267,6 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) -{ - const struct dcom_class *c; - struct QueryInterface qi; - NTSTATUS status; - - if (server != NULL) { - return dcom_get_class_object_remote(ctx, clsid, server, iid, ip); - } - - c = dcom_class_by_clsid(clsid); - if (!c) { - /* FIXME: Better error code.. */ - return WERR_DEST_NOT_FOUND; - } - - qi.in.iid = iid; - - status = dcom_IUnknown_QueryInterface(c->class_object, ctx, &qi ); - if (NT_STATUS_IS_ERR(status)) { - return ntstatus_to_werror(status); - } - - if (!W_ERROR_IS_OK(qi.out.result)) { return qi.out.result; } - - dcom_ifacep_from_OBJREF(ctx, ip, &qi.out.data->obj); - - return WERR_OK; -} - NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding binding; @@ -549,26 +474,3 @@ uint64_t dcom_get_current_oxid(void) { return getpid(); } - -struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct GUID *iid, void *vtable, struct dcom_object *object) -{ - struct dcom_interface_p *ip = talloc(ctx, struct dcom_interface_p); - const struct dcom_interface *iface = dcom_interface_by_iid(iid); - - if (!iface) { - DEBUG (1, ("Unable to find interface with IID %s\n", GUID_string(ctx, iid))); - return NULL; - } - - ip->ctx = ctx; - ip->interface = iface; - ip->vtable = vtable; - ip->ipid = GUID_random(); - ip->object = object; - ip->objref_flags = 0; - ip->orpc_flags = 0; - ip->ox = NULL; - ip->private_references = 1; - - return ip; -} diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c deleted file mode 100644 index 7acdbe066e..0000000000 --- a/source4/lib/dcom/common/rot.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Running object table functions - - Copyright (C) Jelmer Vernooij 2004 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) -{ - /* FIXME: Call the local ROT and do a - * rot_get_interface_pointer call */ - - /* FIXME: Perhaps have a local (thread-local) table with - * local DCOM objects so that not every DCOM call requires a lookup - * to the ROT? */ - return NULL; -} diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c deleted file mode 100644 index cd7e0867ee..0000000000 --- a/source4/lib/dcom/common/tables.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DCOM interface and class tables - Copyright (C) 2004 Jelmer Vernooij - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "dlinklist.h" - -static struct class_list { - struct class_list *prev, *next; - struct dcom_class class; -} *classes = NULL; - -static struct interface_list { - struct interface_list *prev, *next; - struct dcom_interface interface; -} *interfaces = NULL; - -const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) -{ - struct interface_list *l = interfaces; - - while(l) { - - if (GUID_equal(iid, &l->interface.iid)) - return &l->interface; - - l = l->next; - } - - return NULL; -} - -const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) -{ - struct class_list *c = classes; - - while(c) { - - if (GUID_equal(clsid, &c->class.clsid)) { - return &c->class; - } - - c = c->next; - } - - return NULL; -} - -const void *dcom_proxy_vtable_by_iid(const struct GUID *iid) -{ - const struct dcom_interface *iface = dcom_interface_by_iid(iid); - - if (!iface) { - return NULL; - } - - return iface->proxy_vtable; -} - -NTSTATUS dcom_register_interface(const void *_iface) -{ - const struct dcom_interface *iface = _iface; - struct interface_list *l; - TALLOC_CTX *lcl_ctx = talloc_init("dcom_register_interface"); - - DEBUG(5, ("Adding DCOM interface %s\n", GUID_string(lcl_ctx, &iface->iid))); - - talloc_free(lcl_ctx); - - l = talloc_zero(interfaces?interfaces:talloc_autofree_context(), - struct interface_list); - - l->interface = *iface; - - DLIST_ADD(interfaces, l); - - return NT_STATUS_OK; -} - -NTSTATUS dcom_register_class(const void *_class) -{ - const struct dcom_class *class = _class; - struct class_list *l = talloc_zero(classes?classes:talloc_autofree_context(), - struct class_list); - - l->class = *class; - - DLIST_ADD(classes, l); - - return NT_STATUS_OK; -} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index ca280884ea..ae8fe9c4b0 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -1,19 +1,19 @@ ################################################ # Start SUBSYSTEM LIBDCOM -[SUBSYSTEM::LIBDCOM] -INIT_OBJ_FILES = \ - lib/dcom/common/main.o \ - lib/dcom/common/tables.o \ - lib/dcom/common/rot.o -REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ - RPC_NDR_OXIDRESOLVER +#[SUBSYSTEM::LIBDCOM] +#ENABLE = NO +#INIT_OBJ_FILES = \ +# lib/dcom/common/main.o +#REQUIRED_SUBSYSTEMS = LIBCOM DCOM_PROXY_DCOM RPC_NDR_REMACT \ +# RPC_NDR_OXIDRESOLVER -[MODULE::DCOM_SIMPLE] -SUBSYSTEM = LIBDCOM -REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM -INIT_FUNCTION = dcom_simple_init -INIT_OBJ_FILES = \ - lib/dcom/classes/simple.o +#[MODULE::DCOM_SIMPLE] +#ENABLE = NO +#SUBSYSTEM = LIBDCOM +#REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM +#INIT_FUNCTION = dcom_simple_init +#INIT_OBJ_FILES = \ +# lib/dcom/classes/simple.o # # End SUBSYSTEM LIBDCOM ################################################ -- cgit From 9c6ad1f762a07082156673dc1bc67e171fe96251 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Feb 2005 20:51:26 +0000 Subject: r5492: Update example coclass, autogenerate some parts. (This used to be commit 3c31cbaac0cd916e6af49bfd2260bc3b1a75b677) --- source4/lib/com/classes/simple.c | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c index 2c72d56f94..a6134d4c36 100644 --- a/source4/lib/com/classes/simple.c +++ b/source4/lib/com/classes/simple.c @@ -22,57 +22,51 @@ #include "lib/com/com.h" #include "librpc/gen_ndr/com_dcom.h" +extern const struct IClassFactory_vtable simple_classobject_vtable; +extern const struct IStream_vtable simple_IStream_vtable; -static WERROR simple_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +static WERROR simple_IUnknown_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) { *iun = d; return WERR_OK; } -static uint32_t simple_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +static uint32_t simple_IUnknown_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) { return 1; } -static uint32_t simple_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +static uint32_t simple_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) { return 1; } -static WERROR simple_Read (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *pv, uint32_t num_requested, uint32_t *num_readx, uint32_t num_read) +static WERROR simple_IStream_Read (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *pv, uint32_t num_requested, uint32_t *num_readx, uint32_t num_read) { printf("%d bytes are being read\n", num_read); return WERR_OK; } -static WERROR simple_Write (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *data, uint32_t num_requested, uint32_t num_written) +static WERROR simple_IStream_Write (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *data, uint32_t num_requested, uint32_t num_written) { printf("%d bytes are being written\n", num_requested); return WERR_OK; } -static struct IStream_vtable simple_istream_vtable = { - simple_QueryInterface, - simple_AddRef, - simple_Release, - simple_Read, - simple_Write -}; - -static WERROR simpleclass_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +static WERROR simpleclass_IUnknown_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) { /* FIXME: Return WERR_IFACE_NOT_SUPPORTED if IID != IID_IUNKNOWN and IID != IID_CLASSFACTORY */ *iun = d; return WERR_OK; } -static WERROR simpleclass_CreateInstance (struct IClassFactory *d, TALLOC_CTX *mem_ctx, struct IUnknown *iunk, struct GUID *iid, struct IUnknown **ppv) +static WERROR simpleclass_IClassFactory_CreateInstance (struct IClassFactory *d, TALLOC_CTX *mem_ctx, struct IUnknown *iunk, struct GUID *iid, struct IUnknown **ppv) { struct IStream *ret; /* FIXME: Check whether IID == ISTREAM_IID */ ret = talloc(mem_ctx, struct IStream); ret->ctx = NULL; - ret->vtable = &simple_istream_vtable; + ret->vtable = &simple_IStream_vtable; ret->object_data = NULL; *ppv = ret; @@ -80,27 +74,35 @@ static WERROR simpleclass_CreateInstance (struct IClassFactory *d, TALLOC_CTX *m return WERR_OK; } -static uint32_t simpleclass_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +static uint32_t simpleclass_IUnknown_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) { return 1; } -static uint32_t simpleclass_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +static uint32_t simpleclass_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) { return 1; } /* Everything below this line should be autogenerated later on */ -static struct IClassFactory_vtable simple_classobject_vtable = { - simpleclass_QueryInterface, - simpleclass_AddRef, - simpleclass_Release, - simpleclass_CreateInstance, +const struct IClassFactory_vtable simple_classobject_vtable = { + simpleclass_IUnknown_QueryInterface, + simpleclass_IUnknown_AddRef, + simpleclass_IUnknown_Release, + simpleclass_IClassFactory_CreateInstance, NULL, NULL, NULL }; +const struct IStream_vtable simple_IStream_vtable = { + simple_IUnknown_QueryInterface, + simple_IUnknown_AddRef, + simple_IUnknown_Release, + simple_IStream_Read, + simple_IStream_Write +}; + NTSTATUS com_simple_init(void) { struct GUID clsid; @@ -110,7 +112,7 @@ NTSTATUS com_simple_init(void) class_object->object_data = NULL; class_object->vtable = (struct IUnknown_vtable *)&simple_classobject_vtable; - GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &clsid); + GUID_from_string(CLSID_SIMPLE, &clsid); - return com_register_running_class(&clsid, "Samba.Simple", class_object); + return com_register_running_class(&clsid, PROGID_SIMPLE, class_object); } -- cgit From b14727583d6108f11427ec8033986e9d617320c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Feb 2005 01:10:57 +0000 Subject: r5533: Patch to detect infinite loops when traversing a tdb from "Shlomi Yaakobovich" Jeremy. (This used to be commit 84f6d2b3dd29c1aa478708db9617a79382158f64) --- source4/lib/tdb/common/tdb.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 134ee8a4ea..90b586d487 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1314,6 +1314,13 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, goto fail; return tlock->off; } + + /* Detect infinite loops. From "Shlomi Yaakobovich" . */ + if (tlock->off == rec->next) { + TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); + goto fail; + } + /* Try to clean dead ones from old traverses */ current = tlock->off; tlock->off = rec->next; -- cgit From b1b14817eaa6e6579596d54166e17bc8d5605c01 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 27 Feb 2005 11:35:47 +0000 Subject: r5585: LDB interfaces change: changes: - ldb_wrap disappears from code and become a private structure of db_wrap.c thanks to our move to talloc in ldb code, we do not need to expose it anymore - removal of ldb_close() function form the code thanks to our move to talloc in ldb code, we do not need it anymore use talloc_free() to close and free an ldb database - some minor updates to ldb modules code to cope with the change and fix some bugs I found out during the process (This used to be commit d58be9e74b786a11a57e89df36081d55730dfe0a) --- source4/lib/db_wrap.c | 38 ++++++---- source4/lib/ldb/common/ldb.c | 11 +-- source4/lib/ldb/common/ldb_modules.c | 103 ++++++++++++++++++------- source4/lib/ldb/include/ldb.h | 6 -- source4/lib/ldb/include/ldb_private.h | 8 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 11 --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 11 --- source4/lib/ldb/man/man3/ldb.yo | 2 - source4/lib/ldb/modules/schema.c | 40 +++++----- source4/lib/ldb/modules/skel.c | 16 ++-- source4/lib/ldb/modules/timestamps.c | 134 +++++++++++++++++---------------- source4/lib/ldb/tools/ldbadd.c | 2 +- source4/lib/ldb/tools/ldbdel.c | 2 +- source4/lib/ldb/tools/ldbedit.c | 2 +- source4/lib/ldb/tools/ldbmodify.c | 2 +- source4/lib/ldb/tools/ldbrename.c | 2 +- source4/lib/ldb/tools/ldbsearch.c | 2 +- source4/lib/ldb/tools/ldbtest.c | 6 +- source4/lib/registry/reg_backend_ldb.c | 15 ++-- 19 files changed, 215 insertions(+), 198 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 0ec1e378e6..a3a9ee9b86 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -33,6 +33,13 @@ #include "lib/ldb/include/ldb.h" #include "db_wrap.h" +struct ldb_wrap { + struct ldb_context *ldb; + + const char *url; + struct ldb_wrap *next, *prev; +}; + static struct ldb_wrap *ldb_list; static struct tdb_wrap *tdb_list; @@ -55,53 +62,52 @@ static void ldb_wrap_debug(void *context, enum ldb_debug_level level, free(s); } - /* destroy the last connection to a ldb */ static int ldb_wrap_destructor(void *ctx) { struct ldb_wrap *w = ctx; - ldb_close(w->ldb); DLIST_REMOVE(ldb_list, w); return 0; } /* wrapped connection to a ldb database - to close just talloc_free() the ldb_wrap pointer + to close just talloc_free() the returned ldb_context */ -struct ldb_wrap *ldb_wrap_connect(TALLOC_CTX *mem_ctx, +struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, const char *url, unsigned int flags, const char *options[]) { + struct ldb_context *ldb; struct ldb_wrap *w; - for (w=ldb_list;w;w=w->next) { + for (w = ldb_list; w; w = w->next) { if (strcmp(url, w->url) == 0) { - return talloc_reference(mem_ctx, w); + return talloc_reference(mem_ctx, w->ldb); } } - w = talloc(mem_ctx, struct ldb_wrap); - if (w == NULL) { + ldb = ldb_connect(url, flags, options); + if (ldb == NULL) { return NULL; } - w->url = talloc_strdup(w, url); - - w->ldb = ldb_connect(url, flags, options); - if (w->ldb == NULL) { - talloc_free(w); + w = talloc(ldb, struct ldb_wrap); + if (w == NULL) { + talloc_free(ldb); return NULL; } - talloc_steal(w, w->ldb); + + w->ldb = ldb; + w->url = talloc_strdup(w, url); talloc_set_destructor(w, ldb_wrap_destructor); - ldb_set_debug(w->ldb, ldb_wrap_debug, NULL); + ldb_set_debug(ldb, ldb_wrap_debug, NULL); DLIST_ADD(ldb_list, w); - return w; + return ldb; } diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 0fb371011f..40616c5963 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -69,7 +69,7 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, } if (ldb_load_modules(ldb_ctx, options) != 0) { - ldb_close(ldb_ctx); + talloc_free(ldb_ctx); errno = EINVAL; return NULL; } @@ -77,15 +77,6 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, return ldb_ctx; } -/* - close the connection to the database -*/ -int ldb_close(struct ldb_context *ldb) -{ - return ldb->modules->ops->close(ldb->modules); -} - - /* search the database given a LDAP-like search expression diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 22d1ce112e..f8162aee8c 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -41,6 +41,10 @@ #include #include +#ifdef HAVE_DLOPEN_DISABLED +#include +#endif + #define LDB_MODULE_PREFIX "modules" #define LDB_MODULE_PREFIX_LEN 7 #define LDB_MODULE_SEP ':' @@ -49,14 +53,15 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { struct ldb_module *current; char **modules; - char *p, *q; - int pn, i; + int mnum, i; /* find out which modules we are requested to activate */ modules = NULL; - pn = 0; + mnum = 0; if (options) { + char *q, *p; + for (i = 0; options[i] != NULL; i++) { if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) { @@ -68,13 +73,13 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) do { *p = '\0'; q = p + 1; - pn++; - modules = talloc_realloc(ldb, modules, char *, pn); + mnum++; + modules = talloc_realloc(ldb, modules, char *, mnum); if (!modules) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n"); return -1; } - modules[pn - 1] = q; + modules[mnum - 1] = q; } while ((p = strchr(q, LDB_MODULE_SEP))); } } @@ -83,9 +88,10 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) if (!modules && strcmp("ldap", ldb->modules->ops->name)) { /* no modules in the options, look for @MODULES in the db (not for ldap) */ - int ret, j, k; - const char * const attrs[] = { "@MODULE" , NULL}; + int ret; + const char * const attrs[] = { "@LIST" , NULL}; struct ldb_message **msg = NULL; + char *modstr, *c, *p; ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); if (ret == 0) { @@ -100,6 +106,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return -1; } +/* for (j = 0; j < msg[0]->num_elements; j++) { for (k = 0; k < msg[0]->elements[j].num_values; k++) { pn++; @@ -115,12 +122,58 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } } } +*/ + modstr = msg[0]->elements[0].values[0].data; + for (c = modstr, mnum = 0; c != NULL; mnum++) { + c = strchr(c, ','); + if (c != NULL) { + c++; + if (*c == '\0') { /* avoid failing if the modules string lasts with ',' */ + break; + } + } + } + + + modules = talloc_array(ldb, char *, mnum); + if ( ! modules ) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n"); + return -1; + } + + for (p = c = modstr, i = 0; mnum > i; i++) { + c = strchr(p, ','); + if (c) { + *c = '\0'; + } + /* modules are seeked in inverse order. Lets place them as an admin would think the right order is */ + modules[mnum - i - 1] = talloc_strdup(modules, p); + p = c + 1; + } } talloc_free(msg); } if (modules) { - for (i = 0; i < pn; i++) { + for (i = 0; i < mnum; i++) { +#ifdef HAVE_DLOPEN_DISABLED + void *handle; + ldb_module_init_function init; + struct stat st; + char *filename; + const char *errstr; +#endif + + if (strcmp(modules[i], "schema") == 0) { + current = schema_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } + if (strcmp(modules[i], "timestamps") == 0) { current = timestamps_module_init(ldb, options); if (!current) { @@ -131,8 +184,8 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } - if (strcmp(modules[i], "schema") == 0) { - current = schema_module_init(ldb, options); + if (strcmp(modules[i], "samldb") == 0) { + current = samldb_module_init(ldb, options); if (!current) { ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); return -1; @@ -142,18 +195,18 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } #ifdef HAVE_DLOPEN_DISABLED - { - void *handle; - ldb_module_init_function init; - struct stat st; - const char *errstr; + filename = talloc_asprintf(ldb, "%s.so", modules[i]); + if (!filename) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Talloc failed!\n"); + return -1; + } - if (stat(modules[i], &st) < 0) { + if (stat(filename, &st) < 0) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); return -1; } - handle = dlopen(modules[i], RTLD_LAZY); + handle = dlopen(filename, RTLD_LAZY); if (!handle) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror()); @@ -174,10 +227,9 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return -1; } DLIST_ADD(ldb->modules, current); - } #else - ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); - return -1; + ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + return -1; #endif } } @@ -188,13 +240,6 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) /* helper functions to call the next module in chain */ -int ldb_next_close(struct ldb_module *module) -{ - if (!module->next) { - return -1; - } - return module->next->ops->close(module->next); -} int ldb_next_search(struct ldb_module *module, const char *base, diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 09b4cbf84a..0eb661d7ce 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -158,12 +158,6 @@ struct ldb_debug_ops { struct ldb_context *ldb_connect(const char *url, unsigned int flags, const char *options[]); -/* - close the connection to the database -*/ -int ldb_close(struct ldb_context *ldb); - - /* search the database given a LDAP-like search expression diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 426da5ccae..a370a80299 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -55,7 +55,6 @@ struct ldb_module { */ struct ldb_module_ops { const char *name; - int (*close)(struct ldb_module *); int (*search)(struct ldb_module *, const char *, enum ldb_scope, const char *, const char * const [], struct ldb_message ***); int (*search_free)(struct ldb_module *, struct ldb_message **); @@ -68,9 +67,6 @@ struct ldb_module_ops { const char * (*errstring)(struct ldb_module *); }; -/* the modules init function */ -typedef struct ldb_module *(*ldb_module_init_function)(void); - /* every ldb connection is started by establishing a ldb_context */ @@ -82,10 +78,12 @@ struct ldb_context { struct ldb_debug_ops debug_ops; }; +/* the modules init function */ +typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); + /* The following definitions come from lib/ldb/common/ldb_modules.c */ int ldb_load_modules(struct ldb_context *ldb, const char *options[]); -int ldb_next_close(struct ldb_module *module); int ldb_next_search(struct ldb_module *module, const char *base, enum ldb_scope scope, diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 46ea1a9e33..dc392dd56b 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -67,16 +67,6 @@ static const char *lldb_option_find(const struct lldb_private *lldb, const char } #endif -/* - close/free the connection -*/ -static int lldb_close(struct ldb_module *module) -{ - struct ldb_context *ldb = module->ldb; - talloc_free(ldb); - return 0; -} - /* rename a record */ @@ -468,7 +458,6 @@ static const char *lldb_errstring(struct ldb_module *module) static const struct ldb_module_ops lldb_ops = { "ldap", - lldb_close, lldb_search, lldb_search_free, lldb_add, diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 07a9fa8866..204eaf9d3c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -780,16 +780,6 @@ failed: return -1; } -/* - close database -*/ -static int ltdb_close(struct ldb_module *module) -{ - struct ldb_context *ldb = module->ldb; - talloc_free(ldb); - return 0; -} - /* return extended error information @@ -806,7 +796,6 @@ static const char *ltdb_errstring(struct ldb_module *module) static const struct ldb_module_ops ltdb_ops = { "tdb", - ltdb_close, ltdb_search, ltdb_search_free, ltdb_add, diff --git a/source4/lib/ldb/man/man3/ldb.yo b/source4/lib/ldb/man/man3/ldb.yo index ce8a590fbc..8d7a60ccf2 100644 --- a/source4/lib/ldb/man/man3/ldb.yo +++ b/source4/lib/ldb/man/man3/ldb.yo @@ -64,8 +64,6 @@ formatted input dit(bf(ldb_connect(3))) connect to a ldb backend -dit(bf(ldb_close(3))) close a connection to a ldb backend - dit(bf(ldb_search(3))) perform a database search dit(bf(ldb_search_free(3))) free the results of a ldb_search diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 2921bdc68b..ef766b55ee 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -297,12 +297,6 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru return 0; } -/* close */ -static int schema_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - /* search */ static int schema_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -371,18 +365,6 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } - /* check we are not trying to delete a required attribute */ - /* TODO: consider multivalued attrs */ - if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, - "Trying to delete the required attribute %s.\n", - attr->name); - - data->error_string = "Objectclass violation, a required attribute cannot be removed"; - talloc_free(entry_structs); - return -1; - } - /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -477,6 +459,18 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess return -1; } + /* check we are not trying to delete a required attribute */ + /* TODO: consider multivalued attrs */ + if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Trying to delete the required attribute %s.\n", + attr->name); + + data->error_string = "Objectclass violation, a required attribute cannot be removed"; + talloc_free(entry_structs); + return -1; + } + /* mark the attribute as checked */ attr->flags = SCHEMA_FLAG_CHECKED; } @@ -544,9 +538,15 @@ static const char *schema_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int schema_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops schema_ops = { "schema", - schema_close, schema_search, schema_search_free, schema_add_record, @@ -584,5 +584,7 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; + talloc_set_destructor (ctx, schema_destructor); + return ctx; } diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index afafe1bbd9..882a776819 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,12 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -/* close */ -static int skel_close(struct ldb_module *module) -{ - return ldb_next_close(module); -} - /* search */ static int skel_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -98,9 +92,15 @@ static const char *skel_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int skel_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops skel_ops = { "skel", - skel_close, skel_search, skel_search_free, skel_add_record, @@ -129,5 +129,7 @@ struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options ctx->private_data = NULL; ctx->ops = &skel_ops; + talloc_set_destructor (ctx, skel_destructor); + return ctx; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 1deeeb218b..dec564bf66 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -41,12 +41,6 @@ struct private_data { const char *error_string; }; -static int timestamps_close(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_close\n"); - return ldb_next_close(module); -} - static int timestamps_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -106,41 +100,43 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); - if (msg->dn[0] != '@') { /* do not manipulate our control entries */ - timeval = time(NULL); - tm = gmtime(&timeval); - if (!tm) { - return -1; - } + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } - /* formatted like: 20040408072012.0Z */ - timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - if (!timestr) { - return -1; - } + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { + return -1; + } - add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); - add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; } + add_time_element(module, msg2, "createTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenCreated", timestr, LDB_FLAG_MOD_ADD); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_ADD); + if (msg2) { ret = ldb_next_add_record(module, msg2); talloc_free(msg2); @@ -162,40 +158,42 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); - if (msg->dn[0] != '@') { /* do not manipulate our control entries */ - timeval = time(NULL); - tm = gmtime(&timeval); - if (!tm) { - return -1; - } + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_modify_record(module, msg); + } - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } + timeval = time(NULL); + tm = gmtime(&timeval); + if (!tm) { + return -1; + } - /* formatted like: 20040408072012.0Z */ - timestr = talloc_asprintf(msg2, - "%04u%02u%02u%02u%02u%02u.0Z", - tm->tm_year+1900, tm->tm_mon+1, - tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec); - if (!timestr) { - return -1; - } + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } + /* formatted like: 20040408072012.0Z */ + timestr = talloc_asprintf(msg2, + "%04u%02u%02u%02u%02u%02u.0Z", + tm->tm_year+1900, tm->tm_mon+1, + tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + if (!timestr) { + return -1; + } - add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); - add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; } + add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); + add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); + if (msg2) { ret = ldb_next_modify_record(module, msg2); talloc_free(msg2); @@ -247,9 +245,15 @@ static const char *timestamps_errstring(struct ldb_module *module) return ldb_next_errstring(module); } +static int timestamps_destructor(void *module_ctx) +{ + struct ldb_module *ctx = module_ctx; + /* put your clean-up functions here */ + return 0; +} + static const struct ldb_module_ops timestamps_ops = { "timestamps", - timestamps_close, timestamps_search, timestamps_search_free, timestamps_add_record, @@ -288,5 +292,7 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; + talloc_set_destructor (ctx, timestamps_destructor); + return ctx; } diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 927debc65e..41273a08da 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -153,7 +153,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } } - ldb_close(ldb); + talloc_free(ldb); printf("Added %d records with %d failures\n", count, failures); diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 2241a0b823..72540db07a 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -146,7 +146,7 @@ static void usage(void) } } - ldb_close(ldb); + talloc_free(ldb); return 0; } diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 20cb7da810..b9f82c282a 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -434,6 +434,6 @@ static void usage(void) } } - ldb_close(ldb); + talloc_free(ldb); return 0; } diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 97dec1050e..78baa0e36c 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -156,7 +156,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } } - ldb_close(ldb); + talloc_free(ldb); printf("Modified %d records with %d failures\n", count, failures); diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index ba870b0a45..273c792584 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -112,7 +112,7 @@ static void usage(void) argv[0], argv[1], ldb_errstring(ldb)); } - ldb_close(ldb); + talloc_free(ldb); return ret; } diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index f764b28557..8d435e7661 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -176,6 +176,6 @@ static int do_search(struct ldb_context *ldb, ret = do_search(ldb, basedn, scope, argv[0], attrs); } - ldb_close(ldb); + talloc_free(ldb); return ret; } diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index a166447aae..86f39d4606 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -323,8 +323,8 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - if (ldb_close(*ldb) != 0) { - printf("ldb_close failed - %s\n", ldb_errstring(*ldb)); + if (talloc_free(*ldb) != 0) { + printf("failed to free/close ldb database"); exit(1); } @@ -427,7 +427,7 @@ static void usage(void) start_test_index(&ldb); - ldb_close(ldb); + talloc_free(ldb); return 0; } diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 9f44f92888..7e63b14245 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -30,10 +30,10 @@ struct ldb_key_data int subkey_count, value_count; }; -static int ldb_close_hive (void *_hive) +static int ldb_free_hive (void *_hive) { struct registry_hive *hive = _hive; - ldb_close (hive->backend_data); + talloc_free(hive->backend_data); return 0; } @@ -231,9 +231,8 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) { - struct ldb_context *c; struct ldb_key_data *kd; - struct ldb_wrap *wrap; + struct ldb_context *wrap; if (!hive->location) return WERR_INVALID_PARAM; wrap = ldb_wrap_connect(hive, hive->location, 0, NULL); @@ -243,14 +242,12 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) return WERR_FOOBAR; } - c = wrap->ldb; - - ldb_set_debug_stderr(c); - hive->backend_data = c; + ldb_set_debug_stderr(wrap); + hive->backend_data = wrap; *k = talloc_zero(hive, struct registry_key); talloc_set_destructor (*k, reg_close_ldb_key); - talloc_set_destructor (hive, ldb_close_hive); + talloc_set_destructor (hive, ldb_free_hive); (*k)->name = talloc_strdup(*k, ""); (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data); kd->dn = talloc_strdup(*k, "hive="); -- cgit From ec97506a51bf211409dedd6f14b5a40267879c94 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Mar 2005 21:59:02 +0000 Subject: r5664: simo, please look into this. It is possible for the number of elements in msg[0] to be 0, in which case we crash. This is a workaround. Also, if you could please split up this function into readable pieces. It's a bit of a mess at the moment. (This used to be commit 19a22f78c28a4b265f59df1b43c1bb6c9e58f736) --- source4/lib/ldb/common/ldb_modules.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index f8162aee8c..ee70a639fa 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -94,7 +94,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) char *modstr, *c, *p; ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); - if (ret == 0) { + if (ret == 0 || (ret == 1 && msg[0]->num_elements == 0)) { ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); } else { if (ret < 0) { @@ -184,6 +184,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } +#ifdef _SAMBA_BUILD_ if (strcmp(modules[i], "samldb") == 0) { current = samldb_module_init(ldb, options); if (!current) { @@ -193,6 +194,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) DLIST_ADD(ldb->modules, current); continue; } +#endif #ifdef HAVE_DLOPEN_DISABLED filename = talloc_asprintf(ldb, "%s.so", modules[i]); -- cgit From 2f9e1650f9fe5a17a1f8d29f1ae4b04c33a91190 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Mar 2005 21:59:48 +0000 Subject: r5665: the data within el2->values can still be used at this point, so don't free (This used to be commit 12d03f96637b9298e0cbc7ee544ca97fffcab9f8) --- source4/lib/ldb/common/ldb_msg.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index b145565a84..4c903cf936 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -445,7 +445,6 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, sizeof(struct ldb_val) * el2->num_values); el1->num_values += el2->num_values; talloc_free(el2->name); - talloc_free(el2->values); if (i+1num_elements) { memmove(el2, el2+1, sizeof(struct ldb_message_element) * (msg2->num_elements - (i+1))); -- cgit From a52a6f1c425335a4154fcd0d8f1c45f6e387ce53 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 5 Mar 2005 22:50:13 +0000 Subject: r5666: winxp will use a NTTIME of -1 to mean "don't change" in setfileinfo basic_info. Add null_nttime() as the equivalent of the existing null_time() call for cheecking for valid NTTIME values (This used to be commit 439ce2efbf7d2ba9b17d6b4bfaf651e781140715) --- source4/lib/time.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 67397e953a..7b371f58dd 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -112,6 +112,15 @@ BOOL null_time(time_t t) t == (time_t)-1; } + +/**************************************************************************** +check if it's a null NTTIME +****************************************************************************/ +BOOL null_nttime(NTTIME t) +{ + return t == 0 || t == (NTTIME)-1; +} + /******************************************************************* create a 16 bit dos packed date ********************************************************************/ -- cgit From 0b4c61a05a9a070db489986fda5c57697cfd092a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 6 Mar 2005 15:33:40 +0000 Subject: r5670: simplify and clarify ldb_modules.c code rectify the test schema correct a glitch in schema module (This used to be commit 0579b5f7adfe160be8ecf124934b6593a02ed06f) --- source4/lib/ldb/common/ldb_modules.c | 282 +++++++++++++------------ source4/lib/ldb/modules/schema.c | 13 +- source4/lib/ldb/tests/schema-tests/schema.ldif | 3 +- 3 files changed, 155 insertions(+), 143 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index ee70a639fa..40d2cd064a 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -45,53 +45,100 @@ #include #endif -#define LDB_MODULE_PREFIX "modules" -#define LDB_MODULE_PREFIX_LEN 7 -#define LDB_MODULE_SEP ':' +#define LDB_MODULE_PREFIX "modules:" +#define LDB_MODULE_PREFIX_LEN 8 + +static char *talloc_strdup_no_spaces(struct ldb_context *ldb, const char *string) +{ + int i, len; + char *trimmed; + + trimmed = talloc_strdup(ldb, string); + if (!trimmed) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in talloc_strdup_trim_spaces()\n"); + return NULL; + } + + len = strlen(trimmed); + for (i = 0; trimmed[i] != '\0'; i++) { + switch (trimmed[i]) { + case ' ': + case '\t': + case '\n': + memmove(&trimmed[i], &trimmed[i + 1], len -i -1); + break; + } + } + + return trimmed; +} + + +/* modules are called in inverse order on the stack. + Lets place them as an admin would think the right order is. + Modules order is imprtant */ +static char **ldb_modules_list_from_string(struct ldb_context *ldb, const char *string) +{ + char **modules = NULL; + char *modstr, *p; + int i; + + /* spaces not admitted */ + modstr = talloc_strdup_no_spaces(ldb, string); + if ( ! modstr) { + return NULL; + } + + modules = talloc_realloc(ldb, modules, char *, 2); + if ( ! modules ) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n"); + talloc_free(modstr); + return NULL; + } + talloc_steal(modules, modstr); + + i = 0; + while ((p = strrchr(modstr, ',')) != NULL) { + *p = '\0'; + p++; + modules[i] = p; + + i++; + modules = talloc_realloc(ldb, modules, char *, i + 2); + if ( ! modules ) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n"); + return NULL; + } + + } + modules[i] = modstr; + + modules[i + 1] = NULL; + + return modules; +} int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { - struct ldb_module *current; - char **modules; - int mnum, i; + char **modules = NULL; + int i; /* find out which modules we are requested to activate */ - modules = NULL; - mnum = 0; + /* check if we have a custom module list passd as ldb option */ if (options) { - char *q, *p; - for (i = 0; options[i] != NULL; i++) { - if (strncmp(options[i], LDB_MODULE_PREFIX, - LDB_MODULE_PREFIX_LEN) == 0) { - p = q = talloc_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]); - if (*q != ':') { - talloc_free(q); - return -1; - } - do { - *p = '\0'; - q = p + 1; - mnum++; - modules = talloc_realloc(ldb, modules, char *, mnum); - if (!modules) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n"); - return -1; - } - modules[mnum - 1] = q; - } while ((p = strchr(q, LDB_MODULE_SEP))); + if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) { + modules = ldb_modules_list_from_string(ldb, &options[i][LDB_MODULE_PREFIX_LEN]); } } } - if (!modules && strcmp("ldap", ldb->modules->ops->name)) { - /* no modules in the options, look for @MODULES in the - db (not for ldap) */ + /* if not overloaded by options and the backend is not ldap try to load the modules list form ldb */ + if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) { int ret; const char * const attrs[] = { "@LIST" , NULL}; struct ldb_message **msg = NULL; - char *modstr, *c, *p; ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); if (ret == 0 || (ret == 1 && msg[0]->num_elements == 0)) { @@ -103,139 +150,104 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } if (ret > 1) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); + talloc_free(msg); return -1; } -/* - for (j = 0; j < msg[0]->num_elements; j++) { - for (k = 0; k < msg[0]->elements[j].num_values; k++) { - pn++; - modules = talloc_realloc(ldb, modules, char *, pn); - if (!modules) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); - return -1; - } - modules[pn - 1] = talloc_strndup(modules, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length); - if (!modules[pn - 1]) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n"); - return -1; - } - } - } -*/ - modstr = msg[0]->elements[0].values[0].data; - for (c = modstr, mnum = 0; c != NULL; mnum++) { - c = strchr(c, ','); - if (c != NULL) { - c++; - if (*c == '\0') { /* avoid failing if the modules string lasts with ',' */ - break; - } - } - } - - - modules = talloc_array(ldb, char *, mnum); - if ( ! modules ) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n"); - return -1; - } + modules = ldb_modules_list_from_string(ldb, msg[0]->elements[0].values[0].data); - for (p = c = modstr, i = 0; mnum > i; i++) { - c = strchr(p, ','); - if (c) { - *c = '\0'; - } - /* modules are seeked in inverse order. Lets place them as an admin would think the right order is */ - modules[mnum - i - 1] = talloc_strdup(modules, p); - p = c + 1; - } } + talloc_free(msg); } - if (modules) { - for (i = 0; i < mnum; i++) { + if (modules == NULL) { + ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database\n"); + return 0; + } + + for (i = 0; modules[i] != NULL; i++) { #ifdef HAVE_DLOPEN_DISABLED - void *handle; - ldb_module_init_function init; - struct stat st; - char *filename; - const char *errstr; + void *handle; + ldb_module_init_function init; + struct stat st; + char *filename; + const char *errstr; #endif + struct ldb_module *current; - if (strcmp(modules[i], "schema") == 0) { - current = schema_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; + if (strcmp(modules[i], "schema") == 0) { + current = schema_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; } + DLIST_ADD(ldb->modules, current); + continue; + } - if (strcmp(modules[i], "timestamps") == 0) { - current = timestamps_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; + if (strcmp(modules[i], "timestamps") == 0) { + current = timestamps_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; } + DLIST_ADD(ldb->modules, current); + continue; + } #ifdef _SAMBA_BUILD_ - if (strcmp(modules[i], "samldb") == 0) { - current = samldb_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; + if (strcmp(modules[i], "samldb") == 0) { + current = samldb_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; } + DLIST_ADD(ldb->modules, current); + continue; + } #endif #ifdef HAVE_DLOPEN_DISABLED - filename = talloc_asprintf(ldb, "%s.so", modules[i]); - if (!filename) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Talloc failed!\n"); - return -1; - } + filename = talloc_asprintf(ldb, "%s.so", modules[i]); + if (!filename) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Talloc failed!\n"); + return -1; + } - if (stat(filename, &st) < 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); - return -1; - } + if (stat(filename, &st) < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + return -1; + } - handle = dlopen(filename, RTLD_LAZY); + handle = dlopen(filename, RTLD_LAZY); - if (!handle) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror()); - return -1; - } + if (!handle) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror()); + return -1; + } - init = (ldb_module_init_function)dlsym(handle, "init_module"); + init = (ldb_module_init_function)dlsym(handle, "init_module"); - errstr = dlerror(); - if (errstr) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr); - return -1; - } + errstr = dlerror(); + if (errstr) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr); + return -1; + } - current = init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); -#else - ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + current = init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); return -1; -#endif } + DLIST_ADD(ldb->modules, current); +#else + ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); + return -1; +#endif } + talloc_free(modules); return 0; } diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index ef766b55ee..1b08db6170 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -108,7 +108,7 @@ static struct schema_attribute *schema_find_attribute(struct schema_attribute_li /* get all the attributes and objectclasses found in msg and put them in schema_structure attributes go in the entry_attrs structure for later checking objectclasses go in the objectclasses structure */ -static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg) +static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg, int flag_mask) { int i, j, k, l; @@ -132,13 +132,13 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; - ss->objectclasses.attr[l].flags = msg->elements[i].flags; + ss->objectclasses.attr[l].flags = msg->elements[i].flags & flag_mask; l++; } ss->objectclasses.num += msg->elements[i].num_values; } - ss->entry_attrs.attr[j].flags = msg->elements[i].flags; + ss->entry_attrs.attr[j].flags = msg->elements[i].flags & flag_mask; ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, msg->elements[i].name); if (ss->entry_attrs.attr[j].name == NULL) { @@ -163,7 +163,8 @@ static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct } talloc_steal(ss, srch); - ret = get_msg_attributes(ss, *srch); + /* set flags to 0 as flags on search have undefined values */ + ret = get_msg_attributes(ss, *srch, 0); if (ret != 0) { ldb_search_free(ldb, srch); return ret; @@ -336,7 +337,7 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message return -1; } - ret = get_msg_attributes(entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg, SCHEMA_FLAG_MOD_MASK); if (ret != 0) { talloc_free(entry_structs); return ret; @@ -430,7 +431,7 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* get list of values to modify */ - ret = get_msg_attributes(entry_structs, msg); + ret = get_msg_attributes(entry_structs, msg, SCHEMA_FLAG_MOD_MASK); if (ret != 0) { talloc_free(entry_structs); return ret; diff --git a/source4/lib/ldb/tests/schema-tests/schema.ldif b/source4/lib/ldb/tests/schema-tests/schema.ldif index 2661ae30c5..651fdac41f 100644 --- a/source4/lib/ldb/tests/schema-tests/schema.ldif +++ b/source4/lib/ldb/tests/schema-tests/schema.ldif @@ -37,8 +37,7 @@ template: userTemplate template: groupTemplate dn: @MODULES -@MODULE: timestamps -@MODULE: schema +@LIST: timestamps,schema # Top, Schema, Configuration, schema, test dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test -- cgit From 77ec3f684dc8563965ae5118ef5549925ea81d0f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 6 Mar 2005 21:43:54 +0000 Subject: r5674: - Re-enable DCOM support. - Always put IID in vtables (useful for asserts) - Add table to keep track of DCOM proxy classes - Bunch of smaller bug fixes (This used to be commit 26d5a0b92c66bc86d0c26f687f83fa712342ac32) --- source4/lib/com/com.h | 13 ++ source4/lib/com/config.mk | 11 + source4/lib/com/dcom/main.c | 374 ++++++++++++++++++++++++++++++++ source4/lib/com/dcom/tables.c | 50 +++++ source4/lib/dcom/common/dcom.h | 60 ------ source4/lib/dcom/common/main.c | 476 ----------------------------------------- source4/lib/dcom/config.mk | 19 -- 7 files changed, 448 insertions(+), 555 deletions(-) create mode 100644 source4/lib/com/dcom/main.c create mode 100644 source4/lib/com/dcom/tables.c delete mode 100644 source4/lib/dcom/common/dcom.h delete mode 100644 source4/lib/dcom/common/main.c delete mode 100644 source4/lib/dcom/config.mk (limited to 'source4/lib') diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h index be7dcde5b5..a056d1d9ee 100644 --- a/source4/lib/com/com.h +++ b/source4/lib/com/com.h @@ -21,8 +21,21 @@ #ifndef _COM_H /* _COM_H */ #define _COM_H +struct IUnknown_vtable; + struct com_context { + struct { + const char *domain; + const char *user; + const char *password; + struct dcom_object_exporter { + uint64_t oxid; + struct DUALSTRINGARRAY bindings; + struct dcerpc_pipe *pipe; + struct dcom_object_exporter *prev, *next; + } *object_exporters; + } dcom; }; typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid); diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk index 006ea212c1..a4fe891864 100644 --- a/source4/lib/com/config.mk +++ b/source4/lib/com/config.mk @@ -4,6 +4,17 @@ INIT_OBJ_FILES = \ lib/com/rot.o \ lib/com/main.o +################################################ +# Start SUBSYSTEM LIBDCOM +[SUBSYSTEM::LIBDCOM] +INIT_OBJ_FILES = \ + lib/com/dcom/main.o \ + lib/com/dcom/tables.o +REQUIRED_SUBSYSTEMS = LIBCOM DCOM_PROXY_DCOM RPC_NDR_REMACT \ + RPC_NDR_OXIDRESOLVER +# End SUBSYSTEM LIBDCOM +################################################ + [MODULE::com_simple] SUBSYSTEM = LIBCOM INIT_OBJ_FILES = lib/com/classes/simple.o diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c new file mode 100644 index 0000000000..b8c2eef82c --- /dev/null +++ b/source4/lib/com/dcom/main.c @@ -0,0 +1,374 @@ +/* + Unix SMB/CIFS implementation. + Main DCOM functionality + Copyright (C) 2004 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "dlinklist.h" +#include "librpc/gen_ndr/ndr_epmapper.h" +#include "librpc/gen_ndr/ndr_remact.h" +#include "librpc/gen_ndr/ndr_oxidresolver.h" +#include "librpc/gen_ndr/ndr_dcom.h" +#include "librpc/gen_ndr/com_dcom.h" + +#define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } + +static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) +{ + char *host, *endpoint; + + ZERO_STRUCTP(b); + + b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId); + + if (b->transport == -1) { + DEBUG(1, ("Can't find transport match endpoint protocol %d\n", bd->wTowerId)); + return NT_STATUS_NOT_SUPPORTED; + } + + host = talloc_strdup(mem_ctx, bd->NetworkAddr); + endpoint = strchr(host, '['); + + if (endpoint) { + *endpoint = '\0'; + endpoint++; + + endpoint[strlen(endpoint)-1] = '\0'; + } + + b->host = host; + b->endpoint = endpoint; + + return NT_STATUS_OK; +} + +static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe **p, const char *server) +{ + struct dcerpc_binding bd; + enum dcerpc_transport_t available_transports[] = { NCACN_IP_TCP, NCACN_NP }; + int i; + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc_init("dcom_connect"); + + if (server == NULL) { + bd.transport = NCALRPC; + return dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + } + + /* Allow server name to contain a binding string */ + if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { + status = dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + + talloc_free(mem_ctx); + return status; + } + talloc_free(mem_ctx); + + ZERO_STRUCT(bd); + bd.host = server; + + for (i = 0; i < ARRAY_SIZE(available_transports); i++) + { + bd.transport = available_transports[i]; + + status = dcerpc_pipe_connect_b(p, &bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + + if (NT_STATUS_IS_OK(status)) { + return status; + } + } + + return status; +} + +struct dcom_object_exporter *object_exporter_by_oxid(struct com_context *ctx, uint64_t oxid) +{ + return NULL; /* FIXME */ +} + +struct dcom_object_exporter *object_exporter_by_ip(struct com_context *ctx, struct IUnknown *ip) +{ + return NULL; /* FIXME */ +} + +WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct IUnknown ***ip, WERROR *results) +{ + uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + struct dcerpc_pipe *p; + struct dcom_object_exporter *m; + NTSTATUS status; + struct RemoteActivation r; + struct DUALSTRINGARRAY dualstring; + int i; + + status = dcom_connect_host(ctx, &p, server); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); + return ntstatus_to_werror(status); + } + + ZERO_STRUCT(r.in); + r.in.this.version.MajorVersion = COM_MAJOR_VERSION; + r.in.this.version.MinorVersion = COM_MINOR_VERSION; + r.in.this.cid = GUID_random(); + r.in.Clsid = *clsid; + r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; + r.in.num_protseqs = ARRAY_SIZE(protseq); + r.in.protseq = protseq; + r.in.Interfaces = num_ifaces; + r.in.pIIDs = iid; + r.out.ifaces = talloc_array(ctx, struct MInterfacePointer, num_ifaces); + r.out.pdsaOxidBindings = &dualstring; + + status = dcerpc_RemoteActivation(p, ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + if(!W_ERROR_IS_OK(r.out.result)) { + return r.out.result; + } + + if(!W_ERROR_IS_OK(r.out.hr)) { + return r.out.hr; + } + + *ip = talloc_array(ctx, struct IUnknown *, num_ifaces); + for (i = 0; i < num_ifaces; i++) { + results[i] = r.out.results[i]; + (*ip)[i] = NULL; + if (W_ERROR_IS_OK(results[i])) { + status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].obj); + if (!NT_STATUS_IS_OK(status)) { + results[i] = ntstatus_to_werror(status); + } + } + } + + /* Add the OXID data for the returned oxid */ + m = object_exporter_by_oxid(ctx, r.out.pOxid); + m->bindings = *r.out.pdsaOxidBindings; + + return WERR_OK; +} + +WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct IUnknown **ip) +{ + struct dcom_object_exporter *m; + struct RemoteActivation r; + struct dcerpc_pipe *p; + struct DUALSTRINGARRAY dualstring; + NTSTATUS status; + struct MInterfacePointer pm; + uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + + if (!server) { + return com_get_class_object(ctx, clsid, iid, ip); + } + + status = dcom_connect_host(ctx, &p, server); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); + return ntstatus_to_werror(status); + } + + ZERO_STRUCT(r.in); + r.in.this.version.MajorVersion = COM_MAJOR_VERSION; + r.in.this.version.MinorVersion = COM_MINOR_VERSION; + r.in.this.cid = GUID_random(); + r.in.Clsid = *clsid; + r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; + r.in.num_protseqs = ARRAY_SIZE(protseq); + r.in.protseq = protseq; + r.in.Interfaces = 1; + r.in.pIIDs = iid; + r.in.Mode = MODE_GET_CLASS_OBJECT; + r.out.ifaces = ± + r.out.pdsaOxidBindings = &dualstring; + + status = dcerpc_RemoteActivation(p, ctx, &r); + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error while running RemoteActivation - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } + if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } + if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } + + /* Set up the interface data */ + dcom_IUnknown_from_OBJREF(ctx, ip, &pm.obj); + + /* Add the OXID data for the returned oxid */ + m = object_exporter_by_oxid(ctx, r.out.pOxid); + m->bindings = *r.out.pdsaOxidBindings; + + return WERR_OK; +} + +NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) +{ + struct dcerpc_binding binding; + struct GUID iid; + uint64_t oxid; + NTSTATUS status; + int i; + struct dcerpc_pipe *p; + TALLOC_CTX *tmp_ctx; + const char *uuid; + struct dcom_object_exporter *ox; + + ox = object_exporter_by_ip(iface->ctx, iface); + + tmp_ctx = talloc_new(NULL); + + p = ox->pipe; + + iid = iface->vtable->iid; + + uuid = GUID_string(tmp_ctx, &iid); + + if (p) { + if (!GUID_equal(&p->syntax.uuid, &iid)) { + struct dcerpc_pipe *p2; + ox->pipe->syntax.uuid = iid; + status = dcerpc_secondary_context(p, &p2, uuid, 0); + if (NT_STATUS_IS_OK(status)) { + p = p2; + } + } else { + p = talloc_reference(NULL, p); + } + *pp = p; + talloc_free(tmp_ctx); + return status; + } + + i = 0; + do { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, + ox->bindings.stringbindings[i]); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Error parsing string binding")); + } else { + status = dcerpc_pipe_connect_b(&p, &binding, + uuid, 0.0, + iface->ctx->dcom.domain, iface->ctx->dcom.user, + iface->ctx->dcom.password); + } + + i++; + } while (NT_STATUS_IS_ERR(status) && ox->bindings.stringbindings[i]); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); + talloc_free(tmp_ctx); + return status; + } + + DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); + + *pp = p; + talloc_free(tmp_ctx); + + return NT_STATUS_OK; +} + +NTSTATUS dcom_OBJREF_from_IUnknown(struct OBJREF *o, struct IUnknown *p) +{ + /* FIXME: Cache generated objref objects? */ + ZERO_STRUCTP(o); + + o->signature = OBJREF_SIGNATURE; + + if (!p) { + o->flags = OBJREF_NULL; + } else { + o->iid = p->vtable->iid; + /* + OBJREF_STANDARD + OBJREF_CUSTOM + OBJREF_HANDLER + */ + } + + return NT_STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS dcom_IUnknown_from_OBJREF(struct com_context *ctx, struct IUnknown **_p, struct OBJREF *o) +{ + struct IUnknown *p; + struct dcom_object_exporter *ox; + + switch(o->flags) { + case OBJREF_NULL: + *_p = NULL; + return NT_STATUS_OK; + + case OBJREF_STANDARD: + p = talloc(ctx, struct IUnknown); + p->ctx = ctx; + p->vtable = dcom_proxy_vtable_by_iid(&o->iid); + if (!p->vtable) { + DEBUG(0, ("Unable to find proxy class for interface with IID %s\n", GUID_string(ctx, &o->iid))); + return NT_STATUS_NOT_SUPPORTED; + } + + ox = object_exporter_by_oxid(ctx, o->u_objref.u_standard.std.oxid); + /* FIXME: Add object to list of objects to ping */ + *_p = p; + return NT_STATUS_OK; + + case OBJREF_HANDLER: + p = talloc(ctx, struct IUnknown); + p->ctx = ctx; + ox = object_exporter_by_oxid(ctx, o->u_objref.u_handler.std.oxid ); + /* FIXME: Add object to list of objects to ping */ +/*FIXME p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/ + /* FIXME: Do the custom unmarshaling call */ + + *_p = p; + return NT_STATUS_OK; + + case OBJREF_CUSTOM: + p = talloc(ctx, struct IUnknown); + p->ctx = ctx; + p->vtable = NULL; + /* FIXME: Do the actual custom unmarshaling call */ + *_p = p; + return NT_STATUS_NOT_SUPPORTED; + } + + return NT_STATUS_NOT_SUPPORTED; +} + +uint64_t dcom_get_current_oxid(void) +{ + return getpid(); +} diff --git a/source4/lib/com/dcom/tables.c b/source4/lib/com/dcom/tables.c new file mode 100644 index 0000000000..a824413b34 --- /dev/null +++ b/source4/lib/com/dcom/tables.c @@ -0,0 +1,50 @@ +/* + Unix SMB/CIFS implementation. + DCOM proxy tables functionality + Copyright (C) 2005 Jelmer Vernooij + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "dlinklist.h" +#include "librpc/gen_ndr/com_dcom.h" + +static struct dcom_proxy { + struct IUnknown_vtable *vtable; + struct dcom_proxy *prev, *next; +} *proxies = NULL; + +NTSTATUS dcom_register_proxy(struct IUnknown_vtable *proxy_vtable) +{ + struct dcom_proxy *proxy = talloc(talloc_autofree_context(), struct dcom_proxy); + + proxy->vtable = proxy_vtable; + DLIST_ADD(proxies, proxy); + + return NT_STATUS_OK; +} + +struct IUnknown_vtable *dcom_proxy_vtable_by_iid(struct GUID *iid) +{ + struct dcom_proxy *p; + for (p = proxies; p; p = p->next) { + if (GUID_equal(&p->vtable->iid, iid)) { + return p->vtable; + } + } + return NULL; +} diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h deleted file mode 100644 index dd21bb9d29..0000000000 --- a/source4/lib/dcom/common/dcom.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DCOM standard objects - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _DCOM_H /* _DCOM_H */ -#define _DCOM_H - -#include "librpc/ndr/ndr_dcom.h" - -struct dcom_context -{ - struct dcom_object_exporter { - struct dcom_object_exporter *prev, *next; - struct STRINGARRAY resolver_address; - struct DUALSTRINGARRAY bindings; - uint64_t oxid; - struct dcerpc_pipe *pipe; - struct dcom_object - { - struct dcom_object *prev, *next; - uint64_t oid; - void *private_data; - } *objects; - } *oxids; - const char *domain; - const char *user; - const char *password; - uint32_t dcerpc_flags; -}; - -struct dcom_interface_p -{ - struct com_context *ctx; - const struct com_interface *interface; - const void *vtable; /* Points to one of the available implementations */ - struct GUID ipid; - struct com_object *object; - int objref_flags; - int orpc_flags; - struct com_object_exporter *ox; - uint32_t private_references; -}; - -#endif /* _DCOM_H */ diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c deleted file mode 100644 index 315912ba3c..0000000000 --- a/source4/lib/dcom/common/main.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Main DCOM functionality - Copyright (C) 2004 Jelmer Vernooij - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "dlinklist.h" -#include "librpc/gen_ndr/ndr_epmapper.h" -#include "librpc/gen_ndr/ndr_remact.h" -#include "librpc/gen_ndr/ndr_oxidresolver.h" -#include "librpc/gen_ndr/ndr_dcom.h" - -#define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } - -static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) -{ - char *host, *endpoint; - - ZERO_STRUCTP(b); - - b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId); - - if (b->transport == -1) { - DEBUG(1, ("Can't find transport match endpoint protocol %d\n", bd->wTowerId)); - return NT_STATUS_NOT_SUPPORTED; - } - - host = talloc_strdup(mem_ctx, bd->NetworkAddr); - endpoint = strchr(host, '['); - - if (endpoint) { - *endpoint = '\0'; - endpoint++; - - endpoint[strlen(endpoint)-1] = '\0'; - } - - b->host = host; - b->endpoint = endpoint; - - return NT_STATUS_OK; -} - -static NTSTATUS dcom_connect_host(struct dcom_context *ctx, struct dcerpc_pipe **p, const char *server) -{ - struct dcerpc_binding bd; - enum dcerpc_transport_t available_transports[] = { NCACN_IP_TCP, NCACN_NP }; - int i; - NTSTATUS status; - TALLOC_CTX *mem_ctx = talloc_init("dcom_connect"); - - /* Allow server name to contain a binding string */ - if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { - status = dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->domain, ctx->user, ctx->password); - - talloc_free(mem_ctx); - return status; - } - talloc_free(mem_ctx); - - ZERO_STRUCT(bd); - bd.host = server; - - if (server == NULL) { - bd.transport = NCALRPC; - return dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->domain, ctx->user, ctx->password); - } - - for (i = 0; i < ARRAY_SIZE(available_transports); i++) - { - bd.transport = available_transports[i]; - - status = dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->domain, ctx->user, ctx->password); - - if (NT_STATUS_IS_OK(status)) { - return status; - } - } - - return status; -} - -WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user, const char *pass) -{ - *ctx = talloc(NULL, struct dcom_context); - (*ctx)->oxids = NULL; - (*ctx)->domain = talloc_strdup(*ctx, domain); - (*ctx)->user = talloc_strdup(*ctx, user); - (*ctx)->password = talloc_strdup(*ctx, pass); - (*ctx)->dcerpc_flags = 0; - - return WERR_OK; -} - -struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) -{ - struct dcom_object_exporter *m; - - for (m = ctx->oxids;m;m = m->next) { - if (m->oxid == oxid) { - break; - } - } - - /* Add oxid mapping if we couldn't find one */ - if (!m) { - m = talloc_zero(ctx, struct dcom_object_exporter); - m->oxid = oxid; - DLIST_ADD(ctx->oxids, m); - } - - return m; -} - -WERROR dcom_ping(struct dcom_context *ctx) -{ - /* FIXME: If OID's waiting in queue, do a ComplexPing call */ - /* FIXME: otherwise, do a SimplePing call */ - return WERR_OK; -} - -static WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) -{ - uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - struct dcerpc_pipe *p; - struct dcom_object_exporter *m; - NTSTATUS status; - struct RemoteActivation r; - struct DUALSTRINGARRAY dualstring; - int i; - - if (!server) { - return com_create_object(ctx, clsid, num_ifaces, iid, ip, results); - } - - status = dcom_connect_host(ctx, &p, server); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); - return ntstatus_to_werror(status); - } - - ZERO_STRUCT(r.in); - r.in.this.version.MajorVersion = COM_MAJOR_VERSION; - r.in.this.version.MinorVersion = COM_MINOR_VERSION; - r.in.this.cid = GUID_random(); - r.in.Clsid = *clsid; - r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; - r.in.num_protseqs = ARRAY_SIZE(protseq); - r.in.protseq = protseq; - r.in.Interfaces = num_ifaces; - r.in.pIIDs = iid; - r.out.ifaces = talloc_array(ctx, struct pMInterfacePointer, num_ifaces); - r.out.pdsaOxidBindings = &dualstring; - - status = dcerpc_RemoteActivation(p, ctx, &r); - if(NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - if(!W_ERROR_IS_OK(r.out.result)) { - return r.out.result; - } - - if(!W_ERROR_IS_OK(r.out.hr)) { - return r.out.hr; - } - - *ip = talloc_array(ctx, struct dcom_interface_p *, num_ifaces); - for (i = 0; i < num_ifaces; i++) { - results[i] = r.out.results[i]; - (*ip)[i] = NULL; - if (W_ERROR_IS_OK(results[i])) { - status = dcom_ifacep_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].p->obj); - if (NT_STATUS_IS_OK(status)) { - (*ip)[i]->private_references = 1; - } else { - results[i] = ntstatus_to_werror(status); - } - } - } - - /* Add the OXID data for the returned oxid */ - m = oxid_mapping_by_oxid(ctx, r.out.pOxid); - m->bindings = *r.out.pdsaOxidBindings; - - return WERR_OK; -} - -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) -{ - struct dcom_object_exporter *m; - struct RemoteActivation r; - struct dcerpc_pipe *p; - struct DUALSTRINGARRAY dualstring; - NTSTATUS status; - struct pMInterfacePointer pm; - uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - - if (!server) { - return com_get_class_object(ctx, clsid, iid, ip); - } - - status = dcom_connect_host(ctx, &p, server); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); - return ntstatus_to_werror(status); - } - - ZERO_STRUCT(r.in); - r.in.this.version.MajorVersion = COM_MAJOR_VERSION; - r.in.this.version.MinorVersion = COM_MINOR_VERSION; - r.in.this.cid = GUID_random(); - r.in.Clsid = *clsid; - r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; - r.in.num_protseqs = ARRAY_SIZE(protseq); - r.in.protseq = protseq; - r.in.Interfaces = 1; - r.in.pIIDs = iid; - r.in.Mode = MODE_GET_CLASS_OBJECT; - r.out.ifaces = ± - r.out.pdsaOxidBindings = &dualstring; - - status = dcerpc_RemoteActivation(p, ctx, &r); - if(NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error while running RemoteActivation - %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; } - if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; } - if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } - - /* Set up the interface data */ - dcom_ifacep_from_OBJREF(ctx, ip, &pm.p->obj); - (*ip)->private_references = 1; - - /* Add the OXID data for the returned oxid */ - m = oxid_mapping_by_oxid(ctx, r.out.pOxid); - m->bindings = *r.out.pdsaOxidBindings; - - return WERR_OK; -} - -NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) -{ - struct dcerpc_binding binding; - struct GUID iid; - uint64_t oxid; - NTSTATUS status; - int i; - struct dcerpc_pipe *p; - TALLOC_CTX *tmp_ctx; - const char *uuid; - - tmp_ctx = talloc_new(NULL); - - p = iface->ox->pipe; - - oxid = iface->ox->oxid; - iid = iface->interface->iid; - - uuid = GUID_string(tmp_ctx, &iid); - - if (p) { - if (!GUID_equal(&p->syntax.uuid, &iid)) { - struct dcerpc_pipe *p2; - iface->ox->pipe->syntax.uuid = iid; - status = dcerpc_secondary_context(p, &p2, uuid, 0); - if (NT_STATUS_IS_OK(status)) { - p = p2; - } - } else { - p = talloc_reference(NULL, p); - } - *pp = p; - talloc_free(tmp_ctx); - return status; - } - - i = 0; - do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, - iface->ox->bindings.stringbindings[i]); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Error parsing string binding")); - } else { - binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&p, &binding, - uuid, 0.0, - iface->ctx->domain, iface->ctx->user, - iface->ctx->password); - } - - i++; - } while (NT_STATUS_IS_ERR(status) && iface->ox->bindings.stringbindings[i]); - - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); - talloc_free(tmp_ctx); - return status; - } - - DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); - - *pp = p; - talloc_free(tmp_ctx); - - return NT_STATUS_OK; -} - -struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, uint64_t oid) -{ - struct dcom_object *o; - - for (o = ox->objects; o; o = o->next) { - if (o->oid == oid) { - break; - } - } - - if (o == NULL) { - o = talloc_zero(ox, struct dcom_object); - o->oid = oid; - DLIST_ADD(ox->objects, o); - } - - return o; -} - - -NTSTATUS dcom_OBJREF_from_ifacep(struct dcom_context *ctx, struct OBJREF *o, struct dcom_interface_p *_p) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) -{ - struct dcom_interface_p *p = talloc(ctx, struct dcom_interface_p); - - p->ctx = ctx; - p->interface = dcom_interface_by_iid(&o->iid); - if (!p->interface) { - DEBUG(0, ("Unable to find interface with IID %s\n", GUID_string(ctx, &o->iid))); - return NT_STATUS_NOT_SUPPORTED; - } - - p->private_references = 0; - p->objref_flags = o->flags; - - switch(p->objref_flags) { - case OBJREF_NULL: - p->object = NULL; - p->ox = NULL; - p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); - ZERO_STRUCT(p->ipid); - *_p = p; - return NT_STATUS_OK; - - case OBJREF_STANDARD: - p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_standard.std.oxid); - p->ipid = o->u_objref.u_standard.std.ipid; - p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); - p->ox->resolver_address = o->u_objref.u_standard.saResAddr; - p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); - *_p = p; - return NT_STATUS_OK; - - case OBJREF_HANDLER: - p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_handler.std.oxid ); - p->ipid = o->u_objref.u_handler.std.ipid; - p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); - p->ox->resolver_address = o->u_objref.u_handler.saResAddr; -/*FIXME p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/ - /* FIXME: Do the custom unmarshaling call */ - - *_p = p; - return NT_STATUS_OK; - - case OBJREF_CUSTOM: - { - p->vtable = NULL; - - /* FIXME: Do the actual custom unmarshaling call */ - p->ox = NULL; - p->object = NULL; - ZERO_STRUCT(p->ipid); - *_p = p; - return NT_STATUS_NOT_SUPPORTED; - } - } - - return NT_STATUS_NOT_SUPPORTED; - - -#if 0 - struct dcom_oxid_mapping *m; - /* Add OXID mapping if none present yet */ - if (!m) { - struct dcerpc_pipe *po; - struct ResolveOxid r; - uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - - DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", p->ox->oxid)); - - m = talloc_zero(p->ctx, struct dcom_oxid_mapping); - m->oxid = oxid; - - i = 0; - do { - status = dcerpc_binding_from_STRINGBINDING(p->ctx, &binding, p->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); - - if (NT_STATUS_IS_OK(status)) { - binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&po, &binding, DCERPC_IOXIDRESOLVER_UUID, DCERPC_IOXIDRESOLVER_VERSION, iface->ctx->domain, iface->ctx->user, iface->ctx->password); - } else { - DEBUG(1, ("Error parsing string binding - %s", nt_errstr(status))); - } - - i++; - } while (!NT_STATUS_IS_OK(status) && iface->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); - - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); - return status; - } - - r.in.pOxid = oxid; - r.in.cRequestedProtseqs = ARRAY_SIZE(protseq); - r.in.arRequestedProtseqs = protseq; - r.out.ppdsaOxidBindings = &m->bindings; - - status = dcerpc_ResolveOxid(po, iface->ctx, &r); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error while resolving OXID: %s\n", nt_errstr(status))); - return status; - } - - dcerpc_pipe_close(po); - - DLIST_ADD(iface->ctx->oxids, m); - } -#endif - - return NT_STATUS_NOT_SUPPORTED; -} - -uint64_t dcom_get_current_oxid(void) -{ - return getpid(); -} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk deleted file mode 100644 index ae8fe9c4b0..0000000000 --- a/source4/lib/dcom/config.mk +++ /dev/null @@ -1,19 +0,0 @@ -################################################ -# Start SUBSYSTEM LIBDCOM -#[SUBSYSTEM::LIBDCOM] -#ENABLE = NO -#INIT_OBJ_FILES = \ -# lib/dcom/common/main.o -#REQUIRED_SUBSYSTEMS = LIBCOM DCOM_PROXY_DCOM RPC_NDR_REMACT \ -# RPC_NDR_OXIDRESOLVER - -#[MODULE::DCOM_SIMPLE] -#ENABLE = NO -#SUBSYSTEM = LIBDCOM -#REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM -#INIT_FUNCTION = dcom_simple_init -#INIT_OBJ_FILES = \ -# lib/dcom/classes/simple.o -# -# End SUBSYSTEM LIBDCOM -################################################ -- cgit From dd2aefd56b0968da8b1c4d055bc8c2f30382fb23 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 6 Mar 2005 22:37:31 +0000 Subject: r5675: - More DCOM bug fixes - Keep COM and DCOM more seperated (This used to be commit f694f484c422d0c86beb58e8f62f134f8676d5e1) --- source4/lib/com/classes/simple.c | 14 +++++++++----- source4/lib/com/com.h | 12 +----------- source4/lib/com/dcom/dcom.h | 36 ++++++++++++++++++++++++++++++++++++ source4/lib/com/dcom/main.c | 11 ++++++----- 4 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 source4/lib/com/dcom/dcom.h (limited to 'source4/lib') diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c index a6134d4c36..ad03c17cce 100644 --- a/source4/lib/com/classes/simple.c +++ b/source4/lib/com/classes/simple.c @@ -22,8 +22,8 @@ #include "lib/com/com.h" #include "librpc/gen_ndr/com_dcom.h" -extern const struct IClassFactory_vtable simple_classobject_vtable; -extern const struct IStream_vtable simple_IStream_vtable; +extern struct IClassFactory_vtable simple_classobject_vtable; +extern struct IStream_vtable simple_IStream_vtable; static WERROR simple_IUnknown_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) { @@ -69,7 +69,7 @@ static WERROR simpleclass_IClassFactory_CreateInstance (struct IClassFactory *d, ret->vtable = &simple_IStream_vtable; ret->object_data = NULL; - *ppv = ret; + *ppv = (struct IUnknown *)ret; return WERR_OK; } @@ -85,7 +85,8 @@ static uint32_t simpleclass_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *me } /* Everything below this line should be autogenerated later on */ -const struct IClassFactory_vtable simple_classobject_vtable = { +struct IClassFactory_vtable simple_classobject_vtable = { + {}, simpleclass_IUnknown_QueryInterface, simpleclass_IUnknown_AddRef, simpleclass_IUnknown_Release, @@ -95,7 +96,8 @@ const struct IClassFactory_vtable simple_classobject_vtable = { NULL }; -const struct IStream_vtable simple_IStream_vtable = { +struct IStream_vtable simple_IStream_vtable = { + {}, simple_IUnknown_QueryInterface, simple_IUnknown_AddRef, simple_IUnknown_Release, @@ -113,6 +115,8 @@ NTSTATUS com_simple_init(void) class_object->vtable = (struct IUnknown_vtable *)&simple_classobject_vtable; GUID_from_string(CLSID_SIMPLE, &clsid); + GUID_from_string(COM_ICLASSFACTORY_UUID, &simple_classobject_vtable.iid); + GUID_from_string(COM_ISTREAM_UUID, &simple_IStream_vtable.iid); return com_register_running_class(&clsid, PROGID_SIMPLE, class_object); } diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h index a056d1d9ee..97841e14c3 100644 --- a/source4/lib/com/com.h +++ b/source4/lib/com/com.h @@ -25,17 +25,7 @@ struct IUnknown_vtable; struct com_context { - struct { - const char *domain; - const char *user; - const char *password; - struct dcom_object_exporter { - uint64_t oxid; - struct DUALSTRINGARRAY bindings; - struct dcerpc_pipe *pipe; - struct dcom_object_exporter *prev, *next; - } *object_exporters; - } dcom; + struct dcom_client_context *dcom; }; typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid); diff --git a/source4/lib/com/dcom/dcom.h b/source4/lib/com/dcom/dcom.h new file mode 100644 index 0000000000..668d952124 --- /dev/null +++ b/source4/lib/com/dcom/dcom.h @@ -0,0 +1,36 @@ +/* + Unix SMB/CIFS implementation. + COM standard objects + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _DCOM_H /* _DCOM_H */ +#define _DCOM_H + +struct dcom_client_context { + const char *domain; + const char *user; + const char *password; + struct dcom_object_exporter { + uint64_t oxid; + struct DUALSTRINGARRAY bindings; + struct dcerpc_pipe *pipe; + struct dcom_object_exporter *prev, *next; + } *object_exporters; +}; + +#endif /* _DCOM_H */ diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index b8c2eef82c..853af4c739 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -26,6 +26,7 @@ #include "librpc/gen_ndr/ndr_oxidresolver.h" #include "librpc/gen_ndr/ndr_dcom.h" #include "librpc/gen_ndr/com_dcom.h" +#include "lib/com/dcom/dcom.h" #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } @@ -71,7 +72,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** return dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); } /* Allow server name to contain a binding string */ @@ -79,7 +80,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); talloc_free(mem_ctx); return status; @@ -96,7 +97,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect_b(p, &bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom.domain, ctx->dcom.user, ctx->dcom.password); + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); if (NT_STATUS_IS_OK(status)) { return status; @@ -279,8 +280,8 @@ NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) } else { status = dcerpc_pipe_connect_b(&p, &binding, uuid, 0.0, - iface->ctx->dcom.domain, iface->ctx->dcom.user, - iface->ctx->dcom.password); + iface->ctx->dcom->domain, iface->ctx->dcom->user, + iface->ctx->dcom->password); } i++; -- cgit From d892500e733fa2c85f950b69f11546c0f037a25a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 7 Mar 2005 02:14:38 +0000 Subject: r5676: Fix some alignment issues and IRemoteActivation (This used to be commit a9b13f67012d235d98920e639f59411d57a79bd7) --- source4/lib/com/dcom/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index 853af4c739..7c9c3b4394 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -30,6 +30,16 @@ #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } +struct dcom_client_context *dcom_client_init(struct com_context *ctx, const char *domain, const char *user, const char *password) +{ + ctx->dcom = talloc(ctx, struct dcom_client_context); + ctx->dcom->domain = domain; + ctx->dcom->user = user; + ctx->dcom->password = password; + + return ctx->dcom; +} + static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) { char *host, *endpoint; -- cgit From 3e88cae57bd473b492735f90be86940e44e0e78d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 7 Mar 2005 12:02:48 +0000 Subject: r5680: Don't crash if none of the predefined keys is available (reported by Alexander) (This used to be commit 0d789872a890062b0b95aa039bb853bb6c07b2d0) --- source4/lib/registry/tools/regshell.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index ac7dbca49b..ee80837bab 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -408,8 +408,34 @@ static char **reg_completion(const char *text, int start, int end) } if (h) { - /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */ - reg_get_predefined_key(h, HKEY_CLASSES_ROOT, &curkey); + enum reg_predefined_key try_hkeys[] = { + HKEY_CLASSES_ROOT, + HKEY_CURRENT_USER, + HKEY_LOCAL_MACHINE, + HKEY_USERS, + HKEY_PERFORMANCE_DATA, + HKEY_CURRENT_CONFIG, + HKEY_DYN_DATA, + HKEY_PERFORMANCE_TEXT, + HKEY_PERFORMANCE_NLSTEXT, + 0 + }; + int i; + + for (i = 0; try_hkeys[i]; i++) { + WERROR err; + err = reg_get_predefined_key(h, HKEY_CLASSES_ROOT, &curkey); + if (W_ERROR_IS_OK(err)) { + break; + } else { + curkey = NULL; + } + } + } + + if (!curkey) { + fprintf(stderr, "Unable to access any of the predefined keys\n"); + return -1; } poptFreeContext(pc); -- cgit From bbb69c5a7a140813151942fd96f53585e6033099 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 7 Mar 2005 12:45:19 +0000 Subject: r5682: fix the build metze (This used to be commit 67a2b091261d4dee2ed518ae80fdd8c1d9bf0e86) --- source4/lib/com/dcom/main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index 7c9c3b4394..8ef2060eb7 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -153,7 +153,7 @@ WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const cha r.in.protseq = protseq; r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; - r.out.ifaces = talloc_array(ctx, struct MInterfacePointer, num_ifaces); + r.out.ifaces = talloc_array(ctx, struct pMInterfacePointer, num_ifaces); r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); @@ -175,7 +175,7 @@ WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const cha results[i] = r.out.results[i]; (*ip)[i] = NULL; if (W_ERROR_IS_OK(results[i])) { - status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].obj); + status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].ip->obj); if (!NT_STATUS_IS_OK(status)) { results[i] = ntstatus_to_werror(status); } @@ -197,6 +197,7 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const struct DUALSTRINGARRAY dualstring; NTSTATUS status; struct MInterfacePointer pm; + struct pMInterfacePointer ifaces[1]; uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; if (!server) { @@ -220,7 +221,8 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const r.in.Interfaces = 1; r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; - r.out.ifaces = ± + r.out.ifaces = ifaces; + ifaces[0].ip = ± r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); -- cgit From f58143b0256d470e17f2c0a09a7c1a352855d385 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 12 Mar 2005 09:55:08 +0000 Subject: r5769: Fix unused variable warning. (This used to be commit 80dfac3640443a41f7e45e9164ca1a6749494011) --- source4/lib/ldb/modules/timestamps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index dec564bf66..c472fc3c55 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -247,7 +247,7 @@ static const char *timestamps_errstring(struct ldb_module *module) static int timestamps_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; + /* struct ldb_module *ctx = module_ctx; */ /* put your clean-up functions here */ return 0; } -- cgit From e9ca6e48fff41c5f457075156a8c4b2c729c5527 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 12 Mar 2005 17:12:52 +0000 Subject: r5775: Remove some unused functions (unions are no longer as special as they used to be) Add oxid mapping table support in DCOM (This used to be commit e193555f0eec2dda8c8760e9668181200fef0a1e) --- source4/lib/com/dcom/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index 8ef2060eb7..4d9c635be8 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -119,7 +119,14 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** struct dcom_object_exporter *object_exporter_by_oxid(struct com_context *ctx, uint64_t oxid) { - return NULL; /* FIXME */ + struct dcom_object_exporter *ox; + for (ox = ctx->dcom->object_exporters; ox; ox = ox->next) { + if (ox->oxid == oxid) { + return ox; + } + } + + return NULL; } struct dcom_object_exporter *object_exporter_by_ip(struct com_context *ctx, struct IUnknown *ip) -- cgit From 639edc4097d1d5f011ce642b97b522ac4cb8b4ae Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 13 Mar 2005 01:40:45 +0000 Subject: r5779: Remove signal and timeout gubbage from tdb. (This used to be commit dbb56e9a59cf00d57b09ded6d60bf9424d5f1f4c) --- source4/lib/tdb/common/tdb.c | 28 +---------- source4/lib/tdb/common/tdbutil.c | 102 +-------------------------------------- source4/lib/tdb/include/tdb.h | 1 - 3 files changed, 4 insertions(+), 127 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 90b586d487..d9fabaeda9 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -61,7 +61,6 @@ #include #include #include -#include #include "tdb.h" #else #include "includes.h" @@ -193,18 +192,6 @@ struct list_struct { */ }; -/*************************************************************** - Allow a caller to set a "alarm" flag that tdb can check to abort - a blocking lock on SIGALRM. -***************************************************************/ - -static sig_atomic_t *palarm_fired; - -void tdb_set_lock_alarm(sig_atomic_t *palarm) -{ - palarm_fired = palarm; -} - /* a byte range locking function - return 0 on success this functions locks/unlocks 1 byte at the specified offset. @@ -231,27 +218,16 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, do { ret = fcntl(tdb->fd,lck_type,&fl); - if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) - break; } while (ret == -1 && errno == EINTR); if (ret == -1) { if (!probe && lck_type != F_SETLK) { /* Ensure error code is set for log fun to examine. */ - if (errno == EINTR && palarm_fired && *palarm_fired) - tdb->ecode = TDB_ERR_LOCK_TIMEOUT; - else - tdb->ecode = TDB_ERR_LOCK; + tdb->ecode = TDB_ERR_LOCK; TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", tdb->fd, offset, rw_type, lck_type)); } - /* Was it an alarm timeout ? */ - if (errno == EINTR && palarm_fired && *palarm_fired) { - TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1); - } - /* Otherwise - generic lock error. errno set by fcntl. + /* Generic lock error. errno set by fcntl. * EAGAIN is an expected return from non-blocking * locks. */ if (errno != EAGAIN) { diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index e3c5641054..3f9b227591 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -29,57 +29,6 @@ /* these are little tdb utility functions that are meant to make dealing with a tdb database a little less cumbersome in Samba */ -static sig_atomic_t gotalarm; - -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - - -/******************************************************************* - THIS is a copy of the function CatchSignal found in lib/signal.c - I need to copy it there to avoid sucking all of the samba source - into tdb. - - Catch a signal. This should implement the following semantics: - - 1) The handler remains installed after being called. - 2) The signal should be blocked during handler execution. -********************************************************************/ - -static void (*TdbCatchSignal(int signum,void (*handler)(int )))(int) -{ -#ifdef HAVE_SIGACTION - struct sigaction act; - struct sigaction oldact; - - ZERO_STRUCT(act); - - act.sa_handler = handler; -#ifdef SA_RESTART - /* - * We *want* SIGALRM to interrupt a system call. - */ - if(signum != SIGALRM) - act.sa_flags = SA_RESTART; -#endif - sigemptyset(&act.sa_mask); - sigaddset(&act.sa_mask,signum); - sigaction(signum,&act,&oldact); - return oldact.sa_handler; -#else /* !HAVE_SIGACTION */ - /* FIXME: need to handle sigvec and systems with broken signal() */ - return signal(signum, handler); -#endif -} - - - /*************************************************************** Make a TDB_DATA and keep the const warning in one place ****************************************************************/ @@ -92,53 +41,6 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) return ret; } -/**************************************************************************** - Lock a chain with timeout (in seconds). -****************************************************************************/ - -static int tdb_chainlock_with_timeout_internal(TDB_CONTEXT *tdb, TDB_DATA key, uint_t timeout, int rw_type) -{ - /* Allow tdb_chainlock to be interrupted by an alarm. */ - int ret; - gotalarm = 0; - tdb_set_lock_alarm(&gotalarm); - - if (timeout) { - TdbCatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(timeout); - } - - if (rw_type == F_RDLCK) - ret = tdb_chainlock_read(tdb, key); - else - ret = tdb_chainlock(tdb, key); - - if (timeout) { - alarm(0); - TdbCatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); - if (gotalarm) { - tdb->log_fn(tdb, 0, "tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n", - timeout, key.dptr, tdb->name); - /* TODO: If we time out waiting for a lock, it might - * be nice to use F_GETLK to get the pid of the - * process currently holding the lock and print that - * as part of the debugging message. -- mbp */ - return -1; - } - } - - return ret; -} - -/**************************************************************************** - Write lock a chain. Return -1 if timeout or lock failed. -****************************************************************************/ - -int tdb_chainlock_with_timeout(TDB_CONTEXT *tdb, TDB_DATA key, uint_t timeout) -{ - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); -} - /**************************************************************************** Lock a chain by string. Return -1 if timeout or lock failed. ****************************************************************************/ @@ -147,7 +49,7 @@ int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK); + return tdb_chainlock(tdb, key); } /**************************************************************************** @@ -169,7 +71,7 @@ int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK); + return tdb_chainlock_read(tdb, key); } /**************************************************************************** diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 1de5517d91..846b157758 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -138,7 +138,6 @@ int tdb_lockall(TDB_CONTEXT *tdb); void tdb_unlockall(TDB_CONTEXT *tdb); /* Low level locking functions: use with care */ -void tdb_set_lock_alarm(sig_atomic_t *palarm); int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key); -- cgit From 03cd26e353b74d88b02ce36dc73932452a7b3715 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 13 Mar 2005 02:20:51 +0000 Subject: r5780: Remove unused arguments. (This used to be commit 1ee84e373e2b44c96f9353f194b766d6a144e7ce) --- source4/lib/tdb/common/tdbutil.c | 12 ++++++------ source4/lib/tdb/include/tdbutil.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index 3f9b227591..df9ce4e238 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -42,10 +42,10 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) } /**************************************************************************** - Lock a chain by string. Return -1 if timeout or lock failed. + Lock a chain by string. Return -1 if lock failed. ****************************************************************************/ -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -64,10 +64,10 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) } /**************************************************************************** - Read lock a chain by string. Return -1 if timeout or lock failed. + Read lock a chain by string. Return -1 if lock failed. ****************************************************************************/ -int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout) +int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -252,7 +252,7 @@ int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *o int32_t val; int32_t ret = -1; - if (tdb_lock_bystring(tdb, keystr,0) == -1) + if (tdb_lock_bystring(tdb, keystr) == -1) return -1; if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { @@ -293,7 +293,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32_t *ol uint32_t val; BOOL ret = False; - if (tdb_lock_bystring(tdb, keystr,0) == -1) + if (tdb_lock_bystring(tdb, keystr) == -1) return False; if (!tdb_fetch_uint32(tdb, keystr, &val)) { diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index 80d93b7984..fb9e5cf48f 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -35,7 +35,7 @@ typedef struct keys_node TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); void tdb_search_list_free(TDB_LIST_NODE*); int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *oldval, int32_t change_val); -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, uint_t timeout); +int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval); void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval); int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr); int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v); -- cgit From ee461300a5a888d632f4046796ea119023d1303c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 13 Mar 2005 02:48:16 +0000 Subject: r5781: Fix build. (This used to be commit 35354456b2ab2fa173359fa16d8accb13a8fac7d) --- source4/lib/gencache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index b6d62977ad..2db66b7564 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -363,7 +363,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time int gencache_lock_entry( const char *key ) { - return tdb_lock_bystring(cache->tdb, key, 0); + return tdb_lock_bystring(cache->tdb, key); } /******************************************************************** -- cgit From d4c0da18a732d5d437eb1f0d9dd3279ef8cda649 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 18 Mar 2005 00:17:10 +0000 Subject: r5871: Remove file with unused function (that uses fstring) Remove fstring usage from version.c (This used to be commit d25163159c19d6f948551438f459d161ba6ea4ac) --- source4/lib/basic.mk | 1 - source4/lib/username.c | 51 -------------------------------------------------- source4/lib/version.c | 5 +++-- 3 files changed, 3 insertions(+), 54 deletions(-) delete mode 100644 source4/lib/username.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 5f9a60e114..257f59d8ed 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -45,7 +45,6 @@ ADD_OBJ_FILES = \ lib/system.o \ lib/time.o \ lib/genrand.o \ - lib/username.o \ lib/dprintf.o \ lib/xfile.o \ lib/util_str.o \ diff --git a/source4/lib/username.c b/source4/lib/username.c deleted file mode 100644 index 55965a7980..0000000000 --- a/source4/lib/username.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Username handling - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1997-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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "pstring.h" - -/***************************************************************** - Splits passed user or group name to domain and user/group name parts - Returns True if name was splitted and False otherwise. -*****************************************************************/ - -BOOL split_domain_and_name(const char *name, char *domain, char* username) -{ - char *p = strchr(name,*lp_winbind_separator()); - - - /* Parse a string of the form DOMAIN/user into a domain and a user */ - DEBUG(10,("split_domain_and_name: checking whether name |%s| local or not\n", name)); - - if (p) { - fstrcpy(username, p+1); - fstrcpy(domain, name); - domain[PTR_DIFF(p, name)] = 0; - } else if (lp_winbind_use_default_domain()) { - fstrcpy(username, name); - fstrcpy(domain, lp_workgroup()); - } else { - return False; - } - - DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and name is |%s|\n", domain, username)); - return True; -} diff --git a/source4/lib/version.c b/source4/lib/version.c index fb5ed3ce05..1adbc91385 100644 --- a/source4/lib/version.c +++ b/source4/lib/version.c @@ -27,13 +27,14 @@ const char *samba_version_string(void) #ifndef SAMBA_VERSION_VENDOR_SUFFIX return SAMBA_VERSION_OFFICIAL_STRING; #else - static fstring samba_version; + static char *samba_version; static BOOL init_samba_version; if (init_samba_version) return samba_version; - snprintf(samba_version,sizeof(samba_version),"%s-%s", + samba_version = talloc_asprintf( + talloc_autofree_context(), "%s-%s", SAMBA_VERSION_OFFICIAL_STRING, SAMBA_VERSION_VENDOR_SUFFIX); -- cgit From 3240f01636db144f765ec193de10196106537eb9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Mar 2005 06:07:33 +0000 Subject: r5898: Handle errors in the 'sync' name and IP address handling code. Andrew Bartlett (This used to be commit 6b8b40f73bd8b7ce23effc8eb1d808db77bcbf8b) --- source4/lib/socket/socket_ipv4.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 4f8b1e6dd6..93ddf68046 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -111,6 +111,9 @@ static NTSTATUS ipv4_connect(struct socket_context *sock, } srv_ip = interpret_addr2(srv_address); + if (!srv_ip.addr) { + return NT_STATUS_BAD_NETWORK_NAME; + } ZERO_STRUCT(srv_addr); #ifdef HAVE_SOCK_SIN_LEN -- cgit From df643022136a4b229aca817f5b57f7302a97f852 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Mar 2005 08:34:43 +0000 Subject: r5902: A rather large change... I wanted to add a simple 'workstation' argument to the DCERPC authenticated binding calls, but this patch kind of grew from there. With SCHANNEL, the 'workstation' name (the netbios name of the client) matters, as this is what ties the session between the NETLOGON ops and the SCHANNEL bind. This changes a lot of files, and these will again be changed when jelmer does the credentials work. I also correct some schannel IDL to distinguish between workstation names and account names. The distinction matters for domain trust accounts. Issues in handling this (issues with lifetime of talloc pointers) caused me to change the 'creds_CredentialsState' and 'struct dcerpc_binding' pointers to always be talloc()ed pointers. In the schannel DB, we now store both the domain and computername, and query on both. This should ensure we fault correctly when the domain is specified incorrectly in the SCHANNEL bind. In the RPC-SCHANNEL test, I finally fixed a bug that vl pointed out, where the comment claimed we re-used a connection, but in fact we made a new connection. This was achived by breaking apart some of the dcerpc_secondary_connection() logic. The addition of workstation handling was also propogated to NTLMSSP and GENSEC, for completeness. The RPC-SAMSYNC test has been cleaned up a little, using a loop over usernames/passwords rather than manually expanded tests. This will be expanded further (the code in #if 0 in this patch) to use a newly created user account for testing. In making this test pass test_rpc.sh, I found a bug in the RPC-ECHO server, caused by the removal of [ref] and the assoicated pointer from the IDL. This has been re-added, until the underlying pidl issues are solved. (This used to be commit 824289dcc20908ddec957a4a892a103eec2da9b9) --- source4/lib/com/dcom/main.c | 69 ++++++++++++++++++++-------------- source4/lib/registry/reg_backend_rpc.c | 1 + 2 files changed, 41 insertions(+), 29 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index 4d9c635be8..d3d44edc71 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -40,11 +40,15 @@ struct dcom_client_context *dcom_client_init(struct com_context *ctx, const char return ctx->dcom; } -static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding *b, struct STRINGBINDING *bd) +static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding **b_out, struct STRINGBINDING *bd) { char *host, *endpoint; + struct dcerpc_binding *b; - ZERO_STRUCTP(b); + b = talloc_zero(mem_ctx, struct dcerpc_binding); + if (!b) { + return NT_STATUS_NO_MEMORY; + } b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId); @@ -53,7 +57,7 @@ static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dc return NT_STATUS_NOT_SUPPORTED; } - host = talloc_strdup(mem_ctx, bd->NetworkAddr); + host = talloc_strdup(b, bd->NetworkAddr); endpoint = strchr(host, '['); if (endpoint) { @@ -64,56 +68,61 @@ static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dc } b->host = host; - b->endpoint = endpoint; + b->endpoint = talloc_strdup(b, endpoint); + *b_out = b; return NT_STATUS_OK; } static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe **p, const char *server) { - struct dcerpc_binding bd; - enum dcerpc_transport_t available_transports[] = { NCACN_IP_TCP, NCACN_NP }; + struct dcerpc_binding *bd; + const char * available_transports[] = { "ncacn_ip_tcp", "ncacn_np" }; int i; NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_init("dcom_connect"); if (server == NULL) { - bd.transport = NCALRPC; - return dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + return dcerpc_pipe_connect(p, "ncalrpc", + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + lp_netbios_name(), + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); } /* Allow server name to contain a binding string */ if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { - status = dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + status = dcerpc_pipe_connect_b(p, bd, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + lp_netbios_name(), + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); talloc_free(mem_ctx); return status; } - talloc_free(mem_ctx); - ZERO_STRUCT(bd); - bd.host = server; - for (i = 0; i < ARRAY_SIZE(available_transports); i++) { - bd.transport = available_transports[i]; + char *binding = talloc_asprintf(mem_ctx, "%s:%s", available_transports[i], server); + if (!binding) { + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } - status = dcerpc_pipe_connect_b(p, &bd, - DCERPC_IREMOTEACTIVATION_UUID, - DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + status = dcerpc_pipe_connect(p, binding, + DCERPC_IREMOTEACTIVATION_UUID, + DCERPC_IREMOTEACTIVATION_VERSION, + lp_netbios_name(), + ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); if (NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return status; } } + talloc_free(mem_ctx); return status; } @@ -254,7 +263,7 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) { - struct dcerpc_binding binding; + struct dcerpc_binding *binding; struct GUID iid; uint64_t oxid; NTSTATUS status; @@ -297,14 +306,16 @@ NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error parsing string binding")); } else { - status = dcerpc_pipe_connect_b(&p, &binding, + status = dcerpc_pipe_connect_b(&p, binding, uuid, 0.0, - iface->ctx->dcom->domain, iface->ctx->dcom->user, + lp_netbios_name(), + iface->ctx->dcom->domain, + iface->ctx->dcom->user, iface->ctx->dcom->password); } - + talloc_free(binding); i++; - } while (NT_STATUS_IS_ERR(status) && ox->bindings.stringbindings[i]); + } while (!NT_STATUS_IS_OK(status) && ox->bindings.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 2302416554..4a285262c6 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -384,6 +384,7 @@ WERROR reg_open_remote (struct registry_context **ctx, const char *user, const c status = dcerpc_pipe_connect(&p, location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, + lp_netbios_name(), lp_workgroup(), user, pass); (*ctx)->backend_data = p; -- cgit From 63b5ad6d5403f97423af0e8c542714ed691e667f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Mar 2005 10:28:31 +0000 Subject: r5903: While I can't test IPv6, metze asked me to commit a matching change for unknown hosts that I just did for IPv4. Andrew Bartlett (This used to be commit 7e1d82a200b3c679b727e0ef28a245389708ae2f) --- source4/lib/socket/socket_ipv6.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 2384e60550..25c5ca5798 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -105,6 +105,9 @@ static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, } srv_ip = interpret_addr6(srv_address); + if (memcmp(&srv_ip, &in6addr_any, sizeof(srv_ip)) == 0) { + return NT_STATUS_BAD_NETWORK_NAME; + } ZERO_STRUCT(srv_addr); srv_addr.sin6_addr = srv_ip; -- cgit From 105660d3f9b537fa47fe6e33c0418a1d8f85e0e9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 19 Mar 2005 19:31:25 +0000 Subject: r5906: Fix the usage of the internal popt (make proto should ignore it) Updated included popt to 1.7. (This used to be commit d60cb643e8a46771f3d836307ea45b869f34dc9b) --- source4/lib/popt/CHANGES | 5 +- source4/lib/popt/README | 2 +- source4/lib/popt/config.m4 | 15 +- source4/lib/popt/config.mk | 11 + source4/lib/popt/findme.c | 33 +- source4/lib/popt/findme.h | 16 +- source4/lib/popt/popt.c | 1048 +++++++++++++++++++++++++++++------------ source4/lib/popt/popt.h | 585 +++++++++++++++++++---- source4/lib/popt/poptconfig.c | 176 ++++--- source4/lib/popt/popthelp.c | 680 +++++++++++++++++++++----- source4/lib/popt/poptint.h | 103 ++-- source4/lib/popt/poptparse.c | 169 ++++++- source4/lib/popt/system.h | 23 +- 13 files changed, 2205 insertions(+), 661 deletions(-) create mode 100644 source4/lib/popt/config.mk (limited to 'source4/lib') diff --git a/source4/lib/popt/CHANGES b/source4/lib/popt/CHANGES index b6ab2aa308..db16a5fdd0 100644 --- a/source4/lib/popt/CHANGES +++ b/source4/lib/popt/CHANGES @@ -1,4 +1,7 @@ -1.3 -> +1.5 -> 1.6 + - add ability to perform callbacks for every, not just first, match. + +1.3 -> 1.5 - heavy dose of const's - poptParseArgvString() now NULL terminates the list diff --git a/source4/lib/popt/README b/source4/lib/popt/README index 7fccc836ff..0b5205bfdd 100644 --- a/source4/lib/popt/README +++ b/source4/lib/popt/README @@ -5,7 +5,7 @@ to getopt(3), it contains a number of enhancements, including: 2) popt can parse arbitrary argv[] style arrays while getopt(2) makes this quite difficult 3) popt allows users to alias command line arguments - 4) popt provides convience functions for parsting strings + 4) popt provides convience functions for parsing strings into argv[] style arrays popt is used by rpm, the Red Hat install program, and many other Red Hat diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index ff4455efa2..d5a8df9200 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -25,16 +25,17 @@ fi AC_MSG_CHECKING(whether to use included popt) if test x"$INCLUDED_POPT" != x"no"; then - TMP_LIBPOPT_OBJS="lib/popt/findme.o lib/popt/popt.o lib/popt/poptconfig.o \ - lib/popt/popthelp.o lib/popt/poptparse.o" CPPFLAGS="$CPPFLAGS -I$srcdir/lib/popt" + SMB_SUBSYSTEM(LIBPOPT,[], + [], + [INT_LIB_POPT]) AC_MSG_RESULT(yes) else + SMB_SUBSYSTEM(LIBPOPT,[], + [], + [EXT_LIB_POPT]) + SMB_EXT_LIB(POPT, [${TMP_LIBPOPT_LIBS}]) AC_MSG_RESULT(no) fi -SMB_EXT_LIB(POPT, [${TMP_LIBPOPT_LIBS}]) - -SMB_SUBSYSTEM(LIBPOPT,[], - [${TMP_LIBPOPT_OBJS}], - [EXT_LIB_POPT]) +AC_CHECK_HEADERS([float.h]) diff --git a/source4/lib/popt/config.mk b/source4/lib/popt/config.mk new file mode 100644 index 0000000000..fee3ab1e4b --- /dev/null +++ b/source4/lib/popt/config.mk @@ -0,0 +1,11 @@ +############################## +# Start SUBSYSTEM INT_LIB_POPT +[SUBSYSTEM::INT_LIB_POPT] +ADD_OBJ_FILES = lib/popt/findme.o \ + lib/popt/popt.o \ + lib/popt/poptconfig.o \ + lib/popt/popthelp.o \ + lib/popt/poptparse.o +NOPROTO = YES +# End SUBSYSTEM INT_LIB_POPT +############################## diff --git a/source4/lib/popt/findme.c b/source4/lib/popt/findme.c index 67a535ac65..a950e50018 100644 --- a/source4/lib/popt/findme.c +++ b/source4/lib/popt/findme.c @@ -1,47 +1,50 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/findme.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "findme.h" - const char * findProgramPath(const char * argv0) -{ +const char * findProgramPath(const char * argv0) { char * path = getenv("PATH"); char * pathbuf; char * start, * chptr; - char * buf, *local = NULL; + char * buf; - /* If there is a / in the argv[0], it has to be an absolute - path */ + if (argv0 == NULL) return NULL; /* XXX can't happen */ + /* If there is a / in the argv[0], it has to be an absolute path */ if (strchr(argv0, '/')) return xstrdup(argv0); - if (!path) return NULL; + if (path == NULL) return NULL; - local = start = pathbuf = malloc(strlen(path) + 1); - buf = malloc(strlen(path) + strlen(argv0) + 2); + start = pathbuf = alloca(strlen(path) + 1); + buf = malloc(strlen(path) + strlen(argv0) + sizeof("/")); + if (buf == NULL) return NULL; /* XXX can't happen */ strcpy(pathbuf, path); chptr = NULL; + /*@-branchstate@*/ do { if ((chptr = strchr(start, ':'))) *chptr = '\0'; sprintf(buf, "%s/%s", start, argv0); - if (!access(buf, X_OK)) { - if (local) free(local); - return buf; - } + if (!access(buf, X_OK)) + return buf; if (chptr) start = chptr + 1; else start = NULL; } while (start && *start); + /*@=branchstate@*/ free(buf); - if (local) free(local); return NULL; } diff --git a/source4/lib/popt/findme.h b/source4/lib/popt/findme.h index 5e93963d60..a016b867ea 100644 --- a/source4/lib/popt/findme.h +++ b/source4/lib/popt/findme.h @@ -1,10 +1,20 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/findme.h + */ + +/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_FINDME #define H_FINDME -const char * findProgramPath(const char * argv0); +/** + * Return absolute path to executable by searching PATH. + * @param argv0 name of executable + * @return (malloc'd) absolute path to executable (or NULL) + */ +/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0) + /*@*/; #endif diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c index a607f19f2f..eb81c720f5 100644 --- a/source4/lib/popt/popt.c +++ b/source4/lib/popt/popt.c @@ -1,11 +1,28 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/popt.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist */ + +#undef MYDEBUG #include "system.h" + +#if HAVE_FLOAT_H +#include +#endif +#include + #include "findme.h" #include "poptint.h" +#ifdef MYDEBUG +/*@unchecked@*/ +int _popt_debug = 0; +#endif + #ifndef HAVE_STRERROR static char * strerror(int errno) { extern int sys_nerr; @@ -18,50 +35,143 @@ static char * strerror(int errno) { } #endif - void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) +#ifdef MYDEBUG +/*@unused@*/ static void prtcon(const char *msg, poptContext con) { - if (con->execPath) xfree(con->execPath); + if (msg) fprintf(stderr, "%s", msg); + fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n", + con, con->os, + (con->os->nextCharArg ? con->os->nextCharArg : ""), + (con->os->nextArg ? con->os->nextArg : ""), + con->os->next, + (con->os->argv && con->os->argv[con->os->next] + ? con->os->argv[con->os->next] : "")); +} +#endif + +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) +{ + con->execPath = _free(con->execPath); con->execPath = xstrdup(path); con->execAbsolute = allowAbsolute; + /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */ + return; + /*@=nullstate@*/ +} + +static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt) + /*@globals internalState@*/ + /*@modifies internalState@*/ +{ + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->arg == NULL) continue; /* XXX program error. */ + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + /* Recurse on included sub-tables. */ + invokeCallbacksPRE(con, opt->arg); + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + (opt->argInfo & POPT_CBFLAG_PRE)) + { /*@-castfcnptr@*/ + poptCallbackType cb = (poptCallbackType)opt->arg; + /*@=castfcnptr@*/ + /* Perform callback. */ + /*@-moduncon -noeffectuncon @*/ + cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); + /*@=moduncon =noeffectuncon @*/ + } + } } -static void invokeCallbacks(poptContext con, const struct poptOption * table, - int post) +static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt) + /*@globals internalState@*/ + /*@modifies internalState@*/ { - const struct poptOption * opt = table; - poptCallbackType cb; + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->arg == NULL) continue; /* XXX program error. */ + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + /* Recurse on included sub-tables. */ + invokeCallbacksPOST(con, opt->arg); + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + (opt->argInfo & POPT_CBFLAG_POST)) + { /*@-castfcnptr@*/ + poptCallbackType cb = (poptCallbackType)opt->arg; + /*@=castfcnptr@*/ + /* Perform callback. */ + /*@-moduncon -noeffectuncon @*/ + cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); + /*@=moduncon =noeffectuncon @*/ + } + } +} - while (opt->longName || opt->shortName || opt->arg) { +static void invokeCallbacksOPTION(poptContext con, + const struct poptOption * opt, + const struct poptOption * myOpt, + /*@null@*/ const void * myData, int shorty) + /*@globals internalState@*/ + /*@modifies internalState@*/ +{ + const struct poptOption * cbopt = NULL; + + if (opt != NULL) + for (; opt->longName || opt->shortName || opt->arg; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { - invokeCallbacks(con, opt->arg, post); - } else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) && - ((!post && (opt->argInfo & POPT_CBFLAG_PRE)) || - ( post && (opt->argInfo & POPT_CBFLAG_POST)))) { - cb = (poptCallbackType)opt->arg; - cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE, - NULL, NULL, opt->descrip); + /* Recurse on included sub-tables. */ + if (opt->arg != NULL) /* XXX program error */ + invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty); + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && + !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) { + /* Save callback info. */ + cbopt = opt; + } else if (cbopt != NULL && + ((myOpt->shortName && opt->shortName && shorty && + myOpt->shortName == opt->shortName) || + (myOpt->longName && opt->longName && + /*@-nullpass@*/ /* LCL: opt->longName != NULL */ + !strcmp(myOpt->longName, opt->longName))) + /*@=nullpass@*/ + ) + { /*@-castfcnptr@*/ + poptCallbackType cb = (poptCallbackType)cbopt->arg; + /*@=castfcnptr@*/ + const void * cbData = (cbopt->descrip ? cbopt->descrip : myData); + /* Perform callback. */ + if (cb != NULL) { /* XXX program error */ + /*@-moduncon -noeffectuncon @*/ + cb(con, POPT_CALLBACK_REASON_OPTION, myOpt, + con->os->nextArg, cbData); + /*@=moduncon =noeffectuncon @*/ + } + /* Terminate (unless explcitly continuing). */ + if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE)) + return; } - opt++; } } - poptContext poptGetContext(const char * name, int argc, const char ** argv, +poptContext poptGetContext(const char * name, int argc, const char ** argv, const struct poptOption * options, int flags) { poptContext con = malloc(sizeof(*con)); + if (con == NULL) return NULL; /* XXX can't happen */ memset(con, 0, sizeof(*con)); con->os = con->optionStack; con->os->argc = argc; + /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->os->argv = argv; + /*@=dependenttrans =assignexpose@*/ con->os->argb = NULL; if (!(flags & POPT_CONTEXT_KEEP_FIRST)) con->os->next = 1; /* skip argv[0] */ - con->leftovers = calloc( (argc + 1), sizeof(char *) ); + con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) ); + /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->options = options; + /*@=dependenttrans =assignexpose@*/ con->aliases = NULL; con->numAliases = 0; con->flags = flags; @@ -75,41 +185,38 @@ static void invokeCallbacks(poptContext con, const struct poptOption * table, if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) con->flags |= POPT_CONTEXT_POSIXMEHARDER; - if (name) - con->appName = strcpy(malloc(strlen(name) + 1), name); + if (name) { + char * t = malloc(strlen(name) + 1); + if (t) con->appName = strcpy(t, name); + } - invokeCallbacks(con, con->options, 0); + /*@-internalglobs@*/ + invokeCallbacksPRE(con, con->options); + /*@=internalglobs@*/ return con; } -static void cleanOSE(struct optionStackEntry *os) +static void cleanOSE(/*@special@*/ struct optionStackEntry *os) + /*@uses os @*/ + /*@releases os->nextArg, os->argv, os->argb @*/ + /*@modifies os @*/ { - if (os->nextArg) { - xfree(os->nextArg); - os->nextArg = NULL; - } - if (os->argv) { - xfree(os->argv); - os->argv = NULL; - } - if (os->argb) { - PBM_FREE(os->argb); - os->argb = NULL; - } + os->nextArg = _free(os->nextArg); + os->argv = _free(os->argv); + os->argb = PBM_FREE(os->argb); } - void poptResetContext(poptContext con) +/*@-boundswrite@*/ +void poptResetContext(poptContext con) { int i; + if (con == NULL) return; while (con->os > con->optionStack) { cleanOSE(con->os--); } - if (con->os->argb) { - PBM_FREE(con->os->argb); - con->os->argb = NULL; - } + con->os->argb = PBM_FREE(con->os->argb); con->os->currAlias = NULL; con->os->nextCharArg = NULL; con->os->nextArg = NULL; @@ -120,37 +227,47 @@ static void cleanOSE(struct optionStackEntry *os) con->restLeftover = 0; con->doExec = NULL; + if (con->finalArgv != NULL) for (i = 0; i < con->finalArgvCount; i++) { - if (con->finalArgv[i]) { - xfree(con->finalArgv[i]); - con->finalArgv[i] = NULL; - } + /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */ + con->finalArgv[i] = _free(con->finalArgv[i]); + /*@=unqualifiedtrans@*/ } con->finalArgvCount = 0; - - if (con->arg_strip) { - PBM_FREE(con->arg_strip); - con->arg_strip = NULL; - } + con->arg_strip = PBM_FREE(con->arg_strip); + /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */ + return; + /*@=nullstate@*/ } - -/* Only one of longName, shortName may be set at a time */ -static int handleExec(poptContext con, char * longName, char shortName) +/*@=boundswrite@*/ + +/* Only one of longName, shortName should be set, not both. */ +/*@-boundswrite@*/ +static int handleExec(/*@special@*/ poptContext con, + /*@null@*/ const char * longName, char shortName) + /*@uses con->execs, con->numExecs, con->flags, con->doExec, + con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/ + /*@modifies con @*/ { + poptItem item; int i; - i = con->numExecs - 1; - if (longName) { - while (i >= 0 && (!con->execs[i].longName || - strcmp(con->execs[i].longName, longName))) i--; - } else { - while (i >= 0 && - con->execs[i].shortName != shortName) i--; - } + if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */ + return 0; + for (i = con->numExecs - 1; i >= 0; i--) { + item = con->execs + i; + if (longName && !(item->option.longName && + !strcmp(longName, item->option.longName))) + continue; + else if (shortName != item->option.shortName) + continue; + break; + } if (i < 0) return 0; + if (con->flags & POPT_CONTEXT_NO_EXEC) return 1; @@ -168,46 +285,65 @@ static int handleExec(poptContext con, char * longName, char shortName) } i = con->finalArgvCount++; + if (con->finalArgv != NULL) /* XXX can't happen */ { char *s = malloc((longName ? strlen(longName) : 0) + 3); - if (longName) - sprintf(s, "--%s", longName); - else - sprintf(s, "-%c", shortName); - con->finalArgv[i] = s; + if (s != NULL) { /* XXX can't happen */ + if (longName) + sprintf(s, "--%s", longName); + else + sprintf(s, "-%c", shortName); + con->finalArgv[i] = s; + } else + con->finalArgv[i] = NULL; } + /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */ return 1; + /*@=nullstate@*/ } +/*@=boundswrite@*/ /* Only one of longName, shortName may be set at a time */ -static int handleAlias(poptContext con, const char * longName, char shortName, - /*@keep@*/ const char * nextCharArg) +static int handleAlias(/*@special@*/ poptContext con, + /*@null@*/ const char * longName, char shortName, + /*@exposed@*/ /*@null@*/ const char * nextCharArg) + /*@uses con->aliases, con->numAliases, con->optionStack, con->os, + con->os->currAlias, con->os->currAlias->option.longName @*/ + /*@modifies con @*/ { + poptItem item = con->os->currAlias; + int rc; int i; - if (con->os->currAlias && con->os->currAlias->longName && longName && - !strcmp(con->os->currAlias->longName, longName)) - return 0; - if (con->os->currAlias && shortName && - shortName == con->os->currAlias->shortName) + if (item) { + if (longName && (item->option.longName && + !strcmp(longName, item->option.longName))) + return 0; + if (shortName && shortName == item->option.shortName) + return 0; + } + + if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */ return 0; - i = con->numAliases - 1; - if (longName) { - while (i >= 0 && (!con->aliases[i].longName || - strcmp(con->aliases[i].longName, longName))) i--; - } else { - while (i >= 0 && - con->aliases[i].shortName != shortName) i--; + for (i = con->numAliases - 1; i >= 0; i--) { + item = con->aliases + i; + if (longName && !(item->option.longName && + !strcmp(longName, item->option.longName))) + continue; + else if (shortName != item->option.shortName) + continue; + break; } - if (i < 0) return 0; if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; +/*@-boundsread@*/ if (nextCharArg && *nextCharArg) con->os->nextCharArg = nextCharArg; +/*@=boundsread@*/ con->os++; con->os->next = 0; @@ -215,50 +351,67 @@ static int handleAlias(poptContext con, const char * longName, char shortName, con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; - poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, + rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; - return 1; + return (rc ? rc : 1); } -static void execCommand(poptContext con) +/*@-bounds -boundswrite @*/ +static int execCommand(poptContext con) + /*@globals internalState @*/ + /*@modifies internalState @*/ { + poptItem item = con->doExec; const char ** argv; - int pos = 0; - const char * script = con->doExec->script; + int argc = 0; + int rc; - argv = malloc(sizeof(*argv) * - (6 + con->numLeftovers + con->finalArgvCount)); + if (item == NULL) /*XXX can't happen*/ + return POPT_ERROR_NOARG; - if (!con->execAbsolute && strchr(script, '/')) return; + if (item->argv == NULL || item->argc < 1 || + (!con->execAbsolute && strchr(item->argv[0], '/'))) + return POPT_ERROR_NOARG; + + argv = malloc(sizeof(*argv) * + (6 + item->argc + con->numLeftovers + con->finalArgvCount)); + if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */ - if (!strchr(script, '/') && con->execPath) { - char *s = malloc(strlen(con->execPath) + strlen(script) + 2); - sprintf(s, "%s/%s", con->execPath, script); - argv[pos] = s; + if (!strchr(item->argv[0], '/') && con->execPath) { + char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/")); + sprintf(s, "%s/%s", con->execPath, item->argv[0]); + argv[argc] = s; } else { - argv[pos] = script; + argv[argc] = findProgramPath(item->argv[0]); } - pos++; + if (argv[argc++] == NULL) return POPT_ERROR_NOARG; - argv[pos] = findProgramPath(con->os->argv[0]); - if (argv[pos]) pos++; - argv[pos++] = ";"; + if (item->argc > 1) { + memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1)); + argc += (item->argc - 1); + } - memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount); - pos += con->finalArgvCount; + if (con->finalArgv != NULL && con->finalArgvCount > 0) { + memcpy(argv + argc, con->finalArgv, + sizeof(*argv) * con->finalArgvCount); + argc += con->finalArgvCount; + } - if (con->numLeftovers) { - argv[pos++] = "--"; - memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers); - pos += con->numLeftovers; + if (con->leftovers != NULL && con->numLeftovers > 0) { +#if 0 + argv[argc++] = "--"; +#endif + memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers); + argc += con->numLeftovers; } - argv[pos++] = NULL; + argv[argc] = NULL; #ifdef __hpux - setresuid(getuid(), getuid(),-1); + rc = setresuid(getuid(), getuid(),-1); + if (rc) return POPT_ERROR_ERRNO; #else /* * XXX " ... on BSD systems setuid() should be preferred over setreuid()" @@ -266,65 +419,109 @@ static void execCommand(poptContext con) * XXX from Norbert Warmuth */ #if defined(HAVE_SETUID) - setuid(getuid()); + rc = setuid(getuid()); + if (rc) return POPT_ERROR_ERRNO; #elif defined (HAVE_SETREUID) - setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */ + rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */ + if (rc) return POPT_ERROR_ERRNO; #else ; /* Can't drop privileges */ #endif #endif - execvp(argv[0], (char *const *)argv); -} + if (argv[0] == NULL) + return POPT_ERROR_NOARG; -/*@observer@*/ static const struct poptOption * -findOption(const struct poptOption * table, const char * longName, - char shortName, - /*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData, - int singleDash) +#ifdef MYDEBUG +if (_popt_debug) + { const char ** avp; + fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc); + for (avp = argv; *avp; avp++) + fprintf(stderr, " '%s'", *avp); + fprintf(stderr, "\n"); + } +#endif + + rc = execvp(argv[0], (char *const *)argv); + + return POPT_ERROR_ERRNO; +} +/*@=bounds =boundswrite @*/ + +/*@-boundswrite@*/ +/*@observer@*/ /*@null@*/ static const struct poptOption * +findOption(const struct poptOption * opt, /*@null@*/ const char * longName, + char shortName, + /*@null@*/ /*@out@*/ poptCallbackType * callback, + /*@null@*/ /*@out@*/ const void ** callbackData, + int singleDash) + /*@modifies *callback, *callbackData */ { - const struct poptOption * opt = table; - const struct poptOption * opt2; const struct poptOption * cb = NULL; /* This happens when a single - is given */ - if (singleDash && !shortName && !*longName) + if (singleDash && !shortName && (longName && *longName == '\0')) shortName = '-'; - while (opt->longName || opt->shortName || opt->arg) { + for (; opt->longName || opt->shortName || opt->arg; opt++) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + const struct poptOption * opt2; + + /* Recurse on included sub-tables. */ + if (opt->arg == NULL) continue; /* XXX program error */ opt2 = findOption(opt->arg, longName, shortName, callback, callbackData, singleDash); - if (opt2) { - if (*callback && !*callbackData) - *callbackData = opt->descrip; - return opt2; - } + if (opt2 == NULL) continue; + /* Sub-table data will be inheirited if no data yet. */ + if (!(callback && *callback)) return opt2; + if (!(callbackData && *callbackData == NULL)) return opt2; + /*@-observertrans -dependenttrans @*/ + *callbackData = opt->descrip; + /*@=observertrans =dependenttrans @*/ + return opt2; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { cb = opt; } else if (longName && opt->longName && (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && - !strcmp(longName, opt->longName)) { + /*@-nullpass@*/ /* LCL: opt->longName != NULL */ + !strcmp(longName, opt->longName)) + /*@=nullpass@*/ + { break; } else if (shortName && shortName == opt->shortName) { break; } - opt++; } - if (!opt->longName && !opt->shortName) return NULL; - *callbackData = NULL; - *callback = NULL; + if (!opt->longName && !opt->shortName) + return NULL; + /*@-modobserver -mods @*/ + if (callback) *callback = NULL; + if (callbackData) *callbackData = NULL; if (cb) { - *callback = (poptCallbackType)cb->arg; - if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) - *callbackData = cb->descrip; + if (callback) + /*@-castfcnptr@*/ + *callback = (poptCallbackType)cb->arg; + /*@=castfcnptr@*/ + if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) { + if (callbackData) + /*@-observertrans@*/ /* FIX: typedef double indirection. */ + *callbackData = cb->descrip; + /*@=observertrans@*/ + } } + /*@=modobserver =mods @*/ return opt; } +/*@=boundswrite@*/ -static const char *findNextArg(poptContext con, unsigned argx, int delete) +static const char * findNextArg(/*@special@*/ poptContext con, + unsigned argx, int delete_arg) + /*@uses con->optionStack, con->os, + con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ + /*@modifies con @*/ { struct optionStackEntry * os = con->os; const char * arg; @@ -334,43 +531,59 @@ static const char *findNextArg(poptContext con, unsigned argx, int delete) arg = NULL; while (os->next == os->argc && os > con->optionStack) os--; if (os->next == os->argc && os == con->optionStack) break; + if (os->argv != NULL) for (i = os->next; i < os->argc; i++) { - if (os->argb && PBM_ISSET(i, os->argb)) continue; - if (*os->argv[i] == '-') continue; - if (--argx > 0) continue; + /*@-sizeoftype@*/ + if (os->argb && PBM_ISSET(i, os->argb)) + /*@innercontinue@*/ continue; + if (*os->argv[i] == '-') + /*@innercontinue@*/ continue; + if (--argx > 0) + /*@innercontinue@*/ continue; arg = os->argv[i]; - if (delete) { + if (delete_arg) { if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc); + if (os->argb != NULL) /* XXX can't happen */ PBM_SET(i, os->argb); } - break; + /*@innerbreak@*/ break; + /*@=sizeoftype@*/ } if (os > con->optionStack) os--; } while (arg == NULL); return arg; } -static /*@only@*/ const char * expandNextArg(poptContext con, const char * s) +/*@-boundswrite@*/ +static /*@only@*/ /*@null@*/ const char * +expandNextArg(/*@special@*/ poptContext con, const char * s) + /*@uses con->optionStack, con->os, + con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ + /*@modifies con @*/ { - const char *a; + const char * a = NULL; size_t alen; char *t, *te; size_t tn = strlen(s) + 1; char c; te = t = malloc(tn);; + if (t == NULL) return NULL; /* XXX can't happen */ while ((c = *s++) != '\0') { switch (c) { #if 0 /* XXX can't do this */ case '\\': /* escape */ c = *s++; - break; + /*@switchbreak@*/ break; #endif case '!': if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) - break; - if ((a = findNextArg(con, 1, 1)) == NULL) - break; + /*@switchbreak@*/ break; + /* XXX Make sure that findNextArg deletes only next arg. */ + if (a == NULL) { + if ((a = findNextArg(con, 1, 1)) == NULL) + /*@switchbreak@*/ break; + } s += 3; alen = strlen(a); @@ -380,53 +593,116 @@ static /*@only@*/ const char * expandNextArg(poptContext con, const char * s) te = t + strlen(t); strncpy(te, a, alen); te += alen; continue; - /*@notreached@*/ break; + /*@notreached@*/ /*@switchbreak@*/ break; default: - break; + /*@switchbreak@*/ break; } *te++ = c; } *te = '\0'; - t = realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */ + t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */ return t; } +/*@=boundswrite@*/ -static void poptStripArg(poptContext con, int which) +static void poptStripArg(/*@special@*/ poptContext con, int which) + /*@uses con->arg_strip, con->optionStack @*/ + /*@defines con->arg_strip @*/ + /*@modifies con @*/ { - if(con->arg_strip == NULL) { + /*@-sizeoftype@*/ + if (con->arg_strip == NULL) con->arg_strip = PBM_ALLOC(con->optionStack[0].argc); - } + if (con->arg_strip != NULL) /* XXX can't happen */ PBM_SET(which, con->arg_strip); + /*@=sizeoftype@*/ + /*@-compdef@*/ /* LCL: con->arg_strip udefined? */ + return; + /*@=compdef@*/ } +int poptSaveLong(long * arg, int argInfo, long aLong) +{ + /* XXX Check alignment, may fail on funky platforms. */ + if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) + return POPT_ERROR_NULLARG; + + if (argInfo & POPT_ARGFLAG_NOT) + aLong = ~aLong; + switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { + case 0: + *arg = aLong; + break; + case POPT_ARGFLAG_OR: + *arg |= aLong; + break; + case POPT_ARGFLAG_AND: + *arg &= aLong; + break; + case POPT_ARGFLAG_XOR: + *arg ^= aLong; + break; + default: + return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong) +{ + /* XXX Check alignment, may fail on funky platforms. */ + if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) + return POPT_ERROR_NULLARG; + + if (argInfo & POPT_ARGFLAG_NOT) + aLong = ~aLong; + switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { + case 0: + *arg = aLong; + break; + case POPT_ARGFLAG_OR: + *arg |= aLong; + break; + case POPT_ARGFLAG_AND: + *arg &= aLong; + break; + case POPT_ARGFLAG_XOR: + *arg ^= aLong; + break; + default: + return POPT_ERROR_BADOPERATION; + /*@notreached@*/ break; + } + return 0; +} + +/*@-boundswrite@*/ /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ - int poptGetNextOpt(poptContext con) +int poptGetNextOpt(poptContext con) { const struct poptOption * opt = NULL; int done = 0; - /* looks a bit tricky to get rid of alloca properly in this fn */ -#if HAVE_ALLOCA_H -#define ALLOCA(x) alloca(x) -#else -#define ALLOCA(x) malloc(x) -#endif - - + if (con == NULL) + return -1; while (!done) { const char * origOptString = NULL; poptCallbackType cb = NULL; const void * cbData = NULL; const char * longArg = NULL; int canstrip = 0; + int shorty = 0; while (!con->os->nextCharArg && con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } if (!con->os->nextCharArg && con->os->next == con->os->argc) { - invokeCallbacks(con, con->options, 1); - if (con->doExec) execCommand(con); + /*@-internalglobs@*/ + invokeCallbacksPOST(con, con->options); + /*@=internalglobs@*/ + if (con->doExec) return execCommand(con); return -1; } @@ -435,26 +711,36 @@ static void poptStripArg(poptContext con, int which) char * localOptString, * optString; int thisopt; + /*@-sizeoftype@*/ if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { con->os->next++; continue; } - thisopt=con->os->next; + /*@=sizeoftype@*/ + thisopt = con->os->next; + if (con->os->argv != NULL) /* XXX can't happen */ origOptString = con->os->argv[con->os->next++]; + if (origOptString == NULL) /* XXX can't happen */ + return POPT_ERROR_BADOPT; + if (con->restLeftover || *origOptString != '-') { - con->leftovers[con->numLeftovers++] = origOptString; if (con->flags & POPT_CONTEXT_POSIXMEHARDER) con->restLeftover = 1; + if (con->flags & POPT_CONTEXT_ARG_OPTS) { + con->os->nextArg = xstrdup(origOptString); + return 0; + } + if (con->leftovers != NULL) /* XXX can't happen */ + con->leftovers[con->numLeftovers++] = origOptString; continue; } /* Make a copy we can hack at */ localOptString = optString = - strcpy(ALLOCA(strlen(origOptString) + 1), - origOptString); + strcpy(alloca(strlen(origOptString) + 1), origOptString); - if (!optString[0]) + if (optString[0] == '\0') return POPT_ERROR_BADOPT; if (optString[1] == '-' && !optString[2]) { @@ -473,12 +759,13 @@ static void poptStripArg(poptContext con, int which) /* XXX aliases with arg substitution need "--alias=arg" */ if (handleAlias(con, optString, '\0', NULL)) continue; + if (handleExec(con, optString, '\0')) continue; /* Check for "--long=arg" option. */ for (oe = optString; *oe && *oe != '='; oe++) - ; + {}; if (*oe == '=') { *oe++ = '\0'; /* XXX longArg is mapped back to persistent storage. */ @@ -494,110 +781,175 @@ static void poptStripArg(poptContext con, int which) if (!opt) { con->os->nextCharArg = origOptString + 1; } else { - if(con->os == con->optionStack && - opt->argInfo & POPT_ARGFLAG_STRIP) { + if (con->os == con->optionStack && + opt->argInfo & POPT_ARGFLAG_STRIP) + { canstrip = 1; poptStripArg(con, thisopt); } + shorty = 0; } } /* Process next short option */ + /*@-branchstate@*/ /* FIX: W2DO? */ if (con->os->nextCharArg) { origOptString = con->os->nextCharArg; con->os->nextCharArg = NULL; - if (handleAlias(con, NULL, *origOptString, - origOptString + 1)) { + if (handleAlias(con, NULL, *origOptString, origOptString + 1)) + continue; + + if (handleExec(con, NULL, *origOptString)) { + /* Restore rest of short options for further processing */ origOptString++; + if (*origOptString != '\0') + con->os->nextCharArg = origOptString; continue; } - if (handleExec(con, NULL, *origOptString)) - continue; opt = findOption(con->options, NULL, *origOptString, &cb, &cbData, 0); if (!opt) return POPT_ERROR_BADOPT; + shorty = 1; origOptString++; - if (*origOptString) + if (*origOptString != '\0') con->os->nextCharArg = origOptString; } + /*@=branchstate@*/ + if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */ if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) { - *((int *)opt->arg) = 1; + if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L)) + return POPT_ERROR_BADOPERATION; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) { - if (opt->arg) - *((int *) opt->arg) = opt->val; - } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { - if (con->os->nextArg) { - xfree(con->os->nextArg); - con->os->nextArg = NULL; + if (opt->arg) { + if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val)) + return POPT_ERROR_BADOPERATION; } + } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { + con->os->nextArg = _free(con->os->nextArg); + /*@-usedef@*/ /* FIX: W2DO? */ if (longArg) { - con->os->nextArg = expandNextArg(con, longArg); + /*@=usedef@*/ + longArg = expandNextArg(con, longArg); + con->os->nextArg = longArg; } else if (con->os->nextCharArg) { - con->os->nextArg = expandNextArg(con, con->os->nextCharArg); + longArg = expandNextArg(con, con->os->nextCharArg); + con->os->nextArg = longArg; con->os->nextCharArg = NULL; } else { while (con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } - if (con->os->next == con->os->argc) - return POPT_ERROR_NOARG; - - /* make sure this isn't part of a short arg or the - result of an alias expansion */ - if(con->os == con->optionStack && - opt->argInfo & POPT_ARGFLAG_STRIP && - canstrip) { - poptStripArg(con, con->os->next); - } + if (con->os->next == con->os->argc) { + if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL)) + /*@-compdef@*/ /* FIX: con->os->argv not defined */ + return POPT_ERROR_NOARG; + /*@=compdef@*/ + con->os->nextArg = NULL; + } else { + + /* + * Make sure this isn't part of a short arg or the + * result of an alias expansion. + */ + if (con->os == con->optionStack && + (opt->argInfo & POPT_ARGFLAG_STRIP) && + canstrip) { + poptStripArg(con, con->os->next); + } - con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]); + if (con->os->argv != NULL) { /* XXX can't happen */ + /* XXX watchout: subtle side-effects live here. */ + longArg = con->os->argv[con->os->next++]; + longArg = expandNextArg(con, longArg); + con->os->nextArg = longArg; + } + } } + longArg = NULL; if (opt->arg) { - long aLong; - char *end; - switch (opt->argInfo & POPT_ARG_MASK) { - case POPT_ARG_STRING: + case POPT_ARG_STRING: /* XXX memory leak, hard to plug */ - *((const char **) opt->arg) = xstrdup(con->os->nextArg); - break; - - case POPT_ARG_INT: - case POPT_ARG_LONG: - aLong = strtol(con->os->nextArg, &end, 0); - if (!(end && *end == '\0')) - return POPT_ERROR_BADNUMBER; + *((const char **) opt->arg) = (con->os->nextArg) + ? xstrdup(con->os->nextArg) : NULL; + /*@switchbreak@*/ break; + + case POPT_ARG_INT: + case POPT_ARG_LONG: + { long aLong = 0; + char *end; + + if (con->os->nextArg) { + aLong = strtol(con->os->nextArg, &end, 0); + if (!(end && *end == '\0')) + return POPT_ERROR_BADNUMBER; + } - if (aLong == LONG_MIN || aLong == LONG_MAX) - return POPT_ERROR_OVERFLOW; if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { - *((long *) opt->arg) = aLong; + if (aLong == LONG_MIN || aLong == LONG_MAX) + return POPT_ERROR_OVERFLOW; + if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong)) + return POPT_ERROR_BADOPERATION; } else { if (aLong > INT_MAX || aLong < INT_MIN) return POPT_ERROR_OVERFLOW; - *((int *) opt->arg) = aLong; + if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong)) + return POPT_ERROR_BADOPERATION; + } + } /*@switchbreak@*/ break; + + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + { double aDouble = 0.0; + char *end; + + if (con->os->nextArg) { + /*@-mods@*/ + int saveerrno = errno; + errno = 0; + aDouble = strtod(con->os->nextArg, &end); + if (errno == ERANGE) + return POPT_ERROR_OVERFLOW; + errno = saveerrno; + /*@=mods@*/ + if (*end != '\0') + return POPT_ERROR_BADNUMBER; } - break; - default: - fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"), - opt->argInfo & POPT_ARG_MASK); + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) { + *((double *) opt->arg) = aDouble; + } else { +#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a)) + if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON) + return POPT_ERROR_OVERFLOW; + if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON) + return POPT_ERROR_OVERFLOW; + *((float *) opt->arg) = aDouble; + } + } /*@switchbreak@*/ break; + default: + fprintf(stdout, + POPT_("option type (%d) not implemented in popt\n"), + (opt->argInfo & POPT_ARG_MASK)); exit(EXIT_FAILURE); + /*@notreached@*/ /*@switchbreak@*/ break; } } } - if (cb) - cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData); - else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) + if (cb) { + /*@-internalglobs@*/ + invokeCallbacksOPTION(con, con->options, opt, cbData, shorty); + /*@=internalglobs@*/ + } else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) done = 1; if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { @@ -606,138 +958,222 @@ static void poptStripArg(poptContext con, int which) sizeof(*con->finalArgv) * con->finalArgvAlloced); } - { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); - if (opt->longName) - sprintf(s, "--%s", opt->longName); - else - sprintf(s, "-%c", opt->shortName); - con->finalArgv[con->finalArgvCount++] = s; + if (con->finalArgv != NULL) + { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); + if (s != NULL) { /* XXX can't happen */ + if (opt->longName) + sprintf(s, "%s%s", + ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + else + sprintf(s, "-%c", opt->shortName); + con->finalArgv[con->finalArgvCount++] = s; + } else + con->finalArgv[con->finalArgvCount++] = NULL; } - if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE - && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) { - con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg); + if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) + /*@-ifempty@*/ ; /*@=ifempty@*/ + else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) + /*@-ifempty@*/ ; /*@=ifempty@*/ + else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { + if (con->finalArgv != NULL && con->os->nextArg) + con->finalArgv[con->finalArgvCount++] = + /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */ + xstrdup(con->os->nextArg); + /*@=nullpass@*/ } } - return opt->val; + return (opt ? opt->val : -1); /* XXX can't happen */ } +/*@=boundswrite@*/ - const char * poptGetOptArg(poptContext con) +const char * poptGetOptArg(poptContext con) { - const char * ret = con->os->nextArg; - con->os->nextArg = NULL; + const char * ret = NULL; + /*@-branchstate@*/ + if (con) { + ret = con->os->nextArg; + con->os->nextArg = NULL; + } + /*@=branchstate@*/ return ret; } - const char * poptGetArg(poptContext con) +const char * poptGetArg(poptContext con) { - if (con->numLeftovers == con->nextLeftover) return NULL; - return con->leftovers[con->nextLeftover++]; + const char * ret = NULL; + if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover++]; + return ret; } - const char * poptPeekArg(poptContext con) +const char * poptPeekArg(poptContext con) { - if (con->numLeftovers == con->nextLeftover) return NULL; - return con->leftovers[con->nextLeftover]; + const char * ret = NULL; + if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) + ret = con->leftovers[con->nextLeftover]; + return ret; } - const char ** poptGetArgs(poptContext con) +/*@-boundswrite@*/ +const char ** poptGetArgs(poptContext con) { - if (con->numLeftovers == con->nextLeftover) return NULL; + if (con == NULL || + con->leftovers == NULL || con->numLeftovers == con->nextLeftover) + return NULL; /* some apps like [like RPM ;-) ] need this NULL terminated */ con->leftovers[con->numLeftovers] = NULL; + /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */ return (con->leftovers + con->nextLeftover); + /*@=nullret =nullstate @*/ } +/*@=boundswrite@*/ - void poptFreeContext(poptContext con) +poptContext poptFreeContext(poptContext con) { + poptItem item; int i; + if (con == NULL) return con; poptResetContext(con); - if (con->os->argb) free(con->os->argb); + con->os->argb = _free(con->os->argb); + if (con->aliases != NULL) for (i = 0; i < con->numAliases; i++) { - if (con->aliases[i].longName) xfree(con->aliases[i].longName); - free(con->aliases[i].argv); + item = con->aliases + i; + /*@-modobserver -observertrans -dependenttrans@*/ + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); + /*@=modobserver =observertrans =dependenttrans@*/ + item->argv = _free(item->argv); } + con->aliases = _free(con->aliases); + if (con->execs != NULL) for (i = 0; i < con->numExecs; i++) { - if (con->execs[i].longName) xfree(con->execs[i].longName); - xfree(con->execs[i].script); + item = con->execs + i; + /*@-modobserver -observertrans -dependenttrans@*/ + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); + /*@=modobserver =observertrans =dependenttrans@*/ + item->argv = _free(item->argv); } - if (con->execs) xfree(con->execs); - - free(con->leftovers); - free(con->finalArgv); - if (con->appName) xfree(con->appName); - if (con->aliases) free(con->aliases); - if (con->otherHelp) xfree(con->otherHelp); - if (con->execPath) xfree(con->execPath); - if (con->arg_strip) PBM_FREE(con->arg_strip); + con->execs = _free(con->execs); + + con->leftovers = _free(con->leftovers); + con->finalArgv = _free(con->finalArgv); + con->appName = _free(con->appName); + con->otherHelp = _free(con->otherHelp); + con->execPath = _free(con->execPath); + con->arg_strip = PBM_FREE(con->arg_strip); - free(con); + con = _free(con); + return con; } - int poptAddAlias(poptContext con, struct poptAlias newAlias, +int poptAddAlias(poptContext con, struct poptAlias alias, /*@unused@*/ int flags) { - int aliasNum = con->numAliases++; - struct poptAlias * alias; + poptItem item = alloca(sizeof(*item)); + memset(item, 0, sizeof(*item)); + item->option.longName = alias.longName; + item->option.shortName = alias.shortName; + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + item->option.arg = 0; + item->option.val = 0; + item->option.descrip = NULL; + item->option.argDescrip = NULL; + item->argc = alias.argc; + item->argv = alias.argv; + return poptAddItem(con, item, 0); +} - /* SunOS won't realloc(NULL, ...) */ - if (!con->aliases) - con->aliases = malloc(sizeof(newAlias) * con->numAliases); - else - con->aliases = realloc(con->aliases, - sizeof(newAlias) * con->numAliases); - alias = con->aliases + aliasNum; +/*@-boundswrite@*/ +/*@-mustmod@*/ /* LCL: con not modified? */ +int poptAddItem(poptContext con, poptItem newItem, int flags) +{ + poptItem * items, item; + int * nitems; + + switch (flags) { + case 1: + items = &con->execs; + nitems = &con->numExecs; + break; + case 0: + items = &con->aliases; + nitems = &con->numAliases; + break; + default: + return 1; + /*@notreached@*/ break; + } + + *items = realloc((*items), ((*nitems) + 1) * sizeof(**items)); + if ((*items) == NULL) + return 1; + + item = (*items) + (*nitems); + + item->option.longName = + (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL); + item->option.shortName = newItem->option.shortName; + item->option.argInfo = newItem->option.argInfo; + item->option.arg = newItem->option.arg; + item->option.val = newItem->option.val; + item->option.descrip = + (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL); + item->option.argDescrip = + (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL); + item->argc = newItem->argc; + item->argv = newItem->argv; - alias->longName = (newAlias.longName) - ? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName) - : NULL; - alias->shortName = newAlias.shortName; - alias->argc = newAlias.argc; - alias->argv = newAlias.argv; + (*nitems)++; return 0; } +/*@=mustmod@*/ +/*@=boundswrite@*/ - const char * poptBadOption(poptContext con, int flags) +const char * poptBadOption(poptContext con, int flags) { - struct optionStackEntry * os; + struct optionStackEntry * os = NULL; - if (flags & POPT_BADOPTION_NOALIAS) - os = con->optionStack; - else - os = con->os; + if (con != NULL) + os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os; - return os->argv[os->next - 1]; + /*@-nullderef@*/ /* LCL: os->argv != NULL */ + return (os && os->argv ? os->argv[os->next - 1] : NULL); + /*@=nullderef@*/ } -#define POPT_ERROR_NOARG -10 -#define POPT_ERROR_BADOPT -11 -#define POPT_ERROR_OPTSTOODEEP -13 -#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ -#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ - - const char *poptStrerror(const int error) +const char *const poptStrerror(const int error) { switch (error) { case POPT_ERROR_NOARG: return POPT_("missing argument"); case POPT_ERROR_BADOPT: return POPT_("unknown option"); + case POPT_ERROR_BADOPERATION: + return POPT_("mutually exclusive logical operations requested"); + case POPT_ERROR_NULLARG: + return POPT_("opt->arg should not be NULL"); case POPT_ERROR_OPTSTOODEEP: return POPT_("aliases nested too deeply"); case POPT_ERROR_BADQUOTE: - return POPT_("error in paramter quoting"); + return POPT_("error in parameter quoting"); case POPT_ERROR_BADNUMBER: return POPT_("invalid numeric value"); case POPT_ERROR_OVERFLOW: return POPT_("number too large or too small"); + case POPT_ERROR_MALLOC: + return POPT_("memory allocation failed"); case POPT_ERROR_ERRNO: return strerror(errno); default: @@ -745,54 +1181,56 @@ static void poptStripArg(poptContext con, int which) } } - int poptStuffArgs(poptContext con, const char ** argv) +int poptStuffArgs(poptContext con, const char ** argv) { int argc; + int rc; if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; for (argc = 0; argv[argc]; argc++) - ; + {}; con->os++; con->os->next = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = NULL; - poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); + rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; con->os->stuffed = 1; - return 0; + return rc; } - const char * poptGetInvocationName(poptContext con) +const char * poptGetInvocationName(poptContext con) { - return con->os->argv[0]; + return (con->os->argv ? con->os->argv[0] : ""); } - int poptStrippedArgv(poptContext con, int argc, char **argv) +/*@-boundswrite@*/ +int poptStrippedArgv(poptContext con, int argc, char ** argv) { - int i,j=1, numargs=argc; + int numargs = argc; + int j = 1; + int i; - for(i=1; iarg_strip)) { + /*@-sizeoftype@*/ + if (con->arg_strip) + for (i = 1; i < argc; i++) { + if (PBM_ISSET(i, con->arg_strip)) numargs--; - } } - for(i=1; iarg_strip)) { + for (i = 1; i < argc; i++) { + if (con->arg_strip && PBM_ISSET(i, con->arg_strip)) continue; - } else { - if(j /* for FILE * */ #define POPT_OPTION_DEPTH 10 -#define POPT_ARG_NONE 0 -#define POPT_ARG_STRING 1 -#define POPT_ARG_INT 2 -#define POPT_ARG_LONG 3 -#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */ -#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be +/** \ingroup popt + * \name Arg type identifiers + */ +/*@{*/ +#define POPT_ARG_NONE 0 /*!< no arg */ +#define POPT_ARG_STRING 1 /*!< arg will be saved as string */ +#define POPT_ARG_INT 2 /*!< arg will be converted to int */ +#define POPT_ARG_LONG 3 /*!< arg will be converted to long */ +#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */ +#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be set first in table; arg points to callback, descrip points to callback data to pass */ -#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain +#define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain for this table and any included tables; arg points to the domain string */ -#define POPT_ARG_VAL 7 /* arg should take value val */ +#define POPT_ARG_VAL 7 /*!< arg should take value val */ +#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */ +#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */ + #define POPT_ARG_MASK 0x0000FFFF -#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */ -#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */ -#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */ -#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */ -#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */ -#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line, +/*@}*/ + +/** \ingroup popt + * \name Arg modifiers + */ +/*@{*/ +#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */ +#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */ +#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */ +#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */ + +#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */ +#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */ +#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */ +#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */ +#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */ +#define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */ +#define POPT_ARGFLAG_LOGICALOPS \ + (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR) + +#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR) + /*!< set arg bit(s) */ +#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND) + /*!< clear arg bit(s) */ + +#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */ + +/*@}*/ + +/** \ingroup popt + * \name Callback modifiers + */ +/*@{*/ +#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */ +#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */ +#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line, not the subtable */ +#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */ +#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */ +/*@}*/ -#define POPT_ERROR_NOARG -10 -#define POPT_ERROR_BADOPT -11 -#define POPT_ERROR_OPTSTOODEEP -13 -#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ -#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ -#define POPT_ERROR_BADNUMBER -17 -#define POPT_ERROR_OVERFLOW -18 +/** \ingroup popt + * \name Error return values + */ +/*@{*/ +#define POPT_ERROR_NOARG -10 /*!< missing argument */ +#define POPT_ERROR_BADOPT -11 /*!< unknown option */ +#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */ +#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */ +#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */ +#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */ +#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */ +#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */ +#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */ +#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */ +/*@}*/ -/* poptBadOption() flags */ -#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */ +/** \ingroup popt + * \name poptBadOption() flags + */ +/*@{*/ +#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */ +/*@}*/ -/* poptGetContext() flags */ -#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */ -#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */ -#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */ +/** \ingroup popt + * \name poptGetContext() flags + */ +/*@{*/ +#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */ +#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */ +#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */ +#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */ +/*@}*/ +/** \ingroup popt + */ struct poptOption { - /*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */ - char shortName; /* may be '\0' */ +/*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */ + char shortName; /*!< may be '\0' */ int argInfo; - /*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */ - int val; /* 0 means don't return, just update flag */ - /*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */ - /*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */ +/*@shared@*/ /*@null@*/ void * arg; /*!< depends on argInfo */ + int val; /*!< 0 means don't return, just update flag */ +/*@observer@*/ /*@null@*/ const char * descrip; /*!< description for autohelp -- may be NULL */ +/*@observer@*/ /*@null@*/ const char * argDescrip; /*!< argument description for autohelp */ }; +/** \ingroup popt + * A popt alias argument for poptAddAlias(). + */ struct poptAlias { - /*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */ - char shortName; /* may be '\0' */ +/*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */ + char shortName; /*!< may be '\0' */ int argc; - /*@owned@*/ const char ** argv; /* must be free()able */ +/*@owned@*/ const char ** argv; /*!< must be free()able */ }; +/** \ingroup popt + * A popt alias or exec argument for poptAddItem(). + */ +/*@-exporttype@*/ +typedef struct poptItem_s { + struct poptOption option; /*!< alias/exec name(s) and description. */ + int argc; /*!< (alias) no. of args. */ +/*@owned@*/ const char ** argv; /*!< (alias) args, must be free()able. */ +} * poptItem; +/*@=exporttype@*/ + +/** \ingroup popt + * \name Auto-generated help/usage + */ +/*@{*/ + +/** + * Empty table marker to enable displaying popt alias/exec options. + */ +/*@-exportvar@*/ +/*@unchecked@*/ /*@observer@*/ +extern struct poptOption poptAliasOptions[]; +/*@=exportvar@*/ +#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \ + 0, "Options implemented via popt alias/exec:", NULL }, + +/** + * Auto help table options. + */ +/*@-exportvar@*/ +/*@unchecked@*/ /*@observer@*/ extern struct poptOption poptHelpOptions[]; +/*@=exportvar@*/ #define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ - 0, "Help options", NULL }, + 0, "Help options:", NULL }, + +#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL } +/*@}*/ -typedef struct poptContext_s * poptContext; +/** \ingroup popt + */ +/*@-exporttype@*/ +typedef /*@abstract@*/ struct poptContext_s * poptContext; +/*@=exporttype@*/ + +/** \ingroup popt + */ #ifndef __cplusplus +/*@-exporttype -typeuse@*/ typedef struct poptOption * poptOption; +/*@=exporttype =typeuse@*/ +#endif + +/*@-exportconst@*/ +enum poptCallbackReason { + POPT_CALLBACK_REASON_PRE = 0, + POPT_CALLBACK_REASON_POST = 1, + POPT_CALLBACK_REASON_OPTION = 2 +}; +/*@=exportconst@*/ + +#ifdef __cplusplus +extern "C" { #endif +/*@-type@*/ + +/** \ingroup popt + * Table callback prototype. + * @param con context + * @param reason reason for callback + * @param opt option that triggered callback + * @param arg @todo Document. + * @param data @todo Document. + */ +typedef void (*poptCallbackType) (poptContext con, + enum poptCallbackReason reason, + /*@null@*/ const struct poptOption * opt, + /*@null@*/ const char * arg, + /*@null@*/ const void * data) + /*@*/; + +/** \ingroup popt + * Initialize popt context. + * @param name + * @param argc no. of arguments + * @param argv argument array + * @param options address of popt option table + * @param flags or'd POPT_CONTEXT_* bits + * @return initialized popt context + */ +/*@only@*/ /*@null@*/ poptContext poptGetContext( + /*@dependent@*/ /*@keep@*/ const char * name, + int argc, /*@dependent@*/ /*@keep@*/ const char ** argv, + /*@dependent@*/ /*@keep@*/ const struct poptOption * options, + int flags) + /*@*/; -enum poptCallbackReason { POPT_CALLBACK_REASON_PRE, - POPT_CALLBACK_REASON_POST, - POPT_CALLBACK_REASON_OPTION }; -typedef void (*poptCallbackType)(poptContext con, - enum poptCallbackReason reason, - const struct poptOption * opt, - const char * arg, const void * data); - -/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name, - int argc, /*@keep@*/ const char ** argv, - /*@keep@*/ const struct poptOption * options, int flags); -void poptResetContext(poptContext con); - -/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ -int poptGetNextOpt(poptContext con); -/* returns NULL if no argument is available */ -/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con); -/* returns NULL if no more options are available */ -/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con); -/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con); -/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con); -/* returns the option which caused the most recent error */ -/*@observer@*/ const char * poptBadOption(poptContext con, int flags); -void poptFreeContext( /*@only@*/ poptContext con); -int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv); -int poptAddAlias(poptContext con, struct poptAlias alias, int flags); -int poptReadConfigFile(poptContext con, const char * fn); -/* like above, but reads /etc/popt and $HOME/.popt along with environment - vars */ -int poptReadDefaultConfig(poptContext con, int useEnv); -/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated - the same as " and both may include \ quotes */ -int poptDupArgv(int argc, const char **argv, - /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); +/** \ingroup popt + * Reinitialize popt context. + * @param con context + */ +/*@-exportlocal@*/ +void poptResetContext(/*@null@*/poptContext con) + /*@modifies con @*/; +/*@=exportlocal@*/ + +/** \ingroup popt + * Return value of next option found. + * @param con context + * @return next option val, -1 on last item, POPT_ERROR_* on error + */ +int poptGetNextOpt(/*@null@*/poptContext con) + /*@globals fileSystem, internalState @*/ + /*@modifies con, fileSystem, internalState @*/; + +/*@-redecl@*/ +/** \ingroup popt + * Return next option argument (if any). + * @param con context + * @return option argument, NULL if no more options are available + */ +/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Return current option's argument. + * @param con context + * @return option argument, NULL if no more options are available + */ +/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Peek at current option's argument. + * @param con context + * @return option argument + */ +/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con) + /*@*/; + +/** \ingroup popt + * Return remaining arguments. + * @param con context + * @return argument array, terminated with NULL + */ +/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Return the option which caused the most recent error. + * @param con context + * @param flags + * @return offending option + */ +/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags) + /*@*/; +/*@=redecl@*/ + +/** \ingroup popt + * Destroy context. + * @param con context + * @return NULL always + */ +/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con) + /*@modifies con @*/; + +/** \ingroup popt + * Add arguments to context. + * @param con context + * @param argv argument array, NULL terminated + * @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure + */ +int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv) + /*@modifies con @*/; + +/** \ingroup popt + * Add alias to context. + * @todo Pass alias by reference, not value. + * @deprecated Use poptAddItem instead. + * @param con context + * @param alias alias to add + * @param flags (unused) + * @return 0 on success + */ +/*@unused@*/ +int poptAddAlias(poptContext con, struct poptAlias alias, int flags) + /*@modifies con @*/; + +/** \ingroup popt + * Add alias/exec item to context. + * @param con context + * @param newItem alias/exec item to add + * @param flags 0 for alias, 1 for exec + * @return 0 on success + */ +int poptAddItem(poptContext con, poptItem newItem, int flags) + /*@modifies con @*/; + +/** \ingroup popt + * Read configuration file. + * @param con context + * @param fn file name to read + * @return 0 on success, POPT_ERROR_ERRNO on failure + */ +int poptReadConfigFile(poptContext con, const char * fn) + /*@globals fileSystem, internalState @*/ + /*@modifies con->execs, con->numExecs, + fileSystem, internalState @*/; + +/** \ingroup popt + * Read default configuration from /etc/popt and $HOME/.popt. + * @param con context + * @param useEnv (unused) + * @return 0 on success, POPT_ERROR_ERRNO on failure + */ +int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) + /*@globals fileSystem, internalState @*/ + /*@modifies con->execs, con->numExecs, + fileSystem, internalState @*/; + +/** \ingroup popt + * Duplicate an argument array. + * @note: The argument array is malloc'd as a single area, so only argv must + * be free'd. + * + * @param argc no. of arguments + * @param argv argument array + * @retval argcPtr address of returned no. of arguments + * @retval argvPtr address of returned argument array + * @return 0 on success, POPT_ERROR_NOARG on failure + */ +int poptDupArgv(int argc, /*@null@*/ const char **argv, + /*@null@*/ /*@out@*/ int * argcPtr, + /*@null@*/ /*@out@*/ const char *** argvPtr) + /*@modifies *argcPtr, *argvPtr @*/; + +/** \ingroup popt + * Parse a string into an argument array. + * The parse allows ', ", and \ quoting, but ' is treated the same as " and + * both may include \ quotes. + * @note: The argument array is malloc'd as a single area, so only argv must + * be free'd. + * + * @param s string to parse + * @retval argcPtr address of returned no. of arguments + * @retval argvPtr address of returned argument array + */ int poptParseArgvString(const char * s, - /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); -/*@observer@*/ const char *poptStrerror(const int error); -void poptSetExecPath(poptContext con, const char * path, int allowAbsolute); -void poptPrintHelp(poptContext con, FILE * f, int flags); -void poptPrintUsage(poptContext con, FILE * f, int flags); -void poptSetOtherOptionHelp(poptContext con, const char * text); -/*@observer@*/ const char * poptGetInvocationName(poptContext con); -/* shuffles argv pointers to remove stripped args, returns new argc */ -int poptStrippedArgv(poptContext con, int argc, char **argv); + /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr) + /*@modifies *argcPtr, *argvPtr @*/; + +/** \ingroup popt + * Parses an input configuration file and returns an string that is a + * command line. For use with popt. You must free the return value when done. + * + * Given the file: +\verbatim +# this line is ignored + # this one too +aaa + bbb + ccc +bla=bla + +this_is = fdsafdas + bad_line= + reall bad line + reall bad line = again +5555= 55555 + test = with lots of spaces +\endverbatim +* +* The result is: +\verbatim +--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces" +\endverbatim +* +* Passing this to poptParseArgvString() yields an argv of: +\verbatim +'--aaa' +'--bbb' +'--ccc' +'--bla=bla' +'--this_is=fdsafdas' +'--5555=55555' +'--test=with lots of spaces' +\endverbatim + * + * @bug NULL is returned if file line is too long. + * @bug Silently ignores invalid lines. + * + * @param fp file handle to read + * @param *argstrp return string of options (malloc'd) + * @param flags unused + * @return 0 on success + * @see poptParseArgvString + */ +/*@-fcnuse@*/ +int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags) + /*@globals fileSystem @*/ + /*@modifies *fp, *argstrp, fileSystem @*/; +/*@=fcnuse@*/ + +/** \ingroup popt + * Return formatted error string for popt failure. + * @param error popt error + * @return error string + */ +/*@-redecl@*/ +/*@observer@*/ const char *const poptStrerror(const int error) + /*@*/; +/*@=redecl@*/ + +/** \ingroup popt + * Limit search for executables. + * @param con context + * @param path single path to search for executables + * @param allowAbsolute absolute paths only? + */ +void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) + /*@modifies con @*/; + +/** \ingroup popt + * Print detailed description of options. + * @param con context + * @param fp ouput file handle + * @param flags (unused) + */ +void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/; + +/** \ingroup popt + * Print terse description of options. + * @param con context + * @param fp ouput file handle + * @param flags (unused) + */ +void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/; + +/** \ingroup popt + * Provide text to replace default "[OPTION...]" in help/usage output. + * @param con context + * @param text replacement text + */ +/*@-fcnuse@*/ +void poptSetOtherOptionHelp(poptContext con, const char * text) + /*@modifies con @*/; +/*@=fcnuse@*/ + +/** \ingroup popt + * Return argv[0] from context. + * @param con context + * @return argv[0] + */ +/*@-redecl -fcnuse@*/ +/*@observer@*/ const char * poptGetInvocationName(poptContext con) + /*@*/; +/*@=redecl =fcnuse@*/ + +/** \ingroup popt + * Shuffle argv pointers to remove stripped args, returns new argc. + * @param con context + * @param argc no. of args + * @param argv arg vector + * @return new argc + */ +/*@-fcnuse@*/ +int poptStrippedArgv(poptContext con, int argc, char ** argv) + /*@modifies *argv @*/; +/*@=fcnuse@*/ + +/** + * Save a long, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg integer pointer, aligned on int boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong) + /*@modifies *arg @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ + +/** + * Save an integer, performing logical operation with value. + * @warning Alignment check may be too strict on certain platorms. + * @param arg integer pointer, aligned on int boundary. + * @param argInfo logical operation (see POPT_ARGFLAG_*) + * @param aLong value to use + * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION + */ +/*@-incondefs@*/ +int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong) + /*@modifies *arg @*/ + /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; +/*@=incondefs@*/ +/*@=type@*/ #ifdef __cplusplus } #endif diff --git a/source4/lib/popt/poptconfig.c b/source4/lib/popt/poptconfig.c index 113270a569..a600a92905 100644 --- a/source4/lib/popt/poptconfig.c +++ b/source4/lib/popt/poptconfig.c @@ -1,103 +1,147 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/poptconfig.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "poptint.h" +/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ static void configLine(poptContext con, char * line) + /*@modifies con @*/ { + /*@-type@*/ int nameLength = strlen(con->appName); - char * opt; - struct poptAlias alias; - char * entryType; - char * longName = NULL; - char shortName = '\0'; + /*@=type@*/ + const char * entryType; + const char * opt; + poptItem item = alloca(sizeof(*item)); + int i, j; +/*@-boundswrite@*/ + memset(item, 0, sizeof(*item)); + + /*@-type@*/ if (strncmp(line, con->appName, nameLength)) return; + /*@=type@*/ + line += nameLength; - if (!*line || !isspace(*line)) return; - while (*line && isspace(*line)) line++; - entryType = line; + if (*line == '\0' || !isspace(*line)) return; - while (!*line || !isspace(*line)) line++; + while (*line != '\0' && isspace(*line)) line++; + entryType = line; + while (*line == '\0' || !isspace(*line)) line++; *line++ = '\0'; - while (*line && isspace(*line)) line++; - if (!*line) return; - opt = line; - while (!*line || !isspace(*line)) line++; + while (*line != '\0' && isspace(*line)) line++; + if (*line == '\0') return; + opt = line; + while (*line == '\0' || !isspace(*line)) line++; *line++ = '\0'; - while (*line && isspace(*line)) line++; - if (!*line) return; + while (*line != '\0' && isspace(*line)) line++; + if (*line == '\0') return; + + /*@-temptrans@*/ /* FIX: line alias is saved */ if (opt[0] == '-' && opt[1] == '-') - longName = opt + 2; - else if (opt[0] == '-' && !opt[2]) - shortName = opt[1]; - - if (!strcmp(entryType, "alias")) { - if (poptParseArgvString(line, &alias.argc, &alias.argv)) return; - alias.longName = longName, alias.shortName = shortName; - poptAddAlias(con, alias, 0); - } else if (!strcmp(entryType, "exec")) { - con->execs = realloc(con->execs, - sizeof(*con->execs) * (con->numExecs + 1)); - if (longName) - con->execs[con->numExecs].longName = xstrdup(longName); - else - con->execs[con->numExecs].longName = NULL; - - con->execs[con->numExecs].shortName = shortName; - con->execs[con->numExecs].script = xstrdup(line); - - con->numExecs++; + item->option.longName = opt + 2; + else if (opt[0] == '-' && opt[2] == '\0') + item->option.shortName = opt[1]; + /*@=temptrans@*/ + + if (poptParseArgvString(line, &item->argc, &item->argv)) return; + + /*@-modobserver@*/ + item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; + for (i = 0, j = 0; i < item->argc; i++, j++) { + const char * f; + if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { + f = item->argv[i] + sizeof("--POPTdesc="); + if (f[0] == '$' && f[1] == '"') f++; + item->option.descrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + j--; + } else + if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { + f = item->argv[i] + sizeof("--POPTargs="); + if (f[0] == '$' && f[1] == '"') f++; + item->option.argDescrip = f; + item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; + item->option.argInfo |= POPT_ARG_STRING; + j--; + } else + if (j != i) + item->argv[j] = item->argv[i]; + } + if (j != i) { + item->argv[j] = NULL; + item->argc = j; } + /*@=modobserver@*/ +/*@=boundswrite@*/ + + /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ + if (!strcmp(entryType, "alias")) + (void) poptAddItem(con, item, 0); + else if (!strcmp(entryType, "exec")) + (void) poptAddItem(con, item, 1); + /*@=nullstate@*/ } +/*@=compmempass@*/ - int poptReadConfigFile(poptContext con, const char * fn) +int poptReadConfigFile(poptContext con, const char * fn) { - char * file=NULL, * chptr, * end; - char * buf=NULL, * dst; + const char * file, * chptr, * end; + char * buf; +/*@dependent@*/ char * dst; int fd, rc; - int fileLength; + off_t fileLength; fd = open(fn, O_RDONLY); - if (fd < 0) { - if (errno == ENOENT) - return 0; - else - return POPT_ERROR_ERRNO; - } + if (fd < 0) + return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); fileLength = lseek(fd, 0, SEEK_END); - (void) lseek(fd, 0, 0); + if (fileLength == -1 || lseek(fd, 0, 0) == -1) { + rc = errno; + (void) close(fd); + /*@-mods@*/ + errno = rc; + /*@=mods@*/ + return POPT_ERROR_ERRNO; + } - file = malloc(fileLength + 1); - if (read(fd, file, fileLength) != fileLength) { + file = alloca(fileLength + 1); + if (read(fd, (char *)file, fileLength) != fileLength) { rc = errno; - close(fd); + (void) close(fd); + /*@-mods@*/ errno = rc; - if (file) free(file); + /*@=mods@*/ return POPT_ERROR_ERRNO; } - close(fd); + if (close(fd) == -1) + return POPT_ERROR_ERRNO; - dst = buf = malloc(fileLength + 1); +/*@-boundswrite@*/ + dst = buf = alloca(fileLength + 1); chptr = file; end = (file + fileLength); + /*@-infloops@*/ /* LCL: can't detect chptr++ */ while (chptr < end) { switch (*chptr) { case '\n': *dst = '\0'; dst = buf; while (*dst && isspace(*dst)) dst++; - if (*dst && *dst != '#') { + if (*dst && *dst != '#') configLine(con, dst); - } chptr++; - break; + /*@switchbreak@*/ break; case '\\': *dst++ = *chptr++; if (chptr < end) { @@ -107,36 +151,38 @@ static void configLine(poptContext con, char * line) else *dst++ = *chptr++; } - break; + /*@switchbreak@*/ break; default: *dst++ = *chptr++; - break; + /*@switchbreak@*/ break; } } - - free(file); - free(buf); + /*@=infloops@*/ +/*@=boundswrite@*/ return 0; } - int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) +int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { char * fn, * home; int rc; + /*@-type@*/ if (!con->appName) return 0; + /*@=type@*/ rc = poptReadConfigFile(con, "/etc/popt"); if (rc) return rc; +#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) if (getuid() != geteuid()) return 0; +#endif if ((home = getenv("HOME"))) { - fn = malloc(strlen(home) + 20); + fn = alloca(strlen(home) + 20); strcpy(fn, home); strcat(fn, "/.popt"); rc = poptReadConfigFile(con, fn); - free(fn); if (rc) return rc; } diff --git a/source4/lib/popt/popthelp.c b/source4/lib/popt/popthelp.c index 562995c011..4d8f0efc24 100644 --- a/source4/lib/popt/popthelp.c +++ b/source4/lib/popt/popthelp.c @@ -1,49 +1,96 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/*@-type@*/ +/** \ingroup popt + * \file popt/popthelp.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "poptint.h" +/** + * Display arguments. + * @param con context + * @param foo (unused) + * @param key option(s) + * @param arg (unused) + * @param data (unused) + */ static void displayArgs(poptContext con, /*@unused@*/ enum poptCallbackReason foo, struct poptOption * key, /*@unused@*/ const char * arg, /*@unused@*/ void * data) + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ { - if (key->shortName== '?') + if (key->shortName == '?') poptPrintHelp(con, stdout, 0); else poptPrintUsage(con, stdout, 0); exit(0); } +#ifdef NOTYET +/*@unchecked@*/ +static int show_option_defaults = 0; +#endif + +/** + * Empty table marker to enable displaying popt alias/exec options. + */ +/*@observer@*/ /*@unchecked@*/ +struct poptOption poptAliasOptions[] = { + POPT_TABLEEND +}; + +/** + * Auto help table options. + */ +/*@-castfcnptr@*/ +/*@observer@*/ /*@unchecked@*/ struct poptOption poptHelpOptions[] = { - { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, - { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, - { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, - { NULL, '\0', 0, NULL, 0, NULL, NULL } + { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, + { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, + { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, +#ifdef NOTYET + { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0, + N_("Display option defaults in message"), NULL }, +#endif + POPT_TABLEEND } ; - - -/*@observer@*/ /*@null@*/ static const char * -getTableTranslationDomain(const struct poptOption *table) +/*@=castfcnptr@*/ + +/** + * @param table option(s) + */ +/*@observer@*/ /*@null@*/ static const char *const +getTableTranslationDomain(/*@null@*/ const struct poptOption *table) + /*@*/ { - const struct poptOption *opt; - - for(opt = table; - opt->longName || opt->shortName || opt->arg; - opt++) { - if(opt->argInfo == POPT_ARG_INTL_DOMAIN) - return opt->arg; - } + const struct poptOption *opt; - return NULL; + if (table != NULL) + for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { + if (opt->argInfo == POPT_ARG_INTL_DOMAIN) + return opt->arg; + } + return NULL; } -/*@observer@*/ /*@null@*/ static const char * -getArgDescrip(const struct poptOption * opt, const char *translation_domain) +/** + * @param opt option(s) + * @param translation_domain translation domain + */ +/*@observer@*/ /*@null@*/ static const char *const +getArgDescrip(const struct poptOption * opt, + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ const char * translation_domain) + /*@=paramuse@*/ + /*@*/ { if (!(opt->argInfo & POPT_ARG_MASK)) return NULL; @@ -51,46 +98,242 @@ getArgDescrip(const struct poptOption * opt, const char *translation_domain) if (opt->argDescrip) return POPT_(opt->argDescrip); if (opt->argDescrip) return D_(translation_domain, opt->argDescrip); - return POPT_("ARG"); + + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_NONE: return POPT_("NONE"); +#ifdef DYING + case POPT_ARG_VAL: return POPT_("VAL"); +#else + case POPT_ARG_VAL: return NULL; +#endif + case POPT_ARG_INT: return POPT_("INT"); + case POPT_ARG_LONG: return POPT_("LONG"); + case POPT_ARG_STRING: return POPT_("STRING"); + case POPT_ARG_FLOAT: return POPT_("FLOAT"); + case POPT_ARG_DOUBLE: return POPT_("DOUBLE"); + default: return POPT_("ARG"); + } } -static void singleOptionHelp(FILE * f, int maxLeftCol, - const struct poptOption * opt, - const char *translation_domain) +/** + * Display default value for an option. + * @param lineLength + * @param opt option(s) + * @param translation_domain translation domain + * @return + */ +static /*@only@*/ /*@null@*/ char * +singleOptionDefaultValue(int lineLength, + const struct poptOption * opt, + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ const char * translation_domain) + /*@=paramuse@*/ + /*@*/ +{ + const char * defstr = D_(translation_domain, "default"); + char * le = malloc(4*lineLength + 1); + char * l = le; + + if (le == NULL) return NULL; /* XXX can't happen */ +/*@-boundswrite@*/ + *le = '\0'; + *le++ = '('; + strcpy(le, defstr); le += strlen(le); + *le++ = ':'; + *le++ = ' '; + if (opt->arg) /* XXX programmer error */ + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_VAL: + case POPT_ARG_INT: + { long aLong = *((int *)opt->arg); + le += sprintf(le, "%ld", aLong); + } break; + case POPT_ARG_LONG: + { long aLong = *((long *)opt->arg); + le += sprintf(le, "%ld", aLong); + } break; + case POPT_ARG_FLOAT: + { double aDouble = *((float *)opt->arg); + le += sprintf(le, "%g", aDouble); + } break; + case POPT_ARG_DOUBLE: + { double aDouble = *((double *)opt->arg); + le += sprintf(le, "%g", aDouble); + } break; + case POPT_ARG_STRING: + { const char * s = *(const char **)opt->arg; + if (s == NULL) { + strcpy(le, "null"); le += strlen(le); + } else { + size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")"); + *le++ = '"'; + strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le); + if (slen < strlen(s)) { + strcpy(le, "..."); le += strlen(le); + } + *le++ = '"'; + } + } break; + case POPT_ARG_NONE: + default: + l = _free(l); + return NULL; + /*@notreached@*/ break; + } + *le++ = ')'; + *le = '\0'; +/*@=boundswrite@*/ + + return l; +} + +/** + * Display help text for an option. + * @param fp output file handle + * @param maxLeftCol + * @param opt option(s) + * @param translation_domain translation domain + */ +static void singleOptionHelp(FILE * fp, int maxLeftCol, + const struct poptOption * opt, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ { int indentLength = maxLeftCol + 5; int lineLength = 79 - indentLength; const char * help = D_(translation_domain, opt->descrip); + const char * argDescrip = getArgDescrip(opt, translation_domain); int helpLength; - const char * ch; - char format[10]; + char * defs = NULL; char * left; - const char * argDescrip = getArgDescrip(opt, translation_domain); + int nb = maxLeftCol + 1; + + /* Make sure there's more than enough room in target buffer. */ + if (opt->longName) nb += strlen(opt->longName); + if (argDescrip) nb += strlen(argDescrip); - left = malloc(maxLeftCol + 1); - *left = '\0'; +/*@-boundswrite@*/ + left = malloc(nb); + if (left == NULL) return; /* XXX can't happen */ + left[0] = '\0'; + left[maxLeftCol] = '\0'; if (opt->longName && opt->shortName) - sprintf(left, "-%c, --%s", opt->shortName, opt->longName); - else if (opt->shortName) + sprintf(left, "-%c, %s%s", opt->shortName, + ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + else if (opt->shortName != '\0') sprintf(left, "-%c", opt->shortName); else if (opt->longName) - sprintf(left, "--%s", opt->longName); - if (!*left) return ; + sprintf(left, "%s%s", + ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + opt->longName); + if (!*left) goto out; + if (argDescrip) { - strcat(left, "="); - strcat(left, argDescrip); + char * le = left + strlen(left); + + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + *le++ = '['; + + /* Choose type of output */ + /*@-branchstate@*/ + if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) { + defs = singleOptionDefaultValue(lineLength, opt, translation_domain); + if (defs) { + char * t = malloc((help ? strlen(help) : 0) + + strlen(defs) + sizeof(" ")); + if (t) { + char * te = t; + *te = '\0'; + if (help) { + strcpy(te, help); te += strlen(te); + } + *te++ = ' '; + strcpy(te, defs); + defs = _free(defs); + } + defs = t; + } + } + /*@=branchstate@*/ + + if (opt->argDescrip == NULL) { + switch (opt->argInfo & POPT_ARG_MASK) { + case POPT_ARG_NONE: + break; + case POPT_ARG_VAL: +#ifdef NOTNOW /* XXX pug ugly nerdy output */ + { long aLong = opt->val; + int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS); + int negate = (opt->argInfo & POPT_ARGFLAG_NOT); + + /* Don't bother displaying typical values */ + if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L)) + break; + *le++ = '['; + switch (ops) { + case POPT_ARGFLAG_OR: + *le++ = '|'; + /*@innerbreak@*/ break; + case POPT_ARGFLAG_AND: + *le++ = '&'; + /*@innerbreak@*/ break; + case POPT_ARGFLAG_XOR: + *le++ = '^'; + /*@innerbreak@*/ break; + default: + /*@innerbreak@*/ break; + } + *le++ = '='; + if (negate) *le++ = '~'; + /*@-formatconst@*/ + le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong); + /*@=formatconst@*/ + *le++ = ']'; + } +#endif + break; + case POPT_ARG_INT: + case POPT_ARG_LONG: + case POPT_ARG_FLOAT: + case POPT_ARG_DOUBLE: + case POPT_ARG_STRING: + *le++ = '='; + strcpy(le, argDescrip); le += strlen(le); + break; + default: + break; + } + } else { + *le++ = '='; + strcpy(le, argDescrip); le += strlen(le); + } + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + *le++ = ']'; + *le = '\0'; } +/*@=boundswrite@*/ if (help) - fprintf(f," %-*s ", maxLeftCol, left); + fprintf(fp," %-*s ", maxLeftCol, left); else { - fprintf(f," %s\n", left); + fprintf(fp," %s\n", left); goto out; } + left = _free(left); + if (defs) { + help = defs; defs = NULL; + } + helpLength = strlen(help); +/*@-boundsread@*/ while (helpLength > lineLength) { + const char * ch; + char format[16]; + ch = help + lineLength - 1; while (ch > help && !isspace(*ch)) ch--; if (ch == help) break; /* give up */ @@ -98,40 +341,57 @@ static void singleOptionHelp(FILE * f, int maxLeftCol, ch++; sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); - fprintf(f, format, help, " "); + /*@-formatconst@*/ + fprintf(fp, format, help, " "); + /*@=formatconst@*/ help = ch; while (isspace(*help) && *help) help++; helpLength = strlen(help); } +/*@=boundsread@*/ - if (helpLength) fprintf(f, "%s\n", help); + if (helpLength) fprintf(fp, "%s\n", help); out: - free(left); + /*@-dependenttrans@*/ + defs = _free(defs); + /*@=dependenttrans@*/ + left = _free(left); } +/** + * @param opt option(s) + * @param translation_domain translation domain + */ static int maxArgWidth(const struct poptOption * opt, - const char * translation_domain) + /*@null@*/ const char * translation_domain) + /*@*/ { int max = 0; - int this; + int len = 0; const char * s; + if (opt != NULL) while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { - this = maxArgWidth(opt->arg, translation_domain); - if (this > max) max = this; + if (opt->arg) /* XXX program error */ + len = maxArgWidth(opt->arg, translation_domain); + if (len > max) max = len; } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { - this = opt->shortName ? 2 : 0; + len = sizeof(" ")-1; + if (opt->shortName != '\0') len += sizeof("-X")-1; + if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1; if (opt->longName) { - if (this) this += 2; - this += strlen(opt->longName) + 2; + len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH) + ? sizeof("-")-1 : sizeof("--")-1); + len += strlen(opt->longName); } s = getArgDescrip(opt, translation_domain); if (s) - this += strlen(s) + 1; - if (this > max) max = this; + len += sizeof("=")-1 + strlen(s); + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1; + if (len > max) max = len; } opt++; @@ -140,173 +400,343 @@ static int maxArgWidth(const struct poptOption * opt, return max; } -static void singleTableHelp(FILE * f, const struct poptOption * table, - int left, - const char *translation_domain) +/** + * Display popt alias and exec help. + * @param fp output file handle + * @param items alias/exec array + * @param nitems no. of alias/exec entries + * @param left + * @param translation_domain translation domain + */ +static void itemHelp(FILE * fp, + /*@null@*/ poptItem items, int nitems, int left, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ +{ + poptItem item; + int i; + + if (items != NULL) + for (i = 0, item = items; i < nitems; i++, item++) { + const struct poptOption * opt; + opt = &item->option; + if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + singleOptionHelp(fp, left, opt, translation_domain); + } +} + +/** + * Display help text for a table of options. + * @param con context + * @param fp output file handle + * @param table option(s) + * @param left + * @param translation_domain translation domain + */ +static void singleTableHelp(poptContext con, FILE * fp, + /*@null@*/ const struct poptOption * table, int left, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ { const struct poptOption * opt; const char *sub_transdom; - opt = table; - while (opt->longName || opt->shortName || opt->arg) { + if (table == poptAliasOptions) { + itemHelp(fp, con->aliases, con->numAliases, left, NULL); + itemHelp(fp, con->execs, con->numExecs, left, NULL); + return; + } + + if (table != NULL) + for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) { if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) - singleOptionHelp(f, left, opt, translation_domain); - opt++; + singleOptionHelp(fp, left, opt, translation_domain); } - opt = table; - while (opt->longName || opt->shortName || opt->arg) { - if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { - sub_transdom = getTableTranslationDomain(opt->arg); - if(!sub_transdom) - sub_transdom = translation_domain; + if (table != NULL) + for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) { + if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE) + continue; + sub_transdom = getTableTranslationDomain(opt->arg); + if (sub_transdom == NULL) + sub_transdom = translation_domain; - if (opt->descrip) - fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip)); + if (opt->descrip) + fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip)); - singleTableHelp(f, opt->arg, left, sub_transdom); - } - opt++; + singleTableHelp(con, fp, opt->arg, left, sub_transdom); } } -static int showHelpIntro(poptContext con, FILE * f) +/** + * @param con context + * @param fp output file handle + */ +static int showHelpIntro(poptContext con, FILE * fp) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ { int len = 6; const char * fn; - fprintf(f, POPT_("Usage:")); + fprintf(fp, POPT_("Usage:")); if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { +/*@-boundsread@*/ + /*@-nullderef@*/ /* LCL: wazzup? */ fn = con->optionStack->argv[0]; - if (strchr(fn, '/')) fn = strchr(fn, '/') + 1; - fprintf(f, " %s", fn); + /*@=nullderef@*/ +/*@=boundsread@*/ + if (fn == NULL) return len; + if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1; + fprintf(fp, " %s", fn); len += strlen(fn) + 1; } return len; } - void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) +void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags) { int leftColWidth; - showHelpIntro(con, f); + (void) showHelpIntro(con, fp); if (con->otherHelp) - fprintf(f, " %s\n", con->otherHelp); + fprintf(fp, " %s\n", con->otherHelp); else - fprintf(f, " %s\n", POPT_("[OPTION...]")); + fprintf(fp, " %s\n", POPT_("[OPTION...]")); leftColWidth = maxArgWidth(con->options, NULL); - singleTableHelp(f, con->options, leftColWidth, NULL); + singleTableHelp(con, fp, con->options, leftColWidth, NULL); } -static int singleOptionUsage(FILE * f, int cursor, - const struct poptOption * opt, - const char *translation_domain) +/** + * @param fp output file handle + * @param cursor + * @param opt option(s) + * @param translation_domain translation domain + */ +static int singleOptionUsage(FILE * fp, int cursor, + const struct poptOption * opt, + /*@null@*/ const char *translation_domain) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ { - int len = 3; + int len = 4; char shortStr[2] = { '\0', '\0' }; const char * item = shortStr; const char * argDescrip = getArgDescrip(opt, translation_domain); - if (opt->shortName) { - if (!(opt->argInfo & POPT_ARG_MASK)) - return cursor; /* we did these already */ + if (opt->shortName != '\0' && opt->longName != NULL) { + len += 2; + if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; + len += strlen(opt->longName); + } else if (opt->shortName != '\0') { len++; - *shortStr = opt->shortName; + shortStr[0] = opt->shortName; shortStr[1] = '\0'; } else if (opt->longName) { - len += 1 + strlen(opt->longName); + len += strlen(opt->longName); + if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; item = opt->longName; } - if (len == 3) return cursor; + if (len == 4) return cursor; if (argDescrip) len += strlen(argDescrip) + 1; if ((cursor + len) > 79) { - fprintf(f, "\n "); + fprintf(fp, "\n "); cursor = 7; } - fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item, - argDescrip ? (opt->shortName ? " " : "=") : "", - argDescrip ? argDescrip : ""); + if (opt->longName && opt->shortName) { + fprintf(fp, " [-%c|-%s%s%s%s]", + opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"), + opt->longName, + (argDescrip ? " " : ""), + (argDescrip ? argDescrip : "")); + } else { + fprintf(fp, " [-%s%s%s%s]", + ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"), + item, + (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""), + (argDescrip ? argDescrip : "")); + } return cursor + len + 1; } -static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table, - const char *translation_domain) +/** + * Display popt alias and exec usage. + * @param fp output file handle + * @param cursor + * @param item alias/exec array + * @param nitems no. of ara/exec entries + * @param translation_domain translation domain + */ +static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems, + /*@null@*/ const char * translation_domain) + /*@globals fileSystem @*/ + /*@modifies *fp, fileSystem @*/ { - const struct poptOption * opt; - - opt = table; - while (opt->longName || opt->shortName || opt->arg) { - if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) + int i; + + /*@-branchstate@*/ /* FIX: W2DO? */ + if (item != NULL) + for (i = 0; i < nitems; i++, item++) { + const struct poptOption * opt; + opt = &item->option; + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; - else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) - cursor = singleTableUsage(f, cursor, opt->arg, - translation_domain); - else if ((opt->longName || opt->shortName) && - !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) - cursor = singleOptionUsage(f, cursor, opt, translation_domain); + } else if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + cursor = singleOptionUsage(fp, cursor, opt, translation_domain); + } + } + /*@=branchstate@*/ - opt++; + return cursor; +} + +/** + * Keep track of option tables already processed. + */ +typedef struct poptDone_s { + int nopts; + int maxopts; + const void ** opts; +} * poptDone; + +/** + * Display usage text for a table of options. + * @param con context + * @param fp output file handle + * @param cursor + * @param opt option(s) + * @param translation_domain translation domain + * @param done tables already processed + * @return + */ +static int singleTableUsage(poptContext con, FILE * fp, int cursor, + /*@null@*/ const struct poptOption * opt, + /*@null@*/ const char * translation_domain, + /*@null@*/ poptDone done) + /*@globals fileSystem @*/ + /*@modifies *fp, done, fileSystem @*/ +{ + /*@-branchstate@*/ /* FIX: W2DO? */ + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg) ; opt++) { + if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { + translation_domain = (const char *)opt->arg; + } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { + if (done) { + int i = 0; + for (i = 0; i < done->nopts; i++) { +/*@-boundsread@*/ + const void * that = done->opts[i]; +/*@=boundsread@*/ + if (that == NULL || that != opt->arg) + /*@innercontinue@*/ continue; + /*@innerbreak@*/ break; + } + /* Skip if this table has already been processed. */ + if (opt->arg == NULL || i < done->nopts) + continue; +/*@-boundswrite@*/ + if (done->nopts < done->maxopts) + done->opts[done->nopts++] = (const void *) opt->arg; +/*@=boundswrite@*/ + } + cursor = singleTableUsage(con, fp, cursor, opt->arg, + translation_domain, done); + } else if ((opt->longName || opt->shortName) && + !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + cursor = singleOptionUsage(fp, cursor, opt, translation_domain); + } } + /*@=branchstate@*/ return cursor; } -static int showShortOptions(const struct poptOption * opt, FILE * f, - char * str) +/** + * Return concatenated short options for display. + * @todo Sub-tables should be recursed. + * @param opt option(s) + * @param fp output file handle + * @retval str concatenation of short options + * @return length of display string + */ +static int showShortOptions(const struct poptOption * opt, FILE * fp, + /*@null@*/ char * str) + /*@globals fileSystem @*/ + /*@modifies *str, *fp, fileSystem @*/ { - char s[300]; /* this is larger then the ascii set, so - it should do just fine */ + char * s = alloca(300); /* larger then the ascii set */ s[0] = '\0'; + /*@-branchstate@*/ /* FIX: W2DO? */ if (str == NULL) { memset(s, 0, sizeof(s)); str = s; } + /*@=branchstate@*/ - while (opt->longName || opt->shortName || opt->arg) { +/*@-boundswrite@*/ + if (opt != NULL) + for (; (opt->longName || opt->shortName || opt->arg); opt++) { if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) str[strlen(str)] = opt->shortName; else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) - showShortOptions(opt->arg, f, str); - - opt++; + if (opt->arg) /* XXX program error */ + (void) showShortOptions(opt->arg, fp, str); } +/*@=boundswrite@*/ - if (s != str || !*s) + if (s != str || *s != '\0') return 0; - fprintf(f, " [-%s]", s); + fprintf(fp, " [-%s]", s); return strlen(s) + 4; } - void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) +void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags) { + poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done)); int cursor; - cursor = showHelpIntro(con, f); - cursor += showShortOptions(con->options, f, NULL); - singleTableUsage(f, cursor, con->options, NULL); + done->nopts = 0; + done->maxopts = 64; + cursor = done->maxopts * sizeof(*done->opts); +/*@-boundswrite@*/ + done->opts = memset(alloca(cursor), 0, cursor); + done->opts[done->nopts++] = (const void *) con->options; +/*@=boundswrite@*/ + + cursor = showHelpIntro(con, fp); + cursor += showShortOptions(con->options, fp, NULL); + cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done); + cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL); + cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL); if (con->otherHelp) { cursor += strlen(con->otherHelp) + 1; - if (cursor > 79) fprintf(f, "\n "); - fprintf(f, " %s", con->otherHelp); + if (cursor > 79) fprintf(fp, "\n "); + fprintf(fp, " %s", con->otherHelp); } - fprintf(f, "\n"); + fprintf(fp, "\n"); } - void poptSetOtherOptionHelp(poptContext con, const char * text) +void poptSetOtherOptionHelp(poptContext con, const char * text) { - if (con->otherHelp) xfree(con->otherHelp); + con->otherHelp = _free(con->otherHelp); con->otherHelp = xstrdup(text); } +/*@=type@*/ diff --git a/source4/lib/popt/poptint.h b/source4/lib/popt/poptint.h index 1847ffafe6..5d308efe96 100644 --- a/source4/lib/popt/poptint.h +++ b/source4/lib/popt/poptint.h @@ -1,71 +1,116 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/poptint.h + */ + +/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_POPTINT #define H_POPTINT +/** + * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. + * @param p memory to free + * @retval NULL always + */ +/*@unused@*/ static inline /*@null@*/ void * +_free(/*@only@*/ /*@null@*/ const void * p) + /*@modifies p @*/ +{ + if (p != NULL) free((void *)p); + return NULL; +} + /* Bit mask macros. */ +/*@-exporttype -redef @*/ typedef unsigned int __pbm_bits; +/*@=exporttype =redef @*/ #define __PBM_NBITS (8 * sizeof (__pbm_bits)) #define __PBM_IX(d) ((d) / __PBM_NBITS) -#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS)) +#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS)) +/*@-exporttype -redef @*/ typedef struct { __pbm_bits bits[1]; } pbm_set; +/*@=exporttype =redef @*/ #define __PBM_BITS(set) ((set)->bits) #define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) -#define PBM_FREE(s) free(s); +#define PBM_FREE(s) _free(s); #define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) #define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) struct optionStackEntry { int argc; - /*@only@*/ const char ** argv; - /*@only@*/ pbm_set * argb; +/*@only@*/ /*@null@*/ + const char ** argv; +/*@only@*/ /*@null@*/ + pbm_set * argb; int next; - /*@only@*/ const char * nextArg; - /*@keep@*/ const char * nextCharArg; - /*@dependent@*/ struct poptAlias * currAlias; +/*@only@*/ /*@null@*/ + const char * nextArg; +/*@observer@*/ /*@null@*/ + const char * nextCharArg; +/*@dependent@*/ /*@null@*/ + poptItem currAlias; int stuffed; }; -struct execEntry { - const char * longName; - char shortName; - const char * script; -}; - struct poptContext_s { struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; - /*@dependent@*/ struct optionStackEntry * os; - /*@owned@*/ const char ** leftovers; +/*@dependent@*/ + struct optionStackEntry * os; +/*@owned@*/ /*@null@*/ + const char ** leftovers; int numLeftovers; int nextLeftover; - /*@keep@*/ const struct poptOption * options; +/*@keep@*/ + const struct poptOption * options; int restLeftover; - /*@only@*/ const char * appName; - /*@only@*/ struct poptAlias * aliases; +/*@only@*/ /*@null@*/ + const char * appName; +/*@only@*/ /*@null@*/ + poptItem aliases; int numAliases; int flags; - struct execEntry * execs; +/*@owned@*/ /*@null@*/ + poptItem execs; int numExecs; - /*@only@*/ const char ** finalArgv; +/*@only@*/ /*@null@*/ + const char ** finalArgv; int finalArgvCount; int finalArgvAlloced; - /*@dependent@*/ struct execEntry * doExec; - /*@only@*/ const char * execPath; +/*@dependent@*/ /*@null@*/ + poptItem doExec; +/*@only@*/ + const char * execPath; int execAbsolute; - /*@only@*/ const char * otherHelp; +/*@only@*/ + const char * otherHelp; +/*@null@*/ pbm_set * arg_strip; }; -#define xfree(_a) free((void *)_a) +#ifdef HAVE_LIBINTL_H +#include +#endif + +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__) +#define _(foo) gettext(foo) +#else +#define _(foo) foo +#endif + +#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) +#define D_(dom, str) dgettext(dom, str) +#define POPT_(foo) D_("popt", foo) +#else +#define D_(dom, str) str +#define POPT_(foo) foo +#endif -#define POPT_(foo) (foo) -#define D_(dom, str) (str) -#define N_(foo) (foo) +#define N_(foo) foo #endif diff --git a/source4/lib/popt/poptparse.c b/source4/lib/popt/poptparse.c index 93bf7acfb8..a0dea80041 100644 --- a/source4/lib/popt/poptparse.c +++ b/source4/lib/popt/poptparse.c @@ -1,12 +1,17 @@ -/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING +/** \ingroup popt + * \file popt/poptparse.c + */ + +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from - ftp://ftp.redhat.com/pub/code/popt */ + ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #define POPT_ARGV_ARRAY_GROW_DELTA 5 - int poptDupArgv(int argc, const char **argv, +/*@-boundswrite@*/ +int poptDupArgv(int argc, const char **argv, int * argcPtr, const char *** argvPtr) { size_t nb = (argc + 1) * sizeof(*argv); @@ -14,6 +19,8 @@ char * dst; int i; + if (argc <= 0 || argv == NULL) /* XXX can't happen */ + return POPT_ERROR_NOARG; for (i = 0; i < argc; i++) { if (argv[i] == NULL) return POPT_ERROR_NOARG; @@ -21,21 +28,33 @@ } dst = malloc(nb); + if (dst == NULL) /* XXX can't happen */ + return POPT_ERROR_MALLOC; argv2 = (void *) dst; dst += (argc + 1) * sizeof(*argv); + /*@-branchstate@*/ for (i = 0; i < argc; i++) { argv2[i] = dst; dst += strlen(strcpy(dst, argv[i])) + 1; } + /*@=branchstate@*/ argv2[argc] = NULL; - *argvPtr = argv2; - *argcPtr = argc; + if (argvPtr) { + *argvPtr = argv2; + } else { + free(argv2); + argv2 = NULL; + } + if (argcPtr) + *argcPtr = argc; return 0; } +/*@=boundswrite@*/ - int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) +/*@-bounds@*/ +int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * src; char quote = '\0'; @@ -43,31 +62,32 @@ const char ** argv = malloc(sizeof(*argv) * argvAlloced); int argc = 0; int buflen = strlen(s) + 1; - char *buf0 = calloc(buflen, 1); - char *buf = buf0; + char * buf = memset(alloca(buflen), 0, buflen); + int rc = POPT_ERROR_MALLOC; + if (argv == NULL) return rc; argv[argc] = buf; - for (src = s; *src; src++) { + for (src = s; *src != '\0'; src++) { if (quote == *src) { quote = '\0'; - } else if (quote) { + } else if (quote != '\0') { if (*src == '\\') { src++; if (!*src) { - free(argv); - free(buf0); - return POPT_ERROR_BADQUOTE; + rc = POPT_ERROR_BADQUOTE; + goto exit; } if (*src != quote) *buf++ = '\\'; } *buf++ = *src; } else if (isspace(*src)) { - if (*argv[argc]) { + if (*argv[argc] != '\0') { buf++, argc++; if (argc == argvAlloced) { argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argv = realloc(argv, sizeof(*argv) * argvAlloced); + if (argv == NULL) goto exit; } argv[argc] = buf; } @@ -75,18 +95,17 @@ case '"': case '\'': quote = *src; - break; + /*@switchbreak@*/ break; case '\\': src++; if (!*src) { - free(argv); - free(buf0); - return POPT_ERROR_BADQUOTE; + rc = POPT_ERROR_BADQUOTE; + goto exit; } /*@fallthrough@*/ default: *buf++ = *src; - break; + /*@switchbreak@*/ break; } } @@ -94,9 +113,115 @@ argc++, buf++; } - (void) poptDupArgv(argc, argv, argcPtr, argvPtr); + rc = poptDupArgv(argc, argv, argcPtr, argvPtr); + +exit: + if (argv) free(argv); + return rc; +} +/*@=bounds@*/ + +/* still in the dev stage. + * return values, perhaps 1== file erro + * 2== line to long + * 3== umm.... more? + */ +int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags) +{ + char line[999]; + char * argstr; + char * p; + char * q; + char * x; + int t; + int argvlen = 0; + size_t maxlinelen = sizeof(line); + size_t linelen; + int maxargvlen = 480; + int linenum = 0; + + *argstrp = NULL; + + /* | this_is = our_line + * p q x + */ + + if (fp == NULL) + return POPT_ERROR_NULLARG; + + argstr = calloc(maxargvlen, sizeof(*argstr)); + if (argstr == NULL) return POPT_ERROR_MALLOC; + + while (fgets(line, (int)maxlinelen, fp) != NULL) { + linenum++; + p = line; + + /* loop until first non-space char or EOL */ + while( *p != '\0' && isspace(*p) ) + p++; + + linelen = strlen(p); + if (linelen >= maxlinelen-1) + return POPT_ERROR_OVERFLOW; /* XXX line too long */ + + if (*p == '\0' || *p == '\n') continue; /* line is empty */ + if (*p == '#') continue; /* comment line */ + + q = p; + + while (*q != '\0' && (!isspace(*q)) && *q != '=') + q++; + + if (isspace(*q)) { + /* a space after the name, find next non space */ + *q++='\0'; + while( *q != '\0' && isspace((int)*q) ) q++; + } + if (*q == '\0') { + /* single command line option (ie, no name=val, just name) */ + q[-1] = '\0'; /* kill off newline from fgets() call */ + argvlen += (t = q - p) + (sizeof(" --")-1); + if (argvlen >= maxargvlen) { + maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; + argstr = realloc(argstr, maxargvlen); + if (argstr == NULL) return POPT_ERROR_MALLOC; + } + strcat(argstr, " --"); + strcat(argstr, p); + continue; + } + if (*q != '=') + continue; /* XXX for now, silently ignore bogus line */ + + /* *q is an equal sign. */ + *q++ = '\0'; + + /* find next non-space letter of value */ + while (*q != '\0' && isspace(*q)) + q++; + if (*q == '\0') + continue; /* XXX silently ignore missing value */ + + /* now, loop and strip all ending whitespace */ + x = p + linelen; + while (isspace(*--x)) + *x = 0; /* null out last char if space (including fgets() NL) */ + + /* rest of line accept */ + t = x - p; + argvlen += t + (sizeof("' --='")-1); + if (argvlen >= maxargvlen) { + maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; + argstr = realloc(argstr, maxargvlen); + if (argstr == NULL) return POPT_ERROR_MALLOC; + } + strcat(argstr, " --"); + strcat(argstr, p); + strcat(argstr, "=\""); + strcat(argstr, q); + strcat(argstr, "\""); + } - free(argv); - free(buf0); + *argstrp = argstr; return 0; } diff --git a/source4/lib/popt/system.h b/source4/lib/popt/system.h index 059c045817..000e23d484 100644 --- a/source4/lib/popt/system.h +++ b/source4/lib/popt/system.h @@ -1,6 +1,16 @@ #include "config.h" +#if defined (__GLIBC__) && defined(__LCLINT__) +/*@-declundef@*/ +/*@unchecked@*/ +extern __const __int32_t *__ctype_tolower; +/*@unchecked@*/ +extern __const __int32_t *__ctype_toupper; +/*@=declundef@*/ +#endif + #include + #include #include #include @@ -23,6 +33,14 @@ #include #endif +#if defined(__LCLINT__) +/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */ +/*@only@*/ void * alloca (size_t __size) + /*@ensures MaxSet(result) == (__size - 1) @*/ + /*@*/; +/*@=declundef =incondefs =redecl@*/ +#endif + /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H @@ -40,7 +58,10 @@ char *alloca (); #define alloca __builtin_alloca #endif -/*@only@*/ char * xstrdup (const char *str); +/*@-redecl -redef@*/ +/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str) + /*@*/; +/*@=redecl =redef@*/ #if HAVE_MCHECK_H && defined(__GNUC__) #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) -- cgit From 02075be0bbc2095073f8898350fded64a7c97c79 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Mar 2005 02:08:38 +0000 Subject: r5917: First step in using the new cli_credentials structure. This patch puts support for it into popt_common, adds a few utility functions (in lib/credentials.c) and the callback functions for the command-line (lib/cmdline/credentials.c). Comments are welcome :-) (This used to be commit 1d49b57c50fe8c2683ea23e9df41ce8ad774db98) --- source4/lib/basic.mk | 4 +- source4/lib/cmdline/config.m4 | 19 ++- source4/lib/cmdline/config.mk | 7 + source4/lib/cmdline/credentials.c | 49 ++++++ source4/lib/cmdline/getsmbpass.c | 158 ++++++++++++++++++ source4/lib/cmdline/popt_common.c | 303 ++++------------------------------ source4/lib/cmdline/popt_common.h | 9 +- source4/lib/credentials.c | 301 +++++++++++++++++++++++++++++++++ source4/lib/getsmbpass.c | 158 ------------------ source4/lib/registry/tools/regdiff.c | 4 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 13 files changed, 577 insertions(+), 441 deletions(-) create mode 100644 source4/lib/cmdline/config.mk create mode 100644 source4/lib/cmdline/credentials.c create mode 100644 source4/lib/cmdline/getsmbpass.c create mode 100644 source4/lib/credentials.c delete mode 100644 source4/lib/getsmbpass.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 257f59d8ed..29dbbd22c7 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -39,7 +39,6 @@ INIT_OBJ_FILES = lib/version.o ADD_OBJ_FILES = \ lib/debug.o \ lib/fault.o \ - lib/getsmbpass.o \ lib/pidfile.o \ lib/signal.o \ lib/system.o \ @@ -65,7 +64,8 @@ ADD_OBJ_FILES = \ lib/idtree.o \ lib/unix_privs.o \ lib/db_wrap.o \ - lib/gencache.o + lib/gencache.o \ + lib/credentials.o REQUIRED_SUBSYSTEMS = \ LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC # End SUBSYSTEM LIBBASIC diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index e2121d1f14..45c3a70f9f 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -77,4 +77,21 @@ SMB_EXT_LIB(READLINE, [${TMP_LIBCMDLINE_LIBS}]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], [], - [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS]) + [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS LIBCMDLINE_CREDENTIALS]) + +AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper" +AC_TRY_COMPILE([ +#define REPLACE_GETPASS 1 +#define NO_CONFIG_H 1 +#define main dont_declare_main +#include "${srcdir-.}/lib/cmdline/getsmbpass.c" +#undef main +],[],samba_cv_REPLACE_GETPASS=yes,samba_cv_REPLACE_GETPASS=no) +CPPFLAGS="$SAVE_CPPFLAGS" +]) +if test x"$samba_cv_REPLACE_GETPASS" = x"yes"; then + AC_DEFINE(REPLACE_GETPASS,1,[Whether getpass should be replaced]) +fi + diff --git a/source4/lib/cmdline/config.mk b/source4/lib/cmdline/config.mk new file mode 100644 index 0000000000..803c81f273 --- /dev/null +++ b/source4/lib/cmdline/config.mk @@ -0,0 +1,7 @@ +############################## +# Start SUBSYSTEM LIBCMDLINE_CREDENTIALS +[SUBSYSTEM::LIBCMDLINE_CREDENTIALS] +ADD_OBJ_FILES = lib/cmdline/getsmbpass.o \ + lib/cmdline/credentials.o +# End SUBSYSTEM LIBCMDLINE_CREDENTIALS +############################## diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c new file mode 100644 index 0000000000..d827baed76 --- /dev/null +++ b/source4/lib/cmdline/credentials.c @@ -0,0 +1,49 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "version.h" +#include "dynconfig.h" +#include "system/filesys.h" +#include "system/passwd.h" +#include "lib/cmdline/popt_common.h" + +static const char *cmdline_get_userpassword(struct cli_credentials *credentials) +{ + char *prompt; + char *ret; + + prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", + cli_credentials_get_domain(credentials), + cli_credentials_get_username(credentials)); + + ret = getpass(prompt); + + talloc_free(prompt); + return ret; +} + +void cli_credentials_set_cmdline_callbacks(struct cli_credentials *cred) +{ + if (cred->password_obtained <= CRED_CALLBACK) { + cred->password_cb = cmdline_get_userpassword; + cred->password_obtained = CRED_CALLBACK; + } +} diff --git a/source4/lib/cmdline/getsmbpass.c b/source4/lib/cmdline/getsmbpass.c new file mode 100644 index 0000000000..4ffcde8dfd --- /dev/null +++ b/source4/lib/cmdline/getsmbpass.c @@ -0,0 +1,158 @@ +/* Copyright (C) 1992-1998 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ + +#include "includes.h" +#include "system/terminal.h" +#include "system/wait.h" + +#ifdef REPLACE_GETPASS + +#ifdef SYSV_TERMIO + +/* SYSTEM V TERMIO HANDLING */ + +static struct termio t; + +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +#ifndef TCSAFLUSH +#define TCSAFLUSH 1 +#endif + +#ifndef TCSANOW +#define TCSANOW 0 +#endif + +static int tcgetattr(int fd, struct termio *_t) +{ + return ioctl(fd, TCGETA, _t); +} + +static int tcsetattr(int fd, int flags, struct termio *_t) +{ + if(flags & TCSAFLUSH) + ioctl(fd, TCFLSH, TCIOFLUSH); + return ioctl(fd, TCSETS, _t); +} + +#elif !defined(TCSAFLUSH) + +/* BSD TERMIO HANDLING */ + +static struct sgttyb t; + +#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) +#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) + +#define TCSAFLUSH 1 +#define TCSANOW 0 + +static int tcgetattr(int fd, struct sgttyb *_t) +{ + return ioctl(fd, TIOCGETP, (char *)_t); +} + +static int tcsetattr(int fd, int flags, struct sgttyb *_t) +{ + return ioctl(fd, TIOCSETP, (char *)_t); +} + +#else /* POSIX TERMIO HANDLING */ +#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) +#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) +#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) + +static struct termios t; +#endif /* SYSV_TERMIO */ + +char *getsmbpass(const char *prompt) +{ + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + if (ECHO_IS_ON(t)) + { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } + else + echo_off = 0; + } + else + echo_off = 0; + + /* Write the prompt. */ + fputs (prompt, out); + fflush (out); + + /* Read the password. */ + buf[0] = 0; + fgets(buf, bufsize, in); + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) + (void) tcsetattr (fileno (in), TCSANOW, &t); + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + return buf; +} + +#else + void getsmbpasswd_dummy(void); + void getsmbpasswd_dummy(void) {;} +#endif diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 0445877e7a..0792a16b3d 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -38,10 +38,9 @@ * -i,--scope */ - enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL}; -static struct cmdline_auth_info cmdline_auth_info; +struct cli_credentials *cmdline_credentials = NULL; static void popt_common_callback(poptContext con, enum poptCallbackReason reason, @@ -160,182 +159,34 @@ struct poptOption popt_common_version[] = { POPT_TABLEEND }; - - -/**************************************************************************** - * get a password from a a file or file descriptor - * exit on failure - * ****************************************************************************/ -static void get_password_file(struct cmdline_auth_info *a) -{ - int fd = -1; - char *p; - BOOL close_it = False; - pstring spec; - char pass[128]; - - if ((p = getenv("PASSWD_FD")) != NULL) { - pstrcpy(spec, "descriptor "); - pstrcat(spec, p); - sscanf(p, "%d", &fd); - close_it = False; - } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = open(p, O_RDONLY, 0); - pstrcpy(spec, p); - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - spec, strerror(errno)); - exit(1); - } - close_it = True; - } - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, "empty password\n"); - exit(1); - } - - default: - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, strerror(errno)); - exit(1); - } - } - pstrcpy(a->password, pass); - if (close_it) - close(fd); -} - -static void get_credentials_file(const char *file, struct cmdline_auth_info *info) -{ - XFILE *auth; - fstring buf; - uint16_t len = 0; - char *ptr, *val, *param; - - if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) - { - /* fail if we can't open the credentials file */ - d_printf("ERROR: Unable to open credentials file!\n"); - exit(-1); - } - - while (!x_feof(auth)) - { - /* get a line from the file */ - if (!x_fgets(buf, sizeof(buf), auth)) - continue; - len = strlen(buf); - - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } - if (len == 0) - continue; - - /* break up the line into parameter & value. - * will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr_m (buf, '='))) - continue; - - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) { - pstrcpy(info->password, val); - info->got_pass = True; - } else if (strwicmp("username", param) == 0) { - pstrcpy(info->username, val); - } else if (strwicmp("domain", param) == 0) { - pstrcpy(info->domain,val); - info->got_domain = True; - } - memset(buf, 0, sizeof(buf)); - } - x_fclose(auth); -} - /* Handle command line options: * -U,--user * -A,--authentication-file * -k,--use-kerberos * -N,--no-pass * -S,--signing - * -P --machine-pass + * -P --machine-pass */ +static BOOL dont_ask = False; + static void popt_common_credentials_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { - char *p; - if (reason == POPT_CALLBACK_REASON_PRE) { - cmdline_auth_info.use_kerberos = False; - cmdline_auth_info.got_pass = False; - pstrcpy(cmdline_auth_info.username, "GUEST"); - - if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); - - if (getenv("USER")) { - pstring tmp; - - pstrcpy(cmdline_auth_info.username,getenv("USER")); + cmdline_credentials = talloc_zero(talloc_autofree_context(), struct cli_credentials); + cli_credentials_guess(cmdline_credentials); - pstrcpy(tmp,cmdline_auth_info.username); - if ((p = strchr_m(tmp,'\\'))) { - *p = 0; - pstrcpy(cmdline_auth_info.domain,tmp); - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.username,p+1); - } - - if ((p = strchr_m(cmdline_auth_info.username,'%'))) { - *p = 0; - pstrcpy(cmdline_auth_info.password,p+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); - } - } - - if (getenv("DOMAIN")) { - pstrcpy(cmdline_auth_info.domain,getenv("DOMAIN")); - cmdline_auth_info.got_domain = True; - } - - if (getenv("PASSWD")) { - pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); - cmdline_auth_info.got_pass = True; - } - - if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { - get_password_file(&cmdline_auth_info); - cmdline_auth_info.got_pass = True; + return; + } + + if (reason == POPT_CALLBACK_REASON_POST) { + if (!dont_ask) { + cli_credentials_set_cmdline_callbacks(cmdline_credentials); } - return; } @@ -343,41 +194,18 @@ static void popt_common_credentials_callback(poptContext con, case 'U': { char *lp; - pstring tmp; - - pstrcpy(cmdline_auth_info.username,arg); - pstrcpy(tmp,cmdline_auth_info.username); - if ((p = strchr_m(tmp,'\\'))) { - *p = 0; - pstrcpy(cmdline_auth_info.domain,tmp); - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.username,p+1); - } + cli_credentials_parse_string(cmdline_credentials,arg, CRED_SPECIFIED); - if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { + if ((lp=strchr_m(arg,'%'))) { *lp = 0; - pstrcpy(cmdline_auth_info.password,lp+1); - cmdline_auth_info.got_pass = True; - memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); + memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_credentials->password)); } } break; case 'A': - get_credentials_file(arg, &cmdline_auth_info); - break; - - case 'k': -#ifndef HAVE_KRB5 - d_printf("No kerberos support compiled in\n"); - exit(1); -#else - cmdline_auth_info.use_kerberos = True; - cmdline_auth_info.got_pass = True; - lp_set_cmdline("gensec:krb5", "True"); - lp_set_cmdline("gensec:ms_krb5", "True"); -#endif + cli_credentials_parse_file(cmdline_credentials, arg, CRED_SPECIFIED); break; case 'S': @@ -401,97 +229,38 @@ static void popt_common_credentials_callback(poptContext con, d_printf("ERROR: Unable to fetch machine password\n"); exit(1); } - snprintf(cmdline_auth_info.username, sizeof(cmdline_auth_info.username), - "%s$", lp_netbios_name()); - pstrcpy(cmdline_auth_info.password,opt_password); + cmdline_credentials->username = talloc_asprintf(cmdline_credentials, "%s$", lp_netbios_name()); + cmdline_credentials->username_obtained = CRED_SPECIFIED; + cli_credentials_set_password(cmdline_credentials, opt_password, CRED_SPECIFIED); free(opt_password); - cmdline_auth_info.got_pass = True; - pstrcpy(cmdline_auth_info.domain, lp_workgroup()); - cmdline_auth_info.got_domain = True; - - /* machine accounts only work with kerberos */ - cmdline_auth_info.use_kerberos = True; + cli_credentials_set_domain(cmdline_credentials, lp_workgroup(), CRED_SPECIFIED); } + /* machine accounts only work with kerberos */ + + case 'k': +#ifndef HAVE_KRB5 + d_printf("No kerberos support compiled in\n"); + exit(1); +#else + lp_set_cmdline("gensec:krb5", "True"); + lp_set_cmdline("gensec:ms_krb5", "True"); +#endif break; + + } } struct poptOption popt_common_credentials[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, + { "no-pass", 'N', POPT_ARG_NONE, &dont_ask, True, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, NULL, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, - { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, + { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password (implies -k)" }, POPT_TABLEEND }; - -void cmdline_set_username(const char *name) -{ - pstrcpy(cmdline_auth_info.username, name); -} - -const char *cmdline_get_username(void) -{ - return cmdline_auth_info.username; -} - -void cmdline_set_userdomain(const char *domain) -{ - cmdline_auth_info.got_domain = True; - pstrcpy(cmdline_auth_info.domain, domain); -} - -const char *cmdline_get_userdomain(void) -{ - if (cmdline_auth_info.got_domain) { - return cmdline_auth_info.domain; - } - - /* I think this should be lp_netbios_name() - * instead of lp_workgroup(), because if you're logged in - * as domain user the getenv("USER") contains the domain - * and this code path isn't used - * --metze - */ - return lp_netbios_name(); -} - -const char *cmdline_get_userpassword(void) -{ - char *prompt; - char *ret; - - if (cmdline_auth_info.got_pass) { - return cmdline_auth_info.password; - } - - prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", - cmdline_get_userdomain(), - cmdline_get_username()); - - ret = getpass(prompt); - - talloc_free(prompt); - return ret; -} - -void cmdline_set_userpassword(const char *pass) -{ - cmdline_auth_info.got_pass = True; - pstrcpy(cmdline_auth_info.password, pass); -} - -void cmdline_set_use_kerberos(BOOL use_kerberos) -{ - cmdline_auth_info.use_kerberos = use_kerberos; -} - -BOOL cmdline_get_use_kerberos(void) -{ - return cmdline_auth_info.use_kerberos; -} diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index d6ae43d083..28676de56b 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -39,13 +39,6 @@ extern struct poptOption popt_common_credentials[]; #define POPT_COMMON_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version, 0, "Common samba options:", NULL }, #define POPT_COMMON_CREDENTIALS { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_credentials, 0, "Authentication options:", NULL }, -struct cmdline_auth_info { - pstring username; - pstring domain; - BOOL got_domain; - pstring password; - BOOL got_pass; - BOOL use_kerberos; -}; +extern struct cli_credentials *cmdline_credentials; #endif /* _POPT_COMMON_H */ diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c new file mode 100644 index 0000000000..5c78d2b2e6 --- /dev/null +++ b/source4/lib/credentials.c @@ -0,0 +1,301 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Tim Potter 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" + +const char *cli_credentials_get_username(struct cli_credentials *cred) +{ + if (cred->username_obtained == CRED_CALLBACK) { + cred->username = cred->username_cb(cred); + cred->username_obtained = CRED_SPECIFIED; + } + + return cred->username; +} + +BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->username_obtained) { + cred->username = talloc_strdup(cred, val); + cred->username_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_password(struct cli_credentials *cred) +{ + if (cred->password_obtained == CRED_CALLBACK) { + cred->password = cred->password_cb(cred); + cred->password_obtained = CRED_SPECIFIED; + } + + return cred->password; +} + +BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->password_obtained) { + cred->password = talloc_strdup(cred, val); + cred->password_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_domain(struct cli_credentials *cred) +{ + if (cred->domain_obtained == CRED_CALLBACK) { + cred->domain = cred->domain_cb(cred); + cred->domain_obtained = CRED_SPECIFIED; + } + + return cred->domain; +} + + +BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->domain_obtained) { + cred->domain = talloc_strdup(cred, val); + cred->domain_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_realm(struct cli_credentials *cred) +{ + if (cred->realm_obtained == CRED_CALLBACK) { + cred->realm = cred->realm_cb(cred); + cred->realm_obtained = CRED_SPECIFIED; + } + + return cred->realm; +} + +BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->realm_obtained) { + cred->realm = talloc_strdup(cred, val); + cred->realm_obtained = obtained; + return True; + } + + return False; +} + +const char *cli_credentials_get_workstation(struct cli_credentials *cred) +{ + if (cred->workstation_obtained == CRED_CALLBACK) { + cred->workstation = cred->workstation_cb(cred); + cred->workstation_obtained = CRED_SPECIFIED; + } + + return cred->workstation; +} + +BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->workstation_obtained) { + cred->workstation = talloc_strdup(cred, val); + cred->workstation_obtained = obtained; + return True; + } + + return False; +} + +BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained) +{ + char *p; + char pass[128]; + + for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ + p && p - pass < sizeof(pass);) { + switch (read(fd, p, 1)) { + case 1: + if (*p != '\n' && *p != '\0') { + *++p = '\0'; /* advance p, and null-terminate pass */ + break; + } + case 0: + if (p - pass) { + *p = '\0'; /* null-terminate it, just in case... */ + p = NULL; /* then force the loop condition to become false */ + break; + } else { + fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n"); + return False; + } + + default: + fprintf(stderr, "Error reading password from file descriptor %d: %s\n", + fd, strerror(errno)); + return False; + } + } + + cli_credentials_set_password(credentials, pass, obtained); + return True; +} + +BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained) +{ + int fd = open(file, O_RDONLY, 0); + BOOL ret; + + if (fd < 0) { + fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", + file, strerror(errno)); + return False; + } + + ret = cli_credentials_parse_password_fd(credentials, fd, obtained); + + close(fd); + + return ret; +} + +BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) +{ + XFILE *auth; + char buf[128]; + uint16_t len = 0; + char *ptr, *val, *param; + + if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) + { + /* fail if we can't open the credentials file */ + d_printf("ERROR: Unable to open credentials file!\n"); + return False; + } + + while (!x_feof(auth)) + { + /* get a line from the file */ + if (!x_fgets(buf, sizeof(buf), auth)) + continue; + len = strlen(buf); + + if ((len) && (buf[len-1]=='\n')) + { + buf[len-1] = '\0'; + len--; + } + if (len == 0) + continue; + + /* break up the line into parameter & value. + * will need to eat a little whitespace possibly */ + param = buf; + if (!(ptr = strchr_m (buf, '='))) + continue; + + val = ptr+1; + *ptr = '\0'; + + /* eat leading white space */ + while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) + val++; + + if (strwicmp("password", param) == 0) { + cli_credentials_set_password(cred, val, obtained); + } else if (strwicmp("username", param) == 0) { + cli_credentials_set_username(cred, val, obtained); + } else if (strwicmp("domain", param) == 0) { + cli_credentials_set_domain(cred, val, obtained); + } else if (strwicmp("realm", param) == 0) { + cli_credentials_set_realm(cred, val, obtained); + } + memset(buf, 0, sizeof(buf)); + } + + x_fclose(auth); + return True; +} + + +void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained) +{ + char *uname, *p; + + uname = talloc_strdup(credentials, data); + cli_credentials_set_username(credentials, uname, obtained); + + if ((p = strchr_m(uname,'\\'))) { + *p = 0; + cli_credentials_set_domain(credentials, uname, obtained); + credentials->username = uname = p+1; + } + + if ((p = strchr_m(uname,'@'))) { + *p = 0; + cli_credentials_set_realm(credentials, p+1, obtained); + } + + if ((p = strchr_m(uname,'%'))) { + *p = 0; + cli_credentials_set_password(credentials, p+1, obtained); + } +} + +void cli_credentials_guess(struct cli_credentials *cred) +{ + char *p; + + cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); + cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); + + if (getenv("LOGNAME")) { + cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); + } + + if (getenv("USER")) { + cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED); + if ((p = strchr_m(getenv("USER"),'%'))) { + *p = 0; + memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cred->password)); + } + } + + if (getenv("DOMAIN")) { + cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED); + } + + if (getenv("PASSWD")) { + cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED); + } + + if (getenv("PASSWD_FD")) { + cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED); + } + + if (getenv("PASSWD_FILE")) { + cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED); + } +} diff --git a/source4/lib/getsmbpass.c b/source4/lib/getsmbpass.c deleted file mode 100644 index 4ffcde8dfd..0000000000 --- a/source4/lib/getsmbpass.c +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (C) 1992-1998 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ - -#include "includes.h" -#include "system/terminal.h" -#include "system/wait.h" - -#ifdef REPLACE_GETPASS - -#ifdef SYSV_TERMIO - -/* SYSTEM V TERMIO HANDLING */ - -static struct termio t; - -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -#ifndef TCSAFLUSH -#define TCSAFLUSH 1 -#endif - -#ifndef TCSANOW -#define TCSANOW 0 -#endif - -static int tcgetattr(int fd, struct termio *_t) -{ - return ioctl(fd, TCGETA, _t); -} - -static int tcsetattr(int fd, int flags, struct termio *_t) -{ - if(flags & TCSAFLUSH) - ioctl(fd, TCFLSH, TCIOFLUSH); - return ioctl(fd, TCSETS, _t); -} - -#elif !defined(TCSAFLUSH) - -/* BSD TERMIO HANDLING */ - -static struct sgttyb t; - -#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) -#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) - -#define TCSAFLUSH 1 -#define TCSANOW 0 - -static int tcgetattr(int fd, struct sgttyb *_t) -{ - return ioctl(fd, TIOCGETP, (char *)_t); -} - -static int tcsetattr(int fd, int flags, struct sgttyb *_t) -{ - return ioctl(fd, TIOCSETP, (char *)_t); -} - -#else /* POSIX TERMIO HANDLING */ -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -static struct termios t; -#endif /* SYSV_TERMIO */ - -char *getsmbpass(const char *prompt) -{ - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) - { - if (ECHO_IS_ON(t)) - { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); - } - else - echo_off = 0; - } - else - echo_off = 0; - - /* Write the prompt. */ - fputs (prompt, out); - fflush (out); - - /* Read the password. */ - buf[0] = 0; - fgets(buf, bufsize, in); - nread = strlen(buf); - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - - /* Restore echoing. */ - if (echo_off) - (void) tcsetattr (fileno (in), TCSANOW, &t); - - if (in != stdin) - /* We opened the terminal; now close it. */ - fclose (in); - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - - printf("\n"); - return buf; -} - -#else - void getsmbpasswd_dummy(void); - void getsmbpasswd_dummy(void) {;} -#endif diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index ceae3a427e..7206e1e44d 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -146,8 +146,8 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, else if (!h2) error = reg_open_local(&h2); break; case 'R': - if (!h1 && !from_null) error = reg_open_remote(&h1, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); - else if (!h2) error = reg_open_remote(&h2, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); + if (!h1 && !from_null) error = reg_open_remote(&h1, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); + else if (!h2) error = reg_open_remote(&h2, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); break; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index ee7568cc0f..ce3d9a7e1b 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -769,7 +769,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd setup_logging(argv[0], True); if (remote) { - error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else { error = reg_open_local (&h); } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index ee80837bab..cab2c5e34b 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -395,7 +395,7 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); if (remote) { - error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); } else { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index f061f33bd3..81a7fb7f99 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -105,7 +105,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) setup_logging("regtree", True); if (remote) { - error = reg_open_remote(&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + error = reg_open_remote(&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); } else { -- cgit From 05bc2d7b2c11a3583a6d1221cfbd618eb6730518 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Mar 2005 21:22:07 +0000 Subject: r5928: Use cli_credentials in: - gtk+ (returned by GtkHostBindingDialog as well now) - torture/ - librpc/ - lib/com/dcom/ (This used to be commit ccefd782335e01e8e6ecb2bcd28a4f999c53b1a6) --- source4/lib/com/dcom/dcom.h | 4 +--- source4/lib/com/dcom/main.c | 20 ++++++-------------- source4/lib/credentials.c | 24 ++++++++++++++++++++++-- source4/lib/registry/reg_backend_rpc.c | 6 ++---- source4/lib/registry/tools/regdiff.c | 5 +++-- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 8 files changed, 37 insertions(+), 28 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/dcom.h b/source4/lib/com/dcom/dcom.h index 668d952124..1e15daf830 100644 --- a/source4/lib/com/dcom/dcom.h +++ b/source4/lib/com/dcom/dcom.h @@ -22,9 +22,7 @@ #define _DCOM_H struct dcom_client_context { - const char *domain; - const char *user; - const char *password; + struct cli_credentials *credentials; struct dcom_object_exporter { uint64_t oxid; struct DUALSTRINGARRAY bindings; diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index d3d44edc71..be350c32f5 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -30,12 +30,10 @@ #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC } -struct dcom_client_context *dcom_client_init(struct com_context *ctx, const char *domain, const char *user, const char *password) +struct dcom_client_context *dcom_client_init(struct com_context *ctx, struct cli_credentials *credentials) { ctx->dcom = talloc(ctx, struct dcom_client_context); - ctx->dcom->domain = domain; - ctx->dcom->user = user; - ctx->dcom->password = password; + ctx->dcom->credentials = credentials; return ctx->dcom; } @@ -86,8 +84,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** return dcerpc_pipe_connect(p, "ncalrpc", DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - lp_netbios_name(), - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + ctx->dcom->credentials); } /* Allow server name to contain a binding string */ @@ -95,8 +92,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect_b(p, bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - lp_netbios_name(), - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + ctx->dcom->credentials); talloc_free(mem_ctx); return status; @@ -113,8 +109,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect(p, binding, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - lp_netbios_name(), - ctx->dcom->domain, ctx->dcom->user, ctx->dcom->password); + ctx->dcom->credentials); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); @@ -308,10 +303,7 @@ NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) } else { status = dcerpc_pipe_connect_b(&p, binding, uuid, 0.0, - lp_netbios_name(), - iface->ctx->dcom->domain, - iface->ctx->dcom->user, - iface->ctx->dcom->password); + iface->ctx->dcom->credentials); } talloc_free(binding); i++; diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 5c78d2b2e6..1c65bd2aff 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -24,6 +24,10 @@ const char *cli_credentials_get_username(struct cli_credentials *cred) { + if (cred == NULL) { + return NULL; + } + if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; @@ -45,6 +49,10 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_password(struct cli_credentials *cred) { + if (cred == NULL) { + return NULL; + } + if (cred->password_obtained == CRED_CALLBACK) { cred->password = cred->password_cb(cred); cred->password_obtained = CRED_SPECIFIED; @@ -66,6 +74,10 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_domain(struct cli_credentials *cred) { + if (cred == NULL) { + return NULL; + } + if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -87,7 +99,11 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e } const char *cli_credentials_get_realm(struct cli_credentials *cred) -{ +{ + if (cred == NULL) { + return NULL; + } + if (cred->realm_obtained == CRED_CALLBACK) { cred->realm = cred->realm_cb(cred); cred->realm_obtained = CRED_SPECIFIED; @@ -109,6 +125,10 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en const char *cli_credentials_get_workstation(struct cli_credentials *cred) { + if (cred == NULL) { + return NULL; + } + if (cred->workstation_obtained == CRED_CALLBACK) { cred->workstation = cred->workstation_cb(cred); cred->workstation_obtained = CRED_SPECIFIED; @@ -246,7 +266,7 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha uname = talloc_strdup(credentials, data); cli_credentials_set_username(credentials, uname, obtained); - if ((p = strchr_m(uname,'\\'))) { + if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) { *p = 0; cli_credentials_set_domain(credentials, uname, obtained); credentials->username = uname = p+1; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 4a285262c6..a72d104521 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -369,7 +369,7 @@ static struct hive_operations reg_backend_rpc = { .num_values = rpc_num_values, }; -WERROR reg_open_remote (struct registry_context **ctx, const char *user, const char *pass, const char *location) +WERROR reg_open_remote (struct registry_context **ctx, struct cli_credentials *credentials, const char *location) { NTSTATUS status; struct dcerpc_pipe *p; @@ -384,9 +384,7 @@ WERROR reg_open_remote (struct registry_context **ctx, const char *user, const c status = dcerpc_pipe_connect(&p, location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, - lp_netbios_name(), - lp_workgroup(), - user, pass); + credentials); (*ctx)->backend_data = p; if(NT_STATUS_IS_ERR(status)) { diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 7206e1e44d..dfc8be13ca 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -146,8 +146,9 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, else if (!h2) error = reg_open_local(&h2); break; case 'R': - if (!h1 && !from_null) error = reg_open_remote(&h1, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); - else if (!h2) error = reg_open_remote(&h2, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), poptGetOptArg(pc)); + if (!h1 && !from_null) + error = reg_open_remote(&h1, cmdline_credentials, poptGetOptArg(pc)); + else if (!h2) error = reg_open_remote(&h2, cmdline_credentials, poptGetOptArg(pc)); break; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index ce3d9a7e1b..2462fd8241 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -769,7 +769,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd setup_logging(argv[0], True); if (remote) { - error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); + error = reg_open_remote (&h, cmdline_credentials, remote); } else { error = reg_open_local (&h); } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index cab2c5e34b..bb7533e55e 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -395,7 +395,7 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); if (remote) { - error = reg_open_remote (&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); + error = reg_open_remote (&h, cmdline_credentials, remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); } else { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 81a7fb7f99..72cb0670de 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -105,7 +105,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) setup_logging("regtree", True); if (remote) { - error = reg_open_remote(&h, cli_credentials_get_username(cmdline_credentials), cli_credentials_get_password(cmdline_credentials), remote); + error = reg_open_remote(&h, cmdline_credentials, remote); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); } else { -- cgit From 13b0776f60f6a0f35a4afc2b3d3c6b5ec9c1ca6a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Mar 2005 23:35:58 +0000 Subject: r5929: Use cli_credentials for the SMB functions as well. Fix a couple of bugs in the new cli_credentials code (This used to be commit 4ad481cfe5cde514d2ef9646147239f3faaa6173) --- source4/lib/cmdline/popt_common.c | 5 ++--- source4/lib/credentials.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 0792a16b3d..b0b5073e62 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -195,11 +195,10 @@ static void popt_common_credentials_callback(poptContext con, { char *lp; - cli_credentials_parse_string(cmdline_credentials,arg, CRED_SPECIFIED); + cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED); if ((lp=strchr_m(arg,'%'))) { - *lp = 0; - memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_credentials->password)); + memset(lp,0,strlen(cmdline_credentials->password)); } } break; diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 1c65bd2aff..2601028e7e 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -298,8 +298,7 @@ void cli_credentials_guess(struct cli_credentials *cred) if (getenv("USER")) { cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED); if ((p = strchr_m(getenv("USER"),'%'))) { - *p = 0; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cred->password)); + memset(p,0,strlen(cred->password)); } } @@ -319,3 +318,13 @@ void cli_credentials_guess(struct cli_credentials *cred) cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED); } } + +BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) +{ + const char *username = cli_credentials_get_username(credentials); + + if (!username || !username[0]) + return True; + + return False; +} -- cgit From 455be8fb8271bd97058390dca5a76db81ea2928b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 22 Mar 2005 01:35:12 +0000 Subject: r5932: Use cli_credentials somewhat more in the Gtk+ code Support ncacn_spx in DCE/RPC bindings. (This used to be commit a0233a3a9a83176ae46873d3a25ed601758a1511) --- source4/lib/cmdline/popt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index b0b5073e62..c65c311af1 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -255,7 +255,7 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, popt_common_credentials_callback }, - { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, + { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN\\]USERNAME[%PASSWORD]" }, { "no-pass", 'N', POPT_ARG_NONE, &dont_ask, True, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, NULL, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, -- cgit From 340d35be2d3f29a3176d86c0960398c2e36f921f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 22 Mar 2005 04:22:39 +0000 Subject: r5937: - performance improvement to talloc_asprintf_append() - allow standalone talloc to use gcc printf attributes (This used to be commit e25aa54e962796e6e7385afed57aa287ef6f869d) --- source4/lib/talloc/talloc.c | 7 ++----- source4/lib/talloc/talloc.h | 8 ++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 291ee5a8bf..72765448c7 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -946,16 +946,13 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINT static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { + struct talloc_chunk *tc = talloc_chunk_from_ptr(s); int len, s_len; va_list ap2; VA_COPY(ap2, ap); - if (s) { - s_len = strlen(s); - } else { - s_len = 0; - } + s_len = tc->size - 1; len = vsnprintf(NULL, 0, fmt, ap2); s = talloc_realloc(NULL, s, char, s_len + len+1); diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 0a98881054..f639f3c8cf 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -75,8 +75,16 @@ typedef void TALLOC_CTX; #endif #ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else #define PRINTF_ATTRIBUTE(a1, a2) #endif +#endif /* The following definitions come from talloc.c */ -- cgit From 689a803ac7600c1d8bff5e33cce1c098a332c02a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 22 Mar 2005 05:51:41 +0000 Subject: r5938: - allow NULL string argument to talloc_vasprintf_append() - default to using va_copy(), thus assuming a modern libc (This used to be commit 3060b26c9e745330682f6209d97e723113b65b56) --- source4/lib/talloc/talloc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 72765448c7..31796a247b 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -36,6 +36,8 @@ #include #include #include "talloc.h" +/* assume a modern system */ +#define HAVE_VA_COPY #endif /* use this to force every realloc to change the pointer, to stress test @@ -946,10 +948,16 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINT static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { - struct talloc_chunk *tc = talloc_chunk_from_ptr(s); + struct talloc_chunk *tc; int len, s_len; va_list ap2; + if (s == NULL) { + return talloc_vasprintf(NULL, fmt, ap); + } + + tc = talloc_chunk_from_ptr(s); + VA_COPY(ap2, ap); s_len = tc->size - 1; -- cgit From da5349dede9d4add974da3078437a8513a39bbae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 22 Mar 2005 06:00:51 +0000 Subject: r5939: improve talloc_realloc() docs after feedback from lifeless (This used to be commit 301cbb0d12919f83d6b735c2e23b49fb49d5394d) --- source4/lib/talloc/talloc_guide.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index eae6c5e564..4ab0f8eacc 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -267,9 +267,13 @@ particularly useful for creating a new temporary working context. (type *)talloc_realloc(const void *context, void *ptr, type, count); The talloc_realloc() macro changes the size of a talloc -pointer. It has the following equivalences: +pointer. The "count" argument is the number of elements of type "type" +that you want the resulting pointer to hold. + +talloc_realloc() has the following equivalences: talloc_realloc(context, NULL, type, 1) ==> talloc(context, type); + talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N); talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); The "context" argument is only used if "ptr" is not NULL, otherwise it -- cgit From 645711c602313940dcf80ec786557920ecfbf884 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 22 Mar 2005 08:00:45 +0000 Subject: r5941: Commit this patch much earlier than I would normally prefer, but metze needs a working tree... The main volume of this patch was what I started working on today: - Cleans up memory handling around DCE/RPC pipes, to have a parent talloc context. - Uses sepereate inner loops for some of the DCE/RPC tests The other and more important part of this patch fixes issues surrounding the new credentials framwork: This makes the struct cli_credentials always a talloc() structure, rather than on the stack. Parts of the cli_credentials code already assumed this. There were other issues, particularly in the DCERPC over SMB handling, as well as little things that had to be tidied up before test_w2k3.sh would start to pass. Andrew Bartlett (This used to be commit 0453f9d05d2e336fba1f85dbf2718d01fa2bf778) --- source4/lib/cmdline/popt_common.c | 9 ++++--- source4/lib/com/dcom/main.c | 10 ++++---- source4/lib/credentials.c | 43 +++++++++++++++++----------------- source4/lib/registry/reg_backend_rpc.c | 14 ++++------- 4 files changed, 34 insertions(+), 42 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index c65c311af1..d364f4d3bf 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -177,13 +177,13 @@ static void popt_common_credentials_callback(poptContext con, const char *arg, const void *data) { if (reason == POPT_CALLBACK_REASON_PRE) { - cmdline_credentials = talloc_zero(talloc_autofree_context(), struct cli_credentials); - cli_credentials_guess(cmdline_credentials); - + cmdline_credentials = cli_credentials_init(talloc_autofree_context()); return; } if (reason == POPT_CALLBACK_REASON_POST) { + cli_credentials_guess(cmdline_credentials); + if (!dont_ask) { cli_credentials_set_cmdline_callbacks(cmdline_credentials); } @@ -232,8 +232,7 @@ static void popt_common_credentials_callback(poptContext con, cmdline_credentials->username_obtained = CRED_SPECIFIED; cli_credentials_set_password(cmdline_credentials, opt_password, CRED_SPECIFIED); free(opt_password); - - cli_credentials_set_domain(cmdline_credentials, lp_workgroup(), CRED_SPECIFIED); + } /* machine accounts only work with kerberos */ diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index be350c32f5..08a928cda6 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -81,7 +81,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** TALLOC_CTX *mem_ctx = talloc_init("dcom_connect"); if (server == NULL) { - return dcerpc_pipe_connect(p, "ncalrpc", + return dcerpc_pipe_connect(ctx, p, "ncalrpc", DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->dcom->credentials); @@ -89,7 +89,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** /* Allow server name to contain a binding string */ if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) { - status = dcerpc_pipe_connect_b(p, bd, + status = dcerpc_pipe_connect_b(ctx, p, bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->dcom->credentials); @@ -106,7 +106,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** return NT_STATUS_NO_MEMORY; } - status = dcerpc_pipe_connect(p, binding, + status = dcerpc_pipe_connect(ctx, p, binding, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, ctx->dcom->credentials); @@ -301,9 +301,9 @@ NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error parsing string binding")); } else { - status = dcerpc_pipe_connect_b(&p, binding, + status = dcerpc_pipe_connect_b(NULL, &p, binding, uuid, 0.0, - iface->ctx->dcom->credentials); + iface->ctx->dcom->credentials); } talloc_free(binding); i++; diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 2601028e7e..92f389e228 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -3,6 +3,7 @@ Copyright (C) Jelmer Vernooij 2005 Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 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 @@ -22,12 +23,14 @@ #include "includes.h" #include "system/filesys.h" -const char *cli_credentials_get_username(struct cli_credentials *cred) +/* Create a new credentials structure, on the specified TALLOC_CTX */ +struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) { - if (cred == NULL) { - return NULL; - } + return talloc_zero(mem_ctx, struct cli_credentials); +} +const char *cli_credentials_get_username(struct cli_credentials *cred) +{ if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; @@ -49,10 +52,6 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_password(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; - } - if (cred->password_obtained == CRED_CALLBACK) { cred->password = cred->password_cb(cred); cred->password_obtained = CRED_SPECIFIED; @@ -74,10 +73,6 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_domain(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; - } - if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -264,23 +259,20 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha char *uname, *p; uname = talloc_strdup(credentials, data); - cli_credentials_set_username(credentials, uname, obtained); - - if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) { + if ((p = strchr_m(uname,'%'))) { *p = 0; - cli_credentials_set_domain(credentials, uname, obtained); - credentials->username = uname = p+1; + cli_credentials_set_password(credentials, p+1, obtained); } if ((p = strchr_m(uname,'@'))) { *p = 0; cli_credentials_set_realm(credentials, p+1, obtained); - } - - if ((p = strchr_m(uname,'%'))) { + } else if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) { *p = 0; - cli_credentials_set_password(credentials, p+1, obtained); + cli_credentials_set_domain(credentials, uname, obtained); + uname = p+1; } + cli_credentials_set_username(credentials, uname, obtained); } void cli_credentials_guess(struct cli_credentials *cred) @@ -319,11 +311,18 @@ void cli_credentials_guess(struct cli_credentials *cred) } } +/* Fill in a credentails structure as anonymous */ +void cli_credentials_set_anonymous(struct cli_credentials *cred) +{ + cli_credentials_set_username(cred, "", CRED_SPECIFIED); + cli_credentials_set_domain(cred, "", CRED_SPECIFIED); +} + BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) { const char *username = cli_credentials_get_username(credentials); - if (!username || !username[0]) + if (!username[0]) return True; return False; diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index a72d104521..5240cf5696 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -122,13 +122,6 @@ static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hke return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol)); } -static int rpc_close (void *_h) -{ - struct registry_context *h = _h; - dcerpc_pipe_close(h->backend_data); - return 0; -} - #if 0 static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) { @@ -381,7 +374,8 @@ WERROR reg_open_remote (struct registry_context **ctx, struct cli_credentials *c location = talloc_strdup(ctx, "ncalrpc:"); } - status = dcerpc_pipe_connect(&p, location, + status = dcerpc_pipe_connect(*ctx /* TALLOC_CTX */, + &p, location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, credentials); @@ -389,13 +383,13 @@ WERROR reg_open_remote (struct registry_context **ctx, struct cli_credentials *c if(NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status))); + talloc_free(*ctx); + *ctx = NULL; return ntstatus_to_werror(status); } (*ctx)->get_predefined_key = rpc_get_predefined_key; - talloc_set_destructor(*ctx, rpc_close); - return WERR_OK; } -- cgit From e25cff1c110c5b4380caf5f5fb0336c37da78b10 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 22 Mar 2005 10:33:53 +0000 Subject: r5942: A couple of small changes to fix things up with the new credentials infrustructure. Andrew Bartlett (This used to be commit d51718ab8a3771ada4e342a384b744edb803db40) --- source4/lib/credentials.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 92f389e228..211cb9ce07 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -316,6 +316,7 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) { cli_credentials_set_username(cred, "", CRED_SPECIFIED); cli_credentials_set_domain(cred, "", CRED_SPECIFIED); + cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) -- cgit From 7c55d0ffa5af6d372ce63ba369a20d9a46fa6454 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 22 Mar 2005 22:11:50 +0000 Subject: r5976: SIDs can't have more then 5 subauths (caught by [validate] and range()) (This used to be commit ec1eaa274b997197ca6996457229c802f1b76d56) --- source4/lib/cmdline/popt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index d364f4d3bf..7049ce65df 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -3,7 +3,7 @@ Common popt routines Copyright (C) Tim Potter 2001,2002 - Copyright (C) Jelmer Vernooij 2002,2003 + Copyright (C) Jelmer Vernooij 2002,2003,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 -- cgit From 79f6bcd5ae1711075ce0e75392ce83a72766698e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Mar 2005 01:30:43 +0000 Subject: r5988: Fix the -P option (use machine account credentials) to use the Samba4 secrets system, and not the old system from Samba3. This allowed the code from auth_domain to be shared - we now only lookup the secrets.ldb in lib/credentials.c. In order to link the resultant binary, samdb_search() has been moved from deep inside rpc_server into lib/gendb.c, along with the existing gendb_search_v(). The vast majority of this patch is the simple rename that followed, (Depending on the whole SAMDB for just this function seemed pointless, and brought in futher dependencies, such as smbencrypt.c). Andrew Bartlett (This used to be commit e13c671619bd290a8b3cae8555cb281a9a185ee0) --- source4/lib/basic.mk | 2 + source4/lib/cmdline/config.mk | 2 +- source4/lib/cmdline/popt_common.c | 21 +--------- source4/lib/credentials.c | 79 +++++++++++++++++++++++++++++++++++--- source4/lib/gendb.c | 80 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 26 deletions(-) create mode 100644 source4/lib/gendb.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 29dbbd22c7..7d6847c465 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -65,8 +65,10 @@ ADD_OBJ_FILES = \ lib/unix_privs.o \ lib/db_wrap.o \ lib/gencache.o \ + lib/gendb.o \ lib/credentials.o REQUIRED_SUBSYSTEMS = \ LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC # End SUBSYSTEM LIBBASIC ############################## + diff --git a/source4/lib/cmdline/config.mk b/source4/lib/cmdline/config.mk index 803c81f273..831461b7f3 100644 --- a/source4/lib/cmdline/config.mk +++ b/source4/lib/cmdline/config.mk @@ -2,6 +2,6 @@ # Start SUBSYSTEM LIBCMDLINE_CREDENTIALS [SUBSYSTEM::LIBCMDLINE_CREDENTIALS] ADD_OBJ_FILES = lib/cmdline/getsmbpass.o \ - lib/cmdline/credentials.o + lib/cmdline/credentials.o # End SUBSYSTEM LIBCMDLINE_CREDENTIALS ############################## diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 7049ce65df..50e07d95e9 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -213,26 +213,7 @@ static void popt_common_credentials_callback(poptContext con, case 'P': { - char *opt_password = NULL; - /* it is very useful to be able to make ads queries as the - machine account for testing purposes and for domain leave */ - - if (!secrets_init()) { - d_printf("ERROR: Unable to open secrets database\n"); - exit(1); - } - - opt_password = secrets_fetch_machine_password(lp_workgroup()); - - if (!opt_password) { - d_printf("ERROR: Unable to fetch machine password\n"); - exit(1); - } - cmdline_credentials->username = talloc_asprintf(cmdline_credentials, "%s$", lp_netbios_name()); - cmdline_credentials->username_obtained = CRED_SPECIFIED; - cli_credentials_set_password(cmdline_credentials, opt_password, CRED_SPECIFIED); - free(opt_password); - + cli_credentials_set_machine_account(cmdline_credentials); } /* machine accounts only work with kerberos */ diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 211cb9ce07..b997e6ae53 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -22,11 +22,23 @@ #include "includes.h" #include "system/filesys.h" +#include "lib/cmdline/popt_common.h" +#include "include/secrets.h" +#include "lib/ldb/include/ldb.h" /* Create a new credentials structure, on the specified TALLOC_CTX */ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) { - return talloc_zero(mem_ctx, struct cli_credentials); + struct cli_credentails *cred = talloc_zero(mem_ctx, struct cli_credentials); + if (!cred) { + return cred; + } + + cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); + cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); + + return cred; } const char *cli_credentials_get_username(struct cli_credentials *cred) @@ -279,10 +291,6 @@ void cli_credentials_guess(struct cli_credentials *cred) { char *p; - cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); - cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); - cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); - if (getenv("LOGNAME")) { cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); } @@ -311,6 +319,67 @@ void cli_credentials_guess(struct cli_credentials *cred) } } +NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) +{ + TALLOC_CTX *mem_ctx = talloc_named(creds, 0, "cli_credentials fetch machine password"); + + struct ldb_context *ldb; + int ldb_ret; + struct ldb_message **msgs; + const char *base_dn = SECRETS_PRIMARY_DOMAIN_DN; + const char *attrs[] = { + "secret", + "samAccountName", + NULL + }; + + const char *machine_account; + const char *password; + + /* Local secrets are stored in secrets.ldb */ + ldb = secrets_db_connect(mem_ctx); + if (!ldb) { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + /* search for the secret record */ + ldb_ret = gendb_search(ldb, + mem_ctx, base_dn, &msgs, attrs, + SECRETS_PRIMARY_DOMAIN_FILTER, + cli_credentials_get_domain(creds)); + if (ldb_ret == 0) { + DEBUG(1, ("Could not find join record to domain: %s\n", + lp_workgroup())); + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } else if (ldb_ret != 1) { + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + password = ldb_msg_find_string(msgs[0], "secret", NULL); + if (!password) { + DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", + cli_credentials_get_domain(creds))); + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); + if (!machine_account) { + DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", + cli_credentials_get_domain(creds))); + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + cli_credentials_set_username(creds, machine_account, CRED_SPECIFIED); + cli_credentials_set_password(creds, password, CRED_SPECIFIED); + talloc_free(mem_ctx); + + return NT_STATUS_OK; +} + /* Fill in a credentails structure as anonymous */ void cli_credentials_set_anonymous(struct cli_credentials *cred) { diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c new file mode 100644 index 0000000000..befdd63c9e --- /dev/null +++ b/source4/lib/gendb.c @@ -0,0 +1,80 @@ +/* + Unix SMB/CIFS implementation. + + common share info functions + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Tim Potter 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/ldb/include/ldb.h" + +/* + search the sam for the specified attributes - va_list variant +*/ +int gendb_search_v(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, + va_list ap) _PRINTF_ATTRIBUTE(6,0) +{ + char *expr = NULL; + int count; + + vasprintf(&expr, format, ap); + if (expr == NULL) { + return -1; + } + + *res = NULL; + + count = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, attrs, res); + + if (*res) talloc_steal(mem_ctx, *res); + + DEBUG(4,("gendb_search_v: %s %s -> %d (%s)\n", + basedn?basedn:"NULL", expr, count, + count==-1?ldb_errstring(ldb):"OK")); + + free(expr); + + return count; +} + +/* + search the LDB for the specified attributes - varargs variant +*/ +int gendb_search(struct ldb_context *sam_ldb, + TALLOC_CTX *mem_ctx, + const char *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) _PRINTF_ATTRIBUTE(6,7) +{ + va_list ap; + int count; + + va_start(ap, format); + count = gendb_search_v(sam_ldb, mem_ctx, basedn, res, attrs, format, ap); + va_end(ap); + + return count; +} + -- cgit From 4a095be54184230de8ee658399dd8c82c4401d64 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 23 Mar 2005 01:42:29 +0000 Subject: r5989: Display authentication information (list of available auth protocols + principal names per endpoint) to gepdump. Still need to fix memory management in the GTK+ utilities... (This used to be commit b48a0af0b0fbf1234627ec785699896a44b23e75) --- source4/lib/credentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index b997e6ae53..e98e261b05 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -392,7 +392,7 @@ BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) { const char *username = cli_credentials_get_username(credentials); - if (!username[0]) + if (!username || !username[0]) return True; return False; -- cgit From 038c4c4c6a4f6039e0436134de1d9c1e14c444d8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Mar 2005 03:32:25 +0000 Subject: r6024: Some of the ordering constraints on the popt callbacks were getting painful, so don't call lp_*() functions until the post stage (rather than in the cli_credentails_init(), which is called in the pre stage), and don't open the secrets.ldb looking for the machine account details until we actually need them (well after popt is done, and we know we have the other things right). Set the domain and realm, as well as the account and password for -P (fetch machine password) operation. Allow NETLOGON credentials to be stored in this structure - will allow SCHANNEL to be made more generic. Clarify why we don't do special checks for NULL pointers, particularly in the anonymous check (it indicates a programmer error, not a run-time condition). Also make lib/credentials.c a little more consistant. Andrew Bartlett (This used to be commit 730e6056b730c15008772c30cd6f7c03fb6b7e5f) --- source4/lib/cmdline/popt_common.c | 8 +-- source4/lib/credentials.c | 107 ++++++++++++++++++++++++++++++-------- 2 files changed, 90 insertions(+), 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 50e07d95e9..68f491a188 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -212,10 +212,10 @@ static void popt_common_credentials_callback(poptContext con, break; case 'P': - { - cli_credentials_set_machine_account(cmdline_credentials); - } - /* machine accounts only work with kerberos */ + /* Later, after this is all over, get the machine account details from the secrets.ldb */ + cli_credentials_set_machine_account_pending(cmdline_credentials); + + /* machine accounts only work with kerberos (fall though)*/ case 'k': #ifndef HAVE_KRB5 diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index e98e261b05..da0bc4236f 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -34,15 +34,15 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) return cred; } - cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); - cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); - cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); - return cred; } const char *cli_credentials_get_username(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; @@ -64,6 +64,10 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_password(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->password_obtained == CRED_CALLBACK) { cred->password = cred->password_cb(cred); cred->password_obtained = CRED_SPECIFIED; @@ -85,6 +89,10 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_domain(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -107,8 +115,8 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e const char *cli_credentials_get_realm(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); } if (cred->realm_obtained == CRED_CALLBACK) { @@ -119,6 +127,14 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) return cred->realm; } +char *cli_credentials_get_principal(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx) +{ + return talloc_asprintf(mem_ctx, "%s@%s", + cli_credentials_get_username(cred), + cli_credentials_get_realm(cred)); +} + BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) { if (obtained >= cred->realm_obtained) { @@ -132,10 +148,6 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en const char *cli_credentials_get_workstation(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; - } - if (cred->workstation_obtained == CRED_CALLBACK) { cred->workstation = cred->workstation_cb(cred); cred->workstation_obtained = CRED_SPECIFIED; @@ -287,10 +299,20 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha cli_credentials_set_username(credentials, uname, obtained); } +/* Initialise defaults from the lp_*() functions */ +void cli_credentials_set_conf(struct cli_credentials *cred) +{ + cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); + cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); +} + void cli_credentials_guess(struct cli_credentials *cred) { char *p; + cli_credentials_set_conf(cred); + if (getenv("LOGNAME")) { cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); } @@ -319,9 +341,9 @@ void cli_credentials_guess(struct cli_credentials *cred) } } -NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) +NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) { - TALLOC_CTX *mem_ctx = talloc_named(creds, 0, "cli_credentials fetch machine password"); + TALLOC_CTX *mem_ctx; struct ldb_context *ldb; int ldb_ret; @@ -330,15 +352,24 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) const char *attrs[] = { "secret", "samAccountName", + "flatname", + "realm", NULL }; const char *machine_account; const char *password; + const char *domain; + const char *realm; + /* ok, we are going to get it now, don't recurse back here */ + cred->machine_account_pending = False; + + mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password"); /* Local secrets are stored in secrets.ldb */ ldb = secrets_db_connect(mem_ctx); if (!ldb) { + DEBUG(1, ("Could not open secrets.ldb\n")); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -346,13 +377,15 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) ldb_ret = gendb_search(ldb, mem_ctx, base_dn, &msgs, attrs, SECRETS_PRIMARY_DOMAIN_FILTER, - cli_credentials_get_domain(creds)); + cli_credentials_get_domain(cred)); if (ldb_ret == 0) { DEBUG(1, ("Could not find join record to domain: %s\n", - lp_workgroup())); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } else if (ldb_ret != 1) { + DEBUG(1, ("Found more than one (%d) join records to domain: %s\n", + ldb_ret, cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -360,7 +393,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) password = ldb_msg_find_string(msgs[0], "secret", NULL); if (!password) { DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", - cli_credentials_get_domain(creds))); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -368,18 +401,47 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); if (!machine_account) { DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", - cli_credentials_get_domain(creds))); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - cli_credentials_set_username(creds, machine_account, CRED_SPECIFIED); - cli_credentials_set_password(creds, password, CRED_SPECIFIED); + domain = ldb_msg_find_string(msgs[0], "flatname", NULL); + if (domain) { + cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); + } + + realm = ldb_msg_find_string(msgs[0], "realm", NULL); + if (realm) { + cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); + } + + cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); + cli_credentials_set_password(cred, password, CRED_SPECIFIED); talloc_free(mem_ctx); return NT_STATUS_OK; } +void cli_credentials_set_machine_account_pending(struct cli_credentials *cred) +{ + cred->machine_account_pending = True; +} +/* Attach NETLOGON credentials for use with SCHANNEL */ + +void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, + struct creds_CredentialState *netlogon_creds) +{ + cred->netlogon_creds = talloc_reference(cred, netlogon_creds); +} + +/* Return attached NETLOGON credentials */ + +struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) +{ + return cred->netlogon_creds; +} + /* Fill in a credentails structure as anonymous */ void cli_credentials_set_anonymous(struct cli_credentials *cred) { @@ -388,11 +450,14 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } -BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) +BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) { - const char *username = cli_credentials_get_username(credentials); + const char *username = cli_credentials_get_username(cred); - if (!username || !username[0]) + /* Yes, it is deliberate that we die if we have a NULL pointer + * here - anymous is "", not NULL, which is 'never specified, + * never guessed', ie programmer bug */ + if (!username[0]) return True; return False; -- cgit From ae1ea5619b18be9c37f9647756e06718b17b88f2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 24 Mar 2005 08:00:15 +0000 Subject: r6033: Patch from 'lifeless' to clarify behaviour with NULL pointers. Andrew Bartlett (This used to be commit 48c518796797f021c9c7f319ca8cd0a0c185f64c) --- source4/lib/talloc/talloc.c | 3 ++- source4/lib/talloc/talloc_guide.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 31796a247b..0d78dd8d24 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -609,7 +609,8 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n /* move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. */ void *talloc_steal(const void *new_ctx, const void *ptr) { diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 4ab0f8eacc..aca3ab4937 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -306,6 +306,7 @@ NOTE: It is possible to produce loops in the parent/child relationship if you are not careful with talloc_steal(). No guarantees are provided as to your sanity or the safety of your data if you do this. +talloc_steal (new_ctx, NULL) will return NULL with no sideeffects. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- off_t talloc_total_size(const void *ptr); -- cgit From 2fa732c6251f6dd23c3c8ef1facf638c9c531bdd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 24 Mar 2005 20:29:04 +0000 Subject: r6045: Couple of small GTK+ fixes Use uint32_t and uint16_t rather then DWORD and WORD in the NT4 backend. Add some more unknown fields.. (This used to be commit 6c3b1ec3296c7ab1ddfdcee86162f2eb0d73f5a8) --- source4/lib/registry/reg_backend_nt4.c | 121 ++++++++++++++++----------------- 1 file changed, 60 insertions(+), 61 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index d700070cde..6072222a87 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -1,7 +1,7 @@ /* Samba Unix/Linux SMB client utility libeditreg.c Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com - Copyright (C) 2003-2004 Jelmer Vernooij, jelmer@samba.org + Copyright (C) 2003-2005 Jelmer Vernooij, jelmer@samba.org 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 @@ -342,9 +342,6 @@ const char *def_owner_sid_str = NULL; #define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) -typedef uint_t DWORD; -typedef unsigned short WORD; - typedef struct sk_struct SK_HDR; /* * This structure keeps track of the output format of the registry @@ -353,65 +350,67 @@ typedef struct sk_struct SK_HDR; #define REG_OUTBLK_HBIN 2 typedef struct regf_block { - DWORD REGF_ID; /* regf */ - DWORD uk1; - DWORD uk2; - DWORD tim1, tim2; - DWORD uk3; /* 1 */ - DWORD uk4; /* 3 */ - DWORD uk5; /* 0 */ - DWORD uk6; /* 1 */ - DWORD first_key; /* offset */ - uint_t dblk_size; - DWORD uk7[116]; /* 1 */ - DWORD chksum; + uint32_t REGF_ID; /* regf */ + uint32_t update_counter1; + uint32_t update_counter2; + uint32_t tim1, tim2; + uint32_t uk3; /* 1 */ + uint32_t uk4; /* 3 */ + uint32_t uk5; /* 0 */ + uint32_t uk6; /* 1 */ + uint32_t first_key; /* offset */ + uint32_t dblk_size; + uint32_t uk7; /* 1 */ + wchar_t filename[64]; + uint32_t unused[83]; + uint32_t chksum; /* Checksum of first 0x200 bytes */ } REGF_HDR; typedef struct hbin_sub_struct { - DWORD dblocksize; + uint32_t dblocksize; char data[1]; } HBIN_SUB_HDR; typedef struct hbin_struct { - DWORD HBIN_ID; /* hbin */ - DWORD off_from_first; - DWORD off_to_next; - DWORD uk1; - DWORD uk2; - DWORD uk3; - DWORD uk4; - DWORD blk_size; + uint32_t HBIN_ID; /* hbin */ + uint32_t off_from_first; + uint32_t off_to_next; + uint32_t uk1; + uint32_t uk2; + uint32_t uk3; + uint32_t uk4; + uint32_t blk_size; HBIN_SUB_HDR hbin_sub_hdr; } HBIN_HDR; typedef struct nk_struct { - WORD NK_ID; - WORD type; - DWORD t1, t2; - DWORD uk1; - DWORD own_off; - DWORD subk_num; - DWORD uk2; - DWORD lf_off; - DWORD uk3; - DWORD val_cnt; - DWORD val_off; - DWORD sk_off; - DWORD clsnam_off; - DWORD unk4[4]; - DWORD unk5; - WORD nam_len; - WORD clsnam_len; + uint16_t NK_ID; + uint16_t type; + uint32_t t1, t2; + uint32_t uk1; + uint32_t own_off; + uint32_t subk_num; + uint32_t uk2; + uint32_t lf_off; + uint32_t uk3; + uint32_t val_cnt; + uint32_t val_off; + uint32_t sk_off; + uint32_t clsnam_off; + uint32_t unk4[4]; + uint32_t unk5; + uint16_t nam_len; + uint16_t clsnam_len; char key_nam[1]; /* Actual length determined by nam_len */ } NK_HDR; struct sk_struct { - WORD SK_ID; - WORD uk1; - DWORD prev_off; - DWORD next_off; - DWORD ref_cnt; - DWORD rec_size; + uint16_t SK_ID; + uint16_t uk1; + uint32_t prev_off; + uint32_t next_off; + uint32_t ref_cnt; + uint32_t rec_size; char sec_desc[1]; }; @@ -431,27 +430,27 @@ typedef struct sk_map_s { } SK_MAP; typedef struct vk_struct { - WORD VK_ID; - WORD nam_len; - DWORD dat_len; /* If top-bit set, offset contains the data */ - DWORD dat_off; - DWORD dat_type; - WORD flag; /* =1, has name, else no name (=Default). */ - WORD unk1; + uint16_t VK_ID; + uint16_t nam_len; + uint32_t dat_len; /* If top-bit set, offset contains the data */ + uint32_t dat_off; + uint32_t dat_type; + uint16_t flag; /* =1, has name, else no name (=Default). */ + uint16_t unk1; char dat_name[1]; /* Name starts here ... */ } VK_HDR; -typedef DWORD VL_TYPE[1]; /* Value list is an array of vk rec offsets */ +typedef uint32_t VL_TYPE[1]; /* Value list is an array of vk rec offsets */ typedef struct hash_struct { - DWORD nk_off; + uint32_t nk_off; char hash[4]; } HASH_REC; typedef struct lf_struct { - WORD LF_ID; - WORD key_count; + uint16_t LF_ID; + uint16_t key_count; struct hash_struct hr[1]; /* Array of hash records, depending on key_count */} LF_HDR; @@ -491,7 +490,7 @@ typedef struct regf_struct_s { HBIN_BLK *blk_head, *blk_tail, *free_space; } REGF; -static DWORD str_to_dword(const char *a) { +static uint32_t str_to_dword(const char *a) { int i; unsigned long ret = 0; for(i = strlen(a)-1; i >= 0; i--) { @@ -1373,7 +1372,7 @@ static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char * rsd->revision = SEC_DESC_REVISION; rsd->type = SEC_DESC_DACL_PRESENT | SEC_DESC_SELF_RELATIVE; - off = 4 * sizeof(DWORD) + 4; + off = 4 * sizeof(uint32_t) + 4; if (sd->sacl){ size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); -- cgit From 5ae38fb963cf1907043129b4d423c7bc8fe18fb1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 26 Mar 2005 01:08:59 +0000 Subject: r6070: Fix typo's and fallback to "" as default user name if no other username could be guessed. (This used to be commit 7fe77cd65901776b5a78e8398547f364379259d3) --- source4/lib/credentials.c | 5 +++-- source4/lib/socket/socket_unix.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index da0bc4236f..167650f8c2 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -29,7 +29,7 @@ /* Create a new credentials structure, on the specified TALLOC_CTX */ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) { - struct cli_credentails *cred = talloc_zero(mem_ctx, struct cli_credentials); + struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials); if (!cred) { return cred; } @@ -311,6 +311,7 @@ void cli_credentials_guess(struct cli_credentials *cred) { char *p; + cli_credentials_set_username(cred, "", CRED_GUESSED); cli_credentials_set_conf(cred); if (getenv("LOGNAME")) { @@ -455,7 +456,7 @@ BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) const char *username = cli_credentials_get_username(cred); /* Yes, it is deliberate that we die if we have a NULL pointer - * here - anymous is "", not NULL, which is 'never specified, + * here - anonymous is "", not NULL, which is 'never specified, * never guessed', ie programmer bug */ if (!username[0]) return True; diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 7cf12db4b2..614229aaac 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -23,7 +23,6 @@ #include "includes.h" #include "lib/socket/socket.h" -#include "lib/socket/socket.h" #include "system/network.h" #include "system/filesys.h" -- cgit From 0d36266cd4e0034ca5ed2755084a64db3e235ac4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 26 Mar 2005 10:47:44 +0000 Subject: r6075: added talloc_enable_null_tracking() (asked for by lifeless) (This used to be commit 40b8ee186af3e7f771c680dbbb03fdcf559bf103) --- source4/lib/talloc/talloc.c | 14 ++++++++++++-- source4/lib/talloc/talloc.h | 1 + source4/lib/talloc/talloc_guide.txt | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 0d78dd8d24..661282a87d 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -811,12 +811,22 @@ static void talloc_report_null_full(void) } } +/* + enable tracking of the NULL context +*/ +void talloc_enable_null_tracking(void) +{ + if (null_context == NULL) { + null_context = talloc_named_const(NULL, 0, "null_context"); + } +} + /* enable leak reporting on exit */ void talloc_enable_leak_report(void) { - null_context = talloc_named_const(NULL, 0, "null_context"); + talloc_enable_null_tracking(); atexit(talloc_report_null); } @@ -825,7 +835,7 @@ void talloc_enable_leak_report(void) */ void talloc_enable_leak_report_full(void) { - null_context = talloc_named_const(NULL, 0, "null_context"); + talloc_enable_null_tracking(); atexit(talloc_report_null_full); } diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index f639f3c8cf..8b448f63c5 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -110,6 +110,7 @@ off_t talloc_total_size(const void *ptr); off_t talloc_total_blocks(const void *ptr); void talloc_report_full(const void *ptr, FILE *f); void talloc_report(const void *ptr, FILE *f); +void talloc_enable_null_tracking(void); void talloc_enable_leak_report(void); void talloc_enable_leak_report_full(void); void *_talloc_zero(const void *ctx, size_t size, const char *name); diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index aca3ab4937..7d6dfa5cb2 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -408,6 +408,14 @@ full talloc report on 'root' (total 18 bytes in 8 blocks) x1 contains 1 bytes in 1 blocks (ref 0) +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void talloc_enable_null_tracking(void); + +This enables tracking of the NULL memory context without enabling leak +reporting on exit. Useful for when you want to do your own leak +reporting call via talloc_report_null_full(); + + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- (type *)talloc_zero(const void *ctx, type); -- cgit From 6ed40eda29a00cafd9a316bec86c41c5cce592c3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Mar 2005 06:55:03 +0000 Subject: r6079: Add inline documentation on the credentials context API. Andrew Bartlett (This used to be commit 258c04e3678b936bb564ecef10f14128c0a54510) --- source4/lib/credentials.c | 124 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 167650f8c2..9c892b0688 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -26,7 +26,10 @@ #include "include/secrets.h" #include "lib/ldb/include/ldb.h" -/* Create a new credentials structure, on the specified TALLOC_CTX */ +/** + * Create a new credentials structure + * @param mem_ctx TALLOC_CTX parent for credentials structure + */ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) { struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials); @@ -37,6 +40,12 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) return cred; } +/** + * Obtain the username for this credentials context. + * @param cred credentials context + * @retval The username set on this context. + * @note Return value will never be NULL except by programmer error. + */ const char *cli_credentials_get_username(struct cli_credentials *cred) { if (cred->machine_account_pending) { @@ -62,6 +71,11 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, return False; } +/** + * Obtain the password for this credentials context. + * @param cred credentials context + * @retval If set, the cleartext password, otherwise NULL + */ const char *cli_credentials_get_password(struct cli_credentials *cred) { if (cred->machine_account_pending) { @@ -87,6 +101,12 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, return False; } +/** + * Obtain the 'short' or 'NetBIOS' domain for this credentials context. + * @param cred credentials context + * @retval The domain set on this context. + * @note Return value will never be NULL except by programmer error. + */ const char *cli_credentials_get_domain(struct cli_credentials *cred) { if (cred->machine_account_pending) { @@ -113,6 +133,12 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e return False; } +/** + * Obtain the Kerberos realm for this credentials context. + * @param cred credentials context + * @retval The realm set on this context. + * @note Return value will never be NULL except by programmer error. + */ const char *cli_credentials_get_realm(struct cli_credentials *cred) { if (cred->machine_account_pending) { @@ -127,8 +153,15 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) return cred->realm; } +/** + * Obtain the user's Kerberos principal for this credentials context. + * @param cred credentials context + * @param mem_ctx A talloc context to return the prinipal name on. + * @retval The user's Kerberos principal + * @note Return value may be NULL due to out-of memeory or invalid mem_ctx + */ char *cli_credentials_get_principal(struct cli_credentials *cred, - TALLOC_CTX *mem_ctx) + TALLOC_CTX *mem_ctx) { return talloc_asprintf(mem_ctx, "%s@%s", cli_credentials_get_username(cred), @@ -146,6 +179,13 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en return False; } +/** + * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context. + * + * @param cred credentials context + * @retval The workstation name set on this context. + * @note Return value will never be NULL except by programmer error. + */ const char *cli_credentials_get_workstation(struct cli_credentials *cred) { if (cred->workstation_obtained == CRED_CALLBACK) { @@ -167,6 +207,14 @@ BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *v return False; } +/** + * Read a file descriptor, and parse it for a password (eg from a file or stdin) + * + * @param credentials Credentials structure on which to set the password + * @param fd open file descriptor to read the password from + * @param obtained This enum describes how 'specified' this password is + */ + BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained) { char *p; @@ -201,6 +249,14 @@ BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int return True; } +/** + * Read a named file, and parse it for a password + * + * @param credentials Credentials structure on which to set the password + * @param file a named file to read the password from + * @param obtained This enum describes how 'specified' this password is + */ + BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained) { int fd = open(file, O_RDONLY, 0); @@ -219,6 +275,14 @@ BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, co return ret; } +/** + * Read a named file, and parse it for username, domain, realm and password + * + * @param credentials Credentials structure on which to set the password + * @param file a named file to read the details from + * @param obtained This enum describes how 'specified' this password is + */ + BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) { XFILE *auth; @@ -278,6 +342,16 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, } +/** + * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields + * + * The format accepted is [domain\\]user[%password] or user[@realm][%password] + * + * @param credentials Credentials structure on which to set the password + * @param data the string containing the username, password etc + * @param obtained This enum describes how 'specified' this password is + */ + void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained) { char *uname, *p; @@ -299,7 +373,12 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha cli_credentials_set_username(credentials, uname, obtained); } -/* Initialise defaults from the lp_*() functions */ +/** + * Specifies default values for domain, workstation and realm + * from the smb.conf configuration file + * + * @param cred Credentials structure to fill in + */ void cli_credentials_set_conf(struct cli_credentials *cred) { cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); @@ -307,6 +386,12 @@ void cli_credentials_set_conf(struct cli_credentials *cred) cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); } +/** + * Guess defaults for credentials from environment variables, + * and from the configuration file + * + * @param cred Credentials structure to fill in + */ void cli_credentials_guess(struct cli_credentials *cred) { char *p; @@ -342,6 +427,12 @@ void cli_credentials_guess(struct cli_credentials *cred) } } +/** + * Fill in credentials for the machine trust account, from the secrets database. + * + * @param cred Credentials structure to fill in + * @retval NTSTATUS error detailing any failure + */ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) { TALLOC_CTX *mem_ctx; @@ -424,11 +515,23 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) return NT_STATUS_OK; } +/** + * Ask that when required, the credentials system will be filled with + * machine trust account, from the secrets database. + * + * @param cred Credentials structure to fill in + * @note This function is used to call the above function after, rather + * than during, popt processing. + * + */ void cli_credentials_set_machine_account_pending(struct cli_credentials *cred) { cred->machine_account_pending = True; } -/* Attach NETLOGON credentials for use with SCHANNEL */ + +/** + * Attach NETLOGON credentials for use with SCHANNEL + */ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, struct creds_CredentialState *netlogon_creds) @@ -436,14 +539,18 @@ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, cred->netlogon_creds = talloc_reference(cred, netlogon_creds); } -/* Return attached NETLOGON credentials */ +/** + * Return attached NETLOGON credentials + */ struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) { return cred->netlogon_creds; } -/* Fill in a credentails structure as anonymous */ +/** + * Fill in a credentials structure as the anonymous user + */ void cli_credentials_set_anonymous(struct cli_credentials *cred) { cli_credentials_set_username(cred, "", CRED_SPECIFIED); @@ -451,6 +558,11 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } +/** + * Describe a credentials context as anonymous or authenticated + * @retval True if anonymous, False if a username is specified + */ + BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) { const char *username = cli_credentials_get_username(cred); -- cgit From be6285adadfe7f66fffc4dc7d6de3a2dfef65d2a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 28 Mar 2005 00:37:27 +0000 Subject: r6086: default to stderr for error messages in ldb, so we get errors in ldb_connect() (This used to be commit a6e492f95c6f31ed37ee32a13a34fa2847d8352d) --- source4/lib/ldb/common/ldb_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c index 6ba3f30b2d..59f00ccc96 100644 --- a/source4/lib/ldb/common/ldb_debug.c +++ b/source4/lib/ldb/common/ldb_debug.c @@ -79,7 +79,7 @@ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char * { va_list ap; if (ldb->debug_ops.debug == NULL) { - return; + ldb_set_debug_stderr(ldb); } va_start(ap, fmt); ldb->debug_ops.debug(ldb->debug_ops.context, level, fmt, ap); -- cgit From a5ee5aae6921b844f142d3a5dd67c188612723d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 28 Mar 2005 00:40:18 +0000 Subject: r6087: - remove the dlopen code for now (before it goes back, it needs to be made into something that isn't a maze of #ifdefs) - when a module is not found, make it a non-fatal error. Otherwise the standalone ldb tools just bail out. The previous code meant that if you had a module listed and it wasn't present then you could _never_ fix it, as you coudln't open the ldb to remove that module from @MODULES ! (This used to be commit c4728625c093d91e522b80c049e0d42d2b5f143b) --- source4/lib/ldb/common/ldb_modules.c | 45 +----------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 40d2cd064a..ffa150d773 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -167,13 +167,6 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } for (i = 0; modules[i] != NULL; i++) { -#ifdef HAVE_DLOPEN_DISABLED - void *handle; - ldb_module_init_function init; - struct stat st; - char *filename; - const char *errstr; -#endif struct ldb_module *current; if (strcmp(modules[i], "schema") == 0) { @@ -208,43 +201,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) } #endif -#ifdef HAVE_DLOPEN_DISABLED - filename = talloc_asprintf(ldb, "%s.so", modules[i]); - if (!filename) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Talloc failed!\n"); - return -1; - } - - if (stat(filename, &st) < 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); - return -1; - } - - handle = dlopen(filename, RTLD_LAZY); - - if (!handle) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror()); - return -1; - } - - init = (ldb_module_init_function)dlsym(handle, "init_module"); - - errstr = dlerror(); - if (errstr) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr); - return -1; - } - - current = init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); -#else - ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]); - return -1; -#endif + ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", modules[i]); } talloc_free(modules); -- cgit From e91fb065fa83e2ad4e3dacec22f011baf5d3d752 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 28 Mar 2005 01:00:39 +0000 Subject: r6088: Add the socket_wrapper library. This is a very simple library that redirects traffic (currently just IP traffic) over unix domain sockets if the SOCKET_WRAPPER_DIR environment variable has been set. Aim is to use this for the Samba4 torture suite on the buildfarm. The socket_wrapper library can only be used if Samba was compiled with --enable-developer. test_rpc.sh passes against a local smbd with SOCKET_WRAPPER_DIR set. (and ethereal showed no traffic whatsoever) Stuff that still needs to be fixed in socketwrapper: - Give ENETUNREACH if target is not localhost - A given port number can only be used for UDP /or/ TCP, not both. - Perhaps allow some calls to circumvent socketwrapper (do we need DNS?) (This used to be commit f8a63a843ccca092d9756b64e09175d37c08550a) --- source4/lib/basic.mk | 11 +- source4/lib/socket_wrapper.c | 401 +++++++++++++++++++++++++++++++++++++++++++ source4/lib/socket_wrapper.h | 48 ++++++ 3 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 source4/lib/socket_wrapper.c create mode 100644 source4/lib/socket_wrapper.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 7d6847c465..560234a00c 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -32,6 +32,14 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBCRYPTO ############################## +############################## +# Start SUBSYSTEM SOCKET_WRAPPER +[SUBSYSTEM::SOCKET_WRAPPER] +NOPROTO = YES +INIT_OBJ_FILES = lib/socket_wrapper.o +# End SUBSYSTEM SOCKET_WRAPPER +############################## + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] @@ -68,7 +76,8 @@ ADD_OBJ_FILES = \ lib/gendb.o \ lib/credentials.o REQUIRED_SUBSYSTEMS = \ - LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC + LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC \ + SOCKET_WRAPPER # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/socket_wrapper.c b/source4/lib/socket_wrapper.c new file mode 100644 index 0000000000..5decde2cea --- /dev/null +++ b/source4/lib/socket_wrapper.c @@ -0,0 +1,401 @@ +/* + Socket wrapper library. Passes all socket communication over + unix domain sockets if the environment variable SOCKET_WRAPPER_DIR + is set. + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SAMBA_MAJOR_VERSION +#include "includes.h" +#include "system/network.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dlinklist.h" +#endif + +/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support + * for now */ +#define REWRITE_CALLS + +#ifdef REWRITE_CALLS +#define real_accept accept +#define real_connect connect +#define real_bind bind +#define real_getpeername getpeername +#define real_getsockname getsockname +#define real_getsockopt getsockopt +#define real_setsockopt setsockopt +#define real_recvfrom recvfrom +#define real_sendto sendto +#define real_socket socket +#define real_close close +#endif + +static struct sockaddr *memdup(const void *data, socklen_t len) +{ + struct sockaddr *ret = (struct sockaddr *)malloc(len); + memcpy(ret, data, len); + return ret; +} + +struct socket_info +{ + int fd; + + int domain; + int type; + int protocol; + + char *path; + + struct sockaddr *myname; + socklen_t myname_len; + + struct sockaddr *peername; + socklen_t peername_len; + + struct socket_info *prev, *next; +} *sockets = NULL; + +static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) +{ + unsigned int prt; + const char *p; + + if ((*len) < sizeof(struct sockaddr_in)) { + return 0; + } + + in->sin_family = AF_INET; + in->sin_port = 1025; /* Default to 1025 */ + p = strchr(un->sun_path, '/'); + if (p) p++; else p = un->sun_path; + + if(sscanf(p, "sock_ip_%u", &prt) == 1) + { + in->sin_port = htons(prt); + } + in->sin_addr.s_addr = INADDR_LOOPBACK; + *len = sizeof(struct sockaddr_in); + return 0; +} + +static int convert_in_un(const struct sockaddr_in *in, struct sockaddr_un *un) +{ + uint16_t prt = ntohs(in->sin_port); + /* FIXME: ENETUNREACH if in->sin_addr is not loopback */ + un->sun_family = AF_LOCAL; + snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%u", getenv("SOCKET_WRAPPER_DIR"), prt); + return 0; +} + +static struct socket_info *find_socket_info(int fd) +{ + struct socket_info *i; + for (i = sockets; i; i = i->next) { + if (i->fd == fd) + return i; + } + + return NULL; +} + +static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_len, + struct sockaddr_un *out_addr) +{ + if (!out_addr) + return 0; + + switch (in_addr->sa_family) { + case AF_INET: + return convert_in_un((const struct sockaddr_in *)in_addr, out_addr); + case AF_LOCAL: + memcpy(out_addr, in_addr, sizeof(*out_addr)); + return 0; + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +static int sockaddr_convert_from_un(const struct sockaddr_un *in_addr, + int family, + struct sockaddr *out_addr, + socklen_t *out_len) +{ + if (!out_addr) + return 0; + + switch (family) { + case AF_INET: + return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len); + case AF_LOCAL: + memcpy(out_addr, in_addr, sizeof(*in_addr)); + *out_len = sizeof(*in_addr); + return 0; + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +int swrap_socket(int domain, int type, int protocol) +{ + struct socket_info *si; + int fd; + + if (!getenv("SOCKET_WRAPPER_DIR")) { + return real_socket(domain, type, protocol); + } + + fd = real_socket(PF_LOCAL, type, 0); + + if (fd < 0) + return fd; + + si = malloc(sizeof(struct socket_info)); + memset(si, 0, sizeof(*si)); + + si->domain = domain; + si->type = type; + si->protocol = protocol; + si->fd = fd; + + DLIST_ADD(sockets, si); + + return si->fd; +} + +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct socket_info *parent_si, *child_si; + int fd; + socklen_t un_addrlen = sizeof(struct sockaddr_un); + struct sockaddr_un un_addr; + int ret; + + parent_si = find_socket_info(s); + if (!parent_si) { + return real_accept(s, addr, addrlen); + } + + ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret < 0) return ret; + + fd = ret; + + ret = sockaddr_convert_from_un(&un_addr, parent_si->domain, addr, addrlen); + + if (ret < 0) return ret; + + child_si = malloc(sizeof(struct socket_info)); + memset(child_si, 0, sizeof(*child_si)); + + child_si->fd = fd; + + if (addr && addrlen) { + child_si->myname_len = *addrlen; + child_si->myname = memdup(addr, *addrlen); + } + + return fd; +} + +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_connect(s, serv_addr, addrlen); + } + + ret = sockaddr_convert_to_un((const struct sockaddr *)serv_addr, addrlen, &un_addr); + if (ret < 0) return ret; + + ret = real_connect(s, + (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + if (ret >= 0) { + si->peername_len = addrlen; + si->peername = memdup(serv_addr, addrlen); + } + + return ret; +} + +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_bind(s, myaddr, addrlen); + } + + ret = sockaddr_convert_to_un((const struct sockaddr *)myaddr, addrlen, &un_addr); + if (ret < 0) return ret; + + unlink(un_addr.sun_path); + + ret = real_bind(s, + (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + if (ret >= 0) { + si->myname_len = addrlen; + si->myname = memdup(myaddr, addrlen); + } + + return ret; +} + +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getpeername(s, name, addrlen); + } + + if (!si->peername) + { + errno = ENOTCONN; + return -1; + } + + memcpy(name, si->peername, si->peername_len); + *addrlen = si->peername_len; + + return 0; +} + +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getpeername(s, name, addrlen); + } + + memcpy(name, si->myname, si->myname_len); + *addrlen = si->myname_len; + + return 0; +} + +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getsockopt(s, level, optname, optval, optlen); + } + + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return -1; + } + + return real_getsockopt(s, level, optname, optval, optlen); +} + +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_setsockopt(s, level, optname, optval, optlen); + } + + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return -1; + } + + return real_setsockopt(s, level, optname, optval, optlen); +} + +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) +{ + socklen_t un_addrlen; + struct sockaddr_un un_addr; + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_recvfrom(s, buf, len, flags, from, fromlen); + } + + ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret < 0) + return ret; + + ret = sockaddr_convert_from_un(&un_addr, si->domain, from, fromlen); + + return ret; +} + +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +{ + struct sockaddr_un un_addr; + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_sendto(s, buf, len, flags, to, tolen); + } + + ret = sockaddr_convert_to_un(to, tolen, &un_addr); + if (ret < 0) + return ret; + + ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); + + return ret; +} + +int swrap_close(int fd) +{ + struct socket_info *si = find_socket_info(fd); + + if (si) { + DLIST_REMOVE(sockets, si); + + free(si->path); + free(si->myname); + free(si->peername); + free(si); + } + + return real_close(fd); +} diff --git a/source4/lib/socket_wrapper.h b/source4/lib/socket_wrapper.h new file mode 100644 index 0000000000..6da5a2980c --- /dev/null +++ b/source4/lib/socket_wrapper.h @@ -0,0 +1,48 @@ +/* + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SOCKET_WRAPPER_H__ +#define __SOCKET_WRAPPER_H__ + +int swrap_socket(int domain, int type, int protocol); +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen); +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen); +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); +int swrap_close(int); + +#ifdef SOCKET_WRAPPER_REPLACE +#define accept swrap_accept +#define connect swrap_connect +#define bind swrap_bind +#define getpeername swrap_getpeername +#define getsockname swrap_getsockname +#define getsockopt swrap_getsockopt +#define setsockopt swrap_setsockopt +#define recvfrom swrap_recvfrom +#define sendto swrap_sendto +#define socket swrap_socket +#define close swrap_close +#endif + +#endif /* __SOCKET_WRAPPER_H__ */ -- cgit From 8c270fcedb1629526f1f40fb42e0ee329c0f2178 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 28 Mar 2005 03:31:44 +0000 Subject: r6093: Patch to fix sys_select so it can't drop signals if another fd is ready to read. Patch from Mark Weaver . Jeremy. (This used to be commit 857e98e8ea842bb94c93b81d7b69e3d304f100f5) --- source4/lib/select.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/select.c b/source4/lib/select.c index bed02304cc..066465c1be 100644 --- a/source4/lib/select.c +++ b/source4/lib/select.c @@ -100,20 +100,23 @@ int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, s FD_ZERO(writefds); if (errorfds) FD_ZERO(errorfds); - } - - if (FD_ISSET(select_pipe[0], readfds2)) { + } else if (FD_ISSET(select_pipe[0], readfds2)) { char c; saved_errno = errno; if (read(select_pipe[0], &c, 1) == 1) { pipe_read++; - } - errno = saved_errno; - FD_CLR(select_pipe[0], readfds2); - ret--; - if (ret == 0) { + /* Mark Weaver pointed out a critical + fix to ensure we don't lose signals. We must always + return -1 when the select pipe is set, otherwise if another + fd is also ready (so ret == 2) then we used to eat the + byte in the pipe and lose the signal. JRA. + */ ret = -1; errno = EINTR; + } else { + FD_CLR(select_pipe[0], readfds2); + ret--; + errno = saved_errno; } } @@ -146,7 +149,13 @@ int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorf if (tval) tval2 = *tval; - ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval); + /* We must use select and not sys_select here. If we use + sys_select we'd lose the fact a signal occurred when sys_select + read a byte from the pipe. Fix from Mark Weaver + + */ + + ret = select(maxfd, readfds2, writefds2, errorfds2, ptval); } while (ret == -1 && errno == EINTR); if (readfds) -- cgit From da3816690419401d85ab8bf7cee89ac912b152b0 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Wed, 30 Mar 2005 00:15:16 +0000 Subject: r6118: Make it so that we can do --with-zlib=no in configure and also a couple of small typos. (This used to be commit 9b4069e84573f85ce4341ceacd35737a18726a0b) --- source4/lib/ldb/tools/ldbadd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 41273a08da..818c33a11d 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -116,7 +116,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); + fprintf(stderr, "You must specify an ldb URL\n\n"); usage(); } -- cgit From 0403e2032b258d25f6ff744029c3a0327cebda5a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Mar 2005 10:48:52 +0000 Subject: r6129: - add our own MSZIP decompression implementation (taken from cabextract.c from KDE) this code maybe need to be rewritten and the compression side needs to be done, but for now it seems to works - remove the dependency to zlib metze (This used to be commit 5e8558c5b4365a494aa054c3e08d4084b319e6e5) --- source4/lib/basic.mk | 8 + source4/lib/compression/mszip.c | 677 ++++++++++++++++++++++++++++++++++++++++ source4/lib/compression/mszip.h | 34 ++ 3 files changed, 719 insertions(+) create mode 100644 source4/lib/compression/mszip.c create mode 100644 source4/lib/compression/mszip.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 560234a00c..ec61a28d15 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -32,6 +32,14 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBCRYPTO ############################## +################################################ +# Start SUBSYSTEM LIBCOMPRESSION +[SUBSYSTEM::LIBCOMPRESSION] +INIT_OBJ_FILES = \ + lib/compression/mszip.o +# End SUBSYSTEM LIBCOMPRESION +################################################ + ############################## # Start SUBSYSTEM SOCKET_WRAPPER [SUBSYSTEM::SOCKET_WRAPPER] diff --git a/source4/lib/compression/mszip.c b/source4/lib/compression/mszip.c new file mode 100644 index 0000000000..97b53f56ad --- /dev/null +++ b/source4/lib/compression/mszip.c @@ -0,0 +1,677 @@ +/* mszip decompression - based on cabextract.c code from + * Stuart Caie + * + * adapted for Samba by Andrew Tridgell and Stefan Metzmacher 2005 + * + * (C) 2000-2001 Stuart Caie + * reaktivate-specifics by Malte Starostik + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "lib/compression/mszip.h" + +/*--------------------------------------------------------------------------*/ +/* our archiver information / state */ + +/* MSZIP stuff */ +#define ZIPWSIZE 0x8000 /* window size */ +#define ZIPLBITS 9 /* bits in base literal/length lookup table */ +#define ZIPDBITS 6 /* bits in base distance lookup table */ +#define ZIPBMAX 16 /* maximum bit length of any code */ +#define ZIPN_MAX 288 /* maximum number of codes in any set */ + +struct Ziphuft { + uint8_t e; /* number of extra bits or operation */ + uint8_t b; /* number of bits in this code or subcode */ + union { + uint16_t n; /* literal, length base, or distance base */ + struct Ziphuft *t; /* pointer to next level of table */ + } v; +}; + +struct ZIPstate { + uint32_t window_posn; /* current offset within the window */ + uint32_t bb; /* bit buffer */ + uint32_t bk; /* bits in bit buffer */ + uint32_t ll[288+32]; /* literal/length and distance code lengths */ + uint32_t c[ZIPBMAX+1]; /* bit length count table */ + int32_t lx[ZIPBMAX+1]; /* memory for l[-1..ZIPBMAX-1] */ + struct Ziphuft *u[ZIPBMAX]; /* table stack */ + uint32_t v[ZIPN_MAX]; /* values in order of bit length */ + uint32_t x[ZIPBMAX+1]; /* bit offsets, then code stack */ + uint8_t *inpos; +}; + +/* generic stuff */ +#define CAB(x) (decomp_state->x) +#define ZIP(x) (decomp_state->methods.zip.x) + +/* CAB data blocks are <= 32768 bytes in uncompressed form. Uncompressed + * blocks have zero growth. MSZIP guarantees that it won't grow above + * uncompressed size by more than 12 bytes. LZX guarantees it won't grow + * more than 6144 bytes. + */ +#define CAB_BLOCKMAX (32768) +#define CAB_INPUTMAX (CAB_BLOCKMAX+6144) + +struct decomp_state { + struct folder *current; /* current folder we're extracting from */ + uint32_t offset; /* uncompressed offset within folder */ + uint8_t *outpos; /* (high level) start of data to use up */ + uint16_t outlen; /* (high level) amount of data to use up */ + uint16_t split; /* at which split in current folder? */ + int (*decompress)(int, int); /* the chosen compression func */ + uint8_t inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */ + uint8_t outbuf[CAB_BLOCKMAX]; + union { + struct ZIPstate zip; + } methods; +}; + + +/* MSZIP decruncher */ + +/* Dirk Stoecker wrote the ZIP decoder, based on the InfoZip deflate code */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +static const uint8_t Zipborder[] = /* Order of the bit length code lengths */ +{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static const uint16_t Zipcplens[] = /* Copy lengths for literal codes 257..285 */ +{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, + 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; +static const uint16_t Zipcplext[] = /* Extra bits for literal codes 257..285 */ +{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +static const uint16_t Zipcpdist[] = /* Copy offsets for distance codes 0..29 */ +{ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, +513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; +static const uint16_t Zipcpdext[] = /* Extra bits for distance codes */ +{ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, +10, 11, 11, 12, 12, 13, 13}; + +/* And'ing with Zipmask[n] masks the lower n bits */ +static const uint16_t Zipmask[17] = { + 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#define ZIPNEEDBITS(n) {while(k<(n)){int32_t c=*(ZIP(inpos)++);\ + b|=((uint32_t)c)<>=(n);k-=(n);} + +static void Ziphuft_free(struct Ziphuft *t) +{ + register struct Ziphuft *p, *q; + + /* Go through linked list, freeing from the allocated (t[-1]) address. */ + p = t; + while (p != (struct Ziphuft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } +} + +static int32_t Ziphuft_build(struct decomp_state *decomp_state, + uint32_t *b, uint32_t n, uint32_t s, const uint16_t *d, const uint16_t *e, + struct Ziphuft **t, int32_t *m) +{ + uint32_t a; /* counter for codes of length k */ + uint32_t el; /* length of EOB code (value 256) */ + uint32_t f; /* i repeats in table every f entries */ + int32_t g; /* maximum code length */ + int32_t h; /* table level */ + register uint32_t i; /* counter, current code */ + register uint32_t j; /* counter */ + register int32_t k; /* number of bits in current code */ + int32_t *l; /* stack of bits per table */ + register uint32_t *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */ + register struct Ziphuft *q; /* points to current table */ + struct Ziphuft r; /* table entry for structure assignment */ + register int32_t w; /* bits before this table == (l * h) */ + uint32_t *xp; /* pointer into x */ + int32_t y; /* number of dummy codes added */ + uint32_t z; /* number of entries in current table */ + + l = ZIP(lx)+1; + + /* Generate counts for each bit length */ + el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */ + + for(i = 0; i < ZIPBMAX+1; ++i) + ZIP(c)[i] = 0; + p = b; i = n; + do + { + ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */ + } while (--i); + if (ZIP(c)[0] == n) /* null input--all zero length codes */ + { + *t = (struct Ziphuft *)NULL; + *m = 0; + return 0; + } + + /* Find minimum and maximum length, bound *m by those */ + for (j = 1; j <= ZIPBMAX; j++) + if (ZIP(c)[j]) + break; + k = j; /* minimum code length */ + if ((uint32_t)*m < j) + *m = j; + for (i = ZIPBMAX; i; i--) + if (ZIP(c)[i]) + break; + g = i; /* maximum code length */ + if ((uint32_t)*m > i) + *m = i; + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= ZIP(c)[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= ZIP(c)[i]) < 0) + return 2; + ZIP(c)[i] += y; + + /* Generate starting offsets int32_to the value table for each length */ + ZIP(x)[1] = j = 0; + p = ZIP(c) + 1; xp = ZIP(x) + 2; + while (--i) + { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do{ + if ((j = *p++) != 0) + ZIP(v)[ZIP(x)[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + ZIP(x)[0] = i = 0; /* first Huffman code is zero */ + p = ZIP(v); /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = l[-1] = 0; /* no bits decoded yet */ + ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */ + q = (struct Ziphuft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = ZIP(c)[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l[h]) + { + w += l[h++]; /* add bits already decoded */ + + /* compute minimum size table less than or equal to *m bits */ + z = (z = g - w) > (uint32_t)*m ? *m : z; /* upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = ZIP(c) + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + if ((uint32_t)w + j > el && (uint32_t)w < el) + j = el - w; /* make EOB code end at table */ + z = 1 << j; /* table entries for j-bit table */ + l[h] = j; /* set table size in stack */ + + /* allocate and link in new table */ + if (!(q = (struct Ziphuft *) malloc((z + 1)*sizeof(struct Ziphuft)))) + { + if(h) + Ziphuft_free(ZIP(u)[0]); + return 3; /* not enough memory */ + } + *t = q + 1; /* link to list for Ziphuft_free() */ + *(t = &(q->v.t)) = (struct Ziphuft *)NULL; + ZIP(u)[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + ZIP(x)[h] = i; /* save pattern for backing up */ + r.b = (uint8_t)l[h-1]; /* bits to dump before this table */ + r.e = (uint8_t)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = (i & ((1 << w) - 1)) >> (w - l[h-1]); + ZIP(u)[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uint8_t)(k - w); + if (p >= ZIP(v) + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uint8_t)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (uint8_t)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != ZIP(x)[h]) + w -= l[--h]; /* don't need to update q */ + } + } + + /* return actual size of base table */ + *m = l[0]; + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + +static int32_t Zipinflate_codes(struct decomp_state *decomp_state, + struct Ziphuft *tl, struct Ziphuft *td, + int32_t bl, int32_t bd) +{ + register uint32_t e; /* table entry flag/number of extra bits */ + uint32_t n, d; /* length and index for copy */ + uint32_t w; /* current window position */ + struct Ziphuft *t; /* pointer to table entry */ + uint32_t ml, md; /* masks for bl and bd bits */ + register uint32_t b; /* bit buffer */ + register uint32_t k; /* number of bits in bit buffer */ + + DEBUG(10,("Zipinflate_codes\n")); + + /* make local copies of globals */ + b = ZIP(bb); /* initialize bit buffer */ + k = ZIP(bk); + w = ZIP(window_posn); /* initialize window position */ + + /* inflate the coded data */ + ml = Zipmask[bl]; /* precompute masks for speed */ + md = Zipmask[bd]; + + for(;;) + { + ZIPNEEDBITS((uint32_t)bl) + if((e = (t = tl + ((uint32_t)b & ml))->e) > 16) + do + { + if (e == 99) + return 1; + ZIPDUMPBITS(t->b) + e -= 16; + ZIPNEEDBITS(e) + } while ((e = (t = t->v.t + ((uint32_t)b & Zipmask[e]))->e) > 16); + ZIPDUMPBITS(t->b) + if (w >= 32768) break; + if (e == 16) /* then it's a literal */ + CAB(outbuf)[w++] = (uint8_t)t->v.n; + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if(e == 15) + break; + + /* get length of block to copy */ + ZIPNEEDBITS(e) + n = t->v.n + ((uint32_t)b & Zipmask[e]); + ZIPDUMPBITS(e); + + /* decode distance of block to copy */ + ZIPNEEDBITS((uint32_t)bd) + if ((e = (t = td + ((uint32_t)b & md))->e) > 16) + do { + if (e == 99) + return 1; + ZIPDUMPBITS(t->b) + e -= 16; + ZIPNEEDBITS(e) + } while ((e = (t = t->v.t + ((uint32_t)b & Zipmask[e]))->e) > 16); + ZIPDUMPBITS(t->b) + ZIPNEEDBITS(e) + d = w - t->v.n - ((uint32_t)b & Zipmask[e]); + ZIPDUMPBITS(e) + do + { + n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e); + do + { + CAB(outbuf)[w++] = CAB(outbuf)[d++]; + } while (--e); + } while (n); + } + } + + /* restore the globals from the locals */ + ZIP(window_posn) = w; /* restore global window pointer */ + ZIP(bb) = b; /* restore global bit buffer */ + ZIP(bk) = k; + + /* done */ + return 0; +} + +/* "decompress" an inflated type 0 (stored) block. */ +static int32_t Zipinflate_stored(struct decomp_state *decomp_state) +{ + uint32_t n; /* number of bytes in block */ + uint32_t w; /* current window position */ + register uint32_t b; /* bit buffer */ + register uint32_t k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b = ZIP(bb); /* initialize bit buffer */ + k = ZIP(bk); + w = ZIP(window_posn); /* initialize window position */ + + /* go to byte boundary */ + n = k & 7; + ZIPDUMPBITS(n); + + /* get the length and its complement */ + ZIPNEEDBITS(16) + n = ((uint32_t)b & 0xffff); + ZIPDUMPBITS(16) + ZIPNEEDBITS(16) + if (n != (uint32_t)((~b) & 0xffff)) + return 1; /* error in compressed data */ + ZIPDUMPBITS(16) + + /* read and output the compressed data */ + while(n--) + { + ZIPNEEDBITS(8) + CAB(outbuf)[w++] = (uint8_t)b; + ZIPDUMPBITS(8) + } + + /* restore the globals from the locals */ + ZIP(window_posn) = w; /* restore global window pointer */ + ZIP(bb) = b; /* restore global bit buffer */ + ZIP(bk) = k; + return 0; +} + +static int32_t Zipinflate_fixed(struct decomp_state *decomp_state) +{ + struct Ziphuft *fixed_tl; + struct Ziphuft *fixed_td; + int32_t fixed_bl, fixed_bd; + int32_t i; /* temporary variable */ + uint32_t *l; + + l = ZIP(ll); + + /* literal table */ + for(i = 0; i < 144; i++) + l[i] = 8; + for(; i < 256; i++) + l[i] = 9; + for(; i < 280; i++) + l[i] = 7; + for(; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + fixed_bl = 7; + if((i = Ziphuft_build(decomp_state, l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl))) + return i; + + /* distance table */ + for(i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + fixed_bd = 5; + if((i = Ziphuft_build(decomp_state, l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd)) > 1) + { + Ziphuft_free(fixed_tl); + return i; + } + + /* decompress until an end-of-block code */ + i = Zipinflate_codes(decomp_state, fixed_tl, fixed_td, fixed_bl, fixed_bd); + + Ziphuft_free(fixed_td); + Ziphuft_free(fixed_tl); + return i; +} + +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +static int32_t Zipinflate_dynamic(struct decomp_state *decomp_state) +{ + int32_t i; /* temporary variables */ + uint32_t j; + uint32_t *ll; + uint32_t l; /* last length */ + uint32_t m; /* mask for bit lengths table */ + uint32_t n; /* number of lengths to get */ + struct Ziphuft *tl; /* literal/length code table */ + struct Ziphuft *td; /* distance code table */ + int32_t bl; /* lookup bits for tl */ + int32_t bd; /* lookup bits for td */ + uint32_t nb; /* number of bit length codes */ + uint32_t nl; /* number of literal/length codes */ + uint32_t nd; /* number of distance codes */ + register uint32_t b; /* bit buffer */ + register uint32_t k; /* number of bits in bit buffer */ + + /* make local bit buffer */ + b = ZIP(bb); + k = ZIP(bk); + ll = ZIP(ll); + + /* read in table lengths */ + ZIPNEEDBITS(5) + nl = 257 + ((uint32_t)b & 0x1f); /* number of literal/length codes */ + ZIPDUMPBITS(5) + ZIPNEEDBITS(5) + nd = 1 + ((uint32_t)b & 0x1f); /* number of distance codes */ + ZIPDUMPBITS(5) + ZIPNEEDBITS(4) + nb = 4 + ((uint32_t)b & 0xf); /* number of bit length codes */ + ZIPDUMPBITS(4) + if(nl > 288 || nd > 32) + return 1; /* bad lengths */ + + /* read in bit-length-code lengths */ + for(j = 0; j < nb; j++) + { + ZIPNEEDBITS(3) + ll[Zipborder[j]] = (uint32_t)b & 7; + ZIPDUMPBITS(3) + } + for(; j < 19; j++) + ll[Zipborder[j]] = 0; + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if((i = Ziphuft_build(decomp_state, ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if(i == 1) + Ziphuft_free(tl); + return i; /* incomplete code set */ + } + + /* read in literal and distance code lengths */ + n = nl + nd; + m = Zipmask[bl]; + i = l = 0; + while((uint32_t)i < n) + { + ZIPNEEDBITS((uint32_t)bl) + j = (td = tl + ((uint32_t)b & m))->b; + ZIPDUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + ZIPNEEDBITS(2) + j = 3 + ((uint32_t)b & 3); + ZIPDUMPBITS(2) + if((uint32_t)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + ZIPNEEDBITS(3) + j = 3 + ((uint32_t)b & 7); + ZIPDUMPBITS(3) + if ((uint32_t)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + ZIPNEEDBITS(7) + j = 11 + ((uint32_t)b & 0x7f); + ZIPDUMPBITS(7) + if ((uint32_t)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + + /* free decoding table for trees */ + Ziphuft_free(tl); + + /* restore the global bit buffer */ + ZIP(bb) = b; + ZIP(bk) = k; + + /* build the decoding tables for literal/length and distance codes */ + bl = ZIPLBITS; + if((i = Ziphuft_build(decomp_state, ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl)) != 0) + { + if(i == 1) + Ziphuft_free(tl); + return i; /* incomplete code set */ + } + bd = ZIPDBITS; + Ziphuft_build(decomp_state, ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd); + + /* decompress until an end-of-block code */ + if(Zipinflate_codes(decomp_state, tl, td, bl, bd)) + return 1; + + /* free the decoding tables, return */ + Ziphuft_free(tl); + Ziphuft_free(td); + return 0; +} + +/* e == last block flag */ +static int32_t Zipinflate_block(struct decomp_state *decomp_state, int32_t *e) +{ /* decompress an inflated block */ + uint32_t t; /* block type */ + register uint32_t b; /* bit buffer */ + register uint32_t k; /* number of bits in bit buffer */ + + DEBUG(10,("Zipinflate_block\n")); + + /* make local bit buffer */ + b = ZIP(bb); + k = ZIP(bk); + + /* read in last block bit */ + ZIPNEEDBITS(1) + *e = (int32_t)b & 1; + ZIPDUMPBITS(1) + + /* read in block type */ + ZIPNEEDBITS(2) + t = (uint32_t)b & 3; + ZIPDUMPBITS(2) + + /* restore the global bit buffer */ + ZIP(bb) = b; + ZIP(bk) = k; + + DEBUG(10,("inflate type %d\n", t)); + + /* inflate that block type */ + if(t == 2) + return Zipinflate_dynamic(decomp_state); + if(t == 0) + return Zipinflate_stored(decomp_state); + if(t == 1) + return Zipinflate_fixed(decomp_state); + /* bad block type */ + return 2; +} + +struct decomp_state *ZIPdecomp_state(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct decomp_state); +} + +int ZIPdecompress(struct decomp_state *decomp_state, DATA_BLOB *inbuf, DATA_BLOB *outbuf) +{ + int32_t e = 0;/* last block flag */ + + ZIP(inpos) = CAB(inbuf); + ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0; + + if (inbuf->length > sizeof(decomp_state->inbuf)) return DECR_INPUT; + + if (outbuf->length > sizeof(decomp_state->outbuf)) return DECR_OUTPUT; + + if (outbuf->length > ZIPWSIZE) return DECR_DATAFORMAT; + + memcpy(decomp_state->inbuf, inbuf->data, inbuf->length); + + /* CK = Chris Kirmse, official Microsoft purloiner */ + if (ZIP(inpos)[0] != 'C' || ZIP(inpos)[1] != 'K') return DECR_ILLEGALDATA; + ZIP(inpos) += 2; + + while (!e) { + if (Zipinflate_block(decomp_state, &e)) { + return DECR_ILLEGALDATA; + } + } + + memcpy(outbuf->data, decomp_state->outbuf, outbuf->length); + + return DECR_OK; +} diff --git a/source4/lib/compression/mszip.h b/source4/lib/compression/mszip.h new file mode 100644 index 0000000000..cc9769f73a --- /dev/null +++ b/source4/lib/compression/mszip.h @@ -0,0 +1,34 @@ +/* mszip decompression - based on cabextract.c code from + * Stuart Caie + * + * adapted for Samba by Andrew Tridgell and Stefan Metzmacher 2005 + * + * (C) 2000-2001 Stuart Caie + * reaktivate-specifics by Malte Starostik + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +struct decomp_state; +struct decomp_state *ZIPdecomp_state(TALLOC_CTX *mem_ctx); + +#define DECR_OK (0) +#define DECR_DATAFORMAT (1) +#define DECR_ILLEGALDATA (2) +#define DECR_NOMEMORY (3) +#define DECR_CHECKSUM (4) +#define DECR_INPUT (5) +#define DECR_OUTPUT (6) +int ZIPdecompress(struct decomp_state *decomp_state, DATA_BLOB *inbuf, DATA_BLOB *outbuf); -- cgit From 44d7f4f23829d98b95d9153970849a9681e4ef26 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 30 Mar 2005 22:09:16 +0000 Subject: r6139: Move socket_wrapper to a seperate directory (This used to be commit a2ef9225f15e369af7b884262b997ab321fd24d6) --- source4/lib/basic.mk | 8 - source4/lib/socket_wrapper.c | 401 ---------------------------- source4/lib/socket_wrapper.h | 48 ---- source4/lib/socket_wrapper/config.mk | 7 + source4/lib/socket_wrapper/socket_wrapper.c | 401 ++++++++++++++++++++++++++++ source4/lib/socket_wrapper/socket_wrapper.h | 48 ++++ 6 files changed, 456 insertions(+), 457 deletions(-) delete mode 100644 source4/lib/socket_wrapper.c delete mode 100644 source4/lib/socket_wrapper.h create mode 100644 source4/lib/socket_wrapper/config.mk create mode 100644 source4/lib/socket_wrapper/socket_wrapper.c create mode 100644 source4/lib/socket_wrapper/socket_wrapper.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index ec61a28d15..f0b2b05b6a 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -40,14 +40,6 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBCOMPRESION ################################################ -############################## -# Start SUBSYSTEM SOCKET_WRAPPER -[SUBSYSTEM::SOCKET_WRAPPER] -NOPROTO = YES -INIT_OBJ_FILES = lib/socket_wrapper.o -# End SUBSYSTEM SOCKET_WRAPPER -############################## - ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] diff --git a/source4/lib/socket_wrapper.c b/source4/lib/socket_wrapper.c deleted file mode 100644 index 5decde2cea..0000000000 --- a/source4/lib/socket_wrapper.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - Socket wrapper library. Passes all socket communication over - unix domain sockets if the environment variable SOCKET_WRAPPER_DIR - is set. - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifdef SAMBA_MAJOR_VERSION -#include "includes.h" -#include "system/network.h" -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dlinklist.h" -#endif - -/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support - * for now */ -#define REWRITE_CALLS - -#ifdef REWRITE_CALLS -#define real_accept accept -#define real_connect connect -#define real_bind bind -#define real_getpeername getpeername -#define real_getsockname getsockname -#define real_getsockopt getsockopt -#define real_setsockopt setsockopt -#define real_recvfrom recvfrom -#define real_sendto sendto -#define real_socket socket -#define real_close close -#endif - -static struct sockaddr *memdup(const void *data, socklen_t len) -{ - struct sockaddr *ret = (struct sockaddr *)malloc(len); - memcpy(ret, data, len); - return ret; -} - -struct socket_info -{ - int fd; - - int domain; - int type; - int protocol; - - char *path; - - struct sockaddr *myname; - socklen_t myname_len; - - struct sockaddr *peername; - socklen_t peername_len; - - struct socket_info *prev, *next; -} *sockets = NULL; - -static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) -{ - unsigned int prt; - const char *p; - - if ((*len) < sizeof(struct sockaddr_in)) { - return 0; - } - - in->sin_family = AF_INET; - in->sin_port = 1025; /* Default to 1025 */ - p = strchr(un->sun_path, '/'); - if (p) p++; else p = un->sun_path; - - if(sscanf(p, "sock_ip_%u", &prt) == 1) - { - in->sin_port = htons(prt); - } - in->sin_addr.s_addr = INADDR_LOOPBACK; - *len = sizeof(struct sockaddr_in); - return 0; -} - -static int convert_in_un(const struct sockaddr_in *in, struct sockaddr_un *un) -{ - uint16_t prt = ntohs(in->sin_port); - /* FIXME: ENETUNREACH if in->sin_addr is not loopback */ - un->sun_family = AF_LOCAL; - snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%u", getenv("SOCKET_WRAPPER_DIR"), prt); - return 0; -} - -static struct socket_info *find_socket_info(int fd) -{ - struct socket_info *i; - for (i = sockets; i; i = i->next) { - if (i->fd == fd) - return i; - } - - return NULL; -} - -static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_len, - struct sockaddr_un *out_addr) -{ - if (!out_addr) - return 0; - - switch (in_addr->sa_family) { - case AF_INET: - return convert_in_un((const struct sockaddr_in *)in_addr, out_addr); - case AF_LOCAL: - memcpy(out_addr, in_addr, sizeof(*out_addr)); - return 0; - default: - break; - } - - errno = EAFNOSUPPORT; - return -1; -} - -static int sockaddr_convert_from_un(const struct sockaddr_un *in_addr, - int family, - struct sockaddr *out_addr, - socklen_t *out_len) -{ - if (!out_addr) - return 0; - - switch (family) { - case AF_INET: - return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len); - case AF_LOCAL: - memcpy(out_addr, in_addr, sizeof(*in_addr)); - *out_len = sizeof(*in_addr); - return 0; - default: - break; - } - - errno = EAFNOSUPPORT; - return -1; -} - -int swrap_socket(int domain, int type, int protocol) -{ - struct socket_info *si; - int fd; - - if (!getenv("SOCKET_WRAPPER_DIR")) { - return real_socket(domain, type, protocol); - } - - fd = real_socket(PF_LOCAL, type, 0); - - if (fd < 0) - return fd; - - si = malloc(sizeof(struct socket_info)); - memset(si, 0, sizeof(*si)); - - si->domain = domain; - si->type = type; - si->protocol = protocol; - si->fd = fd; - - DLIST_ADD(sockets, si); - - return si->fd; -} - -int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - struct socket_info *parent_si, *child_si; - int fd; - socklen_t un_addrlen = sizeof(struct sockaddr_un); - struct sockaddr_un un_addr; - int ret; - - parent_si = find_socket_info(s); - if (!parent_si) { - return real_accept(s, addr, addrlen); - } - - ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret < 0) return ret; - - fd = ret; - - ret = sockaddr_convert_from_un(&un_addr, parent_si->domain, addr, addrlen); - - if (ret < 0) return ret; - - child_si = malloc(sizeof(struct socket_info)); - memset(child_si, 0, sizeof(*child_si)); - - child_si->fd = fd; - - if (addr && addrlen) { - child_si->myname_len = *addrlen; - child_si->myname = memdup(addr, *addrlen); - } - - return fd; -} - -int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) -{ - int ret; - struct sockaddr_un un_addr; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_connect(s, serv_addr, addrlen); - } - - ret = sockaddr_convert_to_un((const struct sockaddr *)serv_addr, addrlen, &un_addr); - if (ret < 0) return ret; - - ret = real_connect(s, - (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); - - if (ret >= 0) { - si->peername_len = addrlen; - si->peername = memdup(serv_addr, addrlen); - } - - return ret; -} - -int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) -{ - int ret; - struct sockaddr_un un_addr; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_bind(s, myaddr, addrlen); - } - - ret = sockaddr_convert_to_un((const struct sockaddr *)myaddr, addrlen, &un_addr); - if (ret < 0) return ret; - - unlink(un_addr.sun_path); - - ret = real_bind(s, - (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); - - if (ret >= 0) { - si->myname_len = addrlen; - si->myname = memdup(myaddr, addrlen); - } - - return ret; -} - -int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getpeername(s, name, addrlen); - } - - if (!si->peername) - { - errno = ENOTCONN; - return -1; - } - - memcpy(name, si->peername, si->peername_len); - *addrlen = si->peername_len; - - return 0; -} - -int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getpeername(s, name, addrlen); - } - - memcpy(name, si->myname, si->myname_len); - *addrlen = si->myname_len; - - return 0; -} - -int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_getsockopt(s, level, optname, optval, optlen); - } - - if (level != SOL_SOCKET) { - errno = ENOPROTOOPT; - return -1; - } - - return real_getsockopt(s, level, optname, optval, optlen); -} - -int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_setsockopt(s, level, optname, optval, optlen); - } - - if (level != SOL_SOCKET) { - errno = ENOPROTOOPT; - return -1; - } - - return real_setsockopt(s, level, optname, optval, optlen); -} - -ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) -{ - socklen_t un_addrlen; - struct sockaddr_un un_addr; - int ret; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_recvfrom(s, buf, len, flags, from, fromlen); - } - - ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret < 0) - return ret; - - ret = sockaddr_convert_from_un(&un_addr, si->domain, from, fromlen); - - return ret; -} - -ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) -{ - struct sockaddr_un un_addr; - int ret; - struct socket_info *si = find_socket_info(s); - - if (!si) { - return real_sendto(s, buf, len, flags, to, tolen); - } - - ret = sockaddr_convert_to_un(to, tolen, &un_addr); - if (ret < 0) - return ret; - - ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); - - return ret; -} - -int swrap_close(int fd) -{ - struct socket_info *si = find_socket_info(fd); - - if (si) { - DLIST_REMOVE(sockets, si); - - free(si->path); - free(si->myname); - free(si->peername); - free(si); - } - - return real_close(fd); -} diff --git a/source4/lib/socket_wrapper.h b/source4/lib/socket_wrapper.h deleted file mode 100644 index 6da5a2980c..0000000000 --- a/source4/lib/socket_wrapper.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef __SOCKET_WRAPPER_H__ -#define __SOCKET_WRAPPER_H__ - -int swrap_socket(int domain, int type, int protocol); -int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen); -int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen); -int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen); -int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen); -int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); -int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); -ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); -ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); -int swrap_close(int); - -#ifdef SOCKET_WRAPPER_REPLACE -#define accept swrap_accept -#define connect swrap_connect -#define bind swrap_bind -#define getpeername swrap_getpeername -#define getsockname swrap_getsockname -#define getsockopt swrap_getsockopt -#define setsockopt swrap_setsockopt -#define recvfrom swrap_recvfrom -#define sendto swrap_sendto -#define socket swrap_socket -#define close swrap_close -#endif - -#endif /* __SOCKET_WRAPPER_H__ */ diff --git a/source4/lib/socket_wrapper/config.mk b/source4/lib/socket_wrapper/config.mk new file mode 100644 index 0000000000..bc9a0951dc --- /dev/null +++ b/source4/lib/socket_wrapper/config.mk @@ -0,0 +1,7 @@ +############################## +# Start SUBSYSTEM SOCKET_WRAPPER +[SUBSYSTEM::SOCKET_WRAPPER] +NOPROTO = YES +INIT_OBJ_FILES = lib/socket_wrapper/socket_wrapper.o +# End SUBSYSTEM SOCKET_WRAPPER +############################## diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c new file mode 100644 index 0000000000..5decde2cea --- /dev/null +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -0,0 +1,401 @@ +/* + Socket wrapper library. Passes all socket communication over + unix domain sockets if the environment variable SOCKET_WRAPPER_DIR + is set. + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SAMBA_MAJOR_VERSION +#include "includes.h" +#include "system/network.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dlinklist.h" +#endif + +/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support + * for now */ +#define REWRITE_CALLS + +#ifdef REWRITE_CALLS +#define real_accept accept +#define real_connect connect +#define real_bind bind +#define real_getpeername getpeername +#define real_getsockname getsockname +#define real_getsockopt getsockopt +#define real_setsockopt setsockopt +#define real_recvfrom recvfrom +#define real_sendto sendto +#define real_socket socket +#define real_close close +#endif + +static struct sockaddr *memdup(const void *data, socklen_t len) +{ + struct sockaddr *ret = (struct sockaddr *)malloc(len); + memcpy(ret, data, len); + return ret; +} + +struct socket_info +{ + int fd; + + int domain; + int type; + int protocol; + + char *path; + + struct sockaddr *myname; + socklen_t myname_len; + + struct sockaddr *peername; + socklen_t peername_len; + + struct socket_info *prev, *next; +} *sockets = NULL; + +static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) +{ + unsigned int prt; + const char *p; + + if ((*len) < sizeof(struct sockaddr_in)) { + return 0; + } + + in->sin_family = AF_INET; + in->sin_port = 1025; /* Default to 1025 */ + p = strchr(un->sun_path, '/'); + if (p) p++; else p = un->sun_path; + + if(sscanf(p, "sock_ip_%u", &prt) == 1) + { + in->sin_port = htons(prt); + } + in->sin_addr.s_addr = INADDR_LOOPBACK; + *len = sizeof(struct sockaddr_in); + return 0; +} + +static int convert_in_un(const struct sockaddr_in *in, struct sockaddr_un *un) +{ + uint16_t prt = ntohs(in->sin_port); + /* FIXME: ENETUNREACH if in->sin_addr is not loopback */ + un->sun_family = AF_LOCAL; + snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%u", getenv("SOCKET_WRAPPER_DIR"), prt); + return 0; +} + +static struct socket_info *find_socket_info(int fd) +{ + struct socket_info *i; + for (i = sockets; i; i = i->next) { + if (i->fd == fd) + return i; + } + + return NULL; +} + +static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_len, + struct sockaddr_un *out_addr) +{ + if (!out_addr) + return 0; + + switch (in_addr->sa_family) { + case AF_INET: + return convert_in_un((const struct sockaddr_in *)in_addr, out_addr); + case AF_LOCAL: + memcpy(out_addr, in_addr, sizeof(*out_addr)); + return 0; + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +static int sockaddr_convert_from_un(const struct sockaddr_un *in_addr, + int family, + struct sockaddr *out_addr, + socklen_t *out_len) +{ + if (!out_addr) + return 0; + + switch (family) { + case AF_INET: + return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len); + case AF_LOCAL: + memcpy(out_addr, in_addr, sizeof(*in_addr)); + *out_len = sizeof(*in_addr); + return 0; + default: + break; + } + + errno = EAFNOSUPPORT; + return -1; +} + +int swrap_socket(int domain, int type, int protocol) +{ + struct socket_info *si; + int fd; + + if (!getenv("SOCKET_WRAPPER_DIR")) { + return real_socket(domain, type, protocol); + } + + fd = real_socket(PF_LOCAL, type, 0); + + if (fd < 0) + return fd; + + si = malloc(sizeof(struct socket_info)); + memset(si, 0, sizeof(*si)); + + si->domain = domain; + si->type = type; + si->protocol = protocol; + si->fd = fd; + + DLIST_ADD(sockets, si); + + return si->fd; +} + +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct socket_info *parent_si, *child_si; + int fd; + socklen_t un_addrlen = sizeof(struct sockaddr_un); + struct sockaddr_un un_addr; + int ret; + + parent_si = find_socket_info(s); + if (!parent_si) { + return real_accept(s, addr, addrlen); + } + + ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret < 0) return ret; + + fd = ret; + + ret = sockaddr_convert_from_un(&un_addr, parent_si->domain, addr, addrlen); + + if (ret < 0) return ret; + + child_si = malloc(sizeof(struct socket_info)); + memset(child_si, 0, sizeof(*child_si)); + + child_si->fd = fd; + + if (addr && addrlen) { + child_si->myname_len = *addrlen; + child_si->myname = memdup(addr, *addrlen); + } + + return fd; +} + +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_connect(s, serv_addr, addrlen); + } + + ret = sockaddr_convert_to_un((const struct sockaddr *)serv_addr, addrlen, &un_addr); + if (ret < 0) return ret; + + ret = real_connect(s, + (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + if (ret >= 0) { + si->peername_len = addrlen; + si->peername = memdup(serv_addr, addrlen); + } + + return ret; +} + +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) +{ + int ret; + struct sockaddr_un un_addr; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_bind(s, myaddr, addrlen); + } + + ret = sockaddr_convert_to_un((const struct sockaddr *)myaddr, addrlen, &un_addr); + if (ret < 0) return ret; + + unlink(un_addr.sun_path); + + ret = real_bind(s, + (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); + + if (ret >= 0) { + si->myname_len = addrlen; + si->myname = memdup(myaddr, addrlen); + } + + return ret; +} + +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getpeername(s, name, addrlen); + } + + if (!si->peername) + { + errno = ENOTCONN; + return -1; + } + + memcpy(name, si->peername, si->peername_len); + *addrlen = si->peername_len; + + return 0; +} + +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getpeername(s, name, addrlen); + } + + memcpy(name, si->myname, si->myname_len); + *addrlen = si->myname_len; + + return 0; +} + +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_getsockopt(s, level, optname, optval, optlen); + } + + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return -1; + } + + return real_getsockopt(s, level, optname, optval, optlen); +} + +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_setsockopt(s, level, optname, optval, optlen); + } + + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return -1; + } + + return real_setsockopt(s, level, optname, optval, optlen); +} + +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) +{ + socklen_t un_addrlen; + struct sockaddr_un un_addr; + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_recvfrom(s, buf, len, flags, from, fromlen); + } + + ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); + if (ret < 0) + return ret; + + ret = sockaddr_convert_from_un(&un_addr, si->domain, from, fromlen); + + return ret; +} + +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +{ + struct sockaddr_un un_addr; + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_sendto(s, buf, len, flags, to, tolen); + } + + ret = sockaddr_convert_to_un(to, tolen, &un_addr); + if (ret < 0) + return ret; + + ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); + + return ret; +} + +int swrap_close(int fd) +{ + struct socket_info *si = find_socket_info(fd); + + if (si) { + DLIST_REMOVE(sockets, si); + + free(si->path); + free(si->myname); + free(si->peername); + free(si); + } + + return real_close(fd); +} diff --git a/source4/lib/socket_wrapper/socket_wrapper.h b/source4/lib/socket_wrapper/socket_wrapper.h new file mode 100644 index 0000000000..6da5a2980c --- /dev/null +++ b/source4/lib/socket_wrapper/socket_wrapper.h @@ -0,0 +1,48 @@ +/* + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SOCKET_WRAPPER_H__ +#define __SOCKET_WRAPPER_H__ + +int swrap_socket(int domain, int type, int protocol); +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen); +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen); +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); +int swrap_close(int); + +#ifdef SOCKET_WRAPPER_REPLACE +#define accept swrap_accept +#define connect swrap_connect +#define bind swrap_bind +#define getpeername swrap_getpeername +#define getsockname swrap_getsockname +#define getsockopt swrap_getsockopt +#define setsockopt swrap_setsockopt +#define recvfrom swrap_recvfrom +#define sendto swrap_sendto +#define socket swrap_socket +#define close swrap_close +#endif + +#endif /* __SOCKET_WRAPPER_H__ */ -- cgit From 848329b9a0a66281f699d1ae2c9e267c91ce0f43 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 30 Mar 2005 23:28:15 +0000 Subject: r6140: - Add configure option for enabling the socket-wrapper library, so it can be enabled on the buildfarm without requiring --enable-developer - Support tcp and udp being used on the same port - FIx some portability issues (should fix the build on some hosts on the buildfarm) - Ignore setting TCP_NODELAY on (semi-)TCP sockets rather then complain about it not being supported (saves us from a couple of error messages for each connection that is opened) (This used to be commit 443fb7853b8d3cb516c442fdc595038544b75738) --- source4/lib/socket_wrapper/config.m4 | 5 +++ source4/lib/socket_wrapper/socket_wrapper.c | 66 +++++++++++++++++++---------- 2 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 source4/lib/socket_wrapper/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/config.m4 b/source4/lib/socket_wrapper/config.m4 new file mode 100644 index 0000000000..97984d0436 --- /dev/null +++ b/source4/lib/socket_wrapper/config.m4 @@ -0,0 +1,5 @@ +AC_ARG_ENABLE(socket-wrapper, +[ --enable-socket-wrapper Turn on socket wrapper library (default=no)], + [if eval "test x$enable_socket_wrapper = xyes"; then + AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library]) + fi]) diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 5decde2cea..b91ff2cb0e 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -19,7 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef SAMBA_MAJOR_VERSION +#ifdef _SAMBA_BUILD #include "includes.h" #include "system/network.h" #else @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ #define real_close close #endif -static struct sockaddr *memdup(const void *data, socklen_t len) +static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) { struct sockaddr *ret = (struct sockaddr *)malloc(len); memcpy(ret, data, len); @@ -83,6 +84,7 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s { unsigned int prt; const char *p; + int type; if ((*len) < sizeof(struct sockaddr_in)) { return 0; @@ -93,7 +95,7 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s p = strchr(un->sun_path, '/'); if (p) p++; else p = un->sun_path; - if(sscanf(p, "sock_ip_%u", &prt) == 1) + if(sscanf(p, "sock_ip_%d_%u", &type, &prt) == 1) { in->sin_port = htons(prt); } @@ -102,12 +104,11 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s return 0; } -static int convert_in_un(const struct sockaddr_in *in, struct sockaddr_un *un) +static int convert_in_un(int type, const struct sockaddr_in *in, struct sockaddr_un *un) { uint16_t prt = ntohs(in->sin_port); /* FIXME: ENETUNREACH if in->sin_addr is not loopback */ - un->sun_family = AF_LOCAL; - snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%u", getenv("SOCKET_WRAPPER_DIR"), prt); + snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", getenv("SOCKET_WRAPPER_DIR"), type, prt); return 0; } @@ -122,15 +123,17 @@ static struct socket_info *find_socket_info(int fd) return NULL; } -static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_len, +static int sockaddr_convert_to_un(const struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, struct sockaddr_un *out_addr) { if (!out_addr) return 0; + out_addr->sun_family = AF_LOCAL; + switch (in_addr->sa_family) { case AF_INET: - return convert_in_un((const struct sockaddr_in *)in_addr, out_addr); + return convert_in_un(si->type, (const struct sockaddr_in *)in_addr, out_addr); case AF_LOCAL: memcpy(out_addr, in_addr, sizeof(*out_addr)); return 0; @@ -142,7 +145,8 @@ static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_l return -1; } -static int sockaddr_convert_from_un(const struct sockaddr_un *in_addr, +static int sockaddr_convert_from_un(const struct socket_info *si, + const struct sockaddr_un *in_addr, int family, struct sockaddr *out_addr, socklen_t *out_len) @@ -210,7 +214,7 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) fd = ret; - ret = sockaddr_convert_from_un(&un_addr, parent_si->domain, addr, addrlen); + ret = sockaddr_convert_from_un(parent_si, &un_addr, parent_si->domain, addr, addrlen); if (ret < 0) return ret; @@ -221,7 +225,7 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) if (addr && addrlen) { child_si->myname_len = *addrlen; - child_si->myname = memdup(addr, *addrlen); + child_si->myname = sockaddr_dup(addr, *addrlen); } return fd; @@ -237,7 +241,7 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) return real_connect(s, serv_addr, addrlen); } - ret = sockaddr_convert_to_un((const struct sockaddr *)serv_addr, addrlen, &un_addr); + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr); if (ret < 0) return ret; ret = real_connect(s, @@ -246,7 +250,7 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) if (ret >= 0) { si->peername_len = addrlen; - si->peername = memdup(serv_addr, addrlen); + si->peername = sockaddr_dup(serv_addr, addrlen); } return ret; @@ -262,7 +266,7 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) return real_bind(s, myaddr, addrlen); } - ret = sockaddr_convert_to_un((const struct sockaddr *)myaddr, addrlen, &un_addr); + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr); if (ret < 0) return ret; unlink(un_addr.sun_path); @@ -273,7 +277,7 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) if (ret >= 0) { si->myname_len = addrlen; - si->myname = memdup(myaddr, addrlen); + si->myname = sockaddr_dup(myaddr, addrlen); } return ret; @@ -321,12 +325,17 @@ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *opt return real_getsockopt(s, level, optname, optval, optlen); } - if (level != SOL_SOCKET) { + if (level == SOL_SOCKET) { + return real_getsockopt(s, level, optname, optval, optlen); + } + + switch (si->domain) { + case AF_LOCAL: + return real_getsockopt(s, level, optname, optval, optlen); + default: errno = ENOPROTOOPT; return -1; } - - return real_getsockopt(s, level, optname, optval, optlen); } int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) @@ -337,12 +346,23 @@ int swrap_setsockopt(int s, int level, int optname, const void *optval, so return real_setsockopt(s, level, optname, optval, optlen); } - if (level != SOL_SOCKET) { + if (level == SOL_SOCKET) { + return real_setsockopt(s, level, optname, optval, optlen); + } + + switch (si->domain) { + case AF_LOCAL: + return real_setsockopt(s, level, optname, optval, optlen); + case AF_INET: + /* Silence some warnings */ +#ifdef TCP_NODELAY + if (optname == TCP_NODELAY) + return 0; +#endif + default: errno = ENOPROTOOPT; return -1; } - - return real_setsockopt(s, level, optname, optval, optlen); } ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) @@ -360,7 +380,7 @@ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr if (ret < 0) return ret; - ret = sockaddr_convert_from_un(&un_addr, si->domain, from, fromlen); + ret = sockaddr_convert_from_un(si, &un_addr, si->domain, from, fromlen); return ret; } @@ -375,7 +395,7 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str return real_sendto(s, buf, len, flags, to, tolen); } - ret = sockaddr_convert_to_un(to, tolen, &un_addr); + ret = sockaddr_convert_to_un(si, to, tolen, &un_addr); if (ret < 0) return ret; -- cgit From 07e3fa214673fde54c13273c5f95418011d56080 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 31 Mar 2005 00:43:26 +0000 Subject: r6144: Apparently there are more systems that have AF_UNIX then AF_LOCAL (we already use AF_UNIX in other places). (This used to be commit 88d93b9782766ab1159a233307ef508881caa615) --- source4/lib/socket_wrapper/socket_wrapper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index b91ff2cb0e..238155b26b 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -129,12 +129,12 @@ static int sockaddr_convert_to_un(const struct socket_info *si, const struct soc if (!out_addr) return 0; - out_addr->sun_family = AF_LOCAL; + out_addr->sun_family = AF_UNIX; switch (in_addr->sa_family) { case AF_INET: return convert_in_un(si->type, (const struct sockaddr_in *)in_addr, out_addr); - case AF_LOCAL: + case AF_UNIX: memcpy(out_addr, in_addr, sizeof(*out_addr)); return 0; default: @@ -157,7 +157,7 @@ static int sockaddr_convert_from_un(const struct socket_info *si, switch (family) { case AF_INET: return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len); - case AF_LOCAL: + case AF_UNIX: memcpy(out_addr, in_addr, sizeof(*in_addr)); *out_len = sizeof(*in_addr); return 0; @@ -178,7 +178,7 @@ int swrap_socket(int domain, int type, int protocol) return real_socket(domain, type, protocol); } - fd = real_socket(PF_LOCAL, type, 0); + fd = real_socket(AF_UNIX, type, 0); if (fd < 0) return fd; @@ -330,7 +330,7 @@ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *opt } switch (si->domain) { - case AF_LOCAL: + case AF_UNIX: return real_getsockopt(s, level, optname, optval, optlen); default: errno = ENOPROTOOPT; @@ -351,7 +351,7 @@ int swrap_setsockopt(int s, int level, int optname, const void *optval, so } switch (si->domain) { - case AF_LOCAL: + case AF_UNIX: return real_setsockopt(s, level, optname, optval, optlen); case AF_INET: /* Silence some warnings */ -- cgit From c36387446668b494b68ad5cf44407c9ce7cee497 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 31 Mar 2005 02:14:31 +0000 Subject: r6147: The maxfd was being recalculated on every event loop, which made us less scalable. It only needs to be recalculated when we the highest fd is destroyed. (This used to be commit 568b9175f329f594404c9091ee5946670c40697e) --- source4/lib/events/events_standard.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 76c8c4768a..a867f86801 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -514,7 +514,6 @@ static int std_event_loop_wait(struct event_context *ev) struct std_event_context *std_ev = talloc_get_type(ev->additional_data, struct std_event_context); std_ev->exit_code = 0; - std_ev->maxfd = EVENT_INVALID_MAXFD; while (std_ev->fd_events && std_ev->exit_code == 0) { if (std_event_loop_once(ev) != 0) { -- cgit From 4b96d831479f31ae6e0f2039f4b91c1bed643bea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 31 Mar 2005 12:40:12 +0000 Subject: r6150: fixed a few socket_wrapper bugs. - now works properly with UDP, so the NBT tests work - fixed byte order in a few places - connect() now fails to non-localhost - fixed some places that tested for < 0, which should be == -1 (most syscalls return -1 on error, not "negative") (This used to be commit 61e1eea0fdb13577de2506472c5443ee92656263) --- source4/lib/socket_wrapper/socket_wrapper.c | 115 +++++++++++++++++++--------- 1 file changed, 80 insertions(+), 35 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 238155b26b..b7b0aa07b6 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -68,8 +68,10 @@ struct socket_info int domain; int type; int protocol; + int bound; char *path; + char *tmp_path; struct sockaddr *myname; socklen_t myname_len; @@ -78,7 +80,9 @@ struct socket_info socklen_t peername_len; struct socket_info *prev, *next; -} *sockets = NULL; +}; + +static struct socket_info *sockets = NULL; static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) { @@ -95,11 +99,10 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s p = strchr(un->sun_path, '/'); if (p) p++; else p = un->sun_path; - if(sscanf(p, "sock_ip_%d_%u", &type, &prt) == 1) - { + if (sscanf(p, "sock_ip_%d_%u", &type, &prt) == 2) { in->sin_port = htons(prt); } - in->sin_addr.s_addr = INADDR_LOOPBACK; + in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); *len = sizeof(struct sockaddr_in); return 0; } @@ -107,8 +110,8 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s static int convert_in_un(int type, const struct sockaddr_in *in, struct sockaddr_un *un) { uint16_t prt = ntohs(in->sin_port); - /* FIXME: ENETUNREACH if in->sin_addr is not loopback */ - snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", getenv("SOCKET_WRAPPER_DIR"), type, prt); + snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", + getenv("SOCKET_WRAPPER_DIR"), type, prt); return 0; } @@ -146,14 +149,20 @@ static int sockaddr_convert_to_un(const struct socket_info *si, const struct soc } static int sockaddr_convert_from_un(const struct socket_info *si, - const struct sockaddr_un *in_addr, - int family, - struct sockaddr *out_addr, - socklen_t *out_len) + const struct sockaddr_un *in_addr, + socklen_t un_addrlen, + int family, + struct sockaddr *out_addr, + socklen_t *out_len) { - if (!out_addr) + if (out_addr == NULL || out_len == NULL) return 0; + if (un_addrlen == 0) { + *out_len = 0; + return 0; + } + switch (family) { case AF_INET: return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len); @@ -180,11 +189,9 @@ int swrap_socket(int domain, int type, int protocol) fd = real_socket(AF_UNIX, type, 0); - if (fd < 0) - return fd; + if (fd == -1) return -1; - si = malloc(sizeof(struct socket_info)); - memset(si, 0, sizeof(*si)); + si = calloc(1, sizeof(struct socket_info)); si->domain = domain; si->type = type; @@ -210,13 +217,13 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) } ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret < 0) return ret; + if (ret == -1) return ret; fd = ret; - ret = sockaddr_convert_from_un(parent_si, &un_addr, parent_si->domain, addr, addrlen); - - if (ret < 0) return ret; + ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, + parent_si->domain, addr, addrlen); + if (ret == -1) return ret; child_si = malloc(sizeof(struct socket_info)); memset(child_si, 0, sizeof(*child_si)); @@ -241,14 +248,20 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) return real_connect(s, serv_addr, addrlen); } + /* only allow pseudo loopback connections */ + if (((const struct sockaddr_in *)serv_addr)->sin_addr.s_addr != + htonl(INADDR_LOOPBACK)) { + errno = ENETUNREACH; + return -1; + } + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr); - if (ret < 0) return ret; + if (ret == -1) return -1; - ret = real_connect(s, - (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); + ret = real_connect(s, (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); - if (ret >= 0) { + if (ret == 0) { si->peername_len = addrlen; si->peername = sockaddr_dup(serv_addr, addrlen); } @@ -267,17 +280,17 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) } ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr); - if (ret < 0) return ret; + if (ret == -1) return -1; unlink(un_addr.sun_path); - ret = real_bind(s, - (struct sockaddr *)&un_addr, - sizeof(struct sockaddr_un)); + ret = real_bind(s, (struct sockaddr *)&un_addr, + sizeof(struct sockaddr_un)); - if (ret >= 0) { + if (ret == 0) { si->myname_len = addrlen; si->myname = sockaddr_dup(myaddr, addrlen); + si->bound = 1; } return ret; @@ -367,8 +380,8 @@ int swrap_setsockopt(int s, int level, int optname, const void *optval, so ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { - socklen_t un_addrlen; struct sockaddr_un un_addr; + socklen_t un_addrlen = sizeof(un_addr); int ret; struct socket_info *si = find_socket_info(s); @@ -377,10 +390,13 @@ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr } ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); - if (ret < 0) + if (ret == -1) return ret; - ret = sockaddr_convert_from_un(si, &un_addr, si->domain, from, fromlen); + if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, + si->domain, from, fromlen) == -1) { + return -1; + } return ret; } @@ -395,12 +411,37 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str return real_sendto(s, buf, len, flags, to, tolen); } + /* using sendto() on an unbound DGRAM socket would give the + recipient no way to reply, as unlike UDP, a unix domain socket + can't auto-assign emphemeral port numbers, so we need to assign + it here */ + if (si->bound == 0 && si->type == SOCK_DGRAM) { + int i; + + un_addr.sun_family = AF_UNIX; + + for (i=0;i<1000;i++) { + snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), + "%s/sock_ip_%u_%u", getenv("SOCKET_WRAPPER_DIR"), + SOCK_DGRAM, i + 10000); + if (bind(si->fd, (struct sockaddr *)&un_addr, + sizeof(un_addr)) == 0) { + si->tmp_path = strdup(un_addr.sun_path); + si->bound = 1; + break; + } + } + if (i == 1000) { + return -1; + } + } + + ret = sockaddr_convert_to_un(si, to, tolen, &un_addr); - if (ret < 0) - return ret; + if (ret == -1) return -1; ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); - + return ret; } @@ -414,6 +455,10 @@ int swrap_close(int fd) free(si->path); free(si->myname); free(si->peername); + if (si->tmp_path) { + unlink(si->tmp_path); + free(si->tmp_path); + } free(si); } -- cgit From 567a74690c9536f464844d647b9fe21ca56b53f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 6 Apr 2005 10:06:08 +0000 Subject: r6222: fixed the socket wrapper code for getsockname() (This used to be commit 11e245a3f0e1523eba3a042db140dec8732aa985) --- source4/lib/socket_wrapper/socket_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index b7b0aa07b6..4814f6c929 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -321,7 +321,7 @@ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) struct socket_info *si = find_socket_info(s); if (!si) { - return real_getpeername(s, name, addrlen); + return real_getsockname(s, name, addrlen); } memcpy(name, si->myname, si->myname_len); -- cgit From e3775ee8501e2f15ee172970085c2c12e50da1cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Apr 2005 19:50:54 +0000 Subject: r6238: Ensure if realloc fails on an internal tdb we fail gracefully. Jeremy. (This used to be commit d69f7c05468ae54e0474b188fedabe14e7297d53) --- source4/lib/tdb/common/tdb.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index d9fabaeda9..6554ec5697 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -802,9 +802,14 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) tdb->map_size += size; - if (tdb->flags & TDB_INTERNAL) - tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size); - else { + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); + if (!new_map_ptr) { + tdb->map_size -= size; + goto fail; + } + tdb->map_ptr = new_map_ptr; + } else { /* * We must ensure the file is remapped before adding the space * to ensure consistency with systems like OpenBSD where -- cgit From 6d1ae6d35aca66cff090d40927da1ac093dc65ce Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 10 Apr 2005 10:11:36 +0000 Subject: r6271: Don't zero the cli_credentials structure - instead allow valgrind to track the use of un-initialised values. This change will require a recompile from clean, as the enum describing the status of each element now has a default of CRED_UNINITIALISED. Andrew Bartlett (This used to be commit 83c2eb806d43f588bd06336aa7e2dbdc00dc2c67) --- source4/lib/credentials.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 9c892b0688..ba263260bb 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -32,11 +32,17 @@ */ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) { - struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials); + struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials); if (!cred) { return cred; } + cred->machine_account_pending = False; + cred->workstation_obtained = CRED_UNINITIALISED; + cred->username_obtained = CRED_UNINITIALISED; + cred->password_obtained = CRED_UNINITIALISED; + cred->domain_obtained = CRED_UNINITIALISED; + cred->realm_obtained = CRED_UNINITIALISED; return cred; } -- cgit From 9bf2c694010ae9b2773bfe738a1f88c4b6693e48 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Apr 2005 08:24:36 +0000 Subject: r6340: - added an easy to use function to initialise a temporary ldb with some ldif - init the schannel.ldb with some CASE_INSENSITIVE attributes (This used to be commit e6376b24303dc513e15c7e640c8c1c8d8ca11091) --- source4/lib/gendb.c | 13 +++++++++++++ source4/lib/util_file.c | 9 +++++++++ 2 files changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index befdd63c9e..5b4f7b251e 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -78,3 +78,16 @@ int gendb_search(struct ldb_context *sam_ldb, return count; } +/* + setup some initial ldif in a ldb +*/ +int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string) +{ + struct ldb_ldif *ldif; + int ret; + ldif = ldb_ldif_read_string(ldb, ldif_string); + if (ldif == NULL) return -1; + ret = ldb_add(ldb, ldif->msg); + talloc_free(ldif); + return ret; +} diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 6d234b571c..e02198754d 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -386,3 +386,12 @@ BOOL file_save(const char *fname, void *packet, size_t length) close(fd); return True; } + +/* + see if a file exists +*/ +BOOL file_exists(const char *path) +{ + struct stat st; + return (stat(path, &st) == 0); +} -- cgit From b9456e9d67e794d37b395bcb01a758ef15e20123 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 17 Apr 2005 00:07:40 +0000 Subject: r6360: Quieten unused variable warning. (This used to be commit 5a598f5da17b60ad52b2ae9d8e4484286e492a1f) --- source4/lib/ldb/modules/schema.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1b08db6170..4502bba9ed 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -541,7 +541,7 @@ static const char *schema_errstring(struct ldb_module *module) static int schema_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; +/* struct ldb_module *ctx = module_ctx; */ /* put your clean-up functions here */ return 0; } -- cgit From 499f00b4d947b04ab9616a17d9e638caaec9e6f5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 23 Apr 2005 04:30:58 +0000 Subject: r6442: Add mechanism for configuring ldb independantly of the rest of Samba using the autoconf tools. (This used to be commit a8de35ca27e307d1be6ebad517b7012a5de30567) --- source4/lib/ldb/Makefile.in | 115 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/Makefile.ldb | 110 -------------------------------- source4/lib/ldb/configure.in | 9 +++ source4/lib/ldb/man/build_manpages.sh | 11 ---- 4 files changed, 124 insertions(+), 121 deletions(-) create mode 100644 source4/lib/ldb/Makefile.in delete mode 100644 source4/lib/ldb/Makefile.ldb create mode 100644 source4/lib/ldb/configure.in delete mode 100755 source4/lib/ldb/man/build_manpages.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in new file mode 100644 index 0000000000..f07ab5a1d6 --- /dev/null +++ b/source4/lib/ldb/Makefile.in @@ -0,0 +1,115 @@ +CC = @CC@ +GCOV = @GCOV@ +YODL2MAN = @YODL2MAN@ + +ifeq ($(WITH_LDAP),1) +OPENLDAP_PREFIX=/usr +LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -llber -lldap +LDAP_FLAGS=-DHAVE_LDAP=1 +LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o +endif + +TDBDIR=../tdb +TALLOCDIR=../talloc + +CFLAGS1=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ + -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. \ + -I$(TDBDIR)/include -I$(TALLOCDIR) -DUSE_MMAP=1 $(LDAP_FLAGS) + +# enable the following two lines to build with gcov code coverage support +#GCOV_FLAGS = -ftest-coverage -fprofile-arcs +#GCOV_LIBS = -lgcov + +CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) @CFLAGS@ + +LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(GCOV_LIBS) + +TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o +TALLOC_OBJ=$(TALLOCDIR)/talloc.o + +LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ + ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ + ldb_tdb/ldb_cache.o + + +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ + common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ + common/ldb_debug.o common/ldb_modules.o + +MODULES_OBJ=modules/timestamps.o modules/schema.o + +OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) + +LDB_LIB = lib/libldb.a + +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest + +LIBS = $(LDB_LIB)($(OBJS)) + +DIRS = lib bin + +all: $(DIRS) $(BINS) $(LIBS) manpages + +lib: + mkdir -p lib + +bin: + mkdir -p bin + +lib/libldb.a: $(OBJS) + +bin/ldbadd: tools/ldbadd.o $(LIBS) + $(CC) -o bin/ldbadd tools/ldbadd.o $(LIB_FLAGS) + +bin/ldbsearch: tools/ldbsearch.o $(LIBS) + $(CC) -o bin/ldbsearch tools/ldbsearch.o $(LIB_FLAGS) + +bin/ldbdel: tools/ldbdel.o $(LIBS) + $(CC) -o bin/ldbdel tools/ldbdel.o $(LIB_FLAGS) + +bin/ldbmodify: tools/ldbmodify.o $(LIBS) + $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) + +bin/ldbedit: tools/ldbedit.o $(LIBS) + $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) + +bin/ldbrename: tools/ldbrename.o $(LIBS) + $(CC) -o bin/ldbrename tools/ldbrename.o $(LIB_FLAGS) + +bin/ldbtest: tools/ldbtest.o $(LIBS) + $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) + +.SUFFIXES: .1 .2 .3 .yo + +.yo.3: + echo Creating $@ from $< + -$(YODL2MAN) -o $@ `dirname $<`/`basename $< .yo` || rm -f $@ + +manpages: $(patsubst %.yo,%.3,$(wildcard man/man3/*.yo)) + +clean: + rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] + +etags: + etags */*.[ch] + +test-tdb: + @echo "STARTING TDB BACKEND TEST" + tests/test-tdb.sh + +test-ldap: + @echo "STARTING LDAP BACKEND TEST" + tests/test-ldap.sh + +test-schema: + @echo "STARTING SCHEMA MODULE TEST" + tests/test-schema.sh + +test: test-tdb test-ldap test-schema + +gcov: + $(GCOV) -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov + $(GCOV) -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov + $(GCOV) -po common common/*.c 2| tee common.report.gcov + $(GCOV) -po modules modules/*.c 2| tee modules.report.gcov + $(GCOV) -po tools tools/*.c 2| tee tools.report.gcov diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb deleted file mode 100644 index 791a345f72..0000000000 --- a/source4/lib/ldb/Makefile.ldb +++ /dev/null @@ -1,110 +0,0 @@ - -# ldap support is optional edit WITH_LDAP to suit -WITH_LDAP=1 - -ifeq ($(WITH_LDAP),1) -OPENLDAP_PREFIX=/usr -LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -llber -lldap -LDAP_FLAGS=-DHAVE_LDAP=1 -LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o -endif - -TDBDIR=../tdb -TALLOCDIR=../talloc - -CFLAGS1=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ - -Wcast-qual -Wcast-align -Wwrite-strings -g -Iinclude -I. -I.. \ - -I$(TDBDIR)/include -I$(TALLOCDIR) -DUSE_MMAP=1 $(LDAP_FLAGS) - -# enable the following two lines to build with gcov code coverage support -#GCOV_FLAGS = -ftest-coverage -fprofile-arcs -#GCOV_LIBS = -lgcov - -CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) - -LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(GCOV_LIBS) - -TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o -TALLOC_OBJ=$(TALLOCDIR)/talloc.o - -LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ - ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ - ldb_tdb/ldb_cache.o - - -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ - common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ - common/ldb_debug.o common/ldb_modules.o - -MODULES_OBJ=modules/timestamps.o modules/schema.o - -OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) - -LDB_LIB = lib/libldb.a - -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest - -LIBS = $(LDB_LIB)($(OBJS)) - -DIRS = lib bin - -all: $(DIRS) $(BINS) $(LIBS) manpages - -lib: - mkdir -p lib - -bin: - mkdir -p bin - -lib/libldb.a: $(OBJS) - -bin/ldbadd: tools/ldbadd.o $(LIBS) - $(CC) -o bin/ldbadd tools/ldbadd.o $(LIB_FLAGS) - -bin/ldbsearch: tools/ldbsearch.o $(LIBS) - $(CC) -o bin/ldbsearch tools/ldbsearch.o $(LIB_FLAGS) - -bin/ldbdel: tools/ldbdel.o $(LIBS) - $(CC) -o bin/ldbdel tools/ldbdel.o $(LIB_FLAGS) - -bin/ldbmodify: tools/ldbmodify.o $(LIBS) - $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) - -bin/ldbedit: tools/ldbedit.o $(LIBS) - $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) - -bin/ldbrename: tools/ldbrename.o $(LIBS) - $(CC) -o bin/ldbrename tools/ldbrename.o $(LIB_FLAGS) - -bin/ldbtest: tools/ldbtest.o $(LIBS) - $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) - -manpages: - -man/build_manpages.sh - -clean: - rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] - -etags: - etags */*.[ch] - -test-tdb: - @echo "STARTING TDB BACKEND TEST" - tests/test-tdb.sh - -test-ldap: - @echo "STARTING LDAP BACKEND TEST" - tests/test-ldap.sh - -test-schema: - @echo "STARTING SCHEMA MODULE TEST" - tests/test-schema.sh - -test: test-tdb test-ldap test-schema - -gcov: - gcov -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov - gcov -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov - gcov -po common common/*.c 2| tee common.report.gcov - gcov -po modules modules/*.c 2| tee modules.report.gcov - gcov -po tools tools/*.c 2| tee tools.report.gcov diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in new file mode 100644 index 0000000000..94afebb9f5 --- /dev/null +++ b/source4/lib/ldb/configure.in @@ -0,0 +1,9 @@ +AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) +AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) +AC_INIT(include/ldb.h) +AC_FUNC_MMAP +AC_PATH_PROG(YODL2MAN,yodl2man) +AC_PATH_PROG(GCOV,gcov) +AC_PROG_CC +sinclude(config.m4) +AC_OUTPUT(Makefile) diff --git a/source4/lib/ldb/man/build_manpages.sh b/source4/lib/ldb/man/build_manpages.sh deleted file mode 100755 index 5e5e698ac4..0000000000 --- a/source4/lib/ldb/man/build_manpages.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -for f in man/man3/*.yo; do - base=`basename $f .yo`; - man=man/man3/$base.3; - - if test $f -nt $man; then - echo Creating $man from $f - yodl2man -o $man $f || rm -f $man - fi -done -- cgit From 96700ef79d2925a5d67a3b835924b97dcb0b3d79 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Apr 2005 03:03:28 +0000 Subject: r6452: This particular credentials feature needs to be NULL by default. Andrew Bartlett (This used to be commit e4e221705306c63986f384938bbab5006caeec2e) --- source4/lib/credentials.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index ba263260bb..f5ce886ed0 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -37,6 +37,7 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) return cred; } + cred->netlogon_creds = NULL; cred->machine_account_pending = False; cred->workstation_obtained = CRED_UNINITIALISED; cred->username_obtained = CRED_UNINITIALISED; -- cgit From 0501a440bedde5e867e461d266aafe666be53e54 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Apr 2005 08:26:53 +0000 Subject: r6462: Move the arcfour sbox state into it's own structure, and allocate it with talloc() for the NTLMSSP system. Andrew Bartlett (This used to be commit 7a93ac49c28d433ccf0f077294f473fe728b9995) --- source4/lib/crypto/crypto.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/crypto/crypto.h b/source4/lib/crypto/crypto.h index e7a0c290a5..8cf4b21aae 100644 --- a/source4/lib/crypto/crypto.h +++ b/source4/lib/crypto/crypto.h @@ -22,3 +22,9 @@ #include "lib/crypto/md4.h" #include "lib/crypto/hmacmd5.h" #include "lib/crypto/crc32.h" + +struct arcfour_state { + uint8_t sbox[256]; + uint8_t index_i; + uint8_t index_j; +}; -- cgit From fe4d985b6f3d318d9b58a16677be3b4ae34fba15 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 25 Apr 2005 12:46:18 +0000 Subject: r6470: Remove ldb_search_free() it is not needed anymore. Just use talloc_free() to release the memory after an ldb_search(). (This used to be commit 4f0948dab0aa5e8b6a4ce486f3668ca8dfae23db) --- source4/lib/ldb/common/ldb.c | 12 +++--------- source4/lib/ldb/common/ldb_modules.c | 8 -------- source4/lib/ldb/include/ldb.h | 8 ++------ source4/lib/ldb/include/ldb_private.h | 2 -- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 13 +------------ source4/lib/ldb/ldb_tdb/ldb_search.c | 14 -------------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 1 - source4/lib/ldb/ldb_tdb/ldb_tdb.h | 1 - source4/lib/ldb/man/man3/ldb.yo | 2 -- source4/lib/ldb/modules/schema.c | 9 +-------- source4/lib/ldb/modules/skel.c | 7 ------- source4/lib/ldb/modules/timestamps.c | 7 ------- source4/lib/ldb/tools/ldbdel.c | 2 +- source4/lib/ldb/tools/ldbedit.c | 4 ++-- source4/lib/ldb/tools/ldbsearch.c | 4 ++-- source4/lib/ldb/tools/ldbtest.c | 2 +- source4/lib/registry/reg_backend_ldb.c | 6 +++--- 17 files changed, 16 insertions(+), 86 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 40616c5963..600c7063f0 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -81,6 +81,9 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, search the database given a LDAP-like search expression return the number of records found, or -1 on error + + Use talloc_free to free the ldb_message returned in 'res' + */ int ldb_search(struct ldb_context *ldb, const char *base, @@ -91,15 +94,6 @@ int ldb_search(struct ldb_context *ldb, return ldb->modules->ops->search(ldb->modules, base, scope, expression, attrs, res); } -/* - free a set of messages returned by ldb_search -*/ -int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs) -{ - return ldb->modules->ops->search_free(ldb->modules, msgs); -} - - /* add a record to the database. Will fail if a record with the given class and key already exists diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index ffa150d773..644154d645 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -224,14 +224,6 @@ int ldb_next_search(struct ldb_module *module, return module->next->ops->search(module->next, base, scope, expression, attrs, res); } -int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg) -{ - if (!module->next) { - return -1; - } - return module->next->ops->search_free(module->next, msg); -} - int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message) { if (!module->next) { diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 0eb661d7ce..f748bb6b42 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -162,6 +162,8 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, search the database given a LDAP-like search expression return the number of records found, or -1 on error + + use talloc_free to free the ldb_message returned */ int ldb_search(struct ldb_context *ldb, const char *base, @@ -169,12 +171,6 @@ int ldb_search(struct ldb_context *ldb, const char *expression, const char * const *attrs, struct ldb_message ***res); -/* - free a set of messages returned by ldb_search -*/ -int ldb_search_free(struct ldb_context *ldb, struct ldb_message **msgs); - - /* add a record to the database. Will fail if a record with the given class and key already exists diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index a370a80299..7a0b2fef75 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -57,7 +57,6 @@ struct ldb_module_ops { const char *name; int (*search)(struct ldb_module *, const char *, enum ldb_scope, const char *, const char * const [], struct ldb_message ***); - int (*search_free)(struct ldb_module *, struct ldb_message **); int (*add_record)(struct ldb_module *, const struct ldb_message *); int (*modify_record)(struct ldb_module *, const struct ldb_message *); int (*delete_record)(struct ldb_module *, const char *); @@ -89,7 +88,6 @@ int ldb_next_search(struct ldb_module *module, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res); -int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg); int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_delete_record(struct ldb_module *module, const char *dn); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index dc392dd56b..c62c1b9e56 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -125,16 +125,6 @@ static int lldb_delete(struct ldb_module *module, const char *dn) return ret; } -/* - free a search result -*/ -static int lldb_search_free(struct ldb_module *module, struct ldb_message **res) -{ - talloc_free(res); - return 0; -} - - /* add a single set of ldap message values to a ldb_message */ @@ -290,7 +280,7 @@ static int lldb_search(struct ldb_module *module, const char *base, return msg_count; failed: - if (*res) lldb_search_free(module, *res); + if (*res) talloc_free(*res); return -1; } @@ -459,7 +449,6 @@ static const char *lldb_errstring(struct ldb_module *module) static const struct ldb_module_ops lldb_ops = { "ldap", lldb_search, - lldb_search_free, lldb_add, lldb_modify, lldb_delete, diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index f813841edb..4f45fdf376 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -415,20 +415,6 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } -/* - free a set of search results -*/ -int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs) -{ - struct ltdb_private *ltdb = module->private_data; - - ltdb->last_err_string = NULL; - - talloc_free(msgs); - - return 0; -} - /* search the database with a LDAP-like expression. this is the "full search" non-indexed variant diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 204eaf9d3c..87582cf4eb 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -797,7 +797,6 @@ static const char *ltdb_errstring(struct ldb_module *module) static const struct ldb_module_ops ltdb_ops = { "tdb", ltdb_search, - ltdb_search_free, ltdb_add, ltdb_modify, ltdb_delete, diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 4c2fc52f7c..9fb60b6359 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -95,7 +95,6 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], int *count, struct ldb_message ***res); -int ltdb_search_free(struct ldb_module *module, struct ldb_message **msgs); int ltdb_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const attrs[], struct ldb_message ***res); diff --git a/source4/lib/ldb/man/man3/ldb.yo b/source4/lib/ldb/man/man3/ldb.yo index 8d7a60ccf2..c2c7e1b872 100644 --- a/source4/lib/ldb/man/man3/ldb.yo +++ b/source4/lib/ldb/man/man3/ldb.yo @@ -66,8 +66,6 @@ dit(bf(ldb_connect(3))) connect to a ldb backend dit(bf(ldb_search(3))) perform a database search -dit(bf(ldb_search_free(3))) free the results of a ldb_search - dit(bf(ldb_add(3))) add a record to the database dit(bf(ldb_delete(3))) delete a record from the database diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 4502bba9ed..29e5194416 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -166,7 +166,7 @@ static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct /* set flags to 0 as flags on search have undefined values */ ret = get_msg_attributes(ss, *srch, 0); if (ret != 0) { - ldb_search_free(ldb, srch); + talloc_free(srch); return ret; } @@ -306,12 +306,6 @@ static int schema_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -/* search_free */ -static int schema_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -549,7 +543,6 @@ static int schema_destructor(void *module_ctx) static const struct ldb_module_ops schema_ops = { "schema", schema_search, - schema_search_free, schema_add_record, schema_modify_record, schema_delete_record, diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 882a776819..09f2452365 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -44,12 +44,6 @@ static int skel_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -/* search_free */ -static int skel_search_free(struct ldb_module *module, struct ldb_message **res) -{ - return ldb_next_search_free(module, res); -} - /* add_record */ static int skel_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -102,7 +96,6 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { "skel", skel_search, - skel_search_free, skel_add_record, skel_modify_record, skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index c472fc3c55..1c01bd14fd 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -49,12 +49,6 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int timestamps_search_free(struct ldb_module *module, struct ldb_message **res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search_free\n"); - return ldb_next_search_free(module, res); -} - static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { @@ -255,7 +249,6 @@ static int timestamps_destructor(void *module_ctx) static const struct ldb_module_ops timestamps_ops = { "timestamps", timestamps_search, - timestamps_search_free, timestamps_add_record, timestamps_modify_record, timestamps_delete_record, diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 72540db07a..ec2e302b20 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -55,7 +55,7 @@ static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) } } - ldb_search_free(ldb, res); + talloc_free(res); if (total == 0) { return -1; diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index b9f82c282a..4c41b6b19a 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -427,9 +427,9 @@ static void usage(void) do_edit(ldb, msgs, ret, editor); if (ret > 0) { - ret = ldb_search_free(ldb, msgs); + ret = talloc_free(msgs); if (ret == -1) { - fprintf(stderr, "search_free failed - %s\n", ldb_errstring(ldb)); + fprintf(stderr, "talloc_free failed\n"); exit(1); } } diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 8d435e7661..3e6e7d7feb 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -81,9 +81,9 @@ static int do_search(struct ldb_context *ldb, } if (ret > 0) { - ret = ldb_search_free(ldb, msgs); + ret = talloc_free(msgs); if (ret == -1) { - fprintf(stderr, "search_free failed\n"); + fprintf(stderr, "talloc_free failed\n"); exit(1); } } diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 86f39d4606..fc1f3e3098 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -248,7 +248,7 @@ static void search_uid(struct ldb_context *ldb, int nrecords, int nsearches) } if (ret > 0) { - ldb_search_free(ldb, res); + talloc_free(res); } printf("testing uid %d/%d - %d \r", i, uid, ret); diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 7e63b14245..fc01de61a5 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -102,12 +102,12 @@ static int reg_close_ldb_key (void *data) struct ldb_context *c = key->hive->backend_data; if (kd->subkeys) { - ldb_search_free(c, kd->subkeys); + talloc_free(kd->subkeys); kd->subkeys = NULL; } if (kd->values) { - ldb_search_free(c, kd->values); + talloc_free(kd->values); kd->values = NULL; } return 0; @@ -224,7 +224,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch (*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data); newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); - ldb_search_free(c, msg); + talloc_free(msg); return WERR_OK; } -- cgit From acb6110d5ddfdf9c6301d12ae0cc2fe710618b04 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Apr 2005 03:03:54 +0000 Subject: r6474: - added a simple talloc web page at http://talloc.samba.org/ - make it easier to seperataly build talloc for other projects (This used to be commit 27b987d267603977be8798e7e5412b91e18a316b) --- source4/lib/talloc/Makefile.in | 20 ++++++++++++++++ source4/lib/talloc/Makefile.talloc | 16 ------------- source4/lib/talloc/autogen.sh | 7 ++++++ source4/lib/talloc/configure.in | 7 ++++++ source4/lib/talloc/web/index.html | 47 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 source4/lib/talloc/Makefile.in delete mode 100644 source4/lib/talloc/Makefile.talloc create mode 100755 source4/lib/talloc/autogen.sh create mode 100644 source4/lib/talloc/configure.in create mode 100644 source4/lib/talloc/web/index.html (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in new file mode 100644 index 0000000000..ff4fc7f561 --- /dev/null +++ b/source4/lib/talloc/Makefile.in @@ -0,0 +1,20 @@ +#OPT = -g -ftest-coverage -fprofile-arcs +#LIBS = -lgcov +OPT = -O + +CFLAGS = $(OPT) -Wall + +LIBOBJ = talloc.o + +all: libtalloc.a testsuite + +testsuite: $(LIBOBJ) testsuite.o + $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) + +libtalloc.a: libtalloc.a($(LIBOBJ)) + +clean: + rm -f *~ *.o testsuite *.gc?? + +gcov: + gcov talloc.c diff --git a/source4/lib/talloc/Makefile.talloc b/source4/lib/talloc/Makefile.talloc deleted file mode 100644 index a19b4ce311..0000000000 --- a/source4/lib/talloc/Makefile.talloc +++ /dev/null @@ -1,16 +0,0 @@ -#OPT = -g -ftest-coverage -fprofile-arcs -#LIBS = -lgcov -OPT = -O - -CFLAGS = $(OPT) -Wall - -all: testsuite - -testsuite: talloc.o testsuite.o - $(CC) $(CFLAGS) -o testsuite testsuite.o talloc.o $(LIBS) - -clean: - rm -f *~ *.o testsuite *.gc?? - -gcov: - gcov talloc.c diff --git a/source4/lib/talloc/autogen.sh b/source4/lib/talloc/autogen.sh new file mode 100755 index 0000000000..cdd7fd2e04 --- /dev/null +++ b/source4/lib/talloc/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +(autoheader && autoconf) || exit 1 + +echo "Now run ./configure and then make." +exit 0 + diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in new file mode 100644 index 0000000000..5c30200118 --- /dev/null +++ b/source4/lib/talloc/configure.in @@ -0,0 +1,7 @@ +AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) +AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) +AC_INIT(talloc.h) +AC_PROG_CC +AC_PATH_PROG(GCOV,gcov) +sinclude(config.m4) +AC_OUTPUT(Makefile) diff --git a/source4/lib/talloc/web/index.html b/source4/lib/talloc/web/index.html new file mode 100644 index 0000000000..2a6c2d0768 --- /dev/null +++ b/source4/lib/talloc/web/index.html @@ -0,0 +1,47 @@ + + + +talloc + + + +

talloc

+ +talloc is a hierarchical pool based memory allocator with +destructors. It is the core memory allocator used in Samba4, and has +made a huge difference in many aspects of Samba4 development.

+ +To get started with talloc, I would recommend you read the talloc guide. + +

Discussion and bug reports

+ +talloc does not currently have its own mailing list or bug tracking +system. For now, please use the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +

Download

+ +You can download the latest release either via rsync or anonymous +svn. To fetch via svn use the following command: + +
+  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc
+
+ +To fetch via rsync use this command: + +
+  rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc .
+
+ +
+ +Andrew Tridgell
+talloc AT tridgell.net +
+ + + -- cgit From 26a625e85738b37e5323c4612916ccce89ebb0fa Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 26 Apr 2005 03:42:02 +0000 Subject: r6477: Remove call to autoheader as autogenerated header files are not used by talloc (This used to be commit 5ca8a852067c34fed86f70be7f157714ecdd5501) --- source4/lib/talloc/autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/autogen.sh b/source4/lib/talloc/autogen.sh index cdd7fd2e04..94148edf69 100755 --- a/source4/lib/talloc/autogen.sh +++ b/source4/lib/talloc/autogen.sh @@ -1,6 +1,6 @@ #!/bin/sh -(autoheader && autoconf) || exit 1 +autoconf || exit 1 echo "Now run ./configure and then make." exit 0 -- cgit From 9ced235daba8cb6b516eedb857569de8da1aeb5c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 26 Apr 2005 03:59:59 +0000 Subject: r6478: Add 'make install' and a pkg-config file (This used to be commit c8e1b7542736bd674b8407872dbbe3a9941fce59) --- source4/lib/talloc/Makefile.in | 9 +++++++++ source4/lib/talloc/configure.in | 2 +- source4/lib/talloc/talloc.pc.in | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 source4/lib/talloc/talloc.pc.in (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index ff4fc7f561..a3dd3f3e0b 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -1,6 +1,10 @@ #OPT = -g -ftest-coverage -fprofile-arcs #LIBS = -lgcov OPT = -O +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ CFLAGS = $(OPT) -Wall @@ -13,6 +17,11 @@ testsuite: $(LIBOBJ) testsuite.o libtalloc.a: libtalloc.a($(LIBOBJ)) +install: + cp libtalloc.a $(libdir) + cp talloc.h $(includedir) + cp talloc.pc $(libdir)/pkgconfig + clean: rm -f *~ *.o testsuite *.gc?? diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 5c30200118..0ebbde9fcf 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -4,4 +4,4 @@ AC_INIT(talloc.h) AC_PROG_CC AC_PATH_PROG(GCOV,gcov) sinclude(config.m4) -AC_OUTPUT(Makefile) +AC_OUTPUT(Makefile talloc.pc) diff --git a/source4/lib/talloc/talloc.pc.in b/source4/lib/talloc/talloc.pc.in new file mode 100644 index 0000000000..7f9ef754cb --- /dev/null +++ b/source4/lib/talloc/talloc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: talloc +Description: A hierarchical pool based memory system with destructors +Version: 4.0 +Libs: @LIBS@ -L${libdir} -ltalloc +Cflags: -I${includedir} @CFLAGS@ -- cgit From c878d4659b016e7f4866b0315ad8c8f4fd651a01 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Apr 2005 04:02:57 +0000 Subject: r6479: - added a simple web page - fixed configure.in ordering (This used to be commit 5a727d74d74ec23f4c33695bf5665db1ce1bc49f) --- source4/lib/ldb/autogen.sh | 7 ++++ source4/lib/ldb/configure.in | 2 +- source4/lib/ldb/web/index.html | 80 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100755 source4/lib/ldb/autogen.sh create mode 100644 source4/lib/ldb/web/index.html (limited to 'source4/lib') diff --git a/source4/lib/ldb/autogen.sh b/source4/lib/ldb/autogen.sh new file mode 100755 index 0000000000..cdd7fd2e04 --- /dev/null +++ b/source4/lib/ldb/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +(autoheader && autoconf) || exit 1 + +echo "Now run ./configure and then make." +exit 0 + diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 94afebb9f5..33269bbc76 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -1,9 +1,9 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(include/ldb.h) +AC_PROG_CC AC_FUNC_MMAP AC_PATH_PROG(YODL2MAN,yodl2man) AC_PATH_PROG(GCOV,gcov) -AC_PROG_CC sinclude(config.m4) AC_OUTPUT(Makefile) diff --git a/source4/lib/ldb/web/index.html b/source4/lib/ldb/web/index.html new file mode 100644 index 0000000000..4097aa25e4 --- /dev/null +++ b/source4/lib/ldb/web/index.html @@ -0,0 +1,80 @@ + + + +ldb + + + +

ldb

+ +ldb is a LDAP-like embedded database. It is not at all LDAP standards +complient, so if you want a standards complient database then please +see the excellent OpenLDAP +project.

+ +What ldb does is provide a fast database with an LDAP-like API +designed to be used within an application. In some ways it can be seen +as a intermediate solution between key-value pair databases and a real +LDAP database.

+ +ldb is the database engine used in Samba4. + +

Features

+ +The main features that separate ldb from other solutions are: + +
    +
  • Safe multi-reader, multi-writer, using byte range locking +
  • LDAP-like API +
  • fast operation +
  • choice of local tdb or remote LDAP backends +
  • integration with talloc +
  • schema-less operation, for trivial setup +
  • modules for extensions (such as schema support) +
  • easy setup of indexes and attribute properties +
  • ldbedit tool for database editing (reminiscent of 'vipw') +
  • ldif for import/export +
+ +

Documentation

+ +Currently ldb is completely lacking in programmer or user +documentation. This is your opportunity to make a contribution! Start +with the public functions declared in ldb.h +and the example code in the tools +directory. Documentation in the same docbook format used by Samba +would be preferred. + +

Discussion and bug reports

+ +ldb does not currently have its own mailing list or bug tracking +system. For now, please use the samba-technical +mailing list, and the Samba +bugzilla bug tracking system. + +

Download

+ +You can download the latest release either via rsync or anonymous +svn. To fetch via svn use the following command: + +
+  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/ldb ldb
+
+ +To fetch via rsync use this command: + +
+  rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/ldb .
+
+ +
+ +Andrew Tridgell
+ldb AT tridgell.net +
+ + + -- cgit From 35a2368b5a4662d08d66f2e5a2bf83fa6d1975a3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Apr 2005 04:12:29 +0000 Subject: r6480: fixed whitespace typo (This used to be commit 1265c9b8a89177db94de5a8e188b666914c1d33c) --- source4/lib/ldb/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index f07ab5a1d6..88824f031d 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -84,7 +84,7 @@ bin/ldbtest: tools/ldbtest.o $(LIBS) .yo.3: echo Creating $@ from $< -$(YODL2MAN) -o $@ `dirname $<`/`basename $< .yo` || rm -f $@ - + manpages: $(patsubst %.yo,%.3,$(wildcard man/man3/*.yo)) clean: -- cgit From 62a9924781d9d45de87796f531e63594613c86f1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Apr 2005 04:19:03 +0000 Subject: r6481: change download instructions to include tdb and talloc (This used to be commit ebe7071b2e93db93d7963211fce6ef02bc9e978e) --- source4/lib/ldb/web/index.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/web/index.html b/source4/lib/ldb/web/index.html index 4097aa25e4..02da4bf1d3 100644 --- a/source4/lib/ldb/web/index.html +++ b/source4/lib/ldb/web/index.html @@ -58,16 +58,20 @@ bugzilla bug tracking system.

Download

You can download the latest release either via rsync or anonymous -svn. To fetch via svn use the following command: +svn. To fetch via svn use the following commands:
   svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/ldb ldb
+  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb tdb
+  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc
 
-To fetch via rsync use this command: +To fetch via rsync use these commands:
   rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/ldb .
+  rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/tdb .
+  rsync -Pavz samba.org::ftp/unpacked/samba4/source/lib/talloc .
 

-- cgit From 39b2178fc998c9811636a67546d0818df6ca14c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Apr 2005 07:10:43 +0000 Subject: r6483: fix anonymous connections, '-U %' or '-U ""%""' can be used for this metze (This used to be commit d31b4d7df375c0d4ea962a0df1693778d56f03ec) --- source4/lib/cmdline/popt_common.c | 2 +- source4/lib/credentials.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 68f491a188..94b72c520d 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -197,7 +197,7 @@ static void popt_common_credentials_callback(poptContext con, cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED); - if ((lp=strchr_m(arg,'%'))) { + if (cmdline_credentials->password && (lp=strchr_m(arg,'%'))) { memset(lp,0,strlen(cmdline_credentials->password)); } } diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index f5ce886ed0..db796cde35 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -363,6 +363,11 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha { char *uname, *p; + if (strcmp("%",data) == 0) { + cli_credentials_set_anonymous(credentials); + return; + } + uname = talloc_strdup(credentials, data); if ((p = strchr_m(uname,'%'))) { *p = 0; -- cgit From d4bcee3d27974e48e94bae9d3908722596df3a62 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 26 Apr 2005 09:02:00 +0000 Subject: r6485: Move LDAP detection M4 file and use it for the standalone ldb build Remove a couple of unused M4 macros. The standalone LDB build will not work until I've figured out what AC_CHECK_LIB_EXT() does exactly (it's Samba-specific) (This used to be commit cc20d6bb7f06e077ebe4c366e545e187a0c79472) --- source4/lib/ldb/configure.in | 1 + source4/lib/ldb/ldap.m4 | 89 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 source4/lib/ldb/ldap.m4 (limited to 'source4/lib') diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 33269bbc76..9de28cbe26 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -5,5 +5,6 @@ AC_PROG_CC AC_FUNC_MMAP AC_PATH_PROG(YODL2MAN,yodl2man) AC_PATH_PROG(GCOV,gcov) +sinclude(ldap.m4) sinclude(config.m4) AC_OUTPUT(Makefile) diff --git a/source4/lib/ldb/ldap.m4 b/source4/lib/ldb/ldap.m4 new file mode 100644 index 0000000000..a9e3fb5678 --- /dev/null +++ b/source4/lib/ldb/ldap.m4 @@ -0,0 +1,89 @@ +######################################################## +# Compile with LDAP support? + +LDAP_LIBS="" +with_ldap_support=auto +AC_MSG_CHECKING([for LDAP support]) + +AC_ARG_WITH(ldap, +[ --with-ldap LDAP support (default yes)], +[ case "$withval" in + yes|no) + with_ldap_support=$withval + ;; + esac ]) + +AC_MSG_RESULT($with_ldap_support) + +if test x"$with_ldap_support" != x"no"; then + + ################################################################## + # first test for ldap.h and lber.h + # (ldap.h is required for this test) + AC_CHECK_HEADERS(ldap.h lber.h) + + if test x"$ac_cv_header_ldap_h" != x"yes"; then + if test x"$with_ldap_support" = x"yes"; then + AC_MSG_ERROR(ldap.h is needed for LDAP support) + else + AC_MSG_WARN(ldap.h is needed for LDAP support) + fi + + with_ldap_support=no + fi +fi + +if test x"$with_ldap_support" != x"no"; then + ac_save_LIBS=$LIBS + + ################################################################## + # we might need the lber lib on some systems. To avoid link errors + # this test must be before the libldap test + AC_CHECK_LIB_EXT(lber, LDAP_LIBS, ber_scanf) + + ######################################################## + # now see if we can find the ldap libs in standard paths + AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init) + + AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS) + + ######################################################## + # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? + # Check found in pam_ldap 145. + AC_CHECK_FUNC_EXT(ldap_set_rebind_proc,$LDAP_LIBS) + + LIBS="$LIBS $LDAP_LIBS" + AC_CACHE_CHECK(whether ldap_set_rebind_proc takes 3 arguments, smb_ldap_cv_ldap_set_rebind_proc, [ + AC_TRY_COMPILE([ + #include + #include ], + [ldap_set_rebind_proc(0, 0, 0);], + [smb_ldap_cv_ldap_set_rebind_proc=3], + [smb_ldap_cv_ldap_set_rebind_proc=2] + ) + ]) + + AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc]) + + AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS) + + if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then + AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available]) + with_ldap_support=yes + AC_MSG_CHECKING(whether LDAP support is used) + AC_MSG_RESULT(yes) + SMB_EXT_LIB_ENABLE(LDAP,YES) + else + if test x"$with_ldap_support" = x"yes"; then + AC_MSG_ERROR(libldap is needed for LDAP support) + else + AC_MSG_WARN(libldap is needed for LDAP support) + fi + + LDAP_LIBS="" + with_ldap_support=no + fi + LIBS=$ac_save_LIBS +fi + +SMB_EXT_LIB(LDAP,[${LDAP_LIBS}],[${LDAP_CFLAGS}],[${LDAP_CPPFLAGS}],[${LDAP_LDFLAGS}]) -- cgit From 5d794389a02d2cf9060ce3ef861366bafb9fdf66 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 26 Apr 2005 10:58:54 +0000 Subject: r6486: Add 'make install' and pkg-config file. (This used to be commit e3be094fb7b0c0fec50abcb4b242414e84a9a32d) --- source4/lib/ldb/Makefile.in | 11 +++++++++++ source4/lib/ldb/configure.in | 2 +- source4/lib/ldb/ldb.pc.in | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 source4/lib/ldb/ldb.pc.in (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 88824f031d..8b5e66fd75 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -1,6 +1,11 @@ CC = @CC@ GCOV = @GCOV@ YODL2MAN = @YODL2MAN@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +bindir = @bindir@ ifeq ($(WITH_LDAP),1) OPENLDAP_PREFIX=/usr @@ -107,6 +112,12 @@ test-schema: test: test-tdb test-ldap test-schema +install: all + cp include/ldb.h $(includedir) + cp $(LDB_LIB) $(libdir) + cp $(BINS) $(bindir) + cp ldb.pc $(libdir)/pkgconfig + gcov: $(GCOV) -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov $(GCOV) -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 9de28cbe26..74b25577b9 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -7,4 +7,4 @@ AC_PATH_PROG(YODL2MAN,yodl2man) AC_PATH_PROG(GCOV,gcov) sinclude(ldap.m4) sinclude(config.m4) -AC_OUTPUT(Makefile) +AC_OUTPUT(Makefile ldb.pc) diff --git a/source4/lib/ldb/ldb.pc.in b/source4/lib/ldb/ldb.pc.in new file mode 100644 index 0000000000..e524fbed36 --- /dev/null +++ b/source4/lib/ldb/ldb.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: ldb +Description: An LDAP-like embedded database +Version: 4.0 +Libs: @LIBS@ -L${libdir} -lldb +Cflags: -I${includedir} @CFLAGS@ -- cgit From 90be367a18af0afad598d3c62d5b39238ed591a4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 26 Apr 2005 11:10:55 +0000 Subject: r6487: Use autoconf for standalone build of tdb (This used to be commit 78bf8026bde34b7accc78f07c940ef1dcfc0dea7) --- source4/lib/ldb/autogen.sh | 2 +- source4/lib/tdb/autogen.sh | 7 +++++++ source4/lib/tdb/tdb.pc.in | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100755 source4/lib/tdb/autogen.sh create mode 100644 source4/lib/tdb/tdb.pc.in (limited to 'source4/lib') diff --git a/source4/lib/ldb/autogen.sh b/source4/lib/ldb/autogen.sh index cdd7fd2e04..94148edf69 100755 --- a/source4/lib/ldb/autogen.sh +++ b/source4/lib/ldb/autogen.sh @@ -1,6 +1,6 @@ #!/bin/sh -(autoheader && autoconf) || exit 1 +autoconf || exit 1 echo "Now run ./configure and then make." exit 0 diff --git a/source4/lib/tdb/autogen.sh b/source4/lib/tdb/autogen.sh new file mode 100755 index 0000000000..94148edf69 --- /dev/null +++ b/source4/lib/tdb/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +autoconf || exit 1 + +echo "Now run ./configure and then make." +exit 0 + diff --git a/source4/lib/tdb/tdb.pc.in b/source4/lib/tdb/tdb.pc.in new file mode 100644 index 0000000000..0d54afe242 --- /dev/null +++ b/source4/lib/tdb/tdb.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: tdb +Description: A trivial database +Version: 4.0 +#Libs: @LIBS@ -L${libdir} -ltdb +Cflags: -I${includedir} @CFLAGS@ -- cgit From a53548d0741421b57b450d3ef62d3ac42c233030 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Apr 2005 14:54:17 +0000 Subject: r6513: Commit talloc_free_children. Volker (This used to be commit 9fa26d2c971a7baee64d8938e31909cac80f0e5a) --- source4/lib/talloc/talloc.c | 57 ++++++++++++++++++++++++------------- source4/lib/talloc/talloc_guide.txt | 8 ++++++ 2 files changed, 45 insertions(+), 20 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 661282a87d..da3a2300b0 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -461,6 +461,42 @@ void *talloc_init(const char *fmt, ...) return ptr; } +/* + this is a replacement for the Samba3 talloc_destroy_pool functionality. It + should probably not be used in new code. It's in here to keep the talloc + code consistent across Samba 3 and 4. +*/ +void talloc_free_children(void *ptr) +{ + struct talloc_chunk *tc; + + if (ptr == NULL) { + return; + } + + tc = talloc_chunk_from_ptr(ptr); + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = tc->child+1; + const void *new_parent = null_context; + if (tc->child->refs) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = p+1; + } + if (talloc_free(child) == -1) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = p+1; + } + talloc_steal(new_parent, child); + } + } +} /* free a talloc pointer. This also frees all child pointers of this @@ -498,26 +534,7 @@ int talloc_free(void *ptr) tc->destructor = NULL; } - while (tc->child) { - /* we need to work out who will own an abandoned child - if it cannot be freed. In priority order, the first - choice is owner of any remaining reference to this - pointer, the second choice is our parent, and the - final choice is the null context. */ - void *child = tc->child+1; - const void *new_parent = null_context; - if (tc->child->refs) { - struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; - } - if (talloc_free(child) == -1) { - if (new_parent == null_context) { - struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; - } - talloc_steal(new_parent, child); - } - } + talloc_free_children(ptr); if (tc->parent) { _TLIST_REMOVE(tc->parent->child, tc); diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 7d6dfa5cb2..55349ec05b 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -105,6 +105,14 @@ For more control on which parent is removed, see talloc_unlink() talloc_free() operates recursively on its children. +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +int talloc_free_children(void *ptr); + +The talloc_free_children() walks along the list of all children of a +talloc context and talloc_free()s only the children, not the context +itself. + + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- void *talloc_reference(const void *context, const void *ptr); -- cgit From 1403bb7e62d5cf3afe0a108acafb6410d614bd71 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 30 Apr 2005 04:46:17 +0000 Subject: r6520: Fix unused variable warning. (This used to be commit 36de31a63189dcc6126dd0c10b1af8d183d8c235) --- source4/lib/registry/reg_backend_ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index fc01de61a5..5f4e296edf 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -99,7 +99,7 @@ static int reg_close_ldb_key (void *data) { struct registry_key *key = data; struct ldb_key_data *kd = key->backend_data; - struct ldb_context *c = key->hive->backend_data; +/* struct ldb_context *c = key->hive->backend_data; */ if (kd->subkeys) { talloc_free(kd->subkeys); -- cgit From 98549af7bf1932bbc78a07053f193b24bd8685f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 30 Apr 2005 09:04:14 +0000 Subject: r6528: - in tdb_fetch() we effectively disallowed zero length records by returning NULL/0, which is the same as we used for a failure. Having to look at tdb->ecode (which we never do) is too error prone. Instead, tdb_fetch() should behave like malloc() and talloc(), where zero length is not special and malloc(0) returns a valid pointer. - similarly in data_blob(), asking for data_blob(NULL, 0) should return a zero blob, but asking for data_blob(ptr, 0) should return a zero length blob with a valid pointer, just like talloc() and malloc() This change fixes the SummaryInformation stream stored in the tdb backend when manipulated from w2k. The w2k client was using SET_EOF_INFORMATION to create a zero-length stream, which we return STATUS_NOT_FOUND on, as the tdb_fetch() gave us back a NULL/0 blob, which we returned as not-found (This used to be commit 162bbe4402b9de6ac06103df904b9fc204fbff29) --- source4/lib/data_blob.c | 2 +- source4/lib/tdb/common/tdb.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 284db4518f..2ec21717b1 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -29,7 +29,7 @@ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) { DATA_BLOB ret; - if (length == 0) { + if (p == NULL && length == 0) { ZERO_STRUCT(ret); return ret; } diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 6554ec5697..670fdda7cd 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1129,8 +1129,8 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db /* find an entry in the database given a key */ /* If an entry doesn't exist tdb_err will be set to * TDB_ERR_NOEXIST. If a key has no data attached - * tdb_err will not be set. Both will return a - * zero pptr and zero dsize. + * then the TDB_DATA will have zero length but + * a non-zero pointer */ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) @@ -1145,11 +1145,8 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; - if (rec.data_len) - ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - else - ret.dptr = NULL; + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); ret.dsize = rec.data_len; tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); return ret; -- cgit From dfaa7a3baeafa401c5ee3490ef11f23870f65cf1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 1 May 2005 09:04:51 +0000 Subject: r6546: Fix ldb standalone build Add autoconf to tdb (This used to be commit 95fed657f458a856feec2fb256edd642e4179979) --- source4/lib/ldb/Makefile.in | 7 +++++-- source4/lib/ldb/configure.in | 15 +++++++++++++++ source4/lib/tdb/Makefile.in | 39 +++++++++++++++++++++++++++++++++++++++ source4/lib/tdb/Makefile.tdb | 29 ----------------------------- source4/lib/tdb/configure.in | 7 +++++++ 5 files changed, 66 insertions(+), 31 deletions(-) create mode 100644 source4/lib/tdb/Makefile.in delete mode 100644 source4/lib/tdb/Makefile.tdb create mode 100644 source4/lib/tdb/configure.in (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 8b5e66fd75..eedab96ef2 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -6,6 +6,7 @@ exec_prefix = @exec_prefix@ includedir = @includedir@ libdir = @libdir@ bindir = @bindir@ +WITH_GCOV = @WITH_GCOV@ ifeq ($(WITH_LDAP),1) OPENLDAP_PREFIX=/usr @@ -22,8 +23,10 @@ CFLAGS1=-Wall -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ -I$(TDBDIR)/include -I$(TALLOCDIR) -DUSE_MMAP=1 $(LDAP_FLAGS) # enable the following two lines to build with gcov code coverage support -#GCOV_FLAGS = -ftest-coverage -fprofile-arcs -#GCOV_LIBS = -lgcov +ifeq ($(WITH_GCOV),1) +GCOV_FLAGS = -ftest-coverage -fprofile-arcs +GCOV_LIBS = -lgcov +endif CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) @CFLAGS@ diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 74b25577b9..26b39e684a 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -1,6 +1,21 @@ +AC_DEFUN([AC_CHECK_LIB_EXT], [ + AC_CHECK_LIB([$1],[$3],[$4],[$5],[$7]) + ac_cv_lib_ext_$1_$3=$ac_cv_lib_$1_$3 +]) +AC_DEFUN([AC_CHECK_FUNC_EXT], [ + AC_CHECK_FUNC([$1],[$3],[$4]) + ac_cv_func_ext_$1=$ac_cv_func_$1 +]) AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) +AC_DEFUN([SMB_EXT_LIB_ENABLE], [echo -n ""]) +AC_DEFUN([SMB_EXT_LIB], [echo -n ""]) AC_INIT(include/ldb.h) +WITH_GCOV=0 +AC_ARG_ENABLE(gcov, + [ --enable-gcov Enable GCOV code coverage tests], + [ WITH_GCOV=1]) +AC_SUBST(WITH_GCOV) AC_PROG_CC AC_FUNC_MMAP AC_PATH_PROG(YODL2MAN,yodl2man) diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in new file mode 100644 index 0000000000..f9912cd6b1 --- /dev/null +++ b/source4/lib/tdb/Makefile.in @@ -0,0 +1,39 @@ +# +# Makefile for tdb directory +# + +CFLAGS = -DTDB_DEBUG -g -Iinclude +CC = @CC@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +includedir = @includedir@ +libdir = @libdir@ + +PROGS = bin/tdbtest bin/tdbtool bin/tdbtorture +TDB_OBJ = common/tdb.o common/spinlock.o + +all: $(PROGS) + +install: all + cp $(PROGS) $(bindir) + cp include/tdb.h $(includedir) + cp tdb.pc $(libdir)/pkgconfig + +bin/tdbtest: tools/tdbtest.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm + +bin/tdbtool: tools/tdbtool.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbtool tools/tdbtool.o $(TDB_OBJ) + +bin/tdbtorture: tools/tdbtorture.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbtorture tools/tdbtorture.o $(TDB_OBJ) + +bin/tdbdump: tools/tdbdump.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbdump tools/tdbdump.o $(TDB_OBJ) + +bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) + $(CC) $(CFLAGS) -o bin/tdbbackup tools/tdbbackup.o $(TDB_OBJ) + +clean: + rm -f $(PROGS) common/*.o tools/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm diff --git a/source4/lib/tdb/Makefile.tdb b/source4/lib/tdb/Makefile.tdb deleted file mode 100644 index ee612bfb63..0000000000 --- a/source4/lib/tdb/Makefile.tdb +++ /dev/null @@ -1,29 +0,0 @@ -# -# Makefile for tdb directory -# - -CFLAGS = -DTDB_DEBUG -g -DHAVE_MMAP=1 -Iinclude -CC = gcc - -PROGS = bin/tdbtest bin/tdbtool bin/tdbtorture -TDB_OBJ = common/tdb.o common/spinlock.o - -all: $(PROGS) - -bin/tdbtest: tools/tdbtest.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o bin/tdbtest tools/tdbtest.o $(TDB_OBJ) -lgdbm - -bin/tdbtool: tools/tdbtool.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o bin/tdbtool tools/tdbtool.o $(TDB_OBJ) - -bin/tdbtorture: tools/tdbtorture.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o bin/tdbtorture tools/tdbtorture.o $(TDB_OBJ) - -bin/tdbdump: tools/tdbdump.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o bin/tdbdump tools/tdbdump.o $(TDB_OBJ) - -bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) - $(CC) $(CFLAGS) -o bin/tdbbackup tools/tdbbackup.o $(TDB_OBJ) - -clean: - rm -f $(PROGS) common/*.o tools/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm diff --git a/source4/lib/tdb/configure.in b/source4/lib/tdb/configure.in new file mode 100644 index 0000000000..b47b43f0ed --- /dev/null +++ b/source4/lib/tdb/configure.in @@ -0,0 +1,7 @@ +AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) +AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) +AC_INIT(include/tdb.h) +AC_PROG_CC +AC_FUNC_MMAP +sinclude(config.m4) +AC_OUTPUT(Makefile tdb.pc) -- cgit From 425350bb618b7168de1d5d808c9ac5a76d84fcf0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 May 2005 12:34:12 +0000 Subject: r6560: added a tdb_chainlock_read() call in ldb_search(). This guarantees that ldb_search() sees a single consistent view of the database (by blocking writes during a ldb_search) (This used to be commit 917f2a8a073fd501f0626bea4f9deb91b95fdc90) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 7 +++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 34 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 ++ 3 files changed, 43 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 4f45fdf376..7883ee6e7b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -472,9 +472,14 @@ int ltdb_search(struct ldb_module *module, const char *base, struct ldb_parse_tree *tree; int ret; + if (ltdb_lock_read(module) != 0) { + return -1; + } + ltdb->last_err_string = NULL; if (ltdb_cache_load(module) != 0) { + ltdb_unlock_read(module); return -1; } @@ -484,6 +489,7 @@ int ltdb_search(struct ldb_module *module, const char *base, tree = ldb_parse_tree(ldb, expression); if (!tree) { ltdb->last_err_string = "expression parse failed"; + ltdb_unlock_read(module); return -1; } @@ -501,6 +507,7 @@ int ltdb_search(struct ldb_module *module, const char *base, } ldb_parse_tree_free(ldb, tree); + ltdb_unlock_read(module); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 87582cf4eb..b47d79de52 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -248,6 +248,40 @@ static int ltdb_unlock(struct ldb_module *module, const char *lockname) } +/* + lock the database for read - use by ltdb_search +*/ +int ltdb_lock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + TDB_DATA key; + int ret; + key = ltdb_key(module, LDBLOCK); + if (!key.dptr) { + return -1; + } + ret = tdb_chainlock_read(ltdb->tdb, key); + talloc_free(key.dptr); + return ret; +} + +/* + unlock the database after a ltdb_lock_read() +*/ +int ltdb_unlock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + TDB_DATA key; + key = ltdb_key(module, LDBLOCK); + if (!key.dptr) { + return -1; + } + tdb_chainunlock_read(ltdb->tdb, key); + talloc_free(key.dptr); + return 0; +} + + /* we've made a modification to a dn - possibly reindex and update sequence number diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 9fb60b6359..dfb985319e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -104,6 +104,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn); int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); int ltdb_delete_noindex(struct ldb_module *module, const char *dn); int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); +int ltdb_lock_read(struct ldb_module *module); +int ltdb_unlock_read(struct ldb_module *module); /* The following definitions come from lib/ldb/ldb_tdb/ldb_match.c */ int ltdb_val_equal(struct ldb_module *module, -- cgit From 7282ddda0a38139fa457e6451f100f6d1792d927 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 May 2005 18:49:07 +0000 Subject: r6561: re-did the internal message system based on DGRAM unix domain sockets. This gains us about 40% in messaging speed. (This used to be commit f244a64ed537447e44229172427b5b6a5c64800c) --- source4/lib/messaging/messaging.c | 202 ++++++++++++-------------------------- 1 file changed, 64 insertions(+), 138 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 8127e7e8fc..c95028bea5 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -34,10 +34,13 @@ /* the number of microseconds to backoff in retrying to send a message */ #define MESSAGING_BACKOFF 250000 +/* maximum message size */ +#define MESSAGING_MAX_SIZE 512 + struct messaging_context { uint32_t server_id; struct socket_context *sock; - char *path; + const char *path; struct dispatch_fn *dispatch; struct { @@ -60,7 +63,6 @@ struct dispatch_fn { struct messaging_rec { struct messaging_context *msg; struct socket_context *sock; - struct fd_event *fde; const char *path; struct { @@ -72,8 +74,6 @@ struct messaging_rec { } header; DATA_BLOB data; - - uint32_t ndone; }; /* @@ -112,112 +112,58 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r } } - /* we don't free the record itself here as there may - be more messages from this client */ - data_blob_free(&rec->data); rec->header.length = 0; - rec->ndone = 0; } /* - handle IO for a single message + handle a new incoming connection */ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *private) { - struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); - struct messaging_context *msg = rec->msg; + struct messaging_context *msg = talloc_get_type(private, + struct messaging_context); + struct messaging_rec *rec; NTSTATUS status; + uint8_t data[MESSAGING_MAX_SIZE]; + size_t msize; - if (rec->ndone < sizeof(rec->header)) { - /* receive the header */ - size_t nread; - - status = socket_recv(rec->sock, - rec->ndone + (char *)&rec->header, - sizeof(rec->header) - rec->ndone, &nread, 0); - if (NT_STATUS_IS_ERR(status)) { - talloc_free(rec); - return; - } - - if (nread == 0) { - return; - } - - rec->ndone += nread; - - if (rec->ndone == sizeof(rec->header)) { - if (rec->header.version != MESSAGING_VERSION) { - DEBUG(0,("meessage with wrong version %u\n", - rec->header.version)); - talloc_free(rec); - } - rec->data = data_blob_talloc(rec, NULL, rec->header.length); - if (rec->data.length != rec->header.length) { - DEBUG(0,("Unable to allocate message of size %u\n", - rec->header.length)); - talloc_free(rec); - } - } - } - - if (rec->ndone >= sizeof(rec->header) && - rec->ndone < sizeof(rec->header) + rec->header.length) { - /* receive the body, if any */ - size_t nread; - - status = socket_recv(rec->sock, - rec->data.data + (rec->ndone - sizeof(rec->header)), - sizeof(rec->header) + rec->header.length - rec->ndone, - &nread, 0); - if (NT_STATUS_IS_ERR(status)) { - talloc_free(rec); - return; - } - - if (nread == 0) { - return; - } - - rec->ndone += nread; + status = socket_recv(msg->sock, data, sizeof(data), &msize, 0); + if (!NT_STATUS_IS_OK(status)) { + return; } - if (rec->ndone == sizeof(rec->header) + rec->header.length) { - /* we've got the whole message */ - messaging_dispatch(msg, rec); + if (msize < sizeof(rec->header)) { + DEBUG(0,("messaging: bad message of size %d\n", msize)); + return; } -} - -/* - handle a new incoming connection -*/ -static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) -{ - struct messaging_context *msg = talloc_get_type(private, - struct messaging_context); - struct messaging_rec *rec; - NTSTATUS status; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { smb_panic("Unable to allocate messaging_rec"); } - status = socket_accept(msg->sock, &rec->sock); - if (!NT_STATUS_IS_OK(status)) { - smb_panic("Unable to accept messaging_rec"); - } - talloc_steal(rec, rec->sock); - rec->msg = msg; - rec->ndone = 0; - rec->header.length = 0; rec->path = msg->path; - rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), - EVENT_FD_READ, messaging_recv_handler, rec); + rec->sock = NULL; + + memcpy(&rec->header, data, sizeof(rec->header)); + if (msize != sizeof(rec->header) + rec->header.length) { + DEBUG(0,("messaging: bad message header size %d should be %d\n", + rec->header.length, msize - sizeof(rec->header))); + talloc_free(rec); + return; + } + + rec->data = data_blob_talloc(rec, data, rec->header.length); + if (rec->data.data == NULL) { + talloc_free(rec); + return; + } + + messaging_dispatch(msg, rec); + talloc_free(rec); } /* @@ -262,49 +208,28 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd uint16_t flags, void *private) { struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); + uint8_t data[MESSAGING_MAX_SIZE]; + DATA_BLOB blob; + size_t nsent; NTSTATUS status; - if (rec->ndone < sizeof(rec->header)) { - /* send the header */ - size_t nsent; - DATA_BLOB blob; - - blob.data = rec->ndone + (uint8_t *)&rec->header; - blob.length = sizeof(rec->header) - rec->ndone; - - status = socket_send(rec->sock, &blob, &nsent, 0); - if (NT_STATUS_IS_ERR(status)) { - talloc_free(rec); - return; - } - - if (nsent == 0) { - return; - } - - rec->ndone += nsent; - } - - if (rec->ndone >= sizeof(rec->header) && - rec->ndone < sizeof(rec->header) + rec->header.length) { - /* send the body, if any */ - DATA_BLOB blob; - size_t nsent; - - blob.data = rec->data.data + (rec->ndone - sizeof(rec->header)); - blob.length = rec->header.length - (rec->ndone - sizeof(rec->header)); + memcpy(data, &rec->header, sizeof(rec->header)); + memcpy(data + sizeof(rec->header), rec->data.data, rec->data.length); - status = socket_send(rec->sock, &blob, &nsent, 0); - if (NT_STATUS_IS_ERR(status)) { - talloc_free(rec); - return; - } + blob.data = data; + blob.length = sizeof(rec->header) + rec->header.length; - rec->ndone += nsent; + status = socket_send(rec->sock, &blob, &nsent, 0); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3,("Unable to send message of type %d length %d - %s\n", + rec->header.msg_type, + rec->header.length, + nt_errstr(status))); + talloc_free(rec); + return; } - if (rec->ndone == sizeof(rec->header) + rec->header.length) { - /* we've done the whole message */ + if (NT_STATUS_IS_OK(status)) { talloc_free(rec); } } @@ -349,8 +274,8 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve return; } - rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), - EVENT_FD_WRITE, messaging_send_handler, rec); + event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); } @@ -378,9 +303,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t } else { rec->data = data_blob(NULL, 0); } - rec->ndone = 0; - status = socket_create("unix", SOCKET_TYPE_STREAM, &rec->sock, 0); + status = socket_create("unix", SOCKET_TYPE_DGRAM, &rec->sock, 0); if (!NT_STATUS_IS_OK(status)) { talloc_free(rec); return status; @@ -403,8 +327,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t return status; } - rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), - EVENT_FD_WRITE, messaging_send_handler, rec); + event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); return NT_STATUS_OK; } @@ -437,10 +361,12 @@ static int messaging_destructor(void *ptr) /* create the listening socket and setup the dispatcher */ -struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id, struct event_context *ev) +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id, + struct event_context *ev) { struct messaging_context *msg; NTSTATUS status; + char *path; msg = talloc(mem_ctx, struct messaging_context); if (msg == NULL) { @@ -448,15 +374,15 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id } /* create the messaging directory if needed */ - msg->path = smbd_tmp_path(msg, "messaging"); - mkdir(msg->path, 0700); - talloc_free(msg->path); + path = smbd_tmp_path(msg, "messaging"); + mkdir(path, 0700); + talloc_free(path); + msg->path = messaging_path(msg, server_id); msg->server_id = server_id; msg->dispatch = NULL; - msg->path = messaging_path(msg, server_id); - status = socket_create("unix", SOCKET_TYPE_STREAM, &msg->sock, 0); + status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0); if (!NT_STATUS_IS_OK(status)) { talloc_free(msg); return NULL; @@ -475,7 +401,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id msg->event.ev = talloc_reference(msg, ev); msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock), - EVENT_FD_READ, messaging_listen_handler, msg); + EVENT_FD_READ, messaging_recv_handler, msg); talloc_set_destructor(msg, messaging_destructor); -- cgit From b2584a403c6382ef478755979d955043fc9569a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 1 May 2005 18:49:43 +0000 Subject: r6562: added support for datagram unix domain sockets in the socket library (This used to be commit 23b2046dcb5c4593cba6964f400a2e5246fb35f7) --- source4/lib/socket/socket.c | 3 ++- source4/lib/socket/socket_unix.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index ddc2097f42..86e2f05962 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -159,7 +159,8 @@ NTSTATUS socket_recv(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags) { if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && - sock->state != SOCKET_STATE_SERVER_CONNECTED) { + sock->state != SOCKET_STATE_SERVER_CONNECTED && + sock->type != SOCKET_TYPE_DGRAM) { return NT_STATUS_INVALID_PARAMETER; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 614229aaac..3f265f7214 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -38,9 +38,22 @@ static NTSTATUS unixdom_error(int ernum) static NTSTATUS unixdom_init(struct socket_context *sock) { - sock->fd = socket(PF_UNIX, SOCK_STREAM, 0); + int type; + + switch (sock->type) { + case SOCKET_TYPE_STREAM: + type = SOCK_STREAM; + break; + case SOCKET_TYPE_DGRAM: + type = SOCK_DGRAM; + break; + default: + return NT_STATUS_INVALID_PARAMETER; + } + + sock->fd = socket(PF_UNIX, type, 0); if (sock->fd == -1) { - return NT_STATUS_INSUFFICIENT_RESOURCES; + return map_nt_error_from_unix(errno); } sock->private_data = NULL; @@ -126,9 +139,11 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, return unixdom_error(errno); } - ret = listen(sock->fd, queue_size); - if (ret == -1) { - return unixdom_error(errno); + if (sock->type == SOCKET_TYPE_STREAM) { + ret = listen(sock->fd, queue_size); + if (ret == -1) { + return unixdom_error(errno); + } } if (!(flags & SOCKET_FLAG_BLOCK)) { @@ -151,6 +166,10 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, socklen_t cli_addr_len = sizeof(cli_addr); int new_fd; + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { return unixdom_error(errno); @@ -290,8 +309,5 @@ static const struct socket_ops unixdom_ops = { const struct socket_ops *socket_unixdom_ops(enum socket_type type) { - if (type != SOCKET_TYPE_STREAM) { - return NULL; - } return &unixdom_ops; } -- cgit From 7fca1d46cea38229faf9a7092d86a452658f2ca0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 1 May 2005 19:08:35 +0000 Subject: r6564: - Fix bug in socket_wrapper - Add options --quiet and --outputdir options to the provisioning script - Add simple 'make test' and 'make test-swrap' (This used to be commit 7d2d4a57e0e58a51c76c2e86ea447e81a1d79544) --- source4/lib/socket_wrapper/socket_wrapper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 4814f6c929..2a26ba1534 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -249,7 +249,8 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) } /* only allow pseudo loopback connections */ - if (((const struct sockaddr_in *)serv_addr)->sin_addr.s_addr != + if (serv_addr->sa_family == AF_INET && + ((const struct sockaddr_in *)serv_addr)->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { errno = ENETUNREACH; return -1; -- cgit From 85e9412c4786ede6f94d879185d493756d37eebe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 1 May 2005 19:29:00 +0000 Subject: r6565: Cludge, cludge, cludge... We need to pass the 'secure channel type' to the NETLOGON layer, which must match the account type. (Yes, jelmer objects to this inclusion of the kitchen sink ;-) Andrew Bartlett (This used to be commit 8ee208a926d2b15fdc42753b1f9ee586564c6248) --- source4/lib/credentials.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index db796cde35..64e3b9958d 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -465,6 +465,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) const char *password; const char *domain; const char *realm; + enum netr_SchannelType sct; /* ok, we are going to get it now, don't recurse back here */ cred->machine_account_pending = False; @@ -510,6 +511,15 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } + sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0); + if (!sct) { + cli_credentials_set_secure_channel_type(cred, sct); + } else { + DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n", + machine_account)); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + domain = ldb_msg_find_string(msgs[0], "flatname", NULL); if (domain) { cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); @@ -519,7 +529,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) if (realm) { cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); } - + cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); cli_credentials_set_password(cred, password, CRED_SPECIFIED); talloc_free(mem_ctx); @@ -560,6 +570,25 @@ struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_cred return cred->netlogon_creds; } +/** + * Set NETLOGON secure channel type + */ + +void cli_credentials_set_secure_channel_type(struct cli_credentials *cred, + enum netr_SchannelType secure_channel_type) +{ + cred->secure_channel_type = secure_channel_type; +} + +/** + * Return NETLOGON secure chanel type + */ + +enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred) +{ + return cred->secure_channel_type; +} + /** * Fill in a credentials structure as the anonymous user */ -- cgit From 8bf57cf8f57be28831023c2218d358b24b705256 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2005 14:17:19 +0000 Subject: r6573: Start on my project to implement an NT4 compatible BDC in Samba4. This brings in a compatability layer for Samba3 in Samba4 - where we will start to define file formats and similar details. The 'net samdump' command uses 'password server = ' for now, and performs a similar task to Samba3's 'net rpc samsync'. Andrew Bartlett (This used to be commit 550f17f9924fe783917318753de7d1a388423908) --- source4/lib/basic.mk | 9 ++ source4/lib/credentials.c | 3 +- source4/lib/samba3/README | 5 + source4/lib/samba3/smbpasswd.c | 208 +++++++++++++++++++++++++++++++++++++++++ source4/lib/util_str.c | 1 + 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 source4/lib/samba3/README create mode 100644 source4/lib/samba3/smbpasswd.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index f0b2b05b6a..c1a34d39bb 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -40,6 +40,15 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBCOMPRESION ################################################ + +################################################ +# Start SUBSYSTEM LIBSAMBA3 +[SUBSYSTEM::LIBSAMBA3] +INIT_OBJ_FILES = \ + lib/samba3/smbpasswd.o +# End SUBSYSTEM LIBSAMBA3 +################################################ + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 64e3b9958d..7e25fc780b 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -458,6 +458,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) "samAccountName", "flatname", "realm", + "secureChannelType", NULL }; @@ -512,7 +513,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0); - if (!sct) { + if (sct) { cli_credentials_set_secure_channel_type(cred, sct); } else { DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n", diff --git a/source4/lib/samba3/README b/source4/lib/samba3/README new file mode 100644 index 0000000000..cf55be047a --- /dev/null +++ b/source4/lib/samba3/README @@ -0,0 +1,5 @@ +This directory contains various files and functions for the purpose of +Samba3 import, migration and compatability. + +For example, the first file in this directory (smbpasswd.c) handles +portions of the smbpasswd file format. diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c new file mode 100644 index 0000000000..587d038a3d --- /dev/null +++ b/source4/lib/samba3/smbpasswd.c @@ -0,0 +1,208 @@ +/* + Unix SMB/CIFS implementation. + smbpasswd file format routines + + Copyright (C) Andrew Tridgell 1992-1998 + Modified by Jeremy Allison 1995. + Modified by Gerald (Jerry) Carter 2000-2001 + Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/*! \file lib/smbpasswd.c + + The smbpasswd file is used to store encrypted passwords in a similar + fashion to the /etc/passwd file. The format is colon separated fields + with one user per line like so: + + ::::: + + The username and uid must correspond to an entry in the /etc/passwd + file. The lanman and nt password hashes are 32 hex digits corresponding + to the 16-byte lanman and nt hashes respectively. + + The password last change time is stored as a string of the format + LCD- where the change time is expressed as an + + 'N' No password + 'D' Disabled + 'H' Homedir required + 'T' Temp account. + 'U' User account (normal) + 'M' MNS logon user account - what is this ? + 'W' Workstation account + 'S' Server account + 'L' Locked account + 'X' No Xpiry on password + 'I' Interdomain trust account + +*/ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_samr.h" +#include "system/iconv.h" + +/*! Convert 32 hex characters into a 16 byte array. */ + +struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, char *p) +{ + int i; + unsigned char lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password); + + if (!p) return NULL; + + for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2) + { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); + + p1 = strchr_m(hexchars, hinybble); + p2 = strchr_m(hexchars, lonybble); + + if (!p1 || !p2) + { + return (False); + } + + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + pwd->hash[i / 2] = (hinybble << 4) | lonybble; + } + return pwd; +} + +/*! Convert a 16-byte array into 32 hex characters. */ + struct samr_Password *lm_hash_p = NULL; + struct samr_Password *nt_hash_p = NULL; + +char *smbpasswd_sethexpwd(TALLOC_CTX *mem_ctx, struct samr_Password *pwd, uint16_t acb_info) +{ + char *p; + if (pwd != NULL) { + int i; + p = talloc_array(mem_ctx, char, 33); + if (!p) { + return NULL; + } + + for (i = 0; i < sizeof(pwd->hash); i++) + slprintf(&p[i*2], 3, "%02X", pwd->hash[i]); + } else { + if (acb_info & ACB_PWNOTREQ) + p = talloc_strdup(mem_ctx, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + else + p = talloc_strdup(mem_ctx, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + return p; +} + +/*! Decode the account control bits (ACB) info from a string. */ + +uint16_t smbpasswd_decode_acb_info(const char *p) +{ + uint16_t acb_info = 0; + BOOL finished = False; + + /* + * Check if the account type bits have been encoded after the + * NT password (in the form [NDHTUWSLXI]). + */ + + if (*p != '[') return 0; + + for (p++; *p && !finished; p++) + { + switch (*p) { + case 'N': /* 'N'o password. */ + acb_info |= ACB_PWNOTREQ; + break; + case 'D': /* 'D'isabled. */ + acb_info |= ACB_DISABLED; + break; + case 'H': /* 'H'omedir required. */ + acb_info |= ACB_HOMDIRREQ; + break; + case 'T': /* 'T'emp account. */ + acb_info |= ACB_TEMPDUP; + break; + case 'U': /* 'U'ser account (normal). */ + acb_info |= ACB_NORMAL; + break; + case 'M': /* 'M'NS logon user account. What is this ? */ + acb_info |= ACB_MNS; + break; + case 'W': /* 'W'orkstation account. */ + acb_info |= ACB_WSTRUST; + break; + case 'S': /* 'S'erver account. */ + acb_info |= ACB_SVRTRUST; + break; + case 'L': /* 'L'ocked account. */ + acb_info |= ACB_AUTOLOCK; + break; + case 'X': /* No 'X'piry on password */ + acb_info |= ACB_PWNOEXP; + break; + case 'I': /* 'I'nterdomain trust account. */ + acb_info |= ACB_DOMTRUST; + break; + + case ' ': + break; + case ':': + case '\n': + case '\0': + case ']': + default: + finished = True; + break; + } + } + + return acb_info; +} + +/*! Encode account control bits (ACBs) into a string. */ + +char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info) +{ + char *acct_str = talloc_array(mem_ctx, char, 35); + size_t i = 0; + + acct_str[i++] = '['; + + if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N'; + if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D'; + if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H'; + if (acb_info & ACB_TEMPDUP ) acct_str[i++] = 'T'; + if (acb_info & ACB_NORMAL ) acct_str[i++] = 'U'; + if (acb_info & ACB_MNS ) acct_str[i++] = 'M'; + if (acb_info & ACB_WSTRUST ) acct_str[i++] = 'W'; + if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S'; + if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L'; + if (acb_info & ACB_PWNOEXP ) acct_str[i++] = 'X'; + if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I'; + + acct_str[i++] = ']'; + acct_str[i++] = '\0'; + + return acct_str; +} diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index dc39da50c7..5d12a01f6e 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -395,6 +395,7 @@ char *StrnCpy(char *dest,const char *src,size_t n) valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + **/ size_t strhex_to_str(char *p, size_t len, const char *strhex) { -- cgit From fc5c075cff223d36f25b79650c3f739e8d79a801 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 2 May 2005 15:58:03 +0000 Subject: r6578: brown paper bag time with the new messaging code .... (This used to be commit d465ff67bd10340ecd46480039f483daa82c7ebe) --- source4/lib/messaging/messaging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index c95028bea5..2130958b36 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -156,7 +156,7 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd return; } - rec->data = data_blob_talloc(rec, data, rec->header.length); + rec->data = data_blob_talloc(rec, data+sizeof(rec->header), rec->header.length); if (rec->data.data == NULL) { talloc_free(rec); return; -- cgit From aed008c98988d70564f621c48b8ee51bdafaaf91 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 5 May 2005 11:13:16 +0000 Subject: r6617: Let --enable-developer imply --enable-socket-wrapper Add socket-wrapper-enabled test target and use that by default when the socket wrapper was included (This used to be commit d3b0ad8b4b6f8ee80a9c77e1102960d51ced5a5f) --- source4/lib/socket_wrapper/config.m4 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/config.m4 b/source4/lib/socket_wrapper/config.m4 index 97984d0436..69024c869d 100644 --- a/source4/lib/socket_wrapper/config.m4 +++ b/source4/lib/socket_wrapper/config.m4 @@ -1,5 +1,15 @@ AC_ARG_ENABLE(socket-wrapper, -[ --enable-socket-wrapper Turn on socket wrapper library (default=no)], - [if eval "test x$enable_socket_wrapper = xyes"; then +[ --enable-socket-wrapper Turn on socket wrapper library (default=no)]) + +DEFAULT_TEST_TARGET=test-noswrap + +if eval "test x$developer = xyes"; then + enable_socket_wrapper=yes +fi + +if eval "test x$enable_socket_wrapper = xyes"; then AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library]) - fi]) + DEFAULT_TEST_TARGET=test-swrap +fi + +AC_SUBST(DEFAULT_TEST_TARGET) -- cgit From 6b68d5eb7b4fecc923dc1c0ab6f387c525f46b7c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 5 May 2005 11:33:10 +0000 Subject: r6621: Warn when the user is trying to use socket wrapper while it is not compiled in. (This used to be commit d63086918ba79307089b3992dc7ed8fc8c6d18a8) --- source4/lib/socket_wrapper/config.m4 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/config.m4 b/source4/lib/socket_wrapper/config.m4 index 69024c869d..dc4523a8cf 100644 --- a/source4/lib/socket_wrapper/config.m4 +++ b/source4/lib/socket_wrapper/config.m4 @@ -2,6 +2,7 @@ AC_ARG_ENABLE(socket-wrapper, [ --enable-socket-wrapper Turn on socket wrapper library (default=no)]) DEFAULT_TEST_TARGET=test-noswrap +HAVE_SOCKET_WRAPPER=no if eval "test x$developer = xyes"; then enable_socket_wrapper=yes @@ -10,6 +11,8 @@ fi if eval "test x$enable_socket_wrapper = xyes"; then AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library]) DEFAULT_TEST_TARGET=test-swrap + HAVE_SOCKET_WRAPPER=yes fi AC_SUBST(DEFAULT_TEST_TARGET) +AC_SUBST(HAVE_SOCKET_WRAPPER) -- cgit From 88f0a6e5e26e42fe80c0b907dabdcb16071aeff7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 5 May 2005 22:31:49 +0000 Subject: r6622: Add talloc manpage in DocBook XML, based on SGML version by Garry Williams (This used to be commit 62550eac1e56e95c8080a0519579fd97ee5d465a) --- source4/lib/talloc/Makefile.in | 13 +- source4/lib/talloc/configure.in | 1 + source4/lib/talloc/talloc.3.xml | 637 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 650 insertions(+), 1 deletion(-) create mode 100644 source4/lib/talloc/talloc.3.xml (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index a3dd3f3e0b..f3fdf5f01c 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -5,6 +5,8 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ includedir = @includedir@ libdir = @libdir@ +mandir = @mandir@ +XSLTPROC = @XSLTPROC@ CFLAGS = $(OPT) -Wall @@ -17,10 +19,19 @@ testsuite: $(LIBOBJ) testsuite.o libtalloc.a: libtalloc.a($(LIBOBJ)) -install: +install: all doc cp libtalloc.a $(libdir) cp talloc.h $(includedir) cp talloc.pc $(libdir)/pkgconfig + cp talloc.3 $(mandir)/man3 + +doc: talloc.3 + +%.3: %.3.xml + $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +%.html: %.xml + $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< clean: rm -f *~ *.o testsuite *.gc?? diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 0ebbde9fcf..c0e307ab05 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -2,6 +2,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(talloc.h) AC_PROG_CC +AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) sinclude(config.m4) AC_OUTPUT(Makefile talloc.pc) diff --git a/source4/lib/talloc/talloc.3.xml b/source4/lib/talloc/talloc.3.xml new file mode 100644 index 0000000000..7b254ae7c7 --- /dev/null +++ b/source4/lib/talloc/talloc.3.xml @@ -0,0 +1,637 @@ + + + + + talloc + 3 + + + talloc +hierarchical reference counted memory pool system with destructors + + +#include <talloc/talloc.h> + + DESCRIPTION + + If you are used to talloc from Samba3 then please read this + carefully, as talloc has changed a lot. + + + The new talloc is a hierarchical, reference counted memory pool + system with destructors. Quite a mouthful really, but not too bad + once you get used to it. + + + Perhaps the biggest change from Samba3 is that there is no + distinction between a "talloc context" and a "talloc pointer". Any + pointer returned from talloc() is itself a valid talloc context. + This means you can do this: + + + struct foo *X = talloc(mem_ctx, struct foo); + X->name = talloc_strdup(X, "foo"); + + + and the pointer X->name + would be a "child" of the talloc context X which is itself a child of + mem_ctx. So if you do + talloc_free(mem_ctx) then + it is all destroyed, whereas if you do talloc_free(X) then just X and X->name are destroyed, and if + you do talloc_free(X->name) then just + the name element of X is + destroyed. + + + If you think about this, then what this effectively gives you is an + n-ary tree, where you can free any part of the tree with + talloc_free(). + + + If you find this confusing, then I suggest you run the testsuite program to watch talloc + in action. You may also like to add your own tests to testsuite.c to clarify how some + particular situation is handled. + + + TALLOC API + + The following is a complete guide to the talloc API. Read it all at + least twice. + + (type *)talloc(const void *ctx, type); + + The talloc() macro is the core of the talloc library. It takes a + memory ctx and a type, and returns a pointer to a new + area of memory of the given type. + + + The returned pointer is itself a talloc context, so you can use + it as the ctx argument to more + calls to talloc() if you wish. + + + The returned pointer is a "child" of the supplied context. This + means that if you talloc_free() the ctx then the new child disappears as + well. Alternatively you can free just the child. + + + The ctx argument to talloc() + can be NULL, in which case a new top level context is created. + + + void *talloc_size(const void *ctx, size_t size); + + The function talloc_size() should be used when you don't have a + convenient type to pass to talloc(). Unlike talloc(), it is not + type safe (as it returns a void *), so you are on your own for + type checking. + + + int talloc_free(void *ptr); + + The talloc_free() function frees a piece of talloc memory, and + all its children. You can call talloc_free() on any pointer + returned by talloc(). + + + The return value of talloc_free() indicates success or failure, + with 0 returned for success and -1 for failure. The only + possible failure condition is if ptr had a destructor attached to it and + the destructor returned -1. See talloc_set_destructor() + for details on destructors. + + + If this pointer has an additional parent when talloc_free() is + called then the memory is not actually released, but instead the + most recently established parent is destroyed. See talloc_reference() + for details on establishing additional parents. + + + For more control on which parent is removed, see talloc_unlink(). + + + talloc_free() operates recursively on its children. + + + void *talloc_reference(const void *ctx, const void *ptr); + + The talloc_reference() function makes ctx an additional parent of ptr. + + + The return value of talloc_reference() is always the original + pointer ptr, unless talloc ran + out of memory in creating the reference in which case it will + return NULL (each additional reference consumes around 48 bytes + of memory on intel x86 platforms). + + + If ptr is NULL, then the + function is a no-op, and simply returns NULL. + + + After creating a reference you can free it in one of the + following ways: + + + + + + you can talloc_free() any parent of the original pointer. + That will reduce the number of parents of this pointer by 1, + and will cause this pointer to be freed if it runs out of + parents. + + + + + you can talloc_free() the pointer itself. That will destroy + the most recently established parent to the pointer and leave + the pointer as a child of its current parent. + + + + + + For more control on which parent to remove, see talloc_unlink(). + + + int talloc_unlink(const void *ctx, const void *ptr); + + The talloc_unlink() function removes a specific parent from + ptr. The ctx passed must either be a context used + in talloc_reference() with this pointer, or must be a direct + parent of ptr. + + + Note that if the parent has already been removed using + talloc_free() then this function will fail and will return -1. + Likewise, if ptr is NULL, then + the function will make no modifications and return -1. + + + Usually you can just use talloc_free() instead of + talloc_unlink(), but sometimes it is useful to have the + additional control on which parent is removed. + + + void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + + The function talloc_set_destructor() sets the destructor for the pointer ptr. A destructor is a function that is called + when the memory used by a pointer is about to be released. The + destructor receives ptr as an + argument, and should return 0 for success and -1 for failure. + + + The destructor can do anything + it wants to, including freeing other pieces of memory. A common + use for destructors is to clean up operating system resources + (such as open file descriptors) contained in the structure the + destructor is placed on. + + + You can only place one destructor on a pointer. If you need more + than one destructor then you can create a zero-length child of + the pointer and place an additional destructor on that. + + + To remove a destructor call talloc_set_destructor() with NULL for + the destructor. + + + If your destructor attempts to talloc_free() the pointer that it + is the destructor for then talloc_free() will return -1 and the + free will be ignored. This would be a pointless operation + anyway, as the destructor is only called when the memory is just + about to go away. + + + void talloc_increase_ref_count(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_increase_ref_count(ptr) function is exactly equivalent to: + + talloc_reference(NULL, ptr); + + You can use either syntax, depending on which you think is + clearer in your code. + + + void talloc_set_name(const void *ptr, const char *fmt, ...); + + Each talloc pointer has a "name". The name is used principally + for debugging purposes, although it is also possible to set and + get the name on a pointer in as a way of "marking" pointers in + your code. + + + The main use for names on pointer is for "talloc reports". See + talloc_report() + and talloc_report_full() + for details. Also see talloc_enable_leak_report() + and talloc_enable_leak_report_full(). + + + The talloc_set_name() function allocates memory as a child of the + pointer. It is logically equivalent to: + + talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + + Note that multiple calls to talloc_set_name() will allocate more + memory without releasing the name. All of the memory is released + when the ptr is freed using talloc_free(). + + + void talloc_set_name_const(const void *<emphasis role="italic">ptr</emphasis>, const char *<emphasis role="italic">name</emphasis>); + + The function talloc_set_name_const() is just like + talloc_set_name(), but it takes a string constant, and is much + faster. It is extensively used by the "auto naming" macros, such + as talloc_p(). + + + This function does not allocate any memory. It just copies the + supplied pointer into the internal representation of the talloc + ptr. This means you must not pass a name pointer to memory that will + disappear before ptr is freed + with talloc_free(). + + + void *talloc_named(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...); + + The talloc_named() function creates a named talloc pointer. It + is equivalent to: + + ptr = talloc_size(ctx, size); +talloc_set_name(ptr, fmt, ....); + + void *talloc_named_const(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>, const char *<emphasis role="italic">name</emphasis>); + + This is equivalent to: + + ptr = talloc_size(ctx, size); +talloc_set_name_const(ptr, name); + + const char *talloc_get_name(const void *<emphasis role="italic">ptr</emphasis>); + + This returns the current name for the given talloc pointer, + ptr. See talloc_set_name() + for details. + + + void *talloc_init(const char *<emphasis role="italic">fmt</emphasis>, ...); + + This function creates a zero length named talloc context as a top + level context. It is equivalent to: + + talloc_named(NULL, 0, fmt, ...); + + void *talloc_new(void *<emphasis role="italic">ctx</emphasis>); + + This is a utility macro that creates a new memory context hanging + off an exiting context, automatically naming it "talloc_new: + __location__" where __location__ is the source line it is called + from. It is particularly useful for creating a new temporary + working context. + + + (<emphasis role="italic">type</emphasis> *)talloc_realloc(const void *<emphasis role="italic">ctx</emphasis>, void *<emphasis role="italic">ptr</emphasis>, <emphasis role="italic">type</emphasis>, <emphasis role="italic">count</emphasis>); + + The talloc_realloc() macro changes the size of a talloc pointer. + It has the following equivalences: + + talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); +talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); + + The ctx argument is only used + if ptr is not NULL, otherwise + it is ignored. + + + talloc_realloc() returns the new pointer, or NULL on failure. + The call will fail either due to a lack of memory, or because the + pointer has more than one parent (see talloc_reference()). + + + void *talloc_realloc_size(const void *ctx, void *ptr, size_t size); + + the talloc_realloc_size() function is useful when the type is not + known so the type-safe talloc_realloc() cannot be used. + + + void *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_steal() function changes the parent context of a + talloc pointer. It is typically used when the context that the + pointer is currently a child of is going to be freed and you wish + to keep the memory for a longer time. + + + The talloc_steal() function returns the pointer that you pass it. + It does not have any failure modes. + + + NOTE: It is possible to produce loops in the parent/child + relationship if you are not careful with talloc_steal(). No + guarantees are provided as to your sanity or the safety of your + data if you do this. + + + off_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_total_size() function returns the total size in bytes + used by this pointer and all child pointers. Mostly useful for + debugging. + + + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + + + off_t talloc_total_blocks(const void *<emphasis role="italic">ptr</emphasis>); + + The talloc_total_blocks() function returns the total memory block + count used by this pointer and all child pointers. Mostly useful + for debugging. + + + Passing NULL is allowed, but it will only give a meaningful + result if talloc_enable_leak_report() or + talloc_enable_leak_report_full() has been called. + + + void talloc_report(const void *ptr, FILE *f); + + The talloc_report() function prints a summary report of all + memory used by ptr. One line + of report is printed for each immediate child of ptr, showing the + total memory and number of blocks used by that child. + + + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + + + void talloc_report_full(const void *<emphasis role="italic">ptr</emphasis>, FILE *<emphasis role="italic">f</emphasis>); + + This provides a more detailed report than talloc_report(). It + will recursively print the entire tree of memory referenced by + the pointer. References in the tree are shown by giving the name + of the pointer that is referenced. + + + You can pass NULL for the pointer, in which case a report is + printed for the top level memory context, but only if + talloc_enable_leak_report() or talloc_enable_leak_report_full() + has been called. + + + void talloc_enable_leak_report(void); + + This enables calling of talloc_report(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report command line option. + + + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + + + Here is a typical talloc report: + + talloc report on 'null_context' (total 267 bytes in 15 blocks) +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(UTF8,CP850) contains 42 bytes in 2 blocks +libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks +iconv(CP850,UTF8) contains 42 bytes in 2 blocks +iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks +iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + + + void talloc_enable_leak_report_full(void); + + This enables calling of talloc_report_full(NULL, stderr) when the + program exits. In Samba4 this is enabled by using the + --leak-report-full command line option. + + + For it to be useful, this function must be called before any + other talloc function as it establishes a "null context" that + acts as the top of the tree. If you don't call this function + first then passing NULL to talloc_report() or + talloc_report_full() won't give you the full tree printout. + + + Here is a typical full report: + + full talloc report on 'root' (total 18 bytes in 8 blocks) +p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + + + (<emphasis role="italic">type</emphasis> *)talloc_zero(const void *<emphasis role="italic">ctx</emphasis>, <emphasis role="italic">type</emphasis>); + + The talloc_zero() macro is equivalent to: + + ptr = talloc(ctx, type); +if (ptr) memset(ptr, 0, sizeof(type)); + + void *talloc_zero_size(const void *<emphasis role="italic">ctx</emphasis>, size_t <emphasis role="italic">size</emphasis>) + + The talloc_zero_size() function is useful when you don't have a + known type. + + + void *talloc_memdup(const void *<emphasis role="italic">ctx</emphasis>, const void *<emphasis role="italic">p</emphasis>, size_t size); + + The talloc_memdup() function is equivalent to: + + ptr = talloc_size(ctx, size); +if (ptr) memcpy(ptr, p, size); + + char *talloc_strdup(const void *<emphasis role="italic">ctx</emphasis>, const char *<emphasis role="italic">p</emphasis>); + + The talloc_strdup() function is equivalent to: + + ptr = talloc_size(ctx, strlen(p)+1); +if (ptr) memcpy(ptr, p, strlen(p)+1); + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_strndup(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">p</emphasis>, size_t <emphasis role="italic">n</emphasis>); + + The talloc_strndup() function is the talloc equivalent of the C + library function strndup(3). + + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_vasprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, va_list <emphasis role="italic">ap</emphasis>); + + The talloc_vasprintf() function is the talloc equivalent of the C + library function vasprintf(3). + + + char *talloc_asprintf(const void *<emphasis role="italic">t</emphasis>, const char *<emphasis role="italic">fmt</emphasis>, ...); + + The talloc_asprintf() function is the talloc equivalent of the C + library function asprintf(3). + + + This function sets the name of the new pointer to the passed + string. This is equivalent to: + + talloc_set_name_const(ptr, ptr) + + char *talloc_asprintf_append(char *s, const char *fmt, ...); + + The talloc_asprintf_append() function appends the given formatted + string to the given string. + + + (type *)talloc_array(const void *ctx, type, uint_t count); + + The talloc_array() macro is equivalent to: + + (type *)talloc_size(ctx, sizeof(type) * count); + + except that it provides integer overflow protection for the + multiply, returning NULL if the multiply overflows. + + + void *talloc_array_size(const void *ctx, size_t size, uint_t count); + + The talloc_array_size() function is useful when the type is not + known. It operates in the same way as talloc_array(), but takes a + size instead of a type. + + + void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size) + + This is a non-macro version of talloc_realloc(), which is useful + as libraries sometimes want a realloc function pointer. A + realloc(3) implementation encapsulates the functionality of + malloc(3), free(3) and realloc(3) in one call, which is why it is + useful to be able to pass around a single function pointer. + + + void *talloc_autofree_context(void); + + This is a handy utility function that returns a talloc context + which will be automatically freed on program exit. This can be + used to reduce the noise in memory leak reports. + + + void *talloc_check_name(const void *ptr, const char *name); + + This function checks if a pointer has the specified name. If it does then the pointer is + returned. It it doesn't then NULL is returned. + + + (type *)talloc_get_type(const void *ptr, type); + + This macro allows you to do type checking on talloc pointers. It + is particularly useful for void* private pointers. It is + equivalent to this: + + (type *)talloc_check_name(ptr, #type) + + talloc_set_type(const void *ptr, type); + + This macro allows you to force the name of a pointer to be a + particular type. This can be + used in conjunction with talloc_get_type() to do type checking on + void* pointers. + + + It is equivalent to this: + + talloc_set_name_const(ptr, #type) + + + PERFORMANCE + + All the additional features of talloc(3) over malloc(3) do come at a + price. We have a simple performance test in Samba4 that measures + talloc() versus malloc() performance, and it seems that talloc() is + about 10% slower than malloc() on my x86 Debian Linux box. For + Samba, the great reduction in code complexity that we get by using + talloc makes this worthwhile, especially as the total overhead of + talloc/malloc in Samba is already quite small. + + + SEE ALSO + + malloc(3), strndup(3), vasprintf(3), asprintf(3), + + + + COPYRIGHT/LICENSE + + Copyright (C) Andrew Tridgell 2004 + + + 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 (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + -- cgit From 157a32956a111b8cffcfa8d1c62a0ca67cdc0b22 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 7 May 2005 15:22:45 +0000 Subject: r6645: Add talloc_get_size() function. Sometimes it is usefull to know this data. Simo. (This used to be commit df401847827ef660d8b9d55af9b27bb85bad6b5f) --- source4/lib/talloc/talloc.c | 10 ++++++++++ source4/lib/talloc/talloc.h | 1 + source4/lib/talloc/talloc_guide.txt | 8 ++++++++ 3 files changed, 19 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index da3a2300b0..248af6ea3e 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -1082,3 +1082,13 @@ void *talloc_autofree_context(void) } +size_t talloc_get_size(const void *context) { + struct talloc_chunk *tc; + + if (context == NULL) + return 0; + + tc = talloc_chunk_from_ptr(context); + + return tc->size; +} diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 8b448f63c5..ab549cf624 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -126,6 +126,7 @@ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); +size_t talloc_get_size(const void *ctx); #endif diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 55349ec05b..c23ac77cad 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -559,3 +559,11 @@ talloc_get_type() to do type checking on void* pointers. It is equivalent to this: talloc_set_name_const(ptr, #type) + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +talloc_get_size(const void *ctx); + +This function lets you know the amount of memory alloced so far by +this context. It does NOT account for subcontext memory. +This can be used to calculate the size of an array. + -- cgit From 13bb5c34863c85f7d0cec13d7649ade242acbd52 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 7 May 2005 16:27:56 +0000 Subject: r6650: keep style consistent (This used to be commit 34671674ee326ea835408f8c1fdb105ea50ccc55) --- source4/lib/talloc/talloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 248af6ea3e..cb5e91341e 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -1082,7 +1082,8 @@ void *talloc_autofree_context(void) } -size_t talloc_get_size(const void *context) { +size_t talloc_get_size(const void *context) +{ struct talloc_chunk *tc; if (context == NULL) -- cgit From c1d31ac8fc22a46d3ce7d99058e48058464f4e06 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 7 May 2005 22:10:26 +0000 Subject: r6660: Sorry for the spam... I think now I've got a version that should compile on trunk, 3_0 and 4_0. Volker (This used to be commit 777c489cad610fef140ec80d5644111b04a314c1) --- source4/lib/talloc/talloc.c | 11 ++++++++++- source4/lib/talloc/testsuite.c | 14 +++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index cb5e91341e..3650ab7f51 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -29,6 +29,16 @@ #ifdef _SAMBA_BUILD_ #include "includes.h" +#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) +/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file + * we trust ourselves... */ +#ifdef malloc +#undef malloc +#endif +#ifdef realloc +#undef realloc +#endif +#endif #else #include #include @@ -1081,7 +1091,6 @@ void *talloc_autofree_context(void) return cleanup_context; } - size_t talloc_get_size(const void *context) { struct talloc_chunk *tc; diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 967874917d..0447749abd 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -35,6 +35,10 @@ /* the test suite can be built standalone, or as part of Samba */ #ifndef _SAMBA_BUILD_ typedef enum {False=0,True=1} BOOL; +#endif + +/* Samba3 does not define the timeval functions below */ +#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) static struct timeval timeval_current(void) { @@ -51,6 +55,14 @@ static double timeval_elapsed(struct timeval *tv) } #endif /* _SAMBA_BUILD_ */ +#if SAMBA_VERSION_MAJOR<4 +#ifdef malloc +#undef malloc +#endif +#ifdef strdup +#undef strdup +#endif +#endif #define CHECK_SIZE(ptr, tsize) do { \ if (talloc_total_size(ptr) != (tsize)) { \ @@ -827,7 +839,7 @@ BOOL torture_local_talloc(void) -#ifndef _SAMBA_BUILD_ +#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) int main(void) { if (!torture_local_talloc()) { -- cgit From 30f817a2027d9f0629772458eb963cb3dd89864f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 May 2005 22:54:51 +0000 Subject: r6661: fix up talloc autoconf to have a chance of working on the build farm (This used to be commit 9318744fd496a829a57fc8e0f21d4b26b1eb74c7) --- source4/lib/talloc/Makefile.in | 15 ++- source4/lib/talloc/configure.in | 1 + source4/lib/talloc/install-sh | 238 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 4 deletions(-) create mode 100755 source4/lib/talloc/install-sh (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index f3fdf5f01c..b6bc271986 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -7,6 +7,7 @@ includedir = @includedir@ libdir = @libdir@ mandir = @mandir@ XSLTPROC = @XSLTPROC@ +INSTALLCMD=@INSTALL@ CFLAGS = $(OPT) -Wall @@ -20,10 +21,13 @@ testsuite: $(LIBOBJ) testsuite.o libtalloc.a: libtalloc.a($(LIBOBJ)) install: all doc - cp libtalloc.a $(libdir) - cp talloc.h $(includedir) - cp talloc.pc $(libdir)/pkgconfig - cp talloc.3 $(mandir)/man3 + ${INSTALLCMD} -d ${libdir} + ${INSTALLCMD} -m 755 libtalloc.a $(libdir) + ${INSTALLCMD} -d ${includedir} + ${INSTALLCMD} -m 644 talloc.h $(includedir) + ${INSTALLCMD} -m 644 talloc.pc $(libdir)/pkgconfig + ${INSTALLCMD} -d ${mandir}/man3 + ${INSTALLCMD} -m 644 talloc.3 $(mandir)/man3 doc: talloc.3 @@ -36,5 +40,8 @@ doc: talloc.3 clean: rm -f *~ *.o testsuite *.gc?? +test: testsuite + ./testsuite + gcov: gcov talloc.c diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index c0e307ab05..05e6577ce8 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -2,6 +2,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(talloc.h) AC_PROG_CC +AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) sinclude(config.m4) diff --git a/source4/lib/talloc/install-sh b/source4/lib/talloc/install-sh new file mode 100755 index 0000000000..58719246f0 --- /dev/null +++ b/source4/lib/talloc/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 -- cgit From 3059fb2bc748a8ff1876d0f840a50b73139445f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 May 2005 23:14:17 +0000 Subject: r6662: add an installcheck target for talloc (This used to be commit 2f78428cfd823b499c60ac3cc02650183b760ef0) --- source4/lib/talloc/Makefile.in | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index b6bc271986..a986d7766c 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -45,3 +45,6 @@ test: testsuite gcov: gcov talloc.c + +installcheck: + $(MAKE) test -- cgit From 238f36b8995d959ffe5174054bf71228119ce802 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 May 2005 23:19:44 +0000 Subject: r6663: only use -Wall for gcc (This used to be commit b7fbe2173d45456c77fad9673073173704a1b266) --- source4/lib/talloc/Makefile.in | 4 +--- source4/lib/talloc/configure.in | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index a986d7766c..ec906f9453 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -1,5 +1,3 @@ -#OPT = -g -ftest-coverage -fprofile-arcs -#LIBS = -lgcov OPT = -O prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -9,7 +7,7 @@ mandir = @mandir@ XSLTPROC = @XSLTPROC@ INSTALLCMD=@INSTALL@ -CFLAGS = $(OPT) -Wall +CFLAGS = $(OPT) LIBOBJ = talloc.o diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 05e6577ce8..2dfb66a17e 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -2,6 +2,9 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(talloc.h) AC_PROG_CC +if test "x$GCC" = "xyes"; then + CFLAGS="$CFLAGS -Wall -W" +fi AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) -- cgit From 8797d0e29b4c4b2ee19fd7c17c9803fbd4a4d25f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 8 May 2005 13:22:55 +0000 Subject: r6664: Obey overrided CC in the Makefile (should fix build on several buildfarm hosts) (This used to be commit cbd7af4fcf72fd21b2a8ea2ee8f9f61f90f36f03) --- source4/lib/talloc/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index ec906f9453..faf4382b39 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -5,7 +5,8 @@ includedir = @includedir@ libdir = @libdir@ mandir = @mandir@ XSLTPROC = @XSLTPROC@ -INSTALLCMD=@INSTALL@ +INSTALLCMD = @INSTALL@ +CC = @CC@ CFLAGS = $(OPT) -- cgit From 61d95606d06b7ee9541b2097c693afd042459f31 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 May 2005 01:55:18 +0000 Subject: r6687: added a idr helper function for creating random IDs (This used to be commit ef573df2a012e9a192487f207502ef1027c66d4b) --- source4/lib/idtree.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/idtree.c b/source4/lib/idtree.c index 82c1cdd42a..a67a80940a 100644 --- a/source4/lib/idtree.c +++ b/source4/lib/idtree.c @@ -344,6 +344,24 @@ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int l return ret; } +/* + allocate a new id randomly in the given range +*/ +int idr_get_new_random(struct idr_context *idp, void *ptr, int limit) +{ + int id; + + /* first try a random starting point in the whole range, and if that fails, + then start randomly in the bottom half of the range. This can only + fail if the range is over half full */ + id = idr_get_new_above(idp, ptr, 1+(generate_random() % limit), limit); + if (id == -1) { + id = idr_get_new_above(idp, ptr, 1+(generate_random()%(limit/2)), limit); + } + + return id; +} + /* find a pointer value previously set with idr_get_new given an id */ -- cgit From e1369f8720517796438dc57da1965efcfff25ff5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 May 2005 01:56:00 +0000 Subject: r6688: removed unused binary_string() function (This used to be commit 0b48c69e0b94571173a12714b22d3d5e2af17bcf) --- source4/lib/util_str.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 5d12a01f6e..69a4395cfb 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -852,29 +852,6 @@ size_t strlen_m_term(const char *s) return strlen_m(s) + 1; } -/** - Return a RFC2254 binary string representation of a buffer. - Used in LDAP filters. - Caller must free. -**/ -char *binary_string(char *buf, int len) -{ - char *s; - int i, j; - const char *hex = "0123456789ABCDEF"; - s = malloc(len * 3 + 1); - if (!s) - return NULL; - for (j=i=0;i> 4]; - s[j+2] = hex[((uint8_t)buf[i]) & 0xF]; - j += 3; - } - s[j] = 0; - return s; -} - /** Unescape a URL encoded string, in place. **/ -- cgit From 69f3a934d78748d22cbfd8eccd16b3100a1c13e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 10 May 2005 09:51:55 +0000 Subject: r6700: Upper case realms in kerberos-specific parts of the code, as this is no longer done globally. This keeps MIT client libraries happy, because otherwise the windows KDC will return a different case to what was requested. Andrew Bartlett (This used to be commit 9098b9321f938473c367f906cfe2f001ca1d8e6a) --- source4/lib/credentials.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 7e25fc780b..ed9a9788ab 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -175,10 +175,14 @@ char *cli_credentials_get_principal(struct cli_credentials *cred, cli_credentials_get_realm(cred)); } +/** + * Set the realm for this credentials context, and force it to + * uppercase for the sainity of our local kerberos libraries + */ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) { if (obtained >= cred->realm_obtained) { - cred->realm = talloc_strdup(cred, val); + cred->realm = strupper_talloc(cred, val); cred->realm_obtained = obtained; return True; } -- cgit From 9add53863f4bfd870e8af102057a1084e9849d20 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 May 2005 02:54:42 +0000 Subject: r6741: prevent talloc_strndup() from reading one byte past the end of a buffer, giving valgrind errors (This used to be commit 7af0c547e0c0da3bc78a1ee6c2ab29114d8625cc) --- source4/lib/talloc/talloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 3650ab7f51..46abd89bac 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -919,7 +919,7 @@ char *talloc_strndup(const void *t, const char *p, size_t n) size_t len; char *ret; - for (len=0; p[len] && len Date: Thu, 12 May 2005 14:39:03 +0000 Subject: r6759: let us have a wildcard attribute so that we can set a default for all attributes example: *: CASE_INSENSITIVE by placing it in the @ATTRIBUTES object you make all the matching be case insensitive to make an excepion to the general rule now you just need to create an entry like: name: CASE_SENSITIVE the key CASE_SENSITIVE currently does not exist but has the effect of making the code ignore the wildcard default flag and being ldb case sensitive by default it let the "name" attribute be case sensitive again Tridge, can you look at this commit? Should we introduce a CASE_SENSITVE/BINARY flag and handle it in the code ? Simo. (This used to be commit 5f10707e8ac36db03f3aa3e1ee1c40a9d9da2016) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 8cc6616d52..ec22aca3ec 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -272,7 +272,13 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) attrs = ldb_msg_find_string(ltdb->cache->attributes, attr_name, NULL); if (!attrs) { - return ret; + + /* check if theres a wildcard attribute */ + attrs = ldb_msg_find_string(ltdb->cache->attributes, "*", NULL); + + if (!attrs) { + return ret; + } } /* we avoid using strtok and friends due to their nasty -- cgit From e5a3ec0e5b9bc7d85d3c64f0ce9628f788065d84 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 14 May 2005 22:16:02 +0000 Subject: r6790: Use config.h file for ldb and add test for stdint.h (This used to be commit c1f1b5a9455c827f7baf382d919ab8a0eab49bb3) --- source4/lib/ldb/Makefile.in | 3 ++- source4/lib/ldb/autogen.sh | 1 + source4/lib/ldb/configure.in | 4 ++++ source4/lib/ldb/include/includes.h | 4 +++- 4 files changed, 10 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index eedab96ef2..e7bde04658 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -7,8 +7,9 @@ includedir = @includedir@ libdir = @libdir@ bindir = @bindir@ WITH_GCOV = @WITH_GCOV@ +WITH_LDAP = @WITH_LDAP@ -ifeq ($(WITH_LDAP),1) +ifeq ($(WITH_LDAP),yes) OPENLDAP_PREFIX=/usr LDAP_LIBS=-L$(OPENLDAP_PREFIX)/lib -llber -lldap LDAP_FLAGS=-DHAVE_LDAP=1 diff --git a/source4/lib/ldb/autogen.sh b/source4/lib/ldb/autogen.sh index 94148edf69..e118019a39 100755 --- a/source4/lib/ldb/autogen.sh +++ b/source4/lib/ldb/autogen.sh @@ -1,6 +1,7 @@ #!/bin/sh autoconf || exit 1 +autoheader || exit 1 echo "Now run ./configure and then make." exit 0 diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 26b39e684a..ed61344317 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -20,6 +20,10 @@ AC_PROG_CC AC_FUNC_MMAP AC_PATH_PROG(YODL2MAN,yodl2man) AC_PATH_PROG(GCOV,gcov) +AC_CHECK_HEADERS(stdint.h) +AC_CONFIG_HEADER(include/config.h) sinclude(ldap.m4) +WITH_LDAP=$with_ldap_support +AC_SUBST(WITH_LDAP) sinclude(config.m4) AC_OUTPUT(Makefile ldb.pc) diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 66b984a87d..8b513e20c7 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -5,8 +5,8 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include "config.h" #include -#include #include #include #include @@ -18,7 +18,9 @@ #include #include #include +#ifdef HAVE_STDINT_H #include +#endif #include "ldb.h" #include "ldb_private.h" -- cgit From 5b18cf22680c76abb1262a6b75a30b8a37899467 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 15 May 2005 20:16:26 +0000 Subject: r6795: Make some functions static and remove some unused ones. (This used to be commit 46509eb89980bfe6dabd71264d570ea356ee5a22) --- source4/lib/com/classes/simple.c | 8 +++--- source4/lib/registry/common/reg_interface.c | 7 ------ source4/lib/registry/common/reg_util.c | 38 ----------------------------- source4/lib/registry/reg_backend_rpc.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/socket/socket.c | 6 ----- source4/lib/socket/socket.h | 1 - 8 files changed, 7 insertions(+), 59 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c index ad03c17cce..e4bf8d18e1 100644 --- a/source4/lib/com/classes/simple.c +++ b/source4/lib/com/classes/simple.c @@ -22,8 +22,8 @@ #include "lib/com/com.h" #include "librpc/gen_ndr/com_dcom.h" -extern struct IClassFactory_vtable simple_classobject_vtable; -extern struct IStream_vtable simple_IStream_vtable; +static struct IClassFactory_vtable simple_classobject_vtable; +static struct IStream_vtable simple_IStream_vtable; static WERROR simple_IUnknown_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) { @@ -85,7 +85,7 @@ static uint32_t simpleclass_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *me } /* Everything below this line should be autogenerated later on */ -struct IClassFactory_vtable simple_classobject_vtable = { +static struct IClassFactory_vtable simple_classobject_vtable = { {}, simpleclass_IUnknown_QueryInterface, simpleclass_IUnknown_AddRef, @@ -96,7 +96,7 @@ struct IClassFactory_vtable simple_classobject_vtable = { NULL }; -struct IStream_vtable simple_IStream_vtable = { +static struct IStream_vtable simple_IStream_vtable = { {}, simple_IUnknown_QueryInterface, simple_IUnknown_AddRef, diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 407d0d3345..76de2f041f 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -127,13 +127,6 @@ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char * return WERR_BADFILE; } -WERROR reg_close (struct registry_context *ctx) -{ - talloc_free(ctx); - - return WERR_OK; -} - WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key) { WERROR ret = ctx->get_predefined_key(ctx, hkey, key); diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index d4fdc59d70..e12cff186a 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -139,44 +139,6 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da return True; } -WERROR reg_key_get_subkey_val(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *subname, const char *valname, struct registry_value **val) -{ - struct registry_key *k; - WERROR error = reg_key_get_subkey_by_name(mem_ctx, key, subname, &k); - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_get_value_by_name(mem_ctx, k, valname, val); -} - -/*********************************************************************** - Utility function for splitting the base path of a registry path off - by setting base and new_path to the apprapriate offsets withing the - path. - - WARNING!! Does modify the original string! - ***********************************************************************/ - -BOOL reg_split_path( char *path, char **base, char **new_path ) -{ - char *p; - - *new_path = *base = NULL; - - if ( !path) - return False; - - *base = path; - - p = strchr( path, '\\' ); - - if ( p ) { - *p = '\0'; - *new_path = p+1; - } - - return True; -} - /** * Replace all \'s with /'s */ diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 5240cf5696..88cce2584e 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -77,7 +77,7 @@ struct rpc_key_data { int max_valdatalen; }; -struct { +static struct { uint32_t hkey; WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); } known_hives[] = { diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 2462fd8241..aeb418560d 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -576,7 +576,7 @@ typedef struct command_ops_s { int (*exec_cmd)(CMD *cmd); } CMD_OPS; -CMD_OPS default_cmd_ops[] = { +static CMD_OPS default_cmd_ops[] = { {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd}, {1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd}, {-1, NULL, NULL, NULL} diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index bb7533e55e..ecc2bfc7aa 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -187,7 +187,7 @@ static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_contex static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int, char **); -struct { +static struct { const char *name; const char *alias; const char *help; diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 86e2f05962..13d1640f51 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -87,12 +87,6 @@ NTSTATUS socket_create(const char *name, enum socket_type type, return socket_create_with_ops(NULL, ops, new_sock, type, flags); } -void socket_destroy(struct socket_context *sock) -{ - /* the close is handled by the destructor */ - talloc_free(sock); -} - NTSTATUS socket_connect(struct socket_context *sock, const char *my_address, int my_port, const char *server_address, int server_port, diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index b1fae9ac56..bce64f9f6c 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -107,7 +107,6 @@ struct socket_context { /* prototypes */ NTSTATUS socket_create(const char *name, enum socket_type type, struct socket_context **new_sock, uint32_t flags); -void socket_destroy(struct socket_context *sock); NTSTATUS socket_connect(struct socket_context *sock, const char *my_address, int my_port, const char *server_address, int server_port, -- cgit From ffb8ba8cd320b7c25dabb2353d9e7245bcaefcd1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 15 May 2005 23:20:58 +0000 Subject: r6798: Valgrind pain is not something I look forward to - if we ever fall back to the 'not /dev/urandom' method of random number generation, I don't want to be chasing down 'use of uninitialised value' though all the crypto code. Andrew Bartlett (This used to be commit 31ff2cd8e11dee36c42f82dcfd85338d3ff704d3) --- source4/lib/genrand.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index e3df9f9d90..9d40e72afc 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -111,8 +111,10 @@ static void get_random_stream(unsigned char *data, size_t datasize) } /**************************************************************** - Get a 16 byte hash from the contents of a file. - Note that the hash is not initialised. + Get a 16 byte hash from the contents of a file. + + Note that the hash is initialised, because the extra entropy is not + worth the valgrind pain. *****************************************************************/ static void do_filehash(const char *fname, unsigned char *the_hash) @@ -121,6 +123,8 @@ static void do_filehash(const char *fname, unsigned char *the_hash) unsigned char tmp_md4[16]; int fd, n; + ZERO_STRUCT(tmp_md4); + fd = open(fname,O_RDONLY,0); if (fd == -1) return; -- cgit From 03435f5de11b364d6a7bb8bf99c12afd5cdd286e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 01:17:44 +0000 Subject: r6802: - fixed CFLAGS - don't fail if we don't have xsltproc (This used to be commit 235f5c510b4b68edf2a36d049bc0ff2afb73fd72) --- source4/lib/talloc/Makefile.in | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index faf4382b39..6efa9e1920 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -1,4 +1,3 @@ -OPT = -O prefix = @prefix@ exec_prefix = @exec_prefix@ includedir = @includedir@ @@ -7,8 +6,7 @@ mandir = @mandir@ XSLTPROC = @XSLTPROC@ INSTALLCMD = @INSTALL@ CC = @CC@ - -CFLAGS = $(OPT) +CFLAGS=@CFLAGS@ LIBOBJ = talloc.o @@ -26,15 +24,15 @@ install: all doc ${INSTALLCMD} -m 644 talloc.h $(includedir) ${INSTALLCMD} -m 644 talloc.pc $(libdir)/pkgconfig ${INSTALLCMD} -d ${mandir}/man3 - ${INSTALLCMD} -m 644 talloc.3 $(mandir)/man3 + test -z "$(XSLTPROC)" || ${INSTALLCMD} -m 644 talloc.3 $(mandir)/man3 doc: talloc.3 %.3: %.3.xml - $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< %.html: %.xml - $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< + test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< clean: rm -f *~ *.o testsuite *.gc?? -- cgit From 1f474c2692af8ba704a4071fe6e496cb43e19bae Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 16 May 2005 01:57:27 +0000 Subject: r6804: Add config.h for talloc (and use it) (This used to be commit c2ce09d38003fd43212de9cd08e4a781cc2aff88) --- source4/lib/talloc/autogen.sh | 1 + source4/lib/talloc/config.m4 | 9 +++++++++ source4/lib/talloc/configure.in | 2 ++ source4/lib/talloc/talloc.c | 18 +++++++++++++----- source4/lib/talloc/testsuite.c | 10 ++++++---- 5 files changed, 31 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/autogen.sh b/source4/lib/talloc/autogen.sh index 94148edf69..e118019a39 100755 --- a/source4/lib/talloc/autogen.sh +++ b/source4/lib/talloc/autogen.sh @@ -1,6 +1,7 @@ #!/bin/sh autoconf || exit 1 +autoheader || exit 1 echo "Now run ./configure and then make." exit 0 diff --git a/source4/lib/talloc/config.m4 b/source4/lib/talloc/config.m4 index 298c6691b9..5f653e6577 100644 --- a/source4/lib/talloc/config.m4 +++ b/source4/lib/talloc/config.m4 @@ -1,3 +1,12 @@ if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtalloc,YES) fi + +AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[ +AC_TRY_LINK([#include +va_list ap1,ap2;], [va_copy(ap1,ap2);], +samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)]) +if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then + AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) +fi + diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 2dfb66a17e..436fe365da 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -8,5 +8,7 @@ fi AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) +AC_CHECK_HEADERS(stdint.h stdarg.h) +AC_CONFIG_HEADER(config.h) sinclude(config.m4) AC_OUTPUT(Makefile talloc.pc) diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 46abd89bac..ca2fd9a288 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -28,7 +28,6 @@ #ifdef _SAMBA_BUILD_ -#include "includes.h" #if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file * we trust ourselves... */ @@ -39,17 +38,26 @@ #undef realloc #endif #endif -#else +#endif + +#include "config.h" + #include #include #include + +#ifdef HAVE_STDARG_H #include +#else +#include +#endif + +#ifdef HAVE_STDINT_H #include -#include "talloc.h" -/* assume a modern system */ -#define HAVE_VA_COPY #endif +#include "talloc.h" + /* use this to force every realloc to change the pointer, to stress test code that might not cope */ #define ALWAYS_REALLOC 0 diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 0447749abd..0e3d334316 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -20,17 +20,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef _SAMBA_BUILD_ -#include "includes.h" -#else +#include "config.h" #include #include #include + +#ifdef HAVE_STDARG_H #include +#endif + #include #include + #include "talloc.h" -#endif /* the test suite can be built standalone, or as part of Samba */ #ifndef _SAMBA_BUILD_ -- cgit From 5251703764846f0ed2c06127d67f4b4f65d08945 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 16 May 2005 02:38:50 +0000 Subject: r6807: Fix in-tree build of talloc testsuite (This used to be commit 3541ebe31bef8ccae7a8a1ea4f451ddfbd24460a) --- source4/lib/talloc/testsuite.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 0e3d334316..1d5665c338 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -34,13 +34,7 @@ #include "talloc.h" -/* the test suite can be built standalone, or as part of Samba */ -#ifndef _SAMBA_BUILD_ typedef enum {False=0,True=1} BOOL; -#endif - -/* Samba3 does not define the timeval functions below */ -#if !defined(_SAMBA_BUILD_) || ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) static struct timeval timeval_current(void) { @@ -55,7 +49,6 @@ static double timeval_elapsed(struct timeval *tv) return (tv2.tv_sec - tv->tv_sec) + (tv2.tv_usec - tv->tv_usec)*1.0e-6; } -#endif /* _SAMBA_BUILD_ */ #if SAMBA_VERSION_MAJOR<4 #ifdef malloc -- cgit From 9e044848e394e4395f88b77361e7be06833e3bb8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 02:45:36 +0000 Subject: r6808: - test for gcov not needed - samba malloc wrapper avoidance not needed now we don't use includes.h - make testsuite work when BOOL, True, False already defined (This used to be commit c8a274c8735957a8a8dd21421abd65a8a1af20f7) --- source4/lib/talloc/configure.in | 1 - source4/lib/talloc/talloc.c | 13 ------------- source4/lib/talloc/testsuite.c | 11 ++++++++++- 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 436fe365da..8a87ab8754 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -7,7 +7,6 @@ if test "x$GCC" = "xyes"; then fi AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) -AC_PATH_PROG(GCOV,gcov) AC_CHECK_HEADERS(stdint.h stdarg.h) AC_CONFIG_HEADER(config.h) sinclude(config.m4) diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index ca2fd9a288..01d1b9f255 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -27,19 +27,6 @@ */ -#ifdef _SAMBA_BUILD_ -#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) -/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file - * we trust ourselves... */ -#ifdef malloc -#undef malloc -#endif -#ifdef realloc -#undef realloc -#endif -#endif -#endif - #include "config.h" #include diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 1d5665c338..60da1c3f87 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -34,7 +34,15 @@ #include "talloc.h" -typedef enum {False=0,True=1} BOOL; +#ifndef False +#define False 0 +#endif +#ifndef True +#define True 1 +#endif +#ifndef BOOL +#define BOOL int +#endif static struct timeval timeval_current(void) { @@ -706,6 +714,7 @@ static BOOL test_steal(void) talloc_free(root); p1 = talloc_size(NULL, 3); + talloc_report_full(NULL, stdout); CHECK_SIZE(NULL, 3); talloc_free(p1); -- cgit From 3fd2a38e62a9c7c444d7dd9f56673fa216a00fdd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 06:33:37 +0000 Subject: r6812: more talloc portability tweaks (This used to be commit 450ac2e4dea25910ee5384747bdb6ad7323e967d) --- source4/lib/talloc/config.m4 | 5 +---- source4/lib/talloc/configure.in | 3 +-- source4/lib/talloc/talloc.c | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/config.m4 b/source4/lib/talloc/config.m4 index 5f653e6577..60e89f4392 100644 --- a/source4/lib/talloc/config.m4 +++ b/source4/lib/talloc/config.m4 @@ -1,7 +1,3 @@ -if test x"$experimental" = x"yes"; then - SMB_LIBRARY_ENABLE(libtalloc,YES) -fi - AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[ AC_TRY_LINK([#include va_list ap1,ap2;], [va_copy(ap1,ap2);], @@ -10,3 +6,4 @@ if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) fi +AC_CHECK_TYPES(intptr_t) diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 8a87ab8754..8e7e8252fd 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -1,5 +1,4 @@ -AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) -AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) +AC_PREREQ(2.50) AC_INIT(talloc.h) AC_PROG_CC if test "x$GCC" = "xyes"; then diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 01d1b9f255..d3fa961c74 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef HAVE_STDARG_H #include -- cgit From 9469051d5bcdd6a91b688d20bc91bb3cb2ba094d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 11:17:57 +0000 Subject: r6817: - fixed empty ldap search elements in filters - added support for guids in cldap netlogon searches. the cldap server now passes the LDAP-CLDAP torture test (This used to be commit eb7979d9def389942fa1c54693d2dfcb8828f544) --- source4/lib/ldb/common/ldb_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index d9f7dbe524..5221ef4556 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -170,7 +170,7 @@ static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *ctx, const char *s) ret->operation = LDB_OP_SIMPLE; ret->u.simple.attr = l; - ret->u.simple.value.data = val; + ret->u.simple.value.data = val?val:discard_const_p(char, ""); ret->u.simple.value.length = val?strlen(val):0; return ret; -- cgit From d29f44c594f4857593e361e9e31eef3cec1a912c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 16 May 2005 18:57:56 +0000 Subject: r6825: Fall back to chsize if ftruncate is not available patch from Steven Edwards (This used to be commit 82be4978116b73cd6d964da4fad59b5c5b11217e) --- source4/lib/replace.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace.c b/source4/lib/replace.c index ca367da9b5..89612912b7 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -32,6 +32,9 @@ ftruncate for operating systems that don't have it ********************************************************************/ int ftruncate(int f,off_t l) { +#ifdef HAVE_CHSIZE + return chsize(f,l); +#else struct flock fl; fl.l_whence = 0; @@ -39,6 +42,7 @@ ftruncate for operating systems that don't have it fl.l_start = l; fl.l_type = F_WRLCK; return fcntl(f, F_FREESP, &fl); +#endif } #endif /* HAVE_FTRUNCATE */ -- cgit From a0e786c4464a0b25574093295751afd906034c6b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 16 May 2005 21:08:44 +0000 Subject: r6828: More portability fixes (This used to be commit f46c532883e18b8780ff73d3ac0899690eeab3f4) --- source4/lib/talloc/Makefile.in | 2 +- source4/lib/talloc/configure.in | 2 +- source4/lib/talloc/talloc.c | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/Makefile.in b/source4/lib/talloc/Makefile.in index 6efa9e1920..f11124e707 100644 --- a/source4/lib/talloc/Makefile.in +++ b/source4/lib/talloc/Makefile.in @@ -6,7 +6,7 @@ mandir = @mandir@ XSLTPROC = @XSLTPROC@ INSTALLCMD = @INSTALL@ CC = @CC@ -CFLAGS=@CFLAGS@ +CFLAGS = @CFLAGS@ -DHAVE_CONFIG_H= LIBOBJ = talloc.o diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index 8e7e8252fd..d4afacc7a7 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -6,7 +6,7 @@ if test "x$GCC" = "xyes"; then fi AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) -AC_CHECK_HEADERS(stdint.h stdarg.h) +AC_CHECK_HEADERS(stdint.h stdarg.h unistd.h sys/types.h) AC_CONFIG_HEADER(config.h) sinclude(config.m4) AC_OUTPUT(Makefile talloc.pc) diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index d3fa961c74..8a29c8c014 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -27,12 +27,21 @@ */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include #include #include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_UNISTD_H #include +#endif #ifdef HAVE_STDARG_H #include -- cgit From 8557a22f81e7fa6b323126cc070fe89aea222412 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 21:09:51 +0000 Subject: r6829: include the talloc autoconf tests when building ldb standalone (This used to be commit 3339a886178eebf19ce9bbe0dcca16e9d6e3c12c) --- source4/lib/ldb/configure.in | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index ed61344317..a04ae00690 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -1,3 +1,4 @@ +AC_PREREQ(2.50) AC_DEFUN([AC_CHECK_LIB_EXT], [ AC_CHECK_LIB([$1],[$3],[$4],[$5],[$7]) ac_cv_lib_ext_$1_$3=$ac_cv_lib_$1_$3 @@ -26,4 +27,5 @@ sinclude(ldap.m4) WITH_LDAP=$with_ldap_support AC_SUBST(WITH_LDAP) sinclude(config.m4) +sinclude(../talloc/config.m4) AC_OUTPUT(Makefile ldb.pc) -- cgit From eaa11475cdf64449bf53560e9f89c282c0197478 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 21:22:54 +0000 Subject: r6830: put header checks in config.m4 so when it is included by other projects the right configure checks are done (This used to be commit 57c8db4f9aecd161d61cf0011e960edc718d7cf0) --- source4/lib/talloc/config.m4 | 1 + source4/lib/talloc/configure.in | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/config.m4 b/source4/lib/talloc/config.m4 index 60e89f4392..70fedade4a 100644 --- a/source4/lib/talloc/config.m4 +++ b/source4/lib/talloc/config.m4 @@ -7,3 +7,4 @@ if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then fi AC_CHECK_TYPES(intptr_t) +AC_CHECK_HEADERS(stdint.h stdarg.h unistd.h sys/types.h) diff --git a/source4/lib/talloc/configure.in b/source4/lib/talloc/configure.in index d4afacc7a7..24a2e4ead6 100644 --- a/source4/lib/talloc/configure.in +++ b/source4/lib/talloc/configure.in @@ -6,7 +6,6 @@ if test "x$GCC" = "xyes"; then fi AC_PROG_INSTALL AC_PATH_PROG(XSLTPROC,xsltproc) -AC_CHECK_HEADERS(stdint.h stdarg.h unistd.h sys/types.h) AC_CONFIG_HEADER(config.h) sinclude(config.m4) AC_OUTPUT(Makefile talloc.pc) -- cgit From 2cb07b0f1bab01a406d8d75d19d1039ce5ed3105 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 21:42:11 +0000 Subject: r6831: talloc now requires config.h (this fixes ldb build) (This used to be commit aac86583a9bff7d882ed56633126a1d9f27eea6a) --- source4/lib/talloc/talloc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 8a29c8c014..e0f4cf9aff 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -27,9 +27,7 @@ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include #include -- cgit From 9a9cf9e0753c7cf040feecf670c0986a17c16dce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 May 2005 22:31:45 +0000 Subject: r6833: split out the routine that calculates the diff between two ldb messages from ldbedit, so other progs can use it. (This used to be commit fa4f33558af3c65ff31424c01db16cb9d427503d) --- source4/lib/ldb/common/ldb_msg.c | 55 ++++++++++++++++++++++++++++++++++++++++ source4/lib/ldb/include/ldb.h | 4 +++ source4/lib/ldb/tools/ldbedit.c | 47 +++------------------------------- 3 files changed, 63 insertions(+), 43 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 4c903cf936..7a6dea049a 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -456,3 +456,58 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, return msg2; } + + +/* + return a ldb_message representing the differences between msg1 and msg2. If you + then use this in a ldb_modify() call it can be used to save edits to a message +*/ +struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2) +{ + struct ldb_message *mod; + struct ldb_message_element *el; + unsigned int i; + + mod = ldb_msg_new(ldb); + + mod->dn = msg1->dn; + mod->num_elements = 0; + mod->elements = NULL; + + msg2 = ldb_msg_canonicalize(ldb, msg2); + if (msg2 == NULL) { + return NULL; + } + + /* look in msg2 to find elements that need to be added + or modified */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg1, msg2->elements[i].name); + + if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) { + continue; + } + + if (ldb_msg_add(ldb, mod, + &msg2->elements[i], + el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { + return NULL; + } + } + + /* look in msg1 to find elements that need to be deleted */ + for (i=0;inum_elements;i++) { + el = ldb_msg_find_element(msg2, msg1->elements[i].name); + if (!el) { + if (ldb_msg_add_empty(ldb, mod, + msg1->elements[i].name, + LDB_FLAG_MOD_DELETE) != 0) { + return NULL; + } + } + } + + return mod; +} diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index f748bb6b42..18d974cf42 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -295,6 +295,10 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, const struct ldb_message *msg); +struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2); + struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v); /* diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 4c41b6b19a..851eaeebdf 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -65,51 +65,12 @@ static int modify_record(struct ldb_context *ldb, struct ldb_message *msg2) { struct ldb_message *mod; - struct ldb_message_element *el; - unsigned int i; - int count = 0; - mod = ldb_msg_new(ldb); - - mod->dn = msg1->dn; - mod->num_elements = 0; - mod->elements = NULL; - - msg2 = ldb_msg_canonicalize(ldb, msg2); - if (msg2 == NULL) { - fprintf(stderr, "Failed to canonicalise msg2\n"); + mod = ldb_msg_diff(ldb, msg1, msg2); + if (mod == NULL) { + fprintf(stderr, "Failed to calculate message differences\n"); return -1; } - - /* look in msg2 to find elements that need to be added - or modified */ - for (i=0;inum_elements;i++) { - el = ldb_msg_find_element(msg1, msg2->elements[i].name); - - if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) { - continue; - } - - if (ldb_msg_add(ldb, mod, - &msg2->elements[i], - el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { - return -1; - } - count++; - } - - /* look in msg1 to find elements that need to be deleted */ - for (i=0;inum_elements;i++) { - el = ldb_msg_find_element(msg2, msg1->elements[i].name); - if (!el) { - if (ldb_msg_add_empty(ldb, mod, - msg1->elements[i].name, - LDB_FLAG_MOD_DELETE) != 0) { - return -1; - } - count++; - } - } if (mod->num_elements == 0) { return 0; @@ -125,7 +86,7 @@ static int modify_record(struct ldb_context *ldb, ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod); } - return count; + return mod->num_elements; } /* -- cgit From 57bbd16b4172ce53cc631cb4d66918f9a9e8f6ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 17 May 2005 05:48:30 +0000 Subject: r6845: make the talloc header align to 40 bytes, which costs us an extra 4 bytes per allocation, but makes it much more portable (This used to be commit 257027a571da254c16b0b456cb1cbec284d7fda0) --- source4/lib/talloc/talloc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index e0f4cf9aff..6b6eb87f21 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -97,17 +97,20 @@ struct talloc_chunk { struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; size_t size; - unsigned magic; talloc_destructor_t destructor; const char *name; + union { + unsigned magic; + double align_dummy; + } u; }; /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { + if (tc->u.magic != TALLOC_MAGIC) { + if (tc->u.magic == TALLOC_MAGIC_FREE) { TALLOC_ABORT("Bad talloc magic value - double free"); } else { TALLOC_ABORT("Bad talloc magic value - unknown value"); @@ -180,7 +183,7 @@ void *_talloc(const void *context, size_t size) if (tc == NULL) return NULL; tc->size = size; - tc->magic = TALLOC_MAGIC; + tc->u.magic = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -559,7 +562,7 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->magic = TALLOC_MAGIC_FREE; + tc->u.magic = TALLOC_MAGIC_FREE; free(tc); return 0; @@ -599,7 +602,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } /* by resetting magic we catch users of the old memory */ - tc->magic = TALLOC_MAGIC_FREE; + tc->u.magic = TALLOC_MAGIC_FREE; #if ALWAYS_REALLOC new_ptr = malloc(size + sizeof(*tc)); @@ -611,12 +614,12 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n new_ptr = realloc(tc, size + sizeof(*tc)); #endif if (!new_ptr) { - tc->magic = TALLOC_MAGIC; + tc->u.magic = TALLOC_MAGIC; return NULL; } tc = new_ptr; - tc->magic = TALLOC_MAGIC; + tc->u.magic = TALLOC_MAGIC; if (tc->parent) { tc->parent->child = new_ptr; } -- cgit From f9ad3029ae97f5d5beed3f85ad912830fa8d7930 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 17 May 2005 20:18:06 +0000 Subject: r6863: lib-friendlier names + fix some dependencies (This used to be commit cab81a51bfd435b54e6f0d5a308aaf6828d38c00) --- source4/lib/basic.mk | 2 +- source4/lib/com/config.mk | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index c1a34d39bb..5c094a6973 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -86,7 +86,7 @@ ADD_OBJ_FILES = \ lib/credentials.o REQUIRED_SUBSYSTEMS = \ LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC \ - SOCKET_WRAPPER + SOCKET_WRAPPER CONFIG # End SUBSYSTEM LIBBASIC ############################## diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk index a4fe891864..4c0377795c 100644 --- a/source4/lib/com/config.mk +++ b/source4/lib/com/config.mk @@ -1,21 +1,17 @@ -[SUBSYSTEM::LIBCOM] +[SUBSYSTEM::COM] INIT_OBJ_FILES = \ lib/com/tables.o \ lib/com/rot.o \ lib/com/main.o -################################################ -# Start SUBSYSTEM LIBDCOM -[SUBSYSTEM::LIBDCOM] +[SUBSYSTEM::DCOM] INIT_OBJ_FILES = \ lib/com/dcom/main.o \ lib/com/dcom/tables.o -REQUIRED_SUBSYSTEMS = LIBCOM DCOM_PROXY_DCOM RPC_NDR_REMACT \ +REQUIRED_SUBSYSTEMS = COM DCOM_PROXY_DCOM RPC_NDR_REMACT \ RPC_NDR_OXIDRESOLVER -# End SUBSYSTEM LIBDCOM -################################################ [MODULE::com_simple] -SUBSYSTEM = LIBCOM +SUBSYSTEM = COM INIT_OBJ_FILES = lib/com/classes/simple.o INIT_FUNCTION = com_simple_init -- cgit From ca4e0c8539e5b0e01ca9d68eba8692c544d7a4d6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 17 May 2005 21:43:47 +0000 Subject: r6867: this code will change the way the @ATTRIBUTES object is handled this object properties are now used as multivalue attributes now all values inserted are checked against a "valid values table" eg: this form is now accepted: dn: @ATTRIBUTES uid: CASE_INSENSITIVE uid: WILDCARD this form is now rejected: dn: @ATTRIBUTES uid: CASE_INSENSITIVE WILDCARD please update your .ldb files if you make use of @ATTRIBUTES (sam.ldb heavily uses it) the code passes all make test tests for both tdb and ldap, it also passes the new test to check for wrong @ATTRIBUTES attribute values Simo. (This used to be commit 1295b891a26c2cb2c34540f90ded83390cf87da2) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 64 ++++++++++++++---------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 39 ++++++++++++++- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 + source4/lib/ldb/tests/schema-tests/schema.ldif | 9 ++-- source4/lib/ldb/tests/test-attribs.ldif | 3 +- source4/lib/ldb/tests/test-generic.sh | 3 ++ source4/lib/ldb/tests/test-index.ldif | 3 +- source4/lib/ldb/tests/test-wrong_attributes.ldif | 3 ++ 8 files changed, 93 insertions(+), 33 deletions(-) create mode 100644 source4/lib/ldb/tests/test-wrong_attributes.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index ec22aca3ec..0fe573a829 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -37,6 +37,21 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" + +/* valid attribute flags */ +static const struct { + const char *name; + int value; +} ltdb_valid_attr_flags[] = { + { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, + { "INTEGER", LTDB_FLAG_INTEGER }, + { "WILDCARD", LTDB_FLAG_WILDCARD }, + { "HIDDEN", LTDB_FLAG_HIDDEN }, + { "NONE", LTDB_FLAG_NONE }, + { NULL, 0 } +}; + + /* initialise the baseinfo record */ @@ -245,18 +260,7 @@ int ltdb_increase_sequence_number(struct ldb_module *module) int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) { struct ltdb_private *ltdb = module->private_data; - const char *attrs; - const struct { - const char *name; - int value; - } names[] = { - { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, - { "INTEGER", LTDB_FLAG_INTEGER }, - { "WILDCARD", LTDB_FLAG_WILDCARD }, - { "HIDDEN", LTDB_FLAG_HIDDEN }, - { NULL, 0} - }; - size_t len; + const struct ldb_message_element *attr_el; int i, ret=0; if (ltdb->cache->last_attribute.name && @@ -269,30 +273,22 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE; } - attrs = ldb_msg_find_string(ltdb->cache->attributes, attr_name, NULL); + attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name); - if (!attrs) { + if (!attr_el) { /* check if theres a wildcard attribute */ - attrs = ldb_msg_find_string(ltdb->cache->attributes, "*", NULL); + attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*"); - if (!attrs) { + if (!attr_el) { return ret; } } - /* we avoid using strtok and friends due to their nasty - interface. This is a little trickier, but much nicer - from a C interface point of view */ - while ((len = strcspn(attrs, " ,")) > 0) { - for (i=0;names[i].name;i++) { - if (strncmp(names[i].name, attrs, len) == 0 && - names[i].name[len] == 0) { - ret |= names[i].value; - } + for (i = 0; i < attr_el->num_values; i++) { + if (strcmp(ltdb_valid_attr_flags[i].name, attr_el->values[i].data) == 0) { + ret |= ltdb_valid_attr_flags[i].value; } - attrs += len; - attrs += strspn(attrs, " ,"); } talloc_free(ltdb->cache->last_attribute.name); @@ -302,3 +298,17 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) return ret; } + +int ltdb_check_at_attributes_values(const struct ldb_val *value) +{ + int i; + + for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) { + if ((strcmp(ltdb_valid_attr_flags[i].name, value->data) == 0)) { + return 0; + } + } + + return -1; +} + diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index b47d79de52..f6a23d7433 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -281,6 +281,33 @@ int ltdb_unlock_read(struct ldb_module *module) return 0; } +/* + check special dn's have valid attributes + currently only @ATTRIBUTES is checked +*/ +int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ltdb_private *ltdb = module->private_data; + int i, j; + + if (strcmp(msg->dn, LTDB_ATTRIBUTES) != 0) { + return 0; + } + + /* we have @ATTRIBUTES, let's check attributes are fine */ + /* should we check that we deny multivalued attributes ? */ + for (i = 0; i < msg->num_elements; i++) { + for (j = 0; j < msg->elements[i].num_values; j++) { + if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) { + ltdb->last_err_string = "Invalid attribute value in an @ATTRIBUTES entry"; + return -1; + } + } + } + + return 0; +} + /* we've made a modification to a dn - possibly reindex and @@ -351,6 +378,11 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ltdb->last_err_string = NULL; + ret = ltdb_check_special_dn(module, msg); + if (ret != 0) { + return ret; + } + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } @@ -359,7 +391,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ltdb_unlock(module, LDBLOCK); return -1; } - + ret = ltdb_store(module, msg, TDB_INSERT); if (ret == 0) { @@ -736,6 +768,11 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ltdb->last_err_string = NULL; + ret = ltdb_check_special_dn(module, msg); + if (ret != 0) { + return ret; + } + if (ltdb_lock(module, LDBLOCK) != 0) { return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index dfb985319e..eb6c7825d2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -51,6 +51,7 @@ struct ltdb_private { #define LTDB_FLAG_WILDCARD (1<<2) #define LTDB_FLAG_OBJECTCLASS (1<<3) #define LTDB_FLAG_HIDDEN (1<<4) +#define LTDB_FLAG_NONE 0 /* The following definitions come from lib/ldb/ldb_tdb/ldb_cache.c */ @@ -58,6 +59,7 @@ int ltdb_cache_reload(struct ldb_module *module); int ltdb_cache_load(struct ldb_module *module); int ltdb_increase_sequence_number(struct ldb_module *module); int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name); +int ltdb_check_at_attributes_values(const struct ldb_val *value); /* The following definitions come from lib/ldb/ldb_tdb/ldb_index.c */ diff --git a/source4/lib/ldb/tests/schema-tests/schema.ldif b/source4/lib/ldb/tests/schema-tests/schema.ldif index 651fdac41f..59757d22a9 100644 --- a/source4/lib/ldb/tests/schema-tests/schema.ldif +++ b/source4/lib/ldb/tests/schema-tests/schema.ldif @@ -12,9 +12,12 @@ dn: @ATTRIBUTES realm: CASE_INSENSITIVE userPrincipalName: CASE_INSENSITIVE servicePrincipalName: CASE_INSENSITIVE -name: CASE_INSENSITIVE WILDCARD -dn: CASE_INSENSITIVE WILDCARD -sAMAccountName: CASE_INSENSITIVE WILDCARD +name: CASE_INSENSITIVE +name: WILDCARD +dn: CASE_INSENSITIVE +dn: WILDCARD +sAMAccountName: CASE_INSENSITIVE +sAMAccountName: WILDCARD objectClass: CASE_INSENSITIVE unicodePwd: HIDDEN ntPwdHash: HIDDEN diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif index 4bfb1ebd65..e6fe1dcf5a 100644 --- a/source4/lib/ldb/tests/test-attribs.ldif +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -1,5 +1,6 @@ dn: @ATTRIBUTES -uid: CASE_INSENSITIVE WILDCARD +uid: CASE_INSENSITIVE +uid: WILDCARD cn: CASE_INSENSITIVE ou: CASE_INSENSITIVE dn: CASE_INSENSITIVE diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 2b2ab2e78a..78fed1c12b 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -25,6 +25,9 @@ time $VALGRIND bin/ldbtest -r 1000 -s 10 || exit 1 echo "Adding index" $VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 +echo "Adding attributes" +$VALGRIND bin/ldbadd tests/test-wrong_attributes.ldif || exit 1 + echo "testing indexed search" $VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 $VALGRIND bin/ldbsearch '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index 24ac408764..7ba0106394 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -3,7 +3,8 @@ dn: @INDEXLIST @IDXATTR: objectclass dn: @ATTRIBUTES -uid: CASE_INSENSITIVE WILDCARD +uid: CASE_INSENSITIVE +uid: WILDCARD dn: @SUBCLASSES top: person diff --git a/source4/lib/ldb/tests/test-wrong_attributes.ldif b/source4/lib/ldb/tests/test-wrong_attributes.ldif new file mode 100644 index 0000000000..27f45f0e56 --- /dev/null +++ b/source4/lib/ldb/tests/test-wrong_attributes.ldif @@ -0,0 +1,3 @@ +dn: @ATTRIBUTES +uid: CASE_INTENSIVE + -- cgit From fc21940da5d35ae03f73834fb6ed61de5dc15bf1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 May 2005 10:02:53 +0000 Subject: r6931: declare this to avoid warnings until we have loadable modules (This used to be commit 73258909dbd4e14f3c8eb5cebe0647539d141c8d) --- source4/lib/ldb/include/ldb_private.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 7a0b2fef75..4f86655a76 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -110,6 +110,7 @@ struct ldb_context *lldb_connect(const char *url, unsigned int flags, const char *options[]); struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); +struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); const char **ldb_options_parse(const char **options, int *ldbopts, const char *arg); -- cgit From 3d97821243b0d4af866ccc158e0134a49c0e4901 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 May 2005 10:27:51 +0000 Subject: r6934: thanks to HotaruT for pointing out skel.c was not in line with the rest of the code (This used to be commit 9f0963c97f94687a1226d224f80b2aac1128d1a0) --- source4/lib/ldb/modules/skel.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 09f2452365..33e5d53cef 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,6 +36,10 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +static struct private_data { + const char *error_string; +}; + /* search */ static int skel_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, @@ -69,13 +73,13 @@ static int skel_rename_record(struct ldb_module *module, const char *olddn, cons } /* named_lock */ -static const char *skel_named_lock(struct ldb_module *module, const char *lockname) +static int skel_named_lock(struct ldb_module *module, const char *lockname) { return ldb_next_named_lock(module, lockname); } /* named_unlock */ -static const char *skel_named_unlock(struct ldb_module *module, const char *lockname) +static int skel_named_unlock(struct ldb_module *module, const char *lockname) { return ldb_next_named_unlock(module, lockname); } @@ -105,18 +109,28 @@ static const struct ldb_module_ops skel_ops = { skel_errstring }; -#ifdef HAVE_DLOPEN - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#ifdef HAVE_DLOPEN_DISABLED +struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) #else -struct ldb_module *skel_plugin_init(struct ldb_context *ldb, const char *options[]) +struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options[]) #endif { struct ldb_module *ctx; + struct private_data *data; - ctx = (struct ldb_module *)malloc(sizeof(struct ldb_module)); + ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; + data = talloc(ctx, struct private_data); + if (data == NULL) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->private_data = NULL; -- cgit From e4553307c1e3e44a7f772818aae18cca0aca92a3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 22 May 2005 10:40:54 +0000 Subject: r6935: don't do three things at a time :-) (This used to be commit a97eb63c11be6ce2bb94bca61078b303f15c9b9a) --- source4/lib/ldb/modules/skel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 33e5d53cef..9fb01941c9 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,7 +36,8 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -static struct private_data { +const struct private_data { + const char *error_string; }; @@ -133,7 +134,6 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options ctx->ldb = ldb; ctx->prev = ctx->next = NULL; - ctx->private_data = NULL; ctx->ops = &skel_ops; talloc_set_destructor (ctx, skel_destructor); -- cgit From 4f4b92a6904210a467282a997e81a4e8ab1f415a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 May 2005 06:49:17 +0000 Subject: r6937: some minor fixes and updates metze (This used to be commit 03b1ff48f97fa81c515f90a398c6f8cde579cb51) --- source4/lib/ldb/modules/skel.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 9fb01941c9..505b19a288 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -36,9 +36,9 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -const struct private_data { +struct private_data { - const char *error_string; + char *errstring; }; /* search */ @@ -93,21 +93,23 @@ static const char *skel_errstring(struct ldb_module *module) static int skel_destructor(void *module_ctx) { - struct ldb_module *ctx = module_ctx; + struct ldb_module *ctx = talloc_get_type(module_ctx, struct ldb_module); + struct private_data *data = talloc_get_type(ctx->private_data, struct private_data); /* put your clean-up functions here */ + if (data->errstring) talloc_free(data->errstring); return 0; } static const struct ldb_module_ops skel_ops = { - "skel", - skel_search, - skel_add_record, - skel_modify_record, - skel_delete_record, - skel_rename_record, - skel_named_lock, - skel_named_unlock, - skel_errstring + .name = "skel", + .search = skel_search, + .add_record = skel_add_record, + .modify_record = skel_modify_record, + .delete_record = skel_delete_record, + .rename_record = skel_rename_record, + .named_lock = skel_named_lock, + .named_unlock = skel_named_unlock, + .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED @@ -129,7 +131,7 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options return NULL; } - data->error_string = NULL; + data->errstring = NULL; ctx->private_data = data; ctx->ldb = ldb; -- cgit From 4867378592656d812fcd02d1ea24ccb2c99bf9b7 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 24 May 2005 05:51:20 +0000 Subject: r6951: Fix all calls to setup_logging() that use 'True' as a second argument. In Samba4 this is now an enum. Possibly by accident, True just happens to map to the right value in this case. (-: (This used to be commit affacc539864435cbc749a4c1a6b848c61b7182b) --- source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index dfc8be13ca..4260a56142 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -157,7 +157,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, return 1; } } - setup_logging(argv[0], True); + setup_logging(argv[0], DEBUG_STDOUT); poptFreeContext(pc); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index aeb418560d..5c9851b71b 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -766,7 +766,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging(argv[0], True); + setup_logging(argv[0], DEBUG_STDOUT); if (remote) { error = reg_open_remote (&h, cmdline_credentials, remote); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index ecc2bfc7aa..f1fd740830 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -392,7 +392,7 @@ static char **reg_completion(const char *text, int start, int end) while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging("regtree", True); + setup_logging("regtree", DEBUG_STDOUT); if (remote) { error = reg_open_remote (&h, cmdline_credentials, remote); diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 72cb0670de..2cf5f6ab96 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -102,7 +102,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging("regtree", True); + setup_logging("regtree", DEBUG_STDOUT); if (remote) { error = reg_open_remote(&h, cmdline_credentials, remote); -- cgit From 079b96349b352157516390b6e12e679ab638cfb0 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 24 May 2005 05:53:50 +0000 Subject: r6952: Remove unneeded include of popt_common.h (This used to be commit 67d7bf877576853a05a156069ea4b97a1755e897) --- source4/lib/credentials.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index ed9a9788ab..1dbb536f9e 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -22,7 +22,6 @@ #include "includes.h" #include "system/filesys.h" -#include "lib/cmdline/popt_common.h" #include "include/secrets.h" #include "lib/ldb/include/ldb.h" -- cgit From 26eff174ee8bf6b76ecf7f641286ad59c08f2672 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 24 May 2005 13:31:22 +0000 Subject: r6956: added start of ldb_sqlite3 work (This used to be commit ac396a4a53756f40ad5e1d45ca23e002f9c649e7) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 951 ++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 25 + source4/lib/ldb/ldb_sqlite3/schema | 240 ++++++++ 3 files changed, 1216 insertions(+) create mode 100644 source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c create mode 100644 source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h create mode 100644 source4/lib/ldb/ldb_sqlite3/schema (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c new file mode 100644 index 0000000000..67debd8a4e --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -0,0 +1,951 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb sqlite backend + * + * Description: core files for SQLITE3 backend + * + * Author: Derrell Lipman (based on Andrew Tridgell's LDAP backend) + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/ldb_sqlite3/ldb_sqlite3.h" + +#if 0 +/* + we don't need this right now, but will once we add some backend + options +*/ + +/* + find an option in an option list (a null terminated list of strings) + + this assumes the list is short. If it ever gets long then we really + should do this in some smarter way + */ +static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, const char *name) +{ + int i; + size_t len = strlen(name); + + if (!lsqlite3->options) return NULL; + + for (i=0;lsqlite3->options[i];i++) { + if (strncmp(lsqlite3->options[i], name, len) == 0 && + lsqlite3->options[i][len] == '=') { + return &lsqlite3->options[i][len+1]; + } + } + + return NULL; +} +#endif + +/* + rename a record +*/ +static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const char *newdn) +{ + int column; + struct lsqlite3_private *lsqlite3 = module->private_data; + + /* ignore ltdb specials */ + if (olddn[0] == '@' ||newdn[0] == '@') { + return 0; + } + + /* Bind old distinguished names */ + column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":oldDN"); + if (sqlite3_bind_text(lsqlite3->renameDN, column, + olddn, strlen(olddn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + /* Bind new distinguished names */ + column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":newDN"); + if (sqlite3_bind_text(lsqlite3->renameDN, column, + newdn, strlen(newdn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + do { + lsqlite3->last_rc = sqlite3_step(lsqlite3->renameDN); + (void) sqlite3_reset(lsqlite3->renameDN); + } while lsqlite3->last_rc == SQLITE3_BUSY; + + return lsqlite3->last_rc == 0 ? 0 : -1; +} + +/* + delete a record +*/ +static int lsqlite3_delete(struct ldb_module *module, const char *dn) +{ + int ret = 0; + int column; + struct lsqlite3_private *lsqlite3 = module->private_data; + + /* ignore ltdb specials */ + if (dn[0] == '@') { + return 0; + } + + /* Bind new distinguished names */ + column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":dn"); + if (sqlite3_bind_text(lsqlite3->deleteDN, column, + dn, strlen(dn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + do { + lsqlite3->last_rc = sqlite3_step(lsqlite3->deleteDN); + (void) sqlite3_reset(lsqlite3->deleteDN); + } while lsqlite3->last_rc == SQLITE3_BUSY; + + return lsqlite3->last_rc == 0 ? 0 : -1; +} + +/* + free a search result +*/ +static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message **res) +{ + talloc_free(res); + return 0; +} + + +/* + add a single set of ldap message values to a ldb_message +*/ +static int lsqlite3_add_msg_attr(struct ldb_context *ldb, + struct ldb_message *msg, + const char *attr, struct berval **bval) +{ + int count, i; + struct ldb_message_element *el; + + count = ldap_count_values_len(bval); + + if (count <= 0) { + return -1; + } + + el = talloc_realloc(msg, msg->elements, struct ldb_message_element, + msg->num_elements + 1); + if (!el) { + errno = ENOMEM; + return -1; + } + + msg->elements = el; + + el = &msg->elements[msg->num_elements]; + + el->name = talloc_strdup(msg->elements, attr); + if (!el->name) { + errno = ENOMEM; + return -1; + } + el->flags = 0; + + el->num_values = 0; + el->values = talloc_array(msg->elements, struct ldb_val, count); + if (!el->values) { + errno = ENOMEM; + return -1; + } + + for (i=0;ivalues[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len); + if (!el->values[i].data) { + return -1; + } + el->values[i].length = bval[i]->bv_len; + el->num_values++; + } + + msg->num_elements++; + + return 0; +} + +/* + search for matching records +*/ +static int lsqlite3_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + int count, msg_count; + + if (base == NULL) { + base = ""; + } + + lsqlite3->last_rc = ldap_search_s(lsqlite3->ldap, base, (int)scope, + expression, + discard_const_p(char *, attrs), + 0, &ldapres); + if (lsqlite3->last_rc != LDAP_SUCCESS) { + return -1; + } + + count = ldap_count_entries(lsqlite3->ldap, ldapres); + if (count == -1 || count == 0) { + ldap_msgfree(ldapres); + return count; + } + + (*res) = talloc_array(lsqlite3, struct ldb_message *, count+1); + if (! *res) { + ldap_msgfree(ldapres); + errno = ENOMEM; + return -1; + } + + (*res)[0] = NULL; + + msg_count = 0; + + /* loop over all messages */ + for (msg=ldap_first_entry(lsqlite3->ldap, ldapres); + msg; + msg=ldap_next_entry(lsqlite3->ldap, msg)) { + BerElement *berptr = NULL; + char *attr, *dn; + + if (msg_count == count) { + /* hmm, got too many? */ + ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n"); + break; + } + + (*res)[msg_count] = talloc(*res, struct ldb_message); + if (!(*res)[msg_count]) { + goto failed; + } + (*res)[msg_count+1] = NULL; + + dn = ldap_get_dn(lsqlite3->ldap, msg); + if (!dn) { + goto failed; + } + + (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn); + ldap_memfree(dn); + if (!(*res)[msg_count]->dn) { + goto failed; + } + + + (*res)[msg_count]->num_elements = 0; + (*res)[msg_count]->elements = NULL; + (*res)[msg_count]->private_data = NULL; + + /* loop over all attributes */ + for (attr=ldap_first_attribute(lsqlite3->ldap, msg, &berptr); + attr; + attr=ldap_next_attribute(lsqlite3->ldap, msg, berptr)) { + struct berval **bval; + bval = ldap_get_values_len(lsqlite3->ldap, msg, attr); + + if (bval) { + lsqlite3_add_msg_attr(ldb, (*res)[msg_count], attr, bval); + ldap_value_free_len(bval); + } + + ldap_memfree(attr); + } + if (berptr) ber_free(berptr, 0); + + msg_count++; + } + + ldap_msgfree(ldapres); + + return msg_count; + +failed: + if (*res) lsqlite3_search_free(module, *res); + return -1; +} + + +/* + Issue a series of SQL statements to implement the requests in the ldb_message +*/ +static int lsqlite3_msg_to_sql(struct ldb_context *ldb, + const struct ldb_message *msg, + int modify_existing) +{ + unsigned int i, j; + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + sqlite3_stmt *stmt = NULL; + + for (i=0;inum_elements;i++) { + const struct ldb_message_element *el = &msg->elements[i]; + + if (! modify_existing) { + /* This is a new DN. Bind new distinguished name */ + column = + sqlite3_bind_parameter_index( + lsqlite3->queries.newDN, + ":dn"); + if (sqlite3_bind_text(lsqlite3->queries.newDN, column, + msg->dn, strlen(msg->dn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + /* Add this new DN */ + do { + lsqlite3->last_rc = + sqlite3_step(lsqlite3->queries.newDN); + (void) sqlite3_reset(lsqlite3->queries.newDN); + } while lsqlite3->last_rc == SQLITE_BUSY; + + if (lsqlite3->last_rc != SQLITE_DONE) { + return -1; + } + + dn_id = last_insert_rowid(lsqlite3->sqlite3); + + stmt = lsqlite3->queries.newAttribute; + + } else { + /* Get the dn_id for the specified DN */ + xxx; + + switch (el->flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + stmt = lsqlite3->queries.addAttrValuePair; + break; + case LDB_FLAG_MOD_DELETE: + stmt = lsqlite3->queries.deleteAttrValuePairs; + break; + case LDB_FLAG_MOD_REPLACE: + stmt = lsqlite3->queries.replaceAttrValuePairs; + break; + } + + } + + for (j=0;jnum_values;j++) { + mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals, + struct berval); + if (!mods[num_mods]->mod_vals.modv_bvals[j]) { + goto failed; + } + mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data; + mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length; + } + mods[num_mods]->mod_vals.modv_bvals[j] = NULL; + num_mods++; + } + + return mods; + +failed: + talloc_free(mods); + return NULL; +} + + +/* + add a record +*/ +static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + LDAPMod **mods; + int ret = 0; + + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + + mods = lsqlite3_msg_to_mods(ldb, msg, 0); + + lsqlite3->last_rc = ldap_add_s(lsqlite3->ldap, msg->dn, mods); + if (lsqlite3->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + talloc_free(mods); + + return ret; +} + + +/* + modify a record +*/ +static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + LDAPMod **mods; + int ret = 0; + + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + + mods = lsqlite3_msg_to_mods(ldb, msg, 1); + + lsqlite3->last_rc = ldap_modify_s(lsqlite3->ldap, msg->dn, mods); + if (lsqlite3->last_rc != LDAP_SUCCESS) { + ret = -1; + } + + talloc_free(mods); + + return ret; +} + +static int lsqlite3_lock(struct ldb_module *module, const char *lockname) +{ + int ret = 0; + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + + if (lockname == NULL) { + return -1; + } + + /* If we're already locked, just update lock count */ + if (++lsqlite3->lock_count > 1) { + return -1; + } + + /* Write-lock (but not read-lock) the database */ + lsqlite3->last_rc = sqlite3_step(lsqlite3->begin); + + /* Ready the compiled statememt for its next use */ + (void ) sqlite_reset(lsqlite3->begin); + + return lsqlite3->last_rc == 0 ? 0 : -1; +} + +static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) +{ + int ret = 0; + struct ldb_context *ldb = module->ldb; + struct lsqlite3_private *lsqlite3 = module->private_data; + + if (lockname == NULL) { + return -1; + } + + /* If we're not already locked, there's nothing to do */ + if (lsqlite3->lock_count == 0) { + return 0; + } + + /* Decrement lock count */ + if (--lsqlite3->lock_count == 0) { + + /* Final unlock. Unlock the database */ + lsqlite3->last_rc = sqlite3_step(lsqlite3->commit); + + /* Ready the compiled statememt for its next use */ + (void ) sqlite_reset(lsqlite3->commit); + } + + return lsqlite3->last_rc == 0 ? 0 : -1; +} + +/* + return extended error information +*/ +static const char *lsqlite3_errstring(struct ldb_module *module) +{ + struct lsqlite3_private *lsqlite3 = module->private_data; + return sqlite3_errmsg(lsqlite3->sqlite3); +} + + +static const struct ldb_module_ops lsqlite3_ops = { + "sqlite", + lsqlite3_search, + lsqlite3_search_free, + lsqlite3_add, + lsqlite3_modify, + lsqlite3_delete, + lsqlite3_rename, + lsqlite3_lock, + lsqlite3_unlock, + lsqlite3_errstring +}; + + +static int lsqlite3_destructor(void *p) +{ + struct lsqlite3_private *lsqlite3 = p; + (void) sqlite3_close(lsqlite3->sqlite3); + return 0; +} + +static int lsqlite3_initialize(lsqlite3_private *lsqlite3, + const char *url) +{ + int bNewDatabase = False; + char *p; + char *pTail; + struct stat statbuf; + sqlite3_stmt *stmt; + const char *schema = + " + -- ------------------------------------------------------ + + PRAGMA auto_vacuum=1; + + -- ------------------------------------------------------ + + BEGIN EXCLUSIVE; + + -- ------------------------------------------------------ + + CREATE TABLE ldb_info AS + SELECT 'LDB' AS database_type, + '1.0' AS version; + + CREATE TABLE ldb_distinguished_names + ( + dn_id INTEGER PRIMARY KEY AUTOINCREMENT, + dn TEXT UNIQUE + ); + + CREATE TABLE ldb_object_classes + ( + class_name TEXT PRIMARY KEY, + tree_key TEXT, + max_child_num INTEGER + ); + + CREATE TABLE ldb_dn_object_classes + ( + dn_id INTEGER REFERENCES ldb_distinguished_names, + class_name TEXT REFERENCES ldb_object_classes + ); + + CREATE TABLE ldb_attributes + ( + attr_name TEXT PRIMARY KEY, + case_insensitive_p BOOLEAN DEFAULT FALSE, + wildcard_p BOOLEAN DEFAULT FALSE, + hidden_p BOOLEAN DEFAULT FALSE, + integer_p BOOLEAN DEFAULT FALSE + ); + + CREATE TABLE ldb_attr_value_pairs + ( + dn_id INTEGER REFERENCES ldb_distinguished_names, + attr_name TEXT REFERENCES ldb_attributes, + attr_value TEXT + ); + + -- ------------------------------------------------------ + + CREATE TRIGGER ldb_distinguished_names_delete_tr + AFTER DELETE + ON ldb_distinguished_names + FOR EACH ROW + BEGIN + DELETE FROM ldb_attr_value_pairs + WHERE dn_id = old.dn_id; + DELETE FROM ldb_dn_object_classes + WHERE dn_id = old.dn_id; + END; + + CREATE TRIGGER ldb_attr_value_pairs_insert_tr + BEFORE INSERT + ON ldb_attr_value_pairs + FOR EACH ROW + BEGIN + INSERT OR IGNORE INTO ldb_attributes + (attr_name) + VALUES + (new.attr_name); + END; + + CREATE TRIGGER ldb_attr_value_pairs_delete_tr + AFTER DELETE + ON ldb_attr_value_pairs + FOR EACH ROW + BEGIN + DELETE FROM ldb_attributes + WHERE (SELECT COUNT(*) + FROM ldb_attr_value_pairs + WHERE attr_name = old.attr_name) = 0 + AND attr_name = old.attr_name; + END; + + -- ------------------------------------------------------ + + CREATE INDEX ldb_distinguished_names_dn_idx + ON ldb_distinguished_names (dn); + + CREATE INDEX ldb_object_classes_tree_key_idx + ON ldb_object_classes (tree_key); + + + CREATE INDEX ldb_dn_object_classes_dn_id_idx + ON ldb_dn_object_classes (dn_id); + + CREATE INDEX ldb_dn_object_classes_class_name_idx + ON ldb_dn_object_classes (class_name); + + + CREATE INDEX ldb_attr_value_pairs_dn_id_name_case_idx + ON ldb_attr_value_pairs (dn_id, attr_name); + + CREATE INDEX ldb_attr_value_pairs_dn_id_name_nocase_idx + ON ldb_attr_value_pairs (dn_id, attr_name COLLATE NOCASE); + + -- ------------------------------------------------------ + + /* all defaults for dn, initially */ + INSERT INTO ldb_attributes (attr_name) + VALUES ('dn'); + + /* We need an implicit "top" level object class */ + INSERT INTO ldb_object_classes (class_name, tree_key) + SELECT 'top', /* next_tree_key(NULL) */ '0001'; + + -- ------------------------------------------------------ + + COMMIT; + + -- ------------------------------------------------------ + "; + + /* Skip protocol indicator of url */ + if ((p = strchr(url, ':')) == NULL) { + return SQLITE_MISUSE; + } else { + ++p; + } + + /* + * See if we'll be creating a new database, or opening an existing one + */ + if ((stat(p, &statbuf) < 0 && errno == ENOENT) || + statbuf.st_size == 0) { + + bNewDatabase = True; + } + + /* Try to open the (possibly empty/non-existent) database */ + if ((lsqlite3->last_rc = sqlite3_open(p, &lsqlite3->sqlite3)) != SQLITE_SUCCESS) { + return ret; + } + + if (bNewDatabase) { + /* + * Create the database schema + */ + for (pTail = schema; pTail != NULL; ) { + + if ((lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + pTail, + -1, + &stmt, + &pTail)) != SQLITE_SUCCESS || + (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_DONE || + (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS) { + + (void) sqlite3_close(lsqlite3->sqlite3); + return ret; + } + } + } else { + /* + * Ensure that the database we opened is one of ours + */ + if ((lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "SELECT COUNT(*) " + " FROM sqlite_master " + " WHERE type = 'table' " + " AND name IN " + " (" + " 'ldb_info', " + " 'ldb_distinguished_names', " + " 'ldb_object_classes', " + " 'ldb_dn_object_classes', " + " 'ldb_attributes', " + " 'ldb_attr_value_pairs' " + " );", + -1, + &stmt, + &pTail)) != SQLITE_SUCCESS || + (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_ROW || + sqlite3_column_int(stmt, 0) != 6 || + (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "SELECT 1 " + " FROM ldb_info " + " WHERE database_type = 'LDB' " + " AND version = '1.0';", + -1, + &stmt, + &pTail)) != SQLITE_SUCCESS || + (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_ROW || + (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS) { + + /* It's not one that we created. See ya! */ + (void) sqlite3_close(lsqlite3->sqlite3); + return SQLITE_MISUSE; + } + } + + /* + * Pre-compile each of the queries we'll be using. + */ + + if ((lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "BEGIN IMMEDIATE;", + -1, + &lsqlite3->queries.begin, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "COMMIT;", + -1, + &lsqlite3->queries.commit, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "ROLLBACK;", + -1, + &lsqlite3->queries.rollback, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT INTO ldb_distinguished_names (dn_id, dn) " + " VALUES (:dn_id, :dn);", + -1, + &lsqlite3->queries.newDN, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "UPDATE ldb_distinguished_names " + " SET dn = :newDN " + " WHERE dn = :oldDN;", + -1, + &lsqlite3->queries.renameDN, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "DELETE FROM ldb_distinguished_names " + " WHERE dn = :dn;", + -1, + &lsqlite3->queries.deleteDN, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT OR IGNORE INTO ldb_object_classes " + " (class_name, tree_key)" + " SELECT :class_name, next_tree_key(NULL);", + -1, + &lsqlite3->queries.newObjectClass, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT OR REPLACE INTO ldb_dn_object_classes " + " (dn_id, class_name) " + " VALUES (:dn_id, :class_name);", + -1, + &lsqlite3->queries.assignObjectClass, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT OR IGNORE INTO ldb_attributes (name) " + " VALUES (:name);", + -1, + &lsqlite3->queries.newAttributeUseDefaults, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT OR REPLACE INTO ldb_attributes " + " (name, " + " case_insensitive_p, " + " wildcard_p, " + " hidden_p, " + " integer_p) " + " VALUES (:name, " + " :case_insensitive_p, " + " :wildcard_p, " + " :hidden_p, " + " :integer_p);", + -1, + &lsqlite3->queries.newAttribute, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT INTO ldb_attr_value_pairs " + " (dn_id, attr_name, attr_value) " + " VALUES (:dn_id, :attr_name, :attr_value);", + -1, + &lsqlite3->queries.addAttrValuePair, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "UPDATE ldb_attr_value_pairs " + " SET attr_value = :attr_value " + " WHERE dn_id = :dn_id " + " AND attr_name = :attr_name;", + -1, + &lsqlite3->queries.addAttrValuePair, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "DELETE FROM ldb_attr_value_pairs " + " WHERE dn_id = :dn_id " + " AND attr_name = :attr_name;" + -1, + &lsqlite3->queries.deleteAttrValuePair, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "INSERT OR REPLACE INTO ldb_object_classes " + " (class_name, tree_key) " + " SELECT :child_class, next_tree_key(:parent_class);" + -1, + &lsqlite3->queries.insertSubclass, + &pTail)) != SQLITE_SUCCESS) { + + (void) sqlite3_close(lsqlite3->sqlite3); + return ret; + } + + return SQLITE_SUCCESS; +} + +/* + connect to the database +*/ +struct ldb_context *lsqlite3_connect(const char *url, + unsigned int flags, + const char *options[]) +{ + struct ldb_context *ldb = NULL; + struct lsqlite3_private *lsqlite3 = NULL; + int i; + + ldb = talloc(NULL, struct ldb_context); + if (!ldb) { + errno = ENOMEM; + goto failed; + } + + lsqlite3 = talloc(ldb, struct lsqlite3_private); + if (!lsqlite3) { + errno = ENOMEM; + goto failed; + } + + lsqlite3->sqlite3 = NULL; + lsqlite3->options = NULL; + lsqlite3->lock_count = 0; + + lsqlite3->last_rc = lsqlite3_initialize(&lsqlite3->sqlite3, url); + if (lsqlite3->last_rc != LDAP_SUCCESS) { + goto failed; + } + + talloc_set_destructor(lsqlite3, lsqlite3_destructor); + + ldb->modules = talloc(ldb, struct ldb_module); + if (!ldb->modules) { + errno = ENOMEM; + goto failed; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = lsqlite3; + ldb->modules->ops = &lsqlite3_ops; + + if (options) { + /* take a copy of the options array, so we don't have to rely + on the caller keeping it around (it might be dynamic) */ + for (i=0;options[i];i++) ; + + lsqlite3->options = talloc_array(lsqlite3, char *, i+1); + if (!lsqlite3->options) { + goto failed; + } + + for (i=0;options[i];i++) { + lsqlite3->options[i+1] = NULL; + lsqlite3->options[i] = talloc_strdup(lsqlite3->options, options[i]); + if (!lsqlite3->options[i]) { + goto failed; + } + } + } + + return ldb; + +failed: + if (lsqlite3->sqlite3 != NULL) { + (void) sqlite3_close(lsqlite3->sqlite3); + } + talloc_free(ldb); + return NULL; +} + diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h new file mode 100644 index 0000000000..75105fe264 --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -0,0 +1,25 @@ +#include + +struct lsqlite3_private { + char **options; + const char *basedn; + sqlite3 * sqlite; + int lock_count; + int last_rc; + struct { + sqlite3_stmt *begin; + sqlite3_stmt *commit; + sqlite3_stmt *rollback; + sqlite3_stmt *newDN; + sqlite3_stmt *renameDN; + sqlite3_stmt *deleteDN; + sqlite3_stmt *newObjectClass; + sqlite3_stmt *assignObjectClass; + sqlite3_stmt *newAttributeUseDefaults; + sqlite3_stmt *newAttribute; + sqlite3_stmt *addAttrValuePair; + sqlite3_stmt *replaceAttrValuePairs; + sqlite3_stmt *deleteAttrValuePairs; + sqlite3_stmt *insertSubclass; + } queries; +}; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema new file mode 100644 index 0000000000..2ba188c785 --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -0,0 +1,240 @@ + -- ------------------------------------------------------ + + PRAGMA auto_vacuum=1; + + -- ------------------------------------------------------ + + BEGIN EXCLUSIVE; + + -- ------------------------------------------------------ + + CREATE TABLE ldb_info AS + SELECT 'LDB' AS database_type, + '1.0' AS version; + + CREATE TABLE ldb_distinguished_names + ( + dn_id INTEGER PRIMARY KEY AUTOINCREMENT, + dn TEXT UNIQUE + ); + + CREATE TABLE ldb_object_classes + ( + class_name TEXT PRIMARY KEY, + tree_key TEXT, + max_child_num INTEGER + ); + + CREATE TABLE ldb_dn_object_classes + ( + dn_id INTEGER REFERENCES ldb_distinguished_names, + class_name TEXT REFERENCES ldb_object_classes + ); + + CREATE TABLE ldb_attributes + ( + attr_name TEXT PRIMARY KEY, + case_insensitive_p BOOLEAN DEFAULT FALSE, + wildcard_p BOOLEAN DEFAULT FALSE, + hidden_p BOOLEAN DEFAULT FALSE, + integer_p BOOLEAN DEFAULT FALSE + ); + + CREATE TABLE ldb_attr_value_pairs + ( + dn_id INTEGER REFERENCES ldb_distinguished_names, + attr_name TEXT REFERENCES ldb_attributes, + attr_value TEXT + ); + + -- ------------------------------------------------------ + + CREATE TRIGGER ldb_distinguished_names_delete_tr + AFTER DELETE + ON ldb_distinguished_names + FOR EACH ROW + BEGIN + DELETE FROM ldb_attr_value_pairs + WHERE dn_id = old.dn_id; + DELETE FROM ldb_dn_object_classes + WHERE dn_id = old.dn_id; + END; + + CREATE TRIGGER ldb_attr_value_pairs_insert_tr + BEFORE INSERT + ON ldb_attr_value_pairs + FOR EACH ROW + BEGIN + INSERT OR IGNORE INTO ldb_attributes + (attr_name) + VALUES + (new.attr_name); + END; + + CREATE TRIGGER ldb_attr_value_pairs_delete_tr + AFTER DELETE + ON ldb_attr_value_pairs + FOR EACH ROW + BEGIN + DELETE FROM ldb_attributes + WHERE (SELECT COUNT(*) + FROM ldb_attr_value_pairs + WHERE attr_name = old.attr_name) = 0 + AND attr_name = old.attr_name; + END; + + -- ------------------------------------------------------ + + CREATE INDEX ldb_distinguished_names_dn_idx + ON ldb_distinguished_names (dn); + + CREATE INDEX ldb_object_classes_tree_key_idx + ON ldb_object_classes (tree_key); + + + CREATE INDEX ldb_dn_object_classes_dn_id_idx + ON ldb_dn_object_classes (dn_id); + + CREATE INDEX ldb_dn_object_classes_class_name_idx + ON ldb_dn_object_classes (class_name); + + + CREATE INDEX ldb_attr_value_pairs_dn_id_name_case_idx + ON ldb_attr_value_pairs (dn_id, attr_name); + + CREATE INDEX ldb_attr_value_pairs_dn_id_name_nocase_idx + ON ldb_attr_value_pairs (dn_id, attr_name COLLATE NOCASE); + + -- ------------------------------------------------------ + + /* all defaults for dn, initially */ + INSERT INTO ldb_attributes (attr_name) + VALUES ('dn'); + + /* We need an implicit "top" level object class */ + INSERT INTO ldb_object_classes (class_name, tree_key) + SELECT 'top', /* next_tree_key(NULL) */ '0001'; + + -- ------------------------------------------------------ + + COMMIT; + + -- ------------------------------------------------------ + +/* + * dn: o=University of Michigan,c=US + * objectclass: organization + * objectclass: domainRelatedObject + */ +-- newDN +INSERT INTO ldb_distinguished_names (dn_id, dn) + VALUES (1, 'o=University of Michigan,c=US'); + +-- newObjectClass +INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key) + SELECT 'organization', /* next_tree_key(NULL) */ '0002'; + +INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key) + SELECT 'domainRelatedObject', /* next_tree_key(NULL) */ '0003'; + +-- assignObjectClass +INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name) + VALUES (1, 'organization'); + +INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name) + VALUES (1, 'domainRelatedObject'); + +/* + * l: Ann Arbor, Michigan + * st: Michigan + * o: University of Michigan + * o: UMICH + * o: UM + * o: U-M + * o: U of M + * description: The University of Michigan at Ann Arbor + * seeAlso: + * postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 + * 09 $ US + * telephonenumber: +1 313 764-1817 + * associateddomain: example.com + */ +-- addAttrValuePair +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'l', 'Ann Arbor, Michigan'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'st', 'Michigan'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'o', 'University of Michigan'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'o', 'UMICH'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'o', 'UM'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'o', 'U-M'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'o', 'U of M'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'description', 'The University of Michigan at Ann Arbor'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'seeAlso', ''); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'postaladdress', 'University of Michigan $ 535 W. William St. $ Ann Arbor, MI 48109 $ US'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'telephonenumber', '+1 313 764-1817'); +INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) + VALUES (1, 'associateddomain', 'example.com'); + +-- ---------------------------------------------------------------------- + +/* + * dn: @ATTRIBUTES + * uid: CASE_INSENSITIVE WILDCARD + * cn: CASE_INSENSITIVE + * ou: CASE_INSENSITIVE + * dn: CASE_INSENSITIVE + */ +-- newAttribute +INSERT OR REPLACE INTO ldb_attributes + (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) + VALUES ('uid', 1, 1, 0, 0); +INSERT OR REPLACE INTO ldb_attributes + (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) + VALUES ('cn', 1, 0, 0, 0); +INSERT OR REPLACE INTO ldb_attributes + (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) + VALUES ('ou', 1, 0, 0, 0); +INSERT OR REPLACE INTO ldb_attributes + (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) + VALUES ('dn', 1, 0, 0, 0); + +-- ---------------------------------------------------------------------- + +/* + * dn: @SUBCLASSES + * top: domain + * top: person + * domain: domainDNS + * person: organizationalPerson + * person: fooPerson + * organizationalPerson: user + * organizationalPerson: OpenLDAPperson + * user: computer + */ +-- insertSubclass +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'domain', /* next_tree_key('top') */ '00010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'person', /* next_tree_key('top') */ '00010002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'domainDNS', /* next_tree_key('domain') */ '000100010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'organizationalPerson', /* next_tree_key('person') */ '000100020001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'fooPerson', /* next_tree_key('person') */ '000100020002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'user', /* next_tree_key('organizationalPerson') */ '0001000200010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'computer', /* next_tree_key('user') */ '0001000200010001'; -- cgit From 942eb58e61621dc710a2c96418dda6aaba7e06c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 May 2005 09:05:23 +0000 Subject: r6967: fixed the new multi-value dn=@ATTRIBUTES so it actually works :-) this demonstrates that we need a improved test suite as well (This used to be commit 959c73e93faa243154288c91a716e5a293d7a51c) --- source4/lib/ldb/ldb_tdb/ldb_cache.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 0fe573a829..0bc2d7b123 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -261,7 +261,7 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) { struct ltdb_private *ltdb = module->private_data; const struct ldb_message_element *attr_el; - int i, ret=0; + int i, j, ret=0; if (ltdb->cache->last_attribute.name && ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) { @@ -276,7 +276,6 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name); if (!attr_el) { - /* check if theres a wildcard attribute */ attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*"); @@ -286,8 +285,11 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) } for (i = 0; i < attr_el->num_values; i++) { - if (strcmp(ltdb_valid_attr_flags[i].name, attr_el->values[i].data) == 0) { - ret |= ltdb_valid_attr_flags[i].value; + for (j=0; ltdb_valid_attr_flags[j].name; j++) { + if (strcmp(ltdb_valid_attr_flags[j].name, + attr_el->values[i].data) == 0) { + ret |= ltdb_valid_attr_flags[j].value; + } } } -- cgit From e7b3f91678a27d85791f7a62fc418988edc92214 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 May 2005 09:36:22 +0000 Subject: r6968: fixed a typo in the event macros. I'm surprised this one didn't show up earlier! (This used to be commit 517028870747338fe96fd7607ec507e5577b67a9) --- source4/lib/events/events.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h index 6994f6a124..794407204b 100644 --- a/source4/lib/events/events.h +++ b/source4/lib/events/events.h @@ -61,4 +61,4 @@ void event_set_fd_flags(struct fd_event *fde, uint16_t flags); #define EVENT_FD_NOT_WRITEABLE(fde) \ event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) #define EVENT_FD_NOT_READABLE(fde) \ - event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE) + event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ) -- cgit From e5613a3ce9932fb76aef9f721cadabe69bd23be8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 26 May 2005 01:00:58 +0000 Subject: r6980: added data_blob_append(), which I use in the web server (This used to be commit 822e2e5abeba8343e9e8165c14f4371c30cc13b1) --- source4/lib/data_blob.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 2ec21717b1..049210e8ee 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -180,3 +180,16 @@ DATA_BLOB data_blob_const(const void *p, size_t length) blob.length = length; return blob; } + + +/* + append some data to a data blob +*/ +NTSTATUS data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, void *p, size_t length) +{ + blob->data = talloc_realloc_size(mem_ctx, blob->data, blob->length + length); + NT_STATUS_HAVE_NO_MEMORY(blob->data); + memcpy(blob->data + blob->length, p, length); + blob->length += length; + return NT_STATUS_OK; +} -- cgit From a81630c0c43c756b74feea84019769357f03a3e5 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 26 May 2005 02:16:45 +0000 Subject: r6984: added tree representation documentation and utility code, to be used for subclasses of object classes (This used to be commit 7aca32dca6daac54ac77a66438bc5168d5e04227) --- source4/lib/ldb/ldb_sqlite3/README | 4 + source4/lib/ldb/ldb_sqlite3/base160.c | 154 +++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 6 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 7 + source4/lib/ldb/ldb_sqlite3/trees.ps | 1760 +++++++++++++++++++++++++++++ 5 files changed, 1928 insertions(+), 3 deletions(-) create mode 100644 source4/lib/ldb/ldb_sqlite3/README create mode 100644 source4/lib/ldb/ldb_sqlite3/base160.c create mode 100644 source4/lib/ldb/ldb_sqlite3/trees.ps (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/README b/source4/lib/ldb/ldb_sqlite3/README new file mode 100644 index 0000000000..a0b3dcb16d --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/README @@ -0,0 +1,4 @@ +trees.ps contains an explanation of the Genealogical Representation of Trees +in Databases which is being used in ldb_sqlite3. Note that we use fgID +representation with 4 bytes per level, so we can represent 6.5E+08 subclasses +of any object class. This should be adequate for our purposes. :-) diff --git a/source4/lib/ldb/ldb_sqlite3/base160.c b/source4/lib/ldb/ldb_sqlite3/base160.c new file mode 100644 index 0000000000..e7220433fc --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/base160.c @@ -0,0 +1,154 @@ +/* + base160 code used by ldb_sqlite3 + + Copyright (C) 2004 Derrell Lipman + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* + * ldb_sqlite3_base160() + * + * Convert an integer value to a string containing the base 160 representation + * of the integer. We always convert to a string representation that is 4 + * bytes in length, and we always null terminate. + * + * Parameters: + * val -- + * The value to be converted + * + * result -- + * Buffer in which the result is to be placed + * + * Returns: + * nothing + */ +static unsigned char base160tab[161] = +{ + 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , /* 0-9 */ + 58 , 59 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , /* : ; A-H */ + 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , /* I-R */ + 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 97 , 98 , /* S-Z , a-b */ + 99 , 100, 101, 102, 103, 104, 105, 106, 107, 108, /* c-l */ + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, /* m-v */ + 119, 120, 121, 122, 160, 161, 162, 163, 164, 165, /* w-z, latin1 */ + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, /* latin1 */ + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, /* latin1 */ + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, /* latin1 */ + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, /* latin1 */ + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, /* latin1 */ + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, /* latin1 */ + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, /* latin1 */ + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, /* latin1 */ + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, /* latin1 */ + '\0' +}; + + +/* + * lsqlite3_base160() + * + * Convert an unsigned long integer into a base160 representation of the + * number. + * + * Parameters: + * val -- + * value to be converted + * + * result -- + * character array, 5 bytes long, into which the base160 representation + * will be placed. The result will be a four-digit representation of the + * number (with leading zeros prepended as necessary), and null + * terminated. + * + * Returns: + * Nothing + */ +void +lsqlite3_base160(unsigned long val, + unsigned char result[5]) +{ + int i; + + for (i = 3; i >= 0; i--) { + + result[i] = base160tab[val % 160]; + val /= 160; + } + + result[4] = '\0'; +} + + +/* + * lsqlite3_base160Next() + * + * Retrieve the next-greater number in the base160 sequence for the terminal + * tree node (the last four digits). Only one tree level (four digits) are + * operated on. + * + * Parameters: + * base160 -- a character array containing either an empty string (in which + * case no operation is performed), or a string of base160 digits + * with a length of a multiple of four digits. + * + * Upon return, the trailing four digits (one tree level) will + * have been incremented by 1. + * + * Returns: + * base160 -- the modified array + */ +char * +lsqlite3_base160Next(char base160[]) +{ + int i; + unsigned char * pTab; + char * pBase160 = base160; + + /* + * We need a minimum of four digits, and we will always get a multiple of + * four digits. + */ + if (*pBase160 != '\0') + { + pBase160 += strlen(pBase160) - 1; + + /* We only carry through four digits: one level in the tree */ + for (i = 0; i < 4; i++) { + + /* What base160 value does this digit have? */ + pTab = strchr(base160tab, *pBase160); + + /* Is there a carry? */ + if (pTab < base160tab + sizeof(base160tab) - 1) { + + /* Nope. Just increment this value and we're done. */ + *pBase160 = *++pTab; + break; + } else { + + /* + * There's a carry. This value gets base160tab[0], we + * decrement the buffer pointer to get the next higher-order + * digit, and continue in the loop. + */ + *pBase160-- = base160tab[0]; + } + } + } + + return base160; +} diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 67debd8a4e..932da0af31 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -457,7 +457,7 @@ static int lsqlite3_lock(struct ldb_module *module, const char *lockname) /* Write-lock (but not read-lock) the database */ lsqlite3->last_rc = sqlite3_step(lsqlite3->begin); - /* Ready the compiled statememt for its next use */ + /* Ready the compiled statement for its next use */ (void ) sqlite_reset(lsqlite3->begin); return lsqlite3->last_rc == 0 ? 0 : -1; @@ -484,7 +484,7 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) /* Final unlock. Unlock the database */ lsqlite3->last_rc = sqlite3_step(lsqlite3->commit); - /* Ready the compiled statememt for its next use */ + /* Ready the compiled statement for its next use */ (void ) sqlite_reset(lsqlite3->commit); } @@ -904,7 +904,7 @@ struct ldb_context *lsqlite3_connect(const char *url, lsqlite3->lock_count = 0; lsqlite3->last_rc = lsqlite3_initialize(&lsqlite3->sqlite3, url); - if (lsqlite3->last_rc != LDAP_SUCCESS) { + if (lsqlite3->last_rc != SQLITE_SUCCESS) { goto failed; } diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 75105fe264..46aa4ab7c5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -23,3 +23,10 @@ struct lsqlite3_private { sqlite3_stmt *insertSubclass; } queries; }; + +void +lsqlite3_base160(unsigned long val, + unsigned char result[5]); + +char * +lsqlite3_base160Next(char base160[]); diff --git a/source4/lib/ldb/ldb_sqlite3/trees.ps b/source4/lib/ldb/ldb_sqlite3/trees.ps new file mode 100644 index 0000000000..433a064816 --- /dev/null +++ b/source4/lib/ldb/ldb_sqlite3/trees.ps @@ -0,0 +1,1760 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: trees.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -f trees.dvi +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2000.05.06:2055 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (trees.dvi) +@start +%DVIPSBitmapFont: Fa cmr10 10 6 +/Fa 6 55 df<146014E0EB01C0EB0380EB0700130E131E5B5BA25B485AA2485AA212075B +120F90C7FCA25A121EA2123EA35AA65AB2127CA67EA3121EA2121F7EA27F12077F1203A2 +6C7EA26C7E1378A27F7F130E7FEB0380EB01C0EB00E01460135278BD20>40 +D<12C07E12707E7E7E120F6C7E6C7EA26C7E6C7EA21378A2137C133C133E131EA2131F7F +A21480A3EB07C0A6EB03E0B2EB07C0A6EB0F80A31400A25B131EA2133E133C137C1378A2 +5BA2485A485AA2485A48C7FC120E5A5A5A5A5A13527CBD20>I<15301578B3A6007FB812 +F8B912FCA26C17F8C80078C8FCB3A6153036367BAF41>43 D48 DI54 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmr7 7 3 +/Fb 3 55 df48 D<13381378EA01F8121F12FE12E01200B3AB487EB512F8A2 +15267BA521>I54 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fc cmmi10 10 1 +/Fc 1 69 df<0103B7FC4916E018F8903B0007F80007FE4BEB00FFF03F80020FED1FC018 +0F4B15E0F007F0021F1503A24B15F81801143F19FC5DA2147FA292C8FCA25C18035CA213 +0119F84A1507A2130319F04A150FA2010717E0181F4A16C0A2010FEE3F80A24AED7F0018 +7E011F16FE4D5A4A5D4D5A013F4B5A4D5A4A4A5A057FC7FC017F15FEEE03FC91C7EA0FF0 +49EC7FC0B8C8FC16FC16C03E397DB845>68 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fd ectt1000 10 73 +/Fd 73 126 df37 +D39 +D<143814FC13011303EB07F8EB0FF0EB1FC0EB3F80EB7F0013FE485A485A5B12075B120F +5B485AA2123F90C7FCA25A127EA312FE5AAC7E127EA3127F7EA27F121FA26C7E7F12077F +12037F6C7E6C7E137FEB3F80EB1FC0EB0FF0EB07F8EB03FC130113001438164272B92C> +I<127012FC7E7E6C7E6C7EEA0FE06C7E6C7E6C7E6C7E137F7F1480131F14C0130FEB07E0 +A214F01303A214F81301A314FC1300AC130114F8A3130314F0A2130714E0A2EB0FC0131F +1480133F14005B13FE485A485A485A485AEA3FC0485A48C7FC5A5A1270164279B92C>I< +EB0380497EA60020140800F8143E00FE14FE00FF13C1EBC7C7EBE7CF003FB512F8000F14 +E0000314806C140038007FFCA248B5FC481480000F14E0003F14F839FFE7CFFEEBC7C7EB +07C100FE13C000F8143E0020140800001400A66D5A1F247AAA2C>I<147014F8AF003FB6 +12E0B712F8A4C700F8C7FCB0147025267DAB2C>II<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B708A2C>46 +D<1507ED0F80A2151F16005D153E157E157CA215FC5D14015D14035D14075D140F5D141F +92C7FC5C143EA2147E147C14FC5C13015C13035C13075C130F5C131F91C8FC5B133EA213 +7E137C13FC5B12015B12035B12075B120F5B121F90C9FCA25A123E127E127C12FC5AA212 +7021417BB92C>II<1307497EA2131F +A2133F137F13FF5A1207127FB5FC13DF139FEA7C1F1200B3AE007FB512E0B612F0A36C14 +E01C3477B32C>II<000FB512FE4880A35D0180C8FCADEB83FE90389FFF8090B512E015F881 +9038FE03FE9038F000FF01C07F49EB3F8090C7121F6C15C0C8120FA2ED07E0A4123C127E +B4FC150F16C0A248141F007EEC3F80007FEC7F006C6C5B6D485A391FF80FFC6CB55A6C5C +000114C06C6C90C7FCEB0FF823347CB22C>53 DI<1278B712C016E0A316C000FCC7EA3F80ED7F0015FE00785CC712014A +5A4A5A5D140F5D4A5A143F92C7FC5C147E14FE5C13015CA2495AA213075CA3495AA4495A +A5133F91C8FCAA131E23357CB32C>I59 D<1502ED0F80151F157F15 +FF913803FE00EC0FFCEC1FF0EC7FE0ECFF80D903FEC7FC495AEB1FF0495AEBFF80000390 +C8FCEA07FCEA1FF8EA3FE0EAFF8090C9FCA27FEA3FE0EA1FF8EA07FC6CB4FCC67FEB3FE0 +6D7EEB07FC6D7E903800FF80EC7FE0EC1FF0EC0FFCEC03FE913800FF80157F151F150FED +0200212A7BAD2C>I<007FB612F0B712F8A36C15F0CAFCA8007FB612F0B712F8A36C15F0 +25127DA12C>I<122012F87EB4FC7FEA3FE0EA1FF8EA07FC6CB4FCC67FEB3FE06D7EEB07 +FC6D7E903800FF80EC7FE0EC1FF0EC0FFCEC03FE913800FF80157FA215FF913803FE00EC +0FFCEC1FF0EC7FE0ECFF80D903FEC7FC495AEB1FF0495AEBFF80000390C8FCEA07FCEA1F +F8EA3FE0EAFF8090C9FC12FC5A1220212A7BAD2C>I<14FE497EA4497FA214EFA2130781 +A214C7A2010F7FA314C390381F83F0A590383F01F8A490387E00FCA549137E90B512FEA3 +4880A29038F8003FA34848EB1F80A4000715C049130FD87FFEEBFFFC6D5AB514FE6C15FC +497E27347EB32C>65 D<007FB512E015F8B612FE6C8016C03903F0003FED0FE0ED07F015 +03A2ED01F8A6ED03F0A21507ED0FE0ED1FC0EDFF8090B612005D5D15FF16C09039F0001F +E0ED07F0ED03F81501ED00FCA216FE167EA616FE16FC1501ED03F8150FED3FF0007FB612 +E016C0B712806CECFE0015F027337FB22C>I<02FF13700107EBE0F84913F9013F13FD49 +13FFEBFF813901FE007F4848131FD807F0130F1507485A491303485A150148C7FCA25A00 +7EEC00F01600A212FE5AAB7E127EA3007F15F06CEC01F8A26C7EA26C6C13036D14F06C6C +130716E0D803FC131F6C6CEB3FC03A00FF81FF806DB512006D5B010F5B6D13F001001380 +25357DB32C>I<007FB5FCB612C015F0816C803907E003FEEC00FFED7F80153FED1FC0ED +0FE0A2150716F0150316F81501A4ED00FCACED01F8A3150316F0A2150716E0150FED1FC0 +153FED7F80EDFF00EC03FE007FB55AB65A5D15C06C91C7FC26337EB22C>I<007FB612F0 +B712F8A37E3903F00001A7ED00F01600A4EC01E04A7EA490B5FCA5EBF003A46E5A91C8FC +A5163C167EA8007FB612FEB7FCA36C15FC27337EB22C>I<007FB612F8B712FCA37ED803 +F0C7FCA716781600A515F04A7EA490B5FCA5EBF001A46E5A92C7FCAD387FFFE0B5FC805C +7E26337EB22C>I<903901FC038090390FFF87C04913EF017F13FF90B6FC4813073803FC +01497E4848137F4848133F49131F121F5B003F140F90C7FCA2127EED078092C7FCA212FE +5AA8913803FFF84A13FCA27E007E6D13F89138000FC0A36C141FA27F121F6D133F120F6D +137F6C7E6C6C13FF6D5A3801FF076C90B5FC6D13EF011F13CF6DEB0780D901FCC7FC2635 +7DB32C>II<007FB512F8B612FCA36C14 +F839000FC000B3B3A5007FB512F8B612FCA36C14F81E3379B22C>I75 D<387FFFE0B57EA36C5BD803F0C8FCB3AE16F0 +ED01F8A8007FB6FCB7FCA36C15F025337DB22C>IIII<007FB512C0B612 +F88115FF6C15802603F00013C0153FED0FE0ED07F0A2150316F81501A6150316F01507A2 +ED0FE0ED3FC015FF90B61280160015FC5D15C001F0C8FCB0387FFF80B57EA36C5B25337E +B22C>II<387FFFFCB67E15E015F86C803907E007FE1401EC007F6F7E151FA2 +6F7EA64B5AA2153F4BC7FCEC01FE140790B55A5D15E081819038E007FCEC01FE1400157F +81A8160FEE1F80A5D87FFEEB1FBFB5ECFF00815E6C486D5AC8EA01F029347EB22C>I<90 +381FF80790B5EA0F804814CF000714FF5A381FF01F383FC003497E48C7FC007E147F00FE +143F5A151FA46CEC0F00007E91C7FC127F7FEA3FE0EA1FFCEBFFC06C13FC0003EBFFC06C +14F06C6C7F01077F9038007FFEEC07FF02001380153FED1FC0A2ED0FE0A20078140712FC +A56CEC0FC0A26CEC1F806D133F01E0EB7F009038FE01FF90B55A5D00F914F0D8F83F13C0 +D8700790C7FC23357CB32C>I<007FB612FCB712FEA43AFC007E007EA70078153CC71400 +B3AF90383FFFFCA2497F6D5BA227337EB22C>I<3B7FFF803FFFC0B56C4813E0A36C496C +13C03B03F00001F800B3AF6D130300015DA26D130700005D6D130F017F495A6D6C485AEC +E0FF6DB5C7FC6D5B010313F86D5B9038003F802B3480B22C>III<3A3FFF03FFE0484913F0148714076C6D13E03A01 +F800FE007F0000495A13FE017E5BEB7F03013F5B1487011F5B14CF010F5B14FF6D5BA26D +90C7FCA26D5AA26D5AA2497EA2497EA2497F81EB0FCF81EB1FC7EC87F0EB3F83EC03F8EB +7F01017E7FEBFE00497F0001147E49137F000380491480151FD87FFEEBFFFC6D5AB514FE +6C15FC497E27337EB22C>II<387FFFFCB512FEA314FC00FCC7FCB3B3B3B512FC14FEA36C13FC +17416FB92C>91 D<127012F8A27E127C127E123E123F7EA27F120F7F12077F12037F1201 +7F12007F137C137E133EA2133F7F80130F80130780130380130180130080147C147E143E +A2143F8081140F81140781140381140181140081157CA2157E153E153F811680150FA2ED +070021417BB92C>I<387FFFFCB512FEA37EC7127EB3B3B3387FFFFEB5FCA36C13FC1741 +7DB92C>II<007FB6FCB71280A46C150021067B7D +2C>I<1338137CEA01FC1203EA07F813F0EA0FC0EA1F80A2EA3F00123E127E127CA212FC +5AA3EAFFC013E013F013F8A2127FA2123F13F0EA1FE0EA07C00E1D72B82C>I<3801FFF0 +000713FE001F6D7E15E048809038C01FF81407EC01FC381F80000006C77EC8127EA3ECFF +FE131F90B5FC1203120F48EB807E383FF800EA7FC090C7FC12FE5AA47E007F14FEEB8003 +383FE01F6CB612FC6C15FE6C14BF0001EBFE1F3A003FF007FC27247CA32C>II<90 +3803FFE0011F13F8017F13FE48B5FC48804848C6FCEA0FF0485A49137E4848131890C9FC +5A127EA25AA8127EA2127F6C140F6DEB1F806C7E6D133F6C6CEB7F003907FE03FF6CB55A +6C5C6C6C5B011F13E0010390C7FC21247AA32C>III103 +DI< +1307EB1FC0A2497EA36D5AA20107C7FC90C8FCA7387FFFC080B5FC7EA2EA0007B3A8007F +B512FCB612FEA36C14FC1F3479B32C>I107 D<387FFFE0B57EA37EEA0003B3B3A5007F +B61280B712C0A36C158022337BB22C>I<3A7F83F007E09039CFFC1FF83AFFDFFE3FFCD8 +7FFF13FF91B57E3A07FE1FFC3E01FCEBF83F496C487E01F013E001E013C0A301C01380B3 +3B7FFC3FF87FF0027F13FFD8FFFE6D13F8D87FFC4913F0023F137F2D2481A32C>I<397F +F01FE039FFF87FFC9038F9FFFE01FB7F6CB6FC00019038F03F80ECC01F02807FEC000F5B +5BA25BB3267FFFE0B5FCB500F11480A36C01E0140029247FA32C>II<397FF01FE0 +39FFF8FFF801FB13FE90B6FC6C158000019038F07FC09138801FE091380007F049EB03F8 +5BED01FC491300A216FE167EA816FE6D14FCA2ED01F86D13036DEB07F0150F9138801FE0 +9138E07FC091B51280160001FB5B01F813F8EC3FC091C8FCAD387FFFE0B57EA36C5B2736 +7FA32C>I<903903FC078090391FFF0FC0017F13CF48B512EF4814FF3807FE07380FF001 +48487E49137F4848133F90C7FC48141F127E150F5AA87E007E141FA26C143F7F6C6C137F +6D13FF380FF0033807FC0F6CB6FC6C14EF6C6C138F6D130FEB07F890C7FCAD0203B5FC4A +1480A36E140029367DA32C>II<90387FF8700003B512F8120F5A5A387FC00F387E00034813015AA36CEB +00F0007F140013F0383FFFC06C13FE6CEBFF80000314E0C66C13F8010113FCEB0007EC00 +FE0078147F00FC143F151F7EA26C143F6D133E6D13FE9038F007FC90B5FC15F815E000F8 +148039701FFC0020247AA32C>I<131E133FA9007FB6FCB71280A36C1500D8003FC8FCB1 +ED03C0ED07E0A5EC800F011FEB1FC0ECE07F6DB51280160001035B6D13F89038003FE023 +2E7EAD2C>I<3A7FF003FF80486C487FA3007F7F0001EB000FB3A3151FA2153F6D137F39 +00FE03FF90B7FC6D15807F6D13CF902603FE07130029247FA32C>I<3A3FFF03FFF04801 +8713F8A36C010313F03A00FC007E005D90387E01F8013F5BEB1F83EC87E090380FCFC090 +3807EF80EB03FF6D90C7FC5C6D5A147C14FE130180903803EF80903807CFC0EB0FC7EC83 +E090381F01F0013F7FEB7E00017C137C49137E0001803A7FFF01FFFC1483B514FE6C15FC +140127247EA32C>120 D<3A7FFF01FFFCB5008113FE148314816C010113FC3A03E0000F +806C7E151F6D140012005D6D133E137C017E137E013E137CA2013F13FC6D5BA2EB0F815D +A2EB07C1ECC3E0A2EB03E3ECE7C0130114F75DEB00FFA292C7FC80A2143EA2147E147CA2 +14FC5CA2EA0C01003F5BEA7F83EB87E0EA7E0F495A387FFF806C90C8FC6C5A6C5AEA07E0 +27367EA32C>I<15FF02071380141F147F91B512004913C04AC7FCEB03F85CB31307EB1F +E013FF007F5BB55A49C8FC6D7E6C7FC67F131FEB07F01303B380EB01FEECFFC06D13FF6E +1380141F14070200130021417BB92C>123 D<127812FCB3B3B3A9127806416DB92C>II E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fe ecti1000 10 33 +/Fe 33 122 df28 D<150C151C153815F0EC01E0EC03C0EC0780EC0F00141E5C147C5C5C495A1303 +495A5C130F49C7FCA2133EA25BA25BA2485AA212035B12075BA2120F5BA2121FA290C8FC +A25AA2123EA2127EA2127CA412FC5AAD1278A57EA3121C121EA2120E7EA26C7E6C7EA212 +001E5274BD22>40 D<140C140E80EC0380A2EC01C015E0A2140015F0A21578A4157C153C +AB157CA715FCA215F8A21401A215F0A21403A215E0A21407A215C0140F1580A2141F1500 +A2143EA25CA25CA2495AA2495A5C1307495A91C7FC5B133E133C5B5B485A12035B48C8FC +120E5A12785A12C01E527FBD22>I<4B7EA3150393C8FCA35D1506A3150E150CA3151C15 +18A315381530A31570B912E0A2C80060C8FC15E05DA314015DA3140392C9FCA35C1406A3 +140E140CA3141C1418A2333275AD40>43 DI<120E +EA3F80127F12FFA31300127E123C0909778819>46 D<0103B612FEEFFFC018F0903B0007 +F8000FF84BEB03FCEF00FE020F157FF03F804B141F19C0021F150F19E05D1807143F19F0 +5DA2147FA292C8FCA25C180F5CA2130119E04A151FA2130319C04A153FA201071780187F +4A1600A2010F16FEA24A4A5A60011F15034D5A4A5D4D5A013F4B5A173F4A4AC7FC17FC01 +7FEC03F84C5A91C7EA1FC04949B45A007F90B548C8FCB712F016803C397CB83F>68 +D<0103B512F8A390390007F8005DA2140FA25DA2141FA25DA2143FA25DA2147FA292C7FC +A25CA25CA21301A25CA21303A25CA21307A25CA2130FA25CA2131FA25CA2133FA25CA213 +7FA291C8FC497EB6FCA25C25397CB820>73 D<0107B512FCA25E9026000FF8C7FC5D5D14 +1FA25DA2143FA25DA2147FA292C8FCA25CA25CA21301A25CA21303A25CA21307A25CA213 +0F170C4A141CA2011F153C17384A1478A2013F157017F04A14E01601017F140317C091C7 +1207160F49EC1F80163F4914FF000102071300B8FCA25E2E397BB834>76 +D79 +D81 D<92383FC00E913901FFF01C020713FC91 +391FC07E3C91393F001F7C027CEB0FF84A130749481303495A4948EB01F0A2495AA2011F +15E091C7FCA34915C0A36E90C7FCA2806D7E14FCECFF806D13F015FE6D6D7E6D14E00100 +80023F7F14079138007FFC150F15031501A21500A2167C120EA3001E15FC5EA3003E4A5A +A24B5AA2007F4A5A4B5A6D49C7FC6D133ED8F9F013FC39F8FC03F839F07FFFE0D8E01F13 +8026C003FCC8FC2F3D7ABA2F>83 D<0007B812E0A25AD9F800EB001F01C049EB07C0485A +D900011403121E001C5C003C17801403123800785C00701607140700F01700485CA2140F +C792C7FC5DA2141FA25DA2143FA25DA2147FA292C9FCA25CA25CA21301A25CA21303A25C +A21307A25CA2130FA25CEB3FF0007FB512F8B6FCA2333971B83B>I<14F8EB07FE90381F +871C90383E03FE137CEBF801120148486C5A485A120FEBC001001F5CA2EA3F801403007F +5C1300A21407485C5AA2140F5D48ECC1C0A2141F15831680143F1587007C017F1300ECFF +076C485B9038038F8E391F0F079E3907FE03FC3901F000F0222677A42A>97 +D<133FEA1FFFA3C67E137EA313FE5BA312015BA312035BA31207EBE0F8EBE7FE9038EF0F +80390FFC07C013F89038F003E013E0D81FC013F0A21380A2123F1300A214075A127EA214 +0F12FE4814E0A2141F15C05AEC3F80A215005C147E5C387801F8007C5B383C03E0383E07 +C0381E1F80D80FFEC7FCEA01F01C3B77B926>I<147F903803FFC090380FC1E090381F00 +70017E13784913383901F801F83803F003120713E0120FD81FC013F091C7FC485AA2127F +90C8FCA35A5AA45AA3153015381578007C14F0007EEB01E0003EEB03C0EC0F806CEB3E00 +380F81F83803FFE0C690C7FC1D2677A426>II<147F903803FFC090380FC1E09038 +3F00F0017E13785B485A485A485A120F4913F8001F14F0383F8001EC07E0EC1F80397F81 +FF00EBFFF8148090C8FC5A5AA55AA21530007C14381578007E14F0003EEB01E0EC03C06C +EB0F806CEB3E00380781F83803FFE0C690C7FC1D2677A426>IIIII108 +DII<147F903803FFC090380FC1F090381F00F8 +017E137C5B4848137E4848133E0007143F5B120F485AA2485A157F127F90C7FCA215FF5A +4814FEA2140115FC5AEC03F8A2EC07F015E0140F007C14C0007EEB1F80003EEB3F00147E +6C13F8380F83F03803FFC0C648C7FC202677A42A>I<9039078007C090391FE03FF09039 +3CF0787C903938F8E03E9038787FC00170497EECFF00D9F0FE148013E05CEA01E113C15C +A2D80003143FA25CA20107147FA24A1400A2010F5C5E5C4B5A131F5EEC80035E013F495A +6E485A5E6E48C7FC017F133EEC70FC90387E3FF0EC0F8001FEC9FCA25BA21201A25BA212 +03A25B1207B512C0A3293580A42A>I<3903C003F0390FF01FFC391E783C0F381C7C703A +3C3EE03F8038383FC0EB7F800078150000701300151CD8F07E90C7FCEAE0FE5BA2120012 +015BA312035BA312075BA3120F5BA3121F5BA3123F90C9FC120E212679A423>114 +D<14FE903807FF8090380F83C090383E00E04913F00178137001F813F00001130313F0A2 +15E00003EB01C06DC7FC7FEBFFC06C13F814FE6C7F6D13807F010F13C01300143F141F14 +0F123E127E00FE1480A348EB1F0012E06C133E00705B6C5B381E03E06CB45AD801FEC7FC +1C267AA422>II<01F013 +0ED803FC133FD8071EEB7F80EA0E1F121C123C0038143F49131F0070140FA25BD8F07E14 +0000E08013FEC6485B150E12015B151E0003141C5BA2153C000714385B5DA35DA24A5A14 +0300035C6D48C7FC0001130E3800F83CEB7FF8EB0FC0212679A426>118 +D<903907E007C090391FF81FF89039787C383C9038F03E703A01E01EE0FE3803C01F0180 +13C0D8070014FC481480000E1570023F1300001E91C7FC121CA2C75AA2147EA214FEA25C +A21301A24A1370A2010314F016E0001C5B007E1401010714C000FEEC0380010F1307010E +EB0F0039781CF81E9038387C3C393FF03FF03907C00FC027267CA427>120 +D<13F0D803FCEB01C0D8071EEB03E0D80E1F1307121C123C0038140F4914C01270A24913 +1FD8F07E148012E013FEC648133F160012015B5D0003147E5BA215FE00075C5BA214015D +A314035D14070003130FEBF01F3901F87FE038007FF7EB1FC7EB000F5DA2141F003F5C48 +133F92C7FC147E147C007E13FC387001F8EB03E06C485A383C1F80D80FFEC8FCEA03F023 +3679A428>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ff cmsy10 10 1 +/Ff 1 16 df15 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fg ecbx1000 10 36 +/Fg 36 119 df<913803FFC0027F13F00103B512FC010FEB00FED93FF8133FD97FE0EBFF +8049485A5A1480484A13C04A6C1380A36F1300167E93C7FCA592383FFFC0B8FCA4000390 +C7FCB3ABB5D8FC3F13FFA4303A7EB935>28 D45 +DI<141E143E +14FE1307137FB5FCA3138FEA000FB3B3A5007FB61280A4213679B530>49 +DI54 D58 D66 DII73 +D76 DII< +EDFFF8020FEBFF80027F14F0903A01FFC01FFC010790380007FFD91FFC010113C0D93FF0 +6D6C7E49486E7E49486E7E48496E7E48834890C86C7EA248486F1380A248486F13C0A200 +3F18E0A348486F13F0A400FF18F8AC007F18F06D5DA3003F18E0A26D5D001F18C0A26C6C +4B13806C18006E5C6C6D4A5A6C5F6C6D4A5A6D6C4A5AD93FFC49485A6DB401075B0107D9 +C01F90C7FC010190B512FC6D6C14F0020F1480020001F8C8FC3D3B7BB948>III83 D85 DII<13 +FFB5FCA412077EAF4AB47E020F13F0023F13FC9138FE03FFDAF00013804AEB7FC00280EB +3FE091C713F0EE1FF8A217FC160FA217FEAA17FCA3EE1FF8A217F06E133F6EEB7FE06E14 +C0903AFDF001FF80903AF8FC07FE009039F03FFFF8D9E00F13E0D9C00390C7FC2F3A7EB9 +35>98 D100 +D<903803FF80011F13F0017F13FC3901FF83FE3A03FE007F804848133F484814C0001FEC +1FE05B003FEC0FF0A2485A16F8150712FFA290B6FCA301E0C8FCA4127FA36C7E1678121F +6C6C14F86D14F000071403D801FFEB0FE06C9038C07FC06DB51200010F13FC010113E025 +257DA42C>II<161FD907FEEBFFC090387FFFE348B6EAEFE02607FE07138F260FF801131F48486C13 +8F003F15CF4990387FC7C0EEC000007F81A6003F5DA26D13FF001F5D6C6C4890C7FC3907 +FE07FE48B512F86D13E0261E07FEC8FC90CAFCA2123E123F7F6C7E90B512F8EDFF8016E0 +6C15F86C816C815A001F81393FC0000F48C8138048157F5A163FA36C157F6C16006D5C6C +6C495AD81FF0EB07FCD807FEEB3FF00001B612C06C6C91C7FC010713F02B377DA530>I< +EA01F0EA07FC487EA2487EA56C5AA26C5AEA01F0C8FCA913FF127FA412077EB3A9B512F8 +A4153B7DBA1B>105 D<13FFB5FCA412077EAF92380FFFE0A4923803FC0016F0ED0FE0ED +1F804BC7FC157E5DEC03F8EC07E04A5A141FEC7FE04A7E8181A2ECCFFEEC0FFF496C7F80 +6E7F6E7F82157F6F7E6F7E82150F82B5D8F83F13F8A42D3A7EB932>107 +D<13FFB5FCA412077EB3B3ACB512FCA4163A7DB91B>I<01FED97FE0EB0FFC00FF902601 +FFFC90383FFF80020701FF90B512E0DA1F81903983F03FF0DA3C00903887801F000749DA +CF007F00034914DE6D48D97FFC6D7E4A5CA24A5CA291C75BB3A3B5D8FC1FB50083B512F0 +A44C257DA451>I<01FEEB7FC000FF903803FFF8020F13FE91381F03FFDA3C0113800007 +13780003497E6D4814C05CA25CA291C7FCB3A3B5D8FC3F13FFA430257DA435>I<903801 +FFC0010F13F8017F13FFD9FF807F3A03FE003FE048486D7E48486D7E48486D7EA2003F81 +491303007F81A300FF1680A9007F1600A3003F5D6D1307001F5DA26C6C495A6C6C495A6C +6C495A6C6C6CB45A6C6CB5C7FC011F13FC010113C029257DA430>I<9038FE03F000FFEB +0FFEEC3FFF91387C7F809138F8FFC000075B6C6C5A5CA29138807F80ED3F00150C92C7FC +91C8FCB3A2B512FEA422257EA427>114 D<90383FF0383903FFFEF8000F13FF381FC00F +383F0003007E1301007C130012FC15787E7E6D130013FCEBFFE06C13FCECFF806C14C06C +14F06C14F81203C614FC131F9038007FFE140700F0130114007E157E7E157C6C14FC6C14 +F8EB80019038F007F090B512C000F8140038E01FF81F257DA426>I<130FA55BA45BA25B +5BA25A1207001FEBFFE0B6FCA3000390C7FCB21578A815F86CEB80F014816CEBC3E09038 +3FFFC06D1380903803FE001D357EB425>I118 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fh ecrm1000 10 89 +/Fh 89 126 df<486C1360000314E039070001C0000EEB038048EB070000181306003813 +0E0030130C0070131C00601318A200E01338481330A400CEEB338039FF803FE001C013F0 +A3007F131FA2393F800FE0390E0003801C1981B91C>16 D<001C1307007FEB1FC039FF80 +3FE0A201C013F0A3007F131F001CEB073000001300A400011470491360A2000314E090C7 +12C048130100061480000E130348EB070048130E485B006013181C1980B91C>I21 D27 +DI30 D36 D<141FEC7FC0903801F0 +E0903803C0600107137090380F803090381F00381518A25BA2133E133F15381530A21570 +5D5D140190381F838092CAFC1487148E02DC49B51280EB0FF85C4A9039003FF8000107ED +0FC06E5D71C7FC6E140E010F150CD91DFC141C01391518D970FE143801E015302601C07F +1470D803805D00076D6C5BD80F00EBC00148011F5C4890380FE003003E6E48C8FC007E90 +3807F8060203130E00FE6E5A6E6C5A1400ED7F706C4B13036F5A6F7E6C6C6D6C5B701306 +6C6C496C130E6DD979FE5B281FF001F07F133C3C07F80FE03FC0F86CB539800FFFF0C690 +26FE000313C0D91FF0D9007FC7FC393E7DBB41>38 D<121C127FEAFF80A213C0A3127F12 +1C1200A412011380A2120313005A1206120E5A5A5A12600A1979B917>I<146014E0EB01 +C0EB0380EB0700130E131E5B5BA25B485AA2485AA212075B120F90C7FCA25A121EA2123E +A35AA65AB2127CA67EA3121EA2121F7EA27F12077F1203A26C7EA26C7E1378A27F7F130E +7FEB0380EB01C0EB00E01460135278BD20>I<12C07E12707E7E7E120F6C7E6C7EA26C7E +6C7EA21378A2137C133C133E131EA2131F7FA21480A3EB07C0A6EB03E0B2EB07C0A6EB0F +80A31400A25B131EA2133E133C137C1378A25BA2485A485AA2485A48C7FC120E5A5A5A5A +5A13527CBD20>I<1530B3A8B912FCA2C80030C8FCB3A836367BAF41>43 +D<121C127FEAFF80A213C0A3127F121C1200A412011380A2120313005A1206120E5A5A5A +12600A19798817>II<121C127FEAFF80A5EA7F00121C09097988 +17>I<1506A2150E150CA2151C151815381530A215701560A215E015C0A214011580A214 +0315005C1406A2140E140CA2141C1418A214381430A21470146014E05CA213015CA21303 +91C7FCA25B1306A2130E130C131C1318A213381330A213701360A213E05BA212015B1203 +90C8FCA25A1206A2120E120CA2121C1218A21238123012701260A212E05AA21F537BBD2A +>II +III<1538A2157815F8A214011403 +1407A2140F141F141B14331473146314C313011483EB030313071306130C131C13181330 +1370136013C01201EA038013005A120E120C5A123812305A12E0B712F8A3C73803F800AA +4A7E0103B512F8A325387EB72A>I<0006140CD80780133C9038F003F890B5FC5D5D1580 +92C7FC14FC38067FE090C9FCAAEB07F8EB1FFE9038780F809038E007E03907C003F0496C +7E130000066D7E81C8FC8181A21680A4121C127F5A7FA390C713005D12FC00605C12704A +5A6C5C6C1303001E495A6C6C485A3907E03F800001B5C7FC38007FFCEB1FE021397CB62A +>II<12301238123E003FB612E0A316C05A168016 +000070C712060060140E5D5D00E014304814705D5DC712014A5A4AC7FC1406140E5CA25C +1478147014F05C1301A213035C1307A2130FA3131F5CA2133FA5137FA96DC8FC131E233A +7BB72A>III<121C127FEAFF80A5 +EA7F00121CC7FCB2121C127FEAFF80A5EA7F00121C092479A317>I<121C127FEAFF80A5 +EA7F00121CC7FCB2121C127FEAFF80A213C0A3127F121C1200A412011380A2120313005A +1206120E5A5A5A12600A3479A317>II<007FB812F8B912FCCCFCB0B912FC6C17F836147B9E41>I<12E01278121EEA07C0 +EA01F0EA003C130FEB03C0EB00F0143C140FEC03E0EC00F8151EED0780ED01E0ED007816 +1EEE07C0EE01F0EE003C170FEF03C0A2EF0F00173CEE01F0EE07C0041EC7FC1678ED01E0 +ED0780031EC8FC15F8EC03E0020FC9FC143C14F0EB03C0010FCAFC133CEA01F0EA07C000 +1ECBFC127812E0322E79AB41>II<1538A3157CA315FEA34A7EA34A6C7EA202077FEC063FA202 +0E7FEC0C1FA2021C7FEC180FA202387FEC3007A202707FEC6003A202C07F1501A2D90180 +7F81A249C77F167FA20106810107B6FCA24981010CC7121FA2496E7EA3496E7EA3496E7E +A213E0707E1201486C81D80FFC02071380B56C90B512FEA3373C7DBB3E>65 +DI<913A01FF800180020FEBE003027F13F8903A01FF807E07903A03 +FC000F0FD90FF0EB039F4948EB01DFD93F80EB00FF49C8127F01FE153F12014848151F48 +48150FA248481507A2485A1703123F5B007F1601A35B00FF93C7FCAD127F6DED0180A312 +3F7F001F160318006C7E5F6C7E17066C6C150E6C6C5D00001618017F15386D6C5CD91FE0 +5C6D6CEB03C0D903FCEB0F80902701FF803FC7FC9039007FFFFC020F13F002011380313D +7BBA3C>IIIIIII<013FB512 +E0A39039001FFC00EC07F8B3B3A3123FEA7F80EAFFC0A44A5A1380D87F005B0070131F6C +5C6C495A6C49C7FC380781FC3801FFF038007F80233B7DB82B>IIIIIIIII< +D90FF813C090383FFE0190B512813903F807E33907E000F74848137F4848133F48C7121F +003E140F007E1407A2007C140312FC1501A36C1400A37E6D14006C7E7F13F86CB47E6C13 +F8ECFF806C14E06C14F86C14FEC680013F1480010714C0EB007F020713E0EC007FED3FF0 +151F150FED07F8A200C01403A21501A37EA216F07E15036C15E06C14076C15C06C140F6D +EB1F80D8FBF0EB3F00D8F0FE13FE39E03FFFF8010F13E0D8C00190C7FC253D7CBA2E>I< +003FB812E0A3D9C003EB001F273E0001FE130348EE01F00078160000701770A300601730 +A400E01738481718A4C71600B3B0913807FF80011FB612E0A335397DB83C>IIII89 D<003FB7FCA39039FC0001FE +01C0130349495A003EC7FC003C4A5A5E0038141F00784A5A12704B5A5E006014FF4A90C7 +FCA24A5A5DC712074A5AA24A5A5D143F4A5AA24A5A92C8FC5B495AA2495A5C130F4948EB +0180A2495A5C137F495A16034890C7FC5B1203485AEE0700485A495C001F5D48485C5E48 +48495A49130FB8FCA329397BB833>II93 D<007FB81280B912C0A26C17 +803204797041>95 D97 DIIII<147E903803FF8090 +380FC1E0EB1F8790383F0FF0137EA213FCA23901F803C091C7FCADB512FCA3D801F8C7FC +B3AB487E387FFFF8A31C3B7FBA19>IIIIIII<2703F00FF0EB1FE000FFD93FFCEB +7FF8913AF03F01E07E903BF1C01F83803F3D0FF3800FC7001F802603F70013CE01FE14DC +49D907F8EB0FC0A2495CA3495CB3A3486C496CEB1FE0B500C1B50083B5FCA340257EA445 +>I<3903F00FF000FFEB3FFCECF03F9039F1C01F803A0FF3800FC03803F70013FE496D7E +A25BA35BB3A3486C497EB500C1B51280A329257EA42E>II<3903F01F +E000FFEB7FF89038F1E07E9039F3801F803A07F7000FC0D803FEEB07E049EB03F04914F8 +49130116FC150016FEA3167FAA16FEA3ED01FCA26DEB03F816F06D13076DEB0FE001F614 +C09039F7803F009038F1E07E9038F0FFF8EC1FC091C8FCAB487EB512C0A328357EA42E> +II<3807E01F00FFEB7FC09038E1E3E09038E387F0380FE707EA03E613EE9038EC03E0 +9038FC0080491300A45BB3A2487EB512F0A31C257EA421>II<1318A51338A31378A313F812011203 +1207001FB5FCB6FCA2D801F8C7FCB215C0A93800FC011580EB7C03017E13006D5AEB0FFE +EB01F81A347FB220>IIIIII<003FB512FCA2EB8003D83E0013F8003CEB07F00038 +EB0FE012300070EB1FC0EC3F800060137F150014FE495AA2C6485A495AA2495A495A495A +A290387F000613FEA2485A485A0007140E5B4848130C4848131CA24848133C48C7127C48 +EB03FC90B5FCA21F247EA325>II<126012F0B3B3B3 +B3A91260045377BD17>I<12FCEAFFC0EA07F0EA01FCEA007E7F80131F80130FB3A78013 +07806D7E6D7EEB007EEC1FF0EC07F8EC1FF0EC7E00495A495A495A5C130F5CB3A7131F5C +133F91C7FC137E485AEA07F0EAFFC000FCC8FC1D537ABD2A>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fi ecbx1440 14.4 34 +/Fi 34 118 df28 D45 D<151E153E15FE1403140F147FEB07FF00 +03B5FCB6FCA3EBF87FEAFC00C7FCB3B3B3A6007FB712FCA52E4E76CD42>49 +DI<913807FFC0027F13FC0103B67E010F15E090 +261FF80313F890267FC0007F01FEC7EA3FFE48488148486E138013FE486C6C6D13C08048 +17E080A66C5B18C06C5B6C90C75AD80038168090C8FC4C1300A24C5A5F4C5A4B5B4B13C0 +030F5BDB7FFEC7FC91387FFFF816C016FCEEFF80DA000313E09238007FF8EE3FFE707E70 +138018C07013E018F07013F8A218FC82A218FEA3EA03C0EA0FF0EA3FFC487EA2B5FCA218 +FCA25E18F8A26C4816F0495C4916E0D83FE04A13C06C485CD80FF04A1380D807FE91387F +FE003B03FFE003FFFC6C90B65A6C6C15E0010F92C7FC010114FCD9001F1380374F7BCD42 +>I<17FC1601A216031607160FA2161F163F167FA216FF5D5DA25D5D5D167F153E157E15 +FC15F8EC01F01403EC07E015C0EC0F80141FEC3F00143E5C14FC495A5C495A1307495A5C +49C7FC5B137E137C5B1201485A5B485A120F485A90C8FC123E127E5ABA1280A5C901FCC7 +FCAF021FB71280A5394F7CCE42>I<486C150601F0153E01FEEC01FED9FFF0133F91B65A +5F5F5F5F5F94C7FC16FC5E16E093C8FC15FC01F0138091CAFCAC913807FF80023F13F891 +B512FE01F36E7E9026FFFC0113E09139E0007FF891C76C7E496E7E01F86E7E5B70138049 +16C0C9FC18E08218F0A418F8A31203EA0FE0EA3FF8487EA212FF7FA218F0A25B5E6C4816 +E05B01C016C06CC85A18806C6C4A13007FD80FF04A5A6C6CECFFFCD803FE4913F02701FF +E00F5B6C6CB612806D92C7FC010F14F8010114C09026003FFCC8FC354F7ACD42>I58 +D<932603FFF01407047F01FF5C0307B600E05B033F03F85B92B700FE5B02039126C003FF +5B020F01F8C7EA3FC1023F01C0EC0FE391B5C80003B5FC4901FC814949814901E082011F +498249498292CA7E4948834948835A4A83485B4885A2484984A2485B87A2485B87A25AA2 +98C8FC91CFFCA2B5FCAE7E067FB7128080A37E95C76C90C7FC807EA36C7FA26C7FA26C7F +7E806C7F137F6D7E816D6D93B5FC01077F6D01F85D6D7F6D01FF5D023F01E0EC0FEF020F +01FCEC3FE30203903AFFE001FF81020091B6C6FC033F03FC133F030703F0130FDB007F02 +801303040301F8CAFC595479D267>71 D73 D76 +D78 D80 D<93381FFF800303B512FC033FECFFC0 +92B712F00207D9F80113FE021F903AC0003FFF804A48C700077FDAFFF8020113F049496E +7F49496F7E49496F7E49496F7E4990C96C7F4948707F4948707F01FF854849707F4A8248 +86A24849717E48864A83A2481B80A248497113C0A4481BE0A291CB7EA3B51AF0AF6C1BE0 +A36E5FA26C1BC0A36C1B806E5FA26C1B006E5F6C62A26C6DD903FC4A5A6CDB0FFF5D6E49 +EBC0016C4B01E05C6D6C90277E07F0035B6E9039F801F807902A3FFF01F000780F5B6D04 +7C5C6DD981E06D4890C7FC6D01E191381F7FFE010101F1EDFFF86DD9F9F06D5BDA3FFF16 +C06E6D013F5B02079027FE01FFFEC8FC020190B612F8DA003F4B141003071838DB001FEB +83F893C7EA03FC1C7885726C14F8F2C003F2F01F97B512F084A31CE085A27314C01C8085 +1C00735B735B735B735B9638003FC0556A79D263>III<003FBB12FCA59126C0007FEB000301FCC7ED003FD87FF0F00FFE491807 +49180349180190C81600A2007E1A7EA3007C1A3EA500FC1A3F481A1FA6C91700B3B3AC49 +B912C0A550517BD05B>I97 D<913803FFE0023F13FE91B67E010315E0010F9038003FF8D93FFCEB +07FC4948497E4948131F4849497E485B485BA24890C7FC5A5B003F6F5A705A705A007F92 +C8FC5BA312FFAD127F7FA3123F7F6CEE0F80A26C6D141F18006C6D5C6C6D143E6C6D147E +6C6D5C6D6C495A6DB4EB07F0010F9038C01FE06D90B5128001014AC7FCD9003F13F80203 +138031387CB63A>99 D<943803FF80040FB5FCA5EE003F170FB3A4913803FF80023F13F8 +49B512FE0107ECFF8F011F9038C03FEF90273FFE0007B5FCD97FF8130149487F48498048 +4980484980488291C8FC5A5B123FA2127F5BA312FFAD127FA37F123FA3121F7F6C5E6C6D +5C5F6C6D91B5FC6C6D5B6C6D4914E0D97FFCD90FEFEBFF80D91FFFEB7F8F010790B5120F +010114FC6D6C13E00207010049C7FC41547CD249>I<913807FF80027F13F849B512FE01 +076E7E011F010313E0903A3FFC007FF0D97FF06D7E49486D7E4849130F48496D7E488248 +90C77E1880485A82003F17C0A3485A18E082A212FFA290B8FCA401FCCAFCA6127FA37F12 +3FA2EF03E06C7E17076C17C06C6D140F18806C6D141F6C6DEC3F006C6D147ED97FFC495A +D91FFFEB07F86D9038E03FF0010390B512C001005D023F01FCC7FC020113E033387CB63C +>IIII<133FEBFFC0 +487F487FA2487FA66C5BA26C5B6C5B013FC7FC90C8FCAEEB1FF8B5FCA512017EB3B3A6B6 +12F0A51C547CD324>I108 +DII<913801FFC0023F13FE91B67E010315E001 +0F018013F8903A3FFC001FFED97FF0EB07FF49486D7F48496D7F48496D7F91C8127F4883 +488349153F001F83A2003F8349151FA2007F83A400FF1880AC007F1800A3003F5F6D153F +A2001F5FA26C6C4B5AA26C6D4A5A6C5F6C6D495B6C6D495B6D6C4990C7FCD93FFCEB1FFE +6DB46CB45A010790B512F0010115C0D9003F49C8FC020313E039387CB642>II<90393FF001FCB590 +380FFF804B13E0037F13F09238FE1FF89138F1F83F00019138F07FFC6CEBF3E015C0ECF7 +80A2ECFF00EE3FF84AEB1FF0EE0FE093C7FC5CA45CB3ABB612FEA52E367DB535>114 +D<903903FFC00E011FEBFC1E90B6127E000315FE3907FE003FD80FF0130F484813034848 +1301491300127F90C8127EA248153EA27FA27F01F091C7FC13FCEBFF806C13FEECFFF06C +14FE6F7E6C15E06C816C15FC6C81C681133F010F15801301D9000F14C0EC003F030713E0 +150100F880167F6C153FA2161F7EA217C07E6D143F17807F6DEC7F0001F85C6DEB03FE90 +39FF801FFC486CB512F0D8F81F14C0D8F00791C7FC39E0007FF02B387CB634>I<147CA6 +14FCA41301A31303A21307A2130F131F133F137F13FF1203000F90B512FEB7FCA426007F +FCC8FCB3A9EE0F80ABEE1F006D7EA2011F143E806D6D5A6DEBC1F86DEBFFF001005C023F +1380DA03FEC7FC294D7ECB33>II E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fj ecrm0900 9 5 +/Fj 5 109 df<123C127E12FFA4127E123C08087A8715>46 D97 DI104 +D108 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fk ecbx0900 9 7 +/Fk 7 117 df65 D97 DI<903807FF80013F13F090B512FC3903FE01FE4848487EEA0FF8EA1FF0EA3FE0 +A2007F6D5A496C5A153000FF91C7FCA9127F7FA2003FEC07807F6C6C130F000FEC1F00D8 +07FE133E3903FF80FCC6EBFFF8013F13E0010790C7FC21217DA027>I<3901F81F8000FF +EB7FF0ECFFF89038F9E3FC9038FBC7FE380FFF876C1307A213FEEC03FCEC01F8EC006049 +1300B1B512F0A41F217EA024>114 D<9038FFE1C0000713FF5A383F803F387E000F1407 +5A14037EA26C6CC7FC13FCEBFFE06C13FC806CEBFF80000F14C06C14E0C6FC010F13F0EB +007F140F00F0130714037EA26C14E06C13076CEB0FC09038C01F8090B5120000F913FC38 +E03FE01C217DA023>I<133CA5137CA313FCA21201A212031207001FB51280B6FCA3D807 +FCC7FCB0EC03C0A79038FE078012033901FF0F006C13FEEB3FFCEB0FF01A2F7EAE22>I +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fl ecrm1200 12 25 +/Fl 25 122 df<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A3120113 +80120313005A1206120E5A5A5A12600B1D78891B>44 D<14FF010713E090381F81F89038 +3E007C01FC133F4848EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F15 +F8A2003F15FCA390C8FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8A2 +6C6CEB03F0A36C6CEB07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F81 +F8903807FFE0010090C7FC28447CC131>48 D50 D54 D<16C04B7EA34B7EA34B7EA34B7EA3ED +19FEA3ED30FFA203707FED607FA203E07FEDC03FA2020180ED801FA2DA03007F160FA202 +06801607A24A6D7EA34A6D7EA34A6D7EA20270810260147FA202E08191B7FCA249820280 +C7121FA249C87F170FA20106821707A2496F7EA3496F7EA3496F7EA201788313F8486C83 +D80FFF03037FB500E0027FEBFFC0A342477DC649>65 DI68 D77 +D<003FB912F8A3903BF0001FF8001F01806D481303003EC7150048187C0078183CA20070 +181CA30060180CA5481806A5C81600B3B3A54B7EED7FFE49B77EA33F447DC346>84 +D +I97 +D99 D<167FED3FFFA315018182B3EC7F80903803 +FFF090380FC07C90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2485AA2 +127FA290C8FC5AAB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F806C6C +010E13C0013F011C13FE90380FC0F8903803FFE09026007F0013002F467DC436>II103 D105 D108 D<3901FC01FE00FF903807FFC091381E +07F091383801F8000701707F0003EBE0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8 +486CECFF80B5D8F83F13FEA32F2C7DAB36>110 DI<3903F803F000FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C000015B13FBEC00 +7E153C01FF13005BA45BB3A748B4FCB512FEA3202C7DAB26>114 +D<90383FE0183901FFFC383907E01F78390F0003F8001E1301481300007C1478127800F8 +1438A21518A27EA27E6C6C13006C7E13FC383FFFE06C13FC6C13FF6C14C06C14E0C614F0 +011F13F81300EC0FFC140300C0EB01FE1400157E7E153EA27EA36C143C6C147C15786C14 +F86CEB01F039F38003E039F1F00F8039E07FFE0038C00FF01F2E7DAC26>I<1306A5130E +A4131EA3133E137EA213FE12011207001FB512F0B6FCA2C648C7FCB3A4150CAA017E131C +017F1318A26D133890381F8030ECC070903807E0E0903801FFC09038007F001E3E7EBC26 +>III< +B539F001FFFCA3000790C7EA7FE06C48EC1F8000011600160E0000150C6D141C6D1418A2 +6E1338013F1430A26D6C5BA26E13E0010F5CA26D6C485AA2ECF803010391C7FCA2903801 +FC06A2ECFE0E0100130CA2EC7F18A215B8EC3FB0A2EC1FE0A36E5AA26E5AA36EC8FCA214 +06A35CA25CA2123C007E5BB4FC5CA25CEAFE01387C0380D87007C9FCEA3C1EEA0FFCEA03 +F02E3F7EAA33>121 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fm ecbx1200 12 47 +/Fm 47 123 df<0118140C017C143E01FC147E48485C4848495A495C4848495A4848495A +001F140F90C75B003E4AC7FCA2003C141E007C143E0078143CA200F8147CA2481478D8F1 +F014F8D8F7FCEB7BFEB46CEB7FFF6D1580028014C0A36C80A36C806C496C13806C486D13 +006C486D5AD801F0EB00F82A2283C427>16 DI28 D46 D48 DIII<163FA25E5E5D5DA25D5D5D5DA25D92B5FCEC01F7EC03E7140715 +C7EC0F87EC1F07143E147E147C14F8EB01F0EB03E0130714C0EB0F80EB1F00133E5BA25B +485A485A485A120F5B48C7FC123E5A12FCB91280A5C8000F90C7FCAC027FB61280A53141 +7DC038>I<0007150301E0143F01FFEB07FF91B6FC5E5E5E5E5E16804BC7FC5D15E092C8 +FC01C0C9FCAAEC3FF001C1B5FC01C714C001DF14F09039FFE03FFC9138000FFE01FC6D7E +01F06D13804915C0497F6C4815E0C8FC6F13F0A317F8A4EA0F80EA3FE0487E12FF7FA317 +F05B5D6C4815E05B007EC74813C0123E003F4A1380D81FC0491300D80FF0495AD807FEEB +FFFC6CB612F0C65D013F1480010F01FCC7FC010113C02D427BC038>I<4AB47E021F13F0 +027F13FC49B6FC01079038807F8090390FFC001FD93FF014C04948137F4948EBFFE04849 +5A5A1400485A120FA248486D13C0EE7F80EE1E00003F92C7FCA25B127FA2EC07FC91381F +FF8000FF017F13E091B512F89039F9F01FFC9039FBC007FE9039FF8003FF17804A6C13C0 +5B6F13E0A24915F0A317F85BA4127FA5123FA217F07F121FA2000F4A13E0A26C6C15C06D +4913806C018014006C6D485A6C9038E01FFC6DB55A011F5C010714C0010191C7FC903800 +3FF02D427BC038>I<121E121F13FC90B712FEA45A17FC17F817F017E017C0A248168000 +7EC8EA3F00007C157E5E00785D15014B5A00F84A5A484A5A5E151FC848C7FC157E5DA24A +5A14035D14074A5AA2141F5D143FA2147F5D14FFA25BA35B92C8FCA35BA55BAA6D5A6D5A +6D5A2F447AC238>I58 D<1A60F101F01907191FF17FC0953801FF00F007FCF01FF0F07FC04D48C7FCEF07 +FCEF3FF0EFFFC0040390C8FCEE0FFCEE3FE0EEFF80DB03FEC9FCED0FF8ED3FE0EDFF80DA +07FECAFCEC1FF8EC7FE0903801FF80D907FCCBFCEB1FF0EB7FC04848CCFCEA07FCEA1FF0 +EA7FC048CDFCA2EA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FC903801FF809038 +007FE0EC1FF8EC07FE913800FF80ED3FE0ED0FF8ED03FE923800FF80EE3FE0EE0FFCEE03 +FF040013C0EF3FF0EF07FCEF01FF9438007FC0F01FF0F007FCF001FF9538007FC0F11FF0 +19071901F10060444277B957>60 D<126012F812FE6C7EEA3FE0EA0FF8EA03FEC66C7EEB +3FE0EB0FF8EB03FE903800FFC0EC3FF0EC0FFCEC03FF9138007FC0ED1FF0ED07FCED01FF +9238007FC0EE1FF0EE07FE933801FF809338007FE0EF1FF8EF03FE943800FF80F03FE0F0 +0FF8F003FE953800FF80F13FE0F10FF0A2F13FE0F1FF80953803FE00F00FF8F03FE0F0FF +80DD03FEC7FCEF1FF8EF7FE0933801FF80DC07FEC8FCEE1FF0EE7FC04B48C9FCED07FCED +1FF0ED7FC0DA03FFCAFCEC0FFCEC3FF0ECFFC0D903FECBFCEB0FF8EB3FE0EBFF80D803FE +CCFCEA0FF8EA3FE0EAFF8048CDFC12F81260444277B957>62 D<923803FFF0037FEBFF80 +0203B612F0020F15FC913A3FFC000FFFDAFFC0010013C0D903FEC8EA1FF0D907F0ED03F8 +D91FC0ED00FE4948167F017ECAEA1F8049717E4848717E49DAFF8013034848010F01F06D +7E4848013F01FC6D7E92B6FC4848489026C07F80137C49489026001FC0133C484948D907 +E0133E001E49486D6C131E003E49480101141F023F913800FFE0003C4A82007C017F1880 +007819074A5AA300F81AC04848491603AB6C6C7F12781B801A076E7E127C003C133F003E +6E1700021F4A5C001E6D6C5B001F6D6C49EBF01E6C6D6C011F143E6D6CD9C07F6D5A6C6C +6C90B5383FFFF8033FD9FC0F5B6C6C010FD9F0035B6C6C0100903980007F806D91CBFC6C +7E137E6D7E6D6CEF7FC0D907F0EE03FFD903FE043F1300902600FFC0913803FFF8DA3FFC +49B512C0020FB748C7FC020316E0DA007F02FCC8FC030349C9FC4A477AC557>64 +DIIII73 D77 D<923807FFC092B512FE0207ECFFC0021F15F0 +91267FFE0013FC902601FFF0EB1FFF01070180010313C04990C76C7FD91FFC6E6C7E4948 +6F7E49486F7E01FF8348496F7E48496F1380A248496F13C0A24890C96C13E0A24819F049 +82003F19F8A3007F19FC49177FA400FF19FEAD007F19FC6D17FFA3003F19F8A26D5E6C19 +F0A26E5D6C19E0A26C6D4B13C06C19806E5D6C6D4B13006C6D4B5A6D6C4B5A6D6C4B5A6D +6C4A5B6D01C001075B6D01F0011F5B010101FE90B5C7FC6D90B65A023F15F8020715C002 +004AC8FC030713C047467AC454>79 D83 D<007FBA12E0BB12F0A46C19E04406776757>95 D<903801FFE0011F13FE017F6D +7E48B612E03A03FE007FF84848EB1FFC6D6D7E486C6D7EA26F7FA36F7F6C5A6C5AEA00F0 +90C7FCA40203B5FC91B6FC1307013F13F19038FFFC01000313E0481380381FFE00485A5B +127F5B12FF5BA35DA26D5B6C6C5B4B13F0D83FFE013EEBFFC03A1FFF80FC7F0007EBFFF8 +6CECE01FC66CEB8007D90FFCC9FC322F7DAD36>97 DIIIIIII<137C48B4FC4813804813C0A24813E0A56C13 +C0A26C13806C1300EA007C90C7FCAAEB7FC0EA7FFFA512037EB3AFB6FCA518467CC520> +I108 D<90277F8007FEEC0FFC +B590263FFFC090387FFF8092B5D8F001B512E002816E4880913D87F01FFC0FE03FF8913D +8FC00FFE1F801FFC0003D99F009026FF3E007F6C019E6D013C130F02BC5D02F86D496D7E +A24A5D4A5DA34A5DB3A7B60081B60003B512FEA5572D7CAC5E>I<90397F8007FEB59038 +3FFF8092B512E0028114F8913987F03FFC91388F801F000390399F000FFE6C139E14BC02 +F86D7E5CA25CA35CB3A7B60083B512FEA5372D7CAC3E>II<90397FC00FF8B590B57E02C314E002CF14F89139DFC03F +FC9139FF001FFE000301FCEB07FF6C496D13804A15C04A6D13E05C7013F0A2EF7FF8A4EF +3FFCACEF7FF8A318F017FFA24C13E06E15C06E5B6E4913806E4913006E495A9139DFC07F +FC02CFB512F002C314C002C091C7FCED1FF092C9FCADB67EA536407DAC3E>II<90387F807FB53881FFE002 +8313F0028F13F8ED8FFC91389F1FFE000313BE6C13BC14F8A214F0ED0FFC9138E007F8ED +01E092C7FCA35CB3A5B612E0A5272D7DAC2E>I<90391FFC038090B51287000314FF120F +381FF003383FC00049133F48C7121F127E00FE140FA215077EA27F01E090C7FC13FE387F +FFF014FF6C14C015F06C14FC6C800003806C15806C7E010F14C0EB003F020313E0140000 +F0143FA26C141F150FA27EA26C15C06C141FA26DEB3F8001E0EB7F009038F803FE90B55A +00FC5CD8F03F13E026E007FEC7FC232F7CAD2C>II< +D97FC049B4FCB50103B5FCA50003EC000F6C81B3A85EA25EA25E7E6E491380017FD901F7 +13FE9138F807E76DB512C7010F1407010313FE9026007FF0EBFC00372E7CAC3E>I +I120 +D<001FB71280A49026FC001F130001E0495A5B49495A90C7485A48495B123E4A5B4A5B00 +3C495BA24A90C7FC4A5A4A5AC7FC4A5A495B495BA2495B499038800780491300A2495A49 +48130F49481400A2485B48495B485BA248495B4890C75A48485C15034848EB1FFEB7FCA4 +292C7DAB32>122 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fn ecrm1728 17.28 8 +/Fn 8 117 df68 D70 D97 D102 D<1378EA01FE487E487FA66C +90C7FC6C5AEA007890C8FCB3A2EB0780EA0FFFB5FCA41203C6FCA2137FB3B3AC497E487F +B61280A4195F7BDE25>105 D<010FEB07F8D80FFFEB1FFEB590387FFF809238F81FC091 +3801E03F913903C07FE00003EB0780C6EB0F00140E6D5A0218EB3FC00238EB1F800230EB +0600027090C7FCA2146014E0A25CA55CB3B0497E4813F0B612F8A42B3F7BBE34>114 +D<9138FFC003010FEBF807017FEBFE0F3A01FF003F9FD803F0EB07DF48486DB4FCD80F80 +1300001F8148C8FC003E81007E81127C00FC81A4827EA27E7F6C7E6D91C7FC13F8EA3FFE +381FFFE06C13FF15F0000314FE6C6E7E6C6C14E0011F14F801078001008002077FDA003F +13801507030113C0ED007F00E0ED3FE0161F17F06C150F1607A36C1503A37EA26C16E016 +077E17C06D140F6D15806D141FD8FDF0EC3F00D8F8F8147E017C495A3AF01F801FF06DB5 +12C0D8E00391C7FC39C0007FF02C417CBF35>I<1470A714F0A51301A31303A21307A213 +0FA2131F133F137F13FF1203000F90B6FCB8FCA326000FF0C8FCB3AEEE01C0AE6D6CEB03 +80A316076D6C14005E6D6C130E6D6C131E6E6C5A91383FE0F86EB45A020713C0020090C7 +FC2A597ED734>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fo ecbx1728 17.28 18 +/Fo 18 117 df68 D<942603FFF8151C94B66C +143C040F03F0147C047F03FC14FC0303B81301030FDAC00113C0033F01F8C7381FF00392 +B500C0913807F807020349C83801FE0F020F01F89238007F1F4A01E0EE3FBF4A49EE0FFF +91B5CA7E494983494983494983495B4949187F4B183F491A1F495B90B5CC120FA2484919 +075A4A19035A4A19015AA24A19005AA348491A7CA35A9AC8FCA35CA2B5FCB07EA26E043F +B81280A47E96C7000701FCC7FCA26C7FA37E80A27E807E807E6C7FA26D7F6D7F7F816D7F +6D6D5F6D7F6D6D5F6D6D7E023F6D5E6E01F05E6E6DEEFE7F020301FF923801FC3F020002 +C0913807F80F033F01FC91381FF007030F903BFFE001FFC001030391B6EA8000DB007F4B +C7123C040F03F8140C040003C091C8FC050301F8CBFC696677E37A>71 +D82 D<001FBD12F0A59126F8000191C7123F4801C0 +060713F849C71700491A7F01F01A1F491A0F491A07A2491A03A290C81801A2007EF300FC +A4007C1C7CA7481C3EA5C91900B3B3B3A5023FB912F8A55F617AE06C>84 +D<913803FFF0027F13FF0103B612E0010F15F890263FFC0013FED97FC090381FFF8049C7 +6C7F4801C06D7F486D6D7F6E6D7F48836E7F84177F84A36C496E7FA26C5B6C5B013FC8FC +90C9FCA75F0307B6FC4AB7FC141F91B5EAF03F0103EBFE00010F13F0013F1380D9FFFEC7 +FC485B485B485B485B485B485BA24890C8FC1A7CA2485AA35FA394B5FC7F6C5D6EEB03DF +6CDB07CFEBC0F86C6DEB0F8F6C6DD91F07EBF3F06C01F8017E14FF6C9027FE01FC0314E0 +C690B5D8F00114C0013F9126C0007F1380010791C7383FFE009026003FF8EC07F846437B +C14D>97 D<903807FF80B6FCA5C6FC7F7FB3A9933801FFE0041F13FE047FEBFFC00381B6 +12F0922687FC0113FC923A9FE0003FFEDBBF8090380FFF8003FEC76C7F4B6E7F4B6E7F4B +6E7F4B824B157F4B82737EA21B80851BC0A31BE085A41BF0AE1BE0A44F13C0A31B80A24F +1300A262197F6F5E6F4B5A4E5B6F4A5BDAFCF84A5BDAF87E4A5B4A6C4A90C7FC9126E01F +C0EB7FFC913BC00FF803FFF8DA8003B612E091C71580013E023F01FCC8FC90C800031380 +4C657CE356>II101 DII105 D<903807FF80B6FCA5C6FC7F7FB3B3B3B3AFB7 +12E0A523647CE32A>108 D110 D<92381FFF804AB512F8020F +14FF023F15C09126FFFC0313F001039039E0007FFC490180EB1FFED91FFEC73807FF8049 +486E7F49486E7F49486E7F48496F7EA248496F7E4884A248496F7EA2481980A24819C091 +C97EA24819E0A5B518F0AD6C19E0A46C6D4B13C0A36C1980A26C6D4B1300A26C606E157F +6C606C6D4B5A6C606D6C4A5B6D6C4A5B6D6C4A5B6D6C6C011F90C7FC010301E0EB7FFC6D +9039FC03FFF86D6CB612E0020F92C8FC020114F8DA001F138044437CC14D>I<903B07FF +8001FFE0B6011F13FE047FEBFFC00381B612F0922687FC0313FC923A9FE0007FFEC6DABF +806D6C7E6D01FEC7000F7F6D496E7F4B824B6E7F4B6E7F4B804B82737EA21B80851BC0A2 +851BE0A4851BF0AE4F13E0A41BC061A21B80A24F1300A24F5AA26F4A5B6F4A5B626F4A5B +6F4A5B03FE4A5B03BF027F90C7FCDB9FC0EBFFFC92268FF8075B0383B612E00380158004 +3F01FCC8FC0403138093CBFCB3A4B712E0A54C5D7CC056>I114 DII E +%EndDVIPSBitmapFont +end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop 290 639 a Fo(Genealogical)56 b(Represen)l(tation)e(of)f(T)-13 +b(rees)52 b(in)g(Databases)1686 822 y Fn(First)46 b(Draft)1247 +1063 y Fm(Miguel)36 b(Sofer)i()1359 1179 +y Fl(Univ)m(ersidad)33 b(T)-8 b(orcuato)33 b(Di)f(T)-8 +b(ella)1728 1295 y(Buenos)33 b(Aires)1797 1411 y(Argen)m(tina)1746 +1606 y(Ma)m(y)h(6,)e(2000)1839 1905 y Fk(Abstract)441 +2035 y Fj(blah)25 b(blah)h(.)13 b(.)g(.)118 2310 y Fi(1)131 +b(In)l(tro)t(duction)118 2491 y Fh(T)-7 b(rees)28 b(are)h(a)g(v)n(ery)f +(frequen)n(t)h(data)f(structure.)41 b(They)30 b(are)e(the)h(natural)g +(represen)n(tation)e(for)i(instance)g(for)f(organiza-)118 +2591 y(tional)f(c)n(harts,)g(threaded)g(discussion)g(groups,)f(some)h +(bills)g(of)h(materials,)e(.)14 b(.)g(.)243 2691 y(A)n(t)28 +b(least)f(t)n(w)n(o)f(alternativ)n(e)h(represen)n(tations)e(for)i +(trees)g(in)h(RDBMs)g(are)e(kno)n(wn)h(and)h(used:)220 +2857 y(1.)41 b Fg(P)m(oin)m(ters:)k Fh(a)31 b(\034eld)h(in)h(the)f(c)n +(hild)g(record)e(references)h(the)h(paren)n(t)f(no)r(de.)50 +b(This)32 b(seems)g(to)f(b)r(e)i(the)f(canonical)326 +2956 y(represen)n(tation.)38 b(Some)29 b(DB)g(engines)f(pro)n(vide)g +(sp)r(ecial)g(SQL)g(extensions)g(to)h(simplify)g(tree)g(searc)n(hes;)e +(Oracle)326 3056 y(tree)d(extensions)g(are)g(an)h(example)f(\(see)h +(for)f(instance)g([1]\);)i(DB2's)f(WITH)g(can)f(b)r(e)i(used)e(for)h +(this)g(purp)r(ose)f(to)r(o)326 3156 y(\(see)j([3],)g(pp)h(139-162\).) +220 3322 y(2.)41 b Fg(Nested)35 b(Sets:)43 b Fh(t)n(w)n(o)30 +b(n)n(umeric)h(\034elds)g(in)g(ev)n(ery)f(no)r(de)h(record)f(co)r(de)h +(the)g(tree)g(structure.)47 b(I)31 b(can't)g(pro)n(vide)f(a)326 +3421 y(b)r(etter)e(or)e(briefer)h(description)g(of)h(this)g(metho)r(d)g +(than)f(the)h(four)f(articles)g([2].)118 3587 y(These)g(t)n(w)n(o)g +(metho)r(ds)h(o\033er)f(di\033eren)n(t)h(adv)-5 b(an)n(tages)25 +b(and)j(disadv)-5 b(an)n(tages:)243 3753 y Ff(\017)41 +b Fh(P)n(oin)n(ters)30 b(are)g(extremely)g(e\036cien)n(t)h(for)f(no)r +(de)h(insertion)f(and/or)g(deletion,)h(but)h(require)e(recursiv)n(e)f +(table)i(ac-)326 3853 y(cesses)e(to)h(searc)n(h)f(the)h(tree)g(\(I)h +(do)f(not)g(kno)n(w)f(the)i(implemen)n(tation)f(details)g(of)g(the)h +(Oracle)e(tree)g(extensions,)326 3953 y(whic)n(h)e(as)g(far)g(as)g(I)g +(kno)n(w)g(ma)n(y)g(solv)n(e)f(this)i(problem)f(in)n(ternally;)g(they)g +(de\034nitely)h(solv)n(e)f(it)g(for)g(the)h(end)g(user\).)243 +4119 y Ff(\017)41 b Fh(Nested)30 b(sets)g(are)f(v)n(ery)f(e\036cien)n +(t)i(for)g(tree)f(searc)n(hes,)g(but)i(are)e(rather)f(exp)r(ensiv)n(e)i +(for)f(no)r(de)h(insertion)f(and/or)326 4218 y(deletion:)37 +b(they)27 b(require)g(up)r(dating)g(p)r(oten)n(tially)h(man)n(y)f(no)r +(des.)243 4384 y(W)-7 b(e)30 b(prop)r(ose)f(here)h(a)g(di\033eren)n(t)h +(represen)n(tation,)e(based)g(on)i(no)r(de)f(iden)n(ti\034ers)g(whic)n +(h)g(are)f(\020genealogical)f(iden)n(ti-)118 4484 y(\034ers\021:)44 +b(they)32 b(con)n(tain)f(the)h(complete)f(genealogy)f(of)h(the)h(no)r +(de,)h(i.e.,)g(the)f(list)g(of)g(ancestors)d(up)j(to)g(the)g(ro)r(ot)f +(of)g(the)118 4584 y(tree.)243 4683 y(This)j(allo)n(ws)f(to)i(replace)e +(man)n(y)h(searc)n(hes)f(in)h(database)g(tables)g(with)h(string)f(op)r +(erations)f(on)h(the)h(index.)58 b(The)118 4783 y(result,)24 +b(as)f(explained)h(in)g(Section)g(3)f(is)h(that)g(tree)f(searc)n(hes)f +(pro)r(ceed)h(at)h(\020nested)f(sets\021)30 b(sp)r(eed,)25 +b(while)f(no)r(de)g(insertions)118 4882 y(and)k(deletions)f(are)f(as)h +(fast)h(as)f(with)h(p)r(oin)n(ters.)243 4982 y(The)i(ob)n(vious)f(do)n +(wnside)h(of)h(the)g(metho)r(d)g(is)f(that)h(the)g(primary)f(k)n(ey)f +(in)i(the)g(tree)f(needs)h(to)f(b)r(e)h(a)g(v)-5 b(ariable)29 +b(size)118 5082 y(text)j(\034eld,)h(and)f(that)g(the)g(iden)n +(ti\034ers)f(ma)n(y)g(b)r(e)i(extremelly)e(long)g(for)g(deep)h(trees.) +49 b(W)-7 b(e)32 b(will)g(pro)n(vide)e(estimates)i(of)118 +5181 y(the)c(size)f(required)g(as)g(a)g(function)h(of)g(the)f +(magnitude)h(of)f(the)h(tree.)1987 5653 y(1)p eop +%%Page: 2 2 +2 1 bop 118 291 a Fi(2)131 b(Genealogical)45 b(iden)l(ti\034ers)g(for)f +(trees)118 489 y Fm(2.1)112 b(De\034nition)118 642 y +Fh(W)-7 b(e)28 b(de\034ne)g Fe(gene)l(alo)l(gic)l(al)k(identi\034ers)j +Fh(recursiv)n(ely)25 b(as)i(follo)n(ws:)326 808 y Fg(De\034nition:)59 +b Fe(The)42 b(gene)l(alo)l(gic)l(al)h(identi\034er)f(\(gID\))e(of)i(a)f +(no)l(de)h(is)f(obtaine)l(d)h(by)g(app)l(ending)g(a)f(child)326 +908 y(identi\034er)30 b(to)g(the)g(gene)l(alo)l(gic)l(al)h +(identi\034er)g(of)f(the)g(p)l(ar)l(ent)f(no)l(de.)243 +1074 y Fh(Remark)40 b(that)h(genealogical)e(iden)n(ti\034ers)i(are)f +(rather)g(w)n(ell)h(kno)n(wn)f(and)h(used;)48 b(common)41 +b(examples)f(are)g(the)118 1174 y(\020path+\034le-name\021)33 +b(in)28 b(a)f(computer)g(\034le)h(system)f(and)h(the)f(URLs)h(within)g +(a)f(WWW.)243 1273 y(The)d(name)g(\020genealogical)e(iden)n +(ti\034er\021)30 b(is)24 b(suggested)g(b)n(y)g(the)g(fact)h(that)f(the) +h(v)-5 b(alue)24 b(of)g(the)h(iden)n(ti\034er)f(con)n(tains)f(the)118 +1373 y(complete)30 b(genealogy)d(of)j(the)g(no)r(de:)41 +b(it)30 b(con)n(tains)e(as)h(a)h(substring)f(the)h(gID)f(of)h(its)g +(father,)g(whic)n(h)f(in)h(turn)g(con)n(tains)118 1472 +y(as)d(a)g(substring)g(the)h(gID)g(of)f(the)h(grandfather,)e(.)14 +b(.)g(.)243 1572 y(The)27 b(ro)r(ot)g(no)r(de)h(of)f(the)h(tree)f(has)g +(a)h(gID)f(with)h(v)-5 b(alue)28 b(\021)34 b(\(the)28 +b(empt)n(y)g(string\),)f(as)g(it)h(has)f(no)g(paren)n(t.)118 +1804 y Fm(2.2)112 b(Child)36 b(iden)m(ti\034ers)118 1958 +y Fh(The)26 b(ob)n(vious)e(c)n(hild)i(iden)n(ti\034er)g(is)f(a)h +(zero-based)d(coun)n(ter:)35 b(iden)n(tify)26 b(the)h(c)n(hild)e(b)n(y) +h(the)g(n)n(um)n(b)r(er)f(of)h(older)f(brethren)g(it)118 +2057 y(has.)243 2157 y(W)-7 b(e)25 b(could)f(represen)n(t)g(the)h(coun) +n(ter)f(in)h(base)f(10;)h(this)g(ho)n(w)n(ev)n(er)e(is)i(extremely)f(w) +n(asteful)g(of)h(resources.)34 b(It)25 b(is)g(m)n(uc)n(h)118 +2257 y(b)r(etter)33 b(to)f(represen)n(t)f(the)h(coun)n(ter)g(in)g(as)g +(large)e(a)i(base)g(as)f(p)r(ossible:)46 b(in)n(terpret)32 +b(as)f(n)n(um)n(b)r(ers)h(a)g(set)g(of)g(c)n(haracters)118 +2356 y(larger)26 b(than)h({0,1,.)14 b(.)g(.)g(9}.)243 +2456 y(As)26 b(tree)f(op)r(erations)f(will)i(in)n(v)n(olv)n(e)f(string) +g(op)r(erations)f(on)i(the)g(indices,)g(in)g(order)f(to)g(a)n(v)n(oid)g +(a)g(\020quoting)g(hell\021)33 b(it)26 b(is)118 2555 +y(desirable)d(to)h(a)n(v)n(oid)e(using)h(an)n(y)g(c)n(haracter)f(with)i +(a)g(sp)r(ecial)f(meaning)h(in)g(LIKE)g(expressions)e(or)g(regular)g +(expressions;)118 2655 y(i.e.,)28 b(w)n(e)f(will)h(not)f(use)h(an)n(y)f +(of)g(the)h(sym)n(b)r(ols)70 b Fd(.)44 b(*)f(^)g(\\)g([)g(])g({)h(})f +(\()g(\))g(<)g(>)71 b Fh(?)37 b(|)28 b(&)f($)243 2755 +y(W)-7 b(e)28 b(prop)r(ose)e(to)h(reserv)n(e)f(also)g(/)i(as)f(a)g +(separator)e(\(see)i(\020V)-7 b(ariable)27 b(Sized)g(gID\021)34 +b(b)r(elo)n(w\).)243 2854 y(If)g(w)n(e)f(limit)i(ourselv)n(es)d(to)i +(ascii)f(c)n(haracters,)g(and)h(a)n(v)n(oid)e(to)i(b)r(e)g(safe)f(a)h +(lot)g(of)g(other)f(c)n(haracters,)g(w)n(e)g(can)h(use)118 +2954 y(n)n(um)n(b)r(ers)27 b(in)h(base)f(64)g(b)n(y)g(represen)n(ting) +243 3120 y Ff(\017)41 b Fh(0-9)26 b(with)i('0'-'9')f(\(dec)g(ascii)g +(co)r(de)h(48-57\))243 3286 y Ff(\017)41 b Fh(10)26 b(with)i(':')37 +b(\(dec)28 b(ascii)f(co)r(de)h(58\))243 3452 y Ff(\017)41 +b Fh(11)26 b(with)i(';')g(\(dec)g(ascii)f(co)r(de)g(59\))243 +3618 y Ff(\017)41 b Fh(12-37)25 b(with)j('A'-'Z')g(\(dec)f(ascii)g(co)r +(de)h(65-90\))243 3784 y Ff(\017)41 b Fh(38-63)25 b(with)j('a'-'z')f +(\(dec)h(ascii)f(co)r(de)g(97-122\))118 3950 y(By)g(using)g(base)f(64,) +h(up)g(to)h(4096)d(c)n(hildren)i(can)f(b)r(e)i(represen)n(ted)e(using)h +(t)n(w)n(o)f(suc)n(h)h(digits,)g(up)h(to)f(262144)d(with)k(three)118 +4050 y(digits,)g(and)f(up)h(to)f(16777216)d(with)k(four)f(digits.)243 +4149 y(If)37 b(the)g(RDBMs)g(supp)r(orts)f(in)n(ternational)g(c)n +(haracters,)h(it)g(is)g(p)r(ossible)f(to)h(further)f(increase)g(the)h +(base;)k(as)36 b(an)118 4249 y(example,)30 b(b)n(y)f(using)g(the)h(95)f +(additional)g(c)n(haracters)e(of)i(the)h(latin-1)f(c)n(haracter)e(set,) +k(w)n(e)e(could)g(co)r(de)g(n)n(um)n(b)r(ers)g(in)h(a)118 +4349 y(base)f(up)g(to)g(160)f(\025)g(remark)g(that)h(ev)n(ery)f(single) +h(digit)g(is)g(still)h(one)e(b)n(yte)h(in)h(this)f(represen)n(tation.) +40 b(This)29 b(means)f(that)118 4448 y(w)n(e)f(expand)h(the)f(sym)n(b)r +(ols)g(ab)r(o)n(v)n(e)f(b)n(y)i(represen)n(ting)243 4614 +y Ff(\017)41 b Fh(64-159)25 b(with)j(dec)f(latin1)g(co)r(de)h(160-255) +243 4780 y(In)23 b(base)g(160,)g(up)g(to)h(25600)d(c)n(hildren)i(can)f +(b)r(e)i(represen)n(ted)e(using)h(t)n(w)n(o)g(digits,)h(up)g(to)f +(4096000)d(with)k(three)f(digits,)118 4880 y(and)28 b(up)f(to)h +(6.5E+08)e(with)i(four)f(digits.)243 4980 y(Remark)g(that)h(base)f(con) +n(v)n(ersions)f(only)h(need)i(to)e(b)r(e)i(p)r(erformed)e(at)h +(insertion)g(time,)g(when)h(the)f(index)g(of)g(a)g(new)118 +5079 y(no)r(de)g(is)f(computed.)37 b(They)28 b(will)f(therefore)g(only) +g(ha)n(v)n(e)f(an)i(impact)f(on)h(insertion)f(timings.)1987 +5653 y(2)p eop +%%Page: 3 3 +3 2 bop 118 291 a Fm(2.3)112 b(Coun)m(ters:)50 b(\020delimited\021)44 +b(vs.)51 b(\020\034xed)38 b(size\021)118 444 y Fh(The)33 +b(standard)g(represen)n(tation)e(of)i(gID)h(uses)e(a)h(v)-5 +b(ariable)32 b(size)h(c)n(hild)h(iden)n(ti\034er,)g(and)f(delimiters)g +(to)h(separate)d(the)118 543 y(gID)f(of)g(the)h(c)n(hild)f(no)r(de)g +(from)f(the)i(gID)f(of)g(its)g(paren)n(t.)43 b(F)-7 b(or)30 +b(example,)g(w)n(e)g(can)f(represen)n(t)g(the)i(\034fth)g(c)n(hild)f +(of)g(no)r(de)118 643 y('/23/27/1')24 b(as)j('/23/27/1/4'.)32 +b(Let)c(us)f(call)g(this)h(a)f Fg(vgID)h Fh(represen)n(tation)e(\(V)-7 +b(ariable)27 b(Size)h(Genealogical)d(ID\).)243 743 y(This)30 +b(represen)n(tation)f(allo)n(ws)f(for)i(an)n(y)g(n)n(um)n(b)r(er)g(of)g +(c)n(hildren)g(of)h(a)f(no)r(de,)h(sub)5 b(ject)30 b(only)g(to)g(the)h +(limitations)f(the)118 842 y(RDBMS)e(ma)n(y)f(ha)n(v)n(e)f(as)h(to)h +(the)g(length)f(of)h(a)f(v)-5 b(ariable)27 b(sized)g(string.)243 +942 y(Alternativ)n(ely)-7 b(,)24 b(w)n(e)f(could)h(c)n(ho)r(ose)f(to)h +(limit)g(from)g(the)g(outset)g(the)g(quan)n(tit)n(y)g(of)f(c)n(hildren) +h(that)g(a)g(no)r(de)g(ma)n(y)f(ha)n(v)n(e;)118 1042 +y(this)28 b(limit)g(w)n(ould)f(dep)r(end)i(of)e(course)f(on)i(the)g +(application.)36 b(Let)27 b(us)h(call)f(this)h(a)f Fg(fgID)h +Fh(represen)n(tation.)243 1141 y(F)-7 b(or)25 b(example,)h(if)g(no)g +(no)r(de)f(is)h(allo)n(w)n(ed)f(to)g(ha)n(v)n(e)g(more)g(than)h(25600)d +(c)n(hildren,)j(w)n(e)g(could)f(represen)n(t)g(the)h(coun)n(ters)118 +1241 y(alw)n(a)n(ys)36 b(with)i(2)f(digits.)67 b(The)38 +b(no)r(de)f(whic)n(h)h(w)n(as)f(previously)f('/23/27/1/4')d(is)k(no)n +(w)g('23270104'.)64 b(If)38 b(w)n(e)f(require)118 1340 +y(a)g(three)g(digit)h(represen)n(tation)d(of)i(no)r(des)g(\(up)h(to)f +(ab)r(out)h(4)f(million)g(c)n(hildren\),)j(then)d(it)h(will)g(b)r(e)f +(represen)n(ted)f(as)118 1440 y('023027001004'.)118 1672 +y Fm(2.4)112 b(Ordering)37 b(of)h(no)s(des)118 1825 y +Fh(F)-7 b(or)35 b(some)g(applications)g(it)h(is)f(necessary)f(to)i +(obtain)f(subtrees)g(ordered)f(according)g(to)i(some)f(sp)r(ecial)g +(rules.)60 b(F)-7 b(or)118 1925 y(instance:)220 2090 +y(1.)41 b(the)34 b(complete)g(subtree)f(starting)g(at)h(a)f(no)r(de)h +(is)g(listed)g(immediately)g(after)f(the)i(no)r(de)f(in)g(question)f +(\(\020depth)326 2189 y(\034rst\021\))220 2354 y(2.)41 +b(no)r(des)27 b(with)h(a)f(common)g(paren)n(t)g(are)g(listed)g(c)n +(hronologically)243 2519 y(F)-7 b(or)39 b(instance,)k(the)d(displa)n(y) +f(of)h(an)f(organization)f(c)n(hart)h(is)g(usually)h(required)e(to)i +(satisfy)g(at)f(least)h(the)g(\034rst)118 2619 y(condition.)h(In)29 +b(a)g(threaded)f(discussion)h(group)e(one)i(wishes)g(to)f(satisfy)h(b)r +(oth)h(conditions)e(to)h(displa)n(y)f(the)h(messages)118 +2718 y(in)20 b(a)g(thread)g(\025)f(the)i(threads)e(themselv)n(es)h +(\(i.e.,)i(c)n(hildren)e(of)g(the)g(ro)r(ot)f(no)r(de\))i(are)e +(usually)g(listed)i(in)f(in)n(v)n(erse)f(c)n(hronolical)118 +2818 y(order.)243 2917 y(T)-7 b(o)35 b(mak)n(e)f(a)h(particular)f +(ordering)g(e\036cien)n(t,)j(it)f(w)n(ould)f(b)r(e)h(a)f(nice)g +(feature)g(if)h(it)g(could)f(b)r(e)h(made)f(to)g(coincide)118 +3017 y(with)28 b(a)f(lexicographic)f(ordering)f(of)j(the)g(indices)f +(\025i.e.,)g(as)g(pro)r(duced)g(b)n(y)h(an)f(\020ORDER)h(BY)f(id)h +(ASC\021)35 b(in)27 b(SQL.)h(The)118 3117 y(lexicographic)d(ordering)h +(of)h(fgID)h(satis\034es)e(b)r(oth)i(conditions.)36 b(The)27 +b(lexicographic)f(ordering)f(of)i(vgID)g(as)g(describ)r(ed)118 +3216 y(ab)r(o)n(v)n(e)34 b(satis\034es)g(the)h(\034rst)g(requisite)f +(if)i(the)f(separator)d(has)j(the)g(minimal)g(binary)g(represen)n +(tation)e(of)i(all)f(allo)n(w)n(ed)118 3316 y(sym)n(b)r(ols)c(in)h(an)f +(index)h(\025)f(this)h(is)g(wh)n(y)f(w)n(e)g(reserv)n(ed)f(/)h(for)g +(the)i(separator.)43 b(But)31 b(the)g(second)f(prop)r(ert)n(y)g(is)g +(missing:)118 3416 y(for)d(instance,)g(the)h(index)g('/1/10')d(is)j +(lexicographically)d(b)r(efore)i('/1/2'.)243 3515 y(If)c(the)h(second)e +(prop)r(ert)n(y)g(is)i(also)e(required)g(for)h(vgID,)g(w)n(e)f(can)h +(sp)r(ecify)h(the)f(c)n(hild)h(iden)n(ti\034ers)e(with)i(coun)n(ters)e +(built)118 3615 y(in)28 b(the)g(follo)n(wing)e(w)n(a)n(y:)36 +b(represen)n(t)26 b(a)h(n)n(um)n(b)r(er)h(b)n(y)f(a)g(string)g(of)g +(digits,)h(where)243 3779 y Ff(\017)41 b Fh(the)25 b(\034rst)g(digit)h +Fc(D)896 3791 y Fb(0)958 3779 y Fh(represen)n(ts)e(the)i(length)f(in)h +(digits)f(of)g(the)h(decimal)f(expansion)f(of)i(the)f(n)n(um)n(b)r(er,) +h(min)n(us)f(one)243 3945 y Ff(\017)41 b Fh(the)28 b(follo)n(wing)e +Fa(\()p Fc(D)920 3957 y Fb(0)976 3945 y Fa(+)18 b(1\))27 +b Fh(digits)h(are)e(the)i(decimal)g(expansion)e(of)i(the)g(n)n(um)n(b)r +(er)118 4109 y(Let)g(us)f(call)h(these)f(iden)n(ti\034ers)g +Fg(m-vgID)p Fh(,)g(\020m\021)34 b(for)27 b(mo)r(di\034ed.)243 +4209 y(As)e(an)f(example,)h(the)g(no)r(de)g(whic)n(h)g(w)n(as)f +(previously)f(represen)n(ted)h(b)n(y)g(/15/3/182)d(will,)k(after)g +(this)g(mo)r(di\034cation,)118 4309 y(ha)n(v)n(e)h(the)i(index)g +(/115/03/2182.)243 4408 y(The)37 b(lexicographic)f(ordering)g(of)i +(m-vgID)f(is)h(the)g(desired)f(ordering)f(of)h(the)h(tree)g(no)r(des.) +67 b(The)38 b(cost)f(of)g(this)118 4508 y(prop)r(ert)n(y)31 +b(is)i(that)f(\(a\))h(the)g(ID)f(are)g(no)n(w)g(longer,)g(\(b\))h(no)f +(no)r(de)g(can)g(ha)n(v)n(e)g(more)f(than)i Fa(160)3106 +4478 y Fb(160)3240 4508 y Fh(c)n(hildren)f(\(actually)-7 +b(,)118 4607 y(this)32 b(is)g(a)f(non-issue\),)h(and)f(\(c\))h(the)g +(index)g(structure)f(is)h(redundan)n(t,)g(some)f(formally)f(correct)h +(indices)g(are)g(in)n(v)-5 b(alid)118 4707 y(\025e.g.,)24 +b(/316/013/11.)30 b(The)24 b(third)g(issue)g(can)g(b)r(e)g(addressed)f +(b)n(y)g(k)n(eeping)g(a)h(strict)g(con)n(trol)e(on)i(the)g(generation)f +(of)h(new)118 4807 y(indices)k(to)f(insure)g(that)h(all)f(indices)h +(are)e(formally)h(correct.)243 4906 y(The)32 b(issue)f(of)h(the)g(rev)n +(erse)e(c)n(hronological)f(indexing)j(of)f(threads)h(in)g(threaded)f +(discussion)g(groups)g(can)g(b)r(e)h(ad-)118 5006 y(dressed)d(easily)f +(enough)h(in)h(fgID:)f(coun)n(t)g(\020do)n(wn\021)36 +b(instead)29 b(of)g(\020up\021)36 b(the)30 b(c)n(hildren)f(of)g(the)h +(ro)r(ot)e(no)r(de)i(\025)f(this)h(implies)118 5106 y(only)e(an)g +(inconsequen)n(tial)f(mo)r(di\034cation)h(of)g(the)g(no)r(de)h +(insertion)e(routine,)h(as)g(sho)n(wn)f(b)r(elo)n(w.)38 +b(The)29 b(problem)e(is)h(less)118 5205 y(trivial)i(with)g(vgID;)h(in)f +(this)h(case,)f(ma)n(yb)r(e)f(a)h(thread)g(iden)n(ti\034er)g(should)g +(b)r(e)h(k)n(ept)f(in)g(a)g(di\033eren)n(t)g(\034eld)h(-)f(i.e.,)h +(repre-)118 5305 y(sen)n(ting)h(the)h(structure)f(as)g(a)h(forest)f +(rather)f(than)i(a)f(tree,)i(where)e(the)h(thread_id)f(\034eld)h +(selects)f(the)h(\020tree\021)38 b(in)33 b(the)118 5404 +y(forest.)1987 5653 y(3)p eop +%%Page: 4 4 +4 3 bop 118 291 a Fi(3)131 b(T)-11 b(ree)45 b(op)t(erations)e(using)h +(genealogical)g(indices)118 472 y Fh(In)32 b(this)f(section)g(w)n(e)g +(sho)n(w)g(ho)n(w)g(to)g(implemen)n(t)h(v)-5 b(arious)30 +b(tree)h(op)r(erations)f(using)h(gID)g(as)g(the)h(primary)e(k)n(ey)h +(in)g(the)118 572 y(no)r(de)d(table.)243 672 y(Some)h(implemen)n +(tation)h(issues)g(are)f(relev)-5 b(an)n(t)29 b(here,)h(esp)r(ecially)f +(concerning)g(the)h(utilisation)g(of)g(indices)g(b)n(y)f(the)118 +771 y(DB)f(engine.)243 871 y(W)-7 b(e)28 b(discuss)f(a)g(tree)g +(represen)n(ted)f(in)i(a)f(table)h(of)f(the)h(form)326 +1034 y Fd(CREATE)41 b(TABLE)g(tree)h(\()456 1134 y(gid)304 +b(text)42 b(PRIMARY)f(KEY,)456 1234 y(nchildren)f(integer)h(DEFAULT)f +(0,)456 1333 y(\\ldots)h(the)i(actual)e(node)h(data)326 +1433 y(\);)118 1597 y Fh(The)26 b(\034eld)g(\020nc)n(hildren\021)32 +b(is)26 b(a)f(coun)n(ter)g(for)g(the)i(n)n(um)n(b)r(er)e(of)h(c)n +(hildren)f(that)h(the)h(no)r(de)f(has)f Fe(ever)35 b +Fh(had;)27 b(w)n(e)e(assume)g(here)118 1696 y(it)j(is)g(not)f(up)r +(dated)h(when)g(no)r(des)f(or)g(subtrees)g(are)f(deleted.)243 +1796 y(Section)h(4)g(pro)n(vides)f(a)i(complete)f(implemen)n(tation)h +(of)f(these)h(op)r(erations)e(for)h(fgID)h(in)g(P)n(ostgreSQL.)118 +2028 y Fm(3.1)112 b(Computing)37 b(the)g(lev)m(el)f(of)h(a)h(no)s(de) +118 2181 y Fg(Cost:)f Fe(string)30 b(op)l(er)l(ations)g(\(no)g(table)g +(ac)l(c)l(ess\))243 2280 y Fh(This)d(is)h(a)f(pure)g(string)g(op)r +(eration,)f(no)i(table)f(access)g(is)g(required.)243 +2460 y Ff(\017)41 b Fg(vgID:)27 b Fh(coun)n(t)h(the)g(n)n(um)n(b)r(er)f +(of)g(separators)e(\('/'\))j(in)g(the)g(PK)243 2625 y +Ff(\017)41 b Fg(fgID:)27 b Fh(coun)n(t)g(the)h(n)n(um)n(b)r(er)g(of)f +(c)n(haracters)e(in)j(the)g(PK,)g(divide)g(b)n(y)f(the)h(\034xed)f +(size)h(of)f(the)h(coun)n(ters.)118 2857 y Fm(3.2)112 +b(Selecting)36 b(or)h(deleting)f(a)i(subtree)118 3010 +y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +3173 y Ff(\017)41 b Fg(vgID:)27 b Fh(The)h(subtree)f(ro)r(oted)g(at)g +(/26/5/7)e(is)i(selected)g(b)n(y)508 3338 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('/26/5/7\045')d(AND)j(id)h(<)g('/26/5/70')243 +3503 y Ff(\017)e Fg(m-vgID:)26 b Fh(The)h(subtree)h(ro)r(oted)e(at)i +(/126/05/07)22 b(is)28 b(selected)f(b)n(y)508 3668 y +Fd(...)43 b(WHERE)e(id)i(LIKE)f('/126/06/07\045')243 +3833 y Ff(\017)f Fg(fgID:)27 b Fh(The)h(subtree)f(ro)r(oted)g(at)g +(260507)e(is)i(selected)h(b)n(y)508 3997 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('260507\045')118 4229 y Fm(3.3)112 +b(Selecting)36 b(the)h(direct)f(c)m(hildren)g(of)i(a)g(no)s(de)118 +4382 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +4562 y Ff(\017)41 b Fg(vgID:)27 b Fh(The)h(direct)f(c)n(hildren)g(of)h +(/26/5/7)c(are)j(selected)g(b)n(y)508 4727 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('/26/5/7/\045')d(AND)j(id)h(NOT)f(LIKE)g +('26/5/7/\045/\045')243 4892 y Ff(\017)f Fg(m-vgID:)26 +b Fh(The)h(direct)h(c)n(hildren)f(of)g(/26/5/7)e(are)h(selected)i(b)n +(y)508 5056 y Fd(...)43 b(WHERE)e(id)i(LIKE)f('/126/06/07/\045')37 +b(AND)43 b(id)f(NOT)h(LIKE)f('/126/05/07/\045/\045)o(')243 +5221 y Ff(\017)f Fg(fgID:)27 b Fh(The)h(direct)f(c)n(hildren)g(of)h +(260507)c(are)j(selected)g(b)n(y)508 5386 y Fd(...)43 +b(WHERE)e(id)i(LIKE)f('260507\045')d(AND)k(char_length\(id\))37 +b(=)43 b(\(char_length\('26)o(05)o(07')o(\)+)o(2\))1987 +5653 y Fh(4)p eop +%%Page: 5 5 +5 4 bop 118 291 a Fm(3.4)112 b(Inserting)37 b(a)h(no)s(de)g(or)f(a)h +(subtree)118 444 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l +(e)l(e)f(+)h(string)f(and)h(math)g(op)l(er)l(ations)243 +543 y Fh(Insertion)f(is)g(a)h(pro)r(cedural)e(op)r(eration.)42 +b(As)30 b(eac)n(h)f(RDBMS)h(has)f(a)h(di\033eren)n(t)f(w)n(a)n(y)g(of)g +(de\034ning)h(pro)r(cedures,)f(w)n(e)118 643 y(will)f(just)g(describ)r +(e)f(here)g(the)h(necessary)e(steps.)37 b(Examples)27 +b(for)g(P)n(ostgreSQL)f(are)h(pro)n(vided)f(in)i(4.)243 +743 y(In)22 b(order)f(to)h(insert)g(a)g(new)g(c)n(hild)h(of)f +(\020daddy\021)28 b(\(either)23 b(one)f(of)g(/26/5/7,)e(/126/05/07)d +(or)22 b(260507)d(in)k(the)f(examples)118 842 y(ab)r(o)n(v)n(e\))27 +b(y)n(ou)f(ha)n(v)n(e)h(to)220 1008 y(1.)41 b(add)27 +b(one)g(to)h(the)g(n)n(um)n(b)r(er)f(of)g(c)n(hildren)h(of)f +(\020daddy\021)508 1174 y Fd(UPDATE)41 b(tree)h(SET)h(nchildren)c(=)k +(\(nchildren)d(+)j(1\))g(WHERE)e(ID)i(=)g(``daddy'';)220 +1340 y Fh(2.)e(enco)r(de)27 b(the)h(n)n(um)n(b)r(er)f(of)g(c)n(hildren) +g(of)h(\020daddy\021)33 b(in)28 b(base)f(160,)f(bring)h(it)h(to)f(the)h +(correct)e(format)h(dep)r(ending)h(on)326 1440 y(the)c(v)-5 +b(arian)n(t)23 b(of)h(gID)g(\(pad)g(with)h(0)e(or)g(not,)i(prep)r(end)f +(a)g(digit)g(coun)n(ter)f(or)g(not,)i(prep)r(end)f(/)g(or)f(not,)i +(coun)n(t)e(do)n(wn)326 1540 y(or)j(up,)i(.)14 b(.)g(.)g(\))37 +b(and)28 b(app)r(end)f(it)h(to)g(daddy's)f(gID)g(to)h(obtain)f(the)h +(new)g(no)r(de's)f(gID.)220 1706 y(3.)41 b(insert)27 +b(the)h(new)f(no)r(de)243 1872 y(When)35 b(inserting)g(a)f(subtree,)j +(the)e(index)g(of)g(the)h(ro)r(ot)e(of)h(the)g(subtree)g(has)f(to)h(b)r +(e)h(computed)f(as)f(ab)r(o)n(v)n(e,)i(and)118 1971 y(prep)r(ended)28 +b(to)f(the)h(index)g(of)f(eac)n(h)g(no)r(de)h(of)f(the)h(subtree)f(b)r +(efore)h(insertion.)243 2071 y(Remark)e(that)i(only)f(the)h(paren)n(t)f +(no)r(de)h(has)f(to)g(b)r(e)h(up)r(dated)g(on)f(insertion.)118 +2303 y Fm(3.5)112 b(Selecting)36 b(the)h(ancestors)h(of)g(a)g(no)s(de) +118 2457 y Fg(Cost:)f Fe(index)30 b(sc)l(an)g(of)g(the)g(tr)l(e)l(e)243 +2556 y Fh(Y)-7 b(ou)27 b(can)g(sp)r(ecify)h(all)g(ancestors)d(of)j(a)f +(no)r(de)h(in)f(a)h(single)f(SQL)g(statemen)n(t;)g(for)g(instance)h +(for)f(vgID)326 2722 y Fd(...)42 b(WHERE)f('/25/6/7')f(LIKE)i(\(id)g +(||)h('/\045'\))f(AND)g(id)h(<)g('/25/6/7')118 2888 y +Fh(The)31 b(second)e(part)h(of)h(the)g(clause,)f(while)h(logically)e +(redundan)n(t,)h(is)h(a)f(\020hin)n(t\021)37 b(to)30 +b(the)h(optimizer.)45 b(A)n(t)31 b(least)f(in)g(P)n(ost-)118 +2988 y(greSQL,)c(without)i(it)g(the)g(optimizer)f(will)h(c)n(ho)r(ose)e +(a)i(sequen)n(tial)e(scan)h(of)h(the)g(table)f(and)h(disregard)d(the)j +(index.)118 3220 y Fm(3.6)112 b(Selecting)36 b(all)g(lea)m(v)m(es)118 +3374 y Fg(Cost:)h Fe(sc)l(an)30 b(of)g(the)g(tr)l(e)l(e)243 +3473 y Fh(A)e(leaf)f(is)g(a)h(no)r(de)f(without)h(descendan)n(ts:)36 +b(it)28 b(has)f(0)g(c)n(hildren.)37 b(Hence)326 3639 +y Fd(...)42 b(WHERE)f(nchildren)f(=)j(0)118 3805 y Fh(If)28 +b(this)g(t)n(yp)r(e)g(of)f(query)g(is)h(often)f(necessary)-7 +b(,)26 b(y)n(ou)h(ma)n(y)g(b)r(e)h(w)n(ell)f(advised)g(to)g(k)n(eep)g +(an)h(index)f(on)h(tree\(nc)n(hildren\).)118 4038 y Fm(3.7)112 +b(Determining)35 b(if)i(A)g(is)g(a)h(descendan)m(t)g(of)g(B)118 +4191 y Fg(Cost:)f Fe(string)30 b(op)l(er)l(ations,)h(no)f(table)g(ac)l +(c)l(ess)243 4291 y Fh(This)d(is)h(a)f(pure)g(string)g(op)r(eration)f +(on)i(the)g(indices,)f(no)g(table)h(access)e(is)i(necessary)-7 +b(.)118 4565 y Fi(4)131 b(Putting)45 b(it)f(all)h(together:)57 +b(a)44 b(P)l(ostgreSQL)f(implemen)l(tation)118 4747 y +Fh(h)n(ttp://www.p)r(ostgresql.org/mhonarc/pgsq)o(l-sql/)o(20)o(00)o +(-0)o(4/)o(msg0)o(02)o(67)o(.h)n(tml)243 4847 y(W)-7 +b(e)30 b(describ)r(e)g(here)g(a)g(small)f(pac)n(k)-5 +b(age)29 b(that)i(can)e(b)r(e)i(used)f(for)g(implemen)n(ting)g(gID)g +(on)g(P)n(ostgreSQL.)f(It)i(can)e(b)r(e)118 4946 y(found)f(at)f()243 5046 y(The)21 b(pac)n(k)-5 b(age)21 b(uses)g(the)h(pro) +r(cedural)e(language)h(PL/PGsql.)35 b(A)22 b(b)r(etter)g(implemen)n +(tation)g(w)n(ould)f(probably)g(de\034ne)118 5145 y(the)28 +b(gID)g(as)f(new)g(P)n(ostgres)f(t)n(yp)r(es,)i(and)f(co)r(de)g(all)h +(this)g(in)f(C.)243 5245 y(The)g(\034les)h(should)f(b)r(e)h(loaded)f +(in)h(alphab)r(etical)f(order.)1987 5653 y(5)p eop +%%Page: 6 6 +6 5 bop 118 291 a Fm(4.1)112 b(tree0_enco)s(ding.sql)118 +444 y Fh(This)28 b(\034le)f(de\034nes)h(and)f(p)r(opulates)h(the)f +(table)h(_b160_digits)d(of)j(\020digits\021)33 b(in)28 +b(base)f(160,)326 604 y Fd(CREATE)41 b(TABLE)g(\\_b160\\_digits)d +(\(deci)j(integer,)f(code)i(char\);)118 764 y Fh(and)28 +b(the)f(t)n(w)n(o)g(functions)326 924 y Fd(CREATE)41 +b(FUNCTION)f(\\_b160\\_encode\(i)o(nt)o(eg)o(er\))d(RETURNS)j(string) +413 1024 y(AS)j('....')e(LANGUAGE)f('plpgsql';)326 1124 +y(CREATE)h(FUNCTION)f(\\_b160\\_encode\(i)o(nt)o(eg)o(er,)o(in)o(te)o +(ger)o(\))d(RETURNS)k(string)413 1223 y(AS)i('....')e(LANGUAGE)f +('plpgsql';)118 1384 y Fh(The)22 b(\034rst)h(function)f(returns)g(a)g +(v)-5 b(ariable)21 b(size)h(enco)r(ding;)i(the)f(second)e(a)h(\034xed)h +(size)f(enco)r(ding)g(\(the)h(second)e(parameter)118 +1483 y(is)g(the)h(size\),)g(and)f(raises)e(an)i(exception)g(if)h(the)f +(n)n(um)n(b)r(er)g(is)g(to)r(o)g(large)e(to)i(b)r(e)h(represen)n(ted)e +(with)h(the)h(requested)e(n)n(um)n(b)r(er)118 1583 y(of)28 +b(digits.)118 1814 y Fm(4.2)112 b(tree1_de\034ne.sql)118 +1967 y Fh(This)28 b(\034le)f(pro)n(vides)f(a)i(function)326 +2127 y Fd(CREATE)41 b(FUNCTION)f(_tree_create\(tex)o(t,)o(in)o(teg)o +(er)o(,t)o(ext)o(,t)o(ex)o(t\))d(RETURNS)k(bpchar)413 +2227 y(AS)i('....')e(LANGUAGE)f('plpgsql';)118 2387 y +Fh(that)e(creates)f(a)h(tree)f(infrastructure)g(of)h(either)g(fgID)g +(or)f(vgID.)h(Assuming)f(y)n(ou)g(ha)n(v)n(e)g(a)h(table)f(\020m)n +(ytable\021)44 b(with)118 2487 y(primary)26 b(k)n(ey)h(\020m)n +(yid\021,)g(then)h(calling)326 2647 y Fd(SELECT)41 b(_tree_create\('m)o +(yt)o(ree)o(',)o(2,')o(my)o(ta)o(ble)o(',)o('m)o(yid)o('\))o(;)118 +2807 y Fh(will)28 b(cause:)220 2967 y(1.)41 b(the)28 +b(creation)e(of)i(a)f(table)508 3131 y Fd(CREATE)41 b(TABLE)h +(mytree_bkg\()683 3230 y(gid)g(text)g(PRIMARY)e(KEY,)683 +3330 y(nchildren)f(int,)683 3429 y(sid)j(integer)f(REFERENCES)e +(mytable\(myid\))508 3529 y(\);)508 3629 y(CREATE)i(UNIQUE)g(INDEX)h +(mytree_bkg_sid)37 b(ON)43 b(mytree_bkg\(sid\);)326 3792 +y Fh(for)27 b(the)h(tree)f(structure.)220 3955 y(2.)41 +b(the)28 b(creation)e(of)i(a)f(view)508 4118 y Fd(CREATE)41 +b(VIEW)h(mytree)f(AS)639 4218 y(SELECT)g(t.gid,n.*)900 +4317 y(FROM)h(mytable)f(n,)i(mytree_bkg)c(t)900 4417 +y(WHERE)j(t.sid=n.myid;)326 4580 y Fh(with:)35 b(a)23 +b(trigger)e(on)i(UPD)n(A)-7 b(TE)25 b(that)e(blo)r(c)n(ks)g(up)r +(dating)g(the)h(gid)f(and)g(allo)n(ws)f(up)r(dating)h(the)g(no)r(de)h +(data,)f(a)g(rule)326 4680 y(on)k(DELETE)i(that)f(deletes)f(the)h +(corresp)r(onding)e(en)n(try)h(b)r(oth)h(in)g(m)n(ytree_bkg)d(and)j(m)n +(ytable,)f(and)g(a)g(trigger)326 4779 y(ON)h(INSER)-7 +b(T)30 b(that)f(raises)e(an)h(exception)g(and)g(informs)h(the)f(user)g +(to)h(use)f(the)h(insertion)f(function)h(describ)r(ed)326 +4879 y(b)r(elo)n(w.)220 5042 y(3.)41 b(t)n(w)n(o)26 b(insertion)h +(functions)h(that)g(compute)g(automatically)e(the)i(gID)g(of)f(the)h +(new)g(no)r(de:)425 5205 y Ff(\017)41 b Fh(a)27 b(function)i(m)n +(ytree_insert\(text,text,in)n(teger,text\))d(for)h(insertion)g(sim)n +(ultaneosly)f(in)i(b)r(oth)g(tables:)508 5305 y(m)n +(ytree_insert\('2201','hello',0,'not)15 b(m)n(uc)n(h'\))j(inserts)g(a)g +(new)g(c)n(hild)h(of)f(2201)f(with)h(data1='hello',)h(data2=0)508 +5404 y(and)28 b(data3='not)e(m)n(uc)n(h')1987 5653 y(6)p +eop +%%Page: 7 7 +7 6 bop 425 291 a Ff(\017)41 b Fh(a)27 b(function)i(m)n +(ytree_insert_no)r(de\(text,in)n(teger\))c(for)i(insertion)g(in)h(m)n +(ytree_bkg)508 390 y(m)n(ytree_insert\('2201',25\))c(inserts)j(in)h(m)n +(ytree_bkg)e(a)h(new)h(c)n(hild)f(of)h(2201)d(with)j(sid=25)220 +556 y(4.)41 b(a)27 b(function)h(m)n(ytree_mo)n(v)n(e\(text,text\))e +(that)i(mo)n(v)n(es)e(subtrees:)326 656 y(m)n(ytree_mo)n(v)n +(e\('2201','23'\))d(mo)n(v)n(es)j(the)i(subtree)f(ro)r(oted)g(at)g +(2201)f(to)h(a)h(place)f(b)r(elo)n(w)g(23)f(\(ma)n(yb)r(e)i(2307\))220 +822 y(5.)41 b(a)c(function)g(m)n(ytree_len\(\))g(that)h(returns)e(the)i +(length)f(of)g(the)h(enco)r(dings)f(used)g(in)h(the)f(gID)g(\(2)h +(here;)j(0)c(if)326 922 y(v)-5 b(ariable)26 b(size\).)118 +1196 y Fi(5)131 b(Non-tree)44 b(hierarc)l(hies)118 1378 +y Fh(sequence)22 b(as)f(id,)j(table)e(with)h(\(id,g-index\))f(with)g(p) +r(ossibly)g(man)n(y)g(g-indices)f(for)h(eac)n(h)f(id)h(\(if)h(TOO)f +(man)n(y)-7 b(,)23 b(bad)f(mo)r(del:)118 1478 y(list)28 +b(all)f(genealogies,)f(i.e.,)h(paths)h(from)f(the)h(ro)r(ot\))118 +1752 y Fi(References)160 1934 y Fh([1])41 b(Philip)28 +b(Greenspun,)g Fe(T)-6 b(r)l(e)l(es)29 b(in)h(Or)l(acle)g(SQL)p +Fh(,)d(in)h Fg(SQL)k(for)g(W)-8 b(eb)31 b(Nerds)289 2033 +y Fh()160 2200 +y([2])41 b(Jo)r(e)27 b(Celk)n(o,)f Fe(SQL)j(for)i(Smarties)p +Fh(,)d(in)g Fg(DBMS)j(Online)p Fh(,)26 b(Marc)n(h)h(to)g(June)h(1996) +289 2299 y()289 +2399 y()289 +2498 y()289 +2598 y()160 +2764 y([3])41 b(Graeme)26 b(Birc)n(hall,)h Fg(DB2)32 +b(UDB)g(V6.1)f(SQL)h(Co)s(okb)s(o)s(ok)p Fh(,)289 2864 +y()1987 5653 +y(7)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF -- cgit From 30a5e1c1dc405f4cc69fd375bc1bbdfa18fc389f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 27 May 2005 11:54:29 +0000 Subject: r7011: when using macros, the parameters should be specified unless its a varargs function you are replacing. Otherwise if you have any structure element called "socket" and you have a macro for "socket" then the code will fail. (This used to be commit 9b33d0ca583b0cc1602662220cade96b70c98306) --- source4/lib/socket_wrapper/socket_wrapper.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.h b/source4/lib/socket_wrapper/socket_wrapper.h index 6da5a2980c..d8815a2575 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.h +++ b/source4/lib/socket_wrapper/socket_wrapper.h @@ -32,17 +32,17 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str int swrap_close(int); #ifdef SOCKET_WRAPPER_REPLACE -#define accept swrap_accept -#define connect swrap_connect -#define bind swrap_bind -#define getpeername swrap_getpeername -#define getsockname swrap_getsockname -#define getsockopt swrap_getsockopt -#define setsockopt swrap_setsockopt -#define recvfrom swrap_recvfrom -#define sendto swrap_sendto -#define socket swrap_socket -#define close swrap_close +#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen) +#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen) +#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen) +#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen) +#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen) +#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen) +#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen) +#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen) +#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen) +#define socket(domain,type,protocol) swrap_socket(domain,type,protocol) +#define close(s) swrap_close(s) #endif #endif /* __SOCKET_WRAPPER_H__ */ -- cgit From 9dc94f8ab86d80735e4c8999bde1e2dd4f42476d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 28 May 2005 08:47:01 +0000 Subject: r7052: added a case insensitive str_list_check_ci() version of str_list_check() (This used to be commit 5654330b6100a7291cee3631815cfb898100cf23) --- source4/lib/util_strlist.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 3b949f6eef..d5c4d91585 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -173,3 +173,16 @@ BOOL str_list_check(const char **list, const char *s) } return False; } + +/* + return True if a string is in a list, case insensitively +*/ +BOOL str_list_check_ci(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcasecmp(list[i], s) == 0) return True; + } + return False; +} -- cgit From 26ced62131962d92d45b8a383d3ecf4c9af56d02 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 28 May 2005 19:35:49 +0000 Subject: r7058: Add experimenthal pam authentication for web pages (This used to be commit 36d905407465cb9d8950da86322531e3c3102642) --- source4/lib/pam_errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/pam_errors.c b/source4/lib/pam_errors.c index 925441fb1d..a00464e624 100644 --- a/source4/lib/pam_errors.c +++ b/source4/lib/pam_errors.c @@ -20,7 +20,7 @@ #include "includes.h" -#ifdef WITH_PAM +#ifdef WITH_HAVE_SECURITY_PAM_APPL_H #include #if defined(PAM_AUTHTOK_RECOVERY_ERR) && !defined(PAM_AUTHTOK_RECOVER_ERR) -- cgit From 14ade23914b328fcb5924488c2416dfa7748e4ab Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 29 May 2005 03:53:36 +0000 Subject: r7065: Move ejs from web_server to lib so it can be shared with smbscript. (This used to be commit b83dc8fbfb9ffe30654bc4869398f50dd9ccccb7) --- source4/lib/ejs/config.h | 147 +++ source4/lib/ejs/config.mk | 13 + source4/lib/ejs/ejs.c | 1060 ++++++++++++++++++ source4/lib/ejs/ejs.h | 131 +++ source4/lib/ejs/ejsInternal.h | 292 +++++ source4/lib/ejs/ejsLex.c | 910 ++++++++++++++++ source4/lib/ejs/ejsParser.c | 2358 +++++++++++++++++++++++++++++++++++++++++ source4/lib/ejs/ejsProcs.c | 705 ++++++++++++ source4/lib/ejs/miniMpr.c | 505 +++++++++ source4/lib/ejs/miniMpr.h | 290 +++++ source4/lib/ejs/mprOs.h | 627 +++++++++++ source4/lib/ejs/var.c | 2161 +++++++++++++++++++++++++++++++++++++ source4/lib/ejs/var.h | 482 +++++++++ 13 files changed, 9681 insertions(+) create mode 100644 source4/lib/ejs/config.h create mode 100644 source4/lib/ejs/config.mk create mode 100644 source4/lib/ejs/ejs.c create mode 100644 source4/lib/ejs/ejs.h create mode 100644 source4/lib/ejs/ejsInternal.h create mode 100644 source4/lib/ejs/ejsLex.c create mode 100644 source4/lib/ejs/ejsParser.c create mode 100644 source4/lib/ejs/ejsProcs.c create mode 100644 source4/lib/ejs/miniMpr.c create mode 100644 source4/lib/ejs/miniMpr.h create mode 100644 source4/lib/ejs/mprOs.h create mode 100644 source4/lib/ejs/var.c create mode 100644 source4/lib/ejs/var.h (limited to 'source4/lib') diff --git a/source4/lib/ejs/config.h b/source4/lib/ejs/config.h new file mode 100644 index 0000000000..ec350890df --- /dev/null +++ b/source4/lib/ejs/config.h @@ -0,0 +1,147 @@ +// +// config.h -- Build configuration file. +// +// WARNING: DO NOT EDIT. This file is generated by configure. +// +// If you wish to modify the defaults, then edit conf/config.defaults.* and +// then run "configure --reset". +// +//////////////////////////////////////////////////////////////////////////////// + +#define BLD_PRODUCT "Samba4" +#define BLD_NAME "Samba4 SWAT" +#define BLD_VERSION "4" +#define BLD_NUMBER "1" +#define BLD_TYPE "DEBUG" +#define BLD_DEFAULTS "normal" +#define BLD_PACKAGES "" +#define BLD_APPWEB_CONFIG "normal.conf" +#define BLD_APPWEB 0 +#define BLD_COMPANY "Mbedthis" +#define BLD_DEBUG 1 +#define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" +#define BLD_HTTP_PORT 7777 +#define BLD_LIB_VERSION "1.0.0" +#define BLD_SSL_PORT 4443 +#define BLD_CLEAN_INSTALL "0" +#define BLD_LICENSE "gpl" +#define BLD_HOST_SYSTEM "i686-pc-linux-gnu" +#define BLD_BUILD_SYSTEM "i686-pc-linux-gnu" +#define BLD_HOST_OS "LINUX" +#define BLD_HOST_CPU_ARCH MPR_CPU_IX86 +#define BLD_HOST_CPU "i686" +#define BLD_HOST_UNIX 1 +#define BLD_BUILD_OS "LINUX" +#define BLD_BUILD_CPU_ARCH MPR_CPU_IX86 +#define BLD_BUILD_CPU i686 +#define BLD_BUILD_UNIX 1 +#define BLD_ROOT_PREFIX "/" +#define BLD_FEATURE_ACCESS_LOG 0 +#define BLD_FEATURE_ADMIN_MODULE 0 +#define BLD_FEATURE_ASPNET_MODULE 0 +#define BLD_FEATURE_ASSERT 1 +#define BLD_FEATURE_AUTH_MODULE 0 +#define BLD_FEATURE_C_API_MODULE 1 +#define BLD_FEATURE_C_API_CLIENT 0 +#define BLD_FEATURE_CGI_MODULE 0 +#define BLD_FEATURE_COMPAT_MODULE 0 +#define BLD_FEATURE_CONFIG_PARSE 0 +#define BLD_FEATURE_CONFIG_SAVE 0 +#define BLD_FEATURE_COOKIE 0 +#define BLD_FEATURE_COPY_MODULE 0 +#define BLD_FEATURE_DIGEST 0 +#define BLD_FEATURE_DLL 0 +#define BLD_FEATURE_EGI_MODULE 0 +#define BLD_FEATURE_EJS 1 +#define BLD_FEATURE_ESP_MODULE 1 +#define BLD_FEATURE_EVAL_PERIOD 30 +#define BLD_FEATURE_FLOATING_POINT 0 +#define BLD_FEATURE_IF_MODIFIED 0 +#define BLD_FEATURE_INT64 0 +#define BLD_FEATURE_KEEP_ALIVE 0 +#define BLD_FEATURE_LEGACY_API 0 +#define BLD_FEATURE_LIB_STDCPP 0 +#define BLD_FEATURE_LICENSE 0 +#define BLD_FEATURE_LOG 0 +#define BLD_FEATURE_MULTITHREAD 0 +#define BLD_FEATURE_MALLOC 0 +#define BLD_FEATURE_MALLOC_STATS 0 +#define BLD_FEATURE_MALLOC_LEAK 0 +#define BLD_FEATURE_MALLOC_HOOK 0 +#define BLD_FEATURE_NUM_TYPE int +#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT +#define BLD_FEATURE_ROMFS 0 +#define BLD_FEATURE_RUN_AS_SERVICE 0 +#define BLD_FEATURE_SAFE_STRINGS 0 +#define BLD_FEATURE_SAMPLES 0 +#define BLD_FEATURE_SESSION 1 +#define BLD_FEATURE_SHARED 0 +#define BLD_FEATURE_SQUEEZE 0 +#define BLD_FEATURE_SSL_MODULE 0 +#define BLD_FEATURE_STATIC 1 +#define BLD_FEATURE_STATIC_LINK_LIBC 0 +#define BLD_FEATURE_TEST 0 +#define BLD_FEATURE_UPLOAD_MODULE 0 +#define BLD_FEATURE_XDB_MODULE 0 +#define BLD_FEATURE_ADMIN_MODULE_BUILTIN 0 +#define BLD_FEATURE_ASPNET_MODULE_BUILTIN 0 +#define BLD_FEATURE_AUTH_MODULE_BUILTIN 0 +#define BLD_FEATURE_C_API_MODULE_BUILTIN 0 +#define BLD_FEATURE_CGI_MODULE_BUILTIN 0 +#define BLD_FEATURE_COMPAT_MODULE_BUILTIN 0 +#define BLD_FEATURE_COPY_MODULE_BUILTIN 0 +#define BLD_FEATURE_EGI_MODULE_BUILTIN 0 +#define BLD_FEATURE_ESP_MODULE_BUILTIN 0 +#define BLD_FEATURE_SSL_MODULE_BUILTIN 0 +#define BLD_FEATURE_UPLOAD_MODULE_BUILTIN 0 +#define BLD_FEATURE_XDB_MODULE_BUILTIN 0 +#define BLD_FEATURE_ADMIN_MODULE_LOADABLE 0 +#define BLD_FEATURE_ASPNET_MODULE_LOADABLE 0 +#define BLD_FEATURE_AUTH_MODULE_LOADABLE 0 +#define BLD_FEATURE_C_API_MODULE_LOADABLE 0 +#define BLD_FEATURE_CGI_MODULE_LOADABLE 0 +#define BLD_FEATURE_COMPAT_MODULE_LOADABLE 0 +#define BLD_FEATURE_COPY_MODULE_LOADABLE 0 +#define BLD_FEATURE_EGI_MODULE_LOADABLE 0 +#define BLD_FEATURE_ESP_MODULE_LOADABLE 0 +#define BLD_FEATURE_SSL_MODULE_LOADABLE 0 +#define BLD_FEATURE_UPLOAD_MODULE_LOADABLE 0 +#define BLD_FEATURE_XDB_MODULE_LOADABLE 0 +#define BLD_AR_FOR_BUILD "ar" +#define BLD_CC_FOR_BUILD "cc" +#define BLD_CSC_FOR_BUILD "" +#define BLD_JAVAC_FOR_BUILD "" +#define BLD_LD_FOR_BUILD "ld" +#define BLD_RANLIB_FOR_BUILD "" +#define BLD_NM_FOR_BUILD "nm" +#define BLD_CFLAGS_FOR_BUILD "" +#define BLD_IFLAGS_FOR_BUILD "" +#define BLD_LDFLAGS_FOR_BUILD "" +#define BLD_ARCHIVE_FOR_BUILD ".a" +#define BLD_EXE_FOR_BUILD "" +#define BLD_OBJ_FOR_BUILD ".o" +#define BLD_PIOBJ_FOR_BUILD ".lo" +#define BLD_CLASS_FOR_BUILD ".class" +#define BLD_SHLIB_FOR_BUILD "" +#define BLD_SHOBJ_FOR_BUILD ".so" +#define BLD_AR_FOR_HOST "ar" +#define BLD_CC_FOR_HOST "cc" +#define BLD_CSC_FOR_HOST "csc" +#define BLD_JAVAC_FOR_HOST "javac" +#define BLD_LD_FOR_HOST "ld" +#define BLD_RANLIB_FOR_HOST "true" +#define BLD_NM_FOR_HOST "nm" +#define BLD_CFLAGS_FOR_HOST "" +#define BLD_IFLAGS_FOR_HOST "" +#define BLD_LDFLAGS_FOR_HOST "" +#define BLD_ARCHIVE_FOR_HOST ".a" +#define BLD_EXE_FOR_HOST "" +#define BLD_OBJ_FOR_HOST ".o" +#define BLD_PIOBJ_FOR_HOST ".lo" +#define BLD_CLASS_FOR_HOST ".class" +#define BLD_SHLIB_FOR_HOST "" +#define BLD_SHOBJ_FOR_HOST ".so" +#define BLD_TOOLS_DIR "${BLD_TOP}/bin" +#define BLD_BIN_DIR "${BLD_TOP}/bin" +#define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" +#define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" diff --git a/source4/lib/ejs/config.mk b/source4/lib/ejs/config.mk new file mode 100644 index 0000000000..2d436cbe0b --- /dev/null +++ b/source4/lib/ejs/config.mk @@ -0,0 +1,13 @@ +####################### +# Start SUBSYSTEM EJS +[SUBSYSTEM::EJS] +ADD_OBJ_FILES = \ + lib/ejs/ejs.o \ + lib/ejs/ejsLex.o \ + lib/ejs/ejsParser.o \ + lib/ejs/ejsProcs.o \ + lib/ejs/miniMpr.o \ + lib/ejs/var.o +NOPROTO=YES +# End SUBSYSTEM EJS +####################### diff --git a/source4/lib/ejs/ejs.c b/source4/lib/ejs/ejs.c new file mode 100644 index 0000000000..41af795370 --- /dev/null +++ b/source4/lib/ejs/ejs.c @@ -0,0 +1,1060 @@ +/* + * @file ejs.c + * @brief Embedded JavaScript (EJS) + * @overview Main module interface logic. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "lib/ejs/ejsInternal.h" + +#if BLD_FEATURE_EJS + +/********************************** Local Data ********************************/ + +/* + * These fields must be locked before any access when multithreaded + */ +static MprVar master; /* Master object */ +static MprArray *ejsList; /* List of ej handles */ + +#if BLD_FEATURE_MULTITHREAD +static EjsLock lock; +static EjsUnlock unlock; +static void *lockData; +#define ejsLock() if (lock) { (lock)(lockData); } else +#define ejsUnlock() if (unlock) { (unlock)(lockData); } else +#else +#define ejsLock() +#define ejsUnlock() +#endif + +/****************************** Forward Declarations **************************/ + +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); + +/************************************* Code ***********************************/ +/* + * Initialize the EJ subsystem + */ + +int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) +{ + MprVar *np; + +#if BLD_FEATURE_MULTITHREAD + if (lockFn) { + lock = lockFn; + unlock = unlockFn; + lockData = data; + } +#endif + ejsLock(); + + /* + * Master is the top level object (above global). It is used to clone its + * contents into the global scope for each. This is never visible to the + * user, so don't use ejsCreateObj(). + */ + master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); + if (master.type == MPR_TYPE_UNDEFINED) { + ejsUnlock(); + return MPR_ERR_CANT_ALLOCATE; + } + + ejsList = mprCreateArray(); + ejsDefineStandardProperties(&master); + + /* + * Make these objects immutable + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprSetVarReadonly(np, 1); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + ejsUnlock(); + return 0; +} + +/******************************************************************************/ + +void ejsClose() +{ + ejsLock(); + mprDestroyArray(ejsList); + mprDestroyVar(&master); + ejsUnlock(); +} + +/******************************************************************************/ +/* + * Create and initialize an EJS engine + */ + +EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) +{ + MprVar *np; + Ejs *ep; + + ep = mprMalloc(sizeof(Ejs)); + if (ep == 0) { + return (EjsId) -1; + } + memset(ep, 0, sizeof(Ejs)); + + ejsLock(); + ep->eid = (EjsId) mprAddToArray(ejsList, ep); + ejsUnlock(); + + /* + * Create array of local variable frames + */ + ep->frames = mprCreateArray(); + if (ep->frames == 0) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + ep->primaryHandle = primaryHandle; + ep->altHandle = altHandle; + + /* + * Create first frame: global variables + */ + ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); + if (ep->global->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->global); + + /* + * Create first local variable frame + */ + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); + if (ep->local->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->local); + + /* + * Clone all master variables into the global frame. This does a + * reference copy. + * + * ejsDefineStandardProperties(ep->global); + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprCreateProperty(ep->global, np->name, np); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + + mprCreateProperty(ep->global, "global", ep->global); + mprCreateProperty(ep->global, "this", ep->global); + mprCreateProperty(ep->local, "local", ep->local); + + return ep->eid; +} + +/******************************************************************************/ +/* + * Close an EJS instance + */ + +void ejsCloseEngine(EjsId eid) +{ + Ejs *ep; + MprVar *vp; + void **handles; + int i; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + + mprFree(ep->error); + mprDestroyVar(&ep->result); + mprDestroyVar(&ep->tokenNumber); + + mprDeleteProperty(ep->local, "local"); + mprDeleteProperty(ep->global, "this"); + mprDeleteProperty(ep->global, "global"); + + handles = ep->frames->handles; + for (i = 0; i < ep->frames->max; i++) { + vp = handles[i]; + if (vp) { +#if BLD_DEBUG + if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { + mprLog(7, "ejsCloseEngine: %s has ref count %d\n", + vp->name, vp->properties->refCount); + } +#endif + mprDestroyVar(vp); + mprFree(vp); + mprRemoveFromArray(ep->frames, i); + } + } + mprDestroyArray(ep->frames); + + ejsLock(); + mprRemoveFromArray(ejsList, (int) ep->eid); + ejsUnlock(); + + mprFree(ep); +} + +/******************************************************************************/ +/* + * Evaluate an EJS script file + */ + +int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) +{ + struct stat sbuf; + Ejs *ep; + char *script; + int rc, fd; + + mprAssert(path && *path); + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + goto error; + } + + if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { + ejsError(ep, "Can't open %s\n", path); + goto error; + } + + if (stat(path, &sbuf) < 0) { + close(fd); + ejsError(ep, "Cant stat %s", path); + goto error; + } + + if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { + close(fd); + ejsError(ep, "Cant malloc %d", (int)sbuf.st_size); + goto error; + } + + if (read(fd, script, sbuf.st_size) != (int)sbuf.st_size) { + close(fd); + mprFree(script); + ejsError(ep, "Error reading %s", path); + goto error; + } + + script[sbuf.st_size] = '\0'; + close(fd); + + rc = ejsEvalBlock(eid, script, result, emsg); + mprFree(script); + + return rc; + +/* + * Error return + */ +error: + *emsg = mprStrdup(ep->error); + return -1; +} + +/******************************************************************************/ +/* + * Create a new variable scope block. This pushes the old local frame down + * the stack and creates a new local variables frame. + */ + +int ejsOpenBlock(EjsId eid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); + + mprCreateProperty(ep->local, "local", ep->local); + + return mprAddToArray(ep->frames, ep->local); +} + +/******************************************************************************/ +/* + * Close a variable scope block opened via ejsOpenBlock. Pop back the old + * local variables frame. + */ + +int ejsCloseBlock(EjsId eid, int fid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + /* + * Must remove self-references before destroying "local" + */ + mprDeleteProperty(ep->local, "local"); + + mprDestroyVar(ep->local); + mprFree(ep->local); + + mprRemoveFromArray(ep->frames, fid); + ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; + + return 0; +} + +/******************************************************************************/ +/* + * Create a new variable scope block and evaluate a script. All frames + * created during this context will be automatically deleted when complete. + * vp and emsg are optional. i.e. created local variables will be discarded + * when this routine returns. + */ + +int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + int rc, fid; + + mprAssert(script); + + fid = ejsOpenBlock(eid); + rc = ejsEvalScript(eid, script, vp, emsg); + ejsCloseBlock(eid, fid); + + return rc; +} + +/******************************************************************************/ +/* + * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" + * by EJ and the caller must not free it. Returns -1 on errors and zero + * for success. On errors, emsg will be set to the reason. The caller must + * free emsg. + */ + +int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + Ejs *ep; + EjsInput *oldBlock; + int state; + void *endlessLoopTest; + int loopCounter; + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + mprDestroyVar(&ep->result); + + if (script == 0) { + return 0; + } + + /* + * Allocate a new evaluation block, and save the old one + */ + oldBlock = ep->input; + ejsLexOpenScript(ep, script); + + /* + * Do the actual parsing and evaluation + */ + loopCounter = 0; + endlessLoopTest = NULL; + ep->exitStatus = 0; + + do { + state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); + + if (state == EJS_STATE_RET) { + state = EJS_STATE_EOF; + } + /* + * Stuck parser and endless recursion protection. + */ + if (endlessLoopTest == ep->input->scriptServp) { + if (loopCounter++ > 10) { + state = EJS_STATE_ERR; + ejsError(ep, "Syntax error"); + } + } else { + endlessLoopTest = ep->input->scriptServp; + loopCounter = 0; + } + } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); + + ejsLexCloseScript(ep); + + /* + * Return any error string to the user + */ + if (state == EJS_STATE_ERR && emsg) { + *emsg = mprStrdup(ep->error); + } + + /* + * Restore the old evaluation block + */ + ep->input = oldBlock; + + if (state == EJS_STATE_ERR) { + return -1; + } + + if (vp) { + *vp = ep->result; + } + + return ep->exitStatus; +} + +/******************************************************************************/ +/* + * Core error handling + */ + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) PRINTF_ATTRIBUTE(2, 0); + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) +{ + EjsInput *ip; + char *errbuf, *msgbuf; + + mprAssert(ep); + mprAssert(args); + + msgbuf = NULL; + mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); + + if (ep) { + ip = ep->input; + if (ip) { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, + "%s\nError on line %d. Offending line: %s\n\n", + msgbuf, ip->lineNumber, ip->line); + } else { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); + } + mprFree(ep->error); + ep->error = errbuf; + } + mprFree(msgbuf); +} + +/******************************************************************************/ +/* + * Internal use function to set the error message + */ + +void ejsError(Ejs* ep, const char* fmt, ...) +{ + va_list args; + + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Public routine to set the error message + */ + +void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) +{ + va_list args; + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Get the current line number + */ + +int ejsGetLineNumber(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + return ep->input->lineNumber; +} + +/******************************************************************************/ +/* + * Return the local object + */ + +MprVar *ejsGetLocalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->local; +} + +/******************************************************************************/ +/* + * Return the global object + */ + +MprVar *ejsGetGlobalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->global; +} + +/******************************************************************************/ +/* + * Copy the value of an object property. Return value is in "value". + * If deepCopy is true, copy all object/strings. Otherwise, object reference + * counts are incremented. Callers must always call mprDestroyVar on the + * return value to prevent leaks. + * + * Returns: -1 on errors or if the variable is not found. + */ + +int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprCopyProperty(value, vp, deepCopy); +} + +/******************************************************************************/ +/* + * Return the value of an object property. Return value is in "value". + * Objects and strings are not copied and reference counts are not modified. + * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the + * variable is not found. + */ + +int ejsReadVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprReadProperty(vp, value); +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { + return -1; + } + mprAssert(vp); + + /* + * Only copy the value. Don't overwrite the object's name + */ + mprWriteProperty(vp, value); + + return 0; +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) +{ + return ejsWriteVar(eid, var, &value); +} + +/******************************************************************************/ +/* + * Delete a variable + */ + +int ejsDeleteVar(EjsId eid, const char *var) +{ + Ejs *ep; + MprVar *vp; + MprVar *obj; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { + return -1; + } + mprDeleteProperty(obj, vp->name); + return 0; +} + +/******************************************************************************/ +/* + * Set the expression return value + */ + +void ejsSetReturnValue(EjsId eid, MprVar value) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Set the expression return value to a string value + */ + +void ejsSetReturnString(EjsId eid, const char *str) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Get the expression return value + */ + +MprVar *ejsGetReturnValue(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return &ep->result; +} + +/******************************************************************************/ +/* + * Define a C function. If eid < 0, then update the master object with this + * function. NOTE: in this case, functionName must be simple without any "." or + * "[]" elements. If eid >= 0, add to the specified script engine. In this + * case, functionName can be an arbitrary object reference and can contain "." + * or "[]". + */ + +void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, + void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a C function with String arguments + */ + +void ejsDefineStringCFunction(EjsId eid, const char *functionName, + MprStringCFunction fn, void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a JavaScript function. Args should be comma separated. + * Body should not contain braces. + */ + +void ejsDefineFunction(EjsId eid, const char *functionName, char *args, char *body) +{ + MprVar v; + + v = mprCreateFunctionVar(args, body, 0); + if (eid < 0) { + ejsLock(); + mprCreateProperty(&master, functionName, &v); + ejsUnlock(); + } else { + ejsWriteVar(eid, functionName, &v); + } + mprDestroyVar(&v); +} + +/******************************************************************************/ + +void *ejsGetThisPtr(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->thisPtr; +} + +/******************************************************************************/ +/* + * Find a variable given a variable name and return the parent object and + * the variable itself, the variable . This routine supports variable names + * that may be objects or arrays but may NOT have expressions in the array + * indicies. Returns -1 on errors or if the variable is not found. + */ + +int ejsGetVarCore(Ejs *ep, const char *varName_c, MprVar **obj, MprVar **varValue, + int flags) +{ + MprVar *currentObj; + MprVar *currentVar; + char tokBuf[EJS_MAX_ID]; + char *propertyName, *token, *next, *cp, *varName; + + if (obj) { + *obj = 0; + } + if (varValue) { + *varValue = 0; + } + currentObj = ejsFindObj(ep, 0, varName_c, flags); + currentVar = 0; + propertyName = 0; + + varName = mprStrdup(varName_c); + next = varName; + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + while (currentObj != 0 && token != 0 && *token) { + + if (*token == '[') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + propertyName = token; + if (*propertyName == '\"') { + propertyName++; + if ((cp = strchr(propertyName, '\"')) != 0) { + *cp = '\0'; + } + } else if (*propertyName == '\'') { + propertyName++; + if ((cp = strchr(propertyName, '\'')) != 0) { + *cp = '\0'; + } + } + + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (*token != ']') { + mprFree(varName); + return -1; + } + + } else if (*token == '.') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (!isalpha((int) token[0]) && + token[0] != '_' && token[0] != '$') { + mprFree(varName); + return -1; + } + + propertyName = token; + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + + } else { + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + } + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + } + mprFree(varName); + + if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { + currentVar = mprCreatePropertyValue(currentObj, propertyName, + mprCreateUndefinedVar()); + } + if (obj) { + *obj = currentObj; + } + + /* + * Don't use mprCopyVar as it will copy the data + */ + if (varValue) { + *varValue = currentVar; + } + return currentVar ? 0 : -1; +} + +/******************************************************************************/ +/* + * Get the next token as part of a variable specification. This will return + * a pointer to the next token and will return a pointer to the next token + * (after this one) in "next". The tokBuf holds the parsed token. + */ +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) +{ + char *start, *cp; + int len; + + start = *next; + while (isspace((int) *start) || *start == '\n' || *start == '\r') { + start++; + } + cp = start; + + if (*cp == '.' || *cp == '[' || *cp == ']') { + cp++; + } else { + while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && + !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { + cp++; + } + } + len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); + tokBuf[len] = '\0'; + + *next = cp; + return tokBuf; +} + +/******************************************************************************/ +/* + * Get the EJS structure pointer + */ + +Ejs *ejsPtr(EjsId eid) +{ + Ejs *handle; + int intId; + + intId = (int) eid; + + ejsLock(); + mprAssert(0 <= intId && intId < ejsList->max); + + if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { + mprAssert(0); + ejsUnlock(); + return NULL; + } + handle = ejsList->handles[intId]; + ejsUnlock(); + return handle; +} + +/******************************************************************************/ +/* + * Utility routine to crack JavaScript arguments. Return the number of args + * seen. This routine only supports %s and %d type args. + * + * Typical usage: + * + * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { + * mprError("Insufficient args\n"); + * return -1; + * } + */ + +int ejsParseArgs(int argc, char **argv, char *fmt, ...) +{ + va_list vargs; + bool *bp; + char *cp, **sp, *s; + int *ip, argn; + + va_start(vargs, fmt); + + if (argv == 0) { + return 0; + } + + for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { + if (*cp++ != '%') { + continue; + } + + s = argv[argn]; + switch (*cp) { + case 'b': + bp = va_arg(vargs, bool*); + if (bp) { + if (strcmp(s, "true") == 0 || s[0] == '1') { + *bp = 1; + } else { + *bp = 0; + } + } else { + *bp = 0; + } + break; + + case 'd': + ip = va_arg(vargs, int*); + *ip = atoi(s); + break; + + case 's': + sp = va_arg(vargs, char**); + *sp = s; + break; + + default: + mprAssert(0); + } + argn++; + } + + va_end(vargs); + return argn; +} + +/******************************************************************************/ + +#else +void ejsDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/******************************************************************************/ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejs.h b/source4/lib/ejs/ejs.h new file mode 100644 index 0000000000..79216d4712 --- /dev/null +++ b/source4/lib/ejs/ejs.h @@ -0,0 +1,131 @@ +/* + * @file ejs.h + * @brief Primary Embedded Javascript (ECMAScript) header. + * @overview This Embedded Javascript (EJS) header defines the + * public API. This API should only be used by those directly + * using EJS without using Embedded Server Pages (ESP). ESP + * wraps all relevant APIs to expose a single consistent API. + * \n\n + * This API requires the mpr/var.h facilities to create and + * manage objects and properties. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#ifndef _h_EJS +#define _h_EJS 1 + +#include "lib/ejs/miniMpr.h" +#include "lib/ejs/var.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/********************************* Prototypes *********************************/ + +typedef MprVarHandle EjsId; +typedef MprVarHandle EjsHandle; + +/* + * Multithreaded lock routines + */ +typedef void (*EjsLock)(void *lockData); +typedef void (*EjsUnlock)(void *lockData); + +/********************************* Prototypes *********************************/ +/* + * Module management + */ +extern int ejsOpen(EjsLock lock, EjsUnlock unlock, void *lockData); +extern void ejsClose(void); +extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); +extern void ejsCloseEngine(EjsId eid); + +/* + * Evaluation functions + */ +extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); +extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, + char **emsg); +extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, + MprArray *args); + +/* + * Composite variable get / set routines. Can also use the MPR property + * routines on an object variable. + */ +extern MprVar ejsCreateObj(const char *name, int hashSize); +extern MprVar ejsCreateArray(const char *name, int hashSize); +extern bool ejsDestroyVar(MprVar *obj); +extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool copyRef); +extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); +extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); +extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); +extern int ejsDeleteVar(EjsId eid, const char *var); + +extern MprVar *ejsGetLocalObject(EjsId eid); +extern MprVar *ejsGetGlobalObject(EjsId eid); + +/* + * Function routines + */ +extern void ejsDefineFunction(EjsId eid, const char *functionName, char *args, + char *body); +extern void ejsDefineCFunction(EjsId eid, const char *functionName, + MprCFunction fn, void *thisPtr, int flags); +extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, + MprStringCFunction fn, void *thisPtr, int flags); +extern void *ejsGetThisPtr(EjsId eid); +extern MprVar *ejsGetReturnValue(EjsId eid); +extern int ejsGetLineNumber(EjsId eid); +extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); +extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern void ejsSetReturnValue(EjsId eid, MprVar value); +extern void ejsSetReturnString(EjsId eid, const char *str); + +#ifdef __cplusplus +} +#endif +#endif /* _h_EJS */ + +/*****************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejsInternal.h b/source4/lib/ejs/ejsInternal.h new file mode 100644 index 0000000000..4d54c4e8c6 --- /dev/null +++ b/source4/lib/ejs/ejsInternal.h @@ -0,0 +1,292 @@ +/* + * @file ejsInternal.h + * @brief Private header for Embedded Javascript (ECMAScript) + * @overview This Embedded Javascript header defines the private Embedded + * Javascript internal structures. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************* Includes ***********************************/ + +#ifndef _h_EJS_INTERNAL +#define _h_EJS_INTERNAL 1 + +#include "lib/ejs/ejs.h" + +/********************************** Defines ***********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Constants + */ + +#if BLD_FEATURE_SQUEEZE + #define EJS_PARSE_INCR 256 /* Growth factor */ + #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ + #define EJS_MAX_ID 128 /* Maximum ID length */ + #define EJS_OBJ_HASH_SIZE 13 /* Object hash table size */ + #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ + #define EJS_LIST_INCR 8 /* Growth increment for lists */ +#else + #define EJS_PARSE_INCR 1024 /* Growth factor */ + #define EJS_MAX_RECURSE 100 /* Sanity for maximum recursion */ + #define EJS_MAX_ID 256 /* Maximum ID length */ + #define EJS_OBJ_HASH_SIZE 29 /* Object hash table size */ + #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ + #define EJS_LIST_INCR 16 /* Growth increment for lists */ +#endif +#define EJS_TOKEN_STACK 4 /* Put back token stack */ + +/* + * Lexical analyser tokens + */ +#define EJS_TOK_ERR -1 /* Any error */ +#define EJS_TOK_LPAREN 1 /* ( */ +#define EJS_TOK_RPAREN 2 /* ) */ +#define EJS_TOK_IF 3 /* if */ +#define EJS_TOK_ELSE 4 /* else */ +#define EJS_TOK_LBRACE 5 /* { */ +#define EJS_TOK_RBRACE 6 /* } */ +#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ +#define EJS_TOK_EXPR 8 /* +, -, /, % */ +#define EJS_TOK_SEMI 9 /* ; */ +#define EJS_TOK_LITERAL 10 /* literal string */ +#define EJS_TOK_FUNCTION_NAME 11 /* functionName */ +#define EJS_TOK_NEWLINE 12 /* newline white space */ +#define EJS_TOK_ID 13 /* Identifier */ +#define EJS_TOK_EOF 14 /* End of script */ +#define EJS_TOK_COMMA 15 /* Comma */ +#define EJS_TOK_VAR 16 /* var */ +#define EJS_TOK_ASSIGNMENT 17 /* = */ +#define EJS_TOK_FOR 18 /* for */ +#define EJS_TOK_INC_DEC 19 /* ++, -- */ +#define EJS_TOK_RETURN 20 /* return */ +#define EJS_TOK_PERIOD 21 /* . */ +#define EJS_TOK_LBRACKET 22 /* [ */ +#define EJS_TOK_RBRACKET 23 /* ] */ +#define EJS_TOK_NEW 24 /* new */ +#define EJS_TOK_DELETE 25 /* delete */ +#define EJS_TOK_IN 26 /* in */ +#define EJS_TOK_FUNCTION 27 /* function */ +#define EJS_TOK_NUMBER 28 /* Number */ + +/* + * Expression operators + */ +#define EJS_EXPR_LESS 1 /* < */ +#define EJS_EXPR_LESSEQ 2 /* <= */ +#define EJS_EXPR_GREATER 3 /* > */ +#define EJS_EXPR_GREATEREQ 4 /* >= */ +#define EJS_EXPR_EQ 5 /* == */ +#define EJS_EXPR_NOTEQ 6 /* != */ +#define EJS_EXPR_PLUS 7 /* + */ +#define EJS_EXPR_MINUS 8 /* - */ +#define EJS_EXPR_DIV 9 /* / */ +#define EJS_EXPR_MOD 10 /* % */ +#define EJS_EXPR_LSHIFT 11 /* << */ +#define EJS_EXPR_RSHIFT 12 /* >> */ +#define EJS_EXPR_MUL 13 /* * */ +#define EJS_EXPR_ASSIGNMENT 14 /* = */ +#define EJS_EXPR_INC 15 /* ++ */ +#define EJS_EXPR_DEC 16 /* -- */ +#define EJS_EXPR_BOOL_COMP 17 /* ! */ + +/* + * Conditional operators + */ +#define EJS_COND_AND 1 /* && */ +#define EJS_COND_OR 2 /* || */ +#define EJS_COND_NOT 3 /* ! */ + +/* + * States + */ +#define EJS_STATE_ERR -1 /* Error state */ +#define EJS_STATE_EOF 1 /* End of file */ +#define EJS_STATE_COND 2 /* Parsing a "(conditional)" stmt */ +#define EJS_STATE_COND_DONE 3 +#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ +#define EJS_STATE_RELEXP_DONE 5 +#define EJS_STATE_EXPR 6 /* Parsing an expression */ +#define EJS_STATE_EXPR_DONE 7 +#define EJS_STATE_STMT 8 /* Parsing General statement */ +#define EJS_STATE_STMT_DONE 9 +#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ +#define EJS_STATE_ARG_LIST 11 /* Function arg list */ +#define EJS_STATE_ARG_LIST_DONE 12 +#define EJS_STATE_DEC_LIST 16 /* Declaration list */ +#define EJS_STATE_DEC_LIST_DONE 17 +#define EJS_STATE_DEC 18 /* Declaration statement */ +#define EJS_STATE_DEC_DONE 19 +#define EJS_STATE_RET 20 /* Return statement */ + +#define EJS_STATE_BEGIN EJS_STATE_STMT + +/* + * General parsing flags. + */ +#define EJS_FLAGS_EXE 0x1 /* Execute statements */ +#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ +#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ +#define EJS_FLAGS_CREATE 0x8 /* Create var */ +#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ +#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ +#define EJS_FLAGS_FOREACH 0x40 /* In foreach */ +#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ +#define EJS_FLAGS_EXIT 0x100 /* Must exit */ + +/* + * Putback token + */ + +typedef struct EjsToken { + char *token; /* Token string */ + int id; /* Token ID */ +} EjsToken; + +/* + * EJ evaluation block structure + */ +typedef struct ejEval { + EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ + int putBackIndex; /* Top of stack index */ + MprStr line; /* Current line */ + int lineLength; /* Current line length */ + int lineNumber; /* Parse line number */ + int lineColumn; /* Column in line */ + MprStr script; /* Input script for parsing */ + char *scriptServp; /* Next token in the script */ + int scriptSize; /* Length of script */ + MprStr tokbuf; /* Current token */ + char *tokEndp; /* Pointer past end of token */ + char *tokServp; /* Pointer to next token char */ + int tokSize; /* Size of token buffer */ +} EjsInput; + +/* + * Function call structure + */ +typedef struct { + MprArray *args; /* Args for function */ + MprVar *fn; /* Function definition */ + char *procName; /* Function name */ +} EjsProc; + +/* + * Per EJS structure + */ +typedef struct ej { + EjsHandle altHandle; /* alternate callback handle */ + MprVar *currentObj; /* Ptr to current object */ + MprVar *currentProperty; /* Ptr to current property */ + EjsId eid; /* Halloc handle */ + char *error; /* Error message */ + int exitStatus; /* Status to exit() */ + int flags; /* Flags */ + MprArray *frames; /* List of variable frames */ + MprVar *global; /* Global object */ + EjsInput *input; /* Input evaluation block */ + MprVar *local; /* Local object */ + EjsHandle primaryHandle; /* primary callback handle */ + EjsProc *proc; /* Current function */ + MprVar result; /* Variable result */ + void *thisPtr; /* C++ ptr for functions */ + int tid; /* Current token id */ + char *token; /* Pointer to token string */ + MprVar tokenNumber; /* Parsed number */ +} Ejs; + +typedef int EjsBlock; /* Scope block id */ + +/* + * Function callback when using Alternate handles. + */ +typedef int (*EjsAltStringCFunction)(EjsHandle userHandle, EjsHandle altHandle, + int argc, char **argv); +typedef int (*EjsAltCFunction)(EjsHandle userHandle, EjsHandle altHandle, + int argc, MprVar **argv); + +/******************************** Prototypes **********************************/ +/* + * Ejs Lex + */ +extern int ejsLexOpenScript(Ejs* ep, char *script); +extern void ejsLexCloseScript(Ejs* ep); +extern int ejsInitInputState(EjsInput *ip); +extern void ejsLexSaveInputState(Ejs* ep, EjsInput* state); +extern void ejsLexFreeInputState(Ejs* ep, EjsInput* state); +extern void ejsLexRestoreInputState(Ejs* ep, EjsInput* state); +extern int ejsLexGetToken(Ejs* ep, int state); +extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); + +/* + * Parsing + */ +extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags); +extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, + char *property, int flags); +extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, + MprVar **varValue, int flags); +extern int ejsParse(Ejs *ep, int state, int flags); +extern Ejs *ejsPtr(EjsId eid); +extern void ejsSetExitStatus(int eid, int status); +extern void ejsSetFlags(int orFlags, int andFlags); + +/* + * Create variable scope blocks + */ +extern EjsBlock ejsOpenBlock(EjsId eid); +extern int ejsCloseBlock(EjsId eid, EjsBlock vid); +extern int ejsEvalBlock(EjsId eid, char *script, MprVar *v, char **err); +extern int ejsDefineStandardProperties(MprVar *objVar); + +/* + * Error handling + */ +extern void ejsError(Ejs *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +#ifdef __cplusplus +} +#endif +#endif /* _h_EJS_INTERNAL */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c new file mode 100644 index 0000000000..b0d6483c2a --- /dev/null +++ b/source4/lib/ejs/ejsLex.c @@ -0,0 +1,910 @@ +/* + * @file ejsLex.c + * @brief EJS Lexical Analyser + * @overview EJS lexical analyser. This implementes a lexical analyser + * for a subset of the JavaScript language. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "lib/ejs/ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ + +static int getLexicalToken(Ejs *ep, int state); +static int tokenAddChar(Ejs *ep, int c); +static int inputGetc(Ejs *ep); +static void inputPutback(Ejs *ep, int c); +static int charConvert(Ejs *ep, int base, int maxDig); + +/************************************* Code ***********************************/ +/* + * Open a new input script + */ + +int ejsLexOpenScript(Ejs *ep, char *script) +{ + EjsInput *ip; + + mprAssert(ep); + mprAssert(script); + + if ((ep->input = mprMalloc(sizeof(EjsInput))) == NULL) { + return -1; + } + ip = ep->input; + memset(ip, 0, sizeof(*ip)); + +/* + * Create the parse token buffer and script buffer + */ + ip->tokbuf = mprMalloc(EJS_PARSE_INCR); + ip->tokSize = EJS_PARSE_INCR; + ip->tokServp = ip->tokbuf; + ip->tokEndp = ip->tokbuf; + + ip->script = mprStrdup(script); + ip->scriptSize = strlen(script); + ip->scriptServp = ip->script; + + ip->lineNumber = 1; + ip->lineLength = 0; + ip->lineColumn = 0; + ip->line = NULL; + + ip->putBackIndex = -1; + + return 0; +} + +/******************************************************************************/ +/* + * Close the input script + */ + +void ejsLexCloseScript(Ejs *ep) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + + ip = ep->input; + mprAssert(ip); + + for (i = 0; i < EJS_TOKEN_STACK; i++) { + mprFree(ip->putBack[i].token); + ip->putBack[i].token = 0; + } + + mprFree(ip->line); + mprFree(ip->tokbuf); + mprFree(ip->script); + + mprFree(ip); +} + +/******************************************************************************/ +/* + * Initialize an input state structure + */ + +int ejsInitInputState(EjsInput *ip) +{ + mprAssert(ip); + + memset(ip, 0, sizeof(*ip)); + ip->putBackIndex = -1; + + return 0; +} +/******************************************************************************/ +/* + * Save the input state + */ + +void ejsLexSaveInputState(Ejs *ep, EjsInput *state) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + + ip = ep->input; + mprAssert(ip); + + *state = *ip; + + for (i = 0; i < ip->putBackIndex; i++) { + state->putBack[i].token = mprStrdup(ip->putBack[i].token); + state->putBack[i].id = ip->putBack[i].id; + } + for (; i < EJS_TOKEN_STACK; i++) { + state->putBack[i].token = 0; + } + + state->line = mprMalloc(ip->lineLength); + mprStrcpy(state->line, ip->lineLength, ip->line); + + state->lineColumn = ip->lineColumn; + state->lineNumber = ip->lineNumber; + state->lineLength = ip->lineLength; +} + +/******************************************************************************/ +/* + * Restore the input state + */ + +void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + mprAssert(state); + + ip = ep->input; + mprAssert(ip); + + ip->tokbuf = state->tokbuf; + ip->tokServp = state->tokServp; + ip->tokEndp = state->tokEndp; + ip->tokSize = state->tokSize; + + ip->script = state->script; + ip->scriptServp = state->scriptServp; + ip->scriptSize = state->scriptSize; + + ip->putBackIndex = state->putBackIndex; + for (i = 0; i < ip->putBackIndex; i++) { + mprFree(ip->putBack[i].token); + ip->putBack[i].id = state->putBack[i].id; + ip->putBack[i].token = mprStrdup(state->putBack[i].token); + } + + mprFree(ip->line); + ip->line = mprMalloc(state->lineLength); + mprStrcpy(ip->line, state->lineLength, state->line); + + ip->lineColumn = state->lineColumn; + ip->lineNumber = state->lineNumber; + ip->lineLength = state->lineLength; +} + +/******************************************************************************/ +/* + * Free a saved input state + */ + +void ejsLexFreeInputState(Ejs *ep, EjsInput *state) +{ + int i; + + mprAssert(ep); + mprAssert(state); + + for (i = 0; i < EJS_TOKEN_STACK; i++) { + mprFree(state->putBack[i].token); + } + state->putBackIndex = -1; + mprFree(state->line); + state->lineLength = 0; + state->lineColumn = 0; +} + +/******************************************************************************/ +/* + * Get the next EJS token + */ + +int ejsLexGetToken(Ejs *ep, int state) +{ + mprAssert(ep); + + ep->tid = getLexicalToken(ep, state); + return ep->tid; +} + +/******************************************************************************/ + +/* + * Check for reserved words "if", "else", "var", "for", "foreach", + * "delete", "function", and "return". "new", "in" and "function" + * done below. "true", "false", "null", "undefined" are handled + * as global objects. + * + * Other reserved words not supported: + * "break", "case", "catch", "continue", "default", "do", + * "finally", "instanceof", "switch", "this", "throw", "try", + * "typeof", "while", "with" + * + * ECMA extensions reserved words (not supported): + * "abstract", "boolean", "byte", "char", "class", "const", + * "debugger", "double", "enum", "export", "extends", + * "final", "float", "goto", "implements", "import", "int", + * "interface", "long", "native", "package", "private", + * "protected", "public", "short", "static", "super", + * "synchronized", "throws", "transient", "volatile" + */ + +static int checkReservedWord(Ejs *ep, int state, int c, int tid) +{ + if (state == EJS_STATE_STMT) { + if (strcmp(ep->token, "if") == 0) { + inputPutback(ep, c); + return EJS_TOK_IF; + } else if (strcmp(ep->token, "else") == 0) { + inputPutback(ep, c); + return EJS_TOK_ELSE; + } else if (strcmp(ep->token, "var") == 0) { + inputPutback(ep, c); + return EJS_TOK_VAR; + } else if (strcmp(ep->token, "for") == 0) { + inputPutback(ep, c); + return EJS_TOK_FOR; + } else if (strcmp(ep->token, "delete") == 0) { + inputPutback(ep, c); + return EJS_TOK_DELETE; + } else if (strcmp(ep->token, "function") == 0) { + inputPutback(ep, c); + return EJS_TOK_FUNCTION; + } else if (strcmp(ep->token, "return") == 0) { + if ((c == ';') || (c == '(')) { + inputPutback(ep, c); + } + return EJS_TOK_RETURN; + } + } else if (state == EJS_STATE_EXPR) { + if (strcmp(ep->token, "new") == 0) { + inputPutback(ep, c); + return EJS_TOK_NEW; + } else if (strcmp(ep->token, "in") == 0) { + inputPutback(ep, c); + return EJS_TOK_IN; + } else if (strcmp(ep->token, "function") == 0) { + inputPutback(ep, c); + return EJS_TOK_FUNCTION; + } + } + return tid; +} + +/******************************************************************************/ +/* + * Get the next EJS token + */ + +static int getLexicalToken(Ejs *ep, int state) +{ + MprType type; + EjsInput *ip; + int done, tid, c, quote, style, idx; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + ep->tid = -1; + tid = -1; + type = BLD_FEATURE_NUM_TYPE_ID; + + /* + * Use a putback tokens first. Don't free strings as caller needs access. + */ + if (ip->putBackIndex >= 0) { + idx = ip->putBackIndex; + tid = ip->putBack[idx].id; + ep->token = (char*) ip->putBack[idx].token; + tid = checkReservedWord(ep, state, 0, tid); + ip->putBackIndex--; + return tid; + } + ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; + *ip->tokServp = '\0'; + + if ((c = inputGetc(ep)) < 0) { + return EJS_TOK_EOF; + } + + /* + * Main lexical analyser + */ + for (done = 0; !done; ) { + switch (c) { + case -1: + return EJS_TOK_EOF; + + case ' ': + case '\t': + case '\r': + do { + if ((c = inputGetc(ep)) < 0) + break; + } while (c == ' ' || c == '\t' || c == '\r'); + break; + + case '\n': + return EJS_TOK_NEWLINE; + + case '(': + tokenAddChar(ep, c); + return EJS_TOK_LPAREN; + + case ')': + tokenAddChar(ep, c); + return EJS_TOK_RPAREN; + + case '[': + tokenAddChar(ep, c); + return EJS_TOK_LBRACKET; + + case ']': + tokenAddChar(ep, c); + return EJS_TOK_RBRACKET; + + case '.': + tokenAddChar(ep, c); + return EJS_TOK_PERIOD; + + case '{': + tokenAddChar(ep, c); + return EJS_TOK_LBRACE; + + case '}': + tokenAddChar(ep, c); + return EJS_TOK_RBRACE; + + case '+': + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '+' ) { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_PLUS); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_INC); + return EJS_TOK_INC_DEC; + + case '-': + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '-' ) { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_MINUS); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_DEC); + return EJS_TOK_INC_DEC; + + case '*': + tokenAddChar(ep, EJS_EXPR_MUL); + return EJS_TOK_EXPR; + + case '%': + tokenAddChar(ep, EJS_EXPR_MOD); + return EJS_TOK_EXPR; + + case '/': + /* + * Handle the division operator and comments + */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '*' && c != '/') { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_DIV); + return EJS_TOK_EXPR; + } + style = c; + /* + * Eat comments. Both C and C++ comment styles are supported. + */ + while (1) { + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '\n' && style == '/') { + break; + } else if (c == '*') { + c = inputGetc(ep); + if (style == '/') { + if (c == '\n') { + break; + } + } else { + if (c == '/') { + break; + } + } + } + } + /* + * Continue looking for a token, so get the next character + */ + if ((c = inputGetc(ep)) < 0) { + return EJS_TOK_EOF; + } + break; + + case '<': /* < and <= */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '<') { + tokenAddChar(ep, EJS_EXPR_LSHIFT); + return EJS_TOK_EXPR; + } else if (c == '=') { + tokenAddChar(ep, EJS_EXPR_LESSEQ); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_LESS); + inputPutback(ep, c); + return EJS_TOK_EXPR; + + case '>': /* > and >= */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '>') { + tokenAddChar(ep, EJS_EXPR_RSHIFT); + return EJS_TOK_EXPR; + } else if (c == '=') { + tokenAddChar(ep, EJS_EXPR_GREATEREQ); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_GREATER); + inputPutback(ep, c); + return EJS_TOK_EXPR; + + case '=': /* "==" */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '=') { + tokenAddChar(ep, EJS_EXPR_EQ); + return EJS_TOK_EXPR; + } + inputPutback(ep, c); + return EJS_TOK_ASSIGNMENT; + + case '!': /* "!=" or "!"*/ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '=') { + tokenAddChar(ep, EJS_EXPR_NOTEQ); + return EJS_TOK_EXPR; + } + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_BOOL_COMP); + return EJS_TOK_EXPR; + + case ';': + tokenAddChar(ep, c); + return EJS_TOK_SEMI; + + case ',': + tokenAddChar(ep, c); + return EJS_TOK_COMMA; + + case '|': /* "||" */ + if ((c = inputGetc(ep)) < 0 || c != '|') { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + tokenAddChar(ep, EJS_COND_OR); + return EJS_TOK_LOGICAL; + + case '&': /* "&&" */ + if ((c = inputGetc(ep)) < 0 || c != '&') { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + tokenAddChar(ep, EJS_COND_AND); + return EJS_TOK_LOGICAL; + + case '\"': /* String quote */ + case '\'': + quote = c; + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + + while (c != quote) { + /* + * Check for escape sequence characters + */ + if (c == '\\') { + c = inputGetc(ep); + + if (isdigit(c)) { + /* + * Octal support, \101 maps to 65 = 'A'. Put first + * char back so converter will work properly. + */ + inputPutback(ep, c); + c = charConvert(ep, 8, 3); + + } else { + switch (c) { + case 'n': + c = '\n'; break; + case 'b': + c = '\b'; break; + case 'f': + c = '\f'; break; + case 'r': + c = '\r'; break; + case 't': + c = '\t'; break; + case 'x': + /* + * Hex support, \x41 maps to 65 = 'A' + */ + c = charConvert(ep, 16, 2); + break; + case 'u': + /* + * Unicode support, \x0401 maps to 65 = 'A' + */ + c = charConvert(ep, 16, 2); + c = c*16 + charConvert(ep, 16, 2); + + break; + case '\'': + case '\"': + case '\\': + break; + default: + ejsError(ep, "Invalid Escape Sequence"); + return EJS_TOK_ERR; + } + } + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + } else { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + } + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Unmatched Quote"); + return EJS_TOK_ERR; + } + } + return EJS_TOK_LITERAL; + + case '0': + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + if (tolower(c) == 'x') { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + } + if (! isdigit(c)) { +#if BLD_FEATURE_FLOATING_POINT + if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { + /* Fall through */ + type = MPR_TYPE_FLOAT; + } else +#endif + { + mprDestroyVar(&ep->tokenNumber); + ep->tokenNumber = mprParseVar(ep->token, type); + inputPutback(ep, c); + return EJS_TOK_NUMBER; + } + } + /* Fall through to get more digits */ + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } +#if BLD_FEATURE_FLOATING_POINT + if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { + type = MPR_TYPE_FLOAT; + } + } while (isdigit(c) || c == '.' || tolower(c) == 'e' || + c == '+' || c == '-'); +#else + } while (isdigit(c)); +#endif + + mprDestroyVar(&ep->tokenNumber); + ep->tokenNumber = mprParseVar(ep->token, type); + inputPutback(ep, c); + return EJS_TOK_NUMBER; + + default: + /* + * Identifiers or a function names + */ + while (1) { + if (c == '\\') { + if ((c = inputGetc(ep)) < 0) { + break; + } + if (c == '\n' || c == '\r') { + break; + } + } else if (tokenAddChar(ep, c) < 0) { + break; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + if (!isalnum(c) && c != '$' && c != '_' && c != '\\') { + break; + } + } + if (*ep->token == '\0') { + c = inputGetc(ep); + break; + } + if (! isalpha((int) *ep->token) && *ep->token != '$' && + *ep->token != '_') { + ejsError(ep, "Invalid identifier %s", ep->token); + return EJS_TOK_ERR; + } + + tid = checkReservedWord(ep, state, c, EJS_TOK_ID); + if (tid != EJS_TOK_ID) { + return tid; + } + + /* + * Skip white space after token to find out whether this is + * a function or not. + */ + while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { + if ((c = inputGetc(ep)) < 0) + break; + } + + tid = EJS_TOK_ID; + done++; + } + } + + /* + * Putback the last extra character for next time + */ + inputPutback(ep, c); + return tid; +} + +/******************************************************************************/ +/* + * Convert a hex or octal character back to binary, return original char if + * not a hex digit + */ + +static int charConvert(Ejs *ep, int base, int maxDig) +{ + int i, c, lval, convChar; + + lval = 0; + for (i = 0; i < maxDig; i++) { + if ((c = inputGetc(ep)) < 0) { + break; + } + /* + * Initialize to out of range value + */ + convChar = base; + if (isdigit(c)) { + convChar = c - '0'; + } else if (c >= 'a' && c <= 'f') { + convChar = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + convChar = c - 'A' + 10; + } + /* + * If unexpected character then return it to buffer. + */ + if (convChar >= base) { + inputPutback(ep, c); + break; + } + lval = (lval * base) + convChar; + } + return lval; +} + +/******************************************************************************/ +/* + * Putback the last token read. Accept at most one push back token. + */ + +void ejsLexPutbackToken(Ejs *ep, int tid, char *string) +{ + EjsInput *ip; + int idx; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + ip->putBackIndex += 1; + idx = ip->putBackIndex; + ip->putBack[idx].id = tid; + + if (ip->putBack[idx].token) { + if (ip->putBack[idx].token == string) { + return; + } + mprFree(ip->putBack[idx].token); + } + ip->putBack[idx].token = mprStrdup(string); +} + +/******************************************************************************/ +/* + * Add a character to the token buffer + */ + +static int tokenAddChar(Ejs *ep, int c) +{ + EjsInput *ip; + uchar *oldbuf; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + if (ip->tokEndp >= &ip->tokbuf[ip->tokSize - 1]) { + ip->tokSize += EJS_PARSE_INCR; + oldbuf = ip->tokbuf; + ip->tokbuf = mprRealloc(ip->tokbuf, ip->tokSize); + if (ip->tokbuf == 0) { + ejsError(ep, "Token too big"); + return -1; + } + ip->tokEndp += (int) ((uchar*) ip->tokbuf - oldbuf); + ip->tokServp += (int) ((uchar*) ip->tokbuf - oldbuf); + ep->token += (int) ((uchar*) ip->tokbuf - oldbuf); + } + *ip->tokEndp++ = c; + *ip->tokEndp = '\0'; + + return 0; +} + +/******************************************************************************/ +/* + * Get another input character + */ + +static int inputGetc(Ejs *ep) +{ + EjsInput *ip; + int c; + + mprAssert(ep); + ip = ep->input; + + if (ip->scriptSize <= 0) { + return -1; + } + + c = (uchar) (*ip->scriptServp++); + ip->scriptSize--; + + /* + * For debugging, accumulate the line number and the currenly parsed line + */ + if (c == '\n') { +#if BLD_DEBUG && 0 + if (ip->lineColumn > 0) { + printf("PARSED: %s\n", ip->line); + } +#endif + ip->lineNumber++; + ip->lineColumn = 0; + } else { + if ((ip->lineColumn + 2) >= ip->lineLength) { + ip->lineLength += 80; + ip->line = mprRealloc(ip->line, ip->lineLength * sizeof(char)); + } + ip->line[ip->lineColumn++] = c; + ip->line[ip->lineColumn] = '\0'; + } + return c; +} + +/******************************************************************************/ +/* + * Putback a character onto the input queue + */ + +static void inputPutback(Ejs *ep, int c) +{ + EjsInput *ip; + + mprAssert(ep); + + if (c != 0) { + ip = ep->input; + *--ip->scriptServp = c; + ip->scriptSize++; + ip->lineColumn--; + ip->line[ip->lineColumn] = '\0'; + } +} + +/******************************************************************************/ + +#else +void ejsLexDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c new file mode 100644 index 0000000000..f9335ec004 --- /dev/null +++ b/source4/lib/ejs/ejsParser.c @@ -0,0 +1,2358 @@ +/* + * @file ejsParser.c + * @brief EJS Parser and Execution + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/********************************** Includes **********************************/ + +#include "lib/ejs/ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ + +static void appendValue(MprVar *v1, MprVar *v2); +static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +#if BLD_FEATURE_FLOATING_POINT +static int evalFloatExpr(Ejs *ep, double l, int rel, double r); +#endif +static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); +static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); +static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +static int evalFunction(Ejs *ep, MprVar *obj, int flags); +static void freeProc(EjsProc *proc); +static int parseArgs(Ejs *ep, int state, int flags); +static int parseAssignment(Ejs *ep, int state, int flags, char *id, + char *fullName); +static int parseCond(Ejs *ep, int state, int flags); +static int parseDeclaration(Ejs *ep, int state, int flags); +static int parseExpr(Ejs *ep, int state, int flags); +static int parseFor(Ejs *ep, int state, int flags); +static int parseForIn(Ejs *ep, int state, int flags); +static int parseFunctionDec(Ejs *ep, int state, int flags); +static int parseFunction(Ejs *ep, int state, int flags, char *id); +static int parseId(Ejs *ep, int state, int flags, char **id, + char **fullName, int *fullNameLen, int *done); +static int parseInc(Ejs *ep, int state, int flags); +static int parseIf(Ejs *ep, int state, int flags, int *done); +static int parseStmt(Ejs *ep, int state, int flags); +static void removeNewlines(Ejs *ep, int state); +static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); + +/************************************* Code ***********************************/ +/* + * Recursive descent parser for EJS + */ + +int ejsParse(Ejs *ep, int state, int flags) +{ + mprAssert(ep); + + switch (state) { + /* + * Any statement, function arguments or conditional expressions + */ + case EJS_STATE_STMT: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_STMT_DONE && + state != EJS_STATE_EOF && state != EJS_STATE_STMT_BLOCK_DONE && + state != EJS_STATE_RET) { + state = EJS_STATE_ERR; + } + break; + + case EJS_STATE_DEC: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_DEC_DONE && + state != EJS_STATE_EOF) { + state = EJS_STATE_ERR; + } + break; + + case EJS_STATE_EXPR: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_EXPR_DONE && + state != EJS_STATE_EOF) { + state = EJS_STATE_ERR; + } + break; + + /* + * Variable declaration list + */ + case EJS_STATE_DEC_LIST: + state = parseDeclaration(ep, state, flags); + break; + + /* + * Function argument string + */ + case EJS_STATE_ARG_LIST: + state = parseArgs(ep, state, flags); + break; + + /* + * Logical condition list (relational operations separated by &&, ||) + */ + case EJS_STATE_COND: + state = parseCond(ep, state, flags); + break; + + /* + * Expression list + */ + case EJS_STATE_RELEXP: + state = parseExpr(ep, state, flags); + break; + } + + if (state == EJS_STATE_ERR && ep->error == NULL) { + ejsError(ep, "Syntax error"); + } + return state; +} + +/******************************************************************************/ +/* + * Parse any statement including functions and simple relational operations + */ + +static int parseStmt(Ejs *ep, int state, int flags) +{ + EjsProc *saveProc; + MprVar *vp, *saveObj; + char *id, *fullName, *initToken; + int done, expectSemi, tid, fullNameLen, rel; + int initId; + + mprAssert(ep); + + expectSemi = 0; + saveProc = NULL; + id = 0; + fullName = 0; + fullNameLen = 0; + + ep->currentObj = 0; + ep->currentProperty = 0; + + for (done = 0; !done && state != EJS_STATE_ERR; ) { + tid = ejsLexGetToken(ep, state); + + switch (tid) { + default: + ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); + done++; + break; + + case EJS_TOK_EXPR: + rel = (int) *ep->token; + if (state == EJS_STATE_EXPR) { + ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); + } + done++; + break; + + case EJS_TOK_LOGICAL: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_ERR: + state = EJS_STATE_ERR; + done++; + break; + + case EJS_TOK_EOF: + state = EJS_STATE_EOF; + done++; + break; + + case EJS_TOK_NEWLINE: + break; + + case EJS_TOK_SEMI: + /* + * This case is when we discover no statement and just a lone ';' + */ + if (state != EJS_STATE_STMT) { + ejsLexPutbackToken(ep, tid, ep->token); + } + done++; + break; + + case EJS_TOK_PERIOD: + if (flags & EJS_FLAGS_EXE) { + if (ep->currentProperty == 0) { + ejsError(ep, "Undefined object \"%s\"\n", id); + goto error; + } + } + ep->currentObj = ep->currentProperty; + + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { + ejsError(ep, "Bad property after '.': %s\n", ep->token); + goto error; + } + mprFree(id); + id = mprStrdup(ep->token); + + vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); + updateResult(ep, state, flags, vp); + +#if BLD_DEBUG + fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, + 0, ".", 0); +#endif + + ep->currentProperty = vp; + ejsLexPutbackToken(ep, tid, ep->token); + break; + + case EJS_TOK_LBRACKET: + ep->currentObj = ep->currentProperty; + saveObj = ep->currentObj; + if (ejsParse(ep, EJS_STATE_RELEXP, flags) != EJS_STATE_RELEXP_DONE){ + goto error; + } + ep->currentObj = saveObj; + + mprFree(id); + mprVarToString(&id, MPR_MAX_STRING, 0, &ep->result); + + if (id[0] == '\0') { + if (flags & EJS_FLAGS_EXE) { + ejsError(ep, + "[] expression evaluates to the empty string\n"); + goto error; + } + } else { + vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); + ep->currentProperty = vp; + updateResult(ep, state, flags, vp); + } + +#if BLD_DEBUG + if (id[0] && strlen(id) < (MPR_MAX_VAR / 2)) { + /* + * If not executing yet, id may not be known + */ + fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, + fullNameLen, 0, "[", id, "]", 0); + } +#endif + + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { + ejsError(ep, "Missing ']'\n"); + goto error; + } + break; + + case EJS_TOK_ID: + state = parseId(ep, state, flags, &id, &fullName, &fullNameLen, + &done); + if (done && state == EJS_STATE_STMT) { + expectSemi++; + } + break; + + case EJS_TOK_ASSIGNMENT: + state = parseAssignment(ep, state, flags, id, fullName); + if (state == EJS_STATE_STMT) { + expectSemi++; + done++; + } + break; + + case EJS_TOK_INC_DEC: + state = parseInc(ep, state, flags); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + break; + + case EJS_TOK_NEW: + if (ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW) + != EJS_STATE_EXPR_DONE) { + goto error; + } + break; + + case EJS_TOK_DELETE: + if (ejsParse(ep, EJS_STATE_EXPR, + flags | EJS_FLAGS_DELETE) != EJS_STATE_EXPR_DONE) { + goto error; + } + mprDeleteProperty(ep->currentObj, ep->currentProperty->name); + done++; + break; + + case EJS_TOK_FUNCTION: + state = parseFunctionDec(ep, state, flags); + done++; + break; + + case EJS_TOK_LITERAL: + /* + * Set the result to the string literal + */ + mprCopyVarValue(&ep->result, mprCreateStringVar(ep->token, 0), + MPR_SHALLOW_COPY); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + done++; + break; + + case EJS_TOK_NUMBER: + /* + * Set the result to the parsed number + */ + mprCopyVar(&ep->result, &ep->tokenNumber, 0); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + done++; + break; + + case EJS_TOK_FUNCTION_NAME: + state = parseFunction(ep, state, flags, id); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + if (ep->flags & EJS_FLAGS_EXIT) { + state = EJS_STATE_RET; + } + done++; + break; + + case EJS_TOK_IF: + state = parseIf(ep, state, flags, &done); + if (state == EJS_STATE_RET) { + goto doneParse; + } + break; + + case EJS_TOK_FOR: + if (state != EJS_STATE_STMT) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { + goto error; + } + /* + * Need to peek 2-3 tokens ahead and see if this is a + * for ([var] x in set) + * or + * for (init ; whileCond; incr) + */ + initId = ejsLexGetToken(ep, EJS_STATE_EXPR); + if (initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { + /* Simply eat var tokens */ + initId = ejsLexGetToken(ep, EJS_STATE_EXPR); + } + initToken = mprStrdup(ep->token); + + tid = ejsLexGetToken(ep, EJS_STATE_EXPR); + + ejsLexPutbackToken(ep, tid, ep->token); + ejsLexPutbackToken(ep, initId, initToken); + mprFree(initToken); + + if (tid == EJS_TOK_IN) { + if ((state = parseForIn(ep, state, flags)) < 0) { + goto error; + } + } else { + if ((state = parseFor(ep, state, flags)) < 0) { + goto error; + } + } + done++; + break; + + case EJS_TOK_VAR: + if (ejsParse(ep, EJS_STATE_DEC_LIST, flags) + != EJS_STATE_DEC_LIST_DONE) { + goto error; + } + done++; + break; + + case EJS_TOK_COMMA: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_LPAREN: + if (state == EJS_STATE_EXPR) { + if (ejsParse(ep, EJS_STATE_RELEXP, flags) + != EJS_STATE_RELEXP_DONE) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + goto error; + } + } + done++; + break; + + case EJS_TOK_RPAREN: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_LBRACE: + /* + * This handles any code in braces except "if () {} else {}" + */ + if (state != EJS_STATE_STMT) { + goto error; + } + + /* + * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE + * is seen. + */ + do { + state = ejsParse(ep, EJS_STATE_STMT, flags); + } while (state == EJS_STATE_STMT_DONE); + + if (state != EJS_STATE_RET) { + if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { + goto error; + } + state = EJS_STATE_STMT_DONE; + } + done++; + break; + + case EJS_TOK_RBRACE: + if (state == EJS_STATE_STMT) { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_STMT_BLOCK_DONE; + done++; + break; + } + goto error; + + case EJS_TOK_RETURN: + if (ejsParse(ep, EJS_STATE_RELEXP, flags) + != EJS_STATE_RELEXP_DONE) { + goto error; + } + if (flags & EJS_FLAGS_EXE) { + while (ejsLexGetToken(ep, state) != EJS_TOK_EOF) { + ; + } + state = EJS_STATE_RET; + done++; + } + break; + } + } + + if (expectSemi) { + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_SEMI && tid != EJS_TOK_NEWLINE && + tid != EJS_TOK_EOF) { + goto error; + } + + /* + * Skip newline after semi-colon + */ + removeNewlines(ep, state); + } + +/* + * Free resources and return the correct status + */ +doneParse: + mprFree(id); + mprFree(fullName); + + /* + * Advance the state + */ + switch (state) { + case EJS_STATE_STMT: + return EJS_STATE_STMT_DONE; + + case EJS_STATE_DEC: + return EJS_STATE_DEC_DONE; + + case EJS_STATE_EXPR: + return EJS_STATE_EXPR_DONE; + + case EJS_STATE_STMT_DONE: + case EJS_STATE_STMT_BLOCK_DONE: + case EJS_STATE_EOF: + case EJS_STATE_RET: + return state; + + default: + return EJS_STATE_ERR; + } + +/* + * Common error exit + */ +error: + state = EJS_STATE_ERR; + goto doneParse; +} + +/******************************************************************************/ +/* + * Parse function arguments + */ + +static int parseArgs(Ejs *ep, int state, int flags) +{ + int tid; + + mprAssert(ep); + + do { + /* + * Peek and see if there are no args + */ + tid = ejsLexGetToken(ep, state); + ejsLexPutbackToken(ep, tid, ep->token); + if (tid == EJS_TOK_RPAREN) { + break; + } + + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state == EJS_STATE_EOF || state == EJS_STATE_ERR) { + return state; + } + if (state == EJS_STATE_RELEXP_DONE) { + if (flags & EJS_FLAGS_EXE) { + mprAssert(ep->proc->args); + mprAddToArray(ep->proc->args, + mprDupVar(&ep->result, MPR_SHALLOW_COPY)); + } + } + /* + * Peek at the next token, continue if more args (ie. comma seen) + */ + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_COMMA) { + ejsLexPutbackToken(ep, tid, ep->token); + } + } while (tid == EJS_TOK_COMMA); + + if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { + return EJS_STATE_ERR; + } + return EJS_STATE_ARG_LIST_DONE; +} + +/******************************************************************************/ +/* + * Parse an assignment statement + */ + +static int parseAssignment(Ejs *ep, int state, int flags, char *id, + char *fullName) +{ + MprVar *vp, *saveProperty, *saveObj; + + if (id == 0) { + return -1; + } + + saveObj = ep->currentObj; + saveProperty = ep->currentProperty; + if (ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT) + != EJS_STATE_RELEXP_DONE) { + return -1; + } + ep->currentObj = saveObj; + ep->currentProperty = saveProperty; + + if (! (flags & EJS_FLAGS_EXE)) { + return state; + } + + if (ep->currentProperty) { + /* + * Update the variable. Update the property name if not + * yet defined. + */ + if (ep->currentProperty->name == 0 || + ep->currentProperty->name[0] == '\0') { + mprSetVarName(ep->currentProperty, id); + } + if (mprWriteProperty(ep->currentProperty, &ep->result) < 0){ + ejsError(ep, "Can't write to variable\n"); + return -1; + } + + } else { + /* + * Create the variable + */ + if (ep->currentObj) { + if (ep->currentObj->type != MPR_TYPE_OBJECT) { + if (strcmp(ep->currentObj->name, "session") == 0) { + ejsError(ep, "Variable \"%s\" is not an array or object." + "If using ESP, you need useSession(); in your page.", + ep->currentObj->name); + } else { + ejsError(ep, "Variable \"%s\" is not an array or object", + ep->currentObj->name); + } + return -1; + } + vp = mprCreateProperty(ep->currentObj, id, &ep->result); + + } else { + /* + * Standard says: "var x" means declare locally. + * "x = 2" means declare globally if x is undefined. + */ + if (state == EJS_STATE_DEC) { + vp = mprCreateProperty(ep->local, id, &ep->result); + } else { + vp = mprCreateProperty(ep->global, id, &ep->result); + } + } +#if BLD_DEBUG + mprSetVarFullName(vp, fullName); +#endif + } + return state; +} + +/******************************************************************************/ +/* + * Parse conditional expression (relational ops separated by ||, &&) + */ + +static int parseCond(Ejs *ep, int state, int flags) +{ + MprVar lhs, rhs; + int tid, operator; + + mprAssert(ep); + + mprDestroyVar(&ep->result); + rhs = lhs = mprCreateUndefinedVar(); + operator = 0; + + do { + /* + * Recurse to handle one side of a conditional. Accumulate the + * left hand side and the final result in ep->result. + */ + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state != EJS_STATE_RELEXP_DONE) { + state = EJS_STATE_ERR; + break; + } + + if (operator > 0) { + mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); + if (evalCond(ep, &lhs, operator, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } + mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_LOGICAL) { + operator = (int) *ep->token; + + } else if (tid == EJS_TOK_RPAREN || tid == EJS_TOK_SEMI) { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_COND_DONE; + break; + + } else { + ejsLexPutbackToken(ep, tid, ep->token); + } + tid = (state == EJS_STATE_RELEXP_DONE); + + } while (state == EJS_STATE_RELEXP_DONE); + + mprDestroyVar(&lhs); + mprDestroyVar(&rhs); + return state; +} + +/******************************************************************************/ +/* + * Parse variable declaration list. Declarations can be of the following forms: + * var x; + * var x, y, z; + * var x = 1 + 2 / 3, y = 2 + 4; + * + * We set the variable to NULL if there is no associated assignment. + */ + +static int parseDeclaration(Ejs *ep, int state, int flags) +{ + int tid; + + mprAssert(ep); + + do { + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { + return EJS_STATE_ERR; + } + ejsLexPutbackToken(ep, tid, ep->token); + + /* + * Parse the entire assignment or simple identifier declaration + */ + if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { + return EJS_STATE_ERR; + } + + /* + * Peek at the next token, continue if comma seen + */ + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_SEMI) { + return EJS_STATE_DEC_LIST_DONE; + } else if (tid != EJS_TOK_COMMA) { + return EJS_STATE_ERR; + } + } while (tid == EJS_TOK_COMMA); + + if (tid != EJS_TOK_SEMI) { + return EJS_STATE_ERR; + } + return EJS_STATE_DEC_LIST_DONE; +} + +/******************************************************************************/ +/* + * Parse expression (leftHandSide operator rightHandSide) + */ + +static int parseExpr(Ejs *ep, int state, int flags) +{ + MprVar lhs, rhs; + int rel, tid; + + mprAssert(ep); + + mprDestroyVar(&ep->result); + rhs = lhs = mprCreateUndefinedVar(); + rel = 0; + tid = 0; + + do { + /* + * This loop will handle an entire expression list. We call parse + * to evalutate each term which returns the result in ep->result. + */ + if (tid == EJS_TOK_LOGICAL) { + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state != EJS_STATE_RELEXP_DONE) { + state = EJS_STATE_ERR; + break; + } + } else { + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { + lhs = mprCreateIntegerVar(0); + rel = (int) *ep->token; + } else { + ejsLexPutbackToken(ep, tid, ep->token); + } + + state = ejsParse(ep, EJS_STATE_EXPR, flags); + if (state != EJS_STATE_EXPR_DONE) { + state = EJS_STATE_ERR; + break; + } + } + + if (rel > 0) { + mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); + if (tid == EJS_TOK_LOGICAL) { + if (evalCond(ep, &lhs, rel, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } else { + if (evalExpr(ep, &lhs, rel, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } + } + mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); + + if ((tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || + tid == EJS_TOK_INC_DEC || tid == EJS_TOK_LOGICAL) { + rel = (int) *ep->token; + + } else { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_RELEXP_DONE; + } + + } while (state == EJS_STATE_EXPR_DONE); + + mprDestroyVar(&lhs); + mprDestroyVar(&rhs); + + return state; +} + +/******************************************************************************/ +/* + * Parse the "for ... in" statement. Format for the statement is: + * + * for (var in expr) { + * body; + * } + */ + +static int parseForIn(Ejs *ep, int state, int flags) +{ + EjsInput endScript, bodyScript; + MprVar *iteratorVar, *setVar, *vp, v; + int forFlags, tid; + + mprAssert(ep); + + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ID) { + return -1; + } + ejsLexPutbackToken(ep, tid, ep->token); + + if (ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FOREACH | EJS_FLAGS_EXE) + != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ep->currentProperty == 0) { + return -1; + } + iteratorVar = ep->currentProperty; + + if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { + return -1; + } + + /* + * Get the set + */ + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ID) { + return -1; + } + ejsLexPutbackToken(ep, tid, ep->token); + + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ep->currentProperty == 0 && flags & EJS_FLAGS_EXE) { + return -1; + } + setVar = ep->currentProperty; + + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + + /* + * Parse the body and remember the end of the body script + */ + forFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &bodyScript); + if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + ejsInitInputState(&endScript); + ejsLexSaveInputState(ep, &endScript); + + /* + * Now actually do the for loop. + */ + if (flags & EJS_FLAGS_EXE) { + if (setVar->type == MPR_TYPE_OBJECT) { + vp = mprGetFirstProperty(setVar, MPR_ENUM_DATA); + while (vp) { + if (strcmp(vp->name, "length") != 0) { + v = mprCreateStringVar(vp->name, 0); + if (mprWriteProperty(iteratorVar, &v) < 0) { + ejsError(ep, "Can't write to variable\n"); + ejsLexFreeInputState(ep, &bodyScript); + ejsLexFreeInputState(ep, &endScript); + return -1; + } + + ejsLexRestoreInputState(ep, &bodyScript); + switch (ejsParse(ep, EJS_STATE_STMT, flags)) { + case EJS_STATE_RET: + return EJS_STATE_RET; + case EJS_STATE_STMT_DONE: + break; + default: + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + } + vp = mprGetNextProperty(setVar, vp, MPR_ENUM_DATA); + } + } else { + ejsError(ep, "Variable \"%s\" is not an array or object", + setVar->name); + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + } + ejsLexRestoreInputState(ep, &endScript); + + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + + return state; +} + +/******************************************************************************/ +/* + * Parse the for statement. Format for the expression is: + * + * for (initial; condition; incr) { + * body; + * } + */ + +static int parseFor(Ejs *ep, int state, int flags) +{ + EjsInput condScript, endScript, bodyScript, incrScript; + int forFlags, cond; + + ejsInitInputState(&endScript); + ejsInitInputState(&bodyScript); + ejsInitInputState(&incrScript); + ejsInitInputState(&condScript); + + mprAssert(ep); + + /* + * Evaluate the for loop initialization statement + */ + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { + return -1; + } + + /* + * The first time through, we save the current input context just prior + * to each step: prior to the conditional, the loop increment and + * the loop body. + */ + ejsLexSaveInputState(ep, &condScript); + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + goto error; + } + cond = (ep->result.boolean != 0); + + if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { + goto error; + } + + /* + * Don't execute the loop increment statement or the body + * first time. + */ + forFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &incrScript); + if (ejsParse(ep, EJS_STATE_EXPR, forFlags) != EJS_STATE_EXPR_DONE) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + goto error; + } + + /* + * Parse the body and remember the end of the body script + */ + ejsLexSaveInputState(ep, &bodyScript); + if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { + goto error; + } + ejsLexSaveInputState(ep, &endScript); + + /* + * Now actually do the for loop. Note loop has been rotated + */ + while (cond && (flags & EJS_FLAGS_EXE)) { + /* + * Evaluate the body + */ + ejsLexRestoreInputState(ep, &bodyScript); + + switch (ejsParse(ep, EJS_STATE_STMT, flags)) { + case EJS_STATE_RET: + return EJS_STATE_RET; + case EJS_STATE_STMT_DONE: + break; + default: + goto error; + } + /* + * Evaluate the increment script + */ + ejsLexRestoreInputState(ep, &incrScript); + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE){ + goto error; + } + /* + * Evaluate the condition + */ + ejsLexRestoreInputState(ep, &condScript); + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + goto error; + } + mprAssert(ep->result.type == MPR_TYPE_BOOL); + cond = (ep->result.boolean != 0); + } + + ejsLexRestoreInputState(ep, &endScript); + +done: + ejsLexFreeInputState(ep, &condScript); + ejsLexFreeInputState(ep, &incrScript); + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return state; + +error: + state = EJS_STATE_ERR; + goto done; +} + +/******************************************************************************/ +/* + * Parse a function declaration + */ + +static int parseFunctionDec(Ejs *ep, int state, int flags) +{ + EjsInput endScript, bodyScript; + MprVar v, *currentObj, *vp; + char *procName; + int len, tid, bodyFlags; + + mprAssert(ep); + mprAssert(ejsPtr(ep->eid)); + + /* + * function (arg, arg, arg) { body }; + * function name(arg, arg, arg) { body }; + */ + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_ID) { + procName = mprStrdup(ep->token); + tid = ejsLexGetToken(ep, state); + } else { + procName = 0; + } + if (tid != EJS_TOK_LPAREN) { + mprFree(procName); + return EJS_STATE_ERR; + } + + /* + * Hand craft the function value structure. + */ + v = mprCreateFunctionVar(0, 0, 0); + tid = ejsLexGetToken(ep, state); + while (tid == EJS_TOK_ID) { + mprAddToArray(v.function.args, mprStrdup(ep->token)); + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { + break; + } + tid = ejsLexGetToken(ep, state); + } + if (tid != EJS_TOK_RPAREN) { + mprFree(procName); + mprDestroyVar(&v); + return EJS_STATE_ERR; + } + + /* Allow new lines before opening brace */ + do { + tid = ejsLexGetToken(ep, state); + } while (tid == EJS_TOK_NEWLINE); + + if (tid != EJS_TOK_LBRACE) { + mprFree(procName); + mprDestroyVar(&v); + return EJS_STATE_ERR; + } + + /* + * Parse the function body. Turn execute off. + */ + bodyFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &bodyScript); + + do { + state = ejsParse(ep, EJS_STATE_STMT, bodyFlags); + } while (state == EJS_STATE_STMT_DONE); + + tid = ejsLexGetToken(ep, state); + if (state != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { + mprFree(procName); + mprDestroyVar(&v); + ejsLexFreeInputState(ep, &bodyScript); + return EJS_STATE_ERR; + } + ejsLexSaveInputState(ep, &endScript); + + /* + * Save the function body between the starting and ending parse positions. + * Overwrite the trailing '}' with a null. + */ + len = endScript.scriptServp - bodyScript.scriptServp; + v.function.body = mprMalloc(len + 1); + memcpy(v.function.body, bodyScript.scriptServp, len); + + if (len <= 0) { + v.function.body[0] = '\0'; + } else { + v.function.body[len - 1] = '\0'; + } + ejsLexFreeInputState(ep, &bodyScript); + ejsLexFreeInputState(ep, &endScript); + + /* + * If we are in an assignment, don't register the function name, rather + * return the function structure in the parser result. + */ + if (flags & EJS_FLAGS_ASSIGNMENT) { + mprCopyVar(&ep->result, &v, MPR_SHALLOW_COPY); + } else { + currentObj = ejsFindObj(ep, 0, procName, flags); + vp = mprSetProperty(currentObj, procName, &v); + } + + mprFree(procName); + mprDestroyVar(&v); + + return EJS_STATE_STMT; +} + +/******************************************************************************/ +/* + * Parse a function name and invoke the function + */ + +static int parseFunction(Ejs *ep, int state, int flags, char *id) +{ + EjsProc proc, *saveProc; + MprVar *saveObj; + + /* + * Must save any current ep->proc value for the current stack frame + * to allow for recursive function calls. + */ + saveProc = (ep->proc) ? ep->proc: 0; + + memset(&proc, 0, sizeof(EjsProc)); + proc.procName = mprStrdup(id); + proc.fn = ep->currentProperty; + proc.args = mprCreateArray(); + ep->proc = &proc; + + mprDestroyVar(&ep->result); + + saveObj = ep->currentObj; + if (ejsParse(ep, EJS_STATE_ARG_LIST, flags) != EJS_STATE_ARG_LIST_DONE) { + freeProc(&proc); + ep->proc = saveProc; + return -1; + } + ep->currentObj = saveObj; + + /* + * Evaluate the function if required + */ + if (flags & EJS_FLAGS_EXE) { + if (evalFunction(ep, ep->currentObj, flags) < 0) { + freeProc(&proc); + ep->proc = saveProc; + return -1; + } + } + + freeProc(&proc); + ep->proc = saveProc; + + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + return state; +} + +/******************************************************************************/ +/* + * Parse an identifier. This is a segment of a fully qualified variable. + * May come here for an initial identifier or for property names + * after a "." or "[...]". + */ + +static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, + int *fullNameLen, int *done) +{ + int tid; + + mprFree(*id); + *id = mprStrdup(ep->token); +#if BLD_DEBUG + *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, + 0, *id, 0); +#endif + if (ep->currentObj == 0) { + ep->currentObj = ejsFindObj(ep, state, *id, flags); + } + + /* + * Find the referenced variable and store it in currentProperty. + */ + ep->currentProperty = ejsFindProperty(ep, state, ep->currentObj, + *id, flags); + updateResult(ep, state, flags, ep->currentProperty); + +#if BLD_DEBUG + if (ep->currentProperty && (ep->currentProperty->name == 0 || + ep->currentProperty->name[0] == '\0')) { + mprSetVarName(ep->currentProperty, *id); + } +#endif + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_LPAREN) { + if (ep->currentProperty == 0) { + ejsError(ep, "Function name not defined \"%s\"\n", *id); + return -1; + } + ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); + return state; + } + + if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || + tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { + ejsLexPutbackToken(ep, tid, ep->token); + return state; + } + + /* + * Only come here for variable access and declarations. + * Assignment handled elsewhere. + */ + if (flags & EJS_FLAGS_EXE) { + if (state == EJS_STATE_DEC) { + /* + * Declare a variable. Standard allows: var x ; var x ; + */ +#if DISABLED + if (ep->currentProperty != 0) { + ejsError(ep, "Variable already defined \"%s\"\n", *id); + return -1; + } +#endif + /* + * Create or overwrite if it already exists + */ + mprSetPropertyValue(ep->currentObj, *id, + mprCreateUndefinedVar()); + ep->currentProperty = 0; + mprDestroyVar(&ep->result); + + } else if (flags & EJS_FLAGS_FOREACH) { + if (ep->currentProperty == 0) { + ep->currentProperty = + mprCreatePropertyValue(ep->currentObj, *id, + mprCreateUndefinedVar()); + } + + } else { + if (ep->currentProperty == 0) { + if (ep->currentObj == ep->global || + ep->currentObj == ep->local) { + ejsError(ep, "Undefined variable \"%s\"\n", *id); + return -1; + } + ep->currentProperty = mprCreatePropertyValue(ep->currentObj, + *id, mprCreateUndefinedVar()); + } + } + } + ejsLexPutbackToken(ep, tid, ep->token); + if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || + tid == EJS_TOK_IN) { + *done = 1; + } + return state; +} + +/******************************************************************************/ +/* + * Parse an "if" statement + */ + +static int parseIf(Ejs *ep, int state, int flags, int *done) +{ + bool ifResult; + int thenFlags, elseFlags, tid; + + if (state != EJS_STATE_STMT) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { + return -1; + } + + /* + * Evaluate the entire condition list "(condition)" + */ + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + + /* + * This is the "then" case. We need to always parse both cases and + * execute only the relevant case. + */ + ifResult = mprVarToBool(&ep->result); + if (ifResult) { + thenFlags = flags; + elseFlags = flags & ~EJS_FLAGS_EXE; + } else { + thenFlags = flags & ~EJS_FLAGS_EXE; + elseFlags = flags; + } + + /* + * Process the "then" case. + */ + switch (ejsParse(ep, EJS_STATE_STMT, thenFlags)) { + case EJS_STATE_RET: + state = EJS_STATE_RET; + return state; + case EJS_STATE_STMT_DONE: + break; + default: + return -1; + } + + /* + * Check to see if there is an "else" case + */ + removeNewlines(ep, state); + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ELSE) { + ejsLexPutbackToken(ep, tid, ep->token); + *done = 1; + return state; + } + + /* + * Process the "else" case. + */ + switch (ejsParse(ep, EJS_STATE_STMT, elseFlags)) { + case EJS_STATE_RET: + state = EJS_STATE_RET; + return state; + case EJS_STATE_STMT_DONE: + break; + default: + return -1; + } + *done = 1; + return state; +} + +/******************************************************************************/ +/* + * Parse an "++" or "--" statement + */ + +static int parseInc(Ejs *ep, int state, int flags) +{ + MprVar one; + + if (! (flags & EJS_FLAGS_EXE)) { + return state; + } + + if (ep->currentProperty == 0) { + ejsError(ep, "Undefined variable \"%s\"\n", ep->token); + return -1; + } + one = mprCreateIntegerVar(1); + if (evalExpr(ep, ep->currentProperty, (int) *ep->token, + &one) < 0) { + return -1; + } + if (mprWriteProperty(ep->currentProperty, &ep->result) < 0) { + ejsError(ep, "Can't write to variable\n"); + return -1; + } + return state; +} + +/******************************************************************************/ +/* + * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result + * in ep->result. Returns -1 on errors, zero if successful. + */ + +static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + bool l, r, lval; + + mprAssert(rel > 0); + + l = mprVarToBool(lhs); + r = mprVarToBool(rhs); + + switch (rel) { + case EJS_COND_AND: + lval = l && r; + break; + case EJS_COND_OR: + lval = l || r; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Evaluate an operation. Returns with the result in ep->result. Returns -1 + * on errors, otherwise zero is returned. + */ + +static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + char *str; + MprNum lval, num; + int rc; + + mprAssert(rel > 0); + str = 0; + lval = 0; + + /* + * Type conversion. This is tricky and must be according to the standard. + * Only numbers (including floats) and strings can be compared. All other + * types are first converted to numbers by preference and if that fails, + * to strings. + * + * First convert objects to comparable types. The "===" operator will + * test the sameness of object references. Here, we coerce to comparable + * types first. + */ + if (lhs->type == MPR_TYPE_OBJECT) { + if (ejsRunFunction(ep->eid, lhs, "toValue", 0) == 0) { + mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); + } else { + if (ejsRunFunction(ep->eid, lhs, "toString", 0) == 0) { + mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); + } + } + /* Nothing more can be done */ + } + + if (rhs->type == MPR_TYPE_OBJECT) { + if (ejsRunFunction(ep->eid, rhs, "toValue", 0) == 0) { + mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); + } else { + if (ejsRunFunction(ep->eid, rhs, "toString", 0) == 0) { + mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); + } + } + /* Nothing more can be done */ + } + + /* + * From here on, lhs and rhs may contain allocated data (strings), so + * we must always destroy before overwriting. + */ + + /* + * Only allow a few bool operations. Otherwise convert to number. + */ + if (lhs->type == MPR_TYPE_BOOL && rhs->type == MPR_TYPE_BOOL && + (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && + rel != EJS_EXPR_BOOL_COMP)) { + num = mprVarToNumber(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + } + + /* + * Types do not match, so try to coerce the right operand to match the left + * But first, try to convert a left operand that is a numeric stored as a + * string, into a numeric. + */ + if (lhs->type != rhs->type) { + if (lhs->type == MPR_TYPE_STRING) { + if (isdigit((int) lhs->string[0])) { + num = mprVarToNumber(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + /* Examine further below */ + + } else { + /* + * Convert the RHS to a string + */ + mprVarToString(&str, MPR_MAX_STRING, 0, rhs); + mprDestroyVar(rhs); + *rhs = mprCreateStringVar(str, 1); + mprFree(str); + } + +#if BLD_FEATURE_FLOATING_POINT + } else if (lhs->type == MPR_TYPE_FLOAT) { + /* + * Convert rhs to floating + */ + double f = mprVarToFloat(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateFloatVar(f); + +#endif +#if BLD_FEATURE_INT64 + } else if (lhs->type == MPR_TYPE_INT64) { + /* + * Convert the rhs to 64 bit + */ + int64 n = mprVarToInteger64(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateInteger64Var(n); +#endif + } else if (lhs->type == MPR_TYPE_BOOL || lhs->type == MPR_TYPE_INT) { + + if (rhs->type == MPR_TYPE_STRING) { + /* + * Convert to lhs to a string + */ + mprVarToString(&str, MPR_MAX_STRING, 0, lhs); + mprDestroyVar(lhs); + *lhs = mprCreateStringVar(str, 1); + mprFree(str); + +#if BLD_FEATURE_FLOATING_POINT + } else if (rhs->type == MPR_TYPE_FLOAT) { + /* + * Convert lhs to floating + */ + double f = mprVarToFloat(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateFloatVar(f); +#endif + + } else { + /* + * Convert both operands to numbers + */ + num = mprVarToNumber(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + + num = mprVarToNumber(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateNumberVar(num); + } + } + } + + /* + * We have failed to coerce the types to be the same. Special case here + * for undefined and null. We need to allow comparisions against these + * special values. + */ + if (lhs->type == MPR_TYPE_UNDEFINED || lhs->type == MPR_TYPE_NULL) { + switch (rel) { + case EJS_EXPR_EQ: + lval = lhs->type == rhs->type; + break; + case EJS_EXPR_NOTEQ: + lval = lhs->type != rhs->type; + break; + default: + lval = 0; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar((bool) lval), 0); + return 0; + } + + /* + * Types are the same here + */ + switch (lhs->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + /* Should be handled above */ + mprAssert(0); + return 0; + + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); + return 0; + + case MPR_TYPE_BOOL: + rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); + break; +#endif + + case MPR_TYPE_INT: + rc = evalNumericExpr(ep, (MprNum) lhs->integer, rel, + (MprNum) rhs->integer); + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + rc = evalNumericExpr(ep, (MprNum) lhs->integer64, rel, + (MprNum) rhs->integer64); + break; +#endif + + case MPR_TYPE_STRING: + rc = evalStringExpr(ep, lhs, rel, rhs); + } + return rc; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Expressions with floating operands + */ + +static int evalFloatExpr(Ejs *ep, double l, int rel, double r) +{ + double lval; + bool logical; + + lval = 0; + logical = 0; + + switch (rel) { + case EJS_EXPR_PLUS: + lval = l + r; + break; + case EJS_EXPR_INC: + lval = l + 1; + break; + case EJS_EXPR_MINUS: + lval = l - r; + break; + case EJS_EXPR_DEC: + lval = l - 1; + break; + case EJS_EXPR_MUL: + lval = l * r; + break; + case EJS_EXPR_DIV: + lval = l / r; + break; + default: + logical++; + break; + } + + /* + * Logical operators + */ + if (logical) { + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_LESS: + lval = (l < r) ? 1 : 0; + break; + case EJS_EXPR_LESSEQ: + lval = (l <= r) ? 1 : 0; + break; + case EJS_EXPR_GREATER: + lval = (l > r) ? 1 : 0; + break; + case EJS_EXPR_GREATEREQ: + lval = (l >= r) ? 1 : 0; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); + + } else { + mprCopyVarValue(&ep->result, mprCreateFloatVar(lval), 0); + } + return 0; +} + +#endif /* BLD_FEATURE_FLOATING_POINT */ +/******************************************************************************/ +/* + * Expressions with boolean operands + */ + +static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) +{ + bool lval; + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Expressions with numeric operands + */ + +static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) +{ + MprNum lval; + bool logical; + + lval = 0; + logical = 0; + + switch (rel) { + case EJS_EXPR_PLUS: + lval = l + r; + break; + case EJS_EXPR_INC: + lval = l + 1; + break; + case EJS_EXPR_MINUS: + lval = l - r; + break; + case EJS_EXPR_DEC: + lval = l - 1; + break; + case EJS_EXPR_MUL: + lval = l * r; + break; + case EJS_EXPR_DIV: + if (r != 0) { + lval = l / r; + } else { + ejsError(ep, "Divide by zero"); + return -1; + } + break; + case EJS_EXPR_MOD: + if (r != 0) { + lval = l % r; + } else { + ejsError(ep, "Modulo zero"); + return -1; + } + break; + case EJS_EXPR_LSHIFT: + lval = l << r; + break; + case EJS_EXPR_RSHIFT: + lval = l >> r; + break; + + default: + logical++; + break; + } + + /* + * Logical operators + */ + if (logical) { + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_LESS: + lval = (l < r) ? 1 : 0; + break; + case EJS_EXPR_LESSEQ: + lval = (l <= r) ? 1 : 0; + break; + case EJS_EXPR_GREATER: + lval = (l > r) ? 1 : 0; + break; + case EJS_EXPR_GREATEREQ: + lval = (l >= r) ? 1 : 0; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); + + } else { + mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); + } + return 0; +} + +/******************************************************************************/ +/* + * Expressions with string operands + */ + +static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + int lval; + + mprAssert(ep); + mprAssert(lhs); + mprAssert(rhs); + + switch (rel) { + case EJS_EXPR_LESS: + lval = strcmp(lhs->string, rhs->string) < 0; + break; + case EJS_EXPR_LESSEQ: + lval = strcmp(lhs->string, rhs->string) <= 0; + break; + case EJS_EXPR_GREATER: + lval = strcmp(lhs->string, rhs->string) > 0; + break; + case EJS_EXPR_GREATEREQ: + lval = strcmp(lhs->string, rhs->string) >= 0; + break; + case EJS_EXPR_EQ: + lval = strcmp(lhs->string, rhs->string) == 0; + break; + case EJS_EXPR_NOTEQ: + lval = strcmp(lhs->string, rhs->string) != 0; + break; + case EJS_EXPR_PLUS: + /* + * This differs from all the above operations. We append rhs to lhs. + */ + mprDestroyVar(&ep->result); + appendValue(&ep->result, lhs); + appendValue(&ep->result, rhs); + return 0; + + case EJS_EXPR_INC: + case EJS_EXPR_DEC: + case EJS_EXPR_MINUS: + case EJS_EXPR_DIV: + case EJS_EXPR_MOD: + case EJS_EXPR_LSHIFT: + case EJS_EXPR_RSHIFT: + default: + ejsError(ep, "Bad operator"); + return -1; + } + + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Evaluate a function. obj is set to the current object if a function is being + * run. + */ + +static int evalFunction(Ejs *ep, MprVar *obj, int flags) +{ + EjsProc *proc; + MprVar arguments, callee, thisObject, *prototype, **argValues; + MprArray *formalArgs, *actualArgs; + char buf[16], **argNames, **argBuf; + int i, rc, fid; + + mprAssert(ep); + mprAssert(ejsPtr(ep->eid)); + + rc = -1; + proc = ep->proc; + prototype = proc->fn; + actualArgs = proc->args; + argValues = (MprVar**) actualArgs->handles; + + /* + * Create a new variable stack frame. ie. new local variables. + */ + fid = ejsOpenBlock(ep->eid); + + if (flags & EJS_FLAGS_NEW) { + /* + * Create a new bare object and pass it into the constructor as the + * "this" local variable. + */ + thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); + mprCreatePropertyValue(ep->local, "this", thisObject); + + } else if (obj) { + mprCreateProperty(ep->local, "this", obj); + } + + switch (prototype->type) { + default: + mprAssert(0); + break; + + case MPR_TYPE_STRING_CFUNCTION: + if (actualArgs->used > 0) { + argBuf = mprMalloc(actualArgs->used * sizeof(char*)); + for (i = 0; i < actualArgs->used; i++) { + mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); + } + } else { + argBuf = 0; + } + + /* + * Call the function depending on the various handle flags + */ + ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; + if (prototype->flags & MPR_VAR_ALT_HANDLE) { + rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) + (ep->eid, ep->altHandle, actualArgs->used, argBuf); + } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { + rc = (prototype->cFunctionWithStrings.fn)(ep->eid, + actualArgs->used, argBuf); + } else { + rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, + actualArgs->used, argBuf); + } + + if (actualArgs->used > 0) { + for (i = 0; i < actualArgs->used; i++) { + mprFree(argBuf[i]); + } + mprFree(argBuf); + } + ep->thisPtr = 0; + break; + + case MPR_TYPE_CFUNCTION: + /* + * Call the function depending on the various handle flags + */ + ep->thisPtr = prototype->cFunction.thisPtr; + if (prototype->flags & MPR_VAR_ALT_HANDLE) { + rc = ((EjsAltCFunction) prototype->cFunction.fn) + (ep->eid, ep->altHandle, actualArgs->used, argValues); + } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { + rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, + argValues); + } else { + rc = (prototype->cFunction.fn)(ep->primaryHandle, + actualArgs->used, argValues); + } + ep->thisPtr = 0; + break; + + case MPR_TYPE_FUNCTION: + + formalArgs = prototype->function.args; + argNames = (char**) formalArgs->handles; + +#if FUTURE + if (formalArgs->used != actualArgs->used) { + ejsError(ep, "Bad number of args. Should be %d", formalArgs->used); + return -1; + } +#endif + + /* + * Create the arguments and callee variables + */ + arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); + callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); + + /* + * Overwrite the length property + */ + mprCreatePropertyValue(&arguments, "length", + mprCreateIntegerVar(actualArgs->used)); + mprCreatePropertyValue(&callee, "length", + mprCreateIntegerVar(formalArgs->used)); + + /* + * Define all the agruments to be set to the actual parameters + */ + for (i = 0; i < formalArgs->used; i++) { + mprCreateProperty(ep->local, argNames[i], argValues[i]); + mprItoa(i, buf, sizeof(buf)); + mprCreateProperty(&arguments, buf, argValues[i]); + } + + mprCreateProperty(&arguments, "callee", &callee); + mprCreateProperty(ep->local, "arguments", &arguments); + + /* + * Can destroy our variables here as they are now referenced via + * "local" + */ + mprDestroyVar(&callee); + mprDestroyVar(&arguments); + + /* + * Actually run the function + */ + rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); + break; + } + + ejsCloseBlock(ep->eid, fid); + + /* + * New statements return the newly created object as the result of the + * command + */ + if (flags & EJS_FLAGS_NEW) { + mprDestroyVar(&ep->result); + /* + * Don't copy, we want to assign the actual object into result. + * (mprCopyVar would inc the refCount to 2). + */ + ep->result = thisObject; + } + return rc; +} + +/******************************************************************************/ +/* + * Run a function + */ + +int ejsRunFunction(int eid, MprVar *obj, const char *functionName, MprArray *args) +{ + EjsProc proc, *saveProc; + Ejs *ep; + int rc; + + mprAssert(obj); + mprAssert(functionName && *functionName); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return MPR_ERR_NOT_FOUND; + } + saveProc = ep->proc; + ep->proc = &proc; + + memset(&proc, 0, sizeof(EjsProc)); + mprDestroyVar(&ep->result); + + proc.fn = mprGetProperty(obj, functionName, 0); + if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { + ep->proc = saveProc; + return MPR_ERR_NOT_FOUND; + } + proc.procName = mprStrdup(functionName); + if (args == 0) { + proc.args = mprCreateArray(); + rc = evalFunction(ep, obj, 0); + } else { + proc.args = args; + rc = evalFunction(ep, obj, 0); + proc.args = 0; + } + + freeProc(&proc); + ep->proc = saveProc; + + return rc; +} + +/******************************************************************************/ +/* + * Find which object contains the property given the current context. + * Only used for top level properties. + */ + +MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) +{ + MprVar *vp; + MprVar *obj; + + mprAssert(ep); + mprAssert(property && *property); + + if (flags & EJS_FLAGS_GLOBAL) { + obj = ep->global; + + } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { + obj = ep->local; + + } else { + /* First look local, then look global */ + vp = mprGetProperty(ep->local, property, 0); + if (vp) { + obj = ep->local; + } else if (mprGetProperty(ep->local, property, 0)) { + obj = ep->local; + } else { + obj = ep->global; + } + } + return obj; +} + +/******************************************************************************/ +/* + * Find an object property given a object and a property name. We + * intelligently look in the local and global namespaces depending on + * our state. If not found in local or global, try base classes for function + * names only. Returns the property or NULL. + */ + +MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, + int flags) +{ + MprVar *vp; + + mprAssert(ep); + if (flags & EJS_FLAGS_EXE) { + mprAssert(property && *property); + } + + if (obj != 0) { +#if FUTURE && MB + op = obj; + do { + vp = mprGetProperty(op, property, 0); + if (vp != 0) { + if (op != obj && mprVarIsFunction(vp->type)) { + } + break; + } + op = op->baseObj; + } while (op); +#endif + vp = mprGetProperty(obj, property, 0); + + } else { + if (state == EJS_STATE_DEC) { + vp = mprGetProperty(ep->local, property, 0); + + } else { + /* Look local first, then global */ + vp = mprGetProperty(ep->local, property, 0); + if (vp == NULL) { + vp = mprGetProperty(ep->global, property, 0); + } + } + } + return vp; +} + +/******************************************************************************/ +/* + * Update result + */ + +static void updateResult(Ejs *ep, int state, int flags, MprVar *vp) +{ + if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { + mprDestroyVar(&ep->result); + if (vp) { + mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); + } + } +} + +/******************************************************************************/ +/* + * Append to the pointer value + */ + +static void appendValue(MprVar *dest, MprVar *src) +{ + char *value, *oldBuf, *buf; + int len, oldLen; + + mprAssert(dest); + + mprVarToString(&value, MPR_MAX_STRING, 0, src); + + if (mprVarIsValid(dest)) { + len = strlen(value); + oldBuf = dest->string; + oldLen = strlen(oldBuf); + buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); + dest->string = buf; + strncpy(&buf[oldLen], value, len+1); + } else { + *dest = mprCreateStringVar(value, 1); + } + mprFree(value); +} + +/******************************************************************************/ +/* + * Exit with status + */ + +void ejsSetExitStatus(int eid, int status) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + ep->exitStatus = status; + ep->flags |= EJS_FLAGS_EXIT; +} + +/******************************************************************************/ +/* + * Free an argument list + */ + +static void freeProc(EjsProc *proc) +{ + MprVar **argValues; + int i; + + if (proc->args) { + argValues = (MprVar**) proc->args->handles; + + for (i = 0; i < proc->args->max; i++) { + if (argValues[i]) { + mprDestroyVar(argValues[i]); + mprFree(argValues[i]); + mprRemoveFromArray(proc->args, i); + } + } + + mprDestroyArray(proc->args); + } + + if (proc->procName) { + mprFree(proc->procName); + proc->procName = NULL; + } +} + +/******************************************************************************/ +/* + * This function removes any new lines. Used for else cases, etc. + */ + +static void removeNewlines(Ejs *ep, int state) +{ + int tid; + + do { + tid = ejsLexGetToken(ep, state); + } while (tid == EJS_TOK_NEWLINE); + + ejsLexPutbackToken(ep, tid, ep->token); +} + +/******************************************************************************/ + +#else +void ejsParserDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejsProcs.c b/source4/lib/ejs/ejsProcs.c new file mode 100644 index 0000000000..39df18ef94 --- /dev/null +++ b/source4/lib/ejs/ejsProcs.c @@ -0,0 +1,705 @@ +/* + * @file ejsProc.c + * @brief EJS support functions + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "lib/ejs/ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ +/* + * Object constructors + */ +static int objectConsProc(EjsHandle eid, int argc, MprVar **argv); +static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv); +static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv); +static int numberConsProc(EjsHandle eid, int argc, MprVar **argv); +static int stringConsProc(EjsHandle eid, int argc, MprVar **argv); + +/* + * Core functions + */ +static int toStringProc(EjsHandle eid, int argc, MprVar **argv); +static int valueOfProc(EjsHandle eid, int argc, MprVar **argv); + +/* + * Triggers + */ +static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, + MprProperties *parentProperties, MprVar *prop, MprVar *newValue, + bool copyRef); + +/******************************************************************************/ +/* + * Routine to create the base common to all object types + */ + +MprVar ejsCreateObj(const char *name, int hashSize) +{ + MprVar o; + + o = mprCreateObjVar(name, hashSize); + if (o.type == MPR_TYPE_UNDEFINED) { + mprAssert(0); + return o; + } + + mprCreatePropertyValue(&o, "toString", + mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(&o, "valueOf", + mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE)); + return o; +} + +/******************************************************************************/ +/* + * Routine to destroy a variable + */ + +bool ejsDestroyVar(MprVar *obj) +{ + return mprDestroyVar(obj); +} + +/******************************************************************************/ +/* + * Routine to create the base array type + */ + +MprVar ejsCreateArray(const char *name, int size) +{ + MprVar obj, *lp, undef; + char idx[16]; + int i; + + /* Sanity limit for size of hash table */ + + obj = ejsCreateObj(name, max(size, 503)); + if (obj.type == MPR_TYPE_UNDEFINED) { + mprAssert(0); + return obj; + } + + undef = mprCreateUndefinedVar(); + for (i = 0; i < size; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(&obj, idx, &undef); + } + + lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size)); + mprAssert(lp); + + mprSetVarReadonly(lp, 1); + mprAddVarTrigger(lp, lengthTrigger); + + return obj; +} + +/******************************************************************************/ +/******************************** Constructors ********************************/ +/******************************************************************************/ +/* + * Object constructor. Nothing really done here. For future expansion. + */ + +static int objectConsProc(EjsHandle eid, int argc, MprVar **argv) +{ +#if XX_UNUSED_XX + MprVar *obj; + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); +#endif + return 0; +} + +/******************************************************************************/ +/* + * Array constructor + */ + +static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj, *lp, undef; + Ejs *ep; + char idx[16]; + int i, max; + + objectConsProc(eid, argc, argv); + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + + if (argc == 1) { + /* + * x = new Array(size); + */ + undef = mprCreateUndefinedVar(); + max = (int) mprVarToInteger(argv[0]); + for (i = 0; i < max; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(obj, idx, &undef); + } + } else if (argc > 1) { + /* + * x = new Array(element0, element1, ..., elementN): + */ + max = argc; + for (i = 0; i < max; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(obj, idx, argv[i]); + } + + } else { + max = 0; + } + + lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); + mprAssert(lp); + + mprSetVarReadonly(lp, 1); + mprAddVarTrigger(lp, lengthTrigger); + + return 0; +} + +/******************************************************************************/ +/* + * Boolean constructor + */ + +static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +#if FUTURE +/* + * Date constructor + */ + +static int dateConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +#endif +/******************************************************************************/ +/* + * Number constructor + */ + +static int numberConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +/* + * String constructor + */ + +static int stringConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +/********************************** Functions *********************************/ +/******************************************************************************/ + +static int toStringProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj; + Ejs *ep; + char *buf; + int radix; + + if (argc == 0) { + radix = 10; + + } else if (argc == 1) { + radix = (int) mprVarToInteger(argv[0]); + + } else { + mprAssert(0); + return -1; + } + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + mprVarToString(&buf, MPR_MAX_STRING, 0, obj); + mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY); + mprFree(buf); + + return 0; +} + +/******************************************************************************/ + +static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj; + Ejs *ep; + + if (argc != 0) { + mprAssert(0); + return -1; + } + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + switch (obj->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_STRING_CFUNCTION: + mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); + break; + + case MPR_TYPE_STRING: + mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0); + break; + + case MPR_TYPE_BOOL: + case MPR_TYPE_INT: +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: +#endif +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: +#endif + mprCopyVar(&ep->result, obj, 0); + break; + } + return 0; +} + +/******************************************************************************/ +/* + * Var access trigger on the Array.length property. Return the count of + * enumerable properties (don't count functions). + */ + +static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, + MprProperties *parentProperties, MprVar *prop, MprVar *newValue, + bool copyRef) +{ + switch (op) { + case MPR_VAR_READ: + /* + * Subtract one for the length property + * FUTURE -- need an API to access parentProperties + * FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE. + * API needs finer control. + */ + *newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1); + return MPR_TRIGGER_USE_NEW_VALUE; + + case MPR_VAR_WRITE: + return MPR_TRIGGER_ABORT; + + case MPR_VAR_CREATE_PROPERTY: + case MPR_VAR_DELETE_PROPERTY: + case MPR_VAR_DELETE: + default: + break; + } + return MPR_TRIGGER_PROCEED; +} + +/******************************************************************************/ +/**************************** Extension Functions *****************************/ +/******************************************************************************/ +/* + * Assert + */ + +static int assertProc(EjsHandle eid, int argc, MprVar **argv) +{ + bool b; + + if (argc < 1) { + ejsSetErrorMsg(eid, "usage: assert(condition)\n"); + return -1; + } + b = mprVarToBool(argv[0]); + if (b == 0) { + ejsSetErrorMsg(eid, "Assertion failure\n"); + return -1; + } + ejsSetReturnValue(eid, mprCreateBoolVar(b)); + return 0; +} + +/******************************************************************************/ +/* + * Exit + */ + +static int exitProc(EjsHandle eid, int argc, MprVar **argv) +{ + int status; + + if (argc < 1) { + ejsSetErrorMsg(eid, "usage: exit(status)\n"); + return -1; + } + status = (int) mprVarToInteger(argv[0]); + ejsSetExitStatus(eid, status); + + ejsSetReturnValue(eid, mprCreateStringVar("", 0)); + return 0; +} + +/******************************************************************************/ + +static void printVar(MprVar *vp, int recurseCount, int indent) +{ + MprVar *np; + char *buf; + int i; + + if (recurseCount > 5) { + write(1, "Skipping - recursion too deep\n", 29); + return; + } + + for (i = 0; i < indent; i++) { + write(1, " ", 2); + } + + if (vp->type == MPR_TYPE_OBJECT) { + if (vp->name) { + write(1, vp->name, strlen(vp->name)); + } else { + write(1, "unknown", 7); + } + write(1, ": {\n", 4); + np = mprGetFirstProperty(vp, MPR_ENUM_DATA); + while (np) { + if (strcmp(np->name, "local") == 0 || + strcmp(np->name, "global") == 0 || + strcmp(np->name, "this") == 0) { + np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); + continue; + } + printVar(np, recurseCount + 1, indent + 1); + np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); + if (np) { + write(1, ",\n", 2); + } + } + write(1, "\n", 1); + for (i = 0; i < indent; i++) { + write(1, " ", 2); + } + write(1, "}", 1); + + } else { + if (vp->name) { + write(1, vp->name, strlen(vp->name)); + } else { + write(1, "unknown", 7); + } + write(1, ": ", 2); + + /* FUTURE -- other types ? */ + mprVarToString(&buf, MPR_MAX_STRING, 0, vp); + if (vp->type == MPR_TYPE_STRING) { + write(1, "\"", 1); + } + write(1, buf, strlen(buf)); + if (vp->type == MPR_TYPE_STRING) { + write(1, "\"", 1); + } + mprFree(buf); + } +} + +/******************************************************************************/ +/* + * Print the args to stdout + */ + +static int printVarsProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *vp; + char *buf; + int i; + + for (i = 0; i < argc; i++) { + vp = argv[i]; + switch (vp->type) { + case MPR_TYPE_OBJECT: + printVar(vp, 0, 0); + break; + default: + mprVarToString(&buf, MPR_MAX_STRING, 0, vp); + write(1, buf, strlen(buf)); + mprFree(buf); + break; + } + } + write(1, "\n", 1); + + ejsSetReturnValue(eid, mprCreateStringVar("", 0)); + return 0; +} + +/******************************************************************************/ +/* + * Print the args to stdout + */ + +static int printProc(EjsHandle eid, int argc, MprVar **argv) +{ + char *buf; + int i; + + for (i = 0; i < argc; i++) { + mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]); + write(1, buf, strlen(buf)); + mprFree(buf); + } + return 0; +} + +/******************************************************************************/ +/* + * println + */ + +static int printlnProc(EjsHandle eid, int argc, MprVar **argv) +{ + printProc(eid, argc, argv); + write(1, "\n", 1); + return 0; +} + +/******************************************************************************/ +/* + * Trace + */ + +static int traceProc(EjsHandle eid, int argc, char **argv) +{ + if (argc == 1) { + mprLog(0, "%s", argv[0]); + + } else if (argc == 2) { + mprLog(atoi(argv[0]), "%s", argv[1]); + + } else { + ejsSetErrorMsg(eid, "Usage: trace([level], message)"); + return -1; + } + ejsSetReturnString(eid, ""); + return 0; +} + +/******************************************************************************/ +/* + * Return the object reference count + */ + +static int refCountProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *vp; + int count; + + vp = argv[0]; + if (vp->type == MPR_TYPE_OBJECT) { + count = mprGetVarRefCount(vp); + ejsSetReturnValue(eid, mprCreateIntegerVar(count)); + } else { + ejsSetReturnValue(eid, mprCreateIntegerVar(0)); + } + + return 0; +} + +/******************************************************************************/ +/* + * Evaluate a sub-script. It is evaluated in the same variable scope as + * the calling script / function. + */ + +static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *arg; + char *emsg; + int i; + + ejsSetReturnValue(eid, mprCreateUndefinedVar()); + + for (i = 0; i < argc; i++) { + arg = argv[i]; + if (arg->type != MPR_TYPE_STRING) { + continue; + } + if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) { + ejsSetErrorMsg(eid, "%s", emsg); + mprFree(emsg); + return -1; + } + } + /* + * Return with the value of the last expression + */ + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ +/* + * Define the standard properties and functions inherited by all script engines. + */ + +int ejsDefineStandardProperties(MprVar *obj) +{ +#if BLD_FEATURE_FLOATING_POINT + double d = 0.0; + + /* FUTURE - this generates warnings on some systems. This is okay. */ + + mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d)); + d = MAX_FLOAT; + mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d)); +#endif + mprCreatePropertyValue(obj, "null", mprCreateNullVar()); + mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); + mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); + mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); + +#if BLD_FEATURE_LEGACY_API + /* + * DEPRECATED: 2.0. + * So that ESP/ASP can ignore "language=javascript" statements + */ + mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0)); +#endif + + /* + * Extension functions + */ + mprCreatePropertyValue(obj, "assert", + mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "eval", + mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "exit", + mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "refCount", + mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "print", + mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "println", + mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "printVars", + mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "trace", + mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE)); + + /* + * Constructors + */ + mprCreatePropertyValue(obj, "Array", + mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Boolean", + mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Object", + mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Number", + mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "String", + mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + + /* mprCreatePropertyValue(obj, "Date", + * mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + * mprCreatePropertyValue(obj, "Regexp", + * mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + */ + + /* + * Can we use on var x = "string text"; + */ + return 0; +} + +/******************************************************************************/ + +#else +void ejsProcsDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/miniMpr.c b/source4/lib/ejs/miniMpr.c new file mode 100644 index 0000000000..2c6f7bea50 --- /dev/null +++ b/source4/lib/ejs/miniMpr.c @@ -0,0 +1,505 @@ +/* + * @file miniMpr.cpp + * @brief Mini Mbedthis Portable Runtime (MPR) + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +#include "lib/ejs/miniMpr.h" + +/************************************ Code ************************************/ +#if !BLD_APPWEB +#if !BLD_GOAHEAD_WEBSERVER + +static void *mpr_ctx; + +void mprSetCtx(TALLOC_CTX *ctx) +{ + mpr_ctx = ctx; +} + +void mprFree(void *ptr) +{ + talloc_free(ptr); +} + +void *mprMalloc(uint size) +{ + return talloc_size(mpr_ctx, size); +} + +/******************************************************************************/ + +void *mprRealloc(void *ptr, uint size) +{ + return talloc_realloc_size(mpr_ctx, ptr, size); +} + +/******************************************************************************/ + +char *mprStrdup(const char *str) +{ + if (str == 0) { + str = ""; + } + return talloc_strdup(mpr_ctx, str); +} + +/*****************************************************************************/ + +int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) +{ + va_list args; + char *buf; + int count; + + va_start(args, fmt); + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + va_end(args); + return count; +} + +/*****************************************************************************/ + +int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) +{ + char *buf; + int count; + + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + return count; +} + + +/*****************************************************************************/ +/* + * Format a number as a string. FUTURE -- reverse args to be standard. + * ie. mprItoa(char *userBuf, int bufsize, int value); + */ + +char *mprItoa(int value, char *buf, int width) +{ + char numBuf[16]; + char *cp, *dp, *endp; + int negative; + + cp = &numBuf[sizeof(numBuf)]; + *--cp = '\0'; + + if (value < 0) { + negative = 1; + value = -value; + width--; + } else { + negative = 0; + } + + do { + *--cp = '0' + (value % 10); + value /= 10; + } while (value > 0); + + if (negative) { + *--cp = '-'; + } + + dp = buf; + endp = &buf[width]; + while (dp < endp && *cp) { + *dp++ = *cp++; + } + *dp++ = '\0'; + return buf; +} + +/*****************************************************************************/ + +void mprLog(int level, const char *fmt, ...) +{ + va_list args; + char *buf; + + if (DEBUGLVL(level)) { + va_start(args, fmt); + mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); + va_end(args); + DEBUG(level, ("mprLog: %s", buf)); + mprFree(buf); + } +} + +/*****************************************************************************/ + +void mprBreakpoint(const char *file, int line, const char *cond) +{ + char *buf; + mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", + file, line, cond); + http_exception(buf); +} + +#endif /* !BLD_GOAHEAD_WEBSERVER */ +/*****************************************************************************/ +/* + * Create a general growable array structure + */ + +MprArray *mprCreateArray() +{ + MprArray *array; + int size; + + array = (MprArray*) mprMalloc(sizeof(MprArray)); + if (array == 0) { + return 0; + } + memset(array, 0, sizeof(MprArray)); + + size = MPR_ARRAY_INCR * sizeof(void*); + array->handles = (void**) mprMalloc(size); + if (array->handles == 0) { + mprFree(array); + return 0; + } + memset(array->handles, 0, size); + array->max = MPR_ARRAY_INCR; + array->used = 0; + return array; +} + +/*****************************************************************************/ +/* + * Dispose of the array. Callers responsibility to dispose of handle entries. + */ + +void mprDestroyArray(MprArray *array) +{ + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + mprFree(array->handles); + mprFree(array); +} + +/*****************************************************************************/ +/* + * Add an item to the array + */ + +int mprAddToArray(MprArray *array, void *item) +{ + int memsize, idx, len; + + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + if (array->used < array->max) { + idx = array->used++; + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + + for (idx = array->used; idx < array->max; idx++) { + if (array->handles[idx] == 0) { + array->used++; + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + } + + len = array->max + MPR_ARRAY_INCR; + memsize = len * sizeof(void*); + array->handles = (void**) mprRealloc((void*) array->handles, memsize); + if (array->handles == NULL) { + return -1; + } + memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); + array->max = len; + array->used++; + + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + + array->handles[idx] = item; + return idx; +} + +/*****************************************************************************/ +/* + * Remove from the array + */ + +int mprRemoveFromArray(MprArray *array, int idx) +{ + mprAssert(array); + mprAssert(array->max > 0); + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] != 0); + mprAssert(array->used > 0); + + array->handles[idx] = 0; + return --array->used; +} + +/*****************************************************************************/ +/* + * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() + */ + +char *mprStrTok(char *str, const char *delim, char **tok) +{ + char *start, *end; + int i; + + start = str ? str : *tok; + + if (start == 0) { + return 0; + } + + i = strspn(start, delim); + start += i; + if (*start == '\0') { + *tok = 0; + return 0; + } + end = strpbrk(start, delim); + if (end) { + *end++ = '\0'; + i = strspn(end, delim); + end += i; + } + *tok = end; + return start; +} + +/*****************************************************************************/ + +static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, + const char *delim, const char *src, va_list args) +{ + va_list ap; + char *dest, *dp; + const char *str; + int sepLen, addBytes, required; + + mprAssert(destp); + mprAssert(destMax > 0); + mprAssert(src); + + dest = *destp; + sepLen = (delim) ? strlen(delim) : 0; + +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + addBytes = 0; + str = src; + while (str) { + addBytes += strlen(str) + sepLen; + str = va_arg(ap, const char*); + } + + if (existingLen > 0) { + addBytes += sepLen; + } + required = existingLen + addBytes + 1; + if (required >= destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + + if (alloc) { + if (dest == 0) { + dest = (char*) mprMalloc(required); + } else { + dest = (char*) mprRealloc(dest, required); + } + } else { + dest = (char*) *destp; + } + + dp = &dest[existingLen]; + if (delim) { + strcpy(dp, delim); + dp += sepLen; + } + + if (addBytes > 0) { +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + str = src; + while (str) { + strcpy(dp, str); + dp += strlen(str); + str = va_arg(ap, char*); + if (delim && str) { + strcpy(dp, delim); + dp += sepLen; + } + } + } else if (dest == 0) { + dest = (char*) mprMalloc(1); + } + *dp = '\0'; + + *destp = dest; + mprAssert(dp < &dest[required]); + return required - 1; +} + +/*****************************************************************************/ + +int mprReallocStrcat(char **destp, int destMax, int existingLen, + const char *delim, const char *src,...) +{ + va_list ap; + int rc; + + va_start(ap, src); + rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); + va_end(ap); + return rc; +} + +/*****************************************************************************/ +/* + * Return the directory portion of a pathname into the users buffer. + */ + +int mprGetDirName(char *buf, int bufsize, char *path) +{ + char *cp; + int dlen; + + mprAssert(path); + mprAssert(buf); + mprAssert(bufsize > 0); + + cp = strrchr(path, '/'); + if (cp == 0) { +#if WIN + cp = strrchr(path, '\\'); + if (cp == 0) +#endif + { + buf[0] = '\0'; + return 0; + } + } + + if (cp == path && cp[1] == '\0') { + strcpy(buf, "."); + return 0; + } + + dlen = cp - path; + if (dlen < bufsize) { + if (dlen == 0) { + dlen++; + } + mprMemcpy(buf, bufsize, path, dlen); + buf[dlen] = '\0'; + return 0; + } + return MPR_ERR_WONT_FIT; +} + +/*****************************************************************************/ + +int mprStrcpy(char *dest, int destMax, const char *src) +{ + int len; + + mprAssert(dest); + mprAssert(destMax > 0); + mprAssert(src); + + len = strlen(src); + if (len >= destMax && len > 0) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (len > 0) { + memcpy(dest, src, len); + dest[len] = '\0'; + } else { + *dest = '\0'; + len = 0; + } + return len; +} + +/*****************************************************************************/ + +int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) +{ + mprAssert(dest); + mprAssert(destMax > nbytes); + mprAssert(src); + mprAssert(nbytes > 0); + + if (nbytes > destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (nbytes > 0) { + memcpy(dest, src, nbytes); + return nbytes; + } else { + return 0; + } +} + +/*****************************************************************************/ +#else +void miniMprDummy() {} +#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/miniMpr.h b/source4/lib/ejs/miniMpr.h new file mode 100644 index 0000000000..b34fb2e293 --- /dev/null +++ b/source4/lib/ejs/miniMpr.h @@ -0,0 +1,290 @@ +/* + * @file miniMpr.h + * @brief Mini Mbedthis Portable Runtime (MPR) Environment. + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +#ifndef _h_MINI_MPR +#define _h_MINI_MPR 1 + +/********************************** Includes **********************************/ +/* + * Find out about our configuration + */ +#ifndef _INCLUDES_H + #include "includes.h" +#endif + +/* allow this library to use strcpy() */ +#undef strcpy + #include "config.h" + +#if BLD_APPWEB + /* + * If building within AppWeb, use the full MPR + */ + #include "mpr.h" +#else + + #include + #include + #include + #include + #include + #include + #include + +#if !WIN + #include +#endif + +#if CE + #include + #include "CE/wincompat.h" +#endif + +#if LYNX + #include +#endif + +#if QNX4 + #include +#endif + +/********************************** Defines ***********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if BLD_FEATURE_SQUEEZE +/// +/// Reasonable length of a file path name to use in most cases where you know +/// the expected file name and it is certain to be less than this limit. +/// +#define MPR_MAX_FNAME 128 +#define MPR_MAX_STRING 512 +#define MPR_DEFAULT_HASH_SIZE 23 // Default size of hash table index +#define MPR_MAX_HEAP_SIZE (32 * 1024) +#else +#define MPR_MAX_FNAME 256 +#define MPR_MAX_STRING 4096 +#define MPR_DEFAULT_HASH_SIZE 43 // Default size of hash table index +#define MPR_MAX_HEAP_SIZE (64 * 1024) +#endif + +/* + * Useful for debugging + */ +#define MPR_L __FILE__, __LINE__ + +#if BLD_FEATURE_ASSERT +#define mprAssert(C) \ + if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) +#else + #define mprAssert(C) if (1) ; else +#endif + +/// +/// Standard MPR return and error codes +/// +#define MPR_ERR_BASE (-200) ///< Error code +#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) ///< Error code +#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) ///< Error code +#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) ///< Error code +#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) ///< Error code +#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) ///< Error code +#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) ///< Error code +#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) ///< Error code +#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) ///< Error code +#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) ///< Error code +#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) ///< Error code +#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) ///< Error code +#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) ///< Error code +#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) ///< Error code +#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) ///< Error code +#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) ///< Error code +#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) ///< Error code +#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) ///< Error code +#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) ///< Error code +#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) ///< Error code +#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) ///< Error code +#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) ///< Error code +#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) ///< Error code +#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) ///< Error code +#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) ///< Error code +#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) ///< Error code +#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) ///< Error code +#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) ///< Error code +#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) ///< Error code +#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) ///< Error code +#define MPR_ERR_MAX (MPR_ERR_BASE - 30) ///< Error code + +// +// Standard error severity and trace levels. These are ored with the error +// severities below. The MPR_LOG_MASK is used to extract the trace level +// from a flags word. We expect most apps to run with level 2 trace. +// +#define MPR_FATAL 0 ///< Fatal error. Cant continue. +#define MPR_ERROR 1 ///< Hard error +#define MPR_WARN 2 ///< Soft warning +#define MPR_CONFIG 2 ///< Essential configuration settings +#define MPR_INFO 3 ///< Informational only +#define MPR_DEBUG 4 ///< Debug information +#define MPR_VERBOSE 9 ///< Highest level of trace +#define MPR_LOG_MASK 0xf ///< Level mask + +// +// Error flags. Specify where the error should be sent to. Note that the +// product.xml setting "headless" will modify how errors are reported. +// Assert errors are trapped when in DEV mode. Otherwise ignored. +// +#define MPR_TRAP 0x10 ///< Assert error -- trap in debugger +#define MPR_LOG 0x20 ///< Log the error in the O/S event log +#define MPR_USER 0x40 ///< Display to the user +#define MPR_ALERT 0x80 ///< Send a management alert +#define MPR_TRACE 0x100 ///< Trace + +// +// Error format flags +// +#define MPR_RAW 0x200 // Raw trace output + +// +// Error line number information +// +#define MPR_L __FILE__, __LINE__ + +typedef char* MprStr; + +#ifndef __cplusplus +typedef unsigned char uchar; +typedef int bool; +#endif + +/* + * Porters: put other operating system type defines here + */ +#if WIN + typedef unsigned int uint; + typedef __int64 int64; + typedef unsigned __int64 uint64; +#else +#define O_BINARY 0 +#ifndef uint + #define uint unsigned +#endif + __extension__ typedef long long int int64; + __extension__ typedef unsigned long long int uint64; +#endif + +/* + * Flexible array data type + */ +typedef struct { + int max; /* Size of the handles array */ + int used; /* Count of used entries in handles */ + void **handles; +} MprArray; + +#if BLD_FEATURE_SQUEEZE +#define MPR_ARRAY_INCR 8 +#else +#define MPR_ARRAY_INCR 16 +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/********************************* Prototypes *********************************/ +/* + * If running in the GoAhead WebServer, map some MPR routines to WebServer + * equivalents. + */ + +#if BLD_GOAHEAD_WEBSERVER +#include "uemf.h" +#define mprMalloc(size) balloc(B_L, size) +#define mprFree(ptr) bfreeSafe(B_L, ptr) +#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) +#define mprStrdup(ptr) bstrdup(B_L, ptr) +#define mprAllocSprintf fmtAlloc +#define mprAllocVsprintf fmtValloc +#define mprSprintf fmtStatic +#define mprItoa stritoa +#define mprLog trace +#define mprBreakpoint(file, line, cond) \ + error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) + +#else /* !BLD_GOAHEAD_WEBSERVER */ +//#define mprMalloc malloc +#define mprSprintf snprintf +#define mtVsprintf vsnprintf +extern void *mprMalloc(uint size); +extern void *mprRealloc(void *ptr, uint size); +extern void mprFree(void *ptr); +extern char *mprStrdup(const char *str); +extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, + va_list args) PRINTF_ATTRIBUTE(3,0); +extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +extern char *mprItoa(int num, char *buf, int width); +extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern void mprBreakpoint(const char *file, int line, const char *msg); +#endif /* BLD_GOAHEAD_WEBSERVER */ + +extern MprArray *mprCreateArray(void); +extern void mprDestroyArray(MprArray *array); +extern int mprAddToArray(MprArray *array, void *item); +extern int mprRemoveFromArray(MprArray *array, int idx); +extern char *mprStrTok(char *str, const char *delim, char **tok); + +extern int mprGetDirName(char *buf, int bufsize, char *path); +extern int mprReallocStrcat(char **dest, int max, int existingLen, + const char *delim, const char *src, ...); +extern int mprStrcpy(char *dest, int destMax, const char *src); +extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); + +extern void mprSetCtx(void *ctx); + +#ifdef __cplusplus +} +#endif +#endif /* !BLD_APPWEB */ +#endif /* _h_MINI_MPR */ + +/*****************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/mprOs.h b/source4/lib/ejs/mprOs.h new file mode 100644 index 0000000000..c88a3e3c43 --- /dev/null +++ b/source4/lib/ejs/mprOs.h @@ -0,0 +1,627 @@ +/// +/// @file mprOs.h +/// @brief Include O/S headers and smooth out per-O/S differences +// @copy default +// +// Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. +// +// This software is distributed under commercial and open source licenses. +// You may use the GPL open source license described below or you may acquire +// a commercial license from Mbedthis Software. You agree to be fully bound +// by the terms of either license. Consult the LICENSE.TXT distributed with +// this software for full details. +// +// This software is open source; 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 (at your +// option) any later version. See the GNU General Public License for more +// details at: http://www.mbedthis.com/downloads/gplLicense.html +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// This GPL license does NOT permit incorporating this software into +// proprietary programs. If you are unable to comply with the GPL, you must +// acquire a commercial license to use this software. Commercial licenses +// for this software and support services are available from Mbedthis +// Software at http://www.mbedthis.com +// +// @end +//////////////////////////////// Documentation ///////////////////////////////// +/// +/// This header is part of the Mbedthis Portable Runtime and aims to include +/// all necessary O/S headers and to unify the constants and declarations +/// required by Mbedthis products. It can be included by C or C++ programs. +/// +//////////////////////////////////////////////////////////////////////////////// + +#error foo + +blah blah; + +#ifndef _h_MPR_OS_HDRS +#define _h_MPR_OS_HDRS 1 + +#include "lib/ejs/config.h" + +////////////////////////////////// CPU Families //////////////////////////////// +// +// Porters, add your CPU families here and update configure code. +// +#define MPR_CPU_UNKNOWN 0 +#define MPR_CPU_IX86 1 +#define MPR_CPU_PPC 2 +#define MPR_CPU_SPARC 3 +#define MPR_CPU_XSCALE 4 +#define MPR_CPU_ARM 5 +#define MPR_CPU_MIPS 6 +#define MPR_CPU_68K 7 +#define MPR_CPU_SIMNT 8 // VxWorks NT simulator +#define MPR_CPU_SIMSPARC 9 // VxWorks sparc simulator + +////////////////////////////////// O/S Includes //////////////////////////////// + +#if LINUX || SOLARIS + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + +#if LINUX + #include +#endif + +#if SOLARIS + #include +#endif + +#if BLD_FEATURE_FLOATING_POINT + #define __USE_ISOC99 1 + #include + #include +#endif + +#endif // LINUX || SOLARIS + +#if VXWORKS + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #if BLD_FEATURE_FLOATING_POINT + #include + #define __USE_ISOC99 1 + #include + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + +#endif // VXWORKS + +#if MACOSX + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif // MACOSX + +#if WIN + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + #if BLD_FEATURE_FLOATING_POINT + #include + #endif + #include + #include + #include +#endif // WIN + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// General Defines /////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#define MAXINT INT_MAX +#define BITS(type) (BITSPERBYTE * (int) sizeof(type)) + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +// +// Set FD_SETSIZE to the maximum number of files (sockets) that you want to +// support. It is used in select.cpp. +// +// #ifdef FD_SETSIZE +// #undef FD_SETSIZE +// #endif +// #define FD_SETSIZE 128 +// + +typedef char *MprStr; // Used for dynamic strings + +//////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// Linux Defines //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#if LINUX + typedef unsigned char uchar; + +#if BLD_FEATURE_INT64 + __extension__ typedef long long int int64; + __extension__ typedef unsigned long long int uint64; + #define INT64(x) (x##LL) +#endif + + #define closesocket(x) close(x) + #define MPR_BINARY "" + #define MPR_TEXT "" + #define O_BINARY 0 + #define O_TEXT 0 + #define SOCKET_ERROR -1 + #define MPR_DLL_EXT ".so" + +#if BLD_FEATURE_FLOATING_POINT + #define MAX_FLOAT MAXFLOAT +#endif + + #if BLD_FEATURE_MALLOC + // + // PORTERS: You will need add assembler code for your architecture here + // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + // + #if UNUSED + #define MPR_GET_RETURN(ip) __builtin_return_address(0) + #else + #if BLD_HOST_CPU_ARCH == MPR_CPU_IX86 + #define MPR_GET_RETURN(ip) \ + asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \ + "=g" (ip) : \ + : "eax") + #endif + #endif // UNUSED + #endif // BLD_FEATURE_MALLOC + +#if FUTURE +// #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) +// extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); + + // + // Atomic functions + // + typedef struct { volatile int counter; } mprAtomic_t; + + #if BLD_FEATURE_MULTITHREAD + #define LOCK "lock ; " + #else + #define LOCK "" + #endif + + static __inline__ void mprAtomicInc(mprAtomic_t* v) { + __asm__ __volatile__( + LOCK "incl %0" + :"=m" (v->counter) + :"m" (v->counter)); + } + + static __inline__ void mprAtomicDec(mprAtomic_t* v) { + __asm__ __volatile__( + LOCK "decl %0" + :"=m" (v->counter) + :"m" (v->counter)); + } +#endif // FUTURE + +#endif // LINUX + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// VxWorks Defines /////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#if VXWORKS + + typedef unsigned char uchar; + typedef unsigned int uint; + typedef unsigned long ulong; + + #define HAVE_SOCKLEN_T + typedef int socklen_t; + +#if BLD_FEATURE_INT64 + typedef long long int int64; + typedef unsigned long long int uint64; + #define INT64(x) (x##LL) +#endif + + #define closesocket(x) close(x) + #define getpid() taskIdSelf() + #define MPR_BINARY "" + #define MPR_TEXT "" + #define O_BINARY 0 + #define O_TEXT 0 + #define SOCKET_ERROR -1 + #define MPR_DLL_EXT ".so" + +#if BLD_FEATURE_FLOATING_POINT + #define MAX_FLOAT FLT_MAX +#endif + + #undef R_OK + #define R_OK 4 + #undef W_OK + #define W_OK 2 + #undef X_OK + #define X_OK 1 + #undef F_OK + #define F_OK 0 + + #define MSG_NOSIGNAL 0 + + extern int access(char *path, int mode); + extern int sysClkRateGet(); + + #if BLD_FEATURE_MALLOC + // + // PORTERS: You will need add assembler code for your architecture here + // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + // + #if UNUSED + #define MPR_GET_RETURN(ip) __builtin_return_address(0) + #else + #if BLD_HOST_CPU_ARCH == MPR_CPU_IX86 + #define MPR_GET_RETURN(ip) \ + asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \ + "=g" (ip) : \ + : "eax") + #endif + #endif // UNUSED + #endif // BLD_FEATURE_MALLOC +#endif // VXWORKS + +//////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// MacOsx Defines /////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +#if MACOSX + typedef unsigned long ulong; + typedef unsigned char uchar; + +#if BLD_FEATURE_INT64 + __extension__ typedef long long int int64; + __extension__ typedef unsigned long long int uint64; + #define INT64(x) (x##LL) +#endif + #define closesocket(x) close(x) + #define MPR_BINARY "" + #define MPR_TEXT "" + #define O_BINARY 0 + #define O_TEXT 0 + #define SOCKET_ERROR -1 + #define MPR_DLL_EXT ".dylib" + #define MSG_NOSIGNAL 0 + #define __WALL 0x40000000 + #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE + +#if BLD_FEATURE_FLOATING_POINT + #define MAX_FLOAT MAXFLOAT +#endif + + #if MPR_FEATURE_MALLOC + // + // PORTERS: You will need add assembler code for your architecture here + // only if you want to use the fast malloc (MPR_FEATURE_MALLOC) + // + #define MPR_GET_RETURN(ip) __builtin_return_address + #endif + +#if FUTURE +// #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) +// extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); + + // + // Atomic functions + // + typedef struct { volatile int counter; } mprAtomic_t; + + #if MPR_FEATURE_MULTITHREAD + #define LOCK "lock ; " + #else + #define LOCK "" + #endif + + static __inline__ void mprAtomicInc(mprAtomic_t* v) { + __asm__ __volatile__( + LOCK "incl %0" + :"=m" (v->counter) + :"m" (v->counter)); + } + + static __inline__ void mprAtomicDec(mprAtomic_t* v) { + __asm__ __volatile__( + LOCK "decl %0" + :"=m" (v->counter) + :"m" (v->counter)); + } +#endif +#endif // MACOSX + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// Windows Defines /////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#if WIN + typedef unsigned char uchar; + typedef unsigned int uint; + typedef unsigned long ulong; + typedef unsigned short ushort; + +#if BLD_FEATURE_INT64 + typedef __int64 int64; + typedef unsigned __int64 uint64; + #define INT64(x) (x##i64) +#endif + + typedef int uid_t; + typedef void *handle; + typedef char *caddr_t; + typedef long pid_t; + typedef int gid_t; + typedef ushort mode_t; + typedef void *siginfo_t; + + #define HAVE_SOCKLEN_T + typedef int socklen_t; + + #undef R_OK + #define R_OK 4 + #undef W_OK + #define W_OK 2 + #undef X_OK + #define X_OK 1 + #undef F_OK + #define F_OK 0 + + #ifndef EADDRINUSE + #define EADDRINUSE 46 + #endif + #ifndef EWOULDBLOCK + #define EWOULDBLOCK EAGAIN + #endif + #ifndef ENETDOWN + #define ENETDOWN 43 + #endif + #ifndef ECONNRESET + #define ECONNRESET 44 + #endif + #ifndef ECONNREFUSED + #define ECONNREFUSED 45 + #endif + + #define MSG_NOSIGNAL 0 + #define MPR_BINARY "b" + #define MPR_TEXT "t" + +#if BLD_FEATURE_FLOATING_POINT + #define MAX_FLOAT DBL_MAX +#endif + +#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE +#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 +#endif + + #define access _access + #define close _close + #define fileno _fileno + #define fstat _fstat + #define getpid _getpid + #define open _open + #define putenv _putenv + #define read _read + #define stat _stat + #define umask _umask + #define unlink _unlink + #define write _write + #define strdup _strdup + #define lseek _lseek + + #define mkdir(a,b) _mkdir(a) + #define rmdir(a) _rmdir(a) + + #if BLD_FEATURE_MALLOC + // + // PORTERS: You will need add assembler code for your architecture here + // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + // + #if MPR_CPU_IX86 + #define MPR_GET_RETURN(ip) \ + __asm { mov eax, 4[ebp] } \ + __asm { mov ip, eax } + #endif + #endif + + #define MPR_DLL_EXT ".dll" + + extern void srand48(long); + extern long lrand48(void); + extern long ulimit(int, ...); + extern long nap(long); + extern uint sleep(unsigned int secs); + extern uid_t getuid(void); + extern uid_t geteuid(void); + +#endif // WIN + +//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Solaris Defines //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#if SOLARIS + typedef unsigned char uchar; + +#if BLD_FEATURE_INT64 + typedef long long int int64; + typedef unsigned long long int uint64; + #define INT64(x) (x##LL) +#endif + + #define closesocket(x) close(x) + #define MPR_BINARY "" + #define MPR_TEXT "" + #define O_BINARY 0 + #define O_TEXT 0 + #define SOCKET_ERROR -1 + #define MPR_DLL_EXT ".so" + #define MSG_NOSIGNAL 0 + #define INADDR_NONE ((in_addr_t) 0xffffffff) + #define __WALL 0 + #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE + +#if BLD_FEATURE_FLOATING_POINT + #define MAX_FLOAT MAXFLOAT +#endif + +#endif // SOLARIS + +//////////////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +} +#endif + +#endif // _h_MPR_OS_HDRS + +// +// Local variables: +// tab-width: 4 +// c-basic-offset: 4 +// End: +// vim:tw=78 +// vim600: sw=4 ts=4 fdm=marker +// vim<600: sw=4 ts=4 +// diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c new file mode 100644 index 0000000000..5df306797d --- /dev/null +++ b/source4/lib/ejs/var.c @@ -0,0 +1,2161 @@ +/* + * @file var.c + * @brief MPR Universal Variable Type + * @overview + * + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ + +/* + * This module is NOT multithreaded. + * + * Properties are variables that are stored in an object type variable. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. + */ + +/********************************** Includes **********************************/ + +#include "lib/ejs/var.h" + +/*********************************** Locals ***********************************/ +#if VAR_DEBUG + +static MprProperties objectList; /* Dummy head of objects list */ +static int objectCount = -1; /* Count of objects */ + +#endif +/***************************** Forward Declarations ***************************/ + +static int adjustRefCount(MprProperties *pp, int adj); +static int adjustVarRefCount(MprVar *vp, int adj); +static MprVar *allocProperty(const char *propertyName); +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); +static MprProperties + *createProperties(const char *name, int hashSize); +static bool freeVar(MprVar *vp, int force); +static bool freeVarStorage(MprVar *vp, int force); +static MprVar *getObjChain(MprProperties *pp, const char *property); +static int hash(MprProperties *pp, const char *property); +static bool releaseProperties(MprProperties *pp, int force); + +/*********************************** Code *************************************/ +/* + * Destroy a variable and all referenced variables. Release any referenced + * object regardless of whether other users still have references. Be VERY + * careful using this routine. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyAllVars(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all vars. + */ + return freeVar(vp, 1); +} + +/******************************************************************************/ +/* + * Destroy a variable. Release any referenced object (destroy if no other + * users are referencing). + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyVar(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all that have no other + * references. + */ + return freeVar(vp, 0); +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVar(MprVar *vp, int force) +{ + bool freed; + + mprAssert(vp); + + freed = freeVarStorage(vp, force); + + mprFree(vp->name); + mprFree(vp->fullName); + + if (vp->allocatedVar) { + mprFree(vp); + } else { + vp->name = 0; + vp->fullName = 0; + vp->type = MPR_TYPE_UNDEFINED; + } + return freed; +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVarStorage(MprVar *vp, int force) +{ + MprArray *argList; + bool freed; + int i; + + freed = 1; + mprAssert(vp); + + switch (vp->type) { + default: + break; + + case MPR_TYPE_STRING: + if (vp->allocatedData && vp->string != 0) { + mprFree(vp->string); + vp->string = 0; + vp->allocatedData = 0; + } + break; + + case MPR_TYPE_OBJECT: +#if VAR_DEBUG + /* + * Recurse through all properties and release / delete. Release the + * properties hash table. + */ + if (vp->properties->refCount > 1) { + mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } else { + mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } +#endif + if (vp->allocatedData) { + freed = releaseProperties(vp->properties, force); + } + vp->properties = 0; + break; + + case MPR_TYPE_FUNCTION: + if (vp->allocatedData) { + argList = vp->function.args; + for (i = 0; i < argList->max; i++) { + if (argList->handles[i] != 0) { + mprFree(argList->handles[i]); + } + } + mprDestroyArray(argList); + vp->function.args = 0; + mprFree(vp->function.body); + vp->function.body = 0; + } + break; + } + + vp->type = MPR_TYPE_UNDEFINED; + return freed; +} + +/******************************************************************************/ +/* + * Adjust the object reference count and return the currrent count of + * users. + */ + +static int adjustVarRefCount(MprVar *vp, int adj) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, adj); +} + +/******************************************************************************/ +/* + * Get the object reference count + */ + +int mprGetVarRefCount(MprVar *vp) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, 0); +} + +/******************************************************************************/ +/* + * Update the variable's name + */ + +void mprSetVarName(MprVar *vp, char *name) +{ + mprAssert(vp); + + mprFree(vp->name); + vp->name = mprStrdup(name); +} + +/******************************************************************************/ +/* + * Append to the variable's full name + */ + +void mprSetVarFullName(MprVar *vp, char *name) +{ +#if VAR_DEBUG + mprAssert(vp); + + mprFree(vp->fullName); + vp->fullName = mprStrdup(name); + if (vp->type == MPR_TYPE_OBJECT) { + if (strcmp(vp->properties->name, "this") == 0) { + mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); + } + } +#endif +} + +/******************************************************************************/ +/* + * Make a var impervious to recursive forced deletes. + */ + +void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) +{ + mprAssert(vp); + + if (vp->type == MPR_TYPE_OBJECT && vp->properties) { + vp->properties->deleteProtect = deleteProtect; + } +} + +/******************************************************************************/ +/* + * Make a variable readonly. Can still be deleted. + */ + +void mprSetVarReadonly(MprVar *vp, int readonly) +{ + mprAssert(vp); + + vp->readonly = readonly; +} + +/******************************************************************************/ + +MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) +{ + MprVarTrigger oldTrigger; + + mprAssert(vp); + mprAssert(fn); + + oldTrigger = vp->trigger; + vp->trigger = fn; + return oldTrigger; +} + +/******************************************************************************/ + +MprType mprGetVarType(MprVar *vp) +{ + mprAssert(vp); + + return vp->type; +} + +/******************************************************************************/ +/********************************** Properties ********************************/ +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. + */ + +MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, MprVar *newValue) +{ + MprVar *prop, *last; + int bucketIndex; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + /* + * See if property already exists and locate the bucket to hold the + * property reference. + */ + last = 0; + bucketIndex = hash(obj->properties, propertyName); + prop = obj->properties->buckets[bucketIndex]; + + /* + * Find the property in the hash chain if it exists + */ + for (last = 0; prop; last = prop, prop = prop->forw) { + if (prop->name[0] == propertyName[0] && + strcmp(prop->name, propertyName) == 0) { + break; + } + } + + if (prop) { + // FUTURE -- remove. Just for debug. + mprAssert(prop == 0); + mprLog(0, "Attempting to create property %s in object %s\n", + propertyName, obj->name); + return 0; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, + newValue, 0) == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Create a new property + */ + prop = allocProperty(propertyName); + if (prop == 0) { + mprAssert(prop); + return 0; + } + + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + + prop->bucketIndex = bucketIndex; + if (last) { + last->forw = prop; + } else { + obj->properties->buckets[bucketIndex] = prop; + } + prop->parentProperties = obj->properties; + + /* + * Update the item counts + */ + obj->properties->numItems++; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems++; + } + + return prop; +} + +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. Same as + * mprCreateProperty except that the new value is passed by value rather than + * by pointer. + */ + +MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, MprVar newValue) +{ + return mprCreateProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Create a new property + */ + +static MprVar *allocProperty(const char *propertyName) +{ + MprVar *prop; + + prop = (MprVar*) mprMalloc(sizeof(MprVar)); + if (prop == 0) { + mprAssert(prop); + return 0; + } + memset(prop, 0, sizeof(MprVar)); + prop->allocatedVar = 1; + prop->name = mprStrdup(propertyName); + prop->forw = (MprVar*) 0; + + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it doesn not already exist. + */ + +MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) +{ + MprVar *prop, triggerValue; + int rc; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(0); + return 0; + } + + prop = mprGetProperty(obj, propertyName, 0); + if (prop == 0) { + return mprCreateProperty(obj, propertyName, newValue); + } + + if (obj->trigger) { + /* + * Call the trigger before the update and pass it the new value. + */ + triggerValue = *newValue; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + /* + * Trigger must copy to triggerValue a variable that is not + * a structure copy of the existing data. + */ + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return prop; + } + } + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it does not already exist. Same as mprSetProperty except that the + * new value is passed by value rather than by pointer. + */ + +MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, MprVar newValue) +{ + return mprSetProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Delete a property from this object + */ + +int mprDeleteProperty(MprVar *obj, const char *property) +{ + MprVar *prop, *last; + char *cp; + int bucketIndex; + + mprAssert(obj); + mprAssert(property && *property); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + last = 0; + bucketIndex = hash(obj->properties, property); + if ((prop = obj->properties->buckets[bucketIndex]) != 0) { + for ( ; prop; prop = prop->forw) { + cp = prop->name; + if (cp[0] == property[0] && strcmp(cp, property) == 0) { + break; + } + last = prop; + } + } + if (prop == (MprVar*) 0) { + mprAssert(prop); + return MPR_ERR_NOT_FOUND; + } + if (prop->readonly) { + mprAssert(! prop->readonly); + return MPR_ERR_READ_ONLY; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) + == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + } + } + + if (last) { + last->forw = prop->forw; + } else { + obj->properties->buckets[bucketIndex] = prop->forw; + } + + obj->properties->numItems--; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems--; + } + + mprDestroyVar(prop); + + return 0; +} + +/******************************************************************************/ +/* + * Find a property in an object and return a pointer to it. If a value arg + * is supplied, then copy the data into the var. + */ + +MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) +{ + MprVar *prop, triggerValue; + int rc; + + if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || + *property == '\0') { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + + for (prop = getObjChain(obj->properties, property); prop; + prop = prop->forw) { + if (prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { + break; + } + } + if (prop == 0) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + if (value) { + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + /* + * Pass the trigger the current read value and may receive + * a new value. + */ + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + } + } + /* + * Clone. No copy. + */ + *value = *prop; + } + return prop; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns the property's value. It does not + * copy object/string data but returns a pointer directly into the variable. + * The caller does not and should not call mprDestroy on the returned value. + * If value is null, just read the property and run triggers. + */ + +int mprReadProperty(MprVar *prop, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + if (value) { + *value = *prop; + + /* + * Just so that if the user calls mprDestroyVar on value, it will do no + * harm. + */ + value->allocatedVar = 0; + value->allocatedData = 0; + } + return 0; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns a copy of the property variable. + * However, if the property is an object or string, it returns a copy of the + * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, + * then the underlying objects and strings data will be copied as well. If + * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If + * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the + * user must call mprDestroyVar to free resources. This routine will run any + * registered triggers which may modify the value the user receives (without + * updating the properties real value). + * + * WARNING: the args are reversed to most other APIs. This conforms to the + * strcpy(dest, src) standard instead. + */ + +int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + mprAssert(dest); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, copyDepth); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + mprCopyVar(dest, prop, copyDepth); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWriteProperty(MprVar *vp, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(vp); + mprAssert(value); + + if (vp->readonly) { + return MPR_ERR_READ_ONLY; + } + + if (vp->trigger) { + triggerValue = *value; + + rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + /* Fall through */ + } + + copyVarCore(vp, value, MPR_SHALLOW_COPY); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWritePropertyValue(MprVar *vp, MprVar value) +{ + mprAssert(vp); + + return mprWriteProperty(vp, &value); +} + +/******************************************************************************/ +/* + * Get the count of properties. + */ + +int mprGetPropertyCount(MprVar *vp, int includeFlags) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + return 0; + } + if (includeFlags == MPR_ENUM_DATA) { + return vp->properties->numDataItems; + } else { + return vp->properties->numItems; + } +} + +/******************************************************************************/ +/* + * Get the first property in an object. Used for walking all properties in an + * object. + */ + +MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) +{ + MprVar *prop; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + for (i = 0; i < (int) obj->properties->hashSize; i++) { + for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { + if (prop) { + if (mprVarIsFunction(prop->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return prop; + } + break; + } + } + return 0; +} + +/******************************************************************************/ +/* + * Get the next property in sequence. + */ + +MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) +{ + MprProperties *properties; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + properties = obj->properties; + + if (last->forw) { + return last->forw; + } + + for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { + for (last = properties->buckets[i]; last; last = last->forw) { + if (mprVarIsFunction(last->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return last; + } + } + return 0; +} + +/******************************************************************************/ +/************************** Internal Support Routines *************************/ +/******************************************************************************/ +/* + * Create an hash table to hold and index properties. Properties are just + * variables which may contain primitive data types, functions or other + * objects. The hash table is the essence of an object. HashSize specifies + * the size of the hash table to use and should be a prime number. + */ + +static MprProperties *createProperties(const char *name, int hashSize) +{ + MprProperties *pp; + + if (hashSize < 7) { + hashSize = 7; + } + if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { + mprAssert(0); + return 0; + } + mprAssert(pp); + memset(pp, 0, sizeof(MprProperties)); + + pp->numItems = 0; + pp->numDataItems = 0; + pp->hashSize = hashSize; + pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); + mprAssert(pp->buckets); + memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); + pp->refCount = 1; + +#if VAR_DEBUG + if (objectCount == -1) { + objectCount = 0; + objectList.next = objectList.prev = &objectList; + } + + mprStrcpy(pp->name, sizeof(pp->name), name); + pp->next = &objectList; + pp->prev = objectList.prev; + objectList.prev->next = pp; + objectList.prev = pp; + objectCount++; +#endif + return pp; +} + +/******************************************************************************/ +/* + * Release an object's properties hash table. If this is the last person + * using it, free it. Return TRUE if the object is released. + */ + +static bool releaseProperties(MprProperties *obj, int force) +{ + MprProperties *pp; + MprVar *prop, *forw; + int i; + + mprAssert(obj); + mprAssert(obj->refCount > 0); + +#if VAR_DEBUG + /* + * Debug sanity check + */ + mprAssert(obj->refCount < 20); +#endif + + if (--obj->refCount > 0 && !force) { + return 0; + } + +#if VAR_DEBUG + mprAssert(obj->prev); + mprAssert(obj->next); + mprAssert(obj->next->prev); + mprAssert(obj->prev->next); + obj->next->prev = obj->prev; + obj->prev->next = obj->next; + objectCount--; +#endif + + for (i = 0; i < (int) obj->hashSize; i++) { + for (prop = obj->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->type == MPR_TYPE_OBJECT) { + + if (prop->properties == obj) { + /* Self reference */ + continue; + } + pp = prop->properties; + if (pp->visited) { + continue; + } + + pp->visited = 1; + if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { + pp->visited = 0; + } + + } else { + freeVar(prop, force); + } + } + } + + mprFree((void*) obj->buckets); + mprFree((void*) obj); + + return 1; +} + +/******************************************************************************/ +/* + * Adjust the reference count + */ + +static int adjustRefCount(MprProperties *pp, int adj) +{ + mprAssert(pp); + + /* + * Debug sanity check + */ + mprAssert(pp->refCount < 20); + + return pp->refCount += adj; +} + +/******************************************************************************/ +#if VAR_DEBUG +/* + * Print objects held + */ + +void mprPrintObjects(char *msg) +{ + MprProperties *pp, *np; + MprVar *prop, *forw; + char *buf; + int i; + + mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); + pp = objectList.next; + while (pp != &objectList) { + mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", + pp->name, pp, pp->refCount, pp->numItems); + for (i = 0; i < (int) pp->hashSize; i++) { + for (prop = pp->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->properties == pp) { + /* Self reference */ + continue; + } + mprVarToString(&buf, MPR_MAX_STRING, 0, prop); + if (prop->type == MPR_TYPE_OBJECT) { + np = objectList.next; + while (np != &objectList) { + if (prop->properties == np) { + break; + } + np = np->next; + } + if (prop->properties == np) { + mprLog(7, " %s: OBJECT 0x%x, <%s>\n", + prop->name, prop->properties, prop->fullName); + } else { + mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", + prop->name, buf, prop->fullName); + } + } else { + mprLog(7, " %s: <%s> = %s\n", prop->name, + prop->fullName, buf); + } + mprFree(buf); + } + } + pp = pp->next; + } +} + +/******************************************************************************/ + +void mprPrintObjRefCount(MprVar *vp) +{ + mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, + vp->properties->refCount); +} + +#endif +/******************************************************************************/ +/* + * Get the bucket chain containing a property. + */ + +static MprVar *getObjChain(MprProperties *obj, const char *property) +{ + mprAssert(obj); + + return obj->buckets[hash(obj, property)]; +} + +/******************************************************************************/ +/* + * Fast hash. The history of this algorithm is part of lost computer science + * folk lore. + */ + +static int hash(MprProperties *pp, const char *property) +{ + uint sum; + + mprAssert(pp); + mprAssert(property); + + sum = 0; + while (*property) { + sum += (sum * 33) + *property++; + } + + return sum % pp->hashSize; +} + +/******************************************************************************/ +/*********************************** Constructors *****************************/ +/******************************************************************************/ +/* + * Initialize an undefined value. + */ + +MprVar mprCreateUndefinedVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_UNDEFINED; + return v; +} + +/******************************************************************************/ +/* + * Initialize an null value. + */ + +MprVar mprCreateNullVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_NULL; + return v; +} + +/******************************************************************************/ + +MprVar mprCreateBoolVar(bool value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_BOOL; + v.boolean = value; + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_CFUNCTION; + v.cFunction.fn = fn; + v.cFunction.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING_CFUNCTION; + v.cFunctionWithStrings.fn = fn; + v.cFunctionWithStrings.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Initialize a floating value. + */ + +MprVar mprCreateFloatVar(double value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FLOAT; + v.floating = value; + return v; +} + +#endif +/******************************************************************************/ +/* + * Initialize an integer value. + */ + +MprVar mprCreateIntegerVar(int value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT; + v.integer = value; + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Initialize a 64-bit integer value. + */ + +MprVar mprCreateInteger64Var(int64 value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT64; + v.integer64 = value; + return v; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Initialize an number variable. Type is defined by configure. + */ + +MprVar mprCreateNumberVar(MprNum value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = BLD_FEATURE_NUM_TYPE_ID; +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + v.integer64 = value; +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + v.float = value; +#else + v.integer = value; +#endif + return v; +} + +/******************************************************************************/ +/* + * Initialize a (bare) JavaScript function. args and body can be null. + */ + +MprVar mprCreateFunctionVar(char *args, char *body, int flags) +{ + MprVar v; + char *cp, *arg, *last; + int aid; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FUNCTION; + v.flags = flags; + + v.function.args = mprCreateArray(); + + if (args) { + args = mprStrdup(args); + arg = mprStrTok(args, ",", &last); + while (arg) { + while (isspace((int) *arg)) + arg++; + for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { + if (!isspace((int) *cp)) { + break; + } + } + cp[1] = '\0'; + + aid = mprAddToArray(v.function.args, mprStrdup(arg)); + arg = mprStrTok(0, ",", &last); + } + mprFree(args); + } + + if (body) { + v.function.body = mprStrdup(body); + } + v.allocatedData = 1; + return v; +} + +/******************************************************************************/ +/* + * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the + * memory allocation for the properties table failed. + */ + +MprVar mprCreateObjVar(const char *name, int hashSize) +{ + MprVar v; + + mprAssert(name && *name); + + memset(&v, 0x0, sizeof(MprVar)); + v.type = MPR_TYPE_OBJECT; + if (hashSize <= 0) { + hashSize = MPR_DEFAULT_HASH_SIZE; + } + v.properties = createProperties(name, hashSize); + if (v.properties == 0) { + /* Indicate failed memory allocation */ + v.type = MPR_TYPE_UNDEFINED; + } + v.allocatedData = 1; + v.name = mprStrdup(name); + mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); + return v; +} + +/******************************************************************************/ +/* + * Initialize a string value. + */ + +MprVar mprCreateStringVar(const char *value, bool allocate) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING; + if (value == 0) { + v.string = ""; + } else if (allocate) { + v.string = mprStrdup(value); + v.allocatedData = 1; + } else { + v.string = value; + } + return v; +} + +/******************************************************************************/ +/* + * Copy an objects core value (only). This preserves the destination object's + * name. This implements copy by reference for objects and copy by value for + * strings and other types. Caller must free dest prior to calling. + */ + +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) +{ + MprVarTrigger saveTrigger; + MprVar *srcProp, *destProp, *last; + char **srcArgs; + int i; + + mprAssert(dest); + mprAssert(src); + + if (dest == src) { + return; + } + + /* + * FUTURE: we should allow read-only triggers where the value is never + * stored in the object. Currently, triggers override the readonly + * status. + */ + + if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { + mprAssert(0); + return; + } + + if (dest->type != MPR_TYPE_UNDEFINED) { + saveTrigger = dest->trigger; + freeVarStorage(dest, 0); + } else { + saveTrigger = 0; + } + + switch (src->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + break; + + case MPR_TYPE_BOOL: + dest->boolean = src->boolean; + break; + + case MPR_TYPE_STRING_CFUNCTION: + dest->cFunctionWithStrings = src->cFunctionWithStrings; + break; + + case MPR_TYPE_CFUNCTION: + dest->cFunction = src->cFunction; + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + dest->floating = src->floating; + break; +#endif + + case MPR_TYPE_INT: + dest->integer = src->integer; + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + dest->integer64 = src->integer64; + break; +#endif + + case MPR_TYPE_OBJECT: + if (copyDepth == MPR_DEEP_COPY) { + + dest->properties = createProperties(src->name, + src->properties->hashSize); + dest->allocatedData = 1; + + for (i = 0; i < (int) src->properties->hashSize; i++) { + last = 0; + for (srcProp = src->properties->buckets[i]; srcProp; + srcProp = srcProp->forw) { + if (srcProp->visited) { + continue; + } + destProp = allocProperty(srcProp->name); + if (destProp == 0) { + mprAssert(destProp); + return; + } + + destProp->bucketIndex = i; + if (last) { + last->forw = destProp; + } else { + dest->properties->buckets[i] = destProp; + } + destProp->parentProperties = dest->properties; + + /* + * Recursively copy the object + */ + srcProp->visited = 1; + copyVarCore(destProp, srcProp, copyDepth); + srcProp->visited = 0; + last = srcProp; + } + } + dest->properties->numItems = src->properties->numItems; + dest->properties->numDataItems = src->properties->numDataItems; + dest->allocatedData = 1; + + } else if (copyDepth == MPR_SHALLOW_COPY) { + dest->properties = src->properties; + adjustVarRefCount(src, 1); + dest->allocatedData = 1; + + } else { + dest->properties = src->properties; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_FUNCTION: + if (copyDepth != MPR_NO_COPY) { + dest->function.args = mprCreateArray(); + srcArgs = (char**) src->function.args->handles; + for (i = 0; i < src->function.args->max; i++) { + if (srcArgs[i]) { + mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); + } + } + dest->function.body = mprStrdup(src->function.body); + dest->allocatedData = 1; + } else { + dest->function.args = src->function.args; + dest->function.body = src->function.body; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_STRING: + if (src->string && copyDepth != MPR_NO_COPY) { + dest->string = mprStrdup(src->string); + dest->allocatedData = 1; + } else { + dest->string = src->string; + dest->allocatedData = 0; + } + break; + } + + dest->type = src->type; + dest->flags = src->flags; + dest->trigger = saveTrigger; + + /* + * Just for safety + */ + dest->spare = 0; +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) +{ + mprAssert(dest); + mprAssert(src); + + copyVarCore(dest, src, copyDepth); + + mprFree(dest->name); + dest->name = mprStrdup(src->name); + +#if VAR_DEBUG + if (src->type == MPR_TYPE_OBJECT) { + + mprFree(dest->fullName); + dest->fullName = mprStrdup(src->fullName); + + mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", + dest->name, dest->fullName, dest->properties, + dest->properties->refCount); + } +#endif +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) +{ + mprAssert(dest); + + mprCopyVar(dest, &src, copyDepth); +} + +/******************************************************************************/ +/* + * Copy an object. This implements copy by reference for objects and copy by + * value for strings and other types. Caller must free dest prior to calling. + */ + +MprVar *mprDupVar(MprVar *src, int copyDepth) +{ + MprVar *dest; + + mprAssert(src); + + dest = (MprVar*) mprMalloc(sizeof(MprVar)); + memset(dest, 0, sizeof(MprVar)); + + mprCopyVar(dest, src, copyDepth); + return dest; +} + +/******************************************************************************/ +/* + * Convert a value to a text based representation of its value + * FUTURE -- conver this to use the format string in all cases. Allow + * arbitrary format strings. + */ + +void mprVarToString(char** out, int size, char *fmt, MprVar *obj) +{ + char *src; + + mprAssert(out); + + *out = NULL; + + if (obj->trigger) { + mprReadProperty(obj, 0); + } + + switch (obj->type) { + case MPR_TYPE_UNDEFINED: + // FUTURE -- spec says convert to "undefined" + *out = mprStrdup(""); + break; + + case MPR_TYPE_NULL: + *out = mprStrdup("null"); + break; + + case MPR_TYPE_BOOL: + if (obj->boolean) { + *out = mprStrdup("true"); + } else { + *out = mprStrdup("false"); + } + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%f", obj->floating); + } else { + mprAllocSprintf(out, size, fmt, obj->floating); + } + break; +#endif + + case MPR_TYPE_INT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%d", obj->integer); + } else { + mprAllocSprintf(out, size, fmt, obj->integer); + } + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + if (fmt == NULL || *fmt == '\0') { +#if BLD_GOAHEAD_WEBSERVER + mprAllocSprintf(out, size, "%d", (int) obj->integer64); +#else + mprAllocSprintf(out, size, "%Ld", obj->integer64); +#endif + } else { + mprAllocSprintf(out, size, fmt, obj->integer64); + } + break; +#endif + + case MPR_TYPE_CFUNCTION: + mprAllocSprintf(out, size, "[C Function]"); + break; + + case MPR_TYPE_STRING_CFUNCTION: + mprAllocSprintf(out, size, "[C StringFunction]"); + break; + + case MPR_TYPE_FUNCTION: + mprAllocSprintf(out, size, "[JavaScript Function]"); + break; + + case MPR_TYPE_OBJECT: + // FUTURE -- really want: [object class: name] + mprAllocSprintf(out, size, "[object %s]", obj->name); + break; + + case MPR_TYPE_STRING: + src = obj->string; + + mprAssert(src); + if (fmt && *fmt) { + mprAllocSprintf(out, size, fmt, src); + + } else if (src == NULL) { + *out = mprStrdup("null"); + + } else { + *out = mprStrdup(src); + } + break; + + default: + mprAssert(0); + } +} + +/******************************************************************************/ +/* + * Parse a string based on formatting instructions and intelligently + * create a variable. + */ + +MprVar mprParseVar(char *buf, MprType preferredType) +{ + MprType type; + char *cp; + + mprAssert(buf); + + if (preferredType == MPR_TYPE_UNDEFINED) { + if (*buf == '-') { + type = MPR_NUM_VAR; + + } else if (!isdigit((int) *buf)) { + if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { + type = MPR_TYPE_BOOL; + } else { + type = MPR_TYPE_STRING; + } + + } else if (isdigit((int) *buf)) { + type = MPR_NUM_VAR; + cp = buf; + if (*cp && tolower(cp[1]) == 'x') { + cp = &cp[2]; + } + for (cp = buf; *cp; cp++) { + if (! isdigit((int) *cp)) { + break; + } + } + + if (*cp != '\0') { +#if BLD_FEATURE_FLOATING_POINT + if (*cp == '.' || tolower(*cp) == 'e') { + type = MPR_TYPE_FLOAT; + } else +#endif + { + type = MPR_NUM_VAR; + } + } + } + } else { + type = preferredType; + } + + switch (type) { + case MPR_TYPE_OBJECT: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + default: + break; + + case MPR_TYPE_BOOL: + return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); + + case MPR_TYPE_INT: + return mprCreateIntegerVar(mprParseInteger(buf)); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return mprCreateInteger64Var(mprParseInteger64(buf)); +#endif + + case MPR_TYPE_STRING: + if (strcmp(buf, "null") == 0) { + return mprCreateNullVar(); + } else if (strcmp(buf, "undefined") == 0) { + return mprCreateUndefinedVar(); + } + + return mprCreateStringVar(buf, 1); + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return mprCreateFloatVar(atof(buf)); +#endif + + } + return mprCreateUndefinedVar(); +} + +/******************************************************************************/ +/* + * Convert the variable to a boolean. Only for primitive types. + */ + +bool mprVarToBool(MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_BOOL: + return vp->boolean; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return (vp->floating != 0 && !mprIsNan(vp->floating)); +#endif + + case MPR_TYPE_INT: + return (vp->integer != 0); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (vp->integer64 != 0); +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return (vp->string[0] != '\0'); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the variable to a floating point number. Only for primitive types. + */ + +double mprVarToFloat(MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1.0 : 0.0; + + case MPR_TYPE_FLOAT: + return vp->floating; + + case MPR_TYPE_INT: + return (double) vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (double) vp->integer64; +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return atof(vp->string); + } + + /* Not reached */ + return 0; +} + +#endif +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprVarToNumber(MprVar *vp) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprVarToInteger64(vp); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprVarToFloat(vp); +#else + return mprVarToInteger(vp); +#endif +} + +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprParseNumber(char *s) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprParseInteger64(s); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprParseFloat(s); +#else + return mprParseInteger(s); +#endif +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Convert the variable to an Integer64 type. Only works for primitive types. + */ + +int64 mprVarToInteger64(MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int64) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + + case MPR_TYPE_INT64: + return vp->integer64; + + case MPR_TYPE_STRING: + return mprParseInteger64(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer64. + */ + +int64 mprParseInteger64(char *str) +{ + char *cp; + int64 num64; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num64 = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num64 = (*cp - '0') + (num64 * 10); + cp++; + } + } else { + cp++; + if (tolower(*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower(*cp); + if (isdigit(c)) { + num64 = (c - '0') + (num64 * radix); + } else if (c >= 'a' && c <= 'f') { + num64 = (c - 'a') + (num64 * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower(*cp); + if (isdigit(c) && c < '8') { + num64 = (c - '0') + (num64 * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num64; + } + return num64; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Convert the variable to an Integer type. Only works for primitive types. + */ + +int mprVarToInteger(MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (int) vp->integer64; +#endif + + case MPR_TYPE_STRING: + return mprParseInteger(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer. + */ + +int mprParseInteger(char *str) +{ + char *cp; + int num; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num = (*cp - '0') + (num * 10); + cp++; + } + } else { + cp++; + if (tolower(*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower(*cp); + if (isdigit(c)) { + num = (c - '0') + (num * radix); + } else if (c >= 'a' && c <= 'f') { + num = (c - 'a') + (num * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower(*cp); + if (isdigit(c) && c < '8') { + num = (c - '0') + (num * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num; + } + return num; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the string buffer to an Floating. + */ + +double mprParseFloat(char *str) +{ + return atof(str); +} + +/******************************************************************************/ + +bool mprIsNan(double f) +{ +#if WIN + return _isnan(f); +#elif VXWORKS + // FUTURE + return (0); +#else + return (f == FP_NAN); +#endif +} +/******************************************************************************/ + +bool mprIsInfinite(double f) +{ +#if WIN + return !_finite(f); +#elif VXWORKS + // FUTURE + return (0); +#else + return (f == FP_INFINITE); +#endif +} + +#endif // BLD_FEATURE_FLOATING_POINT +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h new file mode 100644 index 0000000000..1f9ab65aa7 --- /dev/null +++ b/source4/lib/ejs/var.h @@ -0,0 +1,482 @@ +/* + * @file var.h + * @brief MPR Universal Variable Type + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ +/* + * Variables can efficiently store primitive types and can hold references to + * objects. Objects can store properties which are themselves variables. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. A variable may store one of + * the following types: + * + * string, integer, integer-64bit, C function, C function with string args, + * Javascript function, Floating point number, boolean value, Undefined + * value and the Null value. + * + * Variables have names while objects may be referenced by multiple variables. + * Objects use reference counting for garbage collection. + * + * This module is not thread safe for performance and compactness. It relies + * on upper modules to provide thread synchronization as required. The API + * provides primitives to get variable/object references or to get copies of + * variables which will help minimize required lock times. + */ + +#ifndef _h_MPR_VAR +#define _h_MPR_VAR 1 + +/********************************* Includes ***********************************/ + +#include "lib/ejs/miniMpr.h" + +/********************************** Defines ***********************************/ + +/* + * Define VAR_DEBUG if you want to track objects. However, this code is not + * thread safe and you need to run the server single threaded. + * + * #define VAR_DEBUG 1 + */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Forward declare types + */ +struct MprProperties; +struct MprVar; + +/* + * Possible variable types. Don't use enum because we need to be able to + * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. + */ +typedef int MprType; +#define MPR_TYPE_UNDEFINED 0 ///< Undefined. No value has been set. +#define MPR_TYPE_NULL 1 ///< Value defined to be null. +#define MPR_TYPE_BOOL 2 ///< Boolean type. +#define MPR_TYPE_CFUNCTION 3 ///< C function or C++ method +#define MPR_TYPE_FLOAT 4 ///< Floating point number +#define MPR_TYPE_INT 5 ///< Integer number +#define MPR_TYPE_INT64 6 ///< 64-bit Integer number +#define MPR_TYPE_OBJECT 7 ///< Object reference +#define MPR_TYPE_FUNCTION 8 ///< JavaScript function +#define MPR_TYPE_STRING 9 ///< String (immutable) +#define MPR_TYPE_STRING_CFUNCTION 10 ///< C/C++ function with string args + +/* + * Create a type for the default number type + * Config.h will define the default number type. For example: + * + * BLD_FEATURE_NUM_TYPE=int + * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT + */ + +/** + * Set to the type used for MPR numeric variables. Will equate to int, int64 + * or double. + */ +typedef BLD_FEATURE_NUM_TYPE MprNum; + +/** + * Set to the MPR_TYPE used for MPR numeric variables. Will equate to + * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. + */ +#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID +#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID + +/* + * Return TRUE if a variable is a function type + */ +#define mprVarIsFunction(type) \ + (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ + type == MPR_TYPE_CFUNCTION) + +/* + * Return TRUE if a variable is a numeric type + */ +#define mprVarIsNumber(type) \ + (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) + +/* + * Return TRUE if a variable is a boolean + */ +#define mprVarIsBoolean(type) \ + (type == MPR_TYPE_BOOL) +#define mprVarIsString(type) \ + (type == MPR_TYPE_STRING) +#define mprVarIsObject(type) \ + (type == MPR_TYPE_OBJECT) +#define mprVarIsFloating(type) \ + (type == MPR_TYPE_FLOAT) +#define mprVarIsUndefined(var) \ + ((var)->type == MPR_TYPE_UNDEFINED) +#define mprVarIsNull(var) \ + ((var)->type == MPR_TYPE_NULL) +#define mprVarIsValid(var) \ + (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) + +#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ + +#if BLD_FEATURE_SQUEEZE +#define MPR_MAX_VAR 64 /* Max var full name */ +#else +#define MPR_MAX_VAR 512 +#endif + +#ifndef __NO_PACK +#pragma pack(2) +#endif /* _NO_PACK */ + +/* + * Function signatures + */ +typedef int MprVarHandle; +typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, + struct MprVar **argv); +typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, + char **argv); + +/* + * Triggers + */ +typedef enum { + MPR_VAR_WRITE, /* This property is being updated */ + MPR_VAR_READ, /* This property is being read */ + MPR_VAR_CREATE_PROPERTY, /* A property is being created */ + MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ + MPR_VAR_DELETE /* This object is being deleted */ +} MprVarTriggerOp; + +/* + * Trigger function return codes. + */ +typedef enum { + MPR_TRIGGER_ABORT, /* Abort the current operation */ + MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ + MPR_TRIGGER_PROCEED /* Proceed with the operation */ +} MprVarTriggerStatus; + +/* + * The MprVarTrigger arguments have the following meaning: + * + * op The operation being performed. See MprVarTriggerOp. + * parentProperties Pointer to the MprProperties structure. + * vp Pointer to the property that registered the trigger. + * newValue New value (see below for more details). + * copyDepth Specify what data items to copy. + * + * For VAR_READ, newVar is set to a temporary variable that the trigger + * function may assign a value to be returned instead of the actual + * property value. + * For VAR_WRITE, newValue holds the new value. The old existing value may be + * accessed via vp. + * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. + * For ADD_PROPERTY, vp is set to the property being added and newValue holds + * the new value. + */ +typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, + struct MprProperties *parentProperties, struct MprVar *vp, + struct MprVar *newValue, int copyDepth); + +/* + * mprCreateFunctionVar flags + */ +/** Use the alternate handle on function callbacks */ +#define MPR_VAR_ALT_HANDLE 0x1 + +/** Use the script handle on function callbacks */ +#define MPR_VAR_SCRIPT_HANDLE 0x2 + +/* + * Useful define for the copyDepth argument + */ +/** Don't copy any data. Copy only the variable name */ +#define MPR_NO_COPY 0 + +/** Copy strings. Increment object reference counts. */ +#define MPR_SHALLOW_COPY 1 + +/** Copy strings and do complete object copies. */ +#define MPR_DEEP_COPY 2 + +/* + * GetFirst / GetNext flags + */ +/** Step into data properties. */ +#define MPR_ENUM_DATA 0x1 + +/** Step into functions properties. */ +#define MPR_ENUM_FUNCTIONS 0x2 + +/* + * Collection type to hold properties in an object + */ +typedef struct MprProperties { /* Collection of properties */ +#if VAR_DEBUG + struct MprProperties *next; /* Linked list */ + struct MprProperties *prev; /* Linked list */ + char name[32]; /* Debug name */ +#endif + struct MprVar **buckets; /* Hash chains */ + int numItems; /* Total count of items */ + int numDataItems; /* Enumerable data items */ + uint hashSize : 8; /* Size of the hash table */ + uint refCount : 8; /* References to this property*/ + uint deleteProtect : 8; /* Don't recursively delete */ + uint visited : 8; /* Node has been processed */ +} MprProperties; + +/* + * Universal Variable Type + */ +typedef struct MprVar { + MprStr name; /* Property name */ + MprStr fullName; /* Full object name */ + MprProperties *properties; /* Pointer to properties */ + + /* + * Packed bit field + */ + MprType type : 8; /* Selector into union */ + uint bucketIndex : 8; /* Copy of bucket index */ + + uint flags : 5; /* Type specific flags */ + uint allocatedData : 1; /* Data needs freeing */ + uint readonly : 1; /* Unmodifiable */ + uint deleteProtect : 1; /* Don't recursively delete */ + + uint visited : 1; /* Node has been processed */ + uint allocatedVar : 1; /* Var needs freeing */ + uint spare : 6; /* Unused */ + + struct MprVar *forw; /* Hash table linkage */ + MprVarTrigger trigger; /* Trigger function */ + +#if UNUSED && KEEP + struct MprVar *baseClass; /* Pointer to class object */ +#endif + MprProperties *parentProperties; /* Pointer to parent object */ + + /* + * Union of primitive types. When debugging on Linux, don't use unions + * as the gdb debugger can't display them. + */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + union { +#endif + int boolean; /* Use int for speed */ +#if BLD_FEATURE_FLOATING_POINT + double floating; +#endif + int integer; +#if BLD_FEATURE_INT64 + int64 integer64; +#endif + struct { /* Javascript functions */ + MprArray *args; /* Null terminated */ + char *body; + } function; + struct { /* Function with MprVar args */ + MprCFunction fn; + void *thisPtr; + } cFunction; + struct { /* Function with string args */ + MprStringCFunction fn; + void *thisPtr; + } cFunctionWithStrings; + MprStr string; /* Allocated string */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + }; +#endif +} MprVar; + +/* + * Define a field macro so code an use numbers in a "generic" fashion. + */ +#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN +//* Default numeric type */ +#define mprNumber integer +#endif +#if MPR_NUM_VAR == MPR_TYPE_INT64 +//* Default numeric type */ +#define mprNumber integer64 +#endif +#if MPR_NUM_VAR == MPR_TYPE_FLOAT +//* Default numeric type */ +#define mprNumber floating +#endif + +typedef BLD_FEATURE_NUM_TYPE MprNumber; + + +#ifndef __NO_PACK +#pragma pack() +#endif /* __NO_PACK */ + +/********************************* Prototypes *********************************/ +/* + * Variable constructors and destructors + */ +extern MprVar mprCreateObjVar(const char *name, int hashSize); +extern MprVar mprCreateBoolVar(bool value); +extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, + int flags); +#if BLD_FEATURE_FLOATING_POINT +extern MprVar mprCreateFloatVar(double value); +#endif +extern MprVar mprCreateIntegerVar(int value); +#if BLD_FEATURE_INT64 +extern MprVar mprCreateInteger64Var(int64 value); +#endif +extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); +extern MprVar mprCreateNullVar(void); +extern MprVar mprCreateNumberVar(MprNumber value); +extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, + void *thisPtr, int flags); +extern MprVar mprCreateStringVar(const char *value, bool allocate); +extern MprVar mprCreateUndefinedVar(void); +extern bool mprDestroyVar(MprVar *vp); +extern bool mprDestroyAllVars(MprVar* vp); +extern MprType mprGetVarType(MprVar *vp); + +/* + * Copy + */ +extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); +extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); +extern MprVar *mprDupVar(MprVar *src, int copyDepth); + +/* + * Manage vars + */ +extern MprVarTrigger + mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); +extern int mprGetVarRefCount(MprVar *vp); +extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); +extern void mprSetVarFullName(MprVar *vp, char *name); +extern void mprSetVarReadonly(MprVar *vp, int readonly); +extern void mprSetVarName(MprVar *vp, char *name); + +/* + * Create properties and return a reference to the property. + */ +extern MprVar *mprCreateProperty(MprVar *obj, const char *property, + MprVar *newValue); +extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, + MprVar newValue); +extern int mprDeleteProperty(MprVar *obj, const char *property); + +/* + * Get/Set properties. Set will update/create. + */ +extern MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value); +extern MprVar *mprSetProperty(MprVar *obj, const char *property, MprVar *value); +extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, MprVar value); + +/* + * Directly read/write property values (the property must already exist) + * For mprCopyProperty, mprDestroyVar must always called on the var. + */ +extern int mprReadProperty(MprVar *prop, MprVar *value); +extern int mprWriteProperty(MprVar *prop, MprVar *newValue); +extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); + +/* + * Copy a property. NOTE: reverse of most other args: (dest, src) + */ +extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); + +/* + * Enumerate properties + */ +extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); +extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, + int includeFlags); + +/* + * Query properties characteristics + */ +extern int mprGetPropertyCount(MprVar *obj, int includeFlags); + +/* + * Conversion routines + */ +extern MprVar mprParseVar(char *str, MprType prefType); +extern MprNum mprVarToNumber(MprVar *vp); +extern int mprVarToInteger(MprVar *vp); +#if BLD_FEATURE_INT64 +extern int64 mprVarToInteger64(MprVar *vp); +#endif +extern bool mprVarToBool(MprVar *vp); +#if BLD_FEATURE_FLOATING_POINT +extern double mprVarToFloat(MprVar *vp); +#endif +extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); + +/* + * Parsing and utility routines + */ +extern MprNum mprParseNumber(char *str); +extern int mprParseInteger(char *str); + +#if BLD_FEATURE_INT64 +extern int64 mprParseInteger64(char *str); +#endif + +#if BLD_FEATURE_FLOATING_POINT +extern double mprParseFloat(char *str); +extern bool mprIsInfinite(double f); +extern bool mprIsNan(double f); +#endif + +#if VAR_DEBUG +extern void mprPrintObjects(char *msg); +extern void mprPrintObjRefCount(MprVar *vp); +#endif + +#ifdef __cplusplus +} +#endif + +/*****************************************************************************/ +#endif /* _h_MPR_VAR */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ -- cgit From 7756b990f38495bf98e335b56bdc510659c34bdb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 29 May 2005 04:10:22 +0000 Subject: r7066: Rename http_exception to ejs_exception. (This used to be commit f2e59d3adfd7813c3c2090350f8ff2a99a5533e9) --- source4/lib/ejs/miniMpr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/miniMpr.c b/source4/lib/ejs/miniMpr.c index 2c6f7bea50..2094052b39 100644 --- a/source4/lib/ejs/miniMpr.c +++ b/source4/lib/ejs/miniMpr.c @@ -163,7 +163,7 @@ void mprBreakpoint(const char *file, int line, const char *cond) char *buf; mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", file, line, cond); - http_exception(buf); + ejs_exception(buf); } #endif /* !BLD_GOAHEAD_WEBSERVER */ -- cgit From 973ea5feb1952a6be443b66d5b49ca6c908a2c92 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 29 May 2005 11:32:29 +0000 Subject: r7071: allow access to the current mpr memory context from ejs calls (This used to be commit a58531dcf30b091913563ca2b8ce5e5843896441) --- source4/lib/ejs/miniMpr.c | 7 +++++++ source4/lib/ejs/miniMpr.h | 1 + 2 files changed, 8 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ejs/miniMpr.c b/source4/lib/ejs/miniMpr.c index 2094052b39..8b969289b0 100644 --- a/source4/lib/ejs/miniMpr.c +++ b/source4/lib/ejs/miniMpr.c @@ -37,11 +37,18 @@ static void *mpr_ctx; +/* set the memory context to be used for all ejs variables */ void mprSetCtx(TALLOC_CTX *ctx) { mpr_ctx = ctx; } +/* return the memory context being used for all ejs variables */ +void *mprMemCtx(void) +{ + return mpr_ctx; +} + void mprFree(void *ptr) { talloc_free(ptr); diff --git a/source4/lib/ejs/miniMpr.h b/source4/lib/ejs/miniMpr.h index b34fb2e293..b74c734728 100644 --- a/source4/lib/ejs/miniMpr.h +++ b/source4/lib/ejs/miniMpr.h @@ -270,6 +270,7 @@ extern int mprStrcpy(char *dest, int destMax, const char *src); extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); extern void mprSetCtx(void *ctx); +extern void *mprMemCtx(void); #ifdef __cplusplus } -- cgit From 89f796006f4f532457d001910c6893aa0e70d559 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 30 May 2005 06:06:27 +0000 Subject: r7085: fixed a bug in ejs with setting up the arguments[] array (This used to be commit 722950c21365982ac9a62f97360b6c4a0bdd4acc) --- source4/lib/ejs/ejsParser.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index f9335ec004..d42d66bcf5 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -2069,6 +2069,8 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) */ for (i = 0; i < formalArgs->used; i++) { mprCreateProperty(ep->local, argNames[i], argValues[i]); + } + for (i = 0; i < actualArgs->used; i++) { mprItoa(i, buf, sizeof(buf)); mprCreateProperty(&arguments, buf, argValues[i]); } -- cgit From dde05bc78735a111e814ab5ece9e79af4555153b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 30 May 2005 15:11:10 +0000 Subject: r7113: Move manpages from docs repository to source repository (This used to be commit f16d346032b9052c9dcd6b15cf65dd62e6943cd3) --- source4/lib/com/README | 9 ++ source4/lib/ldb/man/man1/ldbadd.1.xml | 99 ++++++++++++++++ source4/lib/ldb/man/man1/ldbdel.1.xml | 97 ++++++++++++++++ source4/lib/ldb/man/man1/ldbedit.1.xml | 125 ++++++++++++++++++++ source4/lib/ldb/man/man1/ldbmodify.1.xml | 87 ++++++++++++++ source4/lib/ldb/man/man1/ldbrename.1.xml | 101 +++++++++++++++++ source4/lib/ldb/man/man1/ldbsearch.1.xml | 113 +++++++++++++++++++ source4/lib/registry/man/regdiff.1.xml | 102 +++++++++++++++++ source4/lib/registry/man/regpatch.1.xml | 88 +++++++++++++++ source4/lib/registry/man/regshell.1.xml | 188 +++++++++++++++++++++++++++++++ source4/lib/registry/man/regtree.1.xml | 101 +++++++++++++++++ 11 files changed, 1110 insertions(+) create mode 100644 source4/lib/com/README create mode 100644 source4/lib/ldb/man/man1/ldbadd.1.xml create mode 100644 source4/lib/ldb/man/man1/ldbdel.1.xml create mode 100644 source4/lib/ldb/man/man1/ldbedit.1.xml create mode 100644 source4/lib/ldb/man/man1/ldbmodify.1.xml create mode 100644 source4/lib/ldb/man/man1/ldbrename.1.xml create mode 100644 source4/lib/ldb/man/man1/ldbsearch.1.xml create mode 100644 source4/lib/registry/man/regdiff.1.xml create mode 100644 source4/lib/registry/man/regpatch.1.xml create mode 100644 source4/lib/registry/man/regshell.1.xml create mode 100644 source4/lib/registry/man/regtree.1.xml (limited to 'source4/lib') diff --git a/source4/lib/com/README b/source4/lib/com/README new file mode 100644 index 0000000000..361024e02c --- /dev/null +++ b/source4/lib/com/README @@ -0,0 +1,9 @@ +This directory contains Samba's very simple COM implementation. +It is by no means finished yet. + +The main aim of this implementation is for use by our DCOM implementation, +which lives in the dcom subdirectory. The local version is used mostly for +testing. + +More information on this effort can be found in the DCOM whitepaper in +the lorikeet repository. diff --git a/source4/lib/ldb/man/man1/ldbadd.1.xml b/source4/lib/ldb/man/man1/ldbadd.1.xml new file mode 100644 index 0000000000..0b3122ab32 --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbadd.1.xml @@ -0,0 +1,99 @@ + + + + + + ldbadd + 1 + + + + + ldbadd + Command-line utility for adding records to an LDB + + + + + ldbadd + -h + -H LDB-URL + ldif-file1 + ldif-file2 + ... + + + + + DESCRIPTION + + ldbadd adds records to an ldb(7) database. It reads + the ldif(5) files specified on the command line and adds + the records from these files to the LDB database, which is specified + by the -H option or the LDB_URL environment variable. + + + If - is specified as a ldb file, the ldif input is read from + standard input. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbadd was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbdel.1.xml b/source4/lib/ldb/man/man1/ldbdel.1.xml new file mode 100644 index 0000000000..2f98f9d427 --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbdel.1.xml @@ -0,0 +1,97 @@ + + + + + + ldbdel + 1 + + + + + ldbdel + Command-line program for deleting LDB records + + + + + ldbdel + -h + -H LDB-URL + dn + ... + + + + + DESCRIPTION + + ldbdel deletes records from an ldb(7) database. + It deletes the records identified by the dn's specified + on the command-line. + + ldbdel uses either the database that is specified with + the -H option or the database specified by the LDB_URL environment + variable. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbadd, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbdel was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbedit.1.xml b/source4/lib/ldb/man/man1/ldbedit.1.xml new file mode 100644 index 0000000000..0b5c63a17a --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbedit.1.xml @@ -0,0 +1,125 @@ + + + + + + ldbedit + 1 + + + + + ldbedit + Edit LDB databases using your favorite editor + + + + + ldbedit + -h + -s base|one|sub + -b basedn + -a + -e editor + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbedit is a utility that allows you to edit LDB files using + your favorite editor. ldbedit generates an LDIF file based on + your query, allows you to edit it and then merges it back + into the LDB database. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -a + Edit all records. + + + + -e editor + Specify the editor that should be used (overrides + the VISUAL and EDITOR environment variables). + + + + -b basedn + Specify Base DN to use. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + VISUAL and EDITOR + Environment variables used to determine what + editor to use. If VISUAL isn't set, EDITOR is used. + + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbedit was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbmodify.1.xml b/source4/lib/ldb/man/man1/ldbmodify.1.xml new file mode 100644 index 0000000000..e39f74fffa --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbmodify.1.xml @@ -0,0 +1,87 @@ + + + + + + ldbmodify + 1 + + + + + ldbmodify + Modify records in a LDB database + + + + + ldbmodify + -H LDB-URL + ldif-file + + + + + DESCRIPTION + + + ldbmodify changes, adds and deletes records in a LDB database. + The changes that should be made to the LDB database are read from + the specified LDIF-file. If - is specified as the filename, input is read from stdin. + + + For now, see ldapmodify(1) for details on the LDIF file format. + + + + + + OPTIONS + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbedit + + + + + AUTHOR + + &man.credits.samba; + + ldbmodify was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbrename.1.xml b/source4/lib/ldb/man/man1/ldbrename.1.xml new file mode 100644 index 0000000000..32456243af --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbrename.1.xml @@ -0,0 +1,101 @@ + + + + + + ldbrename + 1 + + + + + ldbrename + Edit LDB databases using your favorite editor + + + + + ldbrename + -h + -o options + olddn + newdb + + + + + DESCRIPTION + + ldbrename is a utility that allows you to rename trees in + an LDB database based by DN. This utility takes + two arguments: the original + DN name of the top element and the DN to change it to. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -o options + Extra ldb options, such as + modules. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbrename was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbsearch.1.xml b/source4/lib/ldb/man/man1/ldbsearch.1.xml new file mode 100644 index 0000000000..8361aa97ff --- /dev/null +++ b/source4/lib/ldb/man/man1/ldbsearch.1.xml @@ -0,0 +1,113 @@ + + + + + + ldbsearch + 1 + + + + + ldbsearch + Search for records in a LDB database + + + + + ldbsearch + -h + -s base|one|sub + -b basedn + -i + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbsearch searches a LDB database for records matching the + specified expression (see the ldapsearch(1) manpage for + a description of the expression format). For each + record, the specified attributes are printed. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -i + Read search expressions from stdin. + + + + -b basedn + Specify Base DN to use. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbedit + + + + + AUTHOR + + &man.credits.samba; + + ldbsearch was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/registry/man/regdiff.1.xml b/source4/lib/registry/man/regdiff.1.xml new file mode 100644 index 0000000000..d4d9d75b91 --- /dev/null +++ b/source4/lib/registry/man/regdiff.1.xml @@ -0,0 +1,102 @@ + + + + + + regdiff + 1 + + + + + regdiff + Diff program for Windows registry files + + + + + regdiff + --help + --backend=BACKEND + --backend=BACKEND + --credentials=CREDENTIALS + --credentials=CREDENTIALS + location + location + + + + + DESCRIPTION + + regdiff compares two Windows registry files key by key + and value by value and generates a text file that contains the + differences between the two files. + + A file generated by regdiff can later be applied to a + registry file by the regpatch utility. + + regdiff and regpatch use the same file format as + the regedit32.exe utility from Windows. + + + + + OPTIONS + + + + --help + + Show list of available options. + + + + --backend BACKEND + Name of backend to load. Possible values are: + w95, nt4, gconf, dir and rpc. The default is dir. + + + This argument can be specified twice: once for the first + registry file and once for the second. + + + + + --credentials=CREDENTIALS + + Credentials to use, if any. Password should be separated from user name by a percent sign. + + + This argument can be specified twice: once for the first + registry file and once for the second. + + + + + +&man.registry.backends; + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + gregedit, regshell, regpatch, regtree, samba, patch, diff + + + + + AUTHOR + + &man.credits.samba; + + This manpage and regdiff were written by Jelmer Vernooij. + + + + diff --git a/source4/lib/registry/man/regpatch.1.xml b/source4/lib/registry/man/regpatch.1.xml new file mode 100644 index 0000000000..f1792d8bc9 --- /dev/null +++ b/source4/lib/registry/man/regpatch.1.xml @@ -0,0 +1,88 @@ + + + + + + regpatch + 1 + + + + + regpatch + Applies registry patches to registry files + + + + + regpatch + --help + --backend=BACKEND + --credentials=CREDENTIALS + location + patch-file + + + + + DESCRIPTION + + The regpatch utility applies registry patches to Windows registry + files. The patch files should have the same format as is being used + by the regdiff utility and regedit32.exe from Windows. + + If no patch file is specified on the command line, + regpatch attempts to read it from standard input. + + + + + OPTIONS + + + + --help + + Show list of available options. + + + + --backend BACKEND + Name of backend to load. Possible values are: + w95, nt4, gconf, dir and rpc. The default is dir. + + + + + --credentials=CREDENTIALS + + Credentials to use, if any. Password should be separated from user name by a percent sign. + + + + +&man.registry.backends; + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + regdiff, regtree, regshell, gregedit, samba, diff, patch + + + + + AUTHOR + + &man.credits.samba; + + This manpage and regpatch were written by Jelmer Vernooij. + + + + diff --git a/source4/lib/registry/man/regshell.1.xml b/source4/lib/registry/man/regshell.1.xml new file mode 100644 index 0000000000..fbfff86b09 --- /dev/null +++ b/source4/lib/registry/man/regshell.1.xml @@ -0,0 +1,188 @@ + + + + + + regshell + 1 + + + + + regshell + Windows registry file browser using readline + + + + + regshell + --help + --backend=BACKEND + --credentials=CREDENTIALS + location + + + + + DESCRIPTION + + + regshell is a utility that lets you browse thru a Windows registry + file as if you were using a regular unix shell to browse thru a + file system. + + + + + + + OPTIONS + + + + --help + + Show list of available options. + + + + --backend BACKEND + Name of backend to load. Possible values are: + w95, nt4, gconf, dir and rpc. The default is dir. + + + + + --credentials=CREDENTIALS + + Credentials to use, if any. Password should be separated from user name by a percent sign. + + + + + + COMMANDS + + + + ck|cd <keyname> + + Go to the specified subkey. + + + + + ch|predef [predefined-key-name] + + Go to the specified predefined key. + + + + + list|ls + + List subkeys and values of the current key. + + + + + mkkey|mkdir <keyname> + + Create a key with the specified keyname as a subkey of the current key. + + + + + rmval|rm <valname> + + Delete the specified value. + + + + + rmkey|rmdir <keyname> + + Delete the specified subkey recursively. + + + + + pwd|pwk + Print the full name of the current key. + + + + set|update + Update the value of a key value. Not implemented at the moment. + + + + help|? + Print a list of available commands. + + + exit|quit + Leave regshell. + + + + +&man.registry.backends; + + + EXAMPLES + + Browsing thru a nt4 registry file + +regshell -b nt4 NTUSER.DAT +$$$PROTO.HIV> ls +K AppEvents +K Console +K Control Panel +K Environment +K Identities +K Keyboard Layout +K Network +K Printers +K Software +K UNICODE Program Groups +K Windows 3.1 Migration Status +$$$PROTO.HIV> exit + + +Listing the subkeys of HKEY_CURRENT_USER\AppEvents on a remote computer: + +regshell --remote=ncacn_np:aurelia -c "jelmer%secret" +HKEY_CURRENT_MACHINE> predef HKEY_CURRENT_USER +HKEY_CURRENT_USER> cd AppEvents +Current path is: HKEY_CURRENT_USER\AppEvents +HKEY_CURRENT_USER\AppEvents> ls +K EventLabels +K Schemes +HKEY_CURRENT_USER\AppEvents> exit + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + regtree, regdiff, regpatch, gregedit, samba + + + + + AUTHOR + + &man.credits.samba; + + This manpage and regshell were written by Jelmer Vernooij. + + + + diff --git a/source4/lib/registry/man/regtree.1.xml b/source4/lib/registry/man/regtree.1.xml new file mode 100644 index 0000000000..7fc0de2721 --- /dev/null +++ b/source4/lib/registry/man/regtree.1.xml @@ -0,0 +1,101 @@ + + + + + + regtree + 1 + + + + + regtree + Text-mode registry viewer + + + + + regtree + --help + --backend=BACKEND + --fullpath + --no-values + --credentials=CREDENTIALS + location + + + + + DESCRIPTION + + The regtree utility prints out all the contents of a + Windows registry file. Subkeys are printed with one level + more indentation then their parents. + + + + + + OPTIONS + + + + --help + + Show list of available options. + + + + --backend BACKEND + Name of backend to load. Possible values are: + w95, nt4, gconf, dir and rpc. The default is dir. + + + + + --credentials=CREDENTIALS + + Credentials to use, if any. Password should be separated from user name by a percent sign. + + + + --fullpath + + Print the full path to each key instead of only its name. + + + + + --no-values + Don't print values, just keys. + + + + + + +&man.registry.backends; + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + gregedit, regshell, regdiff, regpatch, samba + + + + + AUTHOR + + &man.credits.samba; + + This manpage and regtree were written by Jelmer Vernooij. + + + + -- cgit From 1863240bbc6dbd7b0b0832504a9c30573b44ddf6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 30 May 2005 15:59:08 +0000 Subject: r7114: Convert ldb documentation to DocBook/XML (This used to be commit 470c6185fb815983aebffd313361ec0fac723fd0) --- source4/lib/ldb/Makefile.in | 15 ++- source4/lib/ldb/configure.in | 2 +- source4/lib/ldb/man/man3/ldb.3.xml | 262 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/man/man3/ldb.yo | 129 ------------------ 4 files changed, 273 insertions(+), 135 deletions(-) create mode 100644 source4/lib/ldb/man/man3/ldb.3.xml delete mode 100644 source4/lib/ldb/man/man3/ldb.yo (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index e7bde04658..4d93edb884 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -1,6 +1,6 @@ CC = @CC@ GCOV = @GCOV@ -YODL2MAN = @YODL2MAN@ +XSLTPROC = @XSLTPROC@ prefix = @prefix@ exec_prefix = @exec_prefix@ includedir = @includedir@ @@ -90,11 +90,16 @@ bin/ldbtest: tools/ldbtest.o $(LIBS) .SUFFIXES: .1 .2 .3 .yo -.yo.3: - echo Creating $@ from $< - -$(YODL2MAN) -o $@ `dirname $<`/`basename $< .yo` || rm -f $@ +%.3: %.3.xml + test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< -manpages: $(patsubst %.yo,%.3,$(wildcard man/man3/*.yo)) +%.1: %.1.xml + test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +%.html: %.xml + test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< + +manpages: $(patsubst %.xml,%,$(wildcard man/*/*.xml)) clean: rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index a04ae00690..aec149360b 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -19,7 +19,7 @@ AC_ARG_ENABLE(gcov, AC_SUBST(WITH_GCOV) AC_PROG_CC AC_FUNC_MMAP -AC_PATH_PROG(YODL2MAN,yodl2man) +AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) AC_CHECK_HEADERS(stdint.h) AC_CONFIG_HEADER(include/config.h) diff --git a/source4/lib/ldb/man/man3/ldb.3.xml b/source4/lib/ldb/man/man3/ldb.3.xml new file mode 100644 index 0000000000..d9ed135f20 --- /dev/null +++ b/source4/lib/ldb/man/man3/ldb.3.xml @@ -0,0 +1,262 @@ + + + + + + ldb + 3 + + + + ldb + The Samba Project + A light-weight database library + + + + #include <ldb.h> + + + + description + + +ldb is a light weight embedded database library and API. With a +programming interface that is very similar to LDAP, ldb can store its +data either in a tdb(3) database or in a real LDAP database. + + + +When used with the tdb backend ldb does not require any database +daemon. Instead, ldb function calls are processed immediately by the +ldb library, which does IO directly on the database, while allowing +multiple readers/writers using operating system byte range locks. This +leads to an API with very low overheads, often resulting in speeds of +more than 10x what can be achieved with a more traditional LDAP +architecture. + + + +It a taxonomy of databases ldb would sit half way between key/value +pair databases (such as berkley db or tdb) and a full LDAP +database. With a structured attribute oriented API like LDAP and good +indexing capabilities, ldb can be used for quite sophisticated +applications that need a light weight database, without the +administrative overhead of a full LDAP installation. + + + +Included with ldb are a number of useful command line tools for +manipulating a ldb database. These tools are similar in style to the +equivalent ldap command line tools. + + + +In its default mode of operation with a tdb backend, ldb can also be +seen as a "schema-less LDAP". By default ldb does not require a +schema, which greatly reduces the complexity of getting started with +ldb databases. As the complexity of you application grows you can take +advantage of some of the optional schema-like attributes that ldb +offers, or you can migrate to using the full LDAP api while keeping +your exiting ldb code. + + + +If you are new to ldb, then I suggest starting with the manual pages +for ldbsearch(1) and ldbedit(1), and experimenting with a local +database. Then I suggest you look at the ldb_connect(3) and +ldb_search(3) manual pages. + + + + + TOOLS + + + + ldbsearch(1) + - command line ldb search utility + + + + ldbedit(1) + - edit all or part of a ldb database using your favourite editor + + + + ldbadd(1) + - add records to a ldb database using LDIF formatted input + + + + ldbdel(1) + - delete records from a ldb database + + + + ldbmodify(1) + - modify records in a ldb database using LDIF formatted input + + + + + + FUNCTIONS + + + + ldb_connect(3) + - connect to a ldb backend + + + + ldb_search(3) + - perform a database search + + + + ldb_add(3) + - add a record to the database + + + + ldb_delete(3) + - delete a record from the database + + + + ldb_modify(3) + - modify a record in the database + + + + ldb_errstring(3) + - retrieve extended error information from the last operation + + + + ldb_ldif_write(3) + - write a LDIF formatted message + + + + ldb_ldif_write_file(3) + - write a LDIF formatted message to a file + + + + ldb_ldif_read(3) + - read a LDIF formatted message + + + + ldb_ldif_read_free(3) + - free the result of a ldb_ldif_read() + + + + ldb_ldif_read_file(3) + - read a LDIF message from a file + + + + ldb_ldif_read_string(3) + - read a LDIF message from a string + + + + ldb_msg_find_element(3) + - find an element in a ldb_message + + + + ldb_val_equal_exact(3) + - compare two ldb_val structures + + + + ldb_msg_find_val(3) + - find an element by value + + + + ldb_msg_add_empty(3) + - add an empty message element to a ldb_message + + + + + ldb_msg_add(3) + - add a non-empty message element to a ldb_message + + + + + ldb_msg_element_compare(3) + - compare two ldb_message_element structures + + + + + ldb_msg_find_int(3) + - return an integer value from a ldb_message + + + + + ldb_msg_find_uint(3) + - return an unsigned integer value from a ldb_message + + + + + ldb_msg_find_double(3) + - return a double value from a ldb_message + + + + + ldb_msg_find_string(3) + - return a string value from a ldb_message + + + + + ldb_set_alloc(3) + - set the memory allocation function to be used by ldb + + + + + ldb_set_debug(3) + - set a debug handler to be used by ldb + + + + + ldb_set_debug_stderr(3) + - set a debug handler for stderr output + + + + + + description + + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + +ldb is released under the GNU Lesser General Public License version 2 +or later. Please see the file COPYING for license details. + + + diff --git a/source4/lib/ldb/man/man3/ldb.yo b/source4/lib/ldb/man/man3/ldb.yo deleted file mode 100644 index c2c7e1b872..0000000000 --- a/source4/lib/ldb/man/man3/ldb.yo +++ /dev/null @@ -1,129 +0,0 @@ -manpage(ldb)(3)(May 2004)()() -manpagename(ldb)(A light-weight database library) - -manpagesynopsis() - - bf(#include ) - -manpagedescription() - -ldb is a light weight embedded database library and API. With a -programming interface that is very similar to LDAP, ldb can store its -data either in a tdb(3) database or in a real LDAP database. - -When used with the tdb backend ldb does not require any database -daemon. Instead, ldb function calls are processed immediately by the -ldb library, which does IO directly on the database, while allowing -multiple readers/writers using operating system byte range locks. This -leads to an API with very low overheads, often resulting in speeds of -more than 10x what can be achieved with a more traditional LDAP -architecture. - -It a taxonomy of databases ldb would sit half way between key/value -pair databases (such as berkley db or tdb) and a full LDAP -database. With a structured attribute oriented API like LDAP and good -indexing capabilities, ldb can be used for quite sophisticated -applications that need a light weight database, without the -administrative overhead of a full LDAP installation. - -Included with ldb are a number of useful command line tools for -manipulating a ldb database. These tools are similar in style to the -equivalent ldap command line tools. - -In its default mode of operation with a tdb backend, ldb can also be -seen as a "schema-less LDAP". By default ldb does not require a -schema, which greatly reduces the complexity of getting started with -ldb databases. As the complexity of you application grows you can take -advantage of some of the optional schema-like attributes that ldb -offers, or you can migrate to using the full LDAP api while keeping -your exiting ldb code. - -If you are new to ldb, then I suggest starting with the manual pages -for ldbsearch(1) and ldbedit(1), and experimenting with a local -database. Then I suggest you look at the ldb_connect(3) and -ldb_search(3) manual pages. - -manpagesection(INDEX) - -startdit() - -dit(bf(ldbsearch(1))) command line ldb search utility - -dit(bf(ldbedit(1))) edit all or part of a ldb databse using your -favourite editor - -dit(bf(ldbedit(1))) edit all or part of a ldb databse using your -favourite editor - -dit(bf(ldbadd(1))) add records to a ldb database using LDIF formatted input - -dit(bf(ldbdel(1))) delete records from a ldb database - -dit(bf(ldbmodify(1))) modify records in a ldb database using LDIF -formatted input - -dit(bf(ldb_connect(3))) connect to a ldb backend - -dit(bf(ldb_search(3))) perform a database search - -dit(bf(ldb_add(3))) add a record to the database - -dit(bf(ldb_delete(3))) delete a record from the database - -dit(bf(ldb_modify(3))) modify a record in the database - -dit(bf(ldb_errstring(3))) retrieve extended error information from the -last operation - -dit(bf(ldb_ldif_write(3))) write a LDIF formatted message - -dit(bf(ldb_ldif_write_file(3))) write a LDIF formatted message to a file - -dit(bf(ldb_ldif_read(3))) read a LDIF formatted message - -dit(bf(ldb_ldif_read_free(3))) free the result of a ldb_ldif_read() - -dit(bf(ldb_ldif_read_file(3))) read a LDIF message from a file - -dit(bf(ldb_ldif_read_string(3))) read a LDIF message from a string - -dit(bf(ldb_msg_find_element(3))) find an element in a ldb_message - -dit(bf(ldb_val_equal_exact(3))) compare two ldb_val structures - -dit(bf(ldb_msg_find_val(3))) find an element by value - -dit(bf(ldb_msg_add_empty(3))) add an empty message element to a ldb_message - -dit(bf(ldb_msg_add(3))) add a non-empty message element to a ldb_message - -dit(bf(ldb_msg_element_compare(3))) compare two ldb_message_element structures - -dit(bf(ldb_msg_find_int(3))) return an integer value from a ldb_message - -dit(bf(ldb_msg_find_uint(3))) return an unsigned integer value from a ldb_message - -dit(bf(ldb_msg_find_double(3))) return a double value from a ldb_message - -dit(bf(ldb_msg_find_string(3))) return a string value from a ldb_message - -dit(bf(ldb_set_alloc(3))) set the memory allocation function to be used by ldb - -dit(bf(ldb_set_debug(3))) set a debug handler to be used by ldb - -dit(bf(ldb_set_debug_stderr(3))) set a debug handler for stderr output - -enddit() - -manpageauthor() - -ldb was written by Andrew Tridgell -url(http://samba.org/~tridge/)(http://samba.org/~tridge/) - -If you wish to report a problem or make a suggestion then please see -the url(http://ldb.samba.org/)(http://ldb.samba.org/) web site for -current contact and maintainer information. - -ldb is released under the GNU Lesser General Public License version 2 -or later. Please see the file COPYING for license details. - -- cgit From a3972de8949f5d1c804c316b0be61c17e61d903b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 30 May 2005 16:46:54 +0000 Subject: r7116: work in progress (This used to be commit c860a4f9940c04021ecc859240c5f35c3d1c4bed) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 356 +++++++++++++++++++----------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 1 + source4/lib/ldb/ldb_sqlite3/schema | 6 +- 3 files changed, 237 insertions(+), 126 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 932da0af31..a0ffffca9e 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -37,11 +37,21 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" +#undef SQL_EXEC /* just in case; not expected to be defined */ +#define SQL_EXEC(lsqlite3, query, reset) \ + do { \ + lsqlite3->last_rc = \ + sqlite3_step(lsqlite3->queries.query); \ + if (lsqlite3->last_rc == SQLITE_BUSY || reset) \ + (void) sqlite3_reset(lsqlite3->queries.query); \ + } while lsqlite3->last_rc == SQLITE_BUSY; + + + #if 0 /* - we don't need this right now, but will once we add some backend - options -*/ + * we don't need this right now, but will once we add some backend options + */ /* find an option in an option list (a null terminated list of strings) @@ -68,8 +78,8 @@ static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, #endif /* - rename a record -*/ + * rename a record + */ static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const char *newdn) { int column; @@ -81,32 +91,32 @@ static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const c } /* Bind old distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":oldDN"); - if (sqlite3_bind_text(lsqlite3->renameDN, column, + column = sqlite3_bind_parameter_index(lsqlite3->queries.renameDN, + ":oldDN"); + if (sqlite3_bind_text(lsqlite3->queries.renameDN, column, olddn, strlen(olddn), SQLITE_STATIC) != SQLITE_OK) { return -1; } /* Bind new distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":newDN"); - if (sqlite3_bind_text(lsqlite3->renameDN, column, + column = sqlite3_bind_parameter_index(lsqlite3->queries.renameDN, + ":newDN"); + if (sqlite3_bind_text(lsqlite3->queries.renameDN, column, newdn, strlen(newdn), SQLITE_STATIC) != SQLITE_OK) { return -1; } - do { - lsqlite3->last_rc = sqlite3_step(lsqlite3->renameDN); - (void) sqlite3_reset(lsqlite3->renameDN); - } while lsqlite3->last_rc == SQLITE3_BUSY; + /* Execute the query. This sets lsqlite3->last_rc */ + SQL_EXEC(lsqlite3, renameDN, TRUE); return lsqlite3->last_rc == 0 ? 0 : -1; } /* - delete a record -*/ + * delete a record + */ static int lsqlite3_delete(struct ldb_module *module, const char *dn) { int ret = 0; @@ -118,25 +128,24 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn) return 0; } - /* Bind new distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->renameDN, ":dn"); - if (sqlite3_bind_text(lsqlite3->deleteDN, column, + /* Bind distinguished names */ + column = sqlite3_bind_parameter_index(lsqlite3->queries.deleteDN, + ":dn"); + if (sqlite3_bind_text(lsqlite3->queries.deleteDN, column, dn, strlen(dn), SQLITE_STATIC) != SQLITE_OK) { return -1; } - do { - lsqlite3->last_rc = sqlite3_step(lsqlite3->deleteDN); - (void) sqlite3_reset(lsqlite3->deleteDN); - } while lsqlite3->last_rc == SQLITE3_BUSY; + /* Execute the query. This sets lsqlite3->last_rc */ + SQL_EXEC(lsqlite3, deleteDN, TRUE); return lsqlite3->last_rc == 0 ? 0 : -1; } /* - free a search result -*/ + * free a search result + */ static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message **res) { talloc_free(res); @@ -145,8 +154,8 @@ static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message ** /* - add a single set of ldap message values to a ldb_message -*/ + * add a single set of ldap message values to a ldb_message + */ static int lsqlite3_add_msg_attr(struct ldb_context *ldb, struct ldb_message *msg, const char *attr, struct berval **bval) @@ -200,8 +209,8 @@ static int lsqlite3_add_msg_attr(struct ldb_context *ldb, } /* - search for matching records -*/ + * search for matching records + */ static int lsqlite3_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -304,117 +313,175 @@ failed: /* - Issue a series of SQL statements to implement the requests in the ldb_message -*/ + * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE + * requests in the ldb_message + */ static int lsqlite3_msg_to_sql(struct ldb_context *ldb, const struct ldb_message *msg, - int modify_existing) + long long dn_id, + int use_flags) { + int flags; unsigned int i, j; struct ldb_context *ldb = module->ldb; struct lsqlite3_private *lsqlite3 = module->private_data; sqlite3_stmt *stmt = NULL; - for (i=0;inum_elements;i++) { + for (i = 0; i < msg->num_elements; i++) { const struct ldb_message_element *el = &msg->elements[i]; - if (! modify_existing) { - /* This is a new DN. Bind new distinguished name */ - column = - sqlite3_bind_parameter_index( - lsqlite3->queries.newDN, - ":dn"); - if (sqlite3_bind_text(lsqlite3->queries.newDN, column, - msg->dn, strlen(msg->dn), - SQLITE_STATIC) != SQLITE_OK) { - return -1; - } + if (! use_flags) { + flags = LDB_FLAG_MOD_ADD; + } else { + flags = el->flags & LDB_FLAG_MOD_MASK; + } - /* Add this new DN */ - do { - lsqlite3->last_rc = - sqlite3_step(lsqlite3->queries.newDN); - (void) sqlite3_reset(lsqlite3->queries.newDN); - } while lsqlite3->last_rc == SQLITE_BUSY; + /* Determine which query to use */ + switch (flags) { + case LDB_FLAG_MOD_ADD: + stmt = lsqlite3->queries.addAttrValuePair; + break; - if (lsqlite3->last_rc != SQLITE_DONE) { - return -1; - } + case LDB_FLAG_MOD_DELETE: + stmt = lsqlite3->queries.deleteAttrValuePairs; + break; - dn_id = last_insert_rowid(lsqlite3->sqlite3); + case LDB_FLAG_MOD_REPLACE: + stmt = lsqlite3->queries.replaceAttrValuePairs; + break; + } - stmt = lsqlite3->queries.newAttribute; + /* + * All queries use dn id and attribute name. Bind them now. + */ - } else { - /* Get the dn_id for the specified DN */ - xxx; + /* Bind distinguished name id */ + column = + sqlite3_bind_parameter_index( + stmt, + ":dn_id"); + if (sqlite3_bind_int64(stmt, + column, + dn_id) != SQLITE_OK) { - switch (el->flags & LDB_FLAG_MOD_MASK) { - case LDB_FLAG_MOD_ADD: - stmt = lsqlite3->queries.addAttrValuePair; - break; - case LDB_FLAG_MOD_DELETE: - stmt = lsqlite3->queries.deleteAttrValuePairs; - break; - case LDB_FLAG_MOD_REPLACE: - stmt = lsqlite3->queries.replaceAttrValuePairs; - break; - } - + return -1; } - for (j=0;jnum_values;j++) { - mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals, - struct berval); - if (!mods[num_mods]->mod_vals.modv_bvals[j]) { - goto failed; - } - mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data; - mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length; + /* Bind attribute name */ + column = + sqlite3_bind_parameter_index( + stmt, + ":attr_name"); + if (sqlite3_bind_text(lsqlite3->queries.deleteDN, column, + el->name, strlen(el->name), + SQLITE_STATIC) != SQLITE_OK) { + + return -1; + } + + + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + + /* ... bind the attribute value, if necessary */ + switch (flags) { + case LDB_FLAG_MOD_ADD: + case LDB_FLAG_MOD_REPLACE: + /* Bind attribute value */ + column = + sqlite3_bind_parameter_index( + stmt, + ":attr_value"); + if (sqlite3_bind_text( + stmt, column, + el->values[j].data, + el->values[j].length, + SQLITE_STATIC) != SQLITE_OK) { + + return -1; + } + + break; + + case LDB_FLAG_MOD_DELETE: + /* No additional parameters to this query */ + break; + } + + /* Execute the query */ + do { + lsqlite3->last_rc = sqlite3_step(stmt); + (void) sqlite3_reset(stmt); + } while lsqlite3->last_rc == SQLITE_BUSY; + + /* Make sure we succeeded */ + if (lsqlite3->last_rc != SQLITE_OK) { + return -1; + } } - mods[num_mods]->mod_vals.modv_bvals[j] = NULL; - num_mods++; } - return mods; - -failed: - talloc_free(mods); - return NULL; + return 0; } /* - add a record -*/ + * add a record + */ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) { struct ldb_context *ldb = module->ldb; struct lsqlite3_private *lsqlite3 = module->private_data; - LDAPMod **mods; - int ret = 0; + int ret; /* ignore ltdb specials */ if (msg->dn[0] == '@') { return 0; } - mods = lsqlite3_msg_to_mods(ldb, msg, 0); + /* Begin a transaction */ + SQL_EXEC(lsqlite3, begin, TRUE); - lsqlite3->last_rc = ldap_add_s(lsqlite3->ldap, msg->dn, mods); - if (lsqlite3->last_rc != LDAP_SUCCESS) { - ret = -1; - } + /* This is a new DN. Bind new distinguished name */ + column = sqlite3_bind_parameter_index(lsqlite3->queries.newDN, ":dn"); + if (sqlite3_bind_text(lsqlite3->queries.newDN, column, + msg->dn, strlen(msg->dn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + /* Add this new DN. This sets lsqlite3->last_rc */ + SQL_EXEC(lsqlite3, newDN, TRUE); + + if (lsqlite3->last_rc != SQLITE_DONE) { + return -1; + } + + /* Get the id of the just-added DN */ + dn_id = sqlite3_last_insert_rowid(lsqlite3->sqlite3); + + ret = lsqlite3_msg_to_sql(ldb, msg, dn_id, FALSE); - talloc_free(mods); + /* Did the attribute additions (if any) succeeded? */ + if (ret == 0) + { + /* Yup. Commit the transaction */ + SQL_EXEC(lsqlite3, commit, TRUE); + } + else + { + /* Attribute addition failed. Rollback the transaction */ + SQL_EXEC(lsqlite3, rollback, TRUE); + } - return ret; + /* If everything succeeded, return success */ + return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1; } /* - modify a record -*/ + * modify a record + */ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { struct ldb_context *ldb = module->ldb; @@ -427,16 +494,48 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * return 0; } - mods = lsqlite3_msg_to_mods(ldb, msg, 1); + /* Begin a transaction */ + SQL_EXEC(lsqlite3, begin, TRUE); + + /* Get the dn_id for the specified DN */ + column = + sqlite3_bind_parameter_index( + lsqlite3->queries.getDNID, + ":dn"); + if (sqlite3_bind_text(lsqlite3->queries.getDNID, + column, + msg->dn, strlen(msg->dn), + SQLITE_STATIC) != SQLITE_OK) { + return -1; + } + + /* Get the id of this DN. This sets lsqlite3->last_rc */ + SQL_EXEC(lsqlite3, getDNID, FALSE); + + if (lsqlite3->last_rc != SQLITE_ROW) { + return -1; + } - lsqlite3->last_rc = ldap_modify_s(lsqlite3->ldap, msg->dn, mods); - if (lsqlite3->last_rc != LDAP_SUCCESS) { - ret = -1; - } + dn_id = sqlite3_column_int64(lsqlite3->queries.getDNID, + column); + (void) sqlite3_reset(lsqlite3->queries.getDNID); - talloc_free(mods); + ret = lsqlite3_msg_to_sql(ldb, msg, dn_id, FALSE); - return ret; + /* Did the attribute additions (if any) succeeded? */ + if (ret == 0) + { + /* Yup. Commit the transaction */ + SQL_EXEC(lsqlite3, commit, TRUE); + } + else + { + /* Attribute addition failed. Rollback the transaction */ + SQL_EXEC(lsqlite3, rollback, TRUE); + } + + /* If everything succeeded, return success */ + return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1; } static int lsqlite3_lock(struct ldb_module *module, const char *lockname) @@ -455,10 +554,7 @@ static int lsqlite3_lock(struct ldb_module *module, const char *lockname) } /* Write-lock (but not read-lock) the database */ - lsqlite3->last_rc = sqlite3_step(lsqlite3->begin); - - /* Ready the compiled statement for its next use */ - (void ) sqlite_reset(lsqlite3->begin); + SQL_EXEC(lsqlite3, begin, TRUE); return lsqlite3->last_rc == 0 ? 0 : -1; } @@ -482,18 +578,15 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) if (--lsqlite3->lock_count == 0) { /* Final unlock. Unlock the database */ - lsqlite3->last_rc = sqlite3_step(lsqlite3->commit); - - /* Ready the compiled statement for its next use */ - (void ) sqlite_reset(lsqlite3->commit); + SQL_EXEC(lsqlite3, commit, TRUE); } return lsqlite3->last_rc == 0 ? 0 : -1; } /* - return extended error information -*/ + * return extended error information + */ static const char *lsqlite3_errstring(struct ldb_module *module) { struct lsqlite3_private *lsqlite3 = module->private_data; @@ -577,8 +670,10 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, CREATE TABLE ldb_attr_value_pairs ( dn_id INTEGER REFERENCES ldb_distinguished_names, - attr_name TEXT REFERENCES ldb_attributes, - attr_value TEXT + attr_name TEXT, -- optionally REFERENCES ldb_attributes + attr_value TEXT, + + UNIQUE (dn_id, attr_name, attr_value) ); -- ------------------------------------------------------ @@ -645,7 +740,7 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, INSERT INTO ldb_attributes (attr_name) VALUES ('dn'); - /* We need an implicit "top" level object class */ + /* We need an implicit 'top' level object class */ INSERT INTO ldb_object_classes (class_name, tree_key) SELECT 'top', /* next_tree_key(NULL) */ '0001'; @@ -867,6 +962,15 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, " SELECT :child_class, next_tree_key(:parent_class);" -1, &lsqlite3->queries.insertSubclass, + &pTail)) != SQLITE_SUCCESS || + + (lsqlite3->last_rc = sqlite3_prepare( + lsqlite3->sqlite3, + "SELECT dn_id " + " FROM ldb_distinguished_names " + " WHERE dn = :dn;" + -1, + &lsqlite3->queries.getDNID, &pTail)) != SQLITE_SUCCESS) { (void) sqlite3_close(lsqlite3->sqlite3); @@ -877,11 +981,11 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, } /* - connect to the database -*/ + * connect to the database + */ struct ldb_context *lsqlite3_connect(const char *url, - unsigned int flags, - const char *options[]) + unsigned int flags, + const char *options[]) { struct ldb_context *ldb = NULL; struct lsqlite3_private *lsqlite3 = NULL; @@ -921,8 +1025,10 @@ struct ldb_context *lsqlite3_connect(const char *url, ldb->modules->ops = &lsqlite3_ops; if (options) { - /* take a copy of the options array, so we don't have to rely - on the caller keeping it around (it might be dynamic) */ + /* + * take a copy of the options array, so we don't have to rely + * on the caller keeping it around (it might be dynamic) + */ for (i=0;options[i];i++) ; lsqlite3->options = talloc_array(lsqlite3, char *, i+1); @@ -931,8 +1037,10 @@ struct ldb_context *lsqlite3_connect(const char *url, } for (i=0;options[i];i++) { + lsqlite3->options[i+1] = NULL; - lsqlite3->options[i] = talloc_strdup(lsqlite3->options, options[i]); + lsqlite3->options[i] = + talloc_strdup(lsqlite3->options, options[i]); if (!lsqlite3->options[i]) { goto failed; } diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 46aa4ab7c5..2fa08fdcb7 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -21,6 +21,7 @@ struct lsqlite3_private { sqlite3_stmt *replaceAttrValuePairs; sqlite3_stmt *deleteAttrValuePairs; sqlite3_stmt *insertSubclass; + sqlite3_stmt *getDNID; } queries; }; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index 2ba188c785..d06d7d0c34 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -43,8 +43,10 @@ CREATE TABLE ldb_attr_value_pairs ( dn_id INTEGER REFERENCES ldb_distinguished_names, - attr_name TEXT REFERENCES ldb_attributes, - attr_value TEXT + attr_name TEXT, -- optionally REFERENCES ldb_attributes + attr_value TEXT, + + UNIQUE (dn_id, attr_name, attr_value) ); -- ------------------------------------------------------ -- cgit From 5c1a3defc6ba20fd833c99012c01195f39e515e6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 31 May 2005 01:16:01 +0000 Subject: r7124: fixed a bug in array construction (see ECMA standard section 15.4.2.2) (This used to be commit f9f1d85e651afca7a65804b3124daa11208965e8) --- source4/lib/ejs/ejsProcs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsProcs.c b/source4/lib/ejs/ejsProcs.c index 39df18ef94..b15985c8cf 100644 --- a/source4/lib/ejs/ejsProcs.c +++ b/source4/lib/ejs/ejsProcs.c @@ -171,7 +171,7 @@ static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) mprAssert(obj); - if (argc == 1) { + if (argc == 1 && mprVarIsNumber(argv[0]->type)) { /* * x = new Array(size); */ @@ -181,7 +181,7 @@ static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) mprItoa(i, idx, sizeof(idx)); mprCreateProperty(obj, idx, &undef); } - } else if (argc > 1) { + } else { /* * x = new Array(element0, element1, ..., elementN): */ @@ -190,9 +190,6 @@ static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) mprItoa(i, idx, sizeof(idx)); mprCreateProperty(obj, idx, argv[i]); } - - } else { - max = 0; } lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); -- cgit From 999d0eb6e866c8027c0e1197a58d229f1e14f37e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 31 May 2005 01:48:04 +0000 Subject: r7127: allow for recursive ejs functions (This used to be commit 567bb9568c4e46a4abf9250e7319c702fc3a2fc9) --- source4/lib/ejs/ejsParser.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index d42d66bcf5..17fe0ce98a 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -1128,6 +1128,13 @@ static int parseFunctionDec(Ejs *ep, int state, int flags) mprDestroyVar(&v); return EJS_STATE_ERR; } + + /* register the function name early to allow for recursive + function calls (see note in ECMA standard, page 71) */ + if (!(flags & EJS_FLAGS_ASSIGNMENT)) { + currentObj = ejsFindObj(ep, 0, procName, flags); + vp = mprSetProperty(currentObj, procName, &v); + } /* * Parse the function body. Turn execute off. -- cgit From 913c19cd5b9b43f653652967edf9dc4d9816c79b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 31 May 2005 03:31:54 +0000 Subject: r7133: work in progress, including a HIGHLY revised and simplified schema (This used to be commit aa9bb6ad4cb7219a80a6589d406e47a15ac2c3a1) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 204 +++++++++------- source4/lib/ldb/ldb_sqlite3/schema | 377 ++++++++++++++++++++---------- 2 files changed, 366 insertions(+), 215 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index a0ffffca9e..d36ced2667 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1,22 +1,22 @@ /* ldb database library - + Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -25,7 +25,7 @@ /* * Name: ldb * - * Component: ldb sqlite backend + * Component: ldb sqlite3 backend * * Description: core files for SQLITE3 backend * @@ -39,30 +39,30 @@ #undef SQL_EXEC /* just in case; not expected to be defined */ #define SQL_EXEC(lsqlite3, query, reset) \ - do { \ - lsqlite3->last_rc = \ - sqlite3_step(lsqlite3->queries.query); \ - if (lsqlite3->last_rc == SQLITE_BUSY || reset) \ - (void) sqlite3_reset(lsqlite3->queries.query); \ - } while lsqlite3->last_rc == SQLITE_BUSY; + do { \ + lsqlite3->last_rc = \ + sqlite3_step(lsqlite3->queries.query); \ + if (lsqlite3->last_rc == SQLITE_BUSY || reset) \ + (void) sqlite3_reset(lsqlite3->queries.query); \ + } while lsqlite3->last_rc == SQLITE_BUSY; #if 0 /* * we don't need this right now, but will once we add some backend options + * + * find an option in an option list (a null terminated list of strings) + * + * this assumes the list is short. If it ever gets long then we really should + * do this in some smarter way */ - -/* - find an option in an option list (a null terminated list of strings) - - this assumes the list is short. If it ever gets long then we really - should do this in some smarter way - */ -static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, const char *name) +static const char * +lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, + const char *name) { - int i; - size_t len = strlen(name); + int i; + size_t len = strlen(name); if (!lsqlite3->options) return NULL; @@ -80,10 +80,13 @@ static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, /* * rename a record */ -static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const char *newdn) +static int +lsqlite3_rename(struct ldb_module *module, + const char *olddn, + const char *newdn) { - int column; - struct lsqlite3_private *lsqlite3 = module->private_data; + int column; + struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { @@ -117,11 +120,13 @@ static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const c /* * delete a record */ -static int lsqlite3_delete(struct ldb_module *module, const char *dn) +static int +lsqlite3_delete(struct ldb_module *module, + const char *dn) { - int ret = 0; - int column; - struct lsqlite3_private *lsqlite3 = module->private_data; + int ret = 0; + int column; + struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ if (dn[0] == '@') { @@ -146,7 +151,9 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn) /* * free a search result */ -static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message **res) +static int +lsqlite3_search_free(struct ldb_module *module, + struct ldb_message **res) { talloc_free(res); return 0; @@ -156,12 +163,15 @@ static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message ** /* * add a single set of ldap message values to a ldb_message */ -static int lsqlite3_add_msg_attr(struct ldb_context *ldb, - struct ldb_message *msg, - const char *attr, struct berval **bval) +static int +lsqlite3_add_msg_attr(struct ldb_context *ldb, + struct ldb_message *msg, + const char *attr, + struct berval **bval) { - int count, i; - struct ldb_message_element *el; + int i; + int count; + struct ldb_message_element * el; count = ldap_count_values_len(bval); @@ -211,13 +221,18 @@ static int lsqlite3_add_msg_attr(struct ldb_context *ldb, /* * search for matching records */ -static int lsqlite3_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) +static int +lsqlite3_search(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, + struct ldb_message ***res) { - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; - int count, msg_count; + int count; + int msg_count; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; if (base == NULL) { base = ""; @@ -316,16 +331,18 @@ failed: * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE * requests in the ldb_message */ -static int lsqlite3_msg_to_sql(struct ldb_context *ldb, - const struct ldb_message *msg, - long long dn_id, - int use_flags) +static int +lsqlite3_msg_to_sql(struct ldb_context *ldb, + const struct ldb_message *msg, + long long dn_id, + int use_flags) { - int flags; - unsigned int i, j; - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; - sqlite3_stmt *stmt = NULL; + int flags; + unsigned int i; + unsigned int j; + sqlite3_stmt * stmt = NULL; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; for (i = 0; i < msg->num_elements; i++) { const struct ldb_message_element *el = &msg->elements[i]; @@ -428,11 +445,13 @@ static int lsqlite3_msg_to_sql(struct ldb_context *ldb, /* * add a record */ -static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) +static int +lsqlite3_add(struct ldb_module *module, + const struct ldb_message *msg) { - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; - int ret; + int ret; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ if (msg->dn[0] == '@') { @@ -482,12 +501,13 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg /* * modify a record */ -static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) +static int +lsqlite3_modify(struct ldb_module *module, + const struct ldb_message *msg) { - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; - LDAPMod **mods; - int ret = 0; + int ret = 0; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ if (msg->dn[0] == '@') { @@ -538,11 +558,13 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1; } -static int lsqlite3_lock(struct ldb_module *module, const char *lockname) +static int +lsqlite3_lock(struct ldb_module *module, + const char *lockname) { - int ret = 0; - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; + int ret = 0; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; if (lockname == NULL) { return -1; @@ -559,11 +581,13 @@ static int lsqlite3_lock(struct ldb_module *module, const char *lockname) return lsqlite3->last_rc == 0 ? 0 : -1; } -static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) +static int +lsqlite3_unlock(struct ldb_module *module, + const char *lockname) { - int ret = 0; - struct ldb_context *ldb = module->ldb; - struct lsqlite3_private *lsqlite3 = module->private_data; + int ret = 0; + struct ldb_context * ldb = module->ldb; + struct lsqlite3_private * lsqlite3 = module->private_data; if (lockname == NULL) { return -1; @@ -587,9 +611,11 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) /* * return extended error information */ -static const char *lsqlite3_errstring(struct ldb_module *module) +static const char * +lsqlite3_errstring(struct ldb_module *module) { - struct lsqlite3_private *lsqlite3 = module->private_data; + struct lsqlite3_private * lsqlite3 = module->private_data; + return sqlite3_errmsg(lsqlite3->sqlite3); } @@ -608,22 +634,25 @@ static const struct ldb_module_ops lsqlite3_ops = { }; -static int lsqlite3_destructor(void *p) +static int +lsqlite3_destructor(void *p) { - struct lsqlite3_private *lsqlite3 = p; + struct lsqlite3_private * lsqlite3 = p; + (void) sqlite3_close(lsqlite3->sqlite3); return 0; } -static int lsqlite3_initialize(lsqlite3_private *lsqlite3, - const char *url) +static int +lsqlite3_initialize(lsqlite3_private *lsqlite3, + const char *url) { - int bNewDatabase = False; - char *p; - char *pTail; - struct stat statbuf; - sqlite3_stmt *stmt; - const char *schema = + int bNewDatabase = False; + char * p; + char * pTail; + struct stat statbuf; + sqlite3_stmt * stmt; + const char * schema = " -- ------------------------------------------------------ @@ -983,13 +1012,14 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, /* * connect to the database */ -struct ldb_context *lsqlite3_connect(const char *url, - unsigned int flags, - const char *options[]) +struct ldb_context * +lsqlite3_connect(const char *url, + unsigned int flags, + const char *options[]) { - struct ldb_context *ldb = NULL; - struct lsqlite3_private *lsqlite3 = NULL; - int i; + int i; + struct ldb_context * ldb = NULL; + struct lsqlite3_private * lsqlite3 = NULL; ldb = talloc(NULL, struct ldb_context); if (!ldb) { diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index d06d7d0c34..45be5b578f 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -12,110 +12,163 @@ SELECT 'LDB' AS database_type, '1.0' AS version; - CREATE TABLE ldb_distinguished_names + /* + * Get the next USN value with: + * BEGIN EXCLUSIVE; + * UPDATE usn SET value = value + 1; + * SELECT value FROM usn; + * COMMIT; + */ + CREATE TABLE usn ( - dn_id INTEGER PRIMARY KEY AUTOINCREMENT, - dn TEXT UNIQUE + value INTEGER ); - CREATE TABLE ldb_object_classes + CREATE TABLE ldb_object ( - class_name TEXT PRIMARY KEY, - tree_key TEXT, - max_child_num INTEGER - ); - - CREATE TABLE ldb_dn_object_classes - ( - dn_id INTEGER REFERENCES ldb_distinguished_names, - class_name TEXT REFERENCES ldb_object_classes + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT PRIMARY KEY, + + parent_tree_key TEXT, + full_path TEXT, + + attr_name TEXT REFERENCES ldb_attributes, + attr_value TEXT, + + /* + * object_type can take on these values (to date): + * 1: object is a node of a DN + * 2: object is an attribute/value pair of its parent DN + */ + object_type INTEGER, + + /* + * if object_type is 1, the node can have children. + * this tracks the maximum previously assigned child + * number so we can generate a new unique tree key for + * a new child object. note that this is always incremented, + * so if children are deleted, this will not represent + * the _number_ of children. + */ + max_child_num INTEGER, + + /* + * Automatically maintained meta-data (a gift for metze) + */ + object_guid TEXT UNIQUE, + timestamp INTEGER, -- originating_time + invoke_id TEXT, -- GUID: originating_invocation_id + usn INTEGER, -- hyper: originating_usn + + /* do not allow duplicate name/value pairs */ + UNIQUE (parent_tree_key, attr_name, attr_value, object_type) ); CREATE TABLE ldb_attributes ( attr_name TEXT PRIMARY KEY, - case_insensitive_p BOOLEAN DEFAULT FALSE, - wildcard_p BOOLEAN DEFAULT FALSE, - hidden_p BOOLEAN DEFAULT FALSE, - integer_p BOOLEAN DEFAULT FALSE - ); + parent_tree_key TEXT, - CREATE TABLE ldb_attr_value_pairs - ( - dn_id INTEGER REFERENCES ldb_distinguished_names, - attr_name TEXT, -- optionally REFERENCES ldb_attributes - attr_value TEXT, + objectclass_p BOOLEAN DEFAULT 0, + + case_insensitive_p BOOLEAN DEFAULT 0, + wildcard_p BOOLEAN DEFAULT 0, + hidden_p BOOLEAN DEFAULT 0, + integer_p BOOLEAN DEFAULT 0, - UNIQUE (dn_id, attr_name, attr_value) + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT, -- null if not a object/sub class + -- level 1 if an objectclass + -- level 1-n if a subclass + max_child_num INTEGER ); -- ------------------------------------------------------ - CREATE TRIGGER ldb_distinguished_names_delete_tr - AFTER DELETE - ON ldb_distinguished_names + CREATE INDEX ldb_object_full_path_idx + ON ldb_object (full_path); + + CREATE INDEX ldb_attributes_tree_key_ids + ON ldb_attributes (tree_key); + + -- ------------------------------------------------------ + + /* Gifts for metze. Automatically updated meta-data */ + CREATE TRIGGER ldb_object_insert_tr + AFTER INSERT + ON ldb_object FOR EACH ROW BEGIN - DELETE FROM ldb_attr_value_pairs - WHERE dn_id = old.dn_id; - DELETE FROM ldb_dn_object_classes - WHERE dn_id = old.dn_id; + UPDATE ldb_object + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_object + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0, + object_guid = random_guid(), + timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; END; - CREATE TRIGGER ldb_attr_value_pairs_insert_tr - BEFORE INSERT - ON ldb_attr_value_pairs + CREATE TRIGGER ldb_object_update_tr + AFTER UPDATE + ON ldb_object FOR EACH ROW BEGIN - INSERT OR IGNORE INTO ldb_attributes - (attr_name) - VALUES - (new.attr_name); + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; END; - CREATE TRIGGER ldb_attr_value_pairs_delete_tr - AFTER DELETE - ON ldb_attr_value_pairs + CREATE TRIGGER ldb_attributes_insert_tr + AFTER INSERT + ON ldb_attributes FOR EACH ROW BEGIN - DELETE FROM ldb_attributes - WHERE (SELECT COUNT(*) - FROM ldb_attr_value_pairs - WHERE attr_name = old.attr_name) = 0 - AND attr_name = old.attr_name; + UPDATE ldb_attributes + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE ldb_attributes + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_attributes + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0 + WHERE tree_key = new.tree_key; END; - -- ------------------------------------------------------ - - CREATE INDEX ldb_distinguished_names_dn_idx - ON ldb_distinguished_names (dn); - - CREATE INDEX ldb_object_classes_tree_key_idx - ON ldb_object_classes (tree_key); - - - CREATE INDEX ldb_dn_object_classes_dn_id_idx - ON ldb_dn_object_classes (dn_id); - - CREATE INDEX ldb_dn_object_classes_class_name_idx - ON ldb_dn_object_classes (class_name); - - - CREATE INDEX ldb_attr_value_pairs_dn_id_name_case_idx - ON ldb_attr_value_pairs (dn_id, attr_name); - - CREATE INDEX ldb_attr_value_pairs_dn_id_name_nocase_idx - ON ldb_attr_value_pairs (dn_id, attr_name COLLATE NOCASE); -- ------------------------------------------------------ - /* all defaults for dn, initially */ - INSERT INTO ldb_attributes (attr_name) - VALUES ('dn'); + /* Initialize usn */ + INSERT INTO usn (value) VALUES (0); + + /* Create root object */ + INSERT INTO ldb_object + (tree_key, parent_tree_key, + full_path, + object_type, max_child_num) + VALUES ('', NULL, + '', + 1, 0); /* We need an implicit "top" level object class */ - INSERT INTO ldb_object_classes (class_name, tree_key) - SELECT 'top', /* next_tree_key(NULL) */ '0001'; + INSERT INTO ldb_attributes (attr_name, + parent_tree_key) + SELECT 'top', ''; -- ------------------------------------------------------ @@ -129,63 +182,103 @@ * objectclass: domainRelatedObject */ -- newDN -INSERT INTO ldb_distinguished_names (dn_id, dn) - VALUES (1, 'o=University of Michigan,c=US'); +BEGIN; + +INSERT OR IGNORE INTO ldb_object + (parent_tree_key + full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('', + 'c=US', + 'c', 'US', 1, 0); + +INSERT INTO ldb_object + (parent_tree_key, + full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('0001', + 'o=University of Michigan,c=US', + 'o', 'University of Michigan', 1, 0); -- newObjectClass -INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key) - SELECT 'organization', /* next_tree_key(NULL) */ '0002'; - -INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key) - SELECT 'domainRelatedObject', /* next_tree_key(NULL) */ '0003'; +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'organization', 2, 0); + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'domainRelatedObject', 2, 0); + +COMMIT; --- assignObjectClass -INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name) - VALUES (1, 'organization'); - -INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name) - VALUES (1, 'domainRelatedObject'); /* + * dn: o=University of Michigan,c=US * l: Ann Arbor, Michigan * st: Michigan * o: University of Michigan * o: UMICH - * o: UM - * o: U-M - * o: U of M - * description: The University of Michigan at Ann Arbor * seeAlso: - * postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 - * 09 $ US * telephonenumber: +1 313 764-1817 - * associateddomain: example.com */ -- addAttrValuePair -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'l', 'Ann Arbor, Michigan'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'st', 'Michigan'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'o', 'University of Michigan'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'o', 'UMICH'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'o', 'UM'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'o', 'U-M'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'o', 'U of M'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'description', 'The University of Michigan at Ann Arbor'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'seeAlso', ''); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'postaladdress', 'University of Michigan $ 535 W. William St. $ Ann Arbor, MI 48109 $ US'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'telephonenumber', '+1 313 764-1817'); -INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) - VALUES (1, 'associateddomain', 'example.com'); +BEGIN; + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'l', 'Ann Arbor, Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'st', 'Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'University of Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'UMICH', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'seeAlso', '', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, full_path, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'telephonenumber', '+1 313 764-1817', 2, 0); + +COMMIT; -- ---------------------------------------------------------------------- @@ -197,18 +290,41 @@ INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value) * dn: CASE_INSENSITIVE */ -- newAttribute -INSERT OR REPLACE INTO ldb_attributes - (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) - VALUES ('uid', 1, 1, 0, 0); -INSERT OR REPLACE INTO ldb_attributes - (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) - VALUES ('cn', 1, 0, 0, 0); -INSERT OR REPLACE INTO ldb_attributes - (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) - VALUES ('ou', 1, 0, 0, 0); -INSERT OR REPLACE INTO ldb_attributes - (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p) - VALUES ('dn', 1, 0, 0, 0); + +BEGIN; + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('uid', '', 0); + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 1, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'uid' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'cn' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'ou' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'dn' -- ---------------------------------------------------------------------- @@ -224,6 +340,10 @@ INSERT OR REPLACE INTO ldb_attributes * user: computer */ -- insertSubclass + +/* NOT YET UPDATED!!! * + + INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) SELECT 'domain', /* next_tree_key('top') */ '00010001'; INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) @@ -240,3 +360,4 @@ INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002'; INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) SELECT 'computer', /* next_tree_key('user') */ '0001000200010001'; + -- cgit From e4a505192d23c7d77a6ee68e6e2946bab983ae43 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 1 Jun 2005 10:16:35 +0000 Subject: r7166: Move replacement stuff to seperate directory (easier to add win32-specific bits later) Trim LIBBASIC a bit more (This used to be commit fc7f519e4ae2051e9515df5f549c8e1842b7e70b) --- source4/lib/basic.mk | 16 +- source4/lib/dprintf.c | 6 - source4/lib/replace.c | 564 ----------------------- source4/lib/replace/replace.c | 564 +++++++++++++++++++++++ source4/lib/replace/snprintf.c | 981 +++++++++++++++++++++++++++++++++++++++++ source4/lib/snprintf.c | 981 ----------------------------------------- source4/lib/util_file.c | 2 +- 7 files changed, 1556 insertions(+), 1558 deletions(-) delete mode 100644 source4/lib/replace.c create mode 100644 source4/lib/replace/replace.c create mode 100644 source4/lib/replace/snprintf.c delete mode 100644 source4/lib/snprintf.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 5c094a6973..02783366ca 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -3,9 +3,9 @@ ############################## # Start SUBSYSTEM LIBREPLACE [SUBSYSTEM::LIBREPLACE] -INIT_OBJ_FILES = lib/replace.o +INIT_OBJ_FILES = lib/replace/replace.o ADD_OBJ_FILES = \ - lib/snprintf.o + lib/replace/snprintf.o # End SUBSYSTEM LIBREPLACE ############################## @@ -49,11 +49,19 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBSAMBA3 ################################################ +[SUBSYSTEM::PAM_ERRORS] +OBJ_FILES = lib/pam_errors.o + +[SUBSYSTEM::GENCACHE] +OBJ_FILES = \ + lib/gencache.o \ + ############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] INIT_OBJ_FILES = lib/version.o ADD_OBJ_FILES = \ + lib/xfile.o \ lib/debug.o \ lib/fault.o \ lib/pidfile.o \ @@ -62,7 +70,6 @@ ADD_OBJ_FILES = \ lib/time.o \ lib/genrand.o \ lib/dprintf.o \ - lib/xfile.o \ lib/util_str.o \ lib/util_strlist.o \ lib/util_unistr.o \ @@ -74,14 +81,11 @@ ADD_OBJ_FILES = \ lib/fsusage.o \ lib/ms_fnmatch.o \ lib/select.o \ - lib/pam_errors.o \ - intl/lang_tdb.o \ lib/mutex.o \ lib/server_mutex.o \ lib/idtree.o \ lib/unix_privs.o \ lib/db_wrap.o \ - lib/gencache.o \ lib/gendb.o \ lib/credentials.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/lib/dprintf.c b/source4/lib/dprintf.c index 5538c490ce..6653fa4242 100644 --- a/source4/lib/dprintf.c +++ b/source4/lib/dprintf.c @@ -38,16 +38,10 @@ int d_vfprintf(FILE *f, const char *format, va_list ap) _PRINTF_ATTRIBUTE(2,0) char *msgstr; va_list ap2; - /* do any message translations */ - msgstr = lang_msg(format); - if (!msgstr) return -1; - VA_COPY(ap2, ap); ret = vasprintf(&p, msgstr, ap2); - lang_msg_free(msgstr); - if (ret <= 0) return ret; /* now we have the string in unix format, convert it to the display diff --git a/source4/lib/replace.c b/source4/lib/replace.c deleted file mode 100644 index 89612912b7..0000000000 --- a/source4/lib/replace.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - Unix SMB/CIFS implementation. - replacement routines for broken systems - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "system/wait.h" -#include "system/time.h" -#include "system/network.h" - - void replace_dummy(void); - void replace_dummy(void) {} - -#ifndef HAVE_FTRUNCATE - /******************************************************************* -ftruncate for operating systems that don't have it -********************************************************************/ - int ftruncate(int f,off_t l) -{ -#ifdef HAVE_CHSIZE - return chsize(f,l); -#else - struct flock fl; - - fl.l_whence = 0; - fl.l_len = 0; - fl.l_start = l; - fl.l_type = F_WRLCK; - return fcntl(f, F_FREESP, &fl); -#endif -} -#endif /* HAVE_FTRUNCATE */ - - -#ifndef HAVE_STRLCPY -/* like strncpy but does not 0 fill the buffer and always null - terminates. bufsize is the size of the destination buffer */ - size_t strlcpy(char *d, const char *s, size_t bufsize) -{ - size_t len = strlen(s); - size_t ret = len; - if (bufsize <= 0) return 0; - if (len >= bufsize) len = bufsize-1; - memcpy(d, s, len); - d[len] = 0; - return ret; -} -#endif - -#ifndef HAVE_STRLCAT -/* like strncat but does not 0 fill the buffer and always null - terminates. bufsize is the length of the buffer, which should - be one more than the maximum resulting string length */ - size_t strlcat(char *d, const char *s, size_t bufsize) -{ - size_t len1 = strlen(d); - size_t len2 = strlen(s); - size_t ret = len1 + len2; - - if (len1+len2 >= bufsize) { - len2 = bufsize - (len1+1); - } - if (len2 > 0) { - memcpy(d+len1, s, len2); - d[len1+len2] = 0; - } - return ret; -} -#endif - -#ifndef HAVE_MKTIME -/******************************************************************* -a mktime() replacement for those who don't have it - contributed by -C.A. Lademann -Corrections by richard.kettlewell@kewill.com -********************************************************************/ - -#define MINUTE 60 -#define HOUR 60*MINUTE -#define DAY 24*HOUR -#define YEAR 365*DAY - time_t mktime(struct tm *t) -{ - struct tm *u; - time_t epoch = 0; - int n; - int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - y, m, i; - - if(t->tm_year < 70) - return((time_t)-1); - - n = t->tm_year + 1900 - 1; - epoch = (t->tm_year - 70) * YEAR + - ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; - - y = t->tm_year + 1900; - m = 0; - - for(i = 0; i < t->tm_mon; i++) { - epoch += mon [m] * DAY; - if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) - epoch += DAY; - - if(++m > 11) { - m = 0; - y++; - } - } - - epoch += (t->tm_mday - 1) * DAY; - epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; - - if((u = localtime(&epoch)) != NULL) { - t->tm_sec = u->tm_sec; - t->tm_min = u->tm_min; - t->tm_hour = u->tm_hour; - t->tm_mday = u->tm_mday; - t->tm_mon = u->tm_mon; - t->tm_year = u->tm_year; - t->tm_wday = u->tm_wday; - t->tm_yday = u->tm_yday; - t->tm_isdst = u->tm_isdst; - } - - return(epoch); -} -#endif /* !HAVE_MKTIME */ - - - -#ifndef HAVE_RENAME -/* Rename a file. (from libiberty in GNU binutils) */ - int rename(const char *zfrom, const char *zto) -{ - if (link (zfrom, zto) < 0) - { - if (errno != EEXIST) - return -1; - if (unlink (zto) < 0 - || link (zfrom, zto) < 0) - return -1; - } - return unlink (zfrom); -} -#endif /* HAVE_RENAME */ - - -#ifndef HAVE_INNETGR -#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT) -/* - * Search for a match in a netgroup. This replaces it on broken systems. - */ - int innetgr(const char *group,const char *host,const char *user,const char *dom) -{ - char *hst, *usr, *dm; - - setnetgrent(group); - while (getnetgrent(&hst, &usr, &dm)) { - if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && - ((user == 0) || (usr == 0) || !strcmp(user, usr)) && - ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { - endnetgrent(); - return (1); - } - } - endnetgrent(); - return (0); -} -#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */ -#endif /* HAVE_INNETGR */ - - - -#ifndef HAVE_INITGROUPS -/**************************************************************************** - some systems don't have an initgroups call -****************************************************************************/ - int initgroups(char *name,gid_t id) -{ -#ifndef HAVE_SETGROUPS - static int done; - if (!done) { - DEBUG(1,("WARNING: running without setgroups\n")); - done=1; - } - /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ - return(0); -#else /* HAVE_SETGROUPS */ - gid_t *grouplst = NULL; - int max_gr = groups_max(); - int ret; - int i,j; - struct group *g; - char *gr; - - if((grouplst = malloc_array_p(gid_t, max_gr)) == NULL) { - DEBUG(0,("initgroups: malloc fail !\n")); - return -1; - } - - grouplst[0] = id; - i = 1; - while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { - if (g->gr_gid == id) - continue; - j = 0; - gr = g->gr_mem[0]; - while (gr && (*gr != (char)NULL)) { - if (strcmp(name,gr) == 0) { - grouplst[i] = g->gr_gid; - i++; - gr = (char *)NULL; - break; - } - gr = g->gr_mem[++j]; - } - } - endgrent(); - ret = sys_setgroups(i,grouplst); - SAFE_FREE(grouplst); - return ret; -#endif /* HAVE_SETGROUPS */ -} -#endif /* HAVE_INITGROUPS */ - - -#if (defined(SecureWare) && defined(SCO)) -/* This is needed due to needing the nap() function but we don't want - to include the Xenix libraries since that will break other things... - BTW: system call # 0x0c28 is the same as calling nap() */ - long nap(long milliseconds) { - return syscall(0x0c28, milliseconds); - } -#endif - - -#ifndef HAVE_MEMMOVE -/******************************************************************* -safely copies memory, ensuring no overlap problems. -this is only used if the machine does not have it's own memmove(). -this is not the fastest algorithm in town, but it will do for our -needs. -********************************************************************/ - void *memmove(void *dest,const void *src,int size) -{ - unsigned long d,s; - int i; - if (dest==src || !size) return(dest); - - d = (unsigned long)dest; - s = (unsigned long)src; - - if ((d >= (s+size)) || (s >= (d+size))) { - /* no overlap */ - memcpy(dest,src,size); - return(dest); - } - - if (d < s) { - /* we can forward copy */ - if (s-d >= sizeof(int) && - !(s%sizeof(int)) && - !(d%sizeof(int)) && - !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=0;i= sizeof(int) && - !(s%sizeof(int)) && - !(d%sizeof(int)) && - !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=size-1;i>=0;i--) idest[i] = isrc[i]; - } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; - } - } - return(dest); -} -#endif /* HAVE_MEMMOVE */ - -#ifndef HAVE_STRDUP -/**************************************************************************** -duplicate a string -****************************************************************************/ - char *strdup(const char *s) -{ - size_t len; - char *ret; - - if (!s) return(NULL); - - len = strlen(s)+1; - ret = (char *)malloc(len); - if (!ret) return(NULL); - memcpy(ret,s,len); - return(ret); -} -#endif /* HAVE_STRDUP */ - -#ifndef WITH_PTHREADS -/* REWRITE: not thread safe */ -#ifdef REPLACE_INET_NTOA - char *rep_inet_ntoa(struct in_addr ip) -{ - uint8_t *p = (uint8_t *)&ip.s_addr; - static char buf[18]; - slprintf(buf, 17, "%d.%d.%d.%d", - (int)p[0], (int)p[1], (int)p[2], (int)p[3]); - return buf; -} -#endif /* REPLACE_INET_NTOA */ -#endif - -#ifndef HAVE_STRTOUL -#ifndef ULONG_MAX -#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ -#endif - -/* - * Convert a string to an unsigned long integer. - * Taken from libg++ - libiberty code. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ - unsigned long strtoul(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') { - neg = 1; - c = *s++; - } else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base); - for (acc = 0, any = 0;; c = *s++) { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *) (any ? s - 1 : nptr); - return (acc); -} -#endif /* HAVE_STRTOUL */ - -#ifndef HAVE_SETLINEBUF - int setlinebuf(FILE *stream) -{ - return setvbuf(stream, (char *)NULL, _IOLBF, 0); -} -#endif /* HAVE_SETLINEBUF */ - -#ifndef HAVE_VSYSLOG -#ifdef HAVE_SYSLOG - void vsyslog (int facility_priority, char *format, va_list arglist) -{ - char *msg = NULL; - vasprintf(&msg, format, arglist); - if (!msg) - return; - syslog(facility_priority, "%s", msg); - SAFE_FREE(msg); -} -#endif /* HAVE_SYSLOG */ -#endif /* HAVE_VSYSLOG */ - -/******************************************************************* -yield the difference between *A and *B, in seconds, ignoring leap seconds -********************************************************************/ -static int tm_diff(struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (1900 - 1); - int by = b->tm_year + (1900 - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; -} - -/******************************************************************* - return the UTC offset in seconds west of UTC, or 0 if it cannot be determined - ******************************************************************/ -int get_time_zone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - if (!tm) - return 0; - tm_utc = *tm; - tm = localtime(&t); - if (!tm) - return 0; - return tm_diff(&tm_utc,tm); -} - -#ifndef HAVE_TIMEGM -/* - yes, I know this looks insane, but its really needed. The function in the - Linux timegm() manpage does not work on solaris. -*/ - time_t timegm(struct tm *tm) -{ - struct tm tm2, tm3; - time_t t; - - tm2 = *tm; - - t = mktime(&tm2); - tm3 = *localtime(&t); - tm2 = *tm; - tm2.tm_isdst = tm3.tm_isdst; - t = mktime(&tm2); - t -= get_time_zone(t); - - return t; -} -#endif - -#ifndef HAVE_SETENV - int setenv(const char *name, const char *value, int overwrite) -{ - char *p = NULL; - int ret = -1; - - asprintf(&p, "%s=%s", name, value); - - if (overwrite || getenv(name)) { - if (p) ret = putenv(p); - } else { - ret = 0; - } - - return ret; -} -#endif - - -#ifndef HAVE_STRTOULL - unsigned long long int strtoull(const char *str, char **endptr, int base) -{ -#ifdef HAVE_STRTOUQ - return strtouq(str, endptr, base); -#else -#error "system must support 64 bit integer read from strings" -#endif -} -#endif - - -#ifndef HAVE_STRNDUP -/** - Some platforms don't have strndup. -**/ - char *strndup(const char *s, size_t n) -{ - char *ret; - - n = strnlen(s, n); - ret = malloc(n+1); - if (!ret) - return NULL; - memcpy(ret, s, n); - ret[n] = 0; - - return ret; -} -#endif - -#ifndef HAVE_STRNLEN -/** - Some platforms don't have strnlen -**/ - size_t strnlen(const char *s, size_t n) -{ - int i; - for (i=0; s[i] && i= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ + size_t strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif + +#ifndef HAVE_MKTIME +/******************************************************************* +a mktime() replacement for those who don't have it - contributed by +C.A. Lademann +Corrections by richard.kettlewell@kewill.com +********************************************************************/ + +#define MINUTE 60 +#define HOUR 60*MINUTE +#define DAY 24*HOUR +#define YEAR 365*DAY + time_t mktime(struct tm *t) +{ + struct tm *u; + time_t epoch = 0; + int n; + int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + y, m, i; + + if(t->tm_year < 70) + return((time_t)-1); + + n = t->tm_year + 1900 - 1; + epoch = (t->tm_year - 70) * YEAR + + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; + + y = t->tm_year + 1900; + m = 0; + + for(i = 0; i < t->tm_mon; i++) { + epoch += mon [m] * DAY; + if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) + epoch += DAY; + + if(++m > 11) { + m = 0; + y++; + } + } + + epoch += (t->tm_mday - 1) * DAY; + epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; + + if((u = localtime(&epoch)) != NULL) { + t->tm_sec = u->tm_sec; + t->tm_min = u->tm_min; + t->tm_hour = u->tm_hour; + t->tm_mday = u->tm_mday; + t->tm_mon = u->tm_mon; + t->tm_year = u->tm_year; + t->tm_wday = u->tm_wday; + t->tm_yday = u->tm_yday; + t->tm_isdst = u->tm_isdst; + } + + return(epoch); +} +#endif /* !HAVE_MKTIME */ + + + +#ifndef HAVE_RENAME +/* Rename a file. (from libiberty in GNU binutils) */ + int rename(const char *zfrom, const char *zto) +{ + if (link (zfrom, zto) < 0) + { + if (errno != EEXIST) + return -1; + if (unlink (zto) < 0 + || link (zfrom, zto) < 0) + return -1; + } + return unlink (zfrom); +} +#endif /* HAVE_RENAME */ + + +#ifndef HAVE_INNETGR +#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT) +/* + * Search for a match in a netgroup. This replaces it on broken systems. + */ + int innetgr(const char *group,const char *host,const char *user,const char *dom) +{ + char *hst, *usr, *dm; + + setnetgrent(group); + while (getnetgrent(&hst, &usr, &dm)) { + if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && + ((user == 0) || (usr == 0) || !strcmp(user, usr)) && + ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { + endnetgrent(); + return (1); + } + } + endnetgrent(); + return (0); +} +#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */ +#endif /* HAVE_INNETGR */ + + + +#ifndef HAVE_INITGROUPS +/**************************************************************************** + some systems don't have an initgroups call +****************************************************************************/ + int initgroups(char *name,gid_t id) +{ +#ifndef HAVE_SETGROUPS + static int done; + if (!done) { + DEBUG(1,("WARNING: running without setgroups\n")); + done=1; + } + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ + return(0); +#else /* HAVE_SETGROUPS */ + gid_t *grouplst = NULL; + int max_gr = groups_max(); + int ret; + int i,j; + struct group *g; + char *gr; + + if((grouplst = malloc_array_p(gid_t, max_gr)) == NULL) { + DEBUG(0,("initgroups: malloc fail !\n")); + return -1; + } + + grouplst[0] = id; + i = 1; + while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { + if (g->gr_gid == id) + continue; + j = 0; + gr = g->gr_mem[0]; + while (gr && (*gr != (char)NULL)) { + if (strcmp(name,gr) == 0) { + grouplst[i] = g->gr_gid; + i++; + gr = (char *)NULL; + break; + } + gr = g->gr_mem[++j]; + } + } + endgrent(); + ret = sys_setgroups(i,grouplst); + SAFE_FREE(grouplst); + return ret; +#endif /* HAVE_SETGROUPS */ +} +#endif /* HAVE_INITGROUPS */ + + +#if (defined(SecureWare) && defined(SCO)) +/* This is needed due to needing the nap() function but we don't want + to include the Xenix libraries since that will break other things... + BTW: system call # 0x0c28 is the same as calling nap() */ + long nap(long milliseconds) { + return syscall(0x0c28, milliseconds); + } +#endif + + +#ifndef HAVE_MEMMOVE +/******************************************************************* +safely copies memory, ensuring no overlap problems. +this is only used if the machine does not have it's own memmove(). +this is not the fastest algorithm in town, but it will do for our +needs. +********************************************************************/ + void *memmove(void *dest,const void *src,int size) +{ + unsigned long d,s; + int i; + if (dest==src || !size) return(dest); + + d = (unsigned long)dest; + s = (unsigned long)src; + + if ((d >= (s+size)) || (s >= (d+size))) { + /* no overlap */ + memcpy(dest,src,size); + return(dest); + } + + if (d < s) { + /* we can forward copy */ + if (s-d >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=0;i= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + } + } + return(dest); +} +#endif /* HAVE_MEMMOVE */ + +#ifndef HAVE_STRDUP +/**************************************************************************** +duplicate a string +****************************************************************************/ + char *strdup(const char *s) +{ + size_t len; + char *ret; + + if (!s) return(NULL); + + len = strlen(s)+1; + ret = (char *)malloc(len); + if (!ret) return(NULL); + memcpy(ret,s,len); + return(ret); +} +#endif /* HAVE_STRDUP */ + +#ifndef WITH_PTHREADS +/* REWRITE: not thread safe */ +#ifdef REPLACE_INET_NTOA + char *rep_inet_ntoa(struct in_addr ip) +{ + uint8_t *p = (uint8_t *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} +#endif /* REPLACE_INET_NTOA */ +#endif + +#ifndef HAVE_STRTOUL +#ifndef ULONG_MAX +#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ +#endif + +/* + * Convert a string to an unsigned long integer. + * Taken from libg++ - libiberty code. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ + unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base); + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} +#endif /* HAVE_STRTOUL */ + +#ifndef HAVE_SETLINEBUF + int setlinebuf(FILE *stream) +{ + return setvbuf(stream, (char *)NULL, _IOLBF, 0); +} +#endif /* HAVE_SETLINEBUF */ + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG + void vsyslog (int facility_priority, char *format, va_list arglist) +{ + char *msg = NULL; + vasprintf(&msg, format, arglist); + if (!msg) + return; + syslog(facility_priority, "%s", msg); + SAFE_FREE(msg); +} +#endif /* HAVE_SYSLOG */ +#endif /* HAVE_VSYSLOG */ + +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + +/******************************************************************* + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + ******************************************************************/ +int get_time_zone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); +} + +#ifndef HAVE_TIMEGM +/* + yes, I know this looks insane, but its really needed. The function in the + Linux timegm() manpage does not work on solaris. +*/ + time_t timegm(struct tm *tm) +{ + struct tm tm2, tm3; + time_t t; + + tm2 = *tm; + + t = mktime(&tm2); + tm3 = *localtime(&t); + tm2 = *tm; + tm2.tm_isdst = tm3.tm_isdst; + t = mktime(&tm2); + t -= get_time_zone(t); + + return t; +} +#endif + +#ifndef HAVE_SETENV + int setenv(const char *name, const char *value, int overwrite) +{ + char *p = NULL; + int ret = -1; + + asprintf(&p, "%s=%s", name, value); + + if (overwrite || getenv(name)) { + if (p) ret = putenv(p); + } else { + ret = 0; + } + + return ret; +} +#endif + + +#ifndef HAVE_STRTOULL + unsigned long long int strtoull(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOUQ + return strtouq(str, endptr, base); +#else +#error "system must support 64 bit integer read from strings" +#endif +} +#endif + + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ + char *strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + size_t strnlen(const char *s, size_t n) +{ + int i; + for (i=0; s[i] && i 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + **************************************************************/ + +#ifndef NO_CONFIG_H /* for some tests */ +#include "config.h" +#else +#define NULL 0 +#endif + +#ifdef TEST_SNPRINTF /* need math library headers for testing */ +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#elif defined(HAVE___VA_COPY) +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include + /* make the compiler happy with an empty file */ + void dummy_snprintf(void) {} +#else + +#ifdef HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#endif + +static size_t dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + va_list args; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10*min + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } else { + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, LLONG); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (long)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (!strvalue) strvalue = "(NULL)"; + if (max == -1) { + max = strlen(strvalue); + } + if (min > 0 && max >= 0 && min > max) max = min; + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { + long int *num; + num = va_arg (args, long int *); + *num = (long int)currlen; + } else if (cflags == DP_C_LLONG) { + LLONG *num; + num = va_arg (args, LLONG *); + *num = (LLONG)currlen; + } else { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + + return currlen; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = ""; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + long l; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int index; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 16 digits past the decimal because of our + * conversion method + */ + if (max > 16) + max = 16; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + index = (int) ((temp -intpart +0.05)* 10.0); + /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, index); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + index = (int) ((temp -fracpart +0.05)* 10.0); + /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +/* yes this really must be a ||. Don't muck wiith this (tridge) + * + * The logic for these two is that we need our own definition if the + * OS *either* has no definition of *sprintf, or if it does have one + * that doesn't work properly according to the autoconf test. Perhaps + * these should really be smb_snprintf to avoid conflicts with buggy + * linkers? -- mbp + */ +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF) + int snprintf(char *str,size_t count,const char *fmt,...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#endif + +#ifndef HAVE_VASPRINTF + int vasprintf(char **ptr, const char *format, va_list ap) +{ + int ret; + va_list ap2; + + VA_COPY(ap2, ap); + + ret = vsnprintf(NULL, 0, format, ap2); + if (ret <= 0) return ret; + + (*ptr) = (char *)malloc(ret+1); + if (!*ptr) return -1; + + VA_COPY(ap2, ap); + + ret = vsnprintf(*ptr, ret+1, format, ap2); + + return ret; +} +#endif + + +#ifndef HAVE_ASPRINTF + int asprintf(char **ptr, const char *format, ...) +{ + va_list ap; + int ret; + + *ptr = NULL; + va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + int sprintf(char *str,const char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "-16.16f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 5.030201, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + char *str_fmt[] = { + "10.5s", + "5.10s", + "10.1s", + "0.10s", + "10.0s", + "1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + fp_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + int_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); + int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + sprintf (buf2, str_fmt[x], str_vals[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + str_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); + fail++; + } + num++; + } + } + + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + double p = pow(10, x); + double r = v0*p; + snprintf(buf1, sizeof(buf1), "%1.1f", r); + sprintf(buf2, "%1.1f", r); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* SNPRINTF_TEST */ diff --git a/source4/lib/snprintf.c b/source4/lib/snprintf.c deleted file mode 100644 index adfd3c4d78..0000000000 --- a/source4/lib/snprintf.c +++ /dev/null @@ -1,981 +0,0 @@ -/* - * Copyright Patrick Powell 1995 - * This code is based on code written by Patrick Powell (papowell@astart.com) - * It may be used for any purpose as long as this notice remains intact - * on all source code distributions - */ - -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - * - * More Recently: - * Brandon Long 9/15/96 for mutt 0.43 - * This was ugly. It is still ugly. I opted out of floating point - * numbers, but the formatter understands just about everything - * from the normal C string format, at least as far as I can tell from - * the Solaris 2.5 printf(3S) man page. - * - * Brandon Long 10/22/97 for mutt 0.87.1 - * Ok, added some minimal floating point support, which means this - * probably requires libm on most operating systems. Don't yet - * support the exponent (e,E) and sigfig (g,G). Also, fmtint() - * was pretty badly broken, it just wasn't being exercised in ways - * which showed it, so that's been fixed. Also, formated the code - * to mutt conventions, and removed dead code left over from the - * original. Also, there is now a builtin-test, just compile with: - * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm - * and run snprintf for results. - * - * Thomas Roessler 01/27/98 for mutt 0.89i - * The PGP code was using unsigned hexadecimal formats. - * Unfortunately, unsigned formats simply didn't work. - * - * Michael Elkins 03/05/98 for mutt 0.90.8 - * The original code assumed that both snprintf() and vsnprintf() were - * missing. Some systems only have snprintf() but not vsnprintf(), so - * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. - * - * Andrew Tridgell (tridge@samba.org) Oct 1998 - * fixed handling of %.0f - * added test for HAVE_LONG_DOUBLE - * - * tridge@samba.org, idra@samba.org, April 2001 - * got rid of fcvt code (twas buggy and made testing harder) - * added C99 semantics - * - **************************************************************/ - -#ifndef NO_CONFIG_H /* for some tests */ -#include "config.h" -#else -#define NULL 0 -#endif - -#ifdef TEST_SNPRINTF /* need math library headers for testing */ -#include -#endif - -#ifdef HAVE_STRING_H -#include -#endif - -#ifdef HAVE_STRINGS_H -#include -#endif -#ifdef HAVE_CTYPE_H -#include -#endif -#include -#include -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) va_copy(dest, src) -#elif defined(HAVE___VA_COPY) -#define VA_COPY(dest, src) __va_copy(dest, src) -#else -#define VA_COPY(dest, src) (dest) = (src) -#endif -#endif - - -#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) -/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ -#include - /* make the compiler happy with an empty file */ - void dummy_snprintf(void) {} -#else - -#ifdef HAVE_LONG_DOUBLE -#define LDOUBLE long double -#else -#define LDOUBLE double -#endif - -#ifdef HAVE_LONG_LONG -#define LLONG long long -#else -#define LLONG long -#endif - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) -#endif - -static size_t dopr(char *buffer, size_t maxlen, const char *format, - va_list args_in); -static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max); -static void fmtint(char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags); -static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags); -static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); - -/* - * dopr(): poor man's version of doprintf - */ - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) - -/* Conversion Flags */ -#define DP_C_SHORT 1 -#define DP_C_LONG 2 -#define DP_C_LDOUBLE 3 -#define DP_C_LLONG 4 - -#define char_to_int(p) ((p)- '0') -#ifndef MAX -#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) -#endif - -static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) -{ - char ch; - LLONG value; - LDOUBLE fvalue; - char *strvalue; - int min; - int max; - int state; - int flags; - int cflags; - size_t currlen; - va_list args; - - VA_COPY(args, args_in); - - state = DP_S_DEFAULT; - currlen = flags = cflags = min = 0; - max = -1; - ch = *format++; - - while (state != DP_S_DONE) { - if (ch == '\0') - state = DP_S_DONE; - - switch(state) { - case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - dopr_outch (buffer, &currlen, maxlen, ch); - ch = *format++; - break; - case DP_S_FLAGS: - switch (ch) { - case '-': - flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - flags |= DP_F_ZERO; - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (isdigit((unsigned char)ch)) { - min = 10*min + char_to_int (ch); - ch = *format++; - } else if (ch == '*') { - min = va_arg (args, int); - ch = *format++; - state = DP_S_DOT; - } else { - state = DP_S_DOT; - } - break; - case DP_S_DOT: - if (ch == '.') { - state = DP_S_MAX; - ch = *format++; - } else { - state = DP_S_MOD; - } - break; - case DP_S_MAX: - if (isdigit((unsigned char)ch)) { - if (max < 0) - max = 0; - max = 10*max + char_to_int (ch); - ch = *format++; - } else if (ch == '*') { - max = va_arg (args, int); - ch = *format++; - state = DP_S_MOD; - } else { - state = DP_S_MOD; - } - break; - case DP_S_MOD: - switch (ch) { - case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; - case 'l': - cflags = DP_C_LONG; - ch = *format++; - if (ch == 'l') { /* It's a long long */ - cflags = DP_C_LLONG; - ch = *format++; - } - break; - case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - switch (ch) { - case 'd': - case 'i': - if (cflags == DP_C_SHORT) - value = va_arg (args, int); - else if (cflags == DP_C_LONG) - value = va_arg (args, long int); - else if (cflags == DP_C_LLONG) - value = va_arg (args, LLONG); - else - value = va_arg (args, int); - fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'o': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned int); - else if (cflags == DP_C_LONG) - value = (long)va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = (long)va_arg (args, unsigned LLONG); - else - value = (long)va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); - break; - case 'u': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned int); - else if (cflags == DP_C_LONG) - value = (long)va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = (LLONG)va_arg (args, unsigned LLONG); - else - value = (long)va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'X': - flags |= DP_F_UP; - case 'x': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned int); - else if (cflags == DP_C_LONG) - value = (long)va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = (LLONG)va_arg (args, unsigned LLONG); - else - value = (long)va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); - break; - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - /* um, floating point? */ - fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'E': - flags |= DP_F_UP; - case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'G': - flags |= DP_F_UP; - case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'c': - dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); - break; - case 's': - strvalue = va_arg (args, char *); - if (!strvalue) strvalue = "(NULL)"; - if (max == -1) { - max = strlen(strvalue); - } - if (min > 0 && max >= 0 && min > max) max = min; - fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); - break; - case 'p': - strvalue = va_arg (args, void *); - fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); - break; - case 'n': - if (cflags == DP_C_SHORT) { - short int *num; - num = va_arg (args, short int *); - *num = currlen; - } else if (cflags == DP_C_LONG) { - long int *num; - num = va_arg (args, long int *); - *num = (long int)currlen; - } else if (cflags == DP_C_LLONG) { - LLONG *num; - num = va_arg (args, LLONG *); - *num = (LLONG)currlen; - } else { - int *num; - num = va_arg (args, int *); - *num = currlen; - } - break; - case '%': - dopr_outch (buffer, &currlen, maxlen, ch); - break; - case 'w': - /* not supported yet, treat as next char */ - ch = *format++; - break; - default: - /* Unknown, skip */ - break; - } - ch = *format++; - state = DP_S_DEFAULT; - flags = cflags = min = 0; - max = -1; - break; - case DP_S_DONE: - break; - default: - /* hmm? */ - break; /* some picky compilers need this */ - } - } - if (maxlen != 0) { - if (currlen < maxlen - 1) - buffer[currlen] = '\0'; - else if (maxlen > 0) - buffer[maxlen - 1] = '\0'; - } - - return currlen; -} - -static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) -{ - int padlen, strln; /* amount to pad */ - int cnt = 0; - -#ifdef DEBUG_SNPRINTF - printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); -#endif - if (value == 0) { - value = ""; - } - - for (strln = 0; value[strln]; ++strln); /* strlen */ - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justify */ - - while ((padlen > 0) && (cnt < max)) { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - ++cnt; - } - while (*value && (cnt < max)) { - dopr_outch (buffer, currlen, maxlen, *value++); - ++cnt; - } - while ((padlen < 0) && (cnt < max)) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - ++cnt; - } -} - -/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ - -static void fmtint(char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags) -{ - int signvalue = 0; - unsigned long uvalue; - char convert[20]; - int place = 0; - int spadlen = 0; /* amount to space pad */ - int zpadlen = 0; /* amount to zero pad */ - int caps = 0; - - if (max < 0) - max = 0; - - uvalue = value; - - if(!(flags & DP_F_UNSIGNED)) { - if( value < 0 ) { - signvalue = '-'; - uvalue = -value; - } else { - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - } - } - - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ - - do { - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); - } while(uvalue && (place < 20)); - if (place == 20) place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); - if (zpadlen < 0) zpadlen = 0; - if (spadlen < 0) spadlen = 0; - if (flags & DP_F_ZERO) { - zpadlen = MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ - -#ifdef DEBUG_SNPRINTF - printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", - zpadlen, spadlen, min, max, place); -#endif - - /* Spaces */ - while (spadlen > 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* Sign */ - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - /* Zeros */ - if (zpadlen > 0) { - while (zpadlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - - /* Digits */ - while (place > 0) - dopr_outch (buffer, currlen, maxlen, convert[--place]); - - /* Left Justified spaces */ - while (spadlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++spadlen; - } -} - -static LDOUBLE abs_val(LDOUBLE value) -{ - LDOUBLE result = value; - - if (value < 0) - result = -value; - - return result; -} - -static LDOUBLE POW10(int exp) -{ - LDOUBLE result = 1; - - while (exp) { - result *= 10; - exp--; - } - - return result; -} - -static LLONG ROUND(LDOUBLE value) -{ - LLONG intpart; - - intpart = (LLONG)value; - value = value - intpart; - if (value >= 0.5) intpart++; - - return intpart; -} - -/* a replacement for modf that doesn't need the math library. Should - be portable, but slow */ -static double my_modf(double x0, double *iptr) -{ - int i; - long l; - double x = x0; - double f = 1.0; - - for (i=0;i<100;i++) { - l = (long)x; - if (l <= (x+1) && l >= (x-1)) break; - x *= 0.1; - f *= 10.0; - } - - if (i == 100) { - /* yikes! the number is beyond what we can handle. What do we do? */ - (*iptr) = 0; - return 0; - } - - if (i != 0) { - double i2; - double ret; - - ret = my_modf(x0-l*f, &i2); - (*iptr) = l*f + i2; - return ret; - } - - (*iptr) = l; - return x - (*iptr); -} - - -static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags) -{ - int signvalue = 0; - double ufvalue; - char iconvert[311]; - char fconvert[311]; - int iplace = 0; - int fplace = 0; - int padlen = 0; /* amount to pad */ - int zpadlen = 0; - int caps = 0; - int index; - double intpart; - double fracpart; - double temp; - - /* - * AIX manpage says the default is 0, but Solaris says the default - * is 6, and sprintf on AIX defaults to 6 - */ - if (max < 0) - max = 6; - - ufvalue = abs_val (fvalue); - - if (fvalue < 0) { - signvalue = '-'; - } else { - if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ - signvalue = '+'; - } else { - if (flags & DP_F_SPACE) - signvalue = ' '; - } - } - -#if 0 - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ -#endif - -#if 0 - if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ -#endif - - /* - * Sorry, we only support 16 digits past the decimal because of our - * conversion method - */ - if (max > 16) - max = 16; - - /* We "cheat" by converting the fractional part to integer by - * multiplying by a factor of 10 - */ - - temp = ufvalue; - my_modf(temp, &intpart); - - fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); - - if (fracpart >= POW10(max)) { - intpart++; - fracpart -= POW10(max); - } - - - /* Convert integer part */ - do { - temp = intpart*0.1; - my_modf(temp, &intpart); - index = (int) ((temp -intpart +0.05)* 10.0); - /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ - /* printf ("%llf, %f, %x\n", temp, intpart, index); */ - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; - } while (intpart && (iplace < 311)); - if (iplace == 311) iplace--; - iconvert[iplace] = 0; - - /* Convert fractional part */ - if (fracpart) - { - do { - temp = fracpart*0.1; - my_modf(temp, &fracpart); - index = (int) ((temp -fracpart +0.05)* 10.0); - /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ - /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; - } while(fracpart && (fplace < 311)); - if (fplace == 311) fplace--; - } - fconvert[fplace] = 0; - - /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; - if (zpadlen < 0) zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ - - if ((flags & DP_F_ZERO) && (padlen > 0)) { - if (signvalue) { - dopr_outch (buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); - -#ifdef DEBUG_SNPRINTF - printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); -#endif - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - if (max > 0) { - dopr_outch (buffer, currlen, maxlen, '.'); - - while (zpadlen > 0) { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (fplace > 0) - dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); - } - - while (padlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) -{ - if (*currlen < maxlen) { - buffer[(*currlen)] = c; - } - (*currlen)++; -} - -/* yes this really must be a ||. Don't muck with this (tridge) */ -#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) - int vsnprintf (char *str, size_t count, const char *fmt, va_list args) -{ - return dopr(str, count, fmt, args); -} -#endif - -/* yes this really must be a ||. Don't muck wiith this (tridge) - * - * The logic for these two is that we need our own definition if the - * OS *either* has no definition of *sprintf, or if it does have one - * that doesn't work properly according to the autoconf test. Perhaps - * these should really be smb_snprintf to avoid conflicts with buggy - * linkers? -- mbp - */ -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF) - int snprintf(char *str,size_t count,const char *fmt,...) -{ - size_t ret; - va_list ap; - - va_start(ap, fmt); - ret = vsnprintf(str, count, fmt, ap); - va_end(ap); - return ret; -} -#endif - -#endif - -#ifndef HAVE_VASPRINTF - int vasprintf(char **ptr, const char *format, va_list ap) -{ - int ret; - va_list ap2; - - VA_COPY(ap2, ap); - - ret = vsnprintf(NULL, 0, format, ap2); - if (ret <= 0) return ret; - - (*ptr) = (char *)malloc(ret+1); - if (!*ptr) return -1; - - VA_COPY(ap2, ap); - - ret = vsnprintf(*ptr, ret+1, format, ap2); - - return ret; -} -#endif - - -#ifndef HAVE_ASPRINTF - int asprintf(char **ptr, const char *format, ...) -{ - va_list ap; - int ret; - - *ptr = NULL; - va_start(ap, format); - ret = vasprintf(ptr, format, ap); - va_end(ap); - - return ret; -} -#endif - -#ifdef TEST_SNPRINTF - - int sprintf(char *str,const char *fmt,...); - - int main (void) -{ - char buf1[1024]; - char buf2[1024]; - char *fp_fmt[] = { - "%1.1f", - "%-1.5f", - "%1.5f", - "%123.9f", - "%10.5f", - "% 10.5f", - "%+22.9f", - "%+4.9f", - "%01.3f", - "%4f", - "%3.1f", - "%3.2f", - "%.0f", - "%f", - "-16.16f", - NULL - }; - double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 5.030201, 0}; - char *int_fmt[] = { - "%-1.5d", - "%1.5d", - "%123.9d", - "%5.5d", - "%10.5d", - "% 10.5d", - "%+22.33d", - "%01.3d", - "%4d", - "%d", - NULL - }; - long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; - char *str_fmt[] = { - "10.5s", - "5.10s", - "10.1s", - "0.10s", - "10.0s", - "1.10s", - "%s", - "%.1s", - "%.10s", - "%10s", - NULL - }; - char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; - int x, y; - int fail = 0; - int num = 0; - - printf ("Testing snprintf format codes against system sprintf...\n"); - - for (x = 0; fp_fmt[x] ; x++) { - for (y = 0; fp_nums[y] != 0 ; y++) { - int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); - int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); - if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", - fp_fmt[x], buf1, buf2); - fail++; - } - if (l1 != l2) { - printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); - fail++; - } - num++; - } - } - - for (x = 0; int_fmt[x] ; x++) { - for (y = 0; int_nums[y] != 0 ; y++) { - int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); - int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); - sprintf (buf2, int_fmt[x], int_nums[y]); - if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", - int_fmt[x], buf1, buf2); - fail++; - } - if (l1 != l2) { - printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); - fail++; - } - num++; - } - } - - for (x = 0; str_fmt[x] ; x++) { - for (y = 0; str_vals[y] != 0 ; y++) { - int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); - int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); - sprintf (buf2, str_fmt[x], str_vals[y]); - if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", - str_fmt[x], buf1, buf2); - fail++; - } - if (l1 != l2) { - printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); - fail++; - } - num++; - } - } - - printf ("%d tests failed out of %d.\n", fail, num); - - printf("seeing how many digits we support\n"); - { - double v0 = 0.12345678901234567890123456789012345678901; - for (x=0; x<100; x++) { - double p = pow(10, x); - double r = v0*p; - snprintf(buf1, sizeof(buf1), "%1.1f", r); - sprintf(buf2, "%1.1f", r); - if (strcmp(buf1, buf2)) { - printf("we seem to support %d digits\n", x-1); - break; - } - } - } - - return 0; -} -#endif /* SNPRINTF_TEST */ diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index e02198754d..557baa716d 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -115,7 +115,7 @@ read a line from a file with possible \ continuation chars. Blanks at the start or end of a line are stripped. The string will be allocated if s2 is NULL ****************************************************************************/ -char *fgets_slash(char *s2,int maxlen,XFILE *f) +char *fgets_slash(char *s2,int maxlen,FILE *f) { char *s=s2; int len = 0; -- cgit From e83b74244d9e5bc8dee202b86fb3ec192fe93185 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Jun 2005 04:19:32 +0000 Subject: r7205: added support for sendto() on unix domain sockets (This used to be commit 35ef6e3b153f527f79539b2d99c5ff1cd034ba4b) --- source4/lib/socket/socket_unix.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 3f265f7214..04ba89578f 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -249,6 +249,37 @@ static NTSTATUS unixdom_send(struct socket_context *sock, return NT_STATUS_OK; } + +static NTSTATUS unixdom_sendto(struct socket_context *sock, + const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, + const char *dest_addr, int dest_port) +{ + ssize_t len; + int flgs = 0; + struct sockaddr_un srv_addr; + + if (strlen(dest_addr)+1 > sizeof(srv_addr.sun_path)) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(srv_addr); + srv_addr.sun_family = AF_UNIX; + strncpy(srv_addr.sun_path, dest_addr, sizeof(srv_addr.sun_path)); + + *sendlen = 0; + + len = sendto(sock->fd, blob->data, blob->length, flgs, + (struct sockaddr *)&srv_addr, sizeof(srv_addr)); + if (len == -1) { + return map_nt_error_from_unix(errno); + } + + *sendlen = len; + + return NT_STATUS_OK; +} + + static NTSTATUS unixdom_set_option(struct socket_context *sock, const char *option, const char *val) { @@ -294,6 +325,7 @@ static const struct socket_ops unixdom_ops = { .fn_accept = unixdom_accept, .fn_recv = unixdom_recv, .fn_send = unixdom_send, + .fn_sendto = unixdom_sendto, .fn_close = unixdom_close, .fn_set_option = unixdom_set_option, -- cgit From dd43abbd325874b7b6bcfdad453b7507ace4314a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Jun 2005 04:21:25 +0000 Subject: r7206: changed the messaging library to use sendto instead of a connected send on the unix domain datagram socket. This gains us about 50% in speed, and also means that we don't run the risk of running out of file descriptors due to heavy messaging traffic. We now use a single file descriptor no matter how many messages are pending to any number of servers. (This used to be commit 2369170fc1b4ff9a48284779fa6d3a6254177ec1) --- source4/lib/messaging/messaging.c | 213 +++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 119 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 2130958b36..4d2cd9c910 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -31,9 +31,6 @@ /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 -/* the number of microseconds to backoff in retrying to send a message */ -#define MESSAGING_BACKOFF 250000 - /* maximum message size */ #define MESSAGING_MAX_SIZE 512 @@ -42,6 +39,7 @@ struct messaging_context { struct socket_context *sock; const char *path; struct dispatch_fn *dispatch; + struct messaging_rec *pending; struct { struct event_context *ev; @@ -61,8 +59,8 @@ struct dispatch_fn { /* an individual message */ struct messaging_rec { + struct messaging_rec *next, *prev; struct messaging_context *msg; - struct socket_context *sock; const char *path; struct { @@ -76,6 +74,7 @@ struct messaging_rec { DATA_BLOB data; }; + /* A useful function for testing the message system. */ @@ -111,19 +110,67 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r d->fn(msg, d->private, d->msg_type, rec->header.from, &rec->data); } } - rec->header.length = 0; } /* - handle a new incoming connection + try to send the message */ -static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) +static NTSTATUS try_send(struct messaging_rec *rec) +{ + struct messaging_context *msg = rec->msg; + DATA_BLOB blob; + size_t nsent; + void *priv; + NTSTATUS status; + + blob = data_blob_talloc(rec, NULL, sizeof(rec->header) + rec->data.length); + NT_STATUS_HAVE_NO_MEMORY(blob.data); + + memcpy(blob.data, &rec->header, sizeof(rec->header)); + memcpy(blob.data + sizeof(rec->header), rec->data.data, rec->data.length); + + /* we send with privileges so messages work from any context */ + priv = root_privileges(); + status = socket_sendto(msg->sock, &blob, &nsent, 0, rec->path, 0); + talloc_free(priv); + + data_blob_free(&blob); + + return status; +} + +/* + handle a socket write event +*/ +static void messaging_send_handler(struct messaging_context *msg) +{ + while (msg->pending) { + struct messaging_rec *rec = msg->pending; + NTSTATUS status; + status = try_send(rec); + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + break; + } + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("messaging: Lost message from %u to %u of type %u - %s\n", + rec->header.from, rec->header.to, rec->header.msg_type, + nt_errstr(status))); + } + DLIST_REMOVE(msg->pending, rec); + talloc_free(rec); + } + if (msg->pending == NULL) { + EVENT_FD_NOT_WRITEABLE(msg->event.fde); + } +} + +/* + handle a new incoming packet +*/ +static void messaging_recv_handler(struct messaging_context *msg) { - struct messaging_context *msg = talloc_get_type(private, - struct messaging_context); struct messaging_rec *rec; NTSTATUS status; uint8_t data[MESSAGING_MAX_SIZE]; @@ -146,7 +193,6 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd rec->msg = msg; rec->path = msg->path; - rec->sock = NULL; memcpy(&rec->header, data, sizeof(rec->header)); if (msize != sizeof(rec->header) + rec->header.length) { @@ -166,6 +212,24 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd talloc_free(rec); } + +/* + handle a socket event +*/ +static void messaging_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *private) +{ + struct messaging_context *msg = talloc_get_type(private, + struct messaging_context); + if (flags & EVENT_FD_WRITE) { + messaging_send_handler(msg); + } + if (flags & EVENT_FD_READ) { + messaging_recv_handler(msg); + } +} + + /* Register a dispatch function for a particular message type. */ @@ -200,89 +264,11 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void } - -/* - handle IO for sending a message -*/ -static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) -{ - struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); - uint8_t data[MESSAGING_MAX_SIZE]; - DATA_BLOB blob; - size_t nsent; - NTSTATUS status; - - memcpy(data, &rec->header, sizeof(rec->header)); - memcpy(data + sizeof(rec->header), rec->data.data, rec->data.length); - - blob.data = data; - blob.length = sizeof(rec->header) + rec->header.length; - - status = socket_send(rec->sock, &blob, &nsent, 0); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(3,("Unable to send message of type %d length %d - %s\n", - rec->header.msg_type, - rec->header.length, - nt_errstr(status))); - talloc_free(rec); - return; - } - - if (NT_STATUS_IS_OK(status)) { - talloc_free(rec); - } -} - - -/* - wrapper around socket_connect with raised privileges -*/ -static NTSTATUS try_connect(struct messaging_rec *rec) -{ - NTSTATUS status; - void *priv = root_privileges(); - status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0); - talloc_free(priv); - return status; -} - - -/* - when the servers listen queue is full we use this to backoff the message -*/ -static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) -{ - struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); - struct messaging_context *msg = rec->msg; - NTSTATUS status; - - status = try_connect(rec); - if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - /* backoff again */ - event_add_timed(msg->event.ev, rec, - timeval_add(&t, 0, MESSAGING_BACKOFF), - messaging_backoff_handler, rec); - return; - } - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1,("messaging: Lost message from %u to %u of type %u after backoff - %s\n", - rec->header.from, rec->header.to, rec->header.msg_type, nt_errstr(status))); - talloc_free(rec); - return; - } - - event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), - EVENT_FD_WRITE, messaging_send_handler, rec); -} - - /* Send a message to a particular server */ -NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t msg_type, DATA_BLOB *data) +NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, + uint32_t msg_type, DATA_BLOB *data) { struct messaging_rec *rec; NTSTATUS status; @@ -292,45 +278,32 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t return NT_STATUS_NO_MEMORY; } - rec->msg = msg; - rec->header.version = MESSAGING_VERSION; + rec->msg = msg; + rec->header.version = MESSAGING_VERSION; rec->header.msg_type = msg_type; - rec->header.from = msg->server_id; - rec->header.to = server; - rec->header.length = data?data->length:0; + rec->header.from = msg->server_id; + rec->header.to = server; + rec->header.length = data?data->length:0; if (rec->header.length != 0) { rec->data = data_blob_talloc(rec, data->data, data->length); } else { rec->data = data_blob(NULL, 0); } - status = socket_create("unix", SOCKET_TYPE_DGRAM, &rec->sock, 0); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(rec); - return status; - } - talloc_steal(rec, rec->sock); - rec->path = messaging_path(rec, server); - status = try_connect(rec); + status = try_send(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - /* backoff on this message - the servers listen queue is full */ - event_add_timed(msg->event.ev, rec, - timeval_current_ofs(0, MESSAGING_BACKOFF), - messaging_backoff_handler, rec); + if (msg->pending == NULL) { + EVENT_FD_WRITEABLE(msg->event.fde); + } + DLIST_ADD(msg->pending, rec); return NT_STATUS_OK; } - if (!NT_STATUS_IS_OK(status)) { - talloc_free(rec); - return status; - } - - event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), - EVENT_FD_WRITE, messaging_send_handler, rec); + talloc_free(rec); - return NT_STATUS_OK; + return status; } /* @@ -381,6 +354,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id msg->path = messaging_path(msg, server_id); msg->server_id = server_id; msg->dispatch = NULL; + msg->pending = NULL; status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0); if (!NT_STATUS_IS_OK(status)) { @@ -399,9 +373,12 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id return NULL; } + /* it needs to be non blocking for sends */ + set_blocking(socket_get_fd(msg->sock), False); + msg->event.ev = talloc_reference(msg, ev); msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock), - EVENT_FD_READ, messaging_recv_handler, msg); + EVENT_FD_READ, messaging_handler, msg); talloc_set_destructor(msg, messaging_destructor); @@ -409,5 +386,3 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id return msg; } - - -- cgit From f1ade86d756a242e41d610981b948d03c68fbd4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Jun 2005 06:04:34 +0000 Subject: r7211: - use ioctl(FIONREAD) to remove the artificial limit on messaging size - avoid a memcpy (This used to be commit 753839c358f45c02927b137092828f3a79158083) --- source4/lib/messaging/messaging.c | 93 +++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 42 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 4d2cd9c910..eb526fd391 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -31,9 +31,6 @@ /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 -/* maximum message size */ -#define MESSAGING_MAX_SIZE 512 - struct messaging_context { uint32_t server_id; struct socket_context *sock; @@ -63,15 +60,15 @@ struct messaging_rec { struct messaging_context *msg; const char *path; - struct { + struct messaging_header { uint32_t version; uint32_t msg_type; uint32_t from; uint32_t to; uint32_t length; - } header; + } *header; - DATA_BLOB data; + DATA_BLOB packet; }; @@ -106,11 +103,14 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r struct dispatch_fn *d, *next; for (d=msg->dispatch;d;d=next) { next = d->next; - if (d->msg_type == rec->header.msg_type) { - d->fn(msg, d->private, d->msg_type, rec->header.from, &rec->data); + if (d->msg_type == rec->header->msg_type) { + DATA_BLOB data; + data.data = rec->packet.data + sizeof(*rec->header); + data.length = rec->header->length; + d->fn(msg, d->private, d->msg_type, rec->header->from, &data); } } - rec->header.length = 0; + rec->header->length = 0; } @@ -120,24 +120,15 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r static NTSTATUS try_send(struct messaging_rec *rec) { struct messaging_context *msg = rec->msg; - DATA_BLOB blob; size_t nsent; void *priv; NTSTATUS status; - blob = data_blob_talloc(rec, NULL, sizeof(rec->header) + rec->data.length); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - - memcpy(blob.data, &rec->header, sizeof(rec->header)); - memcpy(blob.data + sizeof(rec->header), rec->data.data, rec->data.length); - /* we send with privileges so messages work from any context */ priv = root_privileges(); - status = socket_sendto(msg->sock, &blob, &nsent, 0, rec->path, 0); + status = socket_sendto(msg->sock, &rec->packet, &nsent, 0, rec->path, 0); talloc_free(priv); - data_blob_free(&blob); - return status; } @@ -155,7 +146,7 @@ static void messaging_send_handler(struct messaging_context *msg) } if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("messaging: Lost message from %u to %u of type %u - %s\n", - rec->header.from, rec->header.to, rec->header.msg_type, + rec->header->from, rec->header->to, rec->header->msg_type, nt_errstr(status))); } DLIST_REMOVE(msg->pending, rec); @@ -173,16 +164,31 @@ static void messaging_recv_handler(struct messaging_context *msg) { struct messaging_rec *rec; NTSTATUS status; - uint8_t data[MESSAGING_MAX_SIZE]; + DATA_BLOB packet; size_t msize; + int dsize=0; - status = socket_recv(msg->sock, data, sizeof(data), &msize, 0); + /* see how many bytes are in the next packet */ + if (ioctl(socket_get_fd(msg->sock), FIONREAD, &dsize) != 0) { + DEBUG(0,("FIONREAD failed in messaging - %s\n", strerror(errno))); + return; + } + + packet = data_blob_talloc(msg, NULL, dsize); + if (packet.data == NULL) { + /* assume this is temporary and retry */ + return; + } + + status = socket_recv(msg->sock, packet.data, dsize, &msize, 0); if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&packet); return; } - if (msize < sizeof(rec->header)) { + if (msize < sizeof(*rec->header)) { DEBUG(0,("messaging: bad message of size %d\n", msize)); + data_blob_free(&packet); return; } @@ -191,19 +197,15 @@ static void messaging_recv_handler(struct messaging_context *msg) smb_panic("Unable to allocate messaging_rec"); } + talloc_steal(rec, packet.data); rec->msg = msg; rec->path = msg->path; + rec->header = (struct messaging_header *)packet.data; + rec->packet = packet; - memcpy(&rec->header, data, sizeof(rec->header)); - if (msize != sizeof(rec->header) + rec->header.length) { + if (msize != sizeof(*rec->header) + rec->header->length) { DEBUG(0,("messaging: bad message header size %d should be %d\n", - rec->header.length, msize - sizeof(rec->header))); - talloc_free(rec); - return; - } - - rec->data = data_blob_talloc(rec, data+sizeof(rec->header), rec->header.length); - if (rec->data.data == NULL) { + rec->header->length, msize - sizeof(*rec->header))); talloc_free(rec); return; } @@ -272,22 +274,29 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, { struct messaging_rec *rec; NTSTATUS status; + size_t dlength = data?data->length:0; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { return NT_STATUS_NO_MEMORY; } - rec->msg = msg; - rec->header.version = MESSAGING_VERSION; - rec->header.msg_type = msg_type; - rec->header.from = msg->server_id; - rec->header.to = server; - rec->header.length = data?data->length:0; - if (rec->header.length != 0) { - rec->data = data_blob_talloc(rec, data->data, data->length); - } else { - rec->data = data_blob(NULL, 0); + rec->packet = data_blob_talloc(rec, NULL, sizeof(*rec->header) + dlength); + if (rec->packet.data == NULL) { + talloc_free(rec); + return NT_STATUS_NO_MEMORY; + } + + rec->msg = msg; + rec->header = (struct messaging_header *)rec->packet.data; + rec->header->version = MESSAGING_VERSION; + rec->header->msg_type = msg_type; + rec->header->from = msg->server_id; + rec->header->to = server; + rec->header->length = dlength; + if (dlength != 0) { + memcpy(rec->packet.data + sizeof(*rec->header), + data->data, dlength); } rec->path = messaging_path(rec, server); -- cgit From 0253adcab3157ec73cc96ad74b19faa2c87e067a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 3 Jun 2005 07:47:06 +0000 Subject: r7213: Add a small bit to the ejs parser to ignore a #!/path/to/interpreter as the first line of the script. This allows smbscript to be used as an interpreter. (This used to be commit 875c8164096e7334de25cc57ac4b8bdc39b9c46b) --- source4/lib/ejs/ejs.c | 4 +++- source4/lib/ejs/ejsInternal.h | 5 ++--- source4/lib/ejs/ejsLex.c | 20 ++++++++++++++++++++ source4/lib/ejs/ejsParser.c | 27 +++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejs.c b/source4/lib/ejs/ejs.c index 41af795370..d0eaf6e389 100644 --- a/source4/lib/ejs/ejs.c +++ b/source4/lib/ejs/ejs.c @@ -418,8 +418,10 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) endlessLoopTest = NULL; ep->exitStatus = 0; + ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); /* Skip over #! */ + do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); + state = ejsParse(ep, EJS_STATE_STMT, EJS_FLAGS_EXE); if (state == EJS_STATE_RET) { state = EJS_STATE_EOF; diff --git a/source4/lib/ejs/ejsInternal.h b/source4/lib/ejs/ejsInternal.h index 4d54c4e8c6..2f776b8b79 100644 --- a/source4/lib/ejs/ejsInternal.h +++ b/source4/lib/ejs/ejsInternal.h @@ -100,7 +100,7 @@ extern "C" { #define EJS_TOK_IN 26 /* in */ #define EJS_TOK_FUNCTION 27 /* function */ #define EJS_TOK_NUMBER 28 /* Number */ - +#define EJS_TOK_HASHBANG 29 /* #!/path/to/interpreter */ /* * Expression operators */ @@ -150,8 +150,7 @@ extern "C" { #define EJS_STATE_DEC 18 /* Declaration statement */ #define EJS_STATE_DEC_DONE 19 #define EJS_STATE_RET 20 /* Return statement */ - -#define EJS_STATE_BEGIN EJS_STATE_STMT +#define EJS_STATE_BEGIN 21 /* Start of script */ /* * General parsing flags. diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c index b0d6483c2a..81f56b092e 100644 --- a/source4/lib/ejs/ejsLex.c +++ b/source4/lib/ejs/ejsLex.c @@ -674,6 +674,26 @@ static int getLexicalToken(Ejs *ep, int state) inputPutback(ep, c); return EJS_TOK_NUMBER; + case '#': + if (ip->lineNumber == 1) { + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '!') { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + while ((c = inputGetc(ep)) != -1) { + if (c == '\r' || c == '\n') + break; + tokenAddChar(ep, c); + } + return EJS_TOK_HASHBANG; + } + + /* Fall through to default handling */ + default: /* * Identifiers or a function names diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 17fe0ce98a..942b08272e 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -67,6 +67,7 @@ static int parseId(Ejs *ep, int state, int flags, char **id, static int parseInc(Ejs *ep, int state, int flags); static int parseIf(Ejs *ep, int state, int flags, int *done); static int parseStmt(Ejs *ep, int state, int flags); +static int parseHashBang(Ejs *ep, int state, int flags); static void removeNewlines(Ejs *ep, int state); static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); @@ -80,6 +81,12 @@ int ejsParse(Ejs *ep, int state, int flags) mprAssert(ep); switch (state) { + /* + * The very start of a script. + */ + case EJS_STATE_BEGIN: + state = parseHashBang(ep, state, flags); + break; /* * Any statement, function arguments or conditional expressions */ @@ -140,6 +147,26 @@ int ejsParse(Ejs *ep, int state, int flags) return state; } +/******************************************************************************/ +/* + * Parse a #!/path/to/interpreter line which we just throw away. + */ + +static int parseHashBang(Ejs *ep, int state, int flags) +{ + int tid; + + /* Look for #! */ + + tid = ejsLexGetToken(ep, state); + + if (tid != EJS_TOK_HASHBANG) { + ejsLexPutbackToken(ep, tid, ep->token); + } + + return EJS_STATE_STMT; +} + /******************************************************************************/ /* * Parse any statement including functions and simple relational operations -- cgit From 65d685c722ecf51bf84bb24af66c1f30c33b3b96 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 3 Jun 2005 07:56:41 +0000 Subject: r7214: Undo my interpreter patch. Tridge thought of a much better way to do it that doesn't involve any changes to ejs at all. (This used to be commit 7b49711ecb87e8618be5ae934ffed5995408b748) --- source4/lib/ejs/ejs.c | 4 +--- source4/lib/ejs/ejsInternal.h | 5 +++-- source4/lib/ejs/ejsLex.c | 20 -------------------- source4/lib/ejs/ejsParser.c | 27 --------------------------- 4 files changed, 4 insertions(+), 52 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejs.c b/source4/lib/ejs/ejs.c index d0eaf6e389..41af795370 100644 --- a/source4/lib/ejs/ejs.c +++ b/source4/lib/ejs/ejs.c @@ -418,10 +418,8 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) endlessLoopTest = NULL; ep->exitStatus = 0; - ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); /* Skip over #! */ - do { - state = ejsParse(ep, EJS_STATE_STMT, EJS_FLAGS_EXE); + state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); if (state == EJS_STATE_RET) { state = EJS_STATE_EOF; diff --git a/source4/lib/ejs/ejsInternal.h b/source4/lib/ejs/ejsInternal.h index 2f776b8b79..4d54c4e8c6 100644 --- a/source4/lib/ejs/ejsInternal.h +++ b/source4/lib/ejs/ejsInternal.h @@ -100,7 +100,7 @@ extern "C" { #define EJS_TOK_IN 26 /* in */ #define EJS_TOK_FUNCTION 27 /* function */ #define EJS_TOK_NUMBER 28 /* Number */ -#define EJS_TOK_HASHBANG 29 /* #!/path/to/interpreter */ + /* * Expression operators */ @@ -150,7 +150,8 @@ extern "C" { #define EJS_STATE_DEC 18 /* Declaration statement */ #define EJS_STATE_DEC_DONE 19 #define EJS_STATE_RET 20 /* Return statement */ -#define EJS_STATE_BEGIN 21 /* Start of script */ + +#define EJS_STATE_BEGIN EJS_STATE_STMT /* * General parsing flags. diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c index 81f56b092e..b0d6483c2a 100644 --- a/source4/lib/ejs/ejsLex.c +++ b/source4/lib/ejs/ejsLex.c @@ -674,26 +674,6 @@ static int getLexicalToken(Ejs *ep, int state) inputPutback(ep, c); return EJS_TOK_NUMBER; - case '#': - if (ip->lineNumber == 1) { - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '!') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - while ((c = inputGetc(ep)) != -1) { - if (c == '\r' || c == '\n') - break; - tokenAddChar(ep, c); - } - return EJS_TOK_HASHBANG; - } - - /* Fall through to default handling */ - default: /* * Identifiers or a function names diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 942b08272e..17fe0ce98a 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -67,7 +67,6 @@ static int parseId(Ejs *ep, int state, int flags, char **id, static int parseInc(Ejs *ep, int state, int flags); static int parseIf(Ejs *ep, int state, int flags, int *done); static int parseStmt(Ejs *ep, int state, int flags); -static int parseHashBang(Ejs *ep, int state, int flags); static void removeNewlines(Ejs *ep, int state); static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); @@ -81,12 +80,6 @@ int ejsParse(Ejs *ep, int state, int flags) mprAssert(ep); switch (state) { - /* - * The very start of a script. - */ - case EJS_STATE_BEGIN: - state = parseHashBang(ep, state, flags); - break; /* * Any statement, function arguments or conditional expressions */ @@ -147,26 +140,6 @@ int ejsParse(Ejs *ep, int state, int flags) return state; } -/******************************************************************************/ -/* - * Parse a #!/path/to/interpreter line which we just throw away. - */ - -static int parseHashBang(Ejs *ep, int state, int flags) -{ - int tid; - - /* Look for #! */ - - tid = ejsLexGetToken(ep, state); - - if (tid != EJS_TOK_HASHBANG) { - ejsLexPutbackToken(ep, tid, ep->token); - } - - return EJS_STATE_STMT; -} - /******************************************************************************/ /* * Parse any statement including functions and simple relational operations -- cgit From 1692bbf2e267eabd7099f0b6153da0c7cf209d1d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Jun 2005 13:20:08 +0000 Subject: r7227: added a socket_pending() call to abstract away the FIONREAD ioctl. It will be interesting to see if this causes any portability problems, as it is a less commonly used call. (This used to be commit f6993db31d93059c70b44a23005ba444e205870f) --- source4/lib/socket/socket.c | 16 ++++++++++++++++ source4/lib/socket/socket.h | 2 ++ source4/lib/socket/socket_ipv4.c | 11 +++++++++++ source4/lib/socket/socket_unix.c | 11 +++++++++++ 4 files changed, 40 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 13d1640f51..dd3175468d 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -235,6 +235,22 @@ NTSTATUS socket_sendto(struct socket_context *sock, return sock->ops->fn_sendto(sock, blob, sendlen, flags, dest_addr, dest_port); } + +/* + ask for the number of bytes in a pending incoming datagram +*/ +NTSTATUS socket_pending(struct socket_context *sock, size_t *npending) +{ + if (sock->type != SOCKET_TYPE_DGRAM) { + return NT_STATUS_INVALID_PARAMETER; + } + if (!sock->ops->fn_pending) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return sock->ops->fn_pending(sock, npending); +} + + NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) { if (!sock->ops->fn_set_option) { diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index bce64f9f6c..e2879e5247 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -60,6 +60,7 @@ struct socket_ops { NTSTATUS (*fn_recvfrom)(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags, const char **src_addr, int *src_port); + NTSTATUS (*fn_pending)(struct socket_context *sock, size_t *npending); void (*fn_close)(struct socket_context *sock); @@ -124,6 +125,7 @@ NTSTATUS socket_send(struct socket_context *sock, NTSTATUS socket_sendto(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, const char *dest_addr, int dest_port); +NTSTATUS socket_pending(struct socket_context *sock, size_t *npending); NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val); char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx); char *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 93ddf68046..0fc65698c4 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -435,6 +435,16 @@ static int ipv4_get_fd(struct socket_context *sock) return sock->fd; } +static NTSTATUS ipv4_pending(struct socket_context *sock, size_t *npending) +{ + int value = 0; + if (ioctl(sock->fd, FIONREAD, &value) == 0) { + *npending = value; + return NT_STATUS_OK; + } + return map_nt_error_from_unix(errno); +} + static const struct socket_ops ipv4_ops = { .name = "ipv4", .fn_init = ipv4_init, @@ -446,6 +456,7 @@ static const struct socket_ops ipv4_ops = { .fn_recvfrom = ipv4_recvfrom, .fn_send = ipv4_send, .fn_sendto = ipv4_sendto, + .fn_pending = ipv4_pending, .fn_close = ipv4_close, .fn_set_option = ipv4_set_option, diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 04ba89578f..f27076b5d8 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -316,6 +316,16 @@ static int unixdom_get_fd(struct socket_context *sock) return sock->fd; } +static NTSTATUS unixdom_pending(struct socket_context *sock, size_t *npending) +{ + int value = 0; + if (ioctl(sock->fd, FIONREAD, &value) == 0) { + *npending = value; + return NT_STATUS_OK; + } + return map_nt_error_from_unix(errno); +} + static const struct socket_ops unixdom_ops = { .name = "unix", .fn_init = unixdom_init, @@ -327,6 +337,7 @@ static const struct socket_ops unixdom_ops = { .fn_send = unixdom_send, .fn_sendto = unixdom_sendto, .fn_close = unixdom_close, + .fn_pending = unixdom_pending, .fn_set_option = unixdom_set_option, -- cgit From a8feef8d3647d25b3f5f572139acb1bab361055e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 3 Jun 2005 13:20:45 +0000 Subject: r7228: use socket_pending() instead of the direct ioctl in the messaging code (This used to be commit ca3c4e961713ffd8952fca328e27196ba2ccc0c9) --- source4/lib/messaging/messaging.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index eb526fd391..936e3b9515 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -166,21 +166,22 @@ static void messaging_recv_handler(struct messaging_context *msg) NTSTATUS status; DATA_BLOB packet; size_t msize; - int dsize=0; /* see how many bytes are in the next packet */ - if (ioctl(socket_get_fd(msg->sock), FIONREAD, &dsize) != 0) { - DEBUG(0,("FIONREAD failed in messaging - %s\n", strerror(errno))); + status = socket_pending(msg->sock, &msize); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("socket_pending failed in messaging - %s\n", + nt_errstr(status))); return; } - packet = data_blob_talloc(msg, NULL, dsize); + packet = data_blob_talloc(msg, NULL, msize); if (packet.data == NULL) { /* assume this is temporary and retry */ return; } - status = socket_recv(msg->sock, packet.data, dsize, &msize, 0); + status = socket_recv(msg->sock, packet.data, msize, &msize, 0); if (!NT_STATUS_IS_OK(status)) { data_blob_free(&packet); return; -- cgit From e331dcbc32e4b2fccb964af908f3fdce031fa6bf Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 3 Jun 2005 14:20:25 +0000 Subject: r7239: add a little test (This used to be commit 9293de1c354854ace3f8f60a2accc72f4686c6e2) --- source4/lib/ldb/tests/test-generic.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 78fed1c12b..7b5c24512e 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -38,6 +38,7 @@ $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 $VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 $VALGRIND bin/ldbsearch '((' uid && exit 1 +$VALGRIND bin/ldbsearch '(objectclass=)' uid || exit 1 $VALGRIND bin/ldbsearch 'dn=cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US' uid || exit 1 echo "Starting ldbtest indexed" -- cgit From 77c3d463c88af9f41f5f76446d380c80262ce712 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 3 Jun 2005 20:44:46 +0000 Subject: r7248: Remove enum that is causing trouble on AIX (This used to be commit 512536c9165eb4a630c8bf4e43e71def26006047) --- source4/lib/registry/tools/regshell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index f1fd740830..03cb09c443 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -408,7 +408,7 @@ static char **reg_completion(const char *text, int start, int end) } if (h) { - enum reg_predefined_key try_hkeys[] = { + uint32_t try_hkeys[] = { HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, @@ -424,7 +424,7 @@ static char **reg_completion(const char *text, int start, int end) for (i = 0; try_hkeys[i]; i++) { WERROR err; - err = reg_get_predefined_key(h, HKEY_CLASSES_ROOT, &curkey); + err = reg_get_predefined_key(h, try_hkeys[i], &curkey); if (W_ERROR_IS_OK(err)) { break; } else { -- cgit From 6ade5fc245a6f56b991b1b66742509270d65479d Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 02:31:45 +0000 Subject: r7260: save current schema before I blow it away to try something different (This used to be commit 676a9824934576056208d30ce34716cfb734ce58) --- source4/lib/ldb/ldb_sqlite3/schema | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index 45be5b578f..08dc50de08 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -30,7 +30,7 @@ tree_key TEXT PRIMARY KEY, parent_tree_key TEXT, - full_path TEXT, + dn TEXT, attr_name TEXT REFERENCES ldb_attributes, attr_value TEXT, @@ -85,8 +85,8 @@ -- ------------------------------------------------------ - CREATE INDEX ldb_object_full_path_idx - ON ldb_object (full_path); + CREATE INDEX ldb_object_dn_idx + ON ldb_object (dn); CREATE INDEX ldb_attributes_tree_key_ids ON ldb_attributes (tree_key); @@ -159,7 +159,7 @@ /* Create root object */ INSERT INTO ldb_object (tree_key, parent_tree_key, - full_path, + dn, object_type, max_child_num) VALUES ('', NULL, '', @@ -186,7 +186,7 @@ BEGIN; INSERT OR IGNORE INTO ldb_object (parent_tree_key - full_path, + dn, attr_name, attr_value, object_type, max_child_num) VALUES ('', 'c=US', @@ -194,7 +194,7 @@ INSERT OR IGNORE INTO ldb_object INSERT INTO ldb_object (parent_tree_key, - full_path, + dn, attr_name, attr_value, object_type, max_child_num) VALUES ('0001', 'o=University of Michigan,c=US', @@ -208,7 +208,7 @@ INSERT OR IGNORE INTO ldb_attributes INSERT INTO ldb_object (parent_tree_key, - full_path, + dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, @@ -221,7 +221,7 @@ INSERT OR IGNORE INTO ldb_attributes INSERT INTO ldb_object (parent_tree_key, - full_path, + dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, @@ -243,37 +243,37 @@ COMMIT; BEGIN; INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'l', 'Ann Arbor, Michigan', 2, 0); INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'st', 'Michigan', 2, 0); INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'o', 'University of Michigan', 2, 0); INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'o', 'UMICH', 2, 0); INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'seeAlso', '', 2, 0); INSERT INTO ldb_object - (parent_tree_key, full_path, + (parent_tree_key, dn, attr_name, attr_value, object_type, max_child_num) VALUES ('00010001', NULL, 'telephonenumber', '+1 313 764-1817', 2, 0); -- cgit From 89bcaa79c9181e42a7aaae3ca7e95d01eba203a2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Jun 2005 06:45:11 +0000 Subject: r7265: fixed d_printf() so it works again. Jelmer, can you give me a hint as to why you changed this? It completely broke smbclient, and the change now makes d_printf() almost equivalent to printf() as you removed the language translation code. See your commit 7166. Did you intend to reenable language handling by some other method? Or do you just mean to remove it completely? (This used to be commit 2e293ab06f8b84ef8cf5aafde1715fa21b2bbef0) --- source4/lib/dprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/dprintf.c b/source4/lib/dprintf.c index 6653fa4242..64227148fd 100644 --- a/source4/lib/dprintf.c +++ b/source4/lib/dprintf.c @@ -35,12 +35,12 @@ int d_vfprintf(FILE *f, const char *format, va_list ap) _PRINTF_ATTRIBUTE(2,0) { char *p, *p2; int ret, maxlen, clen; - char *msgstr; va_list ap2; + /* do any message translations */ VA_COPY(ap2, ap); - ret = vasprintf(&p, msgstr, ap2); + ret = vasprintf(&p, format, ap2); if (ret <= 0) return ret; -- cgit From a1ba224107fbcf6f8a9a3091f42cde2a0c47f85e Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 17:13:43 +0000 Subject: r7276: - moved static tdb function ltdb_dn_fold() into common/ so that it can be called from multiple backends. (ldb_sqlite3 needs it too.) Added parameter for a callback function that determines whether an attribute needs case folding. - begin to prepare for sqlite3 in build process - work-in-progress updates, on ldb_sqlite3 (This used to be commit a80bced0b96ffb655559a43cf7f4d7a34deb5a7d) --- source4/lib/ldb/common/ldb.c | 6 + source4/lib/ldb/common/ldb_utf8.c | 77 ++++ source4/lib/ldb/config.m4 | 5 + source4/lib/ldb/config.mk | 12 + source4/lib/ldb/include/ldb.h | 3 + source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 669 +++++++++++------------------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 18 - source4/lib/ldb/ldb_sqlite3/schema | 207 ++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 76 +--- source4/lib/ldb/tools/ldbsearch.c | 21 +- source4/lib/tdb/common/tdb.c | 11 +- 11 files changed, 463 insertions(+), 642 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 600c7063f0..649b0a0f24 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -62,6 +62,12 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, } #endif +#if HAVE_SQLITE3 + if (strncmp(url, "sqlite:", 7) == 0) { + ldb_ctx = lsqlite3_connect(url, flags, options); + } +#endif + if (!ldb_ctx) { errno = EINVAL; diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 577766d9f7..9cbb5646dd 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -88,3 +88,80 @@ int ldb_attr_cmp(const char *dn1, const char *dn2) { return ldb_caseless_cmp(dn1, dn2); } + + +/* + casefold a dn. We need to uppercase the attribute names, and the + attribute values of case insensitive attributes. We also need to remove + extraneous spaces between elements +*/ +char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_attr_fn)(struct ldb_module * module, char * attr)) +{ + const char *dn_orig = dn; + struct ldb_context *ldb = module->ldb; + TALLOC_CTX *tmp_ctx = talloc_new(ldb); + char *ret; + size_t len; + + ret = talloc_strdup(tmp_ctx, ""); + if (ret == NULL) goto failed; + + while ((len = strcspn(dn, ",")) > 0) { + char *p = strchr(dn, '='); + char *attr, *value; + int case_fold_required; + + if (p == NULL || (p-dn) > len) goto failed; + + attr = talloc_strndup(tmp_ctx, dn, p-dn); + if (attr == NULL) goto failed; + + /* trim spaces from the attribute name */ + while (' ' == *attr) attr++; + while (' ' == attr[strlen(attr)-1]) { + attr[strlen(attr)-1] = 0; + } + if (*attr == 0) goto failed; + + value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn)); + if (value == NULL) goto failed; + + /* trim spaces from the value */ + while (' ' == *value) value++; + while (' ' == value[strlen(value)-1]) { + value[strlen(value)-1] = 0; + } + if (*value == 0) goto failed; + + case_fold_required = (* case_fold_attr_fn)(module, attr); + + attr = ldb_casefold(ldb, attr); + if (attr == NULL) goto failed; + talloc_steal(tmp_ctx, attr); + + if (case_fold_required) { + value = ldb_casefold(ldb, value); + if (value == NULL) goto failed; + talloc_steal(tmp_ctx, value); + } + + if (dn[len] == ',') { + ret = talloc_asprintf_append(ret, "%s=%s,", attr, value); + } else { + ret = talloc_asprintf_append(ret, "%s=%s", attr, value); + } + if (ret == NULL) goto failed; + + dn += len; + if (*dn == ',') dn++; + } + + talloc_steal(ldb, ret); + talloc_free(tmp_ctx); + return ret; + +failed: + talloc_free(tmp_ctx); + return ldb_casefold(ldb, dn_orig); +} + diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 1a65eebd01..dfa72e4cd3 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -3,6 +3,11 @@ if test x"$with_ldap_support" = x"yes"; then SMB_MODULE_DEFAULT(libldb_ldap,STATIC) fi +SMB_MODULE_DEFAULT(libldb_sqlite3,NOT) +if test x"$with_sqlite3_support" = x"yes"; then + SMB_MODULE_DEFAULT(libldb_sqlite3,STATIC) +fi + SMB_LIBRARY_ENABLE(libldb,NO) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libldb,YES) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 87ec89e5d3..e5757a92f4 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -28,6 +28,18 @@ NOPROTO = YES # End MODULE libldb_tdb ################################################ +################################################ +# Start MODULE libldb_sqlite3 +[MODULE::libldb_sqlite3] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/ldb_sqlite3/ldb_sqlite3.o +REQUIRED_SUBSYSTEMS = \ + EXT_LIB_SQLITE3 +NOPROTO = YES +# End MODULE libldb_tdb +################################################ + ################################################ # Start MODULE libldb_tdb [MODULE::libldb_tdb] diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 18d974cf42..8ccf8967cb 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -225,6 +225,9 @@ int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif int ldb_dn_cmp(const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); +/* case-fold a DN */ +char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_attr_fn)(struct ldb_module * module, char * attr)); + /* create an empty message */ struct ldb_message *ldb_msg_new(void *mem_ctx); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index d36ced2667..0bce078a85 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -37,15 +37,16 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" -#undef SQL_EXEC /* just in case; not expected to be defined */ -#define SQL_EXEC(lsqlite3, query, reset) \ - do { \ - lsqlite3->last_rc = \ - sqlite3_step(lsqlite3->queries.query); \ - if (lsqlite3->last_rc == SQLITE_BUSY || reset) \ - (void) sqlite3_reset(lsqlite3->queries.query); \ - } while lsqlite3->last_rc == SQLITE_BUSY; - +#define QUERY(lsqlite3, pppValues, pNumRows, bRollbackOnError, sql...) \ + do \ + { \ + if (query(lsqlite3, pppValues, pNumRows, sql) != 0) { \ + if (bRollbackOnError) { \ + query(lsqlite3, NULL, NULL, "ROLLBACK;"); \ + } \ + return -1; \ + } \ + } while (0) #if 0 @@ -93,28 +94,8 @@ lsqlite3_rename(struct ldb_module *module, return 0; } - /* Bind old distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->queries.renameDN, - ":oldDN"); - if (sqlite3_bind_text(lsqlite3->queries.renameDN, column, - olddn, strlen(olddn), - SQLITE_STATIC) != SQLITE_OK) { - return -1; - } - - /* Bind new distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->queries.renameDN, - ":newDN"); - if (sqlite3_bind_text(lsqlite3->queries.renameDN, column, - newdn, strlen(newdn), - SQLITE_STATIC) != SQLITE_OK) { - return -1; - } - - /* Execute the query. This sets lsqlite3->last_rc */ - SQL_EXEC(lsqlite3, renameDN, TRUE); - - return lsqlite3->last_rc == 0 ? 0 : -1; +#warning "rename() is not yet supported" + return -1; } /* @@ -133,19 +114,7 @@ lsqlite3_delete(struct ldb_module *module, return 0; } - /* Bind distinguished names */ - column = sqlite3_bind_parameter_index(lsqlite3->queries.deleteDN, - ":dn"); - if (sqlite3_bind_text(lsqlite3->queries.deleteDN, column, - dn, strlen(dn), - SQLITE_STATIC) != SQLITE_OK) { - return -1; - } - - /* Execute the query. This sets lsqlite3->last_rc */ - SQL_EXEC(lsqlite3, deleteDN, TRUE); - - return lsqlite3->last_rc == 0 ? 0 : -1; + return -1; } /* @@ -332,9 +301,9 @@ failed: * requests in the ldb_message */ static int -lsqlite3_msg_to_sql(struct ldb_context *ldb, +lsqlite3_msg_to_sql(struct ldb_module *module, const struct ldb_message *msg, - long long dn_id, + long long eid, int use_flags) { int flags; @@ -353,88 +322,75 @@ lsqlite3_msg_to_sql(struct ldb_context *ldb, flags = el->flags & LDB_FLAG_MOD_MASK; } - /* Determine which query to use */ - switch (flags) { - case LDB_FLAG_MOD_ADD: - stmt = lsqlite3->queries.addAttrValuePair; - break; - - case LDB_FLAG_MOD_DELETE: - stmt = lsqlite3->queries.deleteAttrValuePairs; - break; - - case LDB_FLAG_MOD_REPLACE: - stmt = lsqlite3->queries.replaceAttrValuePairs; - break; - } - - /* - * All queries use dn id and attribute name. Bind them now. - */ - - /* Bind distinguished name id */ - column = - sqlite3_bind_parameter_index( - stmt, - ":dn_id"); - if (sqlite3_bind_int64(stmt, - column, - dn_id) != SQLITE_OK) { - - return -1; - } - - /* Bind attribute name */ - column = - sqlite3_bind_parameter_index( - stmt, - ":attr_name"); - if (sqlite3_bind_text(lsqlite3->queries.deleteDN, column, - el->name, strlen(el->name), - SQLITE_STATIC) != SQLITE_OK) { - - return -1; + if (flags == LDB_FLAG_MOD_ADD) { + /* Create the attribute table if it doesn't exist */ + if (create_attr_table(module, el->name) != 0) { + return -1; + } } - /* For each value of the specified attribute name... */ for (j = 0; j < el->num_values; j++) { /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: - case LDB_FLAG_MOD_REPLACE: - /* Bind attribute value */ - column = - sqlite3_bind_parameter_index( - stmt, - ":attr_value"); - if (sqlite3_bind_text( - stmt, column, - el->values[j].data, - el->values[j].length, - SQLITE_STATIC) != SQLITE_OK) { - - return -1; - } + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "INSERT INTO ldb_attr_%q " + " (eid, attr_value) " + " VALUES " + " (%lld, %Q);", + eid, el->data); + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " add_attr(entry_data, %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->data, eid); + + break; + case LDB_FLAG_MOD_REPLACE: + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "UPDATE ldb_attr_%q " + " SET attr_value = %Q " + " WHERE eid = %lld;", + el->data, eid); + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " mod_attr(entry_data, %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->data, eid); break; case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "DELETE FROM ldb_attr_%q " + " WHERE eid = %lld " + " AND attr_value = %Q;", + eid, el->data); + QUERY(lsqlite3, + NULL, NULL, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " del_attr(entry_data, %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->data, eid); break; } - - /* Execute the query */ - do { - lsqlite3->last_rc = sqlite3_step(stmt); - (void) sqlite3_reset(stmt); - } while lsqlite3->last_rc == SQLITE_BUSY; - - /* Make sure we succeeded */ - if (lsqlite3->last_rc != SQLITE_OK) { - return -1; - } } } @@ -442,6 +398,35 @@ lsqlite3_msg_to_sql(struct ldb_context *ldb, } +static char * +lsqlite3_normalize_dn(struct ldb_context * ldb, + char * pDN) +{ + char * pSrc; + char * pDest; + char * pNormalized; + + pNormalized = talloc_size(ldb, strlen(pDN) + 1); + if (pNormalized == NULL) { + errno = ENOMEM; + return -1; + } + + for (pSrc = pDN, pDest = pNormalized; *pSrc != '\0'; ) { + + } +} + + +static int +lsqlite3_insert_dn_recursive(struct lsqlite3_private * lsqlite3, + char * pDN, + long long * pEID) +{ + +} + + /* * add a record */ @@ -450,6 +435,7 @@ lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) { int ret; + long long eid; struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -459,42 +445,28 @@ lsqlite3_add(struct ldb_module *module, } /* Begin a transaction */ - SQL_EXEC(lsqlite3, begin, TRUE); + QUERY(lsqlite3, NULL, NULL< FALSE, "BEGIN EXCLUSIVE;"); - /* This is a new DN. Bind new distinguished name */ - column = sqlite3_bind_parameter_index(lsqlite3->queries.newDN, ":dn"); - if (sqlite3_bind_text(lsqlite3->queries.newDN, column, - msg->dn, strlen(msg->dn), - SQLITE_STATIC) != SQLITE_OK) { - return -1; - } - - /* Add this new DN. This sets lsqlite3->last_rc */ - SQL_EXEC(lsqlite3, newDN, TRUE); - - if (lsqlite3->last_rc != SQLITE_DONE) { + /* + * Build any portions of the directory tree that don't exist. If the + * final component already exists, it's an error. + */ + if (lsqlite3_insert_dn_recursive(lsqlite3, + lsqlite3_normalize_dn(ldb, msg->dn), + &eid) != 0) { + QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); return -1; } - - /* Get the id of the just-added DN */ - dn_id = sqlite3_last_insert_rowid(lsqlite3->sqlite3); - - ret = lsqlite3_msg_to_sql(ldb, msg, dn_id, FALSE); - /* Did the attribute additions (if any) succeeded? */ - if (ret == 0) - { - /* Yup. Commit the transaction */ - SQL_EXEC(lsqlite3, commit, TRUE); - } - else - { - /* Attribute addition failed. Rollback the transaction */ - SQL_EXEC(lsqlite3, rollback, TRUE); + /* Add attributes to this new entry */ + if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { + QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); + return -1; } - /* If everything succeeded, return success */ - return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1; + /* Everything worked. Commit it! */ + QUERY(lsqlite3, NULL, NULL, TRUE, "COMMIT;"); + return 0; } @@ -506,6 +478,8 @@ lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { int ret = 0; + int numRows; + char ** ppValues; struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -515,47 +489,37 @@ lsqlite3_modify(struct ldb_module *module, } /* Begin a transaction */ - SQL_EXEC(lsqlite3, begin, TRUE); - - /* Get the dn_id for the specified DN */ - column = - sqlite3_bind_parameter_index( - lsqlite3->queries.getDNID, - ":dn"); - if (sqlite3_bind_text(lsqlite3->queries.getDNID, - column, - msg->dn, strlen(msg->dn), - SQLITE_STATIC) != SQLITE_OK) { + QUERY(lsqlite3, NULL, NULL, FALSE, "BEGIN EXCLUSIVE;"); + + /* Get the id of this DN. */ + QUERY(lsqlite3, + &ppValues, + &numRows, + TRUE, + "SELECT eid " + " FROM ldb_entry " + " WHERE dn = %Q;", + lsqlite3_normalize_dn(ldb, msg->dn)); + + /* Did it exist? */ + if (numRows != 1) { + /* Nope. See ya! */ + sqlite_free_table(ppValues); return -1; } - /* Get the id of this DN. This sets lsqlite3->last_rc */ - SQL_EXEC(lsqlite3, getDNID, FALSE); - - if (lsqlite3->last_rc != SQLITE_ROW) { - return -1; - } - - dn_id = sqlite3_column_int64(lsqlite3->queries.getDNID, - column); - (void) sqlite3_reset(lsqlite3->queries.getDNID); - - ret = lsqlite3_msg_to_sql(ldb, msg, dn_id, FALSE); + /* Retrieve the eid */ + eid = strtoll(ppValues[1], NULL, 10); - /* Did the attribute additions (if any) succeeded? */ - if (ret == 0) - { - /* Yup. Commit the transaction */ - SQL_EXEC(lsqlite3, commit, TRUE); - } - else - { - /* Attribute addition failed. Rollback the transaction */ - SQL_EXEC(lsqlite3, rollback, TRUE); + /* Modify attributes as specified */ + if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { + QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); + return -1; } - /* If everything succeeded, return success */ - return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1; + /* Everything worked. Commit it! */ + QUERY(lsqlite3, NULL, NULL, TRUE, "COMMIT;"); + return 0 ; } static int @@ -570,15 +534,9 @@ lsqlite3_lock(struct ldb_module *module, return -1; } - /* If we're already locked, just update lock count */ - if (++lsqlite3->lock_count > 1) { - return -1; - } - - /* Write-lock (but not read-lock) the database */ - SQL_EXEC(lsqlite3, begin, TRUE); + /* TODO implement a local locking mechanism here */ - return lsqlite3->last_rc == 0 ? 0 : -1; + return 0; } static int @@ -593,19 +551,9 @@ lsqlite3_unlock(struct ldb_module *module, return -1; } - /* If we're not already locked, there's nothing to do */ - if (lsqlite3->lock_count == 0) { - return 0; - } + /* TODO implement a local locking mechanism here */ - /* Decrement lock count */ - if (--lsqlite3->lock_count == 0) { - - /* Final unlock. Unlock the database */ - SQL_EXEC(lsqlite3, commit, TRUE); - } - - return lsqlite3->last_rc == 0 ? 0 : -1; + return 0; } /* @@ -647,6 +595,7 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3, const char *url) { + int ret; int bNewDatabase = False; char * p; char * pTail; @@ -668,110 +617,124 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, SELECT 'LDB' AS database_type, '1.0' AS version; - CREATE TABLE ldb_distinguished_names - ( - dn_id INTEGER PRIMARY KEY AUTOINCREMENT, - dn TEXT UNIQUE - ); + -- ------------------------------------------------------ + -- Schema - CREATE TABLE ldb_object_classes + /* + * The entry table holds the information about an entry. This + * table is used to obtain the EID of the entry and to support + * scope=one and scope=base. The parent and child table + * is included in the entry table since all the other + * attributes on EID. + */ + CREATE TABLE ldb_entry ( - class_name TEXT PRIMARY KEY, - tree_key TEXT, - max_child_num INTEGER + -- Unique identifier of this LDB entry + eid INTEGER PRIMARY KEY, + + -- Unique identifier of the parent LDB entry + peid INTEGER REFERENCES ldb_entry, + + -- Distinguished name of this entry + dn TEXT, + + -- Time when the entry was created + create_timestamp INTEGER, + + -- Time when the entry was last modified + modify_timestamp INTEGER, + + -- Attributes of this entry, in the form + -- attr\1value\0[attr\1value\0]*\0 + entry_data TEXT ); - CREATE TABLE ldb_dn_object_classes + + /* + * The purpose of the descendant table is to support the + * subtree search feature. For each LDB entry with a unique + * ID (AEID), this table contains the unique identifiers + * (DEID) of the descendant entries. + * + * For evern entry in the directory, a row exists in this + * table for each of its ancestors including itself. The size + * of the table depends on the depth of each entry. In the + * worst case, if all the entries were at the same depth, the + * number of rows in the table is O(nm) where n is the number + * of nodes in the directory and m is the depth of the tree. + */ + CREATE TABLE ldb_descendants ( - dn_id INTEGER REFERENCES ldb_distinguished_names, - class_name TEXT REFERENCES ldb_object_classes + -- The unique identifier of the ancestor LDB entry + aeid INTEGER REFERENCES ldb_entry, + + -- The unique identifier of the descendant LDB entry + deid INTEGER REFERENCES ldb_entry ); - CREATE TABLE ldb_attributes + + CREATE TABLE ldb_object_classes ( - attr_name TEXT PRIMARY KEY, - case_insensitive_p BOOLEAN DEFAULT FALSE, - wildcard_p BOOLEAN DEFAULT FALSE, - hidden_p BOOLEAN DEFAULT FALSE, - integer_p BOOLEAN DEFAULT FALSE + -- Object classes are inserted into this table to track + -- their class hierarchy. 'top' is the top-level class + -- of which all other classes are subclasses. + class_name TEXT PRIMARY KEY, + + -- tree_key tracks the position of the class in + -- the hierarchy + tree_key TEXT UNIQUE ); - CREATE TABLE ldb_attr_value_pairs + /* + * There is one attribute table per searchable attribute. + */ +/* + CREATE TABLE ldb_attr_ATTRIBUTE_NAME ( - dn_id INTEGER REFERENCES ldb_distinguished_names, - attr_name TEXT, -- optionally REFERENCES ldb_attributes - attr_value TEXT, + -- The unique identifier of the LDB entry + eid INTEGER REFERENCES ldb_entry, - UNIQUE (dn_id, attr_name, attr_value) + -- Normalized attribute value + attr_value TEXT ); +*/ + -- ------------------------------------------------------ + -- Indexes - CREATE TRIGGER ldb_distinguished_names_delete_tr - AFTER DELETE - ON ldb_distinguished_names - FOR EACH ROW - BEGIN - DELETE FROM ldb_attr_value_pairs - WHERE dn_id = old.dn_id; - DELETE FROM ldb_dn_object_classes - WHERE dn_id = old.dn_id; - END; - CREATE TRIGGER ldb_attr_value_pairs_insert_tr - BEFORE INSERT - ON ldb_attr_value_pairs + -- ------------------------------------------------------ + -- Triggers + + CREATE TRIGGER ldb_entry_insert_tr + AFTER INSERT + ON ldb_entry FOR EACH ROW BEGIN - INSERT OR IGNORE INTO ldb_attributes - (attr_name) - VALUES - (new.attr_name); + UPDATE ldb_entry + SET create_timestamp = strftime('%s', 'now'), + modify_timestamp = strftime('%s', 'now') + WHERE eid = new.eid; END; - CREATE TRIGGER ldb_attr_value_pairs_delete_tr - AFTER DELETE - ON ldb_attr_value_pairs + CREATE TRIGGER ldb_entry_update_tr + AFTER UPDATE + ON ldb_entry FOR EACH ROW BEGIN - DELETE FROM ldb_attributes - WHERE (SELECT COUNT(*) - FROM ldb_attr_value_pairs - WHERE attr_name = old.attr_name) = 0 - AND attr_name = old.attr_name; + UPDATE ldb_entry + SET modify_timestamp = strftime('%s', 'now') + WHERE eid = old.eid; END; -- ------------------------------------------------------ + -- Table initialization - CREATE INDEX ldb_distinguished_names_dn_idx - ON ldb_distinguished_names (dn); - - CREATE INDEX ldb_object_classes_tree_key_idx - ON ldb_object_classes (tree_key); - - - CREATE INDEX ldb_dn_object_classes_dn_id_idx - ON ldb_dn_object_classes (dn_id); - - CREATE INDEX ldb_dn_object_classes_class_name_idx - ON ldb_dn_object_classes (class_name); - - - CREATE INDEX ldb_attr_value_pairs_dn_id_name_case_idx - ON ldb_attr_value_pairs (dn_id, attr_name); - - CREATE INDEX ldb_attr_value_pairs_dn_id_name_nocase_idx - ON ldb_attr_value_pairs (dn_id, attr_name COLLATE NOCASE); - - -- ------------------------------------------------------ - - /* all defaults for dn, initially */ - INSERT INTO ldb_attributes (attr_name) - VALUES ('dn'); - - /* We need an implicit 'top' level object class */ - INSERT INTO ldb_object_classes (class_name, tree_key) - SELECT 'top', /* next_tree_key(NULL) */ '0001'; + /* We need an implicit "top" level object class */ + INSERT INTO ldb_attributes (attr_name, + parent_tree_key) + SELECT 'top', ''; -- ------------------------------------------------------ @@ -797,7 +760,7 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, } /* Try to open the (possibly empty/non-existent) database */ - if ((lsqlite3->last_rc = sqlite3_open(p, &lsqlite3->sqlite3)) != SQLITE_SUCCESS) { + if ((ret = sqlite3_open(p, &lsqlite3->sqlite3)) != SQLITE_SUCCESS) { return ret; } @@ -831,18 +794,15 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, " WHERE type = 'table' " " AND name IN " " (" - " 'ldb_info', " - " 'ldb_distinguished_names', " - " 'ldb_object_classes', " - " 'ldb_dn_object_classes', " - " 'ldb_attributes', " - " 'ldb_attr_value_pairs' " + " 'ldb_entry', " + " 'ldb_descendants', " + " 'ldb_object_classes' " " );", -1, &stmt, &pTail)) != SQLITE_SUCCESS || (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_ROW || - sqlite3_column_int(stmt, 0) != 6 || + sqlite3_column_int(stmt, 0) != 3 || (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS || (lsqlite3->last_rc = sqlite3_prepare( @@ -863,149 +823,6 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, } } - /* - * Pre-compile each of the queries we'll be using. - */ - - if ((lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "BEGIN IMMEDIATE;", - -1, - &lsqlite3->queries.begin, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "COMMIT;", - -1, - &lsqlite3->queries.commit, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "ROLLBACK;", - -1, - &lsqlite3->queries.rollback, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT INTO ldb_distinguished_names (dn_id, dn) " - " VALUES (:dn_id, :dn);", - -1, - &lsqlite3->queries.newDN, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "UPDATE ldb_distinguished_names " - " SET dn = :newDN " - " WHERE dn = :oldDN;", - -1, - &lsqlite3->queries.renameDN, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "DELETE FROM ldb_distinguished_names " - " WHERE dn = :dn;", - -1, - &lsqlite3->queries.deleteDN, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT OR IGNORE INTO ldb_object_classes " - " (class_name, tree_key)" - " SELECT :class_name, next_tree_key(NULL);", - -1, - &lsqlite3->queries.newObjectClass, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT OR REPLACE INTO ldb_dn_object_classes " - " (dn_id, class_name) " - " VALUES (:dn_id, :class_name);", - -1, - &lsqlite3->queries.assignObjectClass, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT OR IGNORE INTO ldb_attributes (name) " - " VALUES (:name);", - -1, - &lsqlite3->queries.newAttributeUseDefaults, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT OR REPLACE INTO ldb_attributes " - " (name, " - " case_insensitive_p, " - " wildcard_p, " - " hidden_p, " - " integer_p) " - " VALUES (:name, " - " :case_insensitive_p, " - " :wildcard_p, " - " :hidden_p, " - " :integer_p);", - -1, - &lsqlite3->queries.newAttribute, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT INTO ldb_attr_value_pairs " - " (dn_id, attr_name, attr_value) " - " VALUES (:dn_id, :attr_name, :attr_value);", - -1, - &lsqlite3->queries.addAttrValuePair, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "UPDATE ldb_attr_value_pairs " - " SET attr_value = :attr_value " - " WHERE dn_id = :dn_id " - " AND attr_name = :attr_name;", - -1, - &lsqlite3->queries.addAttrValuePair, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "DELETE FROM ldb_attr_value_pairs " - " WHERE dn_id = :dn_id " - " AND attr_name = :attr_name;" - -1, - &lsqlite3->queries.deleteAttrValuePair, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "INSERT OR REPLACE INTO ldb_object_classes " - " (class_name, tree_key) " - " SELECT :child_class, next_tree_key(:parent_class);" - -1, - &lsqlite3->queries.insertSubclass, - &pTail)) != SQLITE_SUCCESS || - - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, - "SELECT dn_id " - " FROM ldb_distinguished_names " - " WHERE dn = :dn;" - -1, - &lsqlite3->queries.getDNID, - &pTail)) != SQLITE_SUCCESS) { - - (void) sqlite3_close(lsqlite3->sqlite3); - return ret; - } - return SQLITE_SUCCESS; } diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 2fa08fdcb7..192e28f3dc 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -5,24 +5,6 @@ struct lsqlite3_private { const char *basedn; sqlite3 * sqlite; int lock_count; - int last_rc; - struct { - sqlite3_stmt *begin; - sqlite3_stmt *commit; - sqlite3_stmt *rollback; - sqlite3_stmt *newDN; - sqlite3_stmt *renameDN; - sqlite3_stmt *deleteDN; - sqlite3_stmt *newObjectClass; - sqlite3_stmt *assignObjectClass; - sqlite3_stmt *newAttributeUseDefaults; - sqlite3_stmt *newAttribute; - sqlite3_stmt *addAttrValuePair; - sqlite3_stmt *replaceAttrValuePairs; - sqlite3_stmt *deleteAttrValuePairs; - sqlite3_stmt *insertSubclass; - sqlite3_stmt *getDNID; - } queries; }; void diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index 08dc50de08..78550985d4 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -12,158 +12,119 @@ SELECT 'LDB' AS database_type, '1.0' AS version; + -- ------------------------------------------------------ + -- Schema + /* - * Get the next USN value with: - * BEGIN EXCLUSIVE; - * UPDATE usn SET value = value + 1; - * SELECT value FROM usn; - * COMMIT; + * The entry table holds the information about an entry. This + * table is used to obtain the EID of the entry and to support + * scope="one" and scope="base". The parent and child table + * is included in the entry table since all the other + * attributes on EID. */ - CREATE TABLE usn + CREATE TABLE ldb_entry ( - value INTEGER + -- Unique identifier of this LDB entry + eid INTEGER PRIMARY KEY, + + -- Unique identifier of the parent LDB entry + peid INTEGER REFERENCES ldb_entry, + + -- Distinguished name of this entry + dn TEXT, + + -- Time when the entry was created + create_timestamp INTEGER, + + -- Time when the entry was last modified + modify_timestamp INTEGER, + + -- Attributes of this entry, in the form + -- attr\1value\0[attr\1value\0]*\0 + entry_data TEXT ); - CREATE TABLE ldb_object + + /* + * The purpose of the descendant table is to support the + * subtree search feature. For each LDB entry with a unique + * ID (AEID), this table contains the unique identifiers + * (DEID) of the descendant entries. + * + * For evern entry in the directory, a row exists in this + * table for each of its ancestors including itself. The size + * of the table depends on the depth of each entry. In the + * worst case, if all the entries were at the same depth, the + * number of rows in the table is O(nm) where n is the number + * of nodes in the directory and m is the depth of the tree. + */ + CREATE TABLE ldb_descendants ( - /* tree_key is auto-generated by the insert trigger */ - tree_key TEXT PRIMARY KEY, - - parent_tree_key TEXT, - dn TEXT, - - attr_name TEXT REFERENCES ldb_attributes, - attr_value TEXT, - - /* - * object_type can take on these values (to date): - * 1: object is a node of a DN - * 2: object is an attribute/value pair of its parent DN - */ - object_type INTEGER, - - /* - * if object_type is 1, the node can have children. - * this tracks the maximum previously assigned child - * number so we can generate a new unique tree key for - * a new child object. note that this is always incremented, - * so if children are deleted, this will not represent - * the _number_ of children. - */ - max_child_num INTEGER, - - /* - * Automatically maintained meta-data (a gift for metze) - */ - object_guid TEXT UNIQUE, - timestamp INTEGER, -- originating_time - invoke_id TEXT, -- GUID: originating_invocation_id - usn INTEGER, -- hyper: originating_usn - - /* do not allow duplicate name/value pairs */ - UNIQUE (parent_tree_key, attr_name, attr_value, object_type) + -- The unique identifier of the ancestor LDB entry + aeid INTEGER REFERENCES ldb_entry, + + -- The unique identifier of the descendant LDB entry + deid INTEGER REFERENCES ldb_entry ); - CREATE TABLE ldb_attributes - ( - attr_name TEXT PRIMARY KEY, - parent_tree_key TEXT, - objectclass_p BOOLEAN DEFAULT 0, + CREATE TABLE ldb_object_classes + ( + -- Object classes are inserted into this table to track + -- their class hierarchy. 'top' is the top-level class + -- of which all other classes are subclasses. + class_name TEXT PRIMARY KEY, + + -- tree_key tracks the position of the class in + -- the hierarchy + tree_key TEXT UNIQUE + ); - case_insensitive_p BOOLEAN DEFAULT 0, - wildcard_p BOOLEAN DEFAULT 0, - hidden_p BOOLEAN DEFAULT 0, - integer_p BOOLEAN DEFAULT 0, + /* + * There is one attribute table per searchable attribute. + */ +/* + CREATE TABLE ldb_attr_ATTRIBUTE_NAME + ( + -- The unique identifier of the LDB entry + eid INTEGER REFERENCES ldb_entry, - /* tree_key is auto-generated by the insert trigger */ - tree_key TEXT, -- null if not a object/sub class - -- level 1 if an objectclass - -- level 1-n if a subclass - max_child_num INTEGER + -- Normalized attribute value + attr_value TEXT ); +*/ - -- ------------------------------------------------------ - CREATE INDEX ldb_object_dn_idx - ON ldb_object (dn); + -- ------------------------------------------------------ + -- Indexes - CREATE INDEX ldb_attributes_tree_key_ids - ON ldb_attributes (tree_key); -- ------------------------------------------------------ + -- Triggers - /* Gifts for metze. Automatically updated meta-data */ - CREATE TRIGGER ldb_object_insert_tr + CREATE TRIGGER ldb_entry_insert_tr AFTER INSERT - ON ldb_object + ON ldb_entry FOR EACH ROW BEGIN - UPDATE ldb_object - SET max_child_num = max_child_num + 1 - WHERE tree_key = new.parent_tree_key; - UPDATE usn SET value = value + 1; - UPDATE ldb_object - SET tree_key = - (SELECT - new.tree_key || - base160(SELECT max_child_num - FROM ldb_object - WHERE tree_key = - new.parent_tree_key)); - max_child_num = 0, - object_guid = random_guid(), - timestamp = strftime('%s', 'now'), - usn = (SELECT value FROM usn); - WHERE tree_key = new.tree_key; + UPDATE ldb_entry + SET create_timestamp = strftime('%s', 'now'), + modify_timestamp = strftime('%s', 'now') + WHERE eid = new.eid; END; - CREATE TRIGGER ldb_object_update_tr + CREATE TRIGGER ldb_entry_update_tr AFTER UPDATE - ON ldb_object + ON ldb_entry FOR EACH ROW BEGIN - UPDATE usn SET value = value + 1; - UPDATE ldb_object - SET timestamp = strftime('%s', 'now'), - usn = (SELECT value FROM usn); - WHERE tree_key = new.tree_key; + UPDATE ldb_entry + SET modify_timestamp = strftime('%s', 'now') + WHERE eid = old.eid; END; - CREATE TRIGGER ldb_attributes_insert_tr - AFTER INSERT - ON ldb_attributes - FOR EACH ROW - BEGIN - UPDATE ldb_attributes - SET max_child_num = max_child_num + 1 - WHERE tree_key = new.parent_tree_key; - UPDATE ldb_attributes - SET tree_key = - (SELECT - new.tree_key || - base160(SELECT max_child_num - FROM ldb_attributes - WHERE tree_key = - new.parent_tree_key)); - max_child_num = 0 - WHERE tree_key = new.tree_key; - END; - - -- ------------------------------------------------------ - - /* Initialize usn */ - INSERT INTO usn (value) VALUES (0); - - /* Create root object */ - INSERT INTO ldb_object - (tree_key, parent_tree_key, - dn, - object_type, max_child_num) - VALUES ('', NULL, - '', - 1, 0); + -- Table initialization /* We need an implicit "top" level object class */ INSERT INTO ldb_attributes (attr_name, diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index f6a23d7433..9c126c1dfd 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -44,78 +44,12 @@ /* - casefold a dn. We need to uppercase the attribute names, and the - attribute values of case insensitive attributes. We also need to remove - extraneous spaces between elements + callback function used in call to ldb_dn_fold() for determining whether an + attribute type requires case folding. */ -static char *ltdb_dn_fold(struct ldb_module *module, const char *dn) +static int ltdb_case_fold_attr_required(struct ldb_module *module, char *attr) { - const char *dn_orig = dn; - struct ldb_context *ldb = module->ldb; - TALLOC_CTX *tmp_ctx = talloc_new(ldb); - char *ret; - size_t len; - - ret = talloc_strdup(tmp_ctx, ""); - if (ret == NULL) goto failed; - - while ((len = strcspn(dn, ",")) > 0) { - char *p = strchr(dn, '='); - char *attr, *value; - int flags; - - if (p == NULL || (p-dn) > len) goto failed; - - attr = talloc_strndup(tmp_ctx, dn, p-dn); - if (attr == NULL) goto failed; - - /* trim spaces from the attribute name */ - while (' ' == *attr) attr++; - while (' ' == attr[strlen(attr)-1]) { - attr[strlen(attr)-1] = 0; - } - if (*attr == 0) goto failed; - - value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn)); - if (value == NULL) goto failed; - - /* trim spaces from the value */ - while (' ' == *value) value++; - while (' ' == value[strlen(value)-1]) { - value[strlen(value)-1] = 0; - } - if (*value == 0) goto failed; - - flags = ltdb_attribute_flags(module, attr); - - attr = ldb_casefold(ldb, attr); - if (attr == NULL) goto failed; - talloc_steal(tmp_ctx, attr); - - if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - value = ldb_casefold(ldb, value); - if (value == NULL) goto failed; - talloc_steal(tmp_ctx, value); - } - - if (dn[len] == ',') { - ret = talloc_asprintf_append(ret, "%s=%s,", attr, value); - } else { - ret = talloc_asprintf_append(ret, "%s=%s", attr, value); - } - if (ret == NULL) goto failed; - - dn += len; - if (*dn == ',') dn++; - } - - talloc_steal(ldb, ret); - talloc_free(tmp_ctx); - return ret; - -failed: - talloc_free(tmp_ctx); - return ldb_casefold(ldb, dn_orig); + return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE; } /* @@ -172,7 +106,7 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) } talloc_free(attr_name); } else { - dn_folded = ltdb_dn_fold(module, dn); + dn_folded = ldb_dn_fold(module, dn, ltdb_case_fold_attr_required); } if (!dn_folded) { diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 3e6e7d7feb..26bd198d1d 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -48,6 +48,7 @@ static void usage(void) printf(" -s base|sub|one choose search scope\n"); printf(" -b basedn choose baseDN\n"); printf(" -i read search expressions from stdin\n"); + printf(" -S sort returned attributes\n"); printf(" -o options pass options like modules to activate\n"); printf(" e.g: -o modules:timestamps\n"); exit(1); @@ -56,6 +57,7 @@ static void usage(void) static int do_search(struct ldb_context *ldb, const char *basedn, int scope, + int sort_attribs, const char *expression, const char * const *attrs) { @@ -77,6 +79,15 @@ static int do_search(struct ldb_context *ldb, ldif.changetype = LDB_CHANGETYPE_NONE; ldif.msg = msgs[i]; + if (sort_attribs) { + /* + * Ensure attributes are always returned in the same + * order. For testing, this makes comparison of old + * vs. new much easier. + */ + ldb_msg_sort_elements(ldif.msg); + } + ldb_ldif_write_file(ldb, stdout, &ldif); } @@ -100,7 +111,7 @@ static int do_search(struct ldb_context *ldb, const char **options = NULL; int opt, ldbopts; enum ldb_scope scope = LDB_SCOPE_SUBTREE; - int interactive = 0, ret=0; + int interactive = 0, sort_attribs=0, ret=0; ldb_url = getenv("LDB_URL"); @@ -129,6 +140,10 @@ static int do_search(struct ldb_context *ldb, interactive = 1; break; + case 'S': + sort_attribs = 1; + break; + case 'o': options = ldb_options_parse(options, &ldbopts, optarg); break; @@ -168,12 +183,12 @@ static int do_search(struct ldb_context *ldb, if (interactive) { char line[1024]; while (fgets(line, sizeof(line), stdin)) { - if (do_search(ldb, basedn, scope, line, attrs) == -1) { + if (do_search(ldb, basedn, scope, sort_attribs, line, attrs) == -1) { ret = -1; } } } else { - ret = do_search(ldb, basedn, scope, argv[0], attrs); + ret = do_search(ldb, basedn, scope, sort_attribs, argv[0], attrs); } talloc_free(ldb); diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 670fdda7cd..e9cbc12b91 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -105,9 +105,18 @@ #define MAP_FAILED ((void *)-1) #endif +#ifndef discard_const_p +# if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const(ptr) ((void *)((intptr_t)(ptr))) +# else +# define discard_const(ptr) ((void *)(ptr)) +# endif +# define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + /* free memory if the pointer is valid and zero the pointer */ #ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) #endif #define BUCKET(hash) ((hash) % tdb->header.hash_size) -- cgit From ec9bdca186d1378d327e0f84da60fa18c1fc787a Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 18:33:21 +0000 Subject: r7280: taking advantage of previous research. this is documentation on which latest schema is based (This used to be commit 603faa9cabd6d83c2e0fcfea476c5bda3f76b741) --- source4/lib/ldb/ldb_sqlite3/shi.pdf | Bin 0 -> 1084939 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 source4/lib/ldb/ldb_sqlite3/shi.pdf (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/shi.pdf b/source4/lib/ldb/ldb_sqlite3/shi.pdf new file mode 100644 index 0000000000..1437ce87f1 Binary files /dev/null and b/source4/lib/ldb/ldb_sqlite3/shi.pdf differ -- cgit From 150f127aa3d489cb44486450807517b7cd248ef4 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 20:30:49 +0000 Subject: r7281: removing document (This used to be commit 6867d56796ce4dd85c69107c6a0a5cf4bf93f585) --- source4/lib/ldb/ldb_sqlite3/shi.pdf | Bin 1084939 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 source4/lib/ldb/ldb_sqlite3/shi.pdf (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/shi.pdf b/source4/lib/ldb/ldb_sqlite3/shi.pdf deleted file mode 100644 index 1437ce87f1..0000000000 Binary files a/source4/lib/ldb/ldb_sqlite3/shi.pdf and /dev/null differ -- cgit From 217a8cfe6677c0d435992f96996d5415824f598b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 21:16:54 +0000 Subject: r7282: ldb_sqlite3 work in progress. (This used to be commit d934c42b00b68e8f4ac9d0583ac307818aeb494f) --- source4/lib/ldb/Makefile.in | 13 +- source4/lib/ldb/config.mk | 2 +- source4/lib/ldb/configure.in | 3 + source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 519 ++++++++++++++++-------------- source4/lib/ldb/ldb_sqlite3/schema | 4 +- 5 files changed, 288 insertions(+), 253 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 4d93edb884..88aa66fcf1 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -8,6 +8,7 @@ libdir = @libdir@ bindir = @bindir@ WITH_GCOV = @WITH_GCOV@ WITH_LDAP = @WITH_LDAP@ +WITH_SQLITE3 = @WITH_LDAP@ ifeq ($(WITH_LDAP),yes) OPENLDAP_PREFIX=/usr @@ -16,6 +17,13 @@ LDAP_FLAGS=-DHAVE_LDAP=1 LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o endif +ifeq ($(WITH_SQLITE3),yes) +SQLITE3_PREFIX=/usr +SQLITE3_LIBS=-L$(SQLITE3_PREFIX)/lib -lsqlite3 +SQLITE3_FLAGS=-DHAVE_SQLITE3=1 +LDB_SQLITE3_OBJ=ldb_sqlite3/ldb_sqlite3.o +endif + TDBDIR=../tdb TALLOCDIR=../talloc @@ -31,7 +39,7 @@ endif CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) @CFLAGS@ -LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(GCOV_LIBS) +LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o TALLOC_OBJ=$(TALLOCDIR)/talloc.o @@ -47,7 +55,7 @@ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ MODULES_OBJ=modules/timestamps.o modules/schema.o -OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) +OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) $(LDB_SQLITE3_OBJ) LDB_LIB = lib/libldb.a @@ -128,6 +136,7 @@ install: all cp ldb.pc $(libdir)/pkgconfig gcov: + $(GCOV) -po ldb_sqlite3 ldb_sqlite3/*.c 2| tee ldb_sqlite3.report.gcov $(GCOV) -po ldb_ldap ldb_ldap/*.c 2| tee ldb_ldap.report.gcov $(GCOV) -po ldb_tdb ldb_tdb/*.c 2| tee ldb_tdb.report.gcov $(GCOV) -po common common/*.c 2| tee common.report.gcov diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index e5757a92f4..03a3a401fb 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -37,7 +37,7 @@ INIT_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ EXT_LIB_SQLITE3 NOPROTO = YES -# End MODULE libldb_tdb +# End MODULE libldb_sqlite3 ################################################ ################################################ diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index aec149360b..fcb87cdb3a 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -26,6 +26,9 @@ AC_CONFIG_HEADER(include/config.h) sinclude(ldap.m4) WITH_LDAP=$with_ldap_support AC_SUBST(WITH_LDAP) +sinclude(sqlite3.m4) +WITH_SQLITE3=$with_sqlite3_support +AC_SUBST(WITH_SQLITE3) sinclude(config.m4) sinclude(../talloc/config.m4) AC_OUTPUT(Makefile ldb.pc) diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 0bce078a85..6dfaa0627b 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -37,20 +37,49 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" +#ifndef False +# define False (0) +# define True (! False) +#endif + #define QUERY(lsqlite3, pppValues, pNumRows, bRollbackOnError, sql...) \ do \ { \ - if (query(lsqlite3, pppValues, pNumRows, sql) != 0) { \ + if (lsqlite3_query(lsqlite3, \ + pppValues, \ + pNumRows, \ + sql) != 0) { \ if (bRollbackOnError) { \ - query(lsqlite3, NULL, NULL, "ROLLBACK;"); \ + lsqlite3_query(lsqlite3, \ + NULL, \ + NULL, \ + "ROLLBACK;"); \ } \ return -1; \ } \ } while (0) +static int +lsqlite3_query(const struct lsqlite3_private *lsqlite3, + char ***pppValues, + int *pNumRows, + const char *pSql, + ...) +{ + +} + +static int +lsqlite3_create_attr_table(struct ldb_module *module, + char * pAttr) +{ + +} + + #if 0 -/* +p/* * we don't need this right now, but will once we add some backend options * * find an option in an option list (a null terminated list of strings) @@ -78,6 +107,18 @@ lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, } #endif +/* + callback function used in call to ldb_dn_fold() for determining whether an + attribute type requires case folding. +*/ +static int lsqlite3_case_fold_attr_required(struct ldb_module *module, + char *attr) +{ +#warning "currently, all attributes require case folding" + return True; +} + + /* * rename a record */ @@ -86,15 +127,12 @@ lsqlite3_rename(struct ldb_module *module, const char *olddn, const char *newdn) { - int column; - struct lsqlite3_private * lsqlite3 = module->private_data; - /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { return 0; } -#warning "rename() is not yet supported" +#warning "lsqlite3_rename() is not yet supported" return -1; } @@ -105,10 +143,6 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn) { - int ret = 0; - int column; - struct lsqlite3_private * lsqlite3 = module->private_data; - /* ignore ltdb specials */ if (dn[0] == '@') { return 0; @@ -117,6 +151,7 @@ lsqlite3_delete(struct ldb_module *module, return -1; } +#if 0 /* not currently used * / /* * free a search result */ @@ -127,11 +162,21 @@ lsqlite3_search_free(struct ldb_module *module, talloc_free(res); return 0; } +#endif /* * add a single set of ldap message values to a ldb_message */ + +/* get things to compile before we actually implement this function */ +struct berval +{ + int x; +}; + +#warning "lsqlite3_add_msg_attr() not yet implemented or used" +#if 0 static int lsqlite3_add_msg_attr(struct ldb_context *ldb, struct ldb_message *msg, @@ -186,6 +231,7 @@ lsqlite3_add_msg_attr(struct ldb_context *ldb, return 0; } +#endif /* * search for matching records @@ -195,9 +241,11 @@ lsqlite3_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, - const char * const *attrs, + const char * const attrs[], struct ldb_message ***res) { +#warning "lsqlite3_search() not yet implemented" +#if 0 int count; int msg_count; struct ldb_context * ldb = module->ldb; @@ -293,6 +341,9 @@ lsqlite3_search(struct ldb_module *module, failed: if (*res) lsqlite3_search_free(module, *res); return -1; +#else + return 0; +#endif } @@ -309,8 +360,6 @@ lsqlite3_msg_to_sql(struct ldb_module *module, int flags; unsigned int i; unsigned int j; - sqlite3_stmt * stmt = NULL; - struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; for (i = 0; i < msg->num_elements; i++) { @@ -324,7 +373,8 @@ lsqlite3_msg_to_sql(struct ldb_module *module, if (flags == LDB_FLAG_MOD_ADD) { /* Create the attribute table if it doesn't exist */ - if (create_attr_table(module, el->name) != 0) { + if (lsqlite3_create_attr_table(module, + el->name) != 0) { return -1; } } @@ -337,58 +387,58 @@ lsqlite3_msg_to_sql(struct ldb_module *module, case LDB_FLAG_MOD_ADD: QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "INSERT INTO ldb_attr_%q " " (eid, attr_value) " " VALUES " " (%lld, %Q);", - eid, el->data); + eid, el->values[j].data); QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "UPDATE ldb_entry " " SET entry_data = " " add_attr(entry_data, %Q, %Q) " " WHERE eid = %lld;", - el->name, el->data, eid); + el->name, el->values[j].data, eid); break; case LDB_FLAG_MOD_REPLACE: QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "UPDATE ldb_attr_%q " " SET attr_value = %Q " " WHERE eid = %lld;", - el->data, eid); + el->values[j].data, eid); QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "UPDATE ldb_entry " " SET entry_data = " " mod_attr(entry_data, %Q, %Q) " " WHERE eid = %lld;", - el->name, el->data, eid); + el->name, el->values[j].data, eid); break; case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "DELETE FROM ldb_attr_%q " " WHERE eid = %lld " " AND attr_value = %Q;", - eid, el->data); + eid, el->values[j].data); QUERY(lsqlite3, NULL, NULL, - FALSE, + False, "UPDATE ldb_entry " " SET entry_data = " " del_attr(entry_data, %Q, %Q) " " WHERE eid = %lld;", - el->name, el->data, eid); + el->name, el->values[j].data, eid); break; } } @@ -398,32 +448,12 @@ lsqlite3_msg_to_sql(struct ldb_module *module, } -static char * -lsqlite3_normalize_dn(struct ldb_context * ldb, - char * pDN) -{ - char * pSrc; - char * pDest; - char * pNormalized; - - pNormalized = talloc_size(ldb, strlen(pDN) + 1); - if (pNormalized == NULL) { - errno = ENOMEM; - return -1; - } - - for (pSrc = pDN, pDest = pNormalized; *pSrc != '\0'; ) { - - } -} - - static int -lsqlite3_insert_dn_recursive(struct lsqlite3_private * lsqlite3, - char * pDN, - long long * pEID) +lsqlite3_insert_dn(struct lsqlite3_private * lsqlite3, + char * pDN, + long long * pEID) { - + } @@ -434,9 +464,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) { - int ret; long long eid; - struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -445,27 +473,29 @@ lsqlite3_add(struct ldb_module *module, } /* Begin a transaction */ - QUERY(lsqlite3, NULL, NULL< FALSE, "BEGIN EXCLUSIVE;"); + QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;"); /* * Build any portions of the directory tree that don't exist. If the * final component already exists, it's an error. */ - if (lsqlite3_insert_dn_recursive(lsqlite3, - lsqlite3_normalize_dn(ldb, msg->dn), + if (lsqlite3_insert_dn(lsqlite3, + ldb_dn_fold(module, + msg->dn, + lsqlite3_case_fold_attr_required), &eid) != 0) { - QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); + QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); return -1; } /* Add attributes to this new entry */ - if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { - QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); + if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) { + QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); return -1; } /* Everything worked. Commit it! */ - QUERY(lsqlite3, NULL, NULL, TRUE, "COMMIT;"); + QUERY(lsqlite3, NULL, NULL, True, "COMMIT;"); return 0; } @@ -477,10 +507,9 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { - int ret = 0; int numRows; + long long eid; char ** ppValues; - struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -489,22 +518,24 @@ lsqlite3_modify(struct ldb_module *module, } /* Begin a transaction */ - QUERY(lsqlite3, NULL, NULL, FALSE, "BEGIN EXCLUSIVE;"); + QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;"); /* Get the id of this DN. */ QUERY(lsqlite3, &ppValues, &numRows, - TRUE, + True, "SELECT eid " " FROM ldb_entry " " WHERE dn = %Q;", - lsqlite3_normalize_dn(ldb, msg->dn)); + ldb_dn_fold(module, + msg->dn, + lsqlite3_case_fold_attr_required)); /* Did it exist? */ if (numRows != 1) { /* Nope. See ya! */ - sqlite_free_table(ppValues); + sqlite3_free_table(ppValues); return -1; } @@ -512,13 +543,13 @@ lsqlite3_modify(struct ldb_module *module, eid = strtoll(ppValues[1], NULL, 10); /* Modify attributes as specified */ - if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { - QUERY(lsqlite3, NULL, NULL, FALSE, "ROLLBACK;"); + if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) { + QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); return -1; } /* Everything worked. Commit it! */ - QUERY(lsqlite3, NULL, NULL, TRUE, "COMMIT;"); + QUERY(lsqlite3, NULL, NULL, True, "COMMIT;"); return 0 ; } @@ -526,10 +557,6 @@ static int lsqlite3_lock(struct ldb_module *module, const char *lockname) { - int ret = 0; - struct ldb_context * ldb = module->ldb; - struct lsqlite3_private * lsqlite3 = module->private_data; - if (lockname == NULL) { return -1; } @@ -543,10 +570,6 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) { - int ret = 0; - struct ldb_context * ldb = module->ldb; - struct lsqlite3_private * lsqlite3 = module->private_data; - if (lockname == NULL) { return -1; } @@ -564,14 +587,13 @@ lsqlite3_errstring(struct ldb_module *module) { struct lsqlite3_private * lsqlite3 = module->private_data; - return sqlite3_errmsg(lsqlite3->sqlite3); + return sqlite3_errmsg(lsqlite3->sqlite); } static const struct ldb_module_ops lsqlite3_ops = { "sqlite", lsqlite3_search, - lsqlite3_search_free, lsqlite3_add, lsqlite3_modify, lsqlite3_delete, @@ -587,162 +609,162 @@ lsqlite3_destructor(void *p) { struct lsqlite3_private * lsqlite3 = p; - (void) sqlite3_close(lsqlite3->sqlite3); + (void) sqlite3_close(lsqlite3->sqlite); return 0; } static int -lsqlite3_initialize(lsqlite3_private *lsqlite3, +lsqlite3_initialize(struct lsqlite3_private *lsqlite3, const char *url) { int ret; int bNewDatabase = False; char * p; - char * pTail; + const char * pTail; struct stat statbuf; sqlite3_stmt * stmt; const char * schema = - " - -- ------------------------------------------------------ - - PRAGMA auto_vacuum=1; - - -- ------------------------------------------------------ - - BEGIN EXCLUSIVE; - - -- ------------------------------------------------------ - - CREATE TABLE ldb_info AS - SELECT 'LDB' AS database_type, - '1.0' AS version; - - -- ------------------------------------------------------ - -- Schema - - /* - * The entry table holds the information about an entry. This - * table is used to obtain the EID of the entry and to support - * scope=one and scope=base. The parent and child table - * is included in the entry table since all the other - * attributes on EID. - */ - CREATE TABLE ldb_entry - ( - -- Unique identifier of this LDB entry - eid INTEGER PRIMARY KEY, - - -- Unique identifier of the parent LDB entry - peid INTEGER REFERENCES ldb_entry, - - -- Distinguished name of this entry - dn TEXT, - - -- Time when the entry was created - create_timestamp INTEGER, - - -- Time when the entry was last modified - modify_timestamp INTEGER, - - -- Attributes of this entry, in the form - -- attr\1value\0[attr\1value\0]*\0 - entry_data TEXT - ); - - - /* - * The purpose of the descendant table is to support the - * subtree search feature. For each LDB entry with a unique - * ID (AEID), this table contains the unique identifiers - * (DEID) of the descendant entries. - * - * For evern entry in the directory, a row exists in this - * table for each of its ancestors including itself. The size - * of the table depends on the depth of each entry. In the - * worst case, if all the entries were at the same depth, the - * number of rows in the table is O(nm) where n is the number - * of nodes in the directory and m is the depth of the tree. - */ - CREATE TABLE ldb_descendants - ( - -- The unique identifier of the ancestor LDB entry - aeid INTEGER REFERENCES ldb_entry, - - -- The unique identifier of the descendant LDB entry - deid INTEGER REFERENCES ldb_entry - ); - - - CREATE TABLE ldb_object_classes - ( - -- Object classes are inserted into this table to track - -- their class hierarchy. 'top' is the top-level class - -- of which all other classes are subclasses. - class_name TEXT PRIMARY KEY, - - -- tree_key tracks the position of the class in - -- the hierarchy - tree_key TEXT UNIQUE - ); - - /* - * There is one attribute table per searchable attribute. - */ -/* - CREATE TABLE ldb_attr_ATTRIBUTE_NAME - ( - -- The unique identifier of the LDB entry - eid INTEGER REFERENCES ldb_entry, - - -- Normalized attribute value - attr_value TEXT - ); -*/ - - - -- ------------------------------------------------------ - -- Indexes - - - -- ------------------------------------------------------ - -- Triggers - - CREATE TRIGGER ldb_entry_insert_tr - AFTER INSERT - ON ldb_entry - FOR EACH ROW - BEGIN - UPDATE ldb_entry - SET create_timestamp = strftime('%s', 'now'), - modify_timestamp = strftime('%s', 'now') - WHERE eid = new.eid; - END; - - CREATE TRIGGER ldb_entry_update_tr - AFTER UPDATE - ON ldb_entry - FOR EACH ROW - BEGIN - UPDATE ldb_entry - SET modify_timestamp = strftime('%s', 'now') - WHERE eid = old.eid; - END; - - -- ------------------------------------------------------ - -- Table initialization - - /* We need an implicit "top" level object class */ - INSERT INTO ldb_attributes (attr_name, - parent_tree_key) - SELECT 'top', ''; - - -- ------------------------------------------------------ - - COMMIT; - - -- ------------------------------------------------------ - "; - + "-- ------------------------------------------------------" + + "PRAGMA auto_vacuum=1;" + + "-- ------------------------------------------------------" + + "BEGIN EXCLUSIVE;" + + "-- ------------------------------------------------------" + + "CREATE TABLE ldb_info AS" + " SELECT 'LDB' AS database_type," + " '1.0' AS version;" + + "-- ------------------------------------------------------" + "-- Schema" + + "/*" + " * The entry table holds the information about an entry. " + " * This table is used to obtain the EID of the entry and to " + " * support scope=one and scope=base. The parent and child" + " * table is included in the entry table since all the other" + " * attributes are dependent on EID." + " */" + "CREATE TABLE ldb_entry" + "(" + " -- Unique identifier of this LDB entry" + " eid INTEGER PRIMARY KEY," + + " -- Unique identifier of the parent LDB entry" + " peid INTEGER REFERENCES ldb_entry," + + " -- Distinguished name of this entry" + " dn TEXT," + + " -- Time when the entry was created" + " create_timestamp INTEGER," + + " -- Time when the entry was last modified" + " modify_timestamp INTEGER," + + " -- Attributes of this entry, in the form" + " -- attr\1value\0[attr\1value\0]*\0" + " entry_data TEXT" + ");" + + + "/*" + " * The purpose of the descendant table is to support the" + " * subtree search feature. For each LDB entry with a unique" + " * ID (AEID), this table contains the unique identifiers" + " * (DEID) of the descendant entries." + " *" + " * For evern entry in the directory, a row exists in this" + " * table for each of its ancestors including itself. The " + " * size of the table depends on the depth of each entry. In " + " * the worst case, if all the entries were at the same " + " * depth, the number of rows in the table is O(nm) where " + " * n is the number of nodes in the directory and m is the " + " * depth of the tree. " + " */" + "CREATE TABLE ldb_descendants" + "(" + " -- The unique identifier of the ancestor LDB entry" + " aeid INTEGER REFERENCES ldb_entry," + + " -- The unique identifier of the descendant LDB entry" + " deid INTEGER REFERENCES ldb_entry" + ");" + + + "CREATE TABLE ldb_object_classes" + "(" + " -- Object classes are inserted into this table to track" + " -- their class hierarchy. 'top' is the top-level class" + " -- of which all other classes are subclasses." + " class_name TEXT PRIMARY KEY," + + " -- tree_key tracks the position of the class in" + " -- the hierarchy" + " tree_key TEXT UNIQUE" + ");" + + "/*" + " * There is one attribute table per searchable attribute." + " */" + "/*" + "CREATE TABLE ldb_attr_ATTRIBUTE_NAME" + "(" + " -- The unique identifier of the LDB entry" + " eid INTEGER REFERENCES ldb_entry," + + " -- Normalized attribute value" + " attr_value TEXT" + ");" + "*/" + + + "-- ------------------------------------------------------" + "-- Indexes" + + + "-- ------------------------------------------------------" + "-- Triggers" + + "CREATE TRIGGER ldb_entry_insert_tr" + " AFTER INSERT" + " ON ldb_entry" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_entry" + " SET create_timestamp = strftime('%s', 'now')," + " modify_timestamp = strftime('%s', 'now')" + " WHERE eid = new.eid;" + " END;" + + "CREATE TRIGGER ldb_entry_update_tr" + " AFTER UPDATE" + " ON ldb_entry" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_entry" + " SET modify_timestamp = strftime('%s', 'now')" + " WHERE eid = old.eid;" + " END;" + + "-- ------------------------------------------------------" + "-- Table initialization" + + "/* We need an implicit 'top' level object class */" + "INSERT INTO ldb_attributes (attr_name," + " parent_tree_key)" + " SELECT 'top', '';" + + "-- ------------------------------------------------------" + + "COMMIT;" + + "-- ------------------------------------------------------" + ; + /* Skip protocol indicator of url */ if ((p = strchr(url, ':')) == NULL) { return SQLITE_MISUSE; @@ -760,7 +782,7 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, } /* Try to open the (possibly empty/non-existent) database */ - if ((ret = sqlite3_open(p, &lsqlite3->sqlite3)) != SQLITE_SUCCESS) { + if ((ret = sqlite3_open(p, &lsqlite3->sqlite)) != SQLITE_OK) { return ret; } @@ -768,18 +790,18 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, /* * Create the database schema */ - for (pTail = schema; pTail != NULL; ) { + for (pTail = discard_const_p(char, schema); pTail != NULL; ) { - if ((lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, + if ((ret = sqlite3_prepare( + lsqlite3->sqlite, pTail, -1, &stmt, - &pTail)) != SQLITE_SUCCESS || - (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_DONE || - (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS) { + &pTail)) != SQLITE_OK || + (ret = sqlite3_step(stmt)) != SQLITE_DONE || + (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - (void) sqlite3_close(lsqlite3->sqlite3); + (void) sqlite3_close(lsqlite3->sqlite); return ret; } } @@ -787,8 +809,8 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, /* * Ensure that the database we opened is one of ours */ - if ((lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, + if ((ret = sqlite3_prepare( + lsqlite3->sqlite, "SELECT COUNT(*) " " FROM sqlite_master " " WHERE type = 'table' " @@ -800,30 +822,30 @@ lsqlite3_initialize(lsqlite3_private *lsqlite3, " );", -1, &stmt, - &pTail)) != SQLITE_SUCCESS || - (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_ROW || + &pTail)) != SQLITE_OK || + (ret = sqlite3_step(stmt)) != SQLITE_ROW || sqlite3_column_int(stmt, 0) != 3 || - (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS || + (ret = sqlite3_finalize(stmt)) != SQLITE_OK || - (lsqlite3->last_rc = sqlite3_prepare( - lsqlite3->sqlite3, + (ret = sqlite3_prepare( + lsqlite3->sqlite, "SELECT 1 " " FROM ldb_info " " WHERE database_type = 'LDB' " " AND version = '1.0';", -1, &stmt, - &pTail)) != SQLITE_SUCCESS || - (lsqlite3->last_rc = sqlite3_step(stmt)) != SQLITE_ROW || - (lsqlite3->last_rc = sqlite_finalize(stmt)) != SQLITE_SUCCESS) { + &pTail)) != SQLITE_OK || + (ret = sqlite3_step(stmt)) != SQLITE_ROW || + (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { /* It's not one that we created. See ya! */ - (void) sqlite3_close(lsqlite3->sqlite3); + (void) sqlite3_close(lsqlite3->sqlite); return SQLITE_MISUSE; } } - return SQLITE_SUCCESS; + return SQLITE_OK; } /* @@ -835,6 +857,7 @@ lsqlite3_connect(const char *url, const char *options[]) { int i; + int ret; struct ldb_context * ldb = NULL; struct lsqlite3_private * lsqlite3 = NULL; @@ -850,12 +873,12 @@ lsqlite3_connect(const char *url, goto failed; } - lsqlite3->sqlite3 = NULL; + lsqlite3->sqlite = NULL; lsqlite3->options = NULL; lsqlite3->lock_count = 0; - lsqlite3->last_rc = lsqlite3_initialize(&lsqlite3->sqlite3, url); - if (lsqlite3->last_rc != SQLITE_SUCCESS) { + ret = lsqlite3_initialize(&lsqlite3, url); + if (ret != SQLITE_OK) { goto failed; } @@ -897,8 +920,8 @@ lsqlite3_connect(const char *url, return ldb; failed: - if (lsqlite3->sqlite3 != NULL) { - (void) sqlite3_close(lsqlite3->sqlite3); + if (lsqlite3->sqlite != NULL) { + (void) sqlite3_close(lsqlite3->sqlite); } talloc_free(ldb); return NULL; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index 78550985d4..dddca8d48f 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -20,7 +20,7 @@ * table is used to obtain the EID of the entry and to support * scope="one" and scope="base". The parent and child table * is included in the entry table since all the other - * attributes on EID. + * attributes are dependent on EID. */ CREATE TABLE ldb_entry ( @@ -126,7 +126,7 @@ -- ------------------------------------------------------ -- Table initialization - /* We need an implicit "top" level object class */ + /* We need an implicit 'top' level object class */ INSERT INTO ldb_attributes (attr_name, parent_tree_key) SELECT 'top', ''; -- cgit From f725863f75fda1beed47eaef5cb2c4b5289e4dd1 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 21:20:56 +0000 Subject: r7283: add sqlite3.m4 (This used to be commit 10a828a442b516551762bff81782072d9807d626) --- source4/lib/ldb/sqlite3.m4 | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 source4/lib/ldb/sqlite3.m4 (limited to 'source4/lib') diff --git a/source4/lib/ldb/sqlite3.m4 b/source4/lib/ldb/sqlite3.m4 new file mode 100644 index 0000000000..8bbe186160 --- /dev/null +++ b/source4/lib/ldb/sqlite3.m4 @@ -0,0 +1,49 @@ +######################################################## +# Compile with SQLITE3 support? + +SQLITE3_LIBS="" +with_sqlite3_support=auto +AC_MSG_CHECKING([for SQLITE3 support]) + +AC_ARG_WITH(sqlite3, +[ --with-sqlite3 SQLITE3 support (default yes)], +[ case "$withval" in + yes|no) + with_sqlite3_support=$withval + ;; + esac ]) + +AC_MSG_RESULT($with_sqlite3_support) + +if test x"$with_sqlite3_support" != x"no"; then + + ################################################################## + # first test for sqlite3.h + AC_CHECK_HEADERS(sqlite3.h) + + if test x"$ac_cv_header_sqlite3_h" != x"yes"; then + if test x"$with_sqlite3_support" = x"yes"; then + AC_MSG_ERROR(sqlite3.h is needed for SQLITE3 support) + else + AC_MSG_WARN(sqlite3.h is needed for SQLITE3 support) + fi + + with_sqlite3_support=no + fi +fi + +if test x"$with_sqlite3_support" != x"no"; then + ac_save_LIBS=$LIBS + + ######################################################## + # now see if we can find the sqlite3 libs in standard paths + AC_CHECK_LIB_EXT(sqlite3, SQLITE3_LIBS, sqlite3_open) + + LIBS="$LIBS $SQLITE3_LIBS" + + AC_DEFINE(HAVE_SQLITE3,1,[Whether sqlite3 is available]) + AC_MSG_CHECKING(whether SQLITE3 support is used) + AC_MSG_RESULT(yes) +fi + +SMB_EXT_LIB(SQLITE3,[${SQLITE3_LIBS}],[${SQLITE3_CFLAGS}],[${SQLITE3_CPPFLAGS}],[${SQLITE3_LDFLAGS}]) -- cgit From 1b454c430f0ce2e86350052b5a4e23f899e9eee9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 22:30:38 +0000 Subject: r7286: add prototype for public connect function in ldb_sqlite3 (This used to be commit 10d438af06b3ab442c7a98b704d2e0bfe49b739d) --- source4/lib/ldb/include/ldb_private.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 4f86655a76..69bf4a6dc6 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -109,6 +109,9 @@ struct ldb_context *ltdb_connect(const char *url, struct ldb_context *lldb_connect(const char *url, unsigned int flags, const char *options[]); +struct ldb_context *lsqlite3_connect(const char *url, + unsigned int flags, + const char *options[]); struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); -- cgit From 06cc74a66cef3944573e4390af0ee101517835df Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 4 Jun 2005 23:19:41 +0000 Subject: r7287: work in progress. no more time to work on this right now. save latest changes. (This used to be commit 94cbef9211597d8cdd6b5ab7bc9b655026be283a) --- source4/lib/ldb/ldb_sqlite3/README | 3 ++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 58 +++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/README b/source4/lib/ldb/ldb_sqlite3/README index a0b3dcb16d..6cda0a7759 100644 --- a/source4/lib/ldb/ldb_sqlite3/README +++ b/source4/lib/ldb/ldb_sqlite3/README @@ -2,3 +2,6 @@ trees.ps contains an explanation of the Genealogical Representation of Trees in Databases which is being used in ldb_sqlite3. Note that we use fgID representation with 4 bytes per level, so we can represent 6.5E+08 subclasses of any object class. This should be adequate for our purposes. :-) + +The following document is the primary basis for the schema currently being +used here: http://www.research.ibm.com/journal/sj/392/shi.html diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 6dfaa0627b..3fddbe85d4 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -2,6 +2,7 @@ ldb database library Copyright (C) Andrew Tridgell 2004 + Copyright (C) Derrell Lipman 2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -32,6 +33,7 @@ * Author: Derrell Lipman (based on Andrew Tridgell's LDAP backend) */ +#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" @@ -67,19 +69,62 @@ lsqlite3_query(const struct lsqlite3_private *lsqlite3, const char *pSql, ...) { +// int i; +// int retval; + int numRows; +// int numColumns; + int bFreeTable = False; +// char errorBuf[4096]; + char * p; +// char * pError = NULL; + char ** ppValues; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); + + /* + * If they didn't give us a place to put returned values, use our own + */ + if (pppValues == NULL) + { + pppValues = &ppValues; + bFreeTable = True; + } + /* Similarly for number of rows in result set */ + if (pNumRows == NULL) + { + pNumRows = &numRows; + } + + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + return -1; + } + + +#warning "*** FINISH QUERY FUNCTION. Catch timeouts, schema changed, etc. ***" + + + /* All done with variable argument list */ + va_end(args); + + /* Success! */ + return 0; } static int lsqlite3_create_attr_table(struct ldb_module *module, char * pAttr) { - +#warning "*** lsqlite3_create_attr_table() not yet written ***" + return -1; } #if 0 -p/* +/* * we don't need this right now, but will once we add some backend options * * find an option in an option list (a null terminated list of strings) @@ -151,7 +196,7 @@ lsqlite3_delete(struct ldb_module *module, return -1; } -#if 0 /* not currently used * / +#if 0 /* not currently used */ /* * free a search result */ @@ -342,7 +387,7 @@ failed: if (*res) lsqlite3_search_free(module, *res); return -1; #else - return 0; + return -1; #endif } @@ -453,7 +498,8 @@ lsqlite3_insert_dn(struct lsqlite3_private * lsqlite3, char * pDN, long long * pEID) { - +#warning "*** lsqlite3_insert_dn() not yet implemented ***" + return -1; } @@ -877,7 +923,7 @@ lsqlite3_connect(const char *url, lsqlite3->options = NULL; lsqlite3->lock_count = 0; - ret = lsqlite3_initialize(&lsqlite3, url); + ret = lsqlite3_initialize(lsqlite3, url); if (ret != SQLITE_OK) { goto failed; } -- cgit From c88d65a862cefe832f3b5f38844829372a926e33 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 5 Jun 2005 04:18:57 +0000 Subject: r7292: Fix up the build system support for derrell's sqlite3 ldb backend. It is on by default, so I've also fixed a build issue in it. I'll show how to make it off be default in the next commit. Andrew Bartlett (This used to be commit 5a1ef888100e8ef803100a6341133d96e8a400b0) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 1 + source4/lib/ldb/sqlite3.m4 | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 3fddbe85d4..b82c0ac6a9 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -35,6 +35,7 @@ #include #include "includes.h" +#include "system/filesys.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" diff --git a/source4/lib/ldb/sqlite3.m4 b/source4/lib/ldb/sqlite3.m4 index 8bbe186160..fe0f398624 100644 --- a/source4/lib/ldb/sqlite3.m4 +++ b/source4/lib/ldb/sqlite3.m4 @@ -39,11 +39,24 @@ if test x"$with_sqlite3_support" != x"no"; then # now see if we can find the sqlite3 libs in standard paths AC_CHECK_LIB_EXT(sqlite3, SQLITE3_LIBS, sqlite3_open) - LIBS="$LIBS $SQLITE3_LIBS" - - AC_DEFINE(HAVE_SQLITE3,1,[Whether sqlite3 is available]) - AC_MSG_CHECKING(whether SQLITE3 support is used) - AC_MSG_RESULT(yes) + if test x"$ac_cv_lib_ext_sqlite3_sqlite3_open" = x"yes"; then + AC_DEFINE(HAVE_SQLITE3,1,[Whether sqlite3 is available]) + AC_MSG_CHECKING(whether SQLITE3 support is used) + AC_MSG_RESULT(yes) + with_sqlite3_support=yes + SMB_EXT_LIB_ENABLE(SQLITE3,YES) + else + if test x"$with_sqlite3_support" = x"yes"; then + AC_MSG_ERROR(libsqlite3 is needed for SQLITE3 support) + else + AC_MSG_WARN(libsqlite3 is needed for SQLITE3 support) + fi + + SQLITE3_LIBS="" + with_sqlite3_support=no + fi + + LIBS=$ac_save_LIBS; fi SMB_EXT_LIB(SQLITE3,[${SQLITE3_LIBS}],[${SQLITE3_CFLAGS}],[${SQLITE3_CPPFLAGS}],[${SQLITE3_LDFLAGS}]) -- cgit From 03840652354598db203a3596077ecc55726880c8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 5 Jun 2005 04:27:12 +0000 Subject: r7293: Turn sqlite3 support off by default, use --with-sqlite3 to re-enable. Andrew Bartlett (This used to be commit 422579215462c31dd863ab1b7f187003dafd0af2) --- source4/lib/ldb/sqlite3.m4 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/sqlite3.m4 b/source4/lib/ldb/sqlite3.m4 index fe0f398624..ab7c61f243 100644 --- a/source4/lib/ldb/sqlite3.m4 +++ b/source4/lib/ldb/sqlite3.m4 @@ -6,7 +6,7 @@ with_sqlite3_support=auto AC_MSG_CHECKING([for SQLITE3 support]) AC_ARG_WITH(sqlite3, -[ --with-sqlite3 SQLITE3 support (default yes)], +[ --with-sqlite3 SQLITE3 support (default no)], [ case "$withval" in yes|no) with_sqlite3_support=$withval @@ -15,8 +15,9 @@ AC_ARG_WITH(sqlite3, AC_MSG_RESULT($with_sqlite3_support) -if test x"$with_sqlite3_support" != x"no"; then - +if test x"$with_sqlite3_support" != x"yes"; then + with_sqlite3_support=no +else ################################################################## # first test for sqlite3.h AC_CHECK_HEADERS(sqlite3.h) -- cgit From bf1ffa283caef6a3c98b5cc7f5bc8205c2818b06 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 Jun 2005 06:53:07 +0000 Subject: r7294: implemented the irpc messaging system. This is the core of the management system I proposed on samba-technical a couple of days ago. Essentially it is a very lightweight way for any code in Samba to make IDL based rpc calls to anywhere else in the code, without the client or server having to go to the trouble of setting up a full rpc service. It can be used with any of our existing IDL, but I expect it will mostly be used for a new set of Samba specific management calls. The LOCAL-IRPC torture test demonstrates how it can be used by calling the echo_AddOne() call over this transport. (This used to be commit 3d589a09954eb8b318f567e1150b0c27412fb942) --- source4/lib/messaging/config.mk | 3 + source4/lib/messaging/irpc.h | 94 +++++++++++++ source4/lib/messaging/messaging.c | 283 +++++++++++++++++++++++++++++++++++++- 3 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 source4/lib/messaging/irpc.h (limited to 'source4/lib') diff --git a/source4/lib/messaging/config.mk b/source4/lib/messaging/config.mk index 6c30894779..ef0ea7e6f4 100644 --- a/source4/lib/messaging/config.mk +++ b/source4/lib/messaging/config.mk @@ -4,5 +4,8 @@ [SUBSYSTEM::MESSAGING] INIT_OBJ_FILES = \ lib/messaging/messaging.o +NOPROTO = YES +REQUIRED_SUBSYSTEMS = \ + NDR_IRPC # End SUBSYSTEM MESSAGING ################################################ diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h new file mode 100644 index 0000000000..a483c78c70 --- /dev/null +++ b/source4/lib/messaging/irpc.h @@ -0,0 +1,94 @@ +/* + Unix SMB/CIFS implementation. + + Samba internal rpc code - header + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + an incoming irpc message +*/ +struct irpc_message { + uint32_t from; +}; + +/* don't allow calls to take too long */ +#define IRPC_CALL_TIMEOUT 10 + + +/* the server function type */ +typedef NTSTATUS (*irpc_function_t)(struct irpc_message *, void *r); + +/* register a server function with the irpc messaging system */ +#define IRPC_REGISTER(msg_ctx, pipename, funcname, function) \ + irpc_register(msg_ctx, &dcerpc_table_ ## pipename, \ + DCERPC_ ## funcname, \ + (irpc_function_t)function) + +/* make a irpc call */ +#define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr) \ + irpc_call(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr) + + +/* + a pending irpc call +*/ +struct irpc_request { + struct messaging_context *msg_ctx; + const struct dcerpc_interface_table *table; + int callnum; + int callid; + void *r; + NTSTATUS status; + BOOL done; + struct { + void (*fn)(struct irpc_request *); + void *private; + } async; +}; + + +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id, + struct event_context *ev); +NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, + uint32_t msg_type, DATA_BLOB *data); +void messaging_register(struct messaging_context *msg, void *private, + uint32_t msg_type, + void (*fn)(struct messaging_context *, void *, uint32_t, uint32_t, DATA_BLOB *)); +struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id, + struct event_context *ev); +NTSTATUS messaging_send_ptr(struct messaging_context *msg, uint32_t server, + uint32_t msg_type, void *ptr); +void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private); + + + + +NTSTATUS irpc_register(struct messaging_context *msg_ctx, + const struct dcerpc_interface_table *table, + int call, irpc_function_t fn); +struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, + uint32_t server_id, + const struct dcerpc_interface_table *table, + int callnum, void *r); +NTSTATUS irpc_call_recv(struct irpc_request *irpc); +NTSTATUS irpc_call(struct messaging_context *msg_ctx, + uint32_t server_id, + const struct dcerpc_interface_table *table, + int callnum, void *r); + diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 936e3b9515..b605fa0494 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -27,6 +27,8 @@ #include "messages.h" #include "dlinklist.h" #include "lib/socket/socket.h" +#include "librpc/gen_ndr/ndr_irpc.h" +#include "lib/messaging/irpc.h" /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 @@ -37,6 +39,8 @@ struct messaging_context { const char *path; struct dispatch_fn *dispatch; struct messaging_rec *pending; + struct irpc_list *irpc; + struct idr_context *idr; struct { struct event_context *ev; @@ -72,6 +76,10 @@ struct messaging_rec { }; +static void irpc_handler(struct messaging_context *, void *, + uint32_t, uint32_t, DATA_BLOB *); + + /* A useful function for testing the message system. */ @@ -363,8 +371,10 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id msg->path = messaging_path(msg, server_id); msg->server_id = server_id; - msg->dispatch = NULL; - msg->pending = NULL; + msg->dispatch = NULL; + msg->pending = NULL; + msg->idr = idr_init(msg); + msg->irpc = NULL; status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0); if (!NT_STATUS_IS_OK(status)) { @@ -393,6 +403,275 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id talloc_set_destructor(msg, messaging_destructor); messaging_register(msg, NULL, MSG_PING, ping_message); + messaging_register(msg, NULL, MSG_IRPC, irpc_handler); return msg; } + + +/* + a list of registered irpc server functions +*/ +struct irpc_list { + struct irpc_list *next, *prev; + struct GUID uuid; + const struct dcerpc_interface_table *table; + int callnum; + irpc_function_t fn; +}; + + +/* + register a irpc server function +*/ +NTSTATUS irpc_register(struct messaging_context *msg_ctx, + const struct dcerpc_interface_table *table, + int call, irpc_function_t fn) +{ + struct irpc_list *irpc; + + irpc = talloc(msg_ctx, struct irpc_list); + NT_STATUS_HAVE_NO_MEMORY(irpc); + + irpc->table = table; + irpc->callnum = call; + irpc->fn = fn; + GUID_from_string(irpc->table->uuid, &irpc->uuid); + + DLIST_ADD(msg_ctx->irpc, irpc); + + return NT_STATUS_OK; +} + + +/* + handle an incoming irpc reply message +*/ +static void irpc_handler_reply(struct messaging_context *msg_ctx, + struct ndr_pull *ndr, struct irpc_header *header) +{ + struct irpc_request *irpc; + + irpc = idr_find(msg_ctx->idr, header->callid); + if (irpc == NULL) return; + + /* parse the reply data */ + irpc->status = irpc->table->calls[irpc->callnum].ndr_pull(ndr, NDR_OUT, irpc->r); + if (NT_STATUS_IS_OK(irpc->status)) { + irpc->status = header->status; + } + irpc->done = True; + if (irpc->async.fn) { + irpc->async.fn(irpc); + } +} + + +/* + handle an incoming irpc request message +*/ +static void irpc_handler_request(struct messaging_context *msg_ctx, + struct ndr_pull *ndr, struct irpc_header *header, + uint32_t src) +{ + struct irpc_list *i; + void *r; + NTSTATUS status; + struct irpc_message m; + struct ndr_push *push; + DATA_BLOB packet; + + for (i=msg_ctx->irpc; i; i=i->next) { + if (GUID_equal(&i->uuid, &header->uuid) && + i->table->if_version == header->if_version && + i->callnum == header->callnum) { + break; + } + } + + if (i == NULL) { + /* no registered handler for this message */ + return; + } + + /* allocate space for the structure */ + r = talloc_zero_size(ndr, i->table->calls[header->callnum].struct_size); + if (r == NULL) goto failed; + + /* parse the request data */ + status = i->table->calls[i->callnum].ndr_pull(ndr, NDR_IN, r); + if (!NT_STATUS_IS_OK(status)) goto failed; + + /* make the call */ + m.from = src; + header->status = i->fn(&m, r); + + /* setup the reply */ + push = ndr_push_init_ctx(ndr); + if (push == NULL) goto failed; + + header->flags |= IRPC_FLAG_REPLY; + + /* construct the packet */ + status = ndr_push_irpc_header(push, NDR_SCALARS|NDR_BUFFERS, header); + if (!NT_STATUS_IS_OK(status)) goto failed; + + status = i->table->calls[i->callnum].ndr_push(push, NDR_OUT, r); + if (!NT_STATUS_IS_OK(status)) goto failed; + + /* send the reply message */ + packet = ndr_push_blob(push); + status = messaging_send(msg_ctx, src, MSG_IRPC, &packet); + if (!NT_STATUS_IS_OK(status)) goto failed; + +failed: + /* nothing to clean up */ + return; +} + +/* + handle an incoming irpc message +*/ +static void irpc_handler(struct messaging_context *msg_ctx, void *private, + uint32_t msg_type, uint32_t src, DATA_BLOB *packet) +{ + struct irpc_header header; + struct ndr_pull *ndr; + NTSTATUS status; + + ndr = ndr_pull_init_blob(packet, msg_ctx); + if (ndr == NULL) goto failed; + + status = ndr_pull_irpc_header(ndr, NDR_BUFFERS|NDR_SCALARS, &header); + if (!NT_STATUS_IS_OK(status)) goto failed; + + if (header.flags & IRPC_FLAG_REPLY) { + irpc_handler_reply(msg_ctx, ndr, &header); + } else { + irpc_handler_request(msg_ctx, ndr, &header, src); + } + +failed: + talloc_free(ndr); +} + + +/* + destroy a irpc request +*/ +static int irpc_destructor(void *ptr) +{ + struct irpc_request *irpc = talloc_get_type(ptr, struct irpc_request); + idr_remove(irpc->msg_ctx->idr, irpc->callid); + return 0; +} + +/* + timeout a irpc request +*/ +static void irpc_timeout(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private) +{ + struct irpc_request *irpc = talloc_get_type(private, struct irpc_request); + irpc->status = NT_STATUS_IO_TIMEOUT; + irpc->done = True; + if (irpc->async.fn) { + irpc->async.fn(irpc); + } +} + + +/* + make a irpc call - async send +*/ +struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, + uint32_t server_id, + const struct dcerpc_interface_table *table, + int callnum, void *r) +{ + struct irpc_header header; + struct ndr_push *ndr; + NTSTATUS status; + DATA_BLOB packet; + struct irpc_request *irpc; + + irpc = talloc(msg_ctx, struct irpc_request); + if (irpc == NULL) goto failed; + + irpc->msg_ctx = msg_ctx; + irpc->table = table; + irpc->callnum = callnum; + irpc->callid = idr_get_new(msg_ctx->idr, irpc, UINT16_MAX); + if (irpc->callid == -1) goto failed; + irpc->r = r; + irpc->done = False; + irpc->async.fn = NULL; + + talloc_set_destructor(irpc, irpc_destructor); + + /* setup the header */ + status = GUID_from_string(table->uuid, &header.uuid); + if (!NT_STATUS_IS_OK(status)) goto failed; + + header.if_version = table->if_version; + header.callid = irpc->callid; + header.callnum = callnum; + header.flags = 0; + header.status = NT_STATUS_OK; + + /* construct the irpc packet */ + ndr = ndr_push_init_ctx(irpc); + if (ndr == NULL) goto failed; + + status = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header); + if (!NT_STATUS_IS_OK(status)) goto failed; + + status = table->calls[callnum].ndr_push(ndr, NDR_IN, r); + if (!NT_STATUS_IS_OK(status)) goto failed; + + /* and send it */ + packet = ndr_push_blob(ndr); + status = messaging_send(msg_ctx, server_id, MSG_IRPC, &packet); + if (!NT_STATUS_IS_OK(status)) goto failed; + + event_add_timed(msg_ctx->event.ev, irpc, + timeval_current_ofs(IRPC_CALL_TIMEOUT, 0), + irpc_timeout, irpc); + + talloc_free(ndr); + return irpc; + +failed: + talloc_free(irpc); + return NULL; +} + +/* + wait for a irpc reply +*/ +NTSTATUS irpc_call_recv(struct irpc_request *irpc) +{ + NTSTATUS status; + NT_STATUS_HAVE_NO_MEMORY(irpc); + while (!irpc->done) { + if (event_loop_once(irpc->msg_ctx->event.ev) != 0) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } + } + status = irpc->status; + talloc_free(irpc); + return status; +} + +/* + perform a synchronous irpc request +*/ +NTSTATUS irpc_call(struct messaging_context *msg_ctx, + uint32_t server_id, + const struct dcerpc_interface_table *table, + int callnum, void *r) +{ + struct irpc_request *irpc = irpc_call_send(msg_ctx, server_id, + table, callnum, r); + return irpc_call_recv(irpc); +} -- cgit From d934cb71d0bd2d6ad7a2908cc3c3802cb37e922c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 Jun 2005 07:30:44 +0000 Subject: r7295: added an irpc benchmark. It gets about 16k messages/sec on my laptop, compared to about 20k messages/sec for the raw messaging layer. I think that is quite acceptable given the extra functionality. (This used to be commit a05d38d1d91f1f54d3e3794a596b468992594852) --- source4/lib/messaging/irpc.h | 5 ++++- source4/lib/messaging/messaging.c | 21 ++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index a483c78c70..93cadddd34 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -28,7 +28,7 @@ struct irpc_message { }; /* don't allow calls to take too long */ -#define IRPC_CALL_TIMEOUT 10 +#define IRPC_CALL_TIMEOUT 20 /* the server function type */ @@ -44,6 +44,9 @@ typedef NTSTATUS (*irpc_function_t)(struct irpc_message *, void *r); #define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr) \ irpc_call(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr) +#define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr) \ + irpc_call_send(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr) + /* a pending irpc call diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index b605fa0494..be89c97e5b 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -315,7 +315,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, if (msg->pending == NULL) { EVENT_FD_WRITEABLE(msg->event.fde); } - DLIST_ADD(msg->pending, rec); + DLIST_ADD_END(msg->pending, rec, struct messaging_rec *); return NT_STATUS_OK; } @@ -426,20 +426,27 @@ struct irpc_list { */ NTSTATUS irpc_register(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, - int call, irpc_function_t fn) + int callnum, irpc_function_t fn) { struct irpc_list *irpc; - irpc = talloc(msg_ctx, struct irpc_list); - NT_STATUS_HAVE_NO_MEMORY(irpc); + /* override an existing handler, if any */ + for (irpc=msg_ctx->irpc; irpc; irpc=irpc->next) { + if (irpc->table == table && irpc->callnum == callnum) { + break; + } + } + if (irpc == NULL) { + irpc = talloc(msg_ctx, struct irpc_list); + NT_STATUS_HAVE_NO_MEMORY(irpc); + DLIST_ADD(msg_ctx->irpc, irpc); + } irpc->table = table; - irpc->callnum = call; + irpc->callnum = callnum; irpc->fn = fn; GUID_from_string(irpc->table->uuid, &irpc->uuid); - DLIST_ADD(msg_ctx->irpc, irpc); - return NT_STATUS_OK; } -- cgit From b4a95b949ee15054cf503029327bde9e75b7d17b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 Jun 2005 07:37:27 +0000 Subject: r7296: avoid two stat() calls per message. This increases the raw message rate from 20k/sec to 55k/sec. The irpc rate goes from 16k/sec to 34k/sec. I should have run strace -T on this a long time ago. (This used to be commit b9281668bb0c971af14df37ec3e979b9d5ef276e) --- source4/lib/messaging/messaging.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index be89c97e5b..4c4b6ea8da 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -36,6 +36,7 @@ struct messaging_context { uint32_t server_id; struct socket_context *sock; + const char *base_path; const char *path; struct dispatch_fn *dispatch; struct messaging_rec *pending; @@ -94,13 +95,9 @@ static void ping_message(struct messaging_context *msg, void *private, /* return the path to a messaging socket */ -static char *messaging_path(TALLOC_CTX *mem_ctx, uint32_t server_id) +static char *messaging_path(struct messaging_context *msg, uint32_t server_id) { - char *name = talloc_asprintf(mem_ctx, "messaging/msg.%u", (unsigned)server_id); - char *ret; - ret = smbd_tmp_path(mem_ctx, name); - talloc_free(name); - return ret; + return talloc_asprintf(msg, "%s/msg.%u", msg->base_path, (unsigned)server_id); } /* @@ -308,7 +305,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, data->data, dlength); } - rec->path = messaging_path(rec, server); + rec->path = messaging_path(msg, server); + talloc_steal(rec, rec->path); status = try_send(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { @@ -369,7 +367,8 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id mkdir(path, 0700); talloc_free(path); - msg->path = messaging_path(msg, server_id); + msg->base_path = smbd_tmp_path(msg, "messaging"); + msg->path = messaging_path(msg, server_id); msg->server_id = server_id; msg->dispatch = NULL; msg->pending = NULL; -- cgit From 37fdb858b069d862d53edae11dff42a4696c78a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 5 Jun 2005 07:44:51 +0000 Subject: r7298: ensure messages are sent in order even when under extreme load. This fixes a IO_TIMEOUT problem in the messaging benchmarks (This used to be commit c8b220b65de00418d19347cf298cc80d86e8accb) --- source4/lib/messaging/irpc.h | 2 +- source4/lib/messaging/messaging.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 93cadddd34..99a2d60f35 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -28,7 +28,7 @@ struct irpc_message { }; /* don't allow calls to take too long */ -#define IRPC_CALL_TIMEOUT 20 +#define IRPC_CALL_TIMEOUT 10 /* the server function type */ diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 4c4b6ea8da..823058b0cf 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -308,7 +308,12 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, rec->path = messaging_path(msg, server); talloc_steal(rec, rec->path); - status = try_send(rec); + if (msg->pending != NULL) { + status = STATUS_MORE_ENTRIES; + } else { + status = try_send(rec); + } + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { if (msg->pending == NULL) { EVENT_FD_WRITEABLE(msg->event.fde); -- cgit From 34ffdb12fc519dd5232082103bbe2f44d11f9ae8 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 6 Jun 2005 03:01:50 +0000 Subject: r7316: work in progress (This used to be commit 84a2b4049fde7db0d563e639e99364f40a47ace9) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 384 ++++++++++++++++++------------ 1 file changed, 237 insertions(+), 147 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index b82c0ac6a9..569978e343 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -35,92 +35,107 @@ #include #include "includes.h" -#include "system/filesys.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" -#ifndef False -# define False (0) -# define True (! False) +#ifndef FALSE +# define FALSE (0) +# define TRUE (! FALSE) #endif -#define QUERY(lsqlite3, pppValues, pNumRows, bRollbackOnError, sql...) \ - do \ - { \ - if (lsqlite3_query(lsqlite3, \ - pppValues, \ - pNumRows, \ - sql) != 0) { \ - if (bRollbackOnError) { \ - lsqlite3_query(lsqlite3, \ - NULL, \ - NULL, \ - "ROLLBACK;"); \ - } \ - return -1; \ - } \ +#define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ + do { \ + if (lsqlite3_query_norows(lsqlite3, sql) != 0) { \ + if (bRollbackOnError) { \ + lsqlite3_query_norows(lsqlite3, \ + "ROLLBACK;"); \ + } \ + return -1; \ + } \ } while (0) +/* + * lsqlite3_query_norows() + * + * This function is used for queries that are not expected to return any rows, + * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. + * There are no provisions here for returning data from rows in a table, so do + * not pass SELECT queries to this function. + */ static int -lsqlite3_query(const struct lsqlite3_private *lsqlite3, - char ***pppValues, - int *pNumRows, - const char *pSql, - ...) +lsqlite3_query_norows(const struct lsqlite3_private *lsqlite3, + const char *pSql, + ...) { -// int i; -// int retval; - int numRows; -// int numColumns; - int bFreeTable = False; -// char errorBuf[4096]; + int ret; + int bLoop; char * p; -// char * pError = NULL; - char ** ppValues; + const char * pTail; + sqlite3_stmt * pStmt; va_list args; /* Begin access to variable argument list */ va_start(args, pSql); - /* - * If they didn't give us a place to put returned values, use our own - */ - if (pppValues == NULL) - { - pppValues = &ppValues; - bFreeTable = True; - } - - /* Similarly for number of rows in result set */ - if (pNumRows == NULL) - { - pNumRows = &numRows; - } - /* Format the query */ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { return -1; } + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* No rows expected, so just step through machine code once */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_DONE) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } -#warning "*** FINISH QUERY FUNCTION. Catch timeouts, schema changed, etc. ***" + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } /* All done with variable argument list */ va_end(args); - /* Success! */ - return 0; -} + /* Free the memory we allocated for our query string */ + sqlite3_free(p); -static int -lsqlite3_create_attr_table(struct ldb_module *module, - char * pAttr) -{ -#warning "*** lsqlite3_create_attr_table() not yet written ***" - return -1; + return ret; } @@ -161,7 +176,7 @@ static int lsqlite3_case_fold_attr_required(struct ldb_module *module, char *attr) { #warning "currently, all attributes require case folding" - return True; + return TRUE; } @@ -393,6 +408,22 @@ failed: } +static int +lsqlite3_new_attr(struct lsqlite3_private * lsqlite3, + char * pAttrName) +{ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TABLE ldb_attr_%q " + "(" + " eid INTEGER REFERENCES ldb_entry, " + " attr_value TEXT" + ");", + pAttrName); + + return 0; +} + /* * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE * requests in the ldb_message @@ -419,8 +450,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module, if (flags == LDB_FLAG_MOD_ADD) { /* Create the attribute table if it doesn't exist */ - if (lsqlite3_create_attr_table(module, - el->name) != 0) { + if (lsqlite3_new_attr(lsqlite3, el->name) != 0) { return -1; } } @@ -431,60 +461,62 @@ lsqlite3_msg_to_sql(struct ldb_module *module, /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: - QUERY(lsqlite3, - NULL, NULL, - False, - "INSERT INTO ldb_attr_%q " - " (eid, attr_value) " - " VALUES " - " (%lld, %Q);", - eid, el->values[j].data); - QUERY(lsqlite3, - NULL, NULL, - False, - "UPDATE ldb_entry " - " SET entry_data = " - " add_attr(entry_data, %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, eid); + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_attr_%q " + " (eid, attr_value) " + " VALUES " + " (%lld, %Q);", + eid, el->values[j].data); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " add_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); break; case LDB_FLAG_MOD_REPLACE: - QUERY(lsqlite3, - NULL, NULL, - False, - "UPDATE ldb_attr_%q " - " SET attr_value = %Q " - " WHERE eid = %lld;", - el->values[j].data, eid); - QUERY(lsqlite3, - NULL, NULL, - False, - "UPDATE ldb_entry " - " SET entry_data = " - " mod_attr(entry_data, %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, eid); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_attr_%q " + " SET attr_value = %Q " + " WHERE eid = %lld;", + el->values[j].data, + eid); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " mod_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); break; case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ - QUERY(lsqlite3, - NULL, NULL, - False, - "DELETE FROM ldb_attr_%q " - " WHERE eid = %lld " - " AND attr_value = %Q;", - eid, el->values[j].data); - QUERY(lsqlite3, - NULL, NULL, - False, - "UPDATE ldb_entry " - " SET entry_data = " - " del_attr(entry_data, %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, eid); + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM ldb_attr_%q " + " WHERE eid = %lld " + " AND attr_value = %Q;", + eid, + el->values[j].data); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " del_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); break; } } @@ -495,11 +527,32 @@ lsqlite3_msg_to_sql(struct ldb_module *module, static int -lsqlite3_insert_dn(struct lsqlite3_private * lsqlite3, - char * pDN, - long long * pEID) +lsqlite3_new_dn(struct ldb_module *module, + char * pDN, + long long * pEID) { -#warning "*** lsqlite3_insert_dn() not yet implemented ***" + char * pName; + char * pValue; + + /* Normalize the distinguished name */ + pDN = ldb_dn_fold(module, pDN, lsqlite3_case_fold_attr_required); + + /* Parse the DN into its constituent components */ +#warning "this simple parse of DN ignores escaped '=' and ','. fix it." + while (pDN != NULL) { + pName = strsep(&pDN, ","); + + if (pDN == NULL) { + /* Attribute name with value? Should not occur. */ + return -1; + } + + pValue = pName; + strsep(&pValue, "="); + +#warning "*** lsqlite3_new_dn() not yet fully implemented ***" + } + return -1; } @@ -520,29 +573,25 @@ lsqlite3_add(struct ldb_module *module, } /* Begin a transaction */ - QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;"); + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); /* * Build any portions of the directory tree that don't exist. If the * final component already exists, it's an error. */ - if (lsqlite3_insert_dn(lsqlite3, - ldb_dn_fold(module, - msg->dn, - lsqlite3_case_fold_attr_required), - &eid) != 0) { - QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); + if (lsqlite3_new_dn(module, msg->dn, &eid) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); return -1; } /* Add attributes to this new entry */ - if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) { - QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); + if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); return -1; } /* Everything worked. Commit it! */ - QUERY(lsqlite3, NULL, NULL, True, "COMMIT;"); + QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0; } @@ -554,9 +603,12 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { - int numRows; + int ret; + int bLoop; + char * p; + const char * pTail; long long eid; - char ** ppValues; + sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -565,38 +617,76 @@ lsqlite3_modify(struct ldb_module *module, } /* Begin a transaction */ - QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;"); + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - /* Get the id of this DN. */ - QUERY(lsqlite3, - &ppValues, - &numRows, - True, - "SELECT eid " - " FROM ldb_entry " - " WHERE dn = %Q;", - ldb_dn_fold(module, - msg->dn, - lsqlite3_case_fold_attr_required)); - - /* Did it exist? */ - if (numRows != 1) { - /* Nope. See ya! */ - sqlite3_free_table(ppValues); + /* Format the query */ + if ((p = sqlite3_mprintf( + "SELECT eid " + " FROM ldb_entry " + " WHERE dn = %Q;", + ldb_dn_fold(module, + msg->dn, + lsqlite3_case_fold_attr_required))) == NULL) { return -1; } - /* Retrieve the eid */ - eid = strtoll(ppValues[1], NULL, 10); + /* Get the id of this DN. */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* One row expected */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Retrieve the EID */ + eid = sqlite3_column_int64(pStmt, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Modify attributes as specified */ + if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return -1; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } - /* Modify attributes as specified */ - if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) { - QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;"); + if (ret != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); return -1; } /* Everything worked. Commit it! */ - QUERY(lsqlite3, NULL, NULL, True, "COMMIT;"); + QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0 ; } @@ -665,7 +755,7 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, const char *url) { int ret; - int bNewDatabase = False; + int bNewDatabase = FALSE; char * p; const char * pTail; struct stat statbuf; @@ -825,7 +915,7 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, if ((stat(p, &statbuf) < 0 && errno == ENOENT) || statbuf.st_size == 0) { - bNewDatabase = True; + bNewDatabase = TRUE; } /* Try to open the (possibly empty/non-existent) database */ -- cgit From 0093e1b62cf02d1c3bdc3f18c8c4cc3d0abbf776 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 6 Jun 2005 05:47:14 +0000 Subject: r7320: added support for a private pointer in irpc registered handlers (This used to be commit eec521dffd4ca9efa7f6e31c50cf1ff365aae209) --- source4/lib/messaging/irpc.h | 7 ++++--- source4/lib/messaging/messaging.c | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 99a2d60f35..cba17a2c97 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -25,6 +25,7 @@ */ struct irpc_message { uint32_t from; + void *private; }; /* don't allow calls to take too long */ @@ -35,10 +36,10 @@ struct irpc_message { typedef NTSTATUS (*irpc_function_t)(struct irpc_message *, void *r); /* register a server function with the irpc messaging system */ -#define IRPC_REGISTER(msg_ctx, pipename, funcname, function) \ +#define IRPC_REGISTER(msg_ctx, pipename, funcname, function, private) \ irpc_register(msg_ctx, &dcerpc_table_ ## pipename, \ DCERPC_ ## funcname, \ - (irpc_function_t)function) + (irpc_function_t)function, private) /* make a irpc call */ #define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr) \ @@ -84,7 +85,7 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void NTSTATUS irpc_register(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, - int call, irpc_function_t fn); + int call, irpc_function_t fn, void *private); struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 823058b0cf..70eb2e7680 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -422,6 +422,7 @@ struct irpc_list { const struct dcerpc_interface_table *table; int callnum; irpc_function_t fn; + void *private; }; @@ -430,7 +431,7 @@ struct irpc_list { */ NTSTATUS irpc_register(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, - int callnum, irpc_function_t fn) + int callnum, irpc_function_t fn, void *private) { struct irpc_list *irpc; @@ -449,6 +450,7 @@ NTSTATUS irpc_register(struct messaging_context *msg_ctx, irpc->table = table; irpc->callnum = callnum; irpc->fn = fn; + irpc->private = private; GUID_from_string(irpc->table->uuid, &irpc->uuid); return NT_STATUS_OK; @@ -514,7 +516,8 @@ static void irpc_handler_request(struct messaging_context *msg_ctx, if (!NT_STATUS_IS_OK(status)) goto failed; /* make the call */ - m.from = src; + m.from = src; + m.private = i->private; header->status = i->fn(&m, r); /* setup the reply */ -- cgit From b8e8e5ed4e8436c4ad00eac8d72dd1157b770ab6 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 6 Jun 2005 13:11:06 +0000 Subject: r7332: added note to self for required modification (This used to be commit 8fa340c1d4423673e5a935f815491534413d9536) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 569978e343..602bd05fa2 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -912,6 +912,7 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, /* * See if we'll be creating a new database, or opening an existing one */ +#warning "eliminate stat() here; concurrent processes could conflict" if ((stat(p, &statbuf) < 0 && errno == ENOENT) || statbuf.st_size == 0) { -- cgit From 903a7fb990795deac92e13d8873ab0002572a7bb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Jun 2005 13:30:23 +0000 Subject: r7334: I do not feel oblidged to use sqlite3 when I configure ldap support :-) (fix typo) (This used to be commit d6dae85881a5b49c8a5484a0d155aea4f0beb16e) --- source4/lib/ldb/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 88aa66fcf1..ebeb9e1be0 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -8,7 +8,7 @@ libdir = @libdir@ bindir = @bindir@ WITH_GCOV = @WITH_GCOV@ WITH_LDAP = @WITH_LDAP@ -WITH_SQLITE3 = @WITH_LDAP@ +WITH_SQLITE3 = @WITH_SQLITE3@ ifeq ($(WITH_LDAP),yes) OPENLDAP_PREFIX=/usr -- cgit From 5141a1e50ca86ffaedc02d19768f613b64923968 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 6 Jun 2005 13:36:02 +0000 Subject: r7336: make --with-sqlite3=auto possible metze (This used to be commit cd59ff50ed00526c2af5ebddfb1fca942ba8faa6) --- source4/lib/ldb/sqlite3.m4 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/sqlite3.m4 b/source4/lib/ldb/sqlite3.m4 index ab7c61f243..d4a4c95870 100644 --- a/source4/lib/ldb/sqlite3.m4 +++ b/source4/lib/ldb/sqlite3.m4 @@ -2,22 +2,20 @@ # Compile with SQLITE3 support? SQLITE3_LIBS="" -with_sqlite3_support=auto +with_sqlite3_support=no AC_MSG_CHECKING([for SQLITE3 support]) AC_ARG_WITH(sqlite3, -[ --with-sqlite3 SQLITE3 support (default no)], +[ --with-sqlite3 SQLITE3 support (default=no)], [ case "$withval" in - yes|no) + yes|no|auto) with_sqlite3_support=$withval ;; esac ]) AC_MSG_RESULT($with_sqlite3_support) -if test x"$with_sqlite3_support" != x"yes"; then - with_sqlite3_support=no -else +if test x"$with_sqlite3_support" != x"no"; then ################################################################## # first test for sqlite3.h AC_CHECK_HEADERS(sqlite3.h) -- cgit From 198241adc21657f59e58de4a053a1e2218f05234 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Jun 2005 14:23:20 +0000 Subject: r7338: let it be possible to run sqlite3 tests when it is compiled in make it also so that we do not run test for modules we do not compile in (This used to be commit c226c1c7a393b398510dec0931aba2ddd09af4c3) --- source4/lib/ldb/Makefile.in | 16 +++++++++++++++- source4/lib/ldb/tests/test-sqlite3.sh | 9 +++++++++ source4/lib/ldb/tests/test-tdb.sh | 4 ++-- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100755 source4/lib/ldb/tests/test-sqlite3.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index ebeb9e1be0..648e3074c6 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -119,15 +119,29 @@ test-tdb: @echo "STARTING TDB BACKEND TEST" tests/test-tdb.sh +ifeq ($(WITH_LDAP),yes) test-ldap: @echo "STARTING LDAP BACKEND TEST" tests/test-ldap.sh +else +test-ldap: + @echo "SKIP LDAP TEST - NO LDAP SUPPORT" +endif + +ifeq ($(WITH_SQLITE3),yes) +test-sqlite3: + @echo "STARTING SQLITE3 BACKEND TEST" + tests/test-sqlite3.sh +else +test-sqlite3: + @echo "SKIP SQLITE3 TEST - NO SQLITE3 SUPPORT" +endif test-schema: @echo "STARTING SCHEMA MODULE TEST" tests/test-schema.sh -test: test-tdb test-ldap test-schema +test: test-tdb test-ldap test-sqlite3 test-schema install: all cp include/ldb.h $(includedir) diff --git a/source4/lib/ldb/tests/test-sqlite3.sh b/source4/lib/ldb/tests/test-sqlite3.sh new file mode 100755 index 0000000000..cf443bb8a1 --- /dev/null +++ b/source4/lib/ldb/tests/test-sqlite3.sh @@ -0,0 +1,9 @@ +#!/bin/sh + + +export LDB_URL="sqlite://sqltest.ldb" + +rm -f sqltest.ldb + +. tests/test-generic.sh + diff --git a/source4/lib/ldb/tests/test-tdb.sh b/source4/lib/ldb/tests/test-tdb.sh index 316828c31c..69b30a50b4 100755 --- a/source4/lib/ldb/tests/test-tdb.sh +++ b/source4/lib/ldb/tests/test-tdb.sh @@ -1,9 +1,9 @@ #!/bin/sh -export LDB_URL="tdb://test.ldb" +export LDB_URL="tdb://tdbtest.ldb" -rm -f test.ldb +rm -f tdbtest.ldb . tests/test-generic.sh -- cgit From ca7baa3c9fc4814b7033f68a88ddac8072d62e2a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Jun 2005 15:19:49 +0000 Subject: r7343: handle url like ldb_tdb does (This used to be commit d36fde5c0cfe20d03dd99e2ffffdd13acf9f76f3) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 602bd05fa2..9ed137c4f5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -903,11 +903,16 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, ; /* Skip protocol indicator of url */ - if ((p = strchr(url, ':')) == NULL) { - return SQLITE_MISUSE; - } else { - ++p; - } + if (strchr(url, ':')) { + if (strncmp(url, "sqlite://", 9) != 0) { + errno = EINVAL; + return SQLITE_MISUSE; + } + p = url + 9; + } else { + p = url; + } + /* * See if we'll be creating a new database, or opening an existing one -- cgit From f08fafc49270022e3cca1a89c04b7dc014b9e12b Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 7 Jun 2005 03:01:46 +0000 Subject: r7349: work in progress (This used to be commit 0e4d9729d99a1a148a951878188fe1955713aea4) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 405 ++++++++++++++++++++++-------- 1 file changed, 299 insertions(+), 106 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 9ed137c4f5..25efc8ced2 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1,7 +1,6 @@ /* ldb database library - Copyright (C) Andrew Tridgell 2004 Copyright (C) Derrell Lipman 2005 ** NOTE! The following LGPL license applies to the ldb @@ -37,6 +36,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/include/ldb_parse.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" #ifndef FALSE @@ -294,124 +294,314 @@ lsqlite3_add_msg_attr(struct ldb_context *ldb, } #endif -/* - * search for matching records - */ -static int -lsqlite3_search(struct ldb_module *module, - const char *base, - enum ldb_scope scope, - const char *expression, - const char * const attrs[], - struct ldb_message ***res) +static char * +lsqlite3_parsetree_to_sql(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t) { -#warning "lsqlite3_search() not yet implemented" -#if 0 - int count; - int msg_count; - struct ldb_context * ldb = module->ldb; - struct lsqlite3_private * lsqlite3 = module->private_data; + int i; + char * child; + char * p; + char * ret = NULL; + char * pAttrName; + - if (base == NULL) { - base = ""; - } + switch(t->operation) { + case LDB_OP_SIMPLE: + break; - lsqlite3->last_rc = ldap_search_s(lsqlite3->ldap, base, (int)scope, - expression, - discard_const_p(char *, attrs), - 0, &ldapres); - if (lsqlite3->last_rc != LDAP_SUCCESS) { - return -1; - } + case LDB_OP_AND: + ret = lsqlite3_parsetree_to_sql(module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = + lsqlite3_parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "INTERSECT\n" + "%s\n", + child); + talloc_free(child); + } - count = ldap_count_entries(lsqlite3->ldap, ldapres); - if (count == -1 || count == 0) { - ldap_msgfree(ldapres); - return count; - } + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_OR: + child = + lsqlite3_parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = + lsqlite3_parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "UNION\n" + "%s\n", + child); + talloc_free(child); + } + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_NOT: + child = + lsqlite3_parsetree_to_sql( + module, + hTalloc, + t->u.not.child); + ret = talloc_asprintf(hTalloc, + "(\n" + " SELECT eid\n" + " FROM ldb_entry\n" + " WHERE eid NOT IN %s\n" + ")\n", + child); + talloc_free(child); + return ret; + + default: + /* should never occur */ + abort(); + }; + + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, + t->u.simple.attr); - (*res) = talloc_array(lsqlite3, struct ldb_message *, count+1); - if (! *res) { - ldap_msgfree(ldapres); - errno = ENOMEM; - return -1; - } + /* + * For simple searches, we want to retrieve the list of EIDs that + * match the criteria. We accomplish this by searching the + * appropriate table, ldb_attr_, for the eid + * corresponding to all matching values. + */ + if (t->u.simple.value.length == 1 && + (*(const char *) t->u.simple.value.data) == '*') { + /* + * Special case for "attr_name=*". In this case, we want the + * eid corresponding to all values in the specified attribute + * table. + */ + if ((p = sqlite3_mprintf("(\n" + " SELECT eid\n" + " FROM ldb_attr_%q\n" + ")\n", + pAttrName)) == NULL) { + return NULL; + } - (*res)[0] = NULL; + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); - msg_count = 0; + } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { + /* + * For object classes, we want to search for all objectclasses + * that are subclasses as well. + */ + if ((p = sqlite3_mprintf( + "(\n" + " SELECT eid\n" + " FROM ldb_attr_objectclass\n" + " WHERE attr_name IN\n" + " (SELECT class_name\n" + " FROM ldb_objectclasses\n" + " WHERE tree_key GLOB\n" + " (SELECT tree_key\n" + " FROM ldb_objectclasses\n" + " WHERE class_name = %Q) || '*')\n" + ")\n", + t->u.simple.value.data)) == NULL) { + return NULL; + } - /* loop over all messages */ - for (msg=ldap_first_entry(lsqlite3->ldap, ldapres); - msg; - msg=ldap_next_entry(lsqlite3->ldap, msg)) { - BerElement *berptr = NULL; - char *attr, *dn; + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); - if (msg_count == count) { - /* hmm, got too many? */ - ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n"); - break; - } + } else { + /* A normal query. */ + if ((p = sqlite3_mprintf("(\n" + " SELECT eid\n" + " FROM ldb_attr_%q\n" + " WHERE attr_value = %Q\n" + ")\n", + pAttrName, + t->u.simple.value.data)) == NULL) { + return NULL; + } - (*res)[msg_count] = talloc(*res, struct ldb_message); - if (!(*res)[msg_count]) { - goto failed; - } - (*res)[msg_count+1] = NULL; + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); + } + return ret; +} - dn = ldap_get_dn(lsqlite3->ldap, msg); - if (!dn) { - goto failed; - } - (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn); - ldap_memfree(dn); - if (!(*res)[msg_count]->dn) { - goto failed; - } +static char * +lsqlite3_parsetree_to_tablelist(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t) +{ +#warning "obtain talloc'ed array of attribute names for table list" + return NULL; +} - (*res)[msg_count]->num_elements = 0; - (*res)[msg_count]->elements = NULL; - (*res)[msg_count]->private_data = NULL; +/* + * search for matching records + */ +static int +lsqlite3_search(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + const char * pExpression, + const char * const attrs[], + struct ldb_message *** res) +{ + int ret; + int bLoop; + long long eid; + char * sql; + char * sql_constraints; + char * table_list; + char * hTalloc; + const char * pTail; + sqlite3_stmt * pStmt; + struct ldb_parse_tree * pTree; + struct lsqlite3_private * lsqlite3 = module->private_data; + + if (pBaseDN == NULL) { + pBaseDN = ""; + } - /* loop over all attributes */ - for (attr=ldap_first_attribute(lsqlite3->ldap, msg, &berptr); - attr; - attr=ldap_next_attribute(lsqlite3->ldap, msg, berptr)) { - struct berval **bval; - bval = ldap_get_values_len(lsqlite3->ldap, msg, attr); + /* + * Obtain the eid of the base DN + */ + if ((pTail = sqlite3_mprintf("SELECT eid " + " FROM ldb_attr_dn " + " WHERE attr_value = %Q;", + pBaseDN)) == NULL) { + return -1; + } - if (bval) { - lsqlite3_add_msg_attr(ldb, (*res)[msg_count], attr, bval); - ldap_value_free_len(bval); - } - - ldap_memfree(attr); - } - if (berptr) ber_free(berptr, 0); + for (bLoop = TRUE; bLoop; ) { - msg_count++; - } + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* One row expected */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Retrieve the EID */ + eid = sqlite3_column_int64(pStmt, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } - ldap_msgfree(ldapres); + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } - return msg_count; + /* Parse the filter expression into a tree we can work with */ + if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { + return -1; + } + + /* Allocate a temporary talloc context */ + hTalloc = talloc_new(module); -failed: - if (*res) lsqlite3_search_free(module, *res); - return -1; -#else - return -1; -#endif + /* Move the parse tree to our temporary context */ + talloc_steal(hTalloc, pTree); + + /* Convert filter into a series of SQL statements (constraints) */ + sql_constraints = lsqlite3_parsetree_to_sql(module, hTalloc, pTree); + + /* Get the list of attribute names to use as our extra table list */ + table_list = lsqlite3_parsetree_to_tablelist(module, hTalloc, pTree); + + switch(scope) { + case LDB_SCOPE_DEFAULT: + case LDB_SCOPE_SUBTREE: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT ldb_entry.eid\n" + " FROM ldb_entry,\n" + " ldb_descendants,\n" + " %q\n" + " WHERE ldb_descendants.aeid = %lld\n" + " AND ldb_entry.eid = ldb_descendants.deid\n" + " AND ldap_entry.eid IN\n" + "%s);", + table_list, + sql_constraints); + break; + +#warning "scope BASE and ONLEVEL not yet implemented" + case LDB_SCOPE_BASE: + break; + + case LDB_SCOPE_ONELEVEL: + break; + } + + return ret; } static int -lsqlite3_new_attr(struct lsqlite3_private * lsqlite3, +lsqlite3_new_attr(struct ldb_module * module, char * pAttrName) { + struct lsqlite3_private * lsqlite3 = module->private_data; + + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, pAttrName); + QUERY_NOROWS(lsqlite3, FALSE, "CREATE TABLE ldb_attr_%q " @@ -429,12 +619,13 @@ lsqlite3_new_attr(struct lsqlite3_private * lsqlite3, * requests in the ldb_message */ static int -lsqlite3_msg_to_sql(struct ldb_module *module, - const struct ldb_message *msg, +lsqlite3_msg_to_sql(struct ldb_module * module, + const struct ldb_message * msg, long long eid, int use_flags) { int flags; + char * pAttrName; unsigned int i; unsigned int j; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -450,7 +641,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module, if (flags == LDB_FLAG_MOD_ADD) { /* Create the attribute table if it doesn't exist */ - if (lsqlite3_new_attr(lsqlite3, el->name) != 0) { + if (lsqlite3_new_attr(module, el->name) != 0) { return -1; } } @@ -458,6 +649,10 @@ lsqlite3_msg_to_sql(struct ldb_module *module, /* For each value of the specified attribute name... */ for (j = 0; j < el->num_values; j++) { + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, + el->name); + /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: @@ -467,6 +662,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module, " (eid, attr_value) " " VALUES " " (%lld, %Q);", + pAttrName, eid, el->values[j].data); QUERY_NOROWS(lsqlite3, FALSE, @@ -486,6 +682,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module, "UPDATE ldb_attr_%q " " SET attr_value = %Q " " WHERE eid = %lld;", + pAttrName, el->values[j].data, eid); QUERY_NOROWS(lsqlite3, @@ -506,6 +703,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module, "DELETE FROM ldb_attr_%q " " WHERE eid = %lld " " AND attr_value = %Q;", + pAttrName, eid, el->values[j].data); QUERY_NOROWS(lsqlite3, @@ -903,16 +1101,11 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, ; /* Skip protocol indicator of url */ - if (strchr(url, ':')) { - if (strncmp(url, "sqlite://", 9) != 0) { - errno = EINVAL; - return SQLITE_MISUSE; - } - p = url + 9; - } else { - p = url; - } - + if ((p = strchr(url, ':')) == NULL) { + return SQLITE_MISUSE; + } else { + ++p; + } /* * See if we'll be creating a new database, or opening an existing one -- cgit From bce8cda06123648c377fbef92526f1f56121e513 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 7 Jun 2005 07:22:25 +0000 Subject: r7352: the internal heimdal build change. This changes quite a few things: - if you want kerberos now, you need to unpack a lorikeet heimdal tree in source/heimdal/. If source/heimdal/ does not exist at configure time then all kerberos features are disabled. You cannot use an external kerberos library for now. That may change later. - moved lib/replace/ config stuff to lib/replace/ and create a lib/replace/replace.h. That allows the heimdal build to use our portability layer, and prevenets duplicate definitions of functions like strlcat() - if you do enable heimdal, then you will need to do 'make HEIMDAL_EXTERNAL' before you build Samba. That should be fixed once I explain the problem to jelmer (the problem is the inability to set a depend without also dragging in the object list of the dependency. We need this for building the heimdal asn1 compiler and et compiler. - disabled all of the m4 checks for external kerberos libraries. I left them in place in auth/kerberos/, but disabled it in configure.in some of the heimdal_build/ code is still very rough, for example I don't correctly detect the correct awk, flex, bison replacements for heimdal_build/build_external.sh. I expect to fix that stuff up over the next few days. (This used to be commit d4648249b2c7fc8b5e7c0fc8d8f92ae043b5691f) --- source4/lib/basic.mk | 9 ---- source4/lib/replace/config.mk | 9 ++++ source4/lib/replace/replace.h | 114 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 source4/lib/replace/config.mk create mode 100644 source4/lib/replace/replace.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 02783366ca..6a463b8ec6 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -1,14 +1,5 @@ # LIB BASIC subsystem -############################## -# Start SUBSYSTEM LIBREPLACE -[SUBSYSTEM::LIBREPLACE] -INIT_OBJ_FILES = lib/replace/replace.o -ADD_OBJ_FILES = \ - lib/replace/snprintf.o -# End SUBSYSTEM LIBREPLACE -############################## - ############################## # Start SUBSYSTEM LIBNETIF [SUBSYSTEM::LIBNETIF] diff --git a/source4/lib/replace/config.mk b/source4/lib/replace/config.mk new file mode 100644 index 0000000000..bd60402ba3 --- /dev/null +++ b/source4/lib/replace/config.mk @@ -0,0 +1,9 @@ +############################## +# Start SUBSYSTEM LIBREPLACE +[SUBSYSTEM::LIBREPLACE] +INIT_OBJ_FILES = lib/replace/replace.o +ADD_OBJ_FILES = \ + lib/replace/snprintf.o +# End SUBSYSTEM LIBREPLACE +############################## + diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h new file mode 100644 index 0000000000..e0cb1420ec --- /dev/null +++ b/source4/lib/replace/replace.h @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + + macros to go along with the lib/replace/ portability layer code + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _replace_h +#define _replace_h + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#ifndef HAVE_STRDUP +char *strdup(const char *s); +#endif + +#ifndef HAVE_MEMMOVE +void *memmove(void *dest,const void *src,int size); +#endif + +#ifndef HAVE_MKTIME +time_t mktime(struct tm *t); +#endif + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *d, const char *s, size_t bufsize); +#endif + +#ifndef HAVE_STRLCAT +size_t strlcat(char *d, const char *s, size_t bufsize); +#endif + +#ifndef HAVE_STRNDUP +char *strndup(const char *s, size_t n); +#endif + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t n); +#endif + +#ifndef HAVE_STRTOUL +unsigned long strtoul(const char *nptr, char **endptr, int base); +#endif + +#ifndef HAVE_SETENV +int setenv(const char *name, const char *value, int overwrite); +#endif + +#ifndef HAVE_VASPRINTF_DECL +int vasprintf(char **ptr, const char *format, va_list ap); +#endif + +#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET) +#define bzero(a,b) memset((a),'\0',(b)) +#endif + +/* add varargs prototypes with printf checking */ +#ifndef HAVE_SNPRINTF_DECL +int snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); +#endif +#ifndef HAVE_ASPRINTF_DECL +int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + + +/* we used to use these fns, but now we have good replacements + for snprintf and vsnprintf */ +#define slprintf snprintf + + +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#elif defined(HAVE___VA_COPY) +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#if defined(HAVE_VOLATILE) +#define VOLATILE volatile +#else +#define VOLATILE +#endif + +#ifndef HAVE_COMPARISON_FN_T +typedef int (*comparison_fn_t)(const void *, const void *); +#endif + +#endif -- cgit From c6a3ee8baba002d7568d17fb0bc73908eb4da2e7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 7 Jun 2005 18:11:59 +0000 Subject: r7373: Disable reg_gconf by default, allow building it with --enable-reg-gconf (This used to be commit 6596f619c0500a419a680a7488a0838c234f2069) --- source4/lib/registry/config.m4 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.m4 b/source4/lib/registry/config.m4 index abadcbe1a0..d0d1d2c54b 100644 --- a/source4/lib/registry/config.m4 +++ b/source4/lib/registry/config.m4 @@ -11,9 +11,13 @@ SMB_MODULE_DEFAULT(registry_gconf, NOT) SMB_EXT_LIB_FROM_PKGCONFIG(gconf, gconf-2.0) -if test t$SMB_EXT_LIB_ENABLE_gconf = tYES; then - SMB_MODULE_DEFAULT(registry_gconf, STATIC) -fi +AC_ARG_ENABLE(reg-gconf, +[ --enable-reg-gconf Enable support for GConf registry backend], +[ + if test t$enable = tyes && test t$SMB_EXT_LIB_ENABLE_gconf = tYES; then + SMB_MODULE_DEFAULT(registry_gconf, STATIC) + fi +]) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libwinregistry, YES) -- cgit From 7fc1c3553cd3666c234ec302a54ebd331589c934 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 8 Jun 2005 19:49:49 +0000 Subject: r7408: added DN explode function, based on simo's ldap_parse_dn() function. simo, when you get a chance, please change your license so this can be linked with ldb. (This used to be commit 588a1d1451d4117cb6e427a293455f2a5657b604) --- source4/lib/ldb/Makefile.in | 3 +- source4/lib/ldb/common/ldb_explode_dn.c | 461 ++++++++++++++++++++++++++++++ source4/lib/ldb/include/ldb_explode_dn.h | 38 +++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 55 +++- 4 files changed, 542 insertions(+), 15 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_explode_dn.c create mode 100644 source4/lib/ldb/include/ldb_explode_dn.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 648e3074c6..5bccf17e82 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -51,7 +51,8 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ - common/ldb_debug.o common/ldb_modules.o + common/ldb_debug.o common/ldb_modules.o \ + common/ldb_explode_dn.o MODULES_OBJ=modules/timestamps.o modules/schema.o diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c new file mode 100644 index 0000000000..db8e8f2a85 --- /dev/null +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -0,0 +1,461 @@ +/* + Unix SMB/CIFS implementation. + LDAP server + Copyright (C) Simo Sorce 2004 + Copyright (C) Derrell Lipman 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_explode_dn.h" + +#define LDB_PARSE_DN_INVALID(x) do { \ + if (x) { \ + goto failed; \ + } \ +} while(0) + + + +static char +octet_from_hex(char * p, + char * ret) +{ + unsigned char low_char; + unsigned char high_char; + + unsigned char low_binary; + unsigned char high_binary; + + if (p[0] == '\0' || p[1] == '\0') { + return -1; + } + + high_char = p[0]; + low_char = p[1]; + + if (high_char >= '0' && high_char <= '9') { + high_binary = high_char - '0'; + } else if (high_char >= 'A' && high_char <= 'F') { + high_binary = 10 + (high_char - 'A'); + } else if (high_char >= 'a' && high_char <= 'f') { + high_binary = 10 + (high_char - 'a'); + } else { + return -1; + } + + if (low_char >= '0' && low_char <= '9') { + low_binary = low_char - '0'; + } else if (low_char >= 'A' && low_char <= 'F') { + low_binary = 10 + (low_char - 'A'); + } else if (low_char >= 'a' && low_char <= 'f') { + low_binary = 10 + (low_char - 'a'); + } else { + return -1; + } + + *ret = (char) ((high_binary << 4) | low_binary); + return 0; +} + +static char * +parse_slash(char *p, + char *end) +{ + switch (*(p + 1)) { + case ',': + case '=': + case '\n': + case '+': + case '<': + case '>': + case '#': + case ';': + case '\\': + case '"': + memmove(p, p + 1, end - (p + 1)); + return (end - 1); + + default: + if (*(p + 1) != '\0' && *(p + 2) != '\0') { + if (octet_from_hex(p + 1, p) < 0) { + return NULL; + } + memmove(p + 1, p + 3, end - (p + 3)); + return (end - 2); + } else { + return NULL; + } + } +} + +struct ldb_dn * +ldb_explode_dn(void *mem_ctx, + const char *orig_dn) +{ + struct ldb_dn * dn; + struct ldb_dn_component * component; + struct ldb_dn_attribute * attribute; + char * p; + char * start; + char * separator; + char * src; + char * dest; + char * dn_copy; + char * dn_end; + int i; + int size; + int orig_len; + + /* Allocate a structure to hold the exploded DN */ + if ((dn = talloc(mem_ctx, struct ldb_dn)) == NULL) { + return NULL; + } + + /* Initially there are no components */ + dn->comp_num = 0; + + /* Allocate the component array, with space for one component */ + if ((dn->components = + talloc_array(dn, struct ldb_dn_component *, 1)) == NULL) { + + goto failed; + } + + /* Allocate the first component */ + if ((component = talloc(dn, struct ldb_dn_component)) == NULL) { + goto failed; + } + + /* This component has no attributes yet */ + component->attr_num = 0; + + /* Get the length of the provided DN */ + if ((orig_len = strlen(orig_dn)) == 0) { + + /* We found a zero-length DN. Return it. */ + if ((dn->dn = talloc_strdup(dn, orig_dn)) == NULL) { + goto failed; + } + return dn; + } + + /* Copy the provided DN so we can manipulate it */ + if ((dn_copy = p = talloc_strdup(mem_ctx, orig_dn)) == NULL) { + goto failed; + } + + /* Our copy may end shorter than the original as we unescape chars */ + dn_end = dn_copy + orig_len + 1; + + /* For each attribute/value pair... */ + do { + /* Allocate an array to hold the attributes, initially len 1 */ + if ((component->attributes = + talloc_array(component, + struct ldb_dn_attribute *, 1)) == NULL) { + goto failed; + } + + /* Allocate this attribute */ + if ((attribute = + talloc(component, struct ldb_dn_attribute)) == NULL) { + goto failed; + } + + /* skip white space */ + while (*p == ' ' || *p == '\n') { + p++; + } + + /* start parsing this component */ + do { + /* Save pointer to beginning of attribute name */ + start = p; + + /* find our attribute/value separator '=' */ + while (*p != '\0' && *p != '=') { + if (*p == '\\') { + if ((dn_end = + parse_slash(p, dn_end)) == NULL) { + goto failed; + } + } + p++; + } + + /* Ensure we found the attribute/value separator */ + if (*p != '=') { + goto failed; + } + + /* Save pointer to separator */ + separator = p; + + /* remove trailing white space from attribute name */ + while (p > start && + (*(p - 1) == ' ' || *(p - 1) == '\n')) { + + p--; + } + LDB_PARSE_DN_INVALID((p - start) < 1); + + /* save attribute name */ + if ((attribute->name = + talloc_strndup(attribute, + start, + p - start)) == NULL) { + goto failed; + } + + ldb_debug(mem_ctx, + LDB_DEBUG_TRACE, + "attribute name: [%s]\n", attribute->name); + + /* skip white space after the separator */ + p = separator + 1; + p += strspn(p, " \n"); + + /* ensure there's a value here */ + if (*p == '\0') { + goto failed; + } + + /* check if the value is enclosed in QUOTATION */ + if (*p == '"') { + /* save pointer to beginning of attr value */ + start = p + 1; + + /* find the trailing QUOTE */ + while (*p != '\0' && *p != '"') { + if (*p == '\\') { + if ((dn_end = + parse_slash(p, dn_end)) == NULL) { + goto failed; + } + } + + p++; + } + + /* skip spaces until the separator */ + if (*p == '\0') { + /* We're already at end of string */ + separator = p; + } else { + /* Skip spaces */ + separator = p + 1 + strspn(p+1, " \n"); + } + + /* must be end of string or a separator here */ + if (*separator != '\0' && + *separator != ',' && + *separator != ';' && + *separator != '+') { + /* Error Malformed DN */ + goto failed; + } + } else { + /* + * Value is not quouted. + */ + + /* save pointer to beginning of value */ + start = p; + + /* find end of value */ + while (*p != '\0' && + *p != ',' && + *p != ';' && + *p != '+') { + + if (*p == '\\') { + if ((dn_end = + parse_slash(p, dn_end)) == NULL) { + goto failed; + } + } + + p++; + } + + /* save pointer to the terminating separator */ + separator = p; + + /* remove trailing whitespace */ + while (p > start && + (*(p - 1) == ' ' || + *(p - 1) == '\n')) { + + p--; + } + } + LDB_PARSE_DN_INVALID((p - start) < 1); + + /* save the value */ + if ((attribute->value = + talloc_strndup(attribute, + start, + p - start)) == NULL) { + goto failed; + } + + ldb_debug(mem_ctx, + LDB_DEBUG_TRACE, + "attribute value: [%s]\n", attribute->value); + + /* save the entire RDN */ + if ((attribute->rdn = + talloc_asprintf(attribute, + "%s=%s", + attribute->name, + attribute->value)) == NULL) { + goto failed; + } + + ldb_debug(mem_ctx, + LDB_DEBUG_TRACE, + "attribute: [%s]\n", attribute->rdn); + + /* add this attribute to the attribute list */ + component->attributes[component->attr_num] = attribute; + component->attr_num++; + + /* is this a multi-valued attribute? */ + if (*separator == '+') { + /* Yup. prepare for the next value. */ + if ((component->attributes = + talloc_realloc(component, + component->attributes, + struct ldb_dn_attribute *, + component->attr_num + 1)) == NULL) { + goto failed; + } + + /* allocate new attribute structure */ + if ((attribute = + talloc(component, + struct ldb_dn_attribute)) == NULL) { + goto failed; + } + } + + /* if we're not at end of string, skip white space */ + if (*separator != '\0') { + /* skip spaces past the separator */ + p = separator + 1; + p += strspn(p, " \n"); + } + + } while (*separator == '+'); + + /* find total length of all attributes */ + for (i = 0, size = 0; i < component->attr_num; i++) { + size += strlen(component->attributes[i]->rdn) + 1; + } + + /* + * rebuild the normalized component + */ + + /* allocate space for the normalized component */ + if ((component->component = + dest = talloc_size(component, size)) == NULL) { + + goto failed; + } + + /* copy each of the attributes to the normalized component */ + for (i = 0; i < component->attr_num; i++) { + if (i != 0) { + *dest = '+'; + dest++; + } + src = component->attributes[i]->rdn; + do { + *(dest++) = *(src++); + } while(*src); + *dest = '\0'; + } + + ldb_debug(mem_ctx, + LDB_DEBUG_TRACE, + "component: [%s]\n", component->component); + + /* insert the component into the component list */ + dn->components[dn->comp_num] = component; + dn->comp_num++; + + /* if there are additional components... */ + if (*separator == ',' || *separator == ';') { + /* ... then prepare to parse them */ + if ((dn->components = + talloc_realloc(dn, + dn->components, + struct ldb_dn_component *, + dn->comp_num + 1)) == NULL || + (component = + talloc(dn, struct ldb_dn_component)) == NULL) { + + goto failed; + } + + component->attr_num = 0; + } + + /* update pointer to after the separator */ + p = separator + 1; + + } while(*separator == ',' || *separator == ';'); + + /* find total length of all components */ + for (i = 0, size = 0; i < dn->comp_num; i++) { + size = size + strlen(dn->components[i]->component) + 1; + } + + /* rebuild the normalized DN */ + if ((dn->dn = dest = talloc_size(dn, size)) == NULL) { + goto failed; + } + + /* copy the normalized components into the DN */ + for (i = 0; i < dn->comp_num; i++) { + if (i != 0) { + *dest = ','; + dest++; + } + src = dn->components[i]->component; + do { + *(dest++) = *(src++); + } while(*src); + *dest = '\0'; + } + + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); + + /* we don't need the copy of the DN any more */ + talloc_free(dn_copy); + + /* give 'em what they came for! */ + return dn; + +failed: + /* something went wrong. free memory and tell 'em it failed */ + talloc_free(dn); + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn); + return NULL; +} diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_explode_dn.h new file mode 100644 index 0000000000..fb34be8b87 --- /dev/null +++ b/source4/lib/ldb/include/ldb_explode_dn.h @@ -0,0 +1,38 @@ +/* + Unix SMB/CIFS implementation. + LDAP server + Copyright (C) Simo Sorce 2004 + Copyright (C) Derrell Lipman 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct ldb_dn_attribute { + char * rdn; + char * name; + char * value; +}; + +struct ldb_dn_component { + char * component; + int attr_num; + struct ldb_dn_attribute ** attributes; +}; + +struct ldb_dn { + char *dn; + int comp_num; + struct ldb_dn_component ** components; +}; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 25efc8ced2..147ee599a9 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -569,23 +569,52 @@ lsqlite3_search(struct ldb_module * module, "SELECT entry.entry_data\n" " FROM ldb_entry AS entry\n" " WHERE entry.eid IN\n" - " (SELECT ldb_entry.eid\n" + " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry,\n" " ldb_descendants,\n" " %q\n" " WHERE ldb_descendants.aeid = %lld\n" " AND ldb_entry.eid = ldb_descendants.deid\n" " AND ldap_entry.eid IN\n" - "%s);", + "%s" + ");", table_list, + eid, sql_constraints); break; -#warning "scope BASE and ONLEVEL not yet implemented" case LDB_SCOPE_BASE: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM %q\n" + " WHERE ldb_entry.eid = %lld\n" + " AND ldb_entry.eid IN\n" + "%s" + ");", + table_list, + eid, + sql_constraints); break; case LDB_SCOPE_ONELEVEL: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry AS pchild, " + " %q\n" + " WHERE ldb_entry.eid = pchild.eid " + " AND pchild.peid = %lld " + " AND ldb_entry.eid IN\n" + "%s" + ");", + table_list, + eid, + sql_constraints); break; } @@ -599,9 +628,7 @@ lsqlite3_new_attr(struct ldb_module * module, { struct lsqlite3_private * lsqlite3 = module->private_data; - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, pAttrName); - + /* NOTE: pAttrName is assumed to already be case-folded here! */ QUERY_NOROWS(lsqlite3, FALSE, "CREATE TABLE ldb_attr_%q " @@ -639,9 +666,13 @@ lsqlite3_msg_to_sql(struct ldb_module * module, flags = el->flags & LDB_FLAG_MOD_MASK; } + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, + el->name); + if (flags == LDB_FLAG_MOD_ADD) { /* Create the attribute table if it doesn't exist */ - if (lsqlite3_new_attr(module, el->name) != 0) { + if (lsqlite3_new_attr(module, pAttrName) != 0) { return -1; } } @@ -649,10 +680,6 @@ lsqlite3_msg_to_sql(struct ldb_module * module, /* For each value of the specified attribute name... */ for (j = 0; j < el->num_values; j++) { - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, - el->name); - /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: @@ -725,7 +752,7 @@ lsqlite3_msg_to_sql(struct ldb_module * module, static int -lsqlite3_new_dn(struct ldb_module *module, +lsqlite3_new_dn(struct ldb_module * module, char * pDN, long long * pEID) { @@ -738,10 +765,10 @@ lsqlite3_new_dn(struct ldb_module *module, /* Parse the DN into its constituent components */ #warning "this simple parse of DN ignores escaped '=' and ','. fix it." while (pDN != NULL) { - pName = strsep(&pDN, ","); + pName = strsep(&pValue, "="); if (pDN == NULL) { - /* Attribute name with value? Should not occur. */ + /* Attribute name without value? Should not occur. */ return -1; } -- cgit From 322f0df3f124c95f2f50abbb2c07616a6cf721c0 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 8 Jun 2005 20:30:50 +0000 Subject: r7410: minor cleanup (This used to be commit 4c8bffc3f01d60ef7d8b75e92f4d062326288f4c) --- source4/lib/ldb/common/ldb_explode_dn.c | 21 +++++++++++---------- source4/lib/ldb/include/ldb_explode_dn.h | 9 +++++++-- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index db8e8f2a85..4e71bc70d1 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -386,10 +386,9 @@ ldb_explode_dn(void *mem_ctx, dest++; } src = component->attributes[i]->rdn; - do { - *(dest++) = *(src++); - } while(*src); - *dest = '\0'; + + /* we are guaranteed to have enough space in dest */ + strcpy(dest, src); } ldb_debug(mem_ctx, @@ -434,15 +433,17 @@ ldb_explode_dn(void *mem_ctx, /* copy the normalized components into the DN */ for (i = 0; i < dn->comp_num; i++) { + + /* add a separator between DN components */ if (i != 0) { - *dest = ','; - dest++; + *dest++ = ','; } + + /* point to this component of the DN */ src = dn->components[i]->component; - do { - *(dest++) = *(src++); - } while(*src); - *dest = '\0'; + + /* we are guaranteed to have enough space in dest */ + strcpy(dest, src); } ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_explode_dn.h index fb34be8b87..78768ebb80 100644 --- a/source4/lib/ldb/include/ldb_explode_dn.h +++ b/source4/lib/ldb/include/ldb_explode_dn.h @@ -32,7 +32,12 @@ struct ldb_dn_component { }; struct ldb_dn { - char *dn; - int comp_num; + char * dn; + int comp_num; struct ldb_dn_component ** components; }; + + +extern struct ldb_dn * +ldb_explode_dn(void *mem_ctx, + const char *orig_dn); -- cgit From a6717fae681f89cf427e282d645029ca0b3e4d44 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 02:47:26 +0000 Subject: r7418: work in progress (This used to be commit 2a13e7655b1bce88694ddbb6a4d9349008ba42f0) --- source4/lib/ldb/common/ldb_explode_dn.c | 218 ++++++++++++++++++++---------- source4/lib/ldb/common/ldb_utf8.c | 4 +- source4/lib/ldb/include/ldb.h | 2 +- source4/lib/ldb/include/ldb_explode_dn.h | 7 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 58 ++++---- 5 files changed, 187 insertions(+), 102 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 4e71bc70d1..d3f278c776 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -30,82 +30,67 @@ } while(0) +/* + * Forward declarations + */ static char octet_from_hex(char * p, - char * ret) -{ - unsigned char low_char; - unsigned char high_char; - - unsigned char low_binary; - unsigned char high_binary; - - if (p[0] == '\0' || p[1] == '\0') { - return -1; - } - - high_char = p[0]; - low_char = p[1]; - - if (high_char >= '0' && high_char <= '9') { - high_binary = high_char - '0'; - } else if (high_char >= 'A' && high_char <= 'F') { - high_binary = 10 + (high_char - 'A'); - } else if (high_char >= 'a' && high_char <= 'f') { - high_binary = 10 + (high_char - 'a'); - } else { - return -1; - } - - if (low_char >= '0' && low_char <= '9') { - low_binary = low_char - '0'; - } else if (low_char >= 'A' && low_char <= 'F') { - low_binary = 10 + (low_char - 'A'); - } else if (low_char >= 'a' && low_char <= 'f') { - low_binary = 10 + (low_char - 'a'); - } else { - return -1; - } - - *ret = (char) ((high_binary << 4) | low_binary); - return 0; -} + char * ret); static char * parse_slash(char *p, - char *end) -{ - switch (*(p + 1)) { - case ',': - case '=': - case '\n': - case '+': - case '<': - case '>': - case '#': - case ';': - case '\\': - case '"': - memmove(p, p + 1, end - (p + 1)); - return (end - 1); - - default: - if (*(p + 1) != '\0' && *(p + 2) != '\0') { - if (octet_from_hex(p + 1, p) < 0) { - return NULL; - } - memmove(p + 1, p + 3, end - (p + 3)); - return (end - 2); - } else { - return NULL; - } - } -} - + char *end); + + + +/* + * Public functions + */ + +/* + * ldb_explode_dn() + * + * Explode, normalize, and optionally case-fold a DN string. The result is a + * structure containing arrays of the constituent RDNs. + * + * Parameters: + * mem_ctx - + * talloc context on which all allocated memory is hung + * + * orig_dn - + * The distinguished name, in string format, to be exploded + * + * hUserData - + * Data handle provided by the caller, and passed back to the caller in + * the case_fold_attr_fn callback function. This handle is not otherwise + * used within this function. + * + * case_fold_attr_fn - + * Pointer to a callback function which will be called to determine if a + * particular attribute type (name) requires case-folding of its values. + * If this function pointer is non-null, then attribute names will always + * be case-folded. Additionally, the function pointed to by + * case_fold_attr_fn will be called with the data handle (hUserData) and + * an attribute name as its parameters, and should return TRUE or FALSE to + * indicate whether values of that attribute type should be case-folded. + * + * If case_fold_attr_fn is null, then neither attribute names nor + * attribute values will be case-folded. + * + * Returns: + * Upon success, an ldb_dn structure pointer is returned, containing the + * exploded DN. + * + * If memory could not be allocated or if the DN was improperly formatted, + * NULL is returned. + */ struct ldb_dn * -ldb_explode_dn(void *mem_ctx, - const char *orig_dn) +ldb_explode_dn(void * mem_ctx, + const char * orig_dn, + void * hUserData, + int (*case_fold_attr_fn)(void * hUserData, + char * attr)) { struct ldb_dn * dn; struct ldb_dn_component * component; @@ -222,6 +207,14 @@ ldb_explode_dn(void *mem_ctx, goto failed; } + /* attribute names are always case-folded */ + p = attribute->name; + if ((attribute->name = + ldb_casefold(attribute, p)) == NULL) { + goto failed; + } + talloc_free(p); + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "attribute name: [%s]\n", attribute->name); @@ -314,6 +307,19 @@ ldb_explode_dn(void *mem_ctx, goto failed; } + /* see if this attribute value needs case folding */ + if (case_fold_attr_fn != NULL && + (* case_fold_attr_fn)(hUserData, + attribute->name)) { + /* yup, case-fold it. */ + p = attribute->value; + if ((attribute->value = + ldb_casefold(attribute, p)) == NULL) { + goto failed; + } + talloc_free(p); + } + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "attribute value: [%s]\n", attribute->value); @@ -460,3 +466,77 @@ failed: ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn); return NULL; } + + +static char +octet_from_hex(char * p, + char * ret) +{ + unsigned char low_char; + unsigned char high_char; + + unsigned char low_binary; + unsigned char high_binary; + + if (p[0] == '\0' || p[1] == '\0') { + return -1; + } + + high_char = p[0]; + low_char = p[1]; + + if (high_char >= '0' && high_char <= '9') { + high_binary = high_char - '0'; + } else if (high_char >= 'A' && high_char <= 'F') { + high_binary = 10 + (high_char - 'A'); + } else if (high_char >= 'a' && high_char <= 'f') { + high_binary = 10 + (high_char - 'a'); + } else { + return -1; + } + + if (low_char >= '0' && low_char <= '9') { + low_binary = low_char - '0'; + } else if (low_char >= 'A' && low_char <= 'F') { + low_binary = 10 + (low_char - 'A'); + } else if (low_char >= 'a' && low_char <= 'f') { + low_binary = 10 + (low_char - 'a'); + } else { + return -1; + } + + *ret = (char) ((high_binary << 4) | low_binary); + return 0; +} + +static char * +parse_slash(char *p, + char *end) +{ + switch (*(p + 1)) { + case ',': + case '=': + case '\n': + case '+': + case '<': + case '>': + case '#': + case ';': + case '\\': + case '"': + memmove(p, p + 1, end - (p + 1)); + return (end - 1); + + default: + if (*(p + 1) != '\0' && *(p + 2) != '\0') { + if (octet_from_hex(p + 1, p) < 0) { + return NULL; + } + memmove(p + 1, p + 3, end - (p + 3)); + return (end - 2); + } else { + return NULL; + } + } +} + diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 9cbb5646dd..dc25d6cf13 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -41,10 +41,10 @@ TODO: a simple case folding function - will be replaced by a UTF8 aware function later */ -char *ldb_casefold(struct ldb_context *ldb, const char *s) +char *ldb_casefold(void *mem_ctx, const char *s) { int i; - char *ret = talloc_strdup(ldb, s); + char *ret = talloc_strdup(mem_ctx, s); if (!s) { errno = ENOMEM; return NULL; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 8ccf8967cb..91a826447a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -203,7 +203,7 @@ const char *ldb_errstring(struct ldb_context *ldb); /* casefold a string (should be UTF8, but at the moment it isn't) */ -char *ldb_casefold(struct ldb_context *ldb, const char *s); +char *ldb_casefold(void *mem_ctx, const char *s); /* ldif manipulation functions diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_explode_dn.h index 78768ebb80..af9829ba40 100644 --- a/source4/lib/ldb/include/ldb_explode_dn.h +++ b/source4/lib/ldb/include/ldb_explode_dn.h @@ -39,5 +39,8 @@ struct ldb_dn { extern struct ldb_dn * -ldb_explode_dn(void *mem_ctx, - const char *orig_dn); +ldb_explode_dn(void * mem_ctx, + const char * orig_dn, + void * hUserData, + int (*case_fold_attr_fn)(void * hUserData, + char * attr)); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 147ee599a9..4f774efbae 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -37,6 +37,7 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/include/ldb_parse.h" +#include "ldb/include/ldb_explode_dn.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" #ifndef FALSE @@ -172,9 +173,11 @@ lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, callback function used in call to ldb_dn_fold() for determining whether an attribute type requires case folding. */ -static int lsqlite3_case_fold_attr_required(struct ldb_module *module, - char *attr) +static int lsqlite3_case_fold_attr_required(void * hUserData, + char *attr) { +// struct ldb_module * module = hUserData; + #warning "currently, all attributes require case folding" return TRUE; } @@ -184,9 +187,9 @@ static int lsqlite3_case_fold_attr_required(struct ldb_module *module, * rename a record */ static int -lsqlite3_rename(struct ldb_module *module, - const char *olddn, - const char *newdn) +lsqlite3_rename(struct ldb_module * module, + const char * olddn, + const char * newdn) { /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { @@ -478,7 +481,7 @@ lsqlite3_search(struct ldb_module * module, { int ret; int bLoop; - long long eid; + long long eid = 0; char * sql; char * sql_constraints; char * table_list; @@ -509,7 +512,7 @@ lsqlite3_search(struct ldb_module * module, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + NULL)) != SQLITE_OK) { ret = -1; break; } @@ -541,17 +544,24 @@ lsqlite3_search(struct ldb_module * module, * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. */ + sqlite3_free(discard_const_p(char, pTail)); ret = 0; bLoop = FALSE; } + if (ret != 0) { + sqlite3_free(discard_const_p(char, pTail)); + return -1; + } + /* Parse the filter expression into a tree we can work with */ if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { + sqlite3_free(discard_const_p(char, pTail)); return -1; } /* Allocate a temporary talloc context */ - hTalloc = talloc_new(module); + hTalloc = talloc_new(module->ldb); /* Move the parse tree to our temporary context */ talloc_steal(hTalloc, pTree); @@ -756,28 +766,20 @@ lsqlite3_new_dn(struct ldb_module * module, char * pDN, long long * pEID) { - char * pName; - char * pValue; - - /* Normalize the distinguished name */ - pDN = ldb_dn_fold(module, pDN, lsqlite3_case_fold_attr_required); - - /* Parse the DN into its constituent components */ -#warning "this simple parse of DN ignores escaped '=' and ','. fix it." - while (pDN != NULL) { - pName = strsep(&pValue, "="); - - if (pDN == NULL) { - /* Attribute name without value? Should not occur. */ - return -1; - } - - pValue = pName; - strsep(&pValue, "="); - -#warning "*** lsqlite3_new_dn() not yet fully implemented ***" + struct ldb_dn * pExplodedDN; + struct ldb_context * ldb = module->ldb; +// struct lsqlite3_private * lsqlite3 = module->private_data; + + /* Explode and normalize the DN */ + if ((pExplodedDN = + ldb_explode_dn(ldb, + pDN, + ldb, + lsqlite3_case_fold_attr_required)) == NULL) { + return -1; } +#warning "*** lsqlite3_new_dn() not yet fully implemented ***" return -1; } -- cgit From c96492a9dce25a1881e854ac7861a0b258ee1ae1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 9 Jun 2005 13:13:15 +0000 Subject: r7436: As far as I see it, these are the last two "real" ones for Samba4 on AIX to build. The remaining patch (not now) is to convert the javascript stuff not to use // style comments. Volker (This used to be commit 29f7e430ac4ae43f6844f021be73bf391610ef73) --- source4/lib/com/classes/simple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c index e4bf8d18e1..295f113207 100644 --- a/source4/lib/com/classes/simple.c +++ b/source4/lib/com/classes/simple.c @@ -86,7 +86,7 @@ static uint32_t simpleclass_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *me /* Everything below this line should be autogenerated later on */ static struct IClassFactory_vtable simple_classobject_vtable = { - {}, + { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } }, simpleclass_IUnknown_QueryInterface, simpleclass_IUnknown_AddRef, simpleclass_IUnknown_Release, @@ -97,7 +97,7 @@ static struct IClassFactory_vtable simple_classobject_vtable = { }; static struct IStream_vtable simple_IStream_vtable = { - {}, + { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } }, simple_IUnknown_QueryInterface, simple_IUnknown_AddRef, simple_IUnknown_Release, -- cgit From c63c28f5bd46e4a03e1cdd12b78934c0b88635a8 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 14:15:09 +0000 Subject: r7437: Make Simo happy. I still think this URI syntax for a 'protocol' which has no network component is stupid; it should just be sqlite:local_file or sqlite:/full/path/to/file but there is enough precedent to warrant the behavior that Simo wants that it is not worth arguing. (This used to be commit 61dcb462f30a65256e263e87c192ed7f5280c7af) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 4f774efbae..54f8903231 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1130,7 +1130,7 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, ; /* Skip protocol indicator of url */ - if ((p = strchr(url, ':')) == NULL) { + if (strncmp(url, "sqlite://", 9) != 0) { return SQLITE_MISUSE; } else { ++p; -- cgit From ee3f4b12d22459405372e1c72efe3079a052601d Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 14:50:32 +0000 Subject: r7438: work in progress (This used to be commit 2fc5343f0637ef3109b079dbc33d6cf4e58c8d5e) --- source4/lib/ldb/common/ldb_explode_dn.c | 66 ++---- source4/lib/ldb/config.mk | 5 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 323 ++++++++++++++---------------- source4/lib/ldb/tools/ldbsearch.c | 13 +- 4 files changed, 177 insertions(+), 230 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index d3f278c776..e3cd53d047 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -21,6 +21,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_explode_dn.h" #define LDB_PARSE_DN_INVALID(x) do { \ @@ -34,10 +35,6 @@ * Forward declarations */ -static char -octet_from_hex(char * p, - char * ret); - static char * parse_slash(char *p, char *end); @@ -388,13 +385,14 @@ ldb_explode_dn(void * mem_ctx, /* copy each of the attributes to the normalized component */ for (i = 0; i < component->attr_num; i++) { if (i != 0) { - *dest = '+'; - dest++; + *dest++ = '+'; } src = component->attributes[i]->rdn; /* we are guaranteed to have enough space in dest */ - strcpy(dest, src); + size = strlen(src); + strncpy(dest, src, size + 1); + dest += size; } ldb_debug(mem_ctx, @@ -449,7 +447,9 @@ ldb_explode_dn(void * mem_ctx, src = dn->components[i]->component; /* we are guaranteed to have enough space in dest */ - strcpy(dest, src); + size = strlen(src); + strncpy(dest, src, size + 1); + dest += size; } ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); @@ -468,47 +468,6 @@ failed: } -static char -octet_from_hex(char * p, - char * ret) -{ - unsigned char low_char; - unsigned char high_char; - - unsigned char low_binary; - unsigned char high_binary; - - if (p[0] == '\0' || p[1] == '\0') { - return -1; - } - - high_char = p[0]; - low_char = p[1]; - - if (high_char >= '0' && high_char <= '9') { - high_binary = high_char - '0'; - } else if (high_char >= 'A' && high_char <= 'F') { - high_binary = 10 + (high_char - 'A'); - } else if (high_char >= 'a' && high_char <= 'f') { - high_binary = 10 + (high_char - 'a'); - } else { - return -1; - } - - if (low_char >= '0' && low_char <= '9') { - low_binary = low_char - '0'; - } else if (low_char >= 'A' && low_char <= 'F') { - low_binary = 10 + (low_char - 'A'); - } else if (low_char >= 'a' && low_char <= 'f') { - low_binary = 10 + (low_char - 'a'); - } else { - return -1; - } - - *ret = (char) ((high_binary << 4) | low_binary); - return 0; -} - static char * parse_slash(char *p, char *end) @@ -528,10 +487,11 @@ parse_slash(char *p, return (end - 1); default: - if (*(p + 1) != '\0' && *(p + 2) != '\0') { - if (octet_from_hex(p + 1, p) < 0) { - return NULL; - } + if (isxdigit(p[1]) && isxdigit(p[2])) { + int x; + + sscanf(p + 1, "%02x", &x); + *p = (char) x; memmove(p + 1, p + 3, end - (p + 3)); return (end - 2); } else { diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 03a3a401fb..03855017ba 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -25,7 +25,7 @@ INIT_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ EXT_LIB_LDAP NOPROTO = YES -# End MODULE libldb_tdb +# End MODULE libldb_ldap ################################################ ################################################ @@ -70,7 +70,8 @@ ADD_OBJ_FILES = \ lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_debug.o \ - lib/ldb/common/ldb_modules.o + lib/ldb/common/ldb_modules.o \ + lib/ldb/common/ldb_explode_dn.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE LIBTALLOC NOPROTO = YES diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 54f8903231..c0e3963743 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -56,6 +56,16 @@ } \ } while (0) +#define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \ + do { \ + if (lsqlite3_query_int(lsqlite3, &result_var, sql) != 0) { \ + if (bRollbackOnError) { \ + lsqlite3_query_norows(lsqlite3, \ + "ROLLBACK;"); \ + } \ + return -1; \ + } \ + } while (0) /* * lsqlite3_query_norows() @@ -140,6 +150,94 @@ lsqlite3_query_norows(const struct lsqlite3_private *lsqlite3, } +/* + * lsqlite3_query_int() + * + * This function is used for the common case of queries that return a single + * integer value. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. + */ +static int +lsqlite3_query_int(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pSql, + ...) +{ + int ret; + int bLoop; + char * p; + const char * pTail; + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); + + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + return -1; + } + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* No rows expected, so just step through machine code once */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(pStmt, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } + + /* All done with variable argument list */ + va_end(args); + + /* Free the memory we allocated for our query string */ + sqlite3_free(p); + + return ret; +} + + #if 0 /* * we don't need this right now, but will once we add some backend options @@ -479,15 +577,11 @@ lsqlite3_search(struct ldb_module * module, const char * const attrs[], struct ldb_message *** res) { - int ret; - int bLoop; long long eid = 0; char * sql; char * sql_constraints; char * table_list; char * hTalloc; - const char * pTail; - sqlite3_stmt * pStmt; struct ldb_parse_tree * pTree; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -495,68 +589,22 @@ lsqlite3_search(struct ldb_module * module, pBaseDN = ""; } + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); + /* * Obtain the eid of the base DN */ - if ((pTail = sqlite3_mprintf("SELECT eid " - " FROM ldb_attr_dn " - " WHERE attr_value = %Q;", - pBaseDN)) == NULL) { - return -1; - } - - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, - -1, - &pStmt, - NULL)) != SQLITE_OK) { - ret = -1; - break; - } - - /* One row expected */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_ROW) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Retrieve the EID */ - eid = sqlite3_column_int64(pStmt, 0); - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - sqlite3_free(discard_const_p(char, pTail)); - ret = 0; - bLoop = FALSE; - } - - if (ret != 0) { - sqlite3_free(discard_const_p(char, pTail)); - return -1; - } + QUERY_INT(lsqlite3, + eid, + TRUE, + "SELECT eid " + " FROM ldb_attr_dn " + " WHERE attr_value = %Q;", + pBaseDN); /* Parse the filter expression into a tree we can work with */ if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { - sqlite3_free(discard_const_p(char, pTail)); return -1; } @@ -628,7 +676,12 @@ lsqlite3_search(struct ldb_module * module, break; } - return ret; +#warning "retrieve and return the result set of the search here" + + /* End the transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); + + return 0; } @@ -830,12 +883,6 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { - int ret; - int bLoop; - char * p; - const char * pTail; - long long eid; - sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -846,72 +893,6 @@ lsqlite3_modify(struct ldb_module *module, /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - /* Format the query */ - if ((p = sqlite3_mprintf( - "SELECT eid " - " FROM ldb_entry " - " WHERE dn = %Q;", - ldb_dn_fold(module, - msg->dn, - lsqlite3_case_fold_attr_required))) == NULL) { - return -1; - } - - /* Get the id of this DN. */ - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, - -1, - &pStmt, - &pTail)) != SQLITE_OK) { - ret = -1; - break; - } - - /* One row expected */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_ROW) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Retrieve the EID */ - eid = sqlite3_column_int64(pStmt, 0); - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Modify attributes as specified */ - if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); - return -1; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } - - if (ret != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); - return -1; - } - /* Everything worked. Commit it! */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0 ; @@ -982,10 +963,9 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, const char *url) { int ret; - int bNewDatabase = FALSE; - char * p; + const char * p; + long long queryInt; const char * pTail; - struct stat statbuf; sqlite3_stmt * stmt; const char * schema = "-- ------------------------------------------------------" @@ -1133,25 +1113,29 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, if (strncmp(url, "sqlite://", 9) != 0) { return SQLITE_MISUSE; } else { - ++p; + p = url + 9; } /* * See if we'll be creating a new database, or opening an existing one */ -#warning "eliminate stat() here; concurrent processes could conflict" - if ((stat(p, &statbuf) < 0 && errno == ENOENT) || - statbuf.st_size == 0) { - - bNewDatabase = TRUE; - } - /* Try to open the (possibly empty/non-existent) database */ if ((ret = sqlite3_open(p, &lsqlite3->sqlite)) != SQLITE_OK) { return ret; } - if (bNewDatabase) { + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + + /* Determine if this is a new database */ + QUERY_INT(lsqlite3, + queryInt, + TRUE, + "SELECT COUNT(*) " + " FROM sqlite_master " + " WHERE type = 'table';"); + + if (queryInt == 0) { /* * Create the database schema */ @@ -1174,35 +1158,26 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3, /* * Ensure that the database we opened is one of ours */ - if ((ret = sqlite3_prepare( - lsqlite3->sqlite, - "SELECT COUNT(*) " - " FROM sqlite_master " - " WHERE type = 'table' " - " AND name IN " - " (" - " 'ldb_entry', " - " 'ldb_descendants', " - " 'ldb_object_classes' " - " );", - -1, - &stmt, - &pTail)) != SQLITE_OK || - (ret = sqlite3_step(stmt)) != SQLITE_ROW || - sqlite3_column_int(stmt, 0) != 3 || - (ret = sqlite3_finalize(stmt)) != SQLITE_OK || - - (ret = sqlite3_prepare( - lsqlite3->sqlite, - "SELECT 1 " - " FROM ldb_info " - " WHERE database_type = 'LDB' " - " AND version = '1.0';", - -1, - &stmt, - &pTail)) != SQLITE_OK || - (ret = sqlite3_step(stmt)) != SQLITE_ROW || - (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { + if (lsqlite3_query_int(lsqlite3, + &queryInt, + "SELECT " + " (SELECT COUNT(*) = 3" + " FROM sqlite_master " + " WHERE type = 'table' " + " AND name IN " + " (" + " 'ldb_entry', " + " 'ldb_descendants', " + " 'ldb_object_classes' " + " ) " + " ) " + " AND " + " (SELECT 1 " + " FROM ldb_info " + " WHERE database_type = 'LDB' " + " AND version = '1.0'" + " );") != 0 || + queryInt != 1) { /* It's not one that we created. See ya! */ (void) sqlite3_close(lsqlite3->sqlite); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 26bd198d1d..4bf9db8d90 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -54,6 +54,12 @@ static void usage(void) exit(1); } +static int do_compare_msg(struct ldb_message **el1, + struct ldb_message **el2) +{ + return ldb_dn_cmp((*el1)->dn, (*el2)->dn); +} + static int do_search(struct ldb_context *ldb, const char *basedn, int scope, @@ -72,6 +78,11 @@ static int do_search(struct ldb_context *ldb, printf("# returned %d records\n", ret); + if (sort_attribs) { + qsort(msgs, ret, sizeof(struct ldb_message *), + (comparison_fn_t)do_compare_msg); + } + for (i=0;i Date: Thu, 9 Jun 2005 15:51:36 +0000 Subject: r7441: Get rid of // comments. Tridge, if this breaks anything, please revert it. More tomorrow Volker (This used to be commit 02efa4427d80aa1e9a8f0275c568d977faa0f9b8) --- source4/lib/ejs/config.h | 10 -- source4/lib/ejs/miniMpr.h | 150 ++++++++++++++-------------- source4/lib/ejs/mprOs.h | 246 +++++++++++++++++++++++----------------------- source4/lib/ejs/var.c | 12 +-- source4/lib/ejs/var.h | 28 +++--- 5 files changed, 218 insertions(+), 228 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/config.h b/source4/lib/ejs/config.h index ec350890df..cf75d48270 100644 --- a/source4/lib/ejs/config.h +++ b/source4/lib/ejs/config.h @@ -1,13 +1,3 @@ -// -// config.h -- Build configuration file. -// -// WARNING: DO NOT EDIT. This file is generated by configure. -// -// If you wish to modify the defaults, then edit conf/config.defaults.* and -// then run "configure --reset". -// -//////////////////////////////////////////////////////////////////////////////// - #define BLD_PRODUCT "Samba4" #define BLD_NAME "Samba4 SWAT" #define BLD_VERSION "4" diff --git a/source4/lib/ejs/miniMpr.h b/source4/lib/ejs/miniMpr.h index b74c734728..3bbd63a302 100644 --- a/source4/lib/ejs/miniMpr.h +++ b/source4/lib/ejs/miniMpr.h @@ -82,18 +82,18 @@ extern "C" { #endif #if BLD_FEATURE_SQUEEZE -/// -/// Reasonable length of a file path name to use in most cases where you know -/// the expected file name and it is certain to be less than this limit. -/// +/* + * Reasonable length of a file path name to use in most cases where you know + * the expected file name and it is certain to be less than this limit. + */ #define MPR_MAX_FNAME 128 #define MPR_MAX_STRING 512 -#define MPR_DEFAULT_HASH_SIZE 23 // Default size of hash table index +#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ #define MPR_MAX_HEAP_SIZE (32 * 1024) #else #define MPR_MAX_FNAME 256 #define MPR_MAX_STRING 4096 -#define MPR_DEFAULT_HASH_SIZE 43 // Default size of hash table index +#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ #define MPR_MAX_HEAP_SIZE (64 * 1024) #endif @@ -109,74 +109,74 @@ extern "C" { #define mprAssert(C) if (1) ; else #endif -/// -/// Standard MPR return and error codes -/// -#define MPR_ERR_BASE (-200) ///< Error code -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) ///< Error code -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) ///< Error code -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) ///< Error code -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) ///< Error code -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) ///< Error code -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) ///< Error code -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) ///< Error code -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) ///< Error code -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) ///< Error code -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) ///< Error code -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) ///< Error code -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) ///< Error code -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) ///< Error code -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) ///< Error code -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) ///< Error code -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) ///< Error code -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) ///< Error code -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) ///< Error code -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) ///< Error code -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) ///< Error code -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) ///< Error code -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) ///< Error code -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) ///< Error code -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) ///< Error code -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) ///< Error code -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) ///< Error code -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) ///< Error code -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) ///< Error code -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) ///< Error code -#define MPR_ERR_MAX (MPR_ERR_BASE - 30) ///< Error code - -// -// Standard error severity and trace levels. These are ored with the error -// severities below. The MPR_LOG_MASK is used to extract the trace level -// from a flags word. We expect most apps to run with level 2 trace. -// -#define MPR_FATAL 0 ///< Fatal error. Cant continue. -#define MPR_ERROR 1 ///< Hard error -#define MPR_WARN 2 ///< Soft warning -#define MPR_CONFIG 2 ///< Essential configuration settings -#define MPR_INFO 3 ///< Informational only -#define MPR_DEBUG 4 ///< Debug information -#define MPR_VERBOSE 9 ///< Highest level of trace -#define MPR_LOG_MASK 0xf ///< Level mask - -// -// Error flags. Specify where the error should be sent to. Note that the -// product.xml setting "headless" will modify how errors are reported. -// Assert errors are trapped when in DEV mode. Otherwise ignored. -// -#define MPR_TRAP 0x10 ///< Assert error -- trap in debugger -#define MPR_LOG 0x20 ///< Log the error in the O/S event log -#define MPR_USER 0x40 ///< Display to the user -#define MPR_ALERT 0x80 ///< Send a management alert -#define MPR_TRACE 0x100 ///< Trace - -// -// Error format flags -// -#define MPR_RAW 0x200 // Raw trace output - -// -// Error line number information -// +/* + * Standard MPR return and error codes + */ +#define MPR_ERR_BASE (-200) /* Error code */ +#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ +#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ +#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ +#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ +#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ +#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ +#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ +#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ +#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ +#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ +#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ +#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ +#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ +#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ +#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ +#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ +#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ +#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ +#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ +#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ +#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ +#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ +#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ +#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ +#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ +#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ +#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ +#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ +#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ +#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ + +/* + * Standard error severity and trace levels. These are ored with the error + * severities below. The MPR_LOG_MASK is used to extract the trace level + * from a flags word. We expect most apps to run with level 2 trace. + */ +#define MPR_FATAL 0 /* Fatal error. Cant continue. */ +#define MPR_ERROR 1 /* Hard error */ +#define MPR_WARN 2 /* Soft warning */ +#define MPR_CONFIG 2 /* Essential configuration settings */ +#define MPR_INFO 3 /* Informational only */ +#define MPR_DEBUG 4 /* Debug information */ +#define MPR_VERBOSE 9 /* Highest level of trace */ +#define MPR_LOG_MASK 0xf /* Level mask */ + +/* + * Error flags. Specify where the error should be sent to. Note that the + * product.xml setting "headless" will modify how errors are reported. + * Assert errors are trapped when in DEV mode. Otherwise ignored. + */ +#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ +#define MPR_LOG 0x20 /* Log the error in the O/S event log */ +#define MPR_USER 0x40 /* Display to the user */ +#define MPR_ALERT 0x80 /* Send a management alert */ +#define MPR_TRACE 0x100 /* Trace */ + +/* + * Error format flags + */ +#define MPR_RAW 0x200 /* Raw trace output */ + +/* + * Error line number information + */ #define MPR_L __FILE__, __LINE__ typedef char* MprStr; @@ -242,7 +242,7 @@ typedef struct { error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) #else /* !BLD_GOAHEAD_WEBSERVER */ -//#define mprMalloc malloc +/* #define mprMalloc malloc */ #define mprSprintf snprintf #define mtVsprintf vsnprintf extern void *mprMalloc(uint size); diff --git a/source4/lib/ejs/mprOs.h b/source4/lib/ejs/mprOs.h index c88a3e3c43..6a6d0b4205 100644 --- a/source4/lib/ejs/mprOs.h +++ b/source4/lib/ejs/mprOs.h @@ -1,39 +1,39 @@ -/// -/// @file mprOs.h -/// @brief Include O/S headers and smooth out per-O/S differences -// @copy default -// -// Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. -// -// This software is distributed under commercial and open source licenses. -// You may use the GPL open source license described below or you may acquire -// a commercial license from Mbedthis Software. You agree to be fully bound -// by the terms of either license. Consult the LICENSE.TXT distributed with -// this software for full details. -// -// This software is open source; 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 (at your -// option) any later version. See the GNU General Public License for more -// details at: http://www.mbedthis.com/downloads/gplLicense.html -// -// This program is distributed WITHOUT ANY WARRANTY; without even the -// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// -// This GPL license does NOT permit incorporating this software into -// proprietary programs. If you are unable to comply with the GPL, you must -// acquire a commercial license to use this software. Commercial licenses -// for this software and support services are available from Mbedthis -// Software at http://www.mbedthis.com -// -// @end -//////////////////////////////// Documentation ///////////////////////////////// -/// -/// This header is part of the Mbedthis Portable Runtime and aims to include -/// all necessary O/S headers and to unify the constants and declarations -/// required by Mbedthis products. It can be included by C or C++ programs. -/// -//////////////////////////////////////////////////////////////////////////////// +/* + * @file mprOs.h + * @brief Include O/S headers and smooth out per-O/S differences + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + ******************************* Documentation ********************************* + * + * This header is part of the Mbedthis Portable Runtime and aims to include + * all necessary O/S headers and to unify the constants and declarations + * required by Mbedthis products. It can be included by C or C++ programs. + * + ********************************************************************************/ #error foo @@ -44,10 +44,10 @@ blah blah; #include "lib/ejs/config.h" -////////////////////////////////// CPU Families //////////////////////////////// -// -// Porters, add your CPU families here and update configure code. -// +/********************************* CPU Families *********************************/ +/* + * Porters, add your CPU families here and update configure code. + */ #define MPR_CPU_UNKNOWN 0 #define MPR_CPU_IX86 1 #define MPR_CPU_PPC 2 @@ -56,10 +56,10 @@ blah blah; #define MPR_CPU_ARM 5 #define MPR_CPU_MIPS 6 #define MPR_CPU_68K 7 -#define MPR_CPU_SIMNT 8 // VxWorks NT simulator -#define MPR_CPU_SIMSPARC 9 // VxWorks sparc simulator +#define MPR_CPU_SIMNT 8 /* VxWorks NT simulator */ +#define MPR_CPU_SIMSPARC 9 /* VxWorks sparc simulator */ -////////////////////////////////// O/S Includes //////////////////////////////// +/********************************* O/S Includes *********************************/ #if LINUX || SOLARIS #include @@ -114,7 +114,7 @@ blah blah; #include #endif -#endif // LINUX || SOLARIS +#endif /* LINUX || SOLARIS */ #if VXWORKS #include @@ -162,7 +162,7 @@ blah blah; #include #include -#endif // VXWORKS +#endif /* VXWORKS */ #if MACOSX #include @@ -205,7 +205,7 @@ blah blah; #include #include #include -#endif // MACOSX +#endif /* MACOSX */ #if WIN #include @@ -235,15 +235,15 @@ blah blah; #include #include #include -#endif // WIN +#endif /* WIN */ #ifdef __cplusplus extern "C" { #endif -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// General Defines /////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/******************************* General Defines ********************************/ +/********************************************************************************/ #define MAXINT INT_MAX #define BITS(type) (BITSPERBYTE * (int) sizeof(type)) @@ -256,21 +256,21 @@ extern "C" { #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif -// -// Set FD_SETSIZE to the maximum number of files (sockets) that you want to -// support. It is used in select.cpp. -// -// #ifdef FD_SETSIZE -// #undef FD_SETSIZE -// #endif -// #define FD_SETSIZE 128 -// +/* + * Set FD_SETSIZE to the maximum number of files (sockets) that you want to + * support. It is used in select.cpp. + * + * #ifdef FD_SETSIZE + * #undef FD_SETSIZE + * #endif + * #define FD_SETSIZE 128 + */ -typedef char *MprStr; // Used for dynamic strings +typedef char *MprStr; /* Used for dynamic strings */ -//////////////////////////////////////////////////////////////////////////////// -///////////////////////////////// Linux Defines //////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/*******************************/ Linux Defines *********************************/ +/********************************************************************************/ #if LINUX typedef unsigned char uchar; @@ -294,10 +294,10 @@ typedef char *MprStr; // Used for dynamic strings #endif #if BLD_FEATURE_MALLOC - // - // PORTERS: You will need add assembler code for your architecture here - // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - // + /* + * PORTERS: You will need add assembler code for your architecture here + * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + */ #if UNUSED #define MPR_GET_RETURN(ip) __builtin_return_address(0) #else @@ -307,16 +307,16 @@ typedef char *MprStr; // Used for dynamic strings "=g" (ip) : \ : "eax") #endif - #endif // UNUSED - #endif // BLD_FEATURE_MALLOC +#endif /* UNUSED */ +#endif /* BLD_FEATURE_MALLOC */ #if FUTURE -// #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) -// extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); +/* #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) */ +/* extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); */ - // - // Atomic functions - // + /* */ + /* Atomic functions */ + /* */ typedef struct { volatile int counter; } mprAtomic_t; #if BLD_FEATURE_MULTITHREAD @@ -338,13 +338,13 @@ typedef char *MprStr; // Used for dynamic strings :"=m" (v->counter) :"m" (v->counter)); } -#endif // FUTURE +#endif /* FUTURE */ -#endif // LINUX +#endif /* LINUX */ -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// VxWorks Defines /////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/******************************* VxWorks Defines ********************************/ +/********************************************************************************/ #if VXWORKS @@ -389,10 +389,10 @@ typedef char *MprStr; // Used for dynamic strings extern int sysClkRateGet(); #if BLD_FEATURE_MALLOC - // - // PORTERS: You will need add assembler code for your architecture here - // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - // + /* + * PORTERS: You will need add assembler code for your architecture here + * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + */ #if UNUSED #define MPR_GET_RETURN(ip) __builtin_return_address(0) #else @@ -402,13 +402,13 @@ typedef char *MprStr; // Used for dynamic strings "=g" (ip) : \ : "eax") #endif - #endif // UNUSED - #endif // BLD_FEATURE_MALLOC -#endif // VXWORKS +#endif /* UNUSED */ +#endif /* BLD_FEATURE_MALLOC */ +#endif /* VXWORKS */ -//////////////////////////////////////////////////////////////////////////////// -///////////////////////////////// MacOsx Defines /////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/******************************** MacOsx Defines ********************************/ +/********************************************************************************/ #if MACOSX typedef unsigned long ulong; typedef unsigned char uchar; @@ -434,20 +434,20 @@ typedef char *MprStr; // Used for dynamic strings #endif #if MPR_FEATURE_MALLOC - // - // PORTERS: You will need add assembler code for your architecture here - // only if you want to use the fast malloc (MPR_FEATURE_MALLOC) - // + /* + * PORTERS: You will need add assembler code for your architecture here + * only if you want to use the fast malloc (MPR_FEATURE_MALLOC) + */ #define MPR_GET_RETURN(ip) __builtin_return_address #endif #if FUTURE -// #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) -// extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); +/* #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) */ +/* extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); */ - // - // Atomic functions - // + /* */ + /* Atomic functions */ + /* */ typedef struct { volatile int counter; } mprAtomic_t; #if MPR_FEATURE_MULTITHREAD @@ -470,11 +470,11 @@ typedef char *MprStr; // Used for dynamic strings :"m" (v->counter)); } #endif -#endif // MACOSX +#endif /* MACOSX */ -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// Windows Defines /////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/******************************* Windows Defines ********************************/ +/********************************************************************************/ #if WIN typedef unsigned char uchar; @@ -555,10 +555,10 @@ typedef char *MprStr; // Used for dynamic strings #define rmdir(a) _rmdir(a) #if BLD_FEATURE_MALLOC - // - // PORTERS: You will need add assembler code for your architecture here - // only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - // + /* + * PORTERS: You will need add assembler code for your architecture here + * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) + */ #if MPR_CPU_IX86 #define MPR_GET_RETURN(ip) \ __asm { mov eax, 4[ebp] } \ @@ -576,11 +576,11 @@ typedef char *MprStr; // Used for dynamic strings extern uid_t getuid(void); extern uid_t geteuid(void); -#endif // WIN +#endif /* WIN */ -//////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// Solaris Defines //////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ +/*****************************/ Solaris Defines *********************************/ +/********************************************************************************/ #if SOLARIS typedef unsigned char uchar; @@ -607,21 +607,21 @@ typedef char *MprStr; // Used for dynamic strings #define MAX_FLOAT MAXFLOAT #endif -#endif // SOLARIS +#endif /* SOLARIS */ -//////////////////////////////////////////////////////////////////////////////// +/********************************************************************************/ #ifdef __cplusplus } #endif -#endif // _h_MPR_OS_HDRS - -// -// Local variables: -// tab-width: 4 -// c-basic-offset: 4 -// End: -// vim:tw=78 -// vim600: sw=4 ts=4 fdm=marker -// vim<600: sw=4 ts=4 -// +#endif /* _h_MPR_OS_HDRS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 5df306797d..ce771caa04 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -376,7 +376,7 @@ MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, MprVar *newValu } if (prop) { - // FUTURE -- remove. Just for debug. + /* FUTURE -- remove. Just for debug. */ mprAssert(prop == 0); mprLog(0, "Attempting to create property %s in object %s\n", propertyName, obj->name); @@ -1589,7 +1589,7 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) switch (obj->type) { case MPR_TYPE_UNDEFINED: - // FUTURE -- spec says convert to "undefined" + /* FUTURE -- spec says convert to "undefined" */ *out = mprStrdup(""); break; @@ -1650,7 +1650,7 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) break; case MPR_TYPE_OBJECT: - // FUTURE -- really want: [object class: name] + /* FUTURE -- really want: [object class: name] */ mprAllocSprintf(out, size, "[object %s]", obj->name); break; @@ -2127,7 +2127,7 @@ bool mprIsNan(double f) #if WIN return _isnan(f); #elif VXWORKS - // FUTURE + /* FUTURE */ return (0); #else return (f == FP_NAN); @@ -2140,14 +2140,14 @@ bool mprIsInfinite(double f) #if WIN return !_finite(f); #elif VXWORKS - // FUTURE + /* FUTURE */ return (0); #else return (f == FP_INFINITE); #endif } -#endif // BLD_FEATURE_FLOATING_POINT +#endif /* BLD_FEATURE_FLOATING_POINT */ /******************************************************************************/ /* diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h index 1f9ab65aa7..3cb23cf461 100644 --- a/source4/lib/ejs/var.h +++ b/source4/lib/ejs/var.h @@ -81,17 +81,17 @@ struct MprVar; * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. */ typedef int MprType; -#define MPR_TYPE_UNDEFINED 0 ///< Undefined. No value has been set. -#define MPR_TYPE_NULL 1 ///< Value defined to be null. -#define MPR_TYPE_BOOL 2 ///< Boolean type. -#define MPR_TYPE_CFUNCTION 3 ///< C function or C++ method -#define MPR_TYPE_FLOAT 4 ///< Floating point number -#define MPR_TYPE_INT 5 ///< Integer number -#define MPR_TYPE_INT64 6 ///< 64-bit Integer number -#define MPR_TYPE_OBJECT 7 ///< Object reference -#define MPR_TYPE_FUNCTION 8 ///< JavaScript function -#define MPR_TYPE_STRING 9 ///< String (immutable) -#define MPR_TYPE_STRING_CFUNCTION 10 ///< C/C++ function with string args +#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ +#define MPR_TYPE_NULL 1 /* Value defined to be null. */ +#define MPR_TYPE_BOOL 2 /* Boolean type. */ +#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ +#define MPR_TYPE_FLOAT 4 /* Floating point number */ +#define MPR_TYPE_INT 5 /* Integer number */ +#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ +#define MPR_TYPE_OBJECT 7 /* Object reference */ +#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ +#define MPR_TYPE_STRING 9 /* String (immutable) */ +#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ /* * Create a type for the default number type @@ -324,15 +324,15 @@ typedef struct MprVar { * Define a field macro so code an use numbers in a "generic" fashion. */ #if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN -//* Default numeric type */ +/* Default numeric type */ #define mprNumber integer #endif #if MPR_NUM_VAR == MPR_TYPE_INT64 -//* Default numeric type */ +/* Default numeric type */ #define mprNumber integer64 #endif #if MPR_NUM_VAR == MPR_TYPE_FLOAT -//* Default numeric type */ +/* Default numeric type */ #define mprNumber floating #endif -- cgit From b501bf17ab89b0838cdd13d67f2e16fcc881e59d Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 17:16:49 +0000 Subject: r7443: reorg functions for readability (This used to be commit 7543acfa9fe87b43cfee482cf02e56d73d29596b) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 2061 +++++++++++++++-------------- 1 file changed, 1059 insertions(+), 1002 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index c0e3963743..c16708672d 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -40,6 +40,10 @@ #include "ldb/include/ldb_explode_dn.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" +/* + * Macros used throughout + */ + #ifndef FALSE # define FALSE (0) # define TRUE (! FALSE) @@ -47,9 +51,9 @@ #define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ do { \ - if (lsqlite3_query_norows(lsqlite3, sql) != 0) { \ + if (query_norows(lsqlite3, sql) != 0) { \ if (bRollbackOnError) { \ - lsqlite3_query_norows(lsqlite3, \ + query_norows(lsqlite3, \ "ROLLBACK;"); \ } \ return -1; \ @@ -58,899 +62,689 @@ #define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \ do { \ - if (lsqlite3_query_int(lsqlite3, &result_var, sql) != 0) { \ + if (query_int(lsqlite3, &result_var, sql) != 0) { \ if (bRollbackOnError) { \ - lsqlite3_query_norows(lsqlite3, \ + query_norows(lsqlite3, \ "ROLLBACK;"); \ } \ return -1; \ } \ } while (0) + /* - * lsqlite3_query_norows() - * - * This function is used for queries that are not expected to return any rows, - * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. - * There are no provisions here for returning data from rows in a table, so do - * not pass SELECT queries to this function. + * Forward declarations */ static int -lsqlite3_query_norows(const struct lsqlite3_private *lsqlite3, - const char *pSql, - ...) -{ - int ret; - int bLoop; - char * p; - const char * pTail; - sqlite3_stmt * pStmt; - va_list args; - - /* Begin access to variable argument list */ - va_start(args, pSql); - - /* Format the query */ - if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return -1; - } - - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { +lsqlite3_rename(struct ldb_module * module, + const char * olddn, + const char * newdn); - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, - -1, - &pStmt, - &pTail)) != SQLITE_OK) { - ret = -1; - break; - } - - /* No rows expected, so just step through machine code once */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_DONE) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } +static int +lsqlite3_delete(struct ldb_module *module, + const char *dn); - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } +static int +lsqlite3_search(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + const char * pExpression, + const char * const attrs[], + struct ldb_message *** res); - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } +static int +lsqlite3_add(struct ldb_module *module, + const struct ldb_message *msg); - /* All done with variable argument list */ - va_end(args); +static int +lsqlite3_modify(struct ldb_module *module, + const struct ldb_message *msg); - /* Free the memory we allocated for our query string */ - sqlite3_free(p); +static int +lsqlite3_lock(struct ldb_module *module, + const char *lockname); - return ret; -} +static int +lsqlite3_unlock(struct ldb_module *module, + const char *lockname); +static const char * +lsqlite3_errstring(struct ldb_module *module); -/* - * lsqlite3_query_int() - * - * This function is used for the common case of queries that return a single - * integer value. - * - * NOTE: If more than one value is returned by the query, all but the first - * one will be ignored. - */ static int -lsqlite3_query_int(const struct lsqlite3_private * lsqlite3, - long long * pRet, - const char * pSql, - ...) -{ - int ret; - int bLoop; - char * p; - const char * pTail; - sqlite3_stmt * pStmt; - va_list args; - - /* Begin access to variable argument list */ - va_start(args, pSql); +initialize(struct lsqlite3_private *lsqlite3, + const char *url); - /* Format the query */ - if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return -1; - } +static int +destructor(void *p); - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { +static int +query_norows(const struct lsqlite3_private *lsqlite3, + const char *pSql, + ...); - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, - -1, - &pStmt, - &pTail)) != SQLITE_OK) { - ret = -1; - break; - } - - /* No rows expected, so just step through machine code once */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_ROW) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } +static int +query_int(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pSql, + ...); - /* Get the value to be returned */ - *pRet = sqlite3_column_int64(pStmt, 0); +static int case_fold_attr_required(void * hUserData, + char *attr); - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } +static char * +parsetree_to_sql(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t); - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } +static char * +parsetree_to_tablelist(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t); - /* All done with variable argument list */ - va_end(args); +static int +new_attr(struct ldb_module * module, + char * pAttrName); - /* Free the memory we allocated for our query string */ - sqlite3_free(p); +static int +msg_to_sql(struct ldb_module * module, + const struct ldb_message * msg, + long long eid, + int use_flags); - return ret; -} +static int +new_dn(struct ldb_module * module, + char * pDN, + long long * pEID); -#if 0 /* - * we don't need this right now, but will once we add some backend options - * - * find an option in an option list (a null terminated list of strings) - * - * this assumes the list is short. If it ever gets long then we really should - * do this in some smarter way + * Table of operations for the sqlite3 backend */ -static const char * -lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, - const char *name) -{ - int i; - size_t len = strlen(name); +static const struct ldb_module_ops lsqlite3_ops = { + "sqlite", + lsqlite3_search, + lsqlite3_add, + lsqlite3_modify, + lsqlite3_delete, + lsqlite3_rename, + lsqlite3_lock, + lsqlite3_unlock, + lsqlite3_errstring +}; - if (!lsqlite3->options) return NULL; - for (i=0;lsqlite3->options[i];i++) { - if (strncmp(lsqlite3->options[i], name, len) == 0 && - lsqlite3->options[i][len] == '=') { - return &lsqlite3->options[i][len+1]; - } - } - return NULL; -} -#endif /* - callback function used in call to ldb_dn_fold() for determining whether an - attribute type requires case folding. -*/ -static int lsqlite3_case_fold_attr_required(void * hUserData, - char *attr) -{ -// struct ldb_module * module = hUserData; - -#warning "currently, all attributes require case folding" - return TRUE; -} + * Public functions + */ /* - * rename a record + * connect to the database */ -static int -lsqlite3_rename(struct ldb_module * module, - const char * olddn, - const char * newdn) +struct ldb_context * +lsqlite3_connect(const char *url, + unsigned int flags, + const char *options[]) { - /* ignore ltdb specials */ - if (olddn[0] == '@' ||newdn[0] == '@') { - return 0; - } + int i; + int ret; + struct ldb_context * ldb = NULL; + struct lsqlite3_private * lsqlite3 = NULL; -#warning "lsqlite3_rename() is not yet supported" - return -1; -} + ldb = talloc(NULL, struct ldb_context); + if (!ldb) { + errno = ENOMEM; + goto failed; + } -/* - * delete a record - */ -static int -lsqlite3_delete(struct ldb_module *module, - const char *dn) -{ - /* ignore ltdb specials */ - if (dn[0] == '@') { - return 0; + lsqlite3 = talloc(ldb, struct lsqlite3_private); + if (!lsqlite3) { + errno = ENOMEM; + goto failed; } - - return -1; -} -#if 0 /* not currently used */ -/* - * free a search result - */ -static int -lsqlite3_search_free(struct ldb_module *module, - struct ldb_message **res) -{ - talloc_free(res); - return 0; -} -#endif + lsqlite3->sqlite = NULL; + lsqlite3->options = NULL; + lsqlite3->lock_count = 0; + + ret = initialize(lsqlite3, url); + if (ret != SQLITE_OK) { + goto failed; + } + + talloc_set_destructor(lsqlite3, destructor); + + ldb->modules = talloc(ldb, struct ldb_module); + if (!ldb->modules) { + errno = ENOMEM; + goto failed; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = lsqlite3; + ldb->modules->ops = &lsqlite3_ops; + + if (options) { + /* + * take a copy of the options array, so we don't have to rely + * on the caller keeping it around (it might be dynamic) + */ + for (i=0;options[i];i++) ; + + lsqlite3->options = talloc_array(lsqlite3, char *, i+1); + if (!lsqlite3->options) { + goto failed; + } + + for (i=0;options[i];i++) { + + lsqlite3->options[i+1] = NULL; + lsqlite3->options[i] = + talloc_strdup(lsqlite3->options, options[i]); + if (!lsqlite3->options[i]) { + goto failed; + } + } + } + + return ldb; + +failed: + if (lsqlite3->sqlite != NULL) { + (void) sqlite3_close(lsqlite3->sqlite); + } + talloc_free(ldb); + return NULL; +} /* - * add a single set of ldap message values to a ldb_message + * Interface functions referenced by lsqlite3_ops */ -/* get things to compile before we actually implement this function */ -struct berval -{ - int x; -}; - -#warning "lsqlite3_add_msg_attr() not yet implemented or used" -#if 0 +/* rename a record */ static int -lsqlite3_add_msg_attr(struct ldb_context *ldb, - struct ldb_message *msg, - const char *attr, - struct berval **bval) +lsqlite3_rename(struct ldb_module * module, + const char * olddn, + const char * newdn) { - int i; - int count; - struct ldb_message_element * el; + /* ignore ltdb specials */ + if (olddn[0] == '@' ||newdn[0] == '@') { + return 0; + } - count = ldap_count_values_len(bval); +#warning "lsqlite3_rename() is not yet supported" + return -1; +} - if (count <= 0) { - return -1; +/* delete a record */ +static int +lsqlite3_delete(struct ldb_module *module, + const char *dn) +{ + /* ignore ltdb specials */ + if (dn[0] == '@') { + return 0; } + + return -1; +} - el = talloc_realloc(msg, msg->elements, struct ldb_message_element, - msg->num_elements + 1); - if (!el) { - errno = ENOMEM; - return -1; +/* search for matching records */ +static int +lsqlite3_search(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + const char * pExpression, + const char * const attrs[], + struct ldb_message *** res) +{ + long long eid = 0; + char * sql; + char * sql_constraints; + char * table_list; + char * hTalloc; + struct ldb_parse_tree * pTree; + struct lsqlite3_private * lsqlite3 = module->private_data; + + if (pBaseDN == NULL) { + pBaseDN = ""; } - msg->elements = el; + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); - el = &msg->elements[msg->num_elements]; + /* + * Obtain the eid of the base DN + */ + QUERY_INT(lsqlite3, + eid, + TRUE, + "SELECT eid " + " FROM ldb_attr_dn " + " WHERE attr_value = %Q;", + pBaseDN); - el->name = talloc_strdup(msg->elements, attr); - if (!el->name) { - errno = ENOMEM; + /* Parse the filter expression into a tree we can work with */ + if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { return -1; } - el->flags = 0; + + /* Allocate a temporary talloc context */ + hTalloc = talloc_new(module->ldb); - el->num_values = 0; - el->values = talloc_array(msg->elements, struct ldb_val, count); - if (!el->values) { - errno = ENOMEM; - return -1; - } + /* Move the parse tree to our temporary context */ + talloc_steal(hTalloc, pTree); + + /* Convert filter into a series of SQL statements (constraints) */ + sql_constraints = parsetree_to_sql(module, hTalloc, pTree); + + /* Get the list of attribute names to use as our extra table list */ + table_list = parsetree_to_tablelist(module, hTalloc, pTree); - for (i=0;ivalues[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len); - if (!el->values[i].data) { - return -1; - } - el->values[i].length = bval[i]->bv_len; - el->num_values++; - } + switch(scope) { + case LDB_SCOPE_DEFAULT: + case LDB_SCOPE_SUBTREE: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry,\n" + " ldb_descendants,\n" + " %q\n" + " WHERE ldb_descendants.aeid = %lld\n" + " AND ldb_entry.eid = ldb_descendants.deid\n" + " AND ldap_entry.eid IN\n" + "%s" + ");", + table_list, + eid, + sql_constraints); + break; - msg->num_elements++; + case LDB_SCOPE_BASE: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM %q\n" + " WHERE ldb_entry.eid = %lld\n" + " AND ldb_entry.eid IN\n" + "%s" + ");", + table_list, + eid, + sql_constraints); + break; + + case LDB_SCOPE_ONELEVEL: + sql = sqlite3_mprintf( + "SELECT entry.entry_data\n" + " FROM ldb_entry AS entry\n" + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry AS pchild, " + " %q\n" + " WHERE ldb_entry.eid = pchild.eid " + " AND pchild.peid = %lld " + " AND ldb_entry.eid IN\n" + "%s" + ");", + table_list, + eid, + sql_constraints); + break; + } + +#warning "retrieve and return the result set of the search here" + + /* End the transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); return 0; } -#endif -static char * -lsqlite3_parsetree_to_sql(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t) + +/* add a record */ +static int +lsqlite3_add(struct ldb_module *module, + const struct ldb_message *msg) { - int i; - char * child; - char * p; - char * ret = NULL; - char * pAttrName; - + long long eid; + struct lsqlite3_private * lsqlite3 = module->private_data; - switch(t->operation) { - case LDB_OP_SIMPLE: - break; + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } - case LDB_OP_AND: - ret = lsqlite3_parsetree_to_sql(module, - hTalloc, - t->u.list.elements[0]); + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - for (i = 1; i < t->u.list.num_elements; i++) { - child = - lsqlite3_parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "INTERSECT\n" - "%s\n", - child); - talloc_free(child); - } + /* + * Build any portions of the directory tree that don't exist. If the + * final component already exists, it's an error. + */ + if (new_dn(module, msg->dn, &eid) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return -1; + } - child = ret; - ret = talloc_asprintf("(\n" - "%s\n" - ")\n", - child); - talloc_free(child); - return ret; + /* Add attributes to this new entry */ + if (msg_to_sql(module, msg, eid, FALSE) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return -1; + } - case LDB_OP_OR: - child = - lsqlite3_parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[0]); + /* Everything worked. Commit it! */ + QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + return 0; +} - for (i = 1; i < t->u.list.num_elements; i++) { - child = - lsqlite3_parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "UNION\n" - "%s\n", - child); - talloc_free(child); - } - child = ret; - ret = talloc_asprintf("(\n" - "%s\n" - ")\n", - child); - talloc_free(child); - return ret; - case LDB_OP_NOT: - child = - lsqlite3_parsetree_to_sql( - module, - hTalloc, - t->u.not.child); - ret = talloc_asprintf(hTalloc, - "(\n" - " SELECT eid\n" - " FROM ldb_entry\n" - " WHERE eid NOT IN %s\n" - ")\n", - child); - talloc_free(child); - return ret; +/* modify a record */ +static int +lsqlite3_modify(struct ldb_module *module, + const struct ldb_message *msg) +{ + struct lsqlite3_private * lsqlite3 = module->private_data; - default: - /* should never occur */ - abort(); - }; - - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, - t->u.simple.attr); + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } - /* - * For simple searches, we want to retrieve the list of EIDs that - * match the criteria. We accomplish this by searching the - * appropriate table, ldb_attr_, for the eid - * corresponding to all matching values. - */ - if (t->u.simple.value.length == 1 && - (*(const char *) t->u.simple.value.data) == '*') { - /* - * Special case for "attr_name=*". In this case, we want the - * eid corresponding to all values in the specified attribute - * table. - */ - if ((p = sqlite3_mprintf("(\n" - " SELECT eid\n" - " FROM ldb_attr_%q\n" - ")\n", - pAttrName)) == NULL) { - return NULL; - } + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); + /* Everything worked. Commit it! */ + QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + return 0 ; +} - } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { - /* - * For object classes, we want to search for all objectclasses - * that are subclasses as well. - */ - if ((p = sqlite3_mprintf( - "(\n" - " SELECT eid\n" - " FROM ldb_attr_objectclass\n" - " WHERE attr_name IN\n" - " (SELECT class_name\n" - " FROM ldb_objectclasses\n" - " WHERE tree_key GLOB\n" - " (SELECT tree_key\n" - " FROM ldb_objectclasses\n" - " WHERE class_name = %Q) || '*')\n" - ")\n", - t->u.simple.value.data)) == NULL) { - return NULL; - } +/* obtain a named lock */ +static int +lsqlite3_lock(struct ldb_module *module, + const char *lockname) +{ + if (lockname == NULL) { + return -1; + } - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); + /* TODO implement a local locking mechanism here */ - } else { - /* A normal query. */ - if ((p = sqlite3_mprintf("(\n" - " SELECT eid\n" - " FROM ldb_attr_%q\n" - " WHERE attr_value = %Q\n" - ")\n", - pAttrName, - t->u.simple.value.data)) == NULL) { - return NULL; - } + return 0; +} - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); +/* release a named lock */ +static int +lsqlite3_unlock(struct ldb_module *module, + const char *lockname) +{ + if (lockname == NULL) { + return -1; } - return ret; -} + /* TODO implement a local locking mechanism here */ + + return 0; +} -static char * -lsqlite3_parsetree_to_tablelist(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t) +/* return extended error information */ +static const char * +lsqlite3_errstring(struct ldb_module *module) { -#warning "obtain talloc'ed array of attribute names for table list" - return NULL; + struct lsqlite3_private * lsqlite3 = module->private_data; + + return sqlite3_errmsg(lsqlite3->sqlite); } + + /* - * search for matching records + * Static functions */ + static int -lsqlite3_search(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - const char * pExpression, - const char * const attrs[], - struct ldb_message *** res) +initialize(struct lsqlite3_private *lsqlite3, + const char *url) { - long long eid = 0; - char * sql; - char * sql_constraints; - char * table_list; - char * hTalloc; - struct ldb_parse_tree * pTree; - struct lsqlite3_private * lsqlite3 = module->private_data; - - if (pBaseDN == NULL) { - pBaseDN = ""; - } + int ret; + long long queryInt; + const char * pTail; + sqlite3_stmt * stmt; + const char * schema = + "-- ------------------------------------------------------" - /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); + "PRAGMA auto_vacuum=1;" - /* - * Obtain the eid of the base DN - */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid " - " FROM ldb_attr_dn " - " WHERE attr_value = %Q;", - pBaseDN); + "-- ------------------------------------------------------" - /* Parse the filter expression into a tree we can work with */ - if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { - return -1; - } - - /* Allocate a temporary talloc context */ - hTalloc = talloc_new(module->ldb); + "BEGIN EXCLUSIVE;" - /* Move the parse tree to our temporary context */ - talloc_steal(hTalloc, pTree); - - /* Convert filter into a series of SQL statements (constraints) */ - sql_constraints = lsqlite3_parsetree_to_sql(module, hTalloc, pTree); - - /* Get the list of attribute names to use as our extra table list */ - table_list = lsqlite3_parsetree_to_tablelist(module, hTalloc, pTree); + "-- ------------------------------------------------------" - switch(scope) { - case LDB_SCOPE_DEFAULT: - case LDB_SCOPE_SUBTREE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry,\n" - " ldb_descendants,\n" - " %q\n" - " WHERE ldb_descendants.aeid = %lld\n" - " AND ldb_entry.eid = ldb_descendants.deid\n" - " AND ldap_entry.eid IN\n" - "%s" - ");", - table_list, - eid, - sql_constraints); - break; + "CREATE TABLE ldb_info AS" + " SELECT 'LDB' AS database_type," + " '1.0' AS version;" - case LDB_SCOPE_BASE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM %q\n" - " WHERE ldb_entry.eid = %lld\n" - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, - eid, - sql_constraints); - break; + "-- ------------------------------------------------------" + "-- Schema" - case LDB_SCOPE_ONELEVEL: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry AS pchild, " - " %q\n" - " WHERE ldb_entry.eid = pchild.eid " - " AND pchild.peid = %lld " - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, - eid, - sql_constraints); - break; - } - -#warning "retrieve and return the result set of the search here" - - /* End the transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); + "/*" + " * The entry table holds the information about an entry. " + " * This table is used to obtain the EID of the entry and to " + " * support scope=one and scope=base. The parent and child" + " * table is included in the entry table since all the other" + " * attributes are dependent on EID." + " */" + "CREATE TABLE ldb_entry" + "(" + " -- Unique identifier of this LDB entry" + " eid INTEGER PRIMARY KEY," - return 0; -} + " -- Unique identifier of the parent LDB entry" + " peid INTEGER REFERENCES ldb_entry," + " -- Distinguished name of this entry" + " dn TEXT," -static int -lsqlite3_new_attr(struct ldb_module * module, - char * pAttrName) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; + " -- Time when the entry was created" + " create_timestamp INTEGER," - /* NOTE: pAttrName is assumed to already be case-folded here! */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TABLE ldb_attr_%q " - "(" - " eid INTEGER REFERENCES ldb_entry, " - " attr_value TEXT" - ");", - pAttrName); + " -- Time when the entry was last modified" + " modify_timestamp INTEGER," - return 0; -} + " -- Attributes of this entry, in the form" + " -- attr\1value\0[attr\1value\0]*\0" + " entry_data TEXT" + ");" -/* - * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE - * requests in the ldb_message - */ -static int -lsqlite3_msg_to_sql(struct ldb_module * module, - const struct ldb_message * msg, - long long eid, - int use_flags) -{ - int flags; - char * pAttrName; - unsigned int i; - unsigned int j; - struct lsqlite3_private * lsqlite3 = module->private_data; - for (i = 0; i < msg->num_elements; i++) { - const struct ldb_message_element *el = &msg->elements[i]; + "/*" + " * The purpose of the descendant table is to support the" + " * subtree search feature. For each LDB entry with a unique" + " * ID (AEID), this table contains the unique identifiers" + " * (DEID) of the descendant entries." + " *" + " * For evern entry in the directory, a row exists in this" + " * table for each of its ancestors including itself. The " + " * size of the table depends on the depth of each entry. In " + " * the worst case, if all the entries were at the same " + " * depth, the number of rows in the table is O(nm) where " + " * n is the number of nodes in the directory and m is the " + " * depth of the tree. " + " */" + "CREATE TABLE ldb_descendants" + "(" + " -- The unique identifier of the ancestor LDB entry" + " aeid INTEGER REFERENCES ldb_entry," - if (! use_flags) { - flags = LDB_FLAG_MOD_ADD; - } else { - flags = el->flags & LDB_FLAG_MOD_MASK; - } + " -- The unique identifier of the descendant LDB entry" + " deid INTEGER REFERENCES ldb_entry" + ");" - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, - el->name); - if (flags == LDB_FLAG_MOD_ADD) { - /* Create the attribute table if it doesn't exist */ - if (lsqlite3_new_attr(module, pAttrName) != 0) { - return -1; - } - } + "CREATE TABLE ldb_object_classes" + "(" + " -- Object classes are inserted into this table to track" + " -- their class hierarchy. 'top' is the top-level class" + " -- of which all other classes are subclasses." + " class_name TEXT PRIMARY KEY," - /* For each value of the specified attribute name... */ - for (j = 0; j < el->num_values; j++) { + " -- tree_key tracks the position of the class in" + " -- the hierarchy" + " tree_key TEXT UNIQUE" + ");" - /* ... bind the attribute value, if necessary */ - switch (flags) { - case LDB_FLAG_MOD_ADD: - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_attr_%q " - " (eid, attr_value) " - " VALUES " - " (%lld, %Q);", - pAttrName, - eid, el->values[j].data); - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " add_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); - - break; + "/*" + " * There is one attribute table per searchable attribute." + " */" + "/*" + "CREATE TABLE ldb_attr_ATTRIBUTE_NAME" + "(" + " -- The unique identifier of the LDB entry" + " eid INTEGER REFERENCES ldb_entry," - case LDB_FLAG_MOD_REPLACE: - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_attr_%q " - " SET attr_value = %Q " - " WHERE eid = %lld;", - pAttrName, - el->values[j].data, - eid); - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " mod_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); - break; + " -- Normalized attribute value" + " attr_value TEXT" + ");" + "*/" - case LDB_FLAG_MOD_DELETE: - /* No additional parameters to this query */ - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM ldb_attr_%q " - " WHERE eid = %lld " - " AND attr_value = %Q;", - pAttrName, - eid, - el->values[j].data); - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " del_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); - break; - } - } - } - return 0; -} + "-- ------------------------------------------------------" + "-- Indexes" -static int -lsqlite3_new_dn(struct ldb_module * module, - char * pDN, - long long * pEID) -{ - struct ldb_dn * pExplodedDN; - struct ldb_context * ldb = module->ldb; -// struct lsqlite3_private * lsqlite3 = module->private_data; + "-- ------------------------------------------------------" + "-- Triggers" - /* Explode and normalize the DN */ - if ((pExplodedDN = - ldb_explode_dn(ldb, - pDN, - ldb, - lsqlite3_case_fold_attr_required)) == NULL) { - return -1; - } + "CREATE TRIGGER ldb_entry_insert_tr" + " AFTER INSERT" + " ON ldb_entry" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_entry" + " SET create_timestamp = strftime('%s', 'now')," + " modify_timestamp = strftime('%s', 'now')" + " WHERE eid = new.eid;" + " END;" -#warning "*** lsqlite3_new_dn() not yet fully implemented ***" - return -1; -} + "CREATE TRIGGER ldb_entry_update_tr" + " AFTER UPDATE" + " ON ldb_entry" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_entry" + " SET modify_timestamp = strftime('%s', 'now')" + " WHERE eid = old.eid;" + " END;" + "-- ------------------------------------------------------" + "-- Table initialization" -/* - * add a record - */ -static int -lsqlite3_add(struct ldb_module *module, - const struct ldb_message *msg) -{ - long long eid; - struct lsqlite3_private * lsqlite3 = module->private_data; + "/* We need an implicit 'top' level object class */" + "INSERT INTO ldb_attributes (attr_name," + " parent_tree_key)" + " SELECT 'top', '';" - /* ignore ltdb specials */ - if (msg->dn[0] == '@') { - return 0; - } + "-- ------------------------------------------------------" - /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + "COMMIT;" - /* - * Build any portions of the directory tree that don't exist. If the - * final component already exists, it's an error. - */ - if (lsqlite3_new_dn(module, msg->dn, &eid) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); - return -1; + "-- ------------------------------------------------------" + ; + + /* Skip protocol indicator of url */ + if (strncmp(url, "sqlite://", 9) != 0) { + return SQLITE_MISUSE; } - /* Add attributes to this new entry */ - if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); - return -1; + /* Update pointer to just after the protocol indicator */ + url += 9; + + /* Try to open the (possibly empty/non-existent) database */ + if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) { + return ret; } - /* Everything worked. Commit it! */ - QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); - return 0; -} - - -/* - * modify a record - */ -static int -lsqlite3_modify(struct ldb_module *module, - const struct ldb_message *msg) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* ignore ltdb specials */ - if (msg->dn[0] == '@') { - return 0; - } - /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - /* Everything worked. Commit it! */ - QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); - return 0 ; -} - -static int -lsqlite3_lock(struct ldb_module *module, - const char *lockname) -{ - if (lockname == NULL) { - return -1; - } - - /* TODO implement a local locking mechanism here */ - - return 0; -} + /* Determine if this is a new database. No tables means it is. */ + QUERY_INT(lsqlite3, + queryInt, + TRUE, + "SELECT COUNT(*) " + " FROM sqlite_master " + " WHERE type = 'table';"); -static int -lsqlite3_unlock(struct ldb_module *module, - const char *lockname) -{ - if (lockname == NULL) { - return -1; - } + if (queryInt == 0) { + /* + * Create the database schema + */ + for (pTail = discard_const_p(char, schema); pTail != NULL; ) { - /* TODO implement a local locking mechanism here */ + if ((ret = sqlite3_prepare( + lsqlite3->sqlite, + pTail, + -1, + &stmt, + &pTail)) != SQLITE_OK || + (ret = sqlite3_step(stmt)) != SQLITE_DONE || + (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - return 0; -} + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + (void) sqlite3_close(lsqlite3->sqlite); + return ret; + } + } + } else { + /* + * Ensure that the database we opened is one of ours + */ + if (query_int(lsqlite3, + &queryInt, + "SELECT " + " (SELECT COUNT(*) = 3" + " FROM sqlite_master " + " WHERE type = 'table' " + " AND name IN " + " (" + " 'ldb_entry', " + " 'ldb_descendants', " + " 'ldb_object_classes' " + " ) " + " ) " + " AND " + " (SELECT 1 " + " FROM ldb_info " + " WHERE database_type = 'LDB' " + " AND version = '1.0'" + " );") != 0 || + queryInt != 1) { + + /* It's not one that we created. See ya! */ + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + (void) sqlite3_close(lsqlite3->sqlite); + return SQLITE_MISUSE; + } + } -/* - * return extended error information - */ -static const char * -lsqlite3_errstring(struct ldb_module *module) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; + /* Commit the transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "COMMIT;"); - return sqlite3_errmsg(lsqlite3->sqlite); + return SQLITE_OK; } - -static const struct ldb_module_ops lsqlite3_ops = { - "sqlite", - lsqlite3_search, - lsqlite3_add, - lsqlite3_modify, - lsqlite3_delete, - lsqlite3_rename, - lsqlite3_lock, - lsqlite3_unlock, - lsqlite3_errstring -}; - - static int -lsqlite3_destructor(void *p) +destructor(void *p) { struct lsqlite3_private * lsqlite3 = p; @@ -958,312 +752,575 @@ lsqlite3_destructor(void *p) return 0; } + +/* + * query_norows() + * + * This function is used for queries that are not expected to return any rows, + * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. + * There are no provisions here for returning data from rows in a table, so do + * not pass SELECT queries to this function. + */ static int -lsqlite3_initialize(struct lsqlite3_private *lsqlite3, - const char *url) +query_norows(const struct lsqlite3_private *lsqlite3, + const char *pSql, + ...) { int ret; - const char * p; - long long queryInt; + int bLoop; + char * p; const char * pTail; - sqlite3_stmt * stmt; - const char * schema = - "-- ------------------------------------------------------" - - "PRAGMA auto_vacuum=1;" + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); - "-- ------------------------------------------------------" + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + return -1; + } - "BEGIN EXCLUSIVE;" + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { - "-- ------------------------------------------------------" + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* No rows expected, so just step through machine code once */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_DONE) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } - "CREATE TABLE ldb_info AS" - " SELECT 'LDB' AS database_type," - " '1.0' AS version;" + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } - "-- ------------------------------------------------------" - "-- Schema" + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } - "/*" - " * The entry table holds the information about an entry. " - " * This table is used to obtain the EID of the entry and to " - " * support scope=one and scope=base. The parent and child" - " * table is included in the entry table since all the other" - " * attributes are dependent on EID." - " */" - "CREATE TABLE ldb_entry" - "(" - " -- Unique identifier of this LDB entry" - " eid INTEGER PRIMARY KEY," + /* All done with variable argument list */ + va_end(args); - " -- Unique identifier of the parent LDB entry" - " peid INTEGER REFERENCES ldb_entry," + /* Free the memory we allocated for our query string */ + sqlite3_free(p); - " -- Distinguished name of this entry" - " dn TEXT," + return ret; +} - " -- Time when the entry was created" - " create_timestamp INTEGER," - " -- Time when the entry was last modified" - " modify_timestamp INTEGER," +/* + * query_int() + * + * This function is used for the common case of queries that return a single + * integer value. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. + */ +static int +query_int(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pSql, + ...) +{ + int ret; + int bLoop; + char * p; + const char * pTail; + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); - " -- Attributes of this entry, in the form" - " -- attr\1value\0[attr\1value\0]*\0" - " entry_data TEXT" - ");" + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + return -1; + } + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { - "/*" - " * The purpose of the descendant table is to support the" - " * subtree search feature. For each LDB entry with a unique" - " * ID (AEID), this table contains the unique identifiers" - " * (DEID) of the descendant entries." - " *" - " * For evern entry in the directory, a row exists in this" - " * table for each of its ancestors including itself. The " - " * size of the table depends on the depth of each entry. In " - " * the worst case, if all the entries were at the same " - " * depth, the number of rows in the table is O(nm) where " - " * n is the number of nodes in the directory and m is the " - " * depth of the tree. " - " */" - "CREATE TABLE ldb_descendants" - "(" - " -- The unique identifier of the ancestor LDB entry" - " aeid INTEGER REFERENCES ldb_entry," + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pTail, + -1, + &pStmt, + &pTail)) != SQLITE_OK) { + ret = -1; + break; + } + + /* No rows expected, so just step through machine code once */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } - " -- The unique identifier of the descendant LDB entry" - " deid INTEGER REFERENCES ldb_entry" - ");" + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(pStmt, 0); + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } - "CREATE TABLE ldb_object_classes" - "(" - " -- Object classes are inserted into this table to track" - " -- their class hierarchy. 'top' is the top-level class" - " -- of which all other classes are subclasses." - " class_name TEXT PRIMARY KEY," + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } - " -- tree_key tracks the position of the class in" - " -- the hierarchy" - " tree_key TEXT UNIQUE" - ");" + /* All done with variable argument list */ + va_end(args); - "/*" - " * There is one attribute table per searchable attribute." - " */" - "/*" - "CREATE TABLE ldb_attr_ATTRIBUTE_NAME" - "(" - " -- The unique identifier of the LDB entry" - " eid INTEGER REFERENCES ldb_entry," + /* Free the memory we allocated for our query string */ + sqlite3_free(p); - " -- Normalized attribute value" - " attr_value TEXT" - ");" - "*/" + return ret; +} - "-- ------------------------------------------------------" - "-- Indexes" +/* + callback function used in call to ldb_dn_fold() for determining whether an + attribute type requires case folding. +*/ +static int +case_fold_attr_required(void * hUserData, + char *attr) +{ +// struct ldb_module * module = hUserData; + +#warning "currently, all attributes require case folding" + return TRUE; +} - "-- ------------------------------------------------------" - "-- Triggers" +/* + * add a single set of ldap message values to a ldb_message + */ - "CREATE TRIGGER ldb_entry_insert_tr" - " AFTER INSERT" - " ON ldb_entry" - " FOR EACH ROW" - " BEGIN" - " UPDATE ldb_entry" - " SET create_timestamp = strftime('%s', 'now')," - " modify_timestamp = strftime('%s', 'now')" - " WHERE eid = new.eid;" - " END;" +#warning "add_msg_attr() not yet implemented or used" +#if 0 +static int +add_msg_attr(struct ldb_context *ldb, + struct ldb_message *msg, + const char *attr, + struct berval **bval) +{ + int i; + int count; + struct ldb_message_element * el; - "CREATE TRIGGER ldb_entry_update_tr" - " AFTER UPDATE" - " ON ldb_entry" - " FOR EACH ROW" - " BEGIN" - " UPDATE ldb_entry" - " SET modify_timestamp = strftime('%s', 'now')" - " WHERE eid = old.eid;" - " END;" + count = ldap_count_values_len(bval); - "-- ------------------------------------------------------" - "-- Table initialization" + if (count <= 0) { + return -1; + } - "/* We need an implicit 'top' level object class */" - "INSERT INTO ldb_attributes (attr_name," - " parent_tree_key)" - " SELECT 'top', '';" + el = talloc_realloc(msg, msg->elements, struct ldb_message_element, + msg->num_elements + 1); + if (!el) { + errno = ENOMEM; + return -1; + } + + msg->elements = el; + + el = &msg->elements[msg->num_elements]; + + el->name = talloc_strdup(msg->elements, attr); + if (!el->name) { + errno = ENOMEM; + return -1; + } + el->flags = 0; + + el->num_values = 0; + el->values = talloc_array(msg->elements, struct ldb_val, count); + if (!el->values) { + errno = ENOMEM; + return -1; + } + + for (i=0;ivalues[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len); + if (!el->values[i].data) { + return -1; + } + el->values[i].length = bval[i]->bv_len; + el->num_values++; + } + + msg->num_elements++; + + return 0; +} +#endif + +static char * +parsetree_to_sql(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t) +{ + int i; + char * child; + char * p; + char * ret = NULL; + char * pAttrName; + + + switch(t->operation) { + case LDB_OP_SIMPLE: + break; + + case LDB_OP_AND: + ret = parsetree_to_sql(module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = + parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "INTERSECT\n" + "%s\n", + child); + talloc_free(child); + } + + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_OR: + child = + parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = + parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "UNION\n" + "%s\n", + child); + talloc_free(child); + } + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_NOT: + child = + parsetree_to_sql( + module, + hTalloc, + t->u.not.child); + ret = talloc_asprintf(hTalloc, + "(\n" + " SELECT eid\n" + " FROM ldb_entry\n" + " WHERE eid NOT IN %s\n" + ")\n", + child); + talloc_free(child); + return ret; + + default: + /* should never occur */ + abort(); + }; + + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, + t->u.simple.attr); + + /* + * For simple searches, we want to retrieve the list of EIDs that + * match the criteria. We accomplish this by searching the + * appropriate table, ldb_attr_, for the eid + * corresponding to all matching values. + */ + if (t->u.simple.value.length == 1 && + (*(const char *) t->u.simple.value.data) == '*') { + /* + * Special case for "attr_name=*". In this case, we want the + * eid corresponding to all values in the specified attribute + * table. + */ + if ((p = sqlite3_mprintf("(\n" + " SELECT eid\n" + " FROM ldb_attr_%q\n" + ")\n", + pAttrName)) == NULL) { + return NULL; + } + + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); + + } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { + /* + * For object classes, we want to search for all objectclasses + * that are subclasses as well. + */ + if ((p = sqlite3_mprintf( + "(\n" + " SELECT eid\n" + " FROM ldb_attr_objectclass\n" + " WHERE attr_name IN\n" + " (SELECT class_name\n" + " FROM ldb_objectclasses\n" + " WHERE tree_key GLOB\n" + " (SELECT tree_key\n" + " FROM ldb_objectclasses\n" + " WHERE class_name = %Q) || '*')\n" + ")\n", + t->u.simple.value.data)) == NULL) { + return NULL; + } - "-- ------------------------------------------------------" + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); - "COMMIT;" + } else { + /* A normal query. */ + if ((p = sqlite3_mprintf("(\n" + " SELECT eid\n" + " FROM ldb_attr_%q\n" + " WHERE attr_value = %Q\n" + ")\n", + pAttrName, + t->u.simple.value.data)) == NULL) { + return NULL; + } - "-- ------------------------------------------------------" - ; - - /* Skip protocol indicator of url */ - if (strncmp(url, "sqlite://", 9) != 0) { - return SQLITE_MISUSE; - } else { - p = url + 9; - } - - /* - * See if we'll be creating a new database, or opening an existing one - */ - /* Try to open the (possibly empty/non-existent) database */ - if ((ret = sqlite3_open(p, &lsqlite3->sqlite)) != SQLITE_OK) { - return ret; - } + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); + } + return ret; +} - /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - /* Determine if this is a new database */ - QUERY_INT(lsqlite3, - queryInt, - TRUE, - "SELECT COUNT(*) " - " FROM sqlite_master " - " WHERE type = 'table';"); +static char * +parsetree_to_tablelist(struct ldb_module *module, + char * hTalloc, + const struct ldb_parse_tree *t) +{ +#warning "obtain talloc'ed array of attribute names for table list" + return NULL; +} - if (queryInt == 0) { - /* - * Create the database schema - */ - for (pTail = discard_const_p(char, schema); pTail != NULL; ) { - if ((ret = sqlite3_prepare( - lsqlite3->sqlite, - pTail, - -1, - &stmt, - &pTail)) != SQLITE_OK || - (ret = sqlite3_step(stmt)) != SQLITE_DONE || - (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { +static int +new_attr(struct ldb_module * module, + char * pAttrName) +{ + struct lsqlite3_private * lsqlite3 = module->private_data; - (void) sqlite3_close(lsqlite3->sqlite); - return ret; - } - } - } else { - /* - * Ensure that the database we opened is one of ours - */ - if (lsqlite3_query_int(lsqlite3, - &queryInt, - "SELECT " - " (SELECT COUNT(*) = 3" - " FROM sqlite_master " - " WHERE type = 'table' " - " AND name IN " - " (" - " 'ldb_entry', " - " 'ldb_descendants', " - " 'ldb_object_classes' " - " ) " - " ) " - " AND " - " (SELECT 1 " - " FROM ldb_info " - " WHERE database_type = 'LDB' " - " AND version = '1.0'" - " );") != 0 || - queryInt != 1) { - - /* It's not one that we created. See ya! */ - (void) sqlite3_close(lsqlite3->sqlite); - return SQLITE_MISUSE; - } - } + /* NOTE: pAttrName is assumed to already be case-folded here! */ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TABLE ldb_attr_%q " + "(" + " eid INTEGER REFERENCES ldb_entry, " + " attr_value TEXT" + ");", + pAttrName); - return SQLITE_OK; + return 0; } /* - * connect to the database + * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE + * requests in the ldb_message */ -struct ldb_context * -lsqlite3_connect(const char *url, - unsigned int flags, - const char *options[]) +static int +msg_to_sql(struct ldb_module * module, + const struct ldb_message * msg, + long long eid, + int use_flags) { - int i; - int ret; - struct ldb_context * ldb = NULL; - struct lsqlite3_private * lsqlite3 = NULL; - - ldb = talloc(NULL, struct ldb_context); - if (!ldb) { - errno = ENOMEM; - goto failed; - } + int flags; + char * pAttrName; + unsigned int i; + unsigned int j; + struct lsqlite3_private * lsqlite3 = module->private_data; - lsqlite3 = talloc(ldb, struct lsqlite3_private); - if (!lsqlite3) { - errno = ENOMEM; - goto failed; - } + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_message_element *el = &msg->elements[i]; - lsqlite3->sqlite = NULL; - lsqlite3->options = NULL; - lsqlite3->lock_count = 0; + if (! use_flags) { + flags = LDB_FLAG_MOD_ADD; + } else { + flags = el->flags & LDB_FLAG_MOD_MASK; + } - ret = lsqlite3_initialize(lsqlite3, url); - if (ret != SQLITE_OK) { - goto failed; - } + /* Get a case-folded copy of the attribute name */ + pAttrName = ldb_casefold((struct ldb_context *) module, + el->name); - talloc_set_destructor(lsqlite3, lsqlite3_destructor); + if (flags == LDB_FLAG_MOD_ADD) { + /* Create the attribute table if it doesn't exist */ + if (new_attr(module, pAttrName) != 0) { + return -1; + } + } - ldb->modules = talloc(ldb, struct ldb_module); - if (!ldb->modules) { - errno = ENOMEM; - goto failed; - } - ldb->modules->ldb = ldb; - ldb->modules->prev = ldb->modules->next = NULL; - ldb->modules->private_data = lsqlite3; - ldb->modules->ops = &lsqlite3_ops; + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { - if (options) { - /* - * take a copy of the options array, so we don't have to rely - * on the caller keeping it around (it might be dynamic) - */ - for (i=0;options[i];i++) ; + /* ... bind the attribute value, if necessary */ + switch (flags) { + case LDB_FLAG_MOD_ADD: + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_attr_%q " + " (eid, attr_value) " + " VALUES " + " (%lld, %Q);", + pAttrName, + eid, el->values[j].data); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " add_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); + + break; - lsqlite3->options = talloc_array(lsqlite3, char *, i+1); - if (!lsqlite3->options) { - goto failed; - } - - for (i=0;options[i];i++) { + case LDB_FLAG_MOD_REPLACE: + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_attr_%q " + " SET attr_value = %Q " + " WHERE eid = %lld;", + pAttrName, + el->values[j].data, + eid); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " mod_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); + break; - lsqlite3->options[i+1] = NULL; - lsqlite3->options[i] = - talloc_strdup(lsqlite3->options, options[i]); - if (!lsqlite3->options[i]) { - goto failed; - } + case LDB_FLAG_MOD_DELETE: + /* No additional parameters to this query */ + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM ldb_attr_%q " + " WHERE eid = %lld " + " AND attr_value = %Q;", + pAttrName, + eid, + el->values[j].data); + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET entry_data = " + " del_attr(entry_data, " + " %Q, %Q) " + " WHERE eid = %lld;", + el->name, el->values[j].data, + eid); + break; + } } } - return ldb; + return 0; +} -failed: - if (lsqlite3->sqlite != NULL) { - (void) sqlite3_close(lsqlite3->sqlite); + +static int +new_dn(struct ldb_module * module, + char * pDN, + long long * pEID) +{ + struct ldb_dn * pExplodedDN; + struct ldb_context * ldb = module->ldb; +// struct lsqlite3_private * lsqlite3 = module->private_data; + + /* Explode and normalize the DN */ + if ((pExplodedDN = + ldb_explode_dn(ldb, + pDN, + ldb, + case_fold_attr_required)) == NULL) { + return -1; } - talloc_free(ldb); - return NULL; + +#warning "*** new_dn() not yet fully implemented ***" + return -1; } + -- cgit From 09bdc1b9384ceddc610514a605028f09f8195f1d Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 17:33:30 +0000 Subject: r7446: add distclean target to generated ldb makefile (This used to be commit 9a78161b0fdb3406c70b9f5a8009ed8fc5268445) --- source4/lib/ldb/Makefile.in | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 5bccf17e82..b335331b29 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -113,6 +113,12 @@ manpages: $(patsubst %.xml,%,$(wildcard man/*/*.xml)) clean: rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] +distclean: clean + rm -rf autom4te.cache bin lib + rm -f configure config.log config.status ldb.pc \ + Makefile.ldb include/config.h include/config.h.in + rm -f Makefile + etags: etags */*.[ch] -- cgit From 5351ae59a0d7043f627fa066879cf7252451fbd9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 9 Jun 2005 18:43:56 +0000 Subject: r7449: add ctype.h header to dn expand function (This used to be commit 0e3b872560d82e1a0f7b58fe7d210563d6d29daf) --- source4/lib/ldb/common/ldb_explode_dn.c | 1 + source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 47 ++++++++++++++++--------------- 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index e3cd53d047..f015ce81c7 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index c16708672d..e491fba6e0 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -142,10 +142,6 @@ parsetree_to_tablelist(struct ldb_module *module, char * hTalloc, const struct ldb_parse_tree *t); -static int -new_attr(struct ldb_module * module, - char * pAttrName); - static int msg_to_sql(struct ldb_module * module, const struct ldb_message * msg, @@ -157,6 +153,10 @@ new_dn(struct ldb_module * module, char * pDN, long long * pEID); +static int +new_attr(struct ldb_module * module, + char * pAttrName); + /* * Table of operations for the sqlite3 backend @@ -1172,25 +1172,6 @@ parsetree_to_tablelist(struct ldb_module *module, } -static int -new_attr(struct ldb_module * module, - char * pAttrName) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* NOTE: pAttrName is assumed to already be case-folded here! */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TABLE ldb_attr_%q " - "(" - " eid INTEGER REFERENCES ldb_entry, " - " attr_value TEXT" - ");", - pAttrName); - - return 0; -} - /* * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE * requests in the ldb_message @@ -1301,6 +1282,7 @@ msg_to_sql(struct ldb_module * module, } + static int new_dn(struct ldb_module * module, char * pDN, @@ -1324,3 +1306,22 @@ new_dn(struct ldb_module * module, } +static int +new_attr(struct ldb_module * module, + char * pAttrName) +{ + struct lsqlite3_private * lsqlite3 = module->private_data; + + /* NOTE: pAttrName is assumed to already be case-folded here! */ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TABLE ldb_attr_%q " + "(" + " eid INTEGER REFERENCES ldb_entry, " + " attr_value TEXT" + ");", + pAttrName); + + return 0; +} + -- cgit From a9258487043eb4862769ee8da02b3810db925295 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 10 Jun 2005 07:58:45 +0000 Subject: r7456: Add a simple type that represents a pointer. The ejs people may ask us to change this later but that will be pretty easy. We can use this type to pass around pointers to handles in C. Talloc allows us to do type checking too. (This used to be commit b95c0bc9b0a18aeaa89f704e37669f01df2c2ad0) --- source4/lib/ejs/ejsParser.c | 1 + source4/lib/ejs/ejsProcs.c | 1 + source4/lib/ejs/var.c | 29 +++++++++++++++++++++++++++++ source4/lib/ejs/var.h | 3 +++ 4 files changed, 34 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 17fe0ce98a..8d0aa7ba2c 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -1659,6 +1659,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) case MPR_TYPE_CFUNCTION: case MPR_TYPE_FUNCTION: case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); return 0; diff --git a/source4/lib/ejs/ejsProcs.c b/source4/lib/ejs/ejsProcs.c index b15985c8cf..e9932406ad 100644 --- a/source4/lib/ejs/ejsProcs.c +++ b/source4/lib/ejs/ejsProcs.c @@ -310,6 +310,7 @@ static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) case MPR_TYPE_OBJECT: case MPR_TYPE_FUNCTION: case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_PTR: mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); break; diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index ce771caa04..6ef1c4d3a3 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -1182,6 +1182,21 @@ MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, int fla return v; } +/* + * Initialize an opaque pointer. + */ + +MprVar mprCreatePtrVar(void *ptr, const char *name) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_PTR; + v.ptr = ptr; + + return v; +} + /******************************************************************************/ #if BLD_FEATURE_FLOATING_POINT /* @@ -1398,6 +1413,10 @@ static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) dest->cFunctionWithStrings = src->cFunctionWithStrings; break; + case MPR_TYPE_PTR: + dest->ptr = src->ptr; + break; + case MPR_TYPE_CFUNCTION: dest->cFunction = src->cFunction; break; @@ -1645,6 +1664,10 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) mprAllocSprintf(out, size, "[C StringFunction]"); break; + case MPR_TYPE_PTR: + mprAllocSprintf(out, size, "[C Pointer: %p]", obj->ptr); + break; + case MPR_TYPE_FUNCTION: mprAllocSprintf(out, size, "[JavaScript Function]"); break; @@ -1779,6 +1802,9 @@ bool mprVarToBool(MprVar *vp) case MPR_TYPE_OBJECT: return 0; + case MPR_TYPE_PTR: + return (vp->ptr != NULL); + case MPR_TYPE_BOOL: return vp->boolean; @@ -1821,6 +1847,7 @@ double mprVarToFloat(MprVar *vp) case MPR_TYPE_CFUNCTION: case MPR_TYPE_FUNCTION: case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: return 0; case MPR_TYPE_BOOL: @@ -1896,6 +1923,7 @@ int64 mprVarToInteger64(MprVar *vp) case MPR_TYPE_CFUNCTION: case MPR_TYPE_FUNCTION: case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: return 0; case MPR_TYPE_BOOL: @@ -2010,6 +2038,7 @@ int mprVarToInteger(MprVar *vp) case MPR_TYPE_CFUNCTION: case MPR_TYPE_FUNCTION: case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: return 0; case MPR_TYPE_BOOL: diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h index 3cb23cf461..c313e29544 100644 --- a/source4/lib/ejs/var.h +++ b/source4/lib/ejs/var.h @@ -92,6 +92,7 @@ typedef int MprType; #define MPR_TYPE_FUNCTION 8 /* JavaScript function */ #define MPR_TYPE_STRING 9 /* String (immutable) */ #define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ +#define MPR_TYPE_PTR 11 /* C pointer */ /* * Create a type for the default number type @@ -315,6 +316,7 @@ typedef struct MprVar { void *thisPtr; } cFunctionWithStrings; MprStr string; /* Allocated string */ + void *ptr; /* C pointer */ #if !BLD_DEBUG && !LINUX && !VXWORKS }; #endif @@ -351,6 +353,7 @@ extern MprVar mprCreateObjVar(const char *name, int hashSize); extern MprVar mprCreateBoolVar(bool value); extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags); +extern MprVar mprCreatePtrVar(void *ptr, const char *name); #if BLD_FEATURE_FLOATING_POINT extern MprVar mprCreateFloatVar(double value); #endif -- cgit From d543e4a26510da5293b5c884f026f3e40ec869d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Jun 2005 12:21:46 +0000 Subject: r7460: fixed several problems with the socket wrapper code and unbound sockets This should fix the LOCAL-SOCKET test in the build farm (This used to be commit 417e967afb457ee505c2302cdc83d7060033b0aa) --- source4/lib/socket_wrapper/socket_wrapper.c | 110 ++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 31 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 2a26ba1534..882ef462ea 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -22,8 +22,10 @@ #ifdef _SAMBA_BUILD #include "includes.h" #include "system/network.h" +#include "system/filesys.h" #else #include +#include #include #include #include @@ -95,8 +97,8 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s } in->sin_family = AF_INET; - in->sin_port = 1025; /* Default to 1025 */ - p = strchr(un->sun_path, '/'); + in->sin_port = htons(1025); /* Default to 1025 */ + p = strrchr(un->sun_path, '/'); if (p) p++; else p = un->sun_path; if (sscanf(p, "sock_ip_%d_%u", &type, &prt) == 2) { @@ -107,9 +109,20 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s return 0; } -static int convert_in_un(int type, const struct sockaddr_in *in, struct sockaddr_un *un) +static int convert_in_un(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un) { + int type = si->type; uint16_t prt = ntohs(in->sin_port); + if (prt == 0) { + struct stat st; + /* handle auto-allocation of ephemeral ports */ + prt = 5000; + do { + snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", + getenv("SOCKET_WRAPPER_DIR"), type, ++prt); + } while (stat(un->sun_path, &st) == 0 && prt < 10000); + ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); + } snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", getenv("SOCKET_WRAPPER_DIR"), type, prt); return 0; @@ -126,7 +139,7 @@ static struct socket_info *find_socket_info(int fd) return NULL; } -static int sockaddr_convert_to_un(const struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, +static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, struct sockaddr_un *out_addr) { if (!out_addr) @@ -136,7 +149,7 @@ static int sockaddr_convert_to_un(const struct socket_info *si, const struct soc switch (in_addr->sa_family) { case AF_INET: - return convert_in_un(si->type, (const struct sockaddr_in *)in_addr, out_addr); + return convert_in_un(si, (const struct sockaddr_in *)in_addr, out_addr); case AF_UNIX: memcpy(out_addr, in_addr, sizeof(*out_addr)); return 0; @@ -235,9 +248,53 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) child_si->myname = sockaddr_dup(addr, *addrlen); } + child_si->peername_len = *addrlen; + child_si->peername = sockaddr_dup(addr, *addrlen); + + DLIST_ADD(sockets, child_si); + return fd; } +/* using sendto() or connect() on an unbound socket would give the + recipient no way to reply, as unlike UDP and TCP, a unix domain + socket can't auto-assign emphemeral port numbers, so we need to + assign it here */ +static int swrap_auto_bind(struct socket_info *si) +{ + struct sockaddr_un un_addr; + struct sockaddr_in in; + int i; + + un_addr.sun_family = AF_UNIX; + + for (i=0;i<1000;i++) { + snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), + "%s/sock_ip_%u_%u", getenv("SOCKET_WRAPPER_DIR"), + SOCK_DGRAM, i + 10000); + if (bind(si->fd, (struct sockaddr *)&un_addr, + sizeof(un_addr)) == 0) { + si->tmp_path = strdup(un_addr.sun_path); + si->bound = 1; + break; + } + } + if (i == 1000) { + return -1; + } + + memset(&in, 0, sizeof(in)); + in.sin_family = AF_INET; + in.sin_port = htons(i); + in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + si->myname_len = sizeof(in); + si->myname = sockaddr_dup(&in, si->myname_len); + si->bound = 1; + return 0; +} + + int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) { int ret; @@ -256,6 +313,11 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) return -1; } + if (si->bound == 0 && si->domain != AF_UNIX) { + ret = swrap_auto_bind(si); + if (ret == -1) return -1; + } + ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr); if (ret == -1) return -1; @@ -280,6 +342,14 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) return real_bind(s, myaddr, addrlen); } + si->myname_len = addrlen; + si->myname = sockaddr_dup(myaddr, addrlen); + + if (myaddr->sa_family == AF_INET && + ((const struct sockaddr_in *)myaddr)->sin_addr.s_addr == 0) { + ((struct sockaddr_in *)si->myname)->sin_addr.s_addr = + htonl(INADDR_LOOPBACK); + } ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr); if (ret == -1) return -1; @@ -289,8 +359,6 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) sizeof(struct sockaddr_un)); if (ret == 0) { - si->myname_len = addrlen; - si->myname = sockaddr_dup(myaddr, addrlen); si->bound = 1; } @@ -402,6 +470,7 @@ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr return ret; } + ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { struct sockaddr_un un_addr; @@ -412,31 +481,10 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str return real_sendto(s, buf, len, flags, to, tolen); } - /* using sendto() on an unbound DGRAM socket would give the - recipient no way to reply, as unlike UDP, a unix domain socket - can't auto-assign emphemeral port numbers, so we need to assign - it here */ - if (si->bound == 0 && si->type == SOCK_DGRAM) { - int i; - - un_addr.sun_family = AF_UNIX; - - for (i=0;i<1000;i++) { - snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), - "%s/sock_ip_%u_%u", getenv("SOCKET_WRAPPER_DIR"), - SOCK_DGRAM, i + 10000); - if (bind(si->fd, (struct sockaddr *)&un_addr, - sizeof(un_addr)) == 0) { - si->tmp_path = strdup(un_addr.sun_path); - si->bound = 1; - break; - } - } - if (i == 1000) { - return -1; - } + if (si->bound == 0 && si->domain != AF_UNIX) { + ret = swrap_auto_bind(si); + if (ret == -1) return -1; } - ret = sockaddr_convert_to_un(si, to, tolen, &un_addr); if (ret == -1) return -1; -- cgit From b1b134084f96ba0765241091c47c6187f57f9867 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 11 Jun 2005 02:26:53 +0000 Subject: r7476: ensure dgram sockets are created non-blocking. As they usually skip the connect() stage, we were missing this (This used to be commit f5102b886c10fead0f6bcdc4460584ae53912ebc) --- source4/lib/socket/socket.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index dd3175468d..39379be678 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -69,6 +69,12 @@ static NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK; } + /* we don't do a connect() on dgram sockets, so need to set + non-blocking at socket create time */ + if (!(flags & SOCKET_FLAG_BLOCK) && type == SOCKET_TYPE_DGRAM) { + set_blocking(socket_get_fd(*new_sock), False); + } + talloc_set_destructor(*new_sock, socket_destructor); return NT_STATUS_OK; -- cgit From 0264c1792d951eb212490b1d89d4ba9a635931d5 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 11 Jun 2005 03:20:26 +0000 Subject: r7480: ldb_sqlite3 work in progress (This used to be commit 510e7994da808ab12f51fa7a36c3f5f9244c51ac) --- source4/lib/ldb/common/ldb_explode_dn.c | 11 ++- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 113 ++++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index f015ce81c7..cacd9862b6 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -377,8 +377,7 @@ ldb_explode_dn(void * mem_ctx, */ /* allocate space for the normalized component */ - if ((component->component = - dest = talloc_size(component, size)) == NULL) { + if ((dest = talloc_size(component, size)) == NULL) { goto failed; } @@ -396,6 +395,9 @@ ldb_explode_dn(void * mem_ctx, dest += size; } + /* Save the just-generated string */ + component->component = dest; + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "component: [%s]\n", component->component); @@ -432,7 +434,7 @@ ldb_explode_dn(void * mem_ctx, } /* rebuild the normalized DN */ - if ((dn->dn = dest = talloc_size(dn, size)) == NULL) { + if ((dest = talloc_size(dn, size)) == NULL) { goto failed; } @@ -453,6 +455,9 @@ ldb_explode_dn(void * mem_ctx, dest += size; } + /* Save the just-generated string */ + dn->dn = dest; + ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); /* we don't need the copy of the DN any more */ diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index e491fba6e0..556702a21d 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1288,9 +1288,15 @@ new_dn(struct ldb_module * module, char * pDN, long long * pEID) { + int nComponent; + int bFirst; + char * p; + char * pPartialDN; + long long eid; struct ldb_dn * pExplodedDN; + struct ldb_dn_component * pComponent; struct ldb_context * ldb = module->ldb; -// struct lsqlite3_private * lsqlite3 = module->private_data; + struct lsqlite3_private * lsqlite3 = module->private_data; /* Explode and normalize the DN */ if ((pExplodedDN = @@ -1301,8 +1307,71 @@ new_dn(struct ldb_module * module, return -1; } -#warning "*** new_dn() not yet fully implemented ***" - return -1; + /* Allocate a string to hold the partial DN of each component */ + if ((pPartialDN = talloc_strdup(ldb, "")) == NULL) { + return -1; + } + + /* For each component of the DN (starting with the last one)... */ + eid = 0; + for (nComponent = pExplodedDN->comp_num - 1, bFirst = TRUE; + nComponent >= 0; + nComponent--, bFirst = FALSE) { + + /* Point to the component */ + pComponent = pExplodedDN->components[nComponent]; + + /* Add this component on to the partial DN to date */ + if ((p = talloc_asprintf(ldb, + "%s%s%s", + pComponent->component, + bFirst ? "" : ",", + pPartialDN)) == NULL) { + return -1; + } + + /* No need for the old partial DN any more */ + talloc_free(pPartialDN); + + /* Save the new partial DN */ + pPartialDN = p; + + /* + * Ensure that an entry is in the ldb_entry table for this + * component. Any component other than the last one + * (component 0) may already exist. It is an error if + * component 0 (the full DN requested to be be inserted) + * already exists. + */ + if (bFirst) { + /* This is a top-level entry. Parent EID is null. */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT %s INTO ldb_entry " + " (peid, dn) " + " VALUES " + " (NULL, %q);", + nComponent == 0 ? "" : "OR IGNORE", + pPartialDN); + } else { + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT %s INTO ldb_entry " + " (peid, dn) " + " VALUES " + " (%lld, %q);", + nComponent == 0 ? "" : "OR IGNORE", + eid, pPartialDN); + } + + /* Get the EID of the just inserted row (the next parent) */ + eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); + } + + /* Give 'em what they came for! */ + *pEID = eid; + + return 0; } @@ -1310,18 +1379,38 @@ static int new_attr(struct ldb_module * module, char * pAttrName) { + long long bExists; struct lsqlite3_private * lsqlite3 = module->private_data; - /* NOTE: pAttrName is assumed to already be case-folded here! */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TABLE ldb_attr_%q " - "(" - " eid INTEGER REFERENCES ldb_entry, " - " attr_value TEXT" - ");", - pAttrName); + /* + * NOTE: + * pAttrName is assumed to already be case-folded here! + */ + + /* See if the table already exists */ + QUERY_INT(lsqlite3, + bExists, + FALSE, + "SELECT COUNT(*) <> 0" + " FROM sqlite_master " + " WHERE type = 'table' " + " AND tbl_name = %Q;", + pAttrName); + + /* Did it exist? */ + if (! bExists) { + /* Nope. Create the table */ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TABLE ldb_attr_%q " + "(" + " eid INTEGER REFERENCES ldb_entry, " + " attr_value TEXT" + ");", + pAttrName); + } return 0; } + -- cgit From 182dd02ebe6e5a8e7dab20ae1ef18609b6697d3b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 11 Jun 2005 03:34:11 +0000 Subject: r7481: Add a mprVarIsPtr macro. (This used to be commit 633b24345fecad1111f40999efa2897bba521f19) --- source4/lib/ejs/var.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h index c313e29544..4882aacf0f 100644 --- a/source4/lib/ejs/var.h +++ b/source4/lib/ejs/var.h @@ -139,6 +139,8 @@ typedef BLD_FEATURE_NUM_TYPE MprNum; (type == MPR_TYPE_OBJECT) #define mprVarIsFloating(type) \ (type == MPR_TYPE_FLOAT) +#define mprVarIsPtr(type) \ + (type == MPR_TYPE_PTR) #define mprVarIsUndefined(var) \ ((var)->type == MPR_TYPE_UNDEFINED) #define mprVarIsNull(var) \ -- cgit From 4233f18a3100905e2cc25978230b5f94f8f8077e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 11 Jun 2005 05:06:32 +0000 Subject: r7486: fix for the build farm to display the panic messages and backtrace inside the per test frame metze (This used to be commit 5cf27b4af33fd7e30a59e53e4b08d67ac83ddccd) --- source4/lib/fault.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/fault.c b/source4/lib/fault.c index 9f1e3f44bc..f3a9e78f39 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -140,10 +140,10 @@ static void fault_report(int sig) if (counter) _exit(1); - DEBUG(0,("===============================================================\n")); + DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING)); DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); - DEBUG(0,("===============================================================\n")); + DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); smb_panic("internal error"); -- cgit From 2e1851e1acae4aba40fd38bc0f7b088599e9cba9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sun, 12 Jun 2005 03:07:10 +0000 Subject: r7498: ldb_sqlite3 work in progress (This used to be commit 797263330b9eada019e432ff201bf5c872e35b5d) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 178 +++++++++++++++++++++++------- source4/lib/ldb/ldb_sqlite3/schema | 19 +++- 2 files changed, 153 insertions(+), 44 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 556702a21d..d9e72c8089 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -290,6 +290,7 @@ lsqlite3_delete(struct ldb_module *module, return 0; } +#warning "lsqlite3_delete() is not yet supported" return -1; } @@ -302,11 +303,18 @@ lsqlite3_search(struct ldb_module * module, const char * const attrs[], struct ldb_message *** res) { + int ret; + int bLoop; long long eid = 0; - char * sql; - char * sql_constraints; - char * table_list; + long long prevEID; + char * pSql = NULL; + char * pSqlConstraints; + char * pTableList; char * hTalloc; + const char * pDN; + const char * pAttrName; + const char * pAttrValue; + sqlite3_stmt * pStmt; struct ldb_parse_tree * pTree; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -340,17 +348,21 @@ lsqlite3_search(struct ldb_module * module, talloc_steal(hTalloc, pTree); /* Convert filter into a series of SQL statements (constraints) */ - sql_constraints = parsetree_to_sql(module, hTalloc, pTree); + pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree); /* Get the list of attribute names to use as our extra table list */ - table_list = parsetree_to_tablelist(module, hTalloc, pTree); + pTableList = parsetree_to_tablelist(module, hTalloc, pTree); switch(scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry,\n" @@ -358,55 +370,133 @@ lsqlite3_search(struct ldb_module * module, " %q\n" " WHERE ldb_descendants.aeid = %lld\n" " AND ldb_entry.eid = ldb_descendants.deid\n" - " AND ldap_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldap_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; case LDB_SCOPE_BASE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM %q\n" " WHERE ldb_entry.eid = %lld\n" - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldb_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; case LDB_SCOPE_ONELEVEL: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry AS pchild, " " %q\n" " WHERE ldb_entry.eid = pchild.eid " " AND pchild.peid = %lld " - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldb_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; } -#warning "retrieve and return the result set of the search here" + /* Initially, we have no old eid */ + prevEID = -1; + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pSql, + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + ret = -1; + break; + } + + /* Loop through the returned rows */ + do { + /* Get the next row */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { + + /* Get the values from this row */ + eid = sqlite3_column_int64(pStmt, 0); + pDN = sqlite3_column_text(pStmt, 1); + pAttrName = sqlite3_column_text(pStmt, 2); + pAttrValue = sqlite3_column_text(pStmt, 3); + + /* Add this row data to the return results */ +#warning "finish returning the result set of the search here" + } + } while (ret == SQLITE_ROW); + + if (ret == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_DONE) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } + /* End the transaction */ QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); - return 0; + /* We're alll done with this query */ + sqlite3_free(pSql); + + return ret; } @@ -559,11 +649,7 @@ initialize(struct lsqlite3_private *lsqlite3, " create_timestamp INTEGER," " -- Time when the entry was last modified" - " modify_timestamp INTEGER," - - " -- Attributes of this entry, in the form" - " -- attr\1value\0[attr\1value\0]*\0" - " entry_data TEXT" + " modify_timestamp INTEGER" ");" @@ -603,6 +689,16 @@ initialize(struct lsqlite3_private *lsqlite3, " tree_key TEXT UNIQUE" ");" + "/*" + " * We keep a full listing of attribute/value pairs here" + " */" + "CREATE TABLE ldb_attribute_values" + "(" + " eid INTEGER REFERENCES ldb_entry," + " attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME" + " attr_value TEXT" + ");" + "/*" " * There is one attribute table per searchable attribute." " */" @@ -793,7 +889,9 @@ query_norows(const struct lsqlite3_private *lsqlite3, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + &pTail)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { ret = -1; break; } @@ -878,12 +976,14 @@ query_int(const struct lsqlite3_private * lsqlite3, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + &pTail)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { ret = -1; break; } - /* No rows expected, so just step through machine code once */ + /* One row expected */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); continue; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index dddca8d48f..b02b806150 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -37,11 +37,7 @@ create_timestamp INTEGER, -- Time when the entry was last modified - modify_timestamp INTEGER, - - -- Attributes of this entry, in the form - -- attr\1value\0[attr\1value\0]*\0 - entry_data TEXT + modify_timestamp INTEGER ); @@ -80,6 +76,19 @@ tree_key TEXT UNIQUE ); + /* + * We keep a full listing of attribute/value pairs here + */ + CREATE TABLE ldb_attribute_values + ( + eid INTEGER REFERENCES ldb_entry, + + attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME + + attr_value TEXT + ); + + /* * There is one attribute table per searchable attribute. */ -- cgit From 87acba39f9e45eb6849cfd945ce6255bac5564c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 05:18:17 +0000 Subject: r7514: make the ldb_parse code not depend on a ldb_context, so we can now potentially use it in our ldap client code, instead of replicating all the code (This used to be commit 5b3575d9303d54a771e080a670dcd2f444b10c20) --- source4/lib/ldb/common/ldb_parse.c | 16 +++------------- source4/lib/ldb/include/ldb_parse.h | 3 +-- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- 3 files changed, 5 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 5221ef4556..e64e6d82d3 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -43,7 +43,6 @@ #include "includes.h" #include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_parse.h" #include @@ -327,22 +326,13 @@ static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s) expression ::= | */ -struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s) +struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) { while (isspace(*s)) s++; if (*s == '(') { - return ldb_parse_filter(ldb, &s); + return ldb_parse_filter(mem_ctx, &s); } - return ldb_parse_simple(ldb, s); + return ldb_parse_simple(mem_ctx, s); } - -/* - free a parse tree returned from ldb_parse_tree() -*/ -void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree) -{ - talloc_free(tree); -} - diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h index d9125d05ed..50a9382534 100644 --- a/source4/lib/ldb/include/ldb_parse.h +++ b/source4/lib/ldb/include/ldb_parse.h @@ -54,7 +54,6 @@ struct ldb_parse_tree { } u; }; -struct ldb_parse_tree *ldb_parse_tree(struct ldb_context *ldb, const char *s); -void ldb_parse_tree_free(struct ldb_context *ldb, struct ldb_parse_tree *tree); +struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); #endif diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 7883ee6e7b..e036ae0966 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -506,7 +506,7 @@ int ltdb_search(struct ldb_module *module, const char *base, } } - ldb_parse_tree_free(ldb, tree); + talloc_free(tree); ltdb_unlock_read(module); return ret; -- cgit From 9cb3b2d49bf4093f9eff8cd26a0c9c994da5d096 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 05:33:55 +0000 Subject: r7515: merge in the binary encode/decode enhancements from the libcli/ldap/ code into the ldb parse code (This used to be commit 12647e37223847da810c2d4e5f83328b1fcf88cb) --- source4/lib/ldb/common/ldb_parse.c | 70 +++++++++++++++++++++++++++++++++++-- source4/lib/ldb/include/ldb_parse.h | 1 + 2 files changed, 69 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index e64e6d82d3..80841054c6 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -126,6 +126,73 @@ static const char *match_brace(const char *s) return s; } +/* + decode a RFC2254 binary string representation of a buffer. + Used in LDAP filters. +*/ +struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) +{ + int i, j; + struct ldb_val ret; + int slen = strlen(str); + + ret.data = talloc_size(ctx, slen); + ret.length = 0; + if (ret.data == NULL) return ret; + + for (i=j=0;ioperation = LDB_OP_SIMPLE; ret->u.simple.attr = l; - ret->u.simple.value.data = val?val:discard_const_p(char, ""); - ret->u.simple.value.length = val?strlen(val):0; + ret->u.simple.value = ldb_binary_decode(ret, val); return ret; } diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h index 50a9382534..741a8af618 100644 --- a/source4/lib/ldb/include/ldb_parse.h +++ b/source4/lib/ldb/include/ldb_parse.h @@ -55,5 +55,6 @@ struct ldb_parse_tree { }; struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); +const char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val); #endif -- cgit From e1fa7352ca0c27516f61e85ddf38477a70f12331 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 05:56:46 +0000 Subject: r7516: make sure binary decoding gives us something we can run string functions on (This used to be commit 9913ab2550fae465c7a66fe7fa3a36a65b25b358) --- source4/lib/ldb/common/ldb_parse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 80841054c6..40e83f01bd 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -136,7 +136,7 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) struct ldb_val ret; int slen = strlen(str); - ret.data = talloc_size(ctx, slen); + ret.data = talloc_size(ctx, slen+1); ret.length = 0; if (ret.data == NULL) return ret; @@ -155,6 +155,7 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) } } ret.length = j; + ((uint8_t *)ret.data)[j] = 0; return ret; } -- cgit From d94805ea55aef50403ecf6570039319a4505f835 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 05:58:49 +0000 Subject: r7517: handle zero length equality tests (This used to be commit 18c96f2b3e4d4c769354d61a4cda5c295f50536f) --- source4/lib/ldb/common/ldb_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 40e83f01bd..8058cceed4 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -134,7 +134,7 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) { int i, j; struct ldb_val ret; - int slen = strlen(str); + int slen = str?strlen(str):0; ret.data = talloc_size(ctx, slen+1); ret.length = 0; -- cgit From 490a5a5d595c021771fb6965829a3821d6dddb6a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 06:02:55 +0000 Subject: r7518: don't use an uninitialised ldb debug function when failing to load modules in the ldap backend (This used to be commit 52e4a5b3b0c4c96bf9686ce047ccfc1846dc2c89) --- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index c62c1b9e56..95b620f571 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -483,6 +483,8 @@ struct ldb_context *lldb_connect(const char *url, goto failed; } + ldb->debug_ops.debug = NULL; + lldb = talloc(ldb, struct lldb_private); if (!lldb) { errno = ENOMEM; -- cgit From e5c70a58873d5f274ec38d85884e0e76bbbaa291 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 06:52:48 +0000 Subject: r7522: added a ldb_filter_from_tree() function that takes a ldb_parse_tree and forms a ldab search filter expression. Next step is to make our ldap server code go from ASN.1 to a ldb_parse_tree, instead of trying to construct string filters, then add a ldb_search_tree() call to allow for searches using parse trees. all of this is being done as I am hitting bitwise '&' ldap search expressions from w2k, and want to handle them cleanly. (This used to be commit 04356c1b1ed86d72934bc1b0ed60b767e10a1196) --- source4/lib/ldb/common/ldb_parse.c | 55 ++++++++++++++++++++++++++++++++++++- source4/lib/ldb/include/ldb_parse.h | 5 ++-- 2 files changed, 57 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 8058cceed4..e2eb0f8c78 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -165,7 +165,7 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) encode a blob as a RFC2254 binary string, escaping any non-printable or '\' characters */ -const char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val) +char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val) { int i; char *ret; @@ -403,3 +403,56 @@ struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) return ldb_parse_simple(mem_ctx, s); } + + +/* + construct a ldap parse filter given a parse tree +*/ +char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree) +{ + char *s, *s2, *ret; + int i; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + s = ldb_binary_encode(mem_ctx, tree->u.simple.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s=%s)", + tree->u.simple.attr, s); + talloc_free(s); + return ret; + case LDB_OP_AND: + case LDB_OP_OR: + ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); + if (ret == NULL) return NULL; + for (i=0;iu.list.num_elements;i++) { + s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + s2 = talloc_asprintf_append(ret, "%s", s); + talloc_free(s); + if (s2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = s2; + } + s = talloc_asprintf_append(ret, ")"); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + return s; + case LDB_OP_NOT: + s = ldb_filter_from_tree(mem_ctx, tree->u.not.child); + if (s == NULL) return NULL; + + ret = talloc_asprintf(mem_ctx, "(!%s)", s); + talloc_free(s); + return ret; + } + + return NULL; +} diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h index 741a8af618..c8d89d2165 100644 --- a/source4/lib/ldb/include/ldb_parse.h +++ b/source4/lib/ldb/include/ldb_parse.h @@ -35,7 +35,7 @@ #ifndef _LDB_PARSE_H #define _LDB_PARSE_H 1 -enum ldb_parse_op {LDB_OP_SIMPLE, LDB_OP_AND, LDB_OP_OR, LDB_OP_NOT}; +enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; struct ldb_parse_tree { enum ldb_parse_op operation; @@ -55,6 +55,7 @@ struct ldb_parse_tree { }; struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); -const char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val); +char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree); +char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val); #endif -- cgit From 2b4791ae733488845b2c36bca64db695203de571 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Jun 2005 08:12:39 +0000 Subject: r7525: Unify lp_load(), load_interfaces and logging setup into popt(). There is now a new --debug-stderr option to enable debug to STDERR. popt isn't perfect, but the callbacks are used in all the main Samba binaries, and should be used in the rest. This avoids duplicated code, and ensures every binary is setup correctly. This also ensures the setup happens early enough to have -s function, and have a correct impact on the credentials code. (Fixing a bug that frustrated tridge earlier today). The only 'subtle' aspect of all this is that I'm pretty sure that the SAMBA_COMMON popt code must be above the CREDENTIALS code, in the popt tables. Andrew Bartlett (This used to be commit 50f3c2b3a22971f40e0d3a88127b5120bfc47591) --- source4/lib/cmdline/popt_common.c | 22 +++++++++++++++++----- source4/lib/debug.c | 22 ++++++++++++++++------ source4/lib/registry/tools/regdiff.c | 10 +++------- source4/lib/registry/tools/regpatch.c | 10 ++-------- source4/lib/registry/tools/regshell.c | 11 +++-------- source4/lib/registry/tools/regtree.c | 10 ++-------- 6 files changed, 43 insertions(+), 42 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 94b72c520d..fec85281ef 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -38,7 +38,7 @@ * -i,--scope */ -enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL}; +enum {OPT_OPTION=1,OPT_LEAK_REPORT,OPT_LEAK_REPORT_FULL, OPT_DEBUG_STDERR}; struct cli_credentials *cmdline_credentials = NULL; @@ -49,6 +49,14 @@ static void popt_common_callback(poptContext con, { const char *pname; + if (reason == POPT_CALLBACK_REASON_POST) { + /* Hook any 'every Samba program must do this, after + * the smb.conf is setup' functions here */ + lp_load(dyn_CONFIGFILE,True,False,False); + load_interfaces(); + return; + } + /* Find out basename of current program */ pname = strrchr_m(poptGetInvocationName(con),'/'); @@ -58,9 +66,7 @@ static void popt_common_callback(poptContext con, pname++; if (reason == POPT_CALLBACK_REASON_PRE) { - char *logfile = talloc_asprintf(NULL, "%s/log.%s", dyn_LOGFILEBASE, pname); - lp_set_cmdline("log file", logfile); - talloc_free(logfile); + setup_logging(pname, DEBUG_STDOUT); return; } @@ -69,6 +75,10 @@ static void popt_common_callback(poptContext con, lp_set_cmdline("log level", arg); break; + case OPT_DEBUG_STDERR: + setup_logging(pname, DEBUG_STDERR); + break; + case 'V': printf( "Version %s\n", SAMBA_VERSION_STRING ); exit(0); @@ -128,6 +138,7 @@ static void popt_common_callback(poptContext con, case OPT_LEAK_REPORT_FULL: talloc_enable_leak_report_full(); break; + } } @@ -143,8 +154,9 @@ struct poptOption popt_common_connection[] = { }; struct poptOption popt_common_samba[] = { - { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback }, + { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, popt_common_callback }, { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" }, + { "debug-stderr", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_STDERR, "Send debug output to STDERR", NULL }, { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" }, { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" }, { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" }, diff --git a/source4/lib/debug.c b/source4/lib/debug.c index ab012a98aa..a775c46854 100644 --- a/source4/lib/debug.c +++ b/source4/lib/debug.c @@ -74,8 +74,6 @@ void reopen_logs(void) char *fname = NULL; int old_fd = state.fd; - state.fd = 0; - switch (state.logtype) { case DEBUG_STDOUT: state.fd = 1; @@ -89,12 +87,20 @@ void reopen_logs(void) if ((*logfile) == '/') { fname = strdup(logfile); } else { - asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, logfile); + asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, state.prog_name); } if (fname) { - state.fd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0644); + int newfd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0600); + if (newfd == -1) { + DEBUG(1, ("Failed to open new logfile: %s\n", fname)); + } else { + state.fd = newfd; + } free(fname); + } else { + DEBUG(1, ("Failed to find name for file-based logfile!\n")); } + break; } @@ -109,8 +115,12 @@ void reopen_logs(void) */ void setup_logging(const char *prog_name, enum debug_logtype new_logtype) { - state.logtype = new_logtype; - state.prog_name = prog_name; + if (state.logtype < new_logtype) { + state.logtype = new_logtype; + } + if (prog_name) { + state.prog_name = prog_name; + } reopen_logs(); } diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 4260a56142..f86c0ae383 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -121,21 +121,18 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, WERROR error, error2; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_CREDENTIALS {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL", NULL }, {"remote", 'R', POPT_ARG_STRING, NULL, 0, "Connect to remote server" , NULL }, {"local", 'L', POPT_ARG_NONE, NULL, 0, "Open local registry", NULL }, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + POPT_COMMON_VERSION POPT_TABLEEND }; regdiff_init_subsystems; - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); - } - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { @@ -157,7 +154,6 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, return 1; } } - setup_logging(argv[0], DEBUG_STDOUT); poptFreeContext(pc); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 5c9851b71b..02ef4d4655 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -749,25 +749,19 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_CREDENTIALS {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS POPT_TABLEEND }; regpatch_init_subsystems; - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); - } - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging(argv[0], DEBUG_STDOUT); - if (remote) { error = reg_open_remote (&h, cmdline_credentials, remote); } else { diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 03cb09c443..0c53f737b8 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -374,26 +374,21 @@ static char **reg_completion(const char *text, int start, int end) struct registry_context *h = NULL; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + POPT_COMMON_VERSION POPT_TABLEEND }; regshell_init_subsystems; - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); - } - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging("regtree", DEBUG_STDOUT); - if (remote) { error = reg_open_remote (&h, cmdline_credentials, remote); } else if (backend) { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 2cf5f6ab96..f18467b523 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -82,28 +82,22 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) int fullpath = 0, no_values = 0; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL }, {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS POPT_TABLEEND }; regtree_init_subsystems; - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); - } - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { } - setup_logging("regtree", DEBUG_STDOUT); - if (remote) { error = reg_open_remote(&h, cmdline_credentials, remote); } else if (backend) { -- cgit From d71e1a7a7fe363d27a0e8256ccfb4cec425c13b5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 09:04:01 +0000 Subject: r7526: make test should depend on the bins (This used to be commit 646953df4c272581211ba30dc77e1052ea1f465e) --- source4/lib/ldb/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index b335331b29..f638b340a1 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -148,7 +148,7 @@ test-schema: @echo "STARTING SCHEMA MODULE TEST" tests/test-schema.sh -test: test-tdb test-ldap test-sqlite3 test-schema +test: $(BINS) test-tdb test-ldap test-sqlite3 test-schema install: all cp include/ldb.h $(includedir) -- cgit From 4b0e5bd75373ffa2d847706a71fd0349dfa15e71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 09:10:17 +0000 Subject: r7527: - added a ldb_search_bytree() interface, which takes a ldb_parse_tree instead of a search expression. This allows our ldap server to pass its ASN.1 parsed search expressions straight to ldb, instead of going via strings. - updated all the ldb modules code to handle the new interface - got rid of the separate ldb_parse.h now that the ldb_parse structures are exposed externally - moved to C99 structure initialisation in ldb - switched ldap server to using ldb_search_bytree() (This used to be commit 96620ab2ee5d440bbbc51c1bc0cad9977770f897) --- source4/lib/ldb/common/ldb.c | 17 +++++++++ source4/lib/ldb/common/ldb_modules.c | 20 ++++++++-- source4/lib/ldb/common/ldb_msg.c | 3 +- source4/lib/ldb/common/ldb_parse.c | 47 ++++++++++++------------ source4/lib/ldb/include/ldb.h | 34 +++++++++++++++++ source4/lib/ldb/include/ldb_parse.h | 61 ------------------------------- source4/lib/ldb/include/ldb_private.h | 7 ++++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 40 +++++++++++++++----- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 20 +++++----- source4/lib/ldb/ldb_tdb/ldb_index.c | 1 - source4/lib/ldb/ldb_tdb/ldb_match.c | 1 - source4/lib/ldb/ldb_tdb/ldb_search.c | 42 +++++++++++++-------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 19 +++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 ++ source4/lib/ldb/modules/schema.c | 26 ++++++++----- source4/lib/ldb/modules/skel.c | 1 + source4/lib/ldb/modules/timestamps.c | 27 +++++++++----- 17 files changed, 216 insertions(+), 154 deletions(-) delete mode 100644 source4/lib/ldb/include/ldb_parse.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 649b0a0f24..f5c6d551ea 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -100,6 +100,23 @@ int ldb_search(struct ldb_context *ldb, return ldb->modules->ops->search(ldb->modules, base, scope, expression, attrs, res); } +/* + search the database given a LDAP-like search expression + + return the number of records found, or -1 on error + + Use talloc_free to free the ldb_message returned in 'res' + +*/ +int ldb_search_bytree(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb->modules->ops->search_bytree(ldb->modules, base, scope, tree, attrs, res); +} + /* add a record to the database. Will fail if a record with the given class and key already exists diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 644154d645..7df9901ae9 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -213,10 +213,10 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) */ int ldb_next_search(struct ldb_module *module, - const char *base, - enum ldb_scope scope, - const char *expression, - const char * const *attrs, struct ldb_message ***res) + const char *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, struct ldb_message ***res) { if (!module->next) { return -1; @@ -224,6 +224,18 @@ int ldb_next_search(struct ldb_module *module, return module->next->ops->search(module->next, base, scope, expression, attrs, res); } +int ldb_next_search_bytree(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + if (!module->next) { + return -1; + } + return module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); +} + int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message) { if (!module->next) { diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 7a6dea049a..8d921b989b 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -95,8 +95,7 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, /* duplicate a ldb_val structure */ -struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, - const struct ldb_val *v) +struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v) { struct ldb_val v2; v2.length = v->length; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index e2eb0f8c78..afcda60e8e 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -43,7 +43,6 @@ #include "includes.h" #include "ldb/include/ldb.h" -#include "ldb/include/ldb_parse.h" #include @@ -64,7 +63,7 @@ a filter is defined by: /* return next token element. Caller frees */ -static char *ldb_parse_lex(TALLOC_CTX *ctx, const char **s, const char *sep) +static char *ldb_parse_lex(void *ctx, const char **s, const char *sep) { const char *p = *s; char *ret; @@ -130,13 +129,13 @@ static const char *match_brace(const char *s) decode a RFC2254 binary string representation of a buffer. Used in LDAP filters. */ -struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) +struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str) { int i, j; struct ldb_val ret; int slen = str?strlen(str):0; - ret.data = talloc_size(ctx, slen+1); + ret.data = talloc_size(mem_ctx, slen+1); ret.length = 0; if (ret.data == NULL) return ret; @@ -165,7 +164,7 @@ struct ldb_val ldb_binary_decode(TALLOC_CTX *ctx, const char *str) encode a blob as a RFC2254 binary string, escaping any non-printable or '\' characters */ -char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val) +char *ldb_binary_encode(void *mem_ctx, struct ldb_val val) { int i; char *ret; @@ -177,7 +176,7 @@ char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val) len += 2; } } - ret = talloc_array(ctx, char, len+1); + ret = talloc_array(mem_ctx, char, len+1); if (ret == NULL) return NULL; len = 0; @@ -195,17 +194,17 @@ char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val) return ret; } -static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s); +static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s); /* ::= */ -static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) { char *eq, *val, *l; struct ldb_parse_tree *ret; - ret = talloc(ctx, struct ldb_parse_tree); + ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -249,12 +248,12 @@ static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *ctx, const char *s) ::= '|' ::= | */ -static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, +static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, enum ldb_parse_op op, const char *s) { struct ldb_parse_tree *ret, *next; - ret = talloc(ctx, struct ldb_parse_tree); + ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -300,11 +299,11 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *ctx, /* ::= '!' */ -static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) { struct ldb_parse_tree *ret; - ret = talloc(ctx, struct ldb_parse_tree); + ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; @@ -324,39 +323,39 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *ctx, const char *s) parse a filtercomp ::= | | | */ -static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char *s) { while (isspace(*s)) s++; switch (*s) { case '&': - return ldb_parse_filterlist(ctx, LDB_OP_AND, s+1); + return ldb_parse_filterlist(mem_ctx, LDB_OP_AND, s+1); case '|': - return ldb_parse_filterlist(ctx, LDB_OP_OR, s+1); + return ldb_parse_filterlist(mem_ctx, LDB_OP_OR, s+1); case '!': - return ldb_parse_not(ctx, s+1); + return ldb_parse_not(mem_ctx, s+1); case '(': case ')': return NULL; } - return ldb_parse_simple(ctx, s); + return ldb_parse_simple(mem_ctx, s); } /* ::= '(' ')' */ -static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s) +static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) { char *l, *s2; const char *p, *p2; struct ldb_parse_tree *ret; - l = ldb_parse_lex(ctx, s, LDB_ALL_SEP); + l = ldb_parse_lex(mem_ctx, s, LDB_ALL_SEP); if (!l) { return NULL; } @@ -373,13 +372,13 @@ static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s) } p2 = p + 1; - s2 = talloc_strndup(ctx, *s, p - *s); + s2 = talloc_strndup(mem_ctx, *s, p - *s); if (!s2) { errno = ENOMEM; return NULL; } - ret = ldb_parse_filtercomp(ctx, s2); + ret = ldb_parse_filtercomp(mem_ctx, s2); talloc_free(s2); *s = p2; @@ -393,7 +392,7 @@ static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *ctx, const char **s) expression ::= | */ -struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) +struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) { while (isspace(*s)) s++; @@ -408,7 +407,7 @@ struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) /* construct a ldap parse filter given a parse tree */ -char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree) +char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) { char *s, *s2, *ret; int i; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 91a826447a..02df0ae810 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -145,6 +145,31 @@ struct ldb_debug_ops { #endif +/* structues for ldb_parse_tree handling code */ +enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; + +struct ldb_parse_tree { + enum ldb_parse_op operation; + union { + struct { + char *attr; + struct ldb_val value; + } simple; + struct { + unsigned int num_elements; + struct ldb_parse_tree **elements; + } list; + struct { + struct ldb_parse_tree *child; + } not; + } u; +}; + +struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s); +char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree); +char *ldb_binary_encode(void *ctx, struct ldb_val val); + + /* connect to a database. The URL can either be one of the following forms ldb://path @@ -171,6 +196,15 @@ int ldb_search(struct ldb_context *ldb, const char *expression, const char * const *attrs, struct ldb_message ***res); +/* + like ldb_search() but takes a parse tree +*/ +int ldb_search_bytree(struct ldb_context *ldb, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res); + /* add a record to the database. Will fail if a record with the given class and key already exists diff --git a/source4/lib/ldb/include/ldb_parse.h b/source4/lib/ldb/include/ldb_parse.h deleted file mode 100644 index c8d89d2165..0000000000 --- a/source4/lib/ldb/include/ldb_parse.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb expression parse header - * - * Description: structure for expression parsing - * - * Author: Andrew Tridgell - */ - -#ifndef _LDB_PARSE_H -#define _LDB_PARSE_H 1 - -enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; - -struct ldb_parse_tree { - enum ldb_parse_op operation; - union { - struct { - char *attr; - struct ldb_val value; - } simple; - struct { - unsigned int num_elements; - struct ldb_parse_tree **elements; - } list; - struct { - struct ldb_parse_tree *child; - } not; - } u; -}; - -struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); -char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree); -char *ldb_binary_encode(TALLOC_CTX *ctx, struct ldb_val val); - -#endif diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 69bf4a6dc6..414d8c14a1 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -57,6 +57,8 @@ struct ldb_module_ops { const char *name; int (*search)(struct ldb_module *, const char *, enum ldb_scope, const char *, const char * const [], struct ldb_message ***); + int (*search_bytree)(struct ldb_module *, const char *, enum ldb_scope, + struct ldb_parse_tree *, const char * const [], struct ldb_message ***); int (*add_record)(struct ldb_module *, const struct ldb_message *); int (*modify_record)(struct ldb_module *, const struct ldb_message *); int (*delete_record)(struct ldb_module *, const char *); @@ -88,6 +90,11 @@ int ldb_next_search(struct ldb_module *module, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res); +int ldb_next_search_bytree(struct ldb_module *module, + const char *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res); int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_delete_record(struct ldb_module *module, const char *dn); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 95b620f571..fceaf02196 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -285,6 +285,27 @@ failed: } +/* + search for matching records using a ldb_parse_tree +*/ +static int lldb_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct lldb_private *lldb = module->private_data; + char *expression; + int ret; + + expression = ldb_filter_from_tree(lldb, tree); + if (expression == NULL) { + return -1; + } + ret = lldb_search(module, base, scope, expression, attrs, res); + talloc_free(expression); + return ret; +} + + /* convert a ldb_message structure to a list of LDAPMod structures ready for ldap_add() or ldap_modify() @@ -447,15 +468,16 @@ static const char *lldb_errstring(struct ldb_module *module) static const struct ldb_module_ops lldb_ops = { - "ldap", - lldb_search, - lldb_add, - lldb_modify, - lldb_delete, - lldb_rename, - lldb_lock, - lldb_unlock, - lldb_errstring + .name = "ldap", + .search = lldb_search, + .search_bytree = lldb_search_bytree, + .add_record = lldb_add, + .modify_record = lldb_modify, + .delete_record = lldb_delete, + .rename_record = lldb_rename, + .named_lock = lldb_lock, + .named_unlock = lldb_unlock, + .errstring = lldb_errstring }; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index d9e72c8089..747938116a 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -36,7 +36,6 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include "ldb/include/ldb_parse.h" #include "ldb/include/ldb_explode_dn.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" @@ -162,15 +161,16 @@ new_attr(struct ldb_module * module, * Table of operations for the sqlite3 backend */ static const struct ldb_module_ops lsqlite3_ops = { - "sqlite", - lsqlite3_search, - lsqlite3_add, - lsqlite3_modify, - lsqlite3_delete, - lsqlite3_rename, - lsqlite3_lock, - lsqlite3_unlock, - lsqlite3_errstring + .name = "sqlite", + .search = lsqlite3_search, + .search_bytree = lsqlite3_search_bytree, + .add_record = lsqlite3_add, + .modify_record = lsqlite3_modify, + .delete_record = lsqlite3_delete, + .rename_record = lsqlite3_rename, + .named_lock = lsqlite3_lock, + .named_unlock = lsqlite3_unlock, + .errstring = lsqlite3_errstring }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 1cf1b5c531..b6ba413ba5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -36,7 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" -#include "ldb/include/ldb_parse.h" /* find an element in a list, using the given comparison function and diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 3bb63e2b5b..abaa5e98c6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -36,7 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" -#include "ldb/include/ldb_parse.h" #include /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index e036ae0966..17eff6f0a6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -36,7 +36,6 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" -#include "ldb/include/ldb_parse.h" /* add one element to a message @@ -463,13 +462,11 @@ static int ltdb_search_full(struct ldb_module *module, search the database with a LDAP-like expression. choses a search method */ -int ltdb_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const attrs[], struct ldb_message ***res) +int ltdb_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const attrs[], struct ldb_message ***res) { - struct ldb_context *ldb = module->ldb; struct ltdb_private *ltdb = module->private_data; - struct ldb_parse_tree *tree; int ret; if (ltdb_lock_read(module) != 0) { @@ -485,14 +482,6 @@ int ltdb_search(struct ldb_module *module, const char *base, *res = NULL; - /* form a parse tree for the expression */ - tree = ldb_parse_tree(ldb, expression); - if (!tree) { - ltdb->last_err_string = "expression parse failed"; - ltdb_unlock_read(module); - return -1; - } - if (tree->operation == LDB_OP_SIMPLE && (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 || ldb_attr_cmp(tree->u.simple.attr, "distinguishedName") == 0) && @@ -506,9 +495,32 @@ int ltdb_search(struct ldb_module *module, const char *base, } } - talloc_free(tree); ltdb_unlock_read(module); return ret; } + +/* + search the database with a LDAP-like expression. + choses a search method +*/ +int ltdb_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const attrs[], struct ldb_message ***res) +{ + struct ltdb_private *ltdb = module->private_data; + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(ltdb, expression); + if (tree == NULL) { + ltdb->last_err_string = "expression parse failed"; + return -1; + } + + ret = ltdb_search_bytree(module, base, scope, tree, attrs, res); + talloc_free(tree); + return ret; +} + diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 9c126c1dfd..0366809c33 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -800,15 +800,16 @@ static const char *ltdb_errstring(struct ldb_module *module) static const struct ldb_module_ops ltdb_ops = { - "tdb", - ltdb_search, - ltdb_add, - ltdb_modify, - ltdb_delete, - ltdb_rename, - ltdb_lock, - ltdb_unlock, - ltdb_errstring + .name = "tdb", + .search = ltdb_search, + .search_bytree = ltdb_search_bytree, + .add_record = ltdb_add, + .modify_record = ltdb_modify, + .delete_record = ltdb_delete, + .rename_record = ltdb_rename, + .named_lock = ltdb_lock, + .named_unlock = ltdb_unlock, + .errstring = ltdb_errstring }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index eb6c7825d2..891522f300 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -100,6 +100,10 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, int ltdb_search(struct ldb_module *module, const char *base, enum ldb_scope scope, const char *expression, const char * const attrs[], struct ldb_message ***res); +int ltdb_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const attrs[], struct ldb_message ***res); + /* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn); diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 29e5194416..e11c8b4e4e 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -306,6 +306,13 @@ static int schema_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } +static int schema_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -541,15 +548,16 @@ static int schema_destructor(void *module_ctx) } static const struct ldb_module_ops schema_ops = { - "schema", - schema_search, - schema_add_record, - schema_modify_record, - schema_delete_record, - schema_rename_record, - schema_named_lock, - schema_named_unlock, - schema_errstring, + .name = "schema", + .search = schema_search, + .search_bytree = schema_search_bytree, + .add_record = schema_add_record, + .modify_record = schema_modify_record, + .delete_record = schema_delete_record, + .rename_record = schema_rename_record, + .named_lock = schema_named_lock, + .named_unlock = schema_named_unlock, + .errstring = schema_errstring, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 505b19a288..1221ac70f1 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -103,6 +103,7 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { .name = "skel", .search = skel_search, + .search_bytree = skel_search_bytree, .add_record = skel_add_record, .modify_record = skel_modify_record, .delete_record = skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 1c01bd14fd..c1db85a284 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -49,6 +49,14 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } +static int timestamps_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { @@ -247,15 +255,16 @@ static int timestamps_destructor(void *module_ctx) } static const struct ldb_module_ops timestamps_ops = { - "timestamps", - timestamps_search, - timestamps_add_record, - timestamps_modify_record, - timestamps_delete_record, - timestamps_rename_record, - timestamps_lock, - timestamps_unlock, - timestamps_errstring + .name = "timestamps", + .search = timestamps_search, + .search_bytree = timestamps_search_bytree, + .add_record = timestamps_add_record, + .modify_record = timestamps_modify_record, + .delete_record = timestamps_delete_record, + .rename_record = timestamps_rename_record, + .named_lock = timestamps_lock, + .named_unlock = timestamps_unlock, + .errstring = timestamps_errstring }; -- cgit From 00e2b7c1b49b128488cf977b40b086b935fb605a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Jun 2005 10:01:11 +0000 Subject: r7530: Simply calling convention of lp_load(). This always loads all the services, as we now don't have an easy way to split out smbd. Andrew Bartlett (This used to be commit 990e061939c76b559c4f5914c5fc6ca1b13e19dd) --- source4/lib/cmdline/popt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index fec85281ef..fb7356dc0e 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -52,7 +52,7 @@ static void popt_common_callback(poptContext con, if (reason == POPT_CALLBACK_REASON_POST) { /* Hook any 'every Samba program must do this, after * the smb.conf is setup' functions here */ - lp_load(dyn_CONFIGFILE,True,False,False); + lp_load(dyn_CONFIGFILE); load_interfaces(); return; } -- cgit From 734ff692f3efb9604031bf5741a09cff65f50d5e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Jun 2005 12:37:37 +0000 Subject: r7533: don't show compile flags for each file (This used to be commit 6a9ab148a98490e52da81d4ddedf42af2b5bf1a7) --- source4/lib/ldb/Makefile.in | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index f638b340a1..3bfae08c27 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -68,6 +68,10 @@ DIRS = lib bin all: $(DIRS) $(BINS) $(LIBS) manpages +.c.o: + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $< -o $@ + lib: mkdir -p lib -- cgit From 4a139f81719a0105c93258b985de31a71a4766dc Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 14 Jun 2005 01:04:20 +0000 Subject: r7556: fixed typo in documentation (This used to be commit 77fc2036a0db7bde9e90f090dbcd75ea70b3e0a0) --- source4/lib/talloc/talloc_guide.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index c23ac77cad..d30538bf9f 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -284,8 +284,8 @@ talloc_realloc() has the following equivalences: talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N); talloc_realloc(context, ptr, type, 0) ==> talloc_free(ptr); -The "context" argument is only used if "ptr" is not NULL, otherwise it -is ignored. +The "context" argument is only used if "ptr" is NULL, otherwise it is +ignored. talloc_realloc() returns the new pointer, or NULL on failure. The call will fail either due to a lack of memory, or because the pointer has -- cgit From 4fec6356ea190d202783fe19013387462a22c441 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 01:35:44 +0000 Subject: r7558: added support in ldb for extended ldap search requests. These are using to perform such things as bitop tests on integers. So far I have only added support for the 1.2.840.113556.1.4.803 and 1.2.840.113556.1.4.804 rules, which are for bitwise and/or (This used to be commit 5f773b065f1db959e59c02de68bcf30cef1a6c2c) --- source4/lib/ldb/common/ldb_parse.c | 71 +++++++++++++++++++ source4/lib/ldb/include/ldb.h | 9 ++- source4/lib/ldb/include/ldb_private.h | 4 ++ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 4 ++ source4/lib/ldb/ldb_tdb/ldb_index.c | 5 ++ source4/lib/ldb/ldb_tdb/ldb_match.c | 114 ++++++++++++++++++++++++++---- 6 files changed, 193 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index afcda60e8e..c9a35cc255 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -196,6 +196,61 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val) static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s); + +/* + parse an extended match + + possible forms: + (attr:oid:=value) + (attr:dn:oid:=value) + (attr:dn:=value) + (:dn:oid:=value) + + the ':dn' part sets the dnAttributes boolean if present + the oid sets the rule_id string + +*/ +static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, + char *attr, char *value) +{ + char *p1, *p2, *p3; + ret->operation = LDB_OP_EXTENDED; + ret->u.extended.value = ldb_binary_decode(ret, value); + p1 = strchr(attr, ':'); + if (p1 == NULL) goto failed; + p2 = strchr(p1+1, ':'); + if (p2 == NULL) goto failed; + p3 = strchr(p2+1, ':'); + + *p1 = 0; + *p2 = 0; + if (p3) *p3 = 0; + + ret->u.extended.attr = talloc_strdup(ret, attr); + if (ret->u.extended.attr == NULL) goto failed; + if (strcmp(p1+1, "dn") == 0) { + ret->u.extended.dnAttributes = 1; + if (p3) { + ret->u.extended.rule_id = talloc_strdup(ret, p2+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } else { + ret->u.extended.rule_id = NULL; + } + } else { + ret->u.extended.dnAttributes = 0; + ret->u.extended.rule_id = talloc_strdup(ret, p1+1); + if (ret->u.extended.rule_id == NULL) goto failed; + } + ret->u.extended.value = ldb_binary_decode(ret, value); + + return ret; + +failed: + talloc_free(ret); + return NULL; +} + + /* ::= */ @@ -233,6 +288,11 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) talloc_free(ret); return NULL; } + + if (l[strlen(l)-1] == ':') { + /* its an extended match */ + return ldb_parse_extended(ret, l, val); + } ret->operation = LDB_OP_SIMPLE; ret->u.simple.attr = l; @@ -420,6 +480,17 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) tree->u.simple.attr, s); talloc_free(s); return ret; + case LDB_OP_EXTENDED: + s = ldb_binary_encode(mem_ctx, tree->u.extended.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s%s%s%s=%s)", + tree->u.extended.attr?tree->u.extended.attr:"", + tree->u.extended.dnAttributes?":dn":"", + tree->u.extended.rule_id?":":"", + tree->u.extended.rule_id?tree->u.extended.rule_id:"", + s); + talloc_free(s); + return ret; case LDB_OP_AND: case LDB_OP_OR: ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 02df0ae810..5773e39fa9 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -146,7 +146,8 @@ struct ldb_debug_ops { /* structues for ldb_parse_tree handling code */ -enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; +enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_EXTENDED=2, + LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; struct ldb_parse_tree { enum ldb_parse_op operation; @@ -155,6 +156,12 @@ struct ldb_parse_tree { char *attr; struct ldb_val value; } simple; + struct { + char *attr; + int dnAttributes; + char *rule_id; + struct ldb_val value; + } extended; struct { unsigned int num_elements; struct ldb_parse_tree **elements; diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 414d8c14a1..e022d68ec7 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -82,6 +82,10 @@ struct ldb_context { /* the modules init function */ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + /* The following definitions come from lib/ldb/common/ldb_modules.c */ int ldb_load_modules(struct ldb_context *ldb, const char *options[]); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 747938116a..4089f0bdb5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1117,6 +1117,10 @@ parsetree_to_sql(struct ldb_module *module, case LDB_OP_SIMPLE: break; + case LDB_OP_EXTENDED: +#warning "derrell, you'll need to work out how to handle bitops" + return NULL; + case LDB_OP_AND: ret = parsetree_to_sql(module, hTalloc, diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index b6ba413ba5..00b124a9cf 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -550,6 +550,11 @@ static int ltdb_index_dn(struct ldb_module *module, ret = ltdb_index_dn_leaf(module, tree, index_list, list); break; + case LDB_OP_EXTENDED: + /* we can't index with fancy bitops yet */ + ret = -1; + break; + case LDB_OP_AND: ret = ltdb_index_dn_and(module, tree, index_list, list); break; diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index abaa5e98c6..5bc59383a5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -262,7 +262,8 @@ static int match_leaf(struct ldb_module *module, const char *base, enum ldb_scope scope) { - unsigned int i, j; + unsigned int i; + struct ldb_message_element *el; if (!scope_match(msg->dn, base, scope)) { return 0; @@ -275,20 +276,104 @@ static int match_leaf(struct ldb_module *module, return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; } - for (i=0;inum_elements;i++) { - if (ldb_attr_cmp(msg->elements[i].name, tree->u.simple.attr) == 0) { - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; - } - for (j=0;jelements[i].num_values;j++) { - if (ltdb_val_equal(module, msg->elements[i].name, - &msg->elements[i].values[j], - &tree->u.simple.value)) { - return 1; - } - } + el = ldb_msg_find_element(msg, tree->u.simple.attr); + if (el == NULL) { + return 0; + } + + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + + for (i=0;inum_values;i++) { + if (ltdb_val_equal(module, el->name, &el->values[i], + &tree->u.simple.value)) { + return 1; + } + } + + return 0; +} + + +/* + bitwise-and comparator +*/ +static int comparator_and(struct ldb_val *v1, struct ldb_val *v2) +{ + unsigned i1, i2; + i1 = strtoul(v1->data, NULL, 0); + i2 = strtoul(v2->data, NULL, 0); + return ((i1 & i2) == i2); +} + +/* + bitwise-or comparator +*/ +static int comparator_or(struct ldb_val *v1, struct ldb_val *v2) +{ + unsigned i1, i2; + i1 = strtoul(v1->data, NULL, 0); + i2 = strtoul(v2->data, NULL, 0); + return ((i1 & i2) != 0); +} + + +/* + extended match, handles things like bitops +*/ +static int ltdb_extended_match(struct ldb_module *module, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + int i; + const struct { + const char *oid; + int (*comparator)(struct ldb_val *, struct ldb_val *); + } rules[] = { + { "1.2.840.113556.1.4.803", comparator_and}, + { "1.2.840.113556.1.4.804", comparator_or} + }; + int (*comp)(struct ldb_val *, struct ldb_val *) = NULL; + struct ldb_message_element *el; + + if (tree->u.extended.dnAttributes) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet"); + return -1; + } + if (tree->u.extended.rule_id == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); + return -1; + } + if (tree->u.extended.attr == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); + return -1; + } + + for (i=0;iu.extended.rule_id) == 0) { + comp = rules[i].comparator; + break; } } + if (comp == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n", + tree->u.extended.rule_id); + return -1; + } + + /* find the message element */ + el = ldb_msg_find_element(msg, tree->u.extended.attr); + if (el == NULL) { + return 0; + } + + for (i=0;inum_values;i++) { + int ret = comp(&el->values[i], &tree->u.extended.value); + if (ret == -1 || ret == 1) return ret; + } return 0; } @@ -314,6 +399,9 @@ int ltdb_message_match(struct ldb_module *module, case LDB_OP_SIMPLE: break; + case LDB_OP_EXTENDED: + return ltdb_extended_match(module, msg, tree, base, scope); + case LDB_OP_NOT: return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope); -- cgit From 3f094627193994f08afc8dcf186a7a65c1c350b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 02:33:49 +0000 Subject: r7559: support 64 bit matching in bitops (This used to be commit 0c44a67001b9ae91c1ba7fc52f22d1eafc22dcc7) --- source4/lib/ldb/ldb_tdb/ldb_match.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 5bc59383a5..51b0ab9aa7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -301,9 +301,9 @@ static int match_leaf(struct ldb_module *module, */ static int comparator_and(struct ldb_val *v1, struct ldb_val *v2) { - unsigned i1, i2; - i1 = strtoul(v1->data, NULL, 0); - i2 = strtoul(v2->data, NULL, 0); + uint64_t i1, i2; + i1 = strtoull(v1->data, NULL, 0); + i2 = strtoull(v2->data, NULL, 0); return ((i1 & i2) == i2); } @@ -312,9 +312,9 @@ static int comparator_and(struct ldb_val *v1, struct ldb_val *v2) */ static int comparator_or(struct ldb_val *v1, struct ldb_val *v2) { - unsigned i1, i2; - i1 = strtoul(v1->data, NULL, 0); - i2 = strtoul(v2->data, NULL, 0); + uint64_t i1, i2; + i1 = strtoull(v1->data, NULL, 0); + i2 = strtoull(v2->data, NULL, 0); return ((i1 & i2) != 0); } -- cgit From 5ec2c79dc58f340a9635b34400797fa85361c6ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 02:34:13 +0000 Subject: r7560: added tests for extended bitop search functions (This used to be commit 7b58b3a9c53952f606eb75f5e916e0cf994b2d06) --- source4/lib/ldb/tests/test-extended.sh | 49 ++++++++++++++++++++++++++++++++++ source4/lib/ldb/tests/test-tdb.sh | 1 + 2 files changed, 50 insertions(+) create mode 100755 source4/lib/ldb/tests/test-extended.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh new file mode 100755 index 0000000000..246b55f5b9 --- /dev/null +++ b/source4/lib/ldb/tests/test-extended.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +rm -f $LDB_URL + +cat < Date: Tue, 14 Jun 2005 03:04:24 +0000 Subject: r7561: moved OID constants into ldb.h and used manifest constants in ldb_match.c (This used to be commit 42cbb155c20779c458f727488c8554842b24681b) --- source4/lib/ldb/include/ldb.h | 6 ++++++ source4/lib/ldb/ldb_tdb/ldb_match.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 5773e39fa9..7a28d05b38 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -71,6 +71,12 @@ struct ldb_val { #define LDB_FLAG_MOD_DELETE 3 +/* + well known object IDs +*/ +#define LDB_OID_COMPARATOR_AND "1.2.840.113556.1.4.803" +#define LDB_OID_COMPARATOR_OR "1.2.840.113556.1.4.804" + /* results are given back as arrays of ldb_message_element */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 51b0ab9aa7..4c11542971 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -333,8 +333,8 @@ static int ltdb_extended_match(struct ldb_module *module, const char *oid; int (*comparator)(struct ldb_val *, struct ldb_val *); } rules[] = { - { "1.2.840.113556.1.4.803", comparator_and}, - { "1.2.840.113556.1.4.804", comparator_or} + { LDB_OID_COMPARATOR_AND, comparator_and}, + { LDB_OID_COMPARATOR_OR, comparator_or} }; int (*comp)(struct ldb_val *, struct ldb_val *) = NULL; struct ldb_message_element *el; -- cgit From 81b4183e1c8f70f69b97a99265ee5020c207f9e4 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 14 Jun 2005 03:08:34 +0000 Subject: r7562: work in progress (This used to be commit d8a9ce78533639f510b60b48c8f305bd07f3f717) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 1022 ++++++++++++++++++++--------- 1 file changed, 699 insertions(+), 323 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 4089f0bdb5..dbbb775928 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -48,27 +48,30 @@ # define TRUE (! FALSE) #endif +#define FILTER_ATTR_TABLE "temp_filter_attrs" +#define RESULT_ATTR_TABLE "temp_result_attrs" + #define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ - do { \ - if (query_norows(lsqlite3, sql) != 0) { \ - if (bRollbackOnError) { \ - query_norows(lsqlite3, \ - "ROLLBACK;"); \ + do { \ + if (query_norows(lsqlite3, sql) != 0) { \ + if (bRollbackOnError) { \ + query_norows(lsqlite3, \ + "ROLLBACK;"); \ + } \ + return -1; \ } \ - return -1; \ - } \ - } while (0) + } while (0) #define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \ - do { \ - if (query_int(lsqlite3, &result_var, sql) != 0) { \ - if (bRollbackOnError) { \ - query_norows(lsqlite3, \ - "ROLLBACK;"); \ - } \ - return -1; \ - } \ - } while (0) + do { \ + if (query_int(lsqlite3, &result_var, sql) != 0) { \ + if (bRollbackOnError) { \ + query_norows(lsqlite3, \ + "ROLLBACK;"); \ + } \ + return -1; \ + } \ + } while (0) /* @@ -83,13 +86,21 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn); +static int +lsqlite3_search_bytree(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + struct ldb_parse_tree * pTree, + const char * const * attrs, + struct ldb_message *** pppRes); + static int lsqlite3_search(struct ldb_module * module, const char * pBaseDN, enum ldb_scope scope, const char * pExpression, const char * const attrs[], - struct ldb_message *** res); + struct ldb_message *** pppRes); static int lsqlite3_add(struct ldb_module *module, @@ -131,15 +142,28 @@ query_int(const struct lsqlite3_private * lsqlite3, static int case_fold_attr_required(void * hUserData, char *attr); +static int +add_msg_attr(void * hTalloc, + long long eid, + const char * pDN, + const char * pAttrName, + const char * pAttrValue, + long long prevEID, + int * pAllocated, + struct ldb_message *** pppRes); + static char * parsetree_to_sql(struct ldb_module *module, - char * hTalloc, + char * hTalloc, const struct ldb_parse_tree *t); +static int +parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, + const struct ldb_parse_tree * t); + static char * -parsetree_to_tablelist(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t); +build_attr_table_list(void * hTalloc, + struct lsqlite3_private * lsqlite3); static int msg_to_sql(struct ldb_module * module, @@ -193,54 +217,51 @@ lsqlite3_connect(const char *url, int ret; struct ldb_context * ldb = NULL; struct lsqlite3_private * lsqlite3 = NULL; - + ldb = talloc(NULL, struct ldb_context); if (!ldb) { - errno = ENOMEM; goto failed; } - + lsqlite3 = talloc(ldb, struct lsqlite3_private); if (!lsqlite3) { - errno = ENOMEM; goto failed; } - + lsqlite3->sqlite = NULL; lsqlite3->options = NULL; lsqlite3->lock_count = 0; - + ret = initialize(lsqlite3, url); if (ret != SQLITE_OK) { goto failed; } - + talloc_set_destructor(lsqlite3, destructor); - + ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { - errno = ENOMEM; goto failed; } ldb->modules->ldb = ldb; ldb->modules->prev = ldb->modules->next = NULL; ldb->modules->private_data = lsqlite3; ldb->modules->ops = &lsqlite3_ops; - + if (options) { /* * take a copy of the options array, so we don't have to rely * on the caller keeping it around (it might be dynamic) */ for (i=0;options[i];i++) ; - + lsqlite3->options = talloc_array(lsqlite3, char *, i+1); if (!lsqlite3->options) { goto failed; } - + for (i=0;options[i];i++) { - + lsqlite3->options[i+1] = NULL; lsqlite3->options[i] = talloc_strdup(lsqlite3->options, options[i]); @@ -249,9 +270,9 @@ lsqlite3_connect(const char *url, } } } - + return ldb; - + failed: if (lsqlite3->sqlite != NULL) { (void) sqlite3_close(lsqlite3->sqlite); @@ -275,7 +296,7 @@ lsqlite3_rename(struct ldb_module * module, if (olddn[0] == '@' ||newdn[0] == '@') { return 0; } - + #warning "lsqlite3_rename() is not yet supported" return -1; } @@ -289,42 +310,44 @@ lsqlite3_delete(struct ldb_module *module, if (dn[0] == '@') { return 0; } - + #warning "lsqlite3_delete() is not yet supported" return -1; } -/* search for matching records */ +/* search for matching records, by tree */ static int -lsqlite3_search(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - const char * pExpression, - const char * const attrs[], - struct ldb_message *** res) +lsqlite3_search_bytree(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + struct ldb_parse_tree * pTree, + const char * const * attrs, + struct ldb_message *** pppRes) { + int i; int ret; + int allocated; int bLoop; long long eid = 0; long long prevEID; char * pSql = NULL; char * pSqlConstraints; char * pTableList; - char * hTalloc; + char * hTalloc = NULL; const char * pDN; const char * pAttrName; const char * pAttrValue; + const char * const * pRequestedAttrs; sqlite3_stmt * pStmt; - struct ldb_parse_tree * pTree; struct lsqlite3_private * lsqlite3 = module->private_data; - + if (pBaseDN == NULL) { pBaseDN = ""; } - + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); - + /* * Obtain the eid of the base DN */ @@ -335,24 +358,60 @@ lsqlite3_search(struct ldb_module * module, " FROM ldb_attr_dn " " WHERE attr_value = %Q;", pBaseDN); - - /* Parse the filter expression into a tree we can work with */ - if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { - return -1; - } - + /* Allocate a temporary talloc context */ - hTalloc = talloc_new(module->ldb); - - /* Move the parse tree to our temporary context */ - talloc_steal(hTalloc, pTree); - - /* Convert filter into a series of SQL statements (constraints) */ + if ((hTalloc = talloc_new(module->ldb)) == NULL) { + ret = -1; + talloc_free(pTree); + goto cleanup; + } + + /* Convert filter into a series of SQL conditions (constraints) */ pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree); - - /* Get the list of attribute names to use as our extra table list */ - pTableList = parsetree_to_tablelist(module, hTalloc, pTree); - + + /* Ensure we're starting with an empty result attribute table */ + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM " RESULT_ATTR_TABLE " " + " WHERE 1;");/* avoid a schema change with WHERE 1 */ + + /* Insert the list of requested attributes into this table */ + for (pRequestedAttrs = (const char * const *) attrs; + pRequestedAttrs != NULL; + pRequestedAttrs++) { + + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT OR IGNORE INTO " RESULT_ATTR_TABLE " " + " (attr_name) " + " VALUES " + " (%Q);", + *pRequestedAttrs); + } + + /* Ensure we're starting with an empty filter attribute table */ + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM " FILTER_ATTR_TABLE " " + " WHERE 1;");/* avoid a schema change with WHERE 1 */ + + /* + * Create a table of unique attribute names for our extra table list + */ + if (parsetree_to_attrlist(lsqlite3, pTree) != 0) { + ret = -1; + goto cleanup; + } + + /* + * Build the attribute table list from the list of unique names. + */ + + if ((pTableList = build_attr_table_list(hTalloc, lsqlite3)) == NULL) { + ret = -1; + goto cleanup; + } + switch(scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: @@ -373,12 +432,15 @@ lsqlite3_search(struct ldb_module * module, " AND ldap_entry.eid IN\n%s\n" " ) " " AND av.eid = entry.eid " + " AND av.attr_name IN " + " (SELECT attr_name " + " FROM " RESULT_ATTR_TABLE ") " " ORDER BY av.eid, av.attr_name;", pTableList, eid, pSqlConstraints); break; - + case LDB_SCOPE_BASE: pSql = sqlite3_mprintf( "SELECT entry.eid,\n" @@ -394,12 +456,15 @@ lsqlite3_search(struct ldb_module * module, " AND ldb_entry.eid IN\n%s\n" " ) " " AND av.eid = entry.eid " + " AND av.attr_name IN " + " (SELECT attr_name " + " FROM " RESULT_ATTR_TABLE ") " " ORDER BY av.eid, av.attr_name;", pTableList, eid, pSqlConstraints); break; - + case LDB_SCOPE_ONELEVEL: pSql = sqlite3_mprintf( "SELECT entry.eid,\n" @@ -417,70 +482,96 @@ lsqlite3_search(struct ldb_module * module, " AND ldb_entry.eid IN\n%s\n" " ) " " AND av.eid = entry.eid " + " AND av.attr_name IN " + " (SELECT attr_name " + " FROM " RESULT_ATTR_TABLE ") " " ORDER BY av.eid, av.attr_name;", pTableList, eid, pSqlConstraints); break; } - - /* Initially, we have no old eid */ - prevEID = -1; - + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, * requiring retrying the operation. */ for (bLoop = TRUE; bLoop; ) { - + /* There are no allocate message structures yet */ + allocated = 0; + + for (i = 0; i < allocated; i++) { + (*pppRes)[i] = NULL; + } + /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, pSql, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + talloc_free(*pppRes); continue; } else if (ret != SQLITE_OK) { ret = -1; break; } + /* Initially, we have no previous eid */ + prevEID = -1; + /* Loop through the returned rows */ - do { + for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { + /* Get the next row */ if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { - + /* Get the values from this row */ eid = sqlite3_column_int64(pStmt, 0); pDN = sqlite3_column_text(pStmt, 1); pAttrName = sqlite3_column_text(pStmt, 2); pAttrValue = sqlite3_column_text(pStmt, 3); - /* Add this row data to the return results */ -#warning "finish returning the result set of the search here" + /* Add this result to the result set */ + if ((ret = add_msg_attr(hTalloc, + eid, + pDN, + pAttrName, + pAttrValue, + prevEID, + &allocated, + pppRes)) != 0) { + + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } } - } while (ret == SQLITE_ROW); - +#warning "finish returning the result set of the search here" + } + if (ret == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); + talloc_free(*pppRes); continue; } else if (ret != SQLITE_DONE) { (void) sqlite3_finalize(pStmt); ret = -1; break; } - + /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); + talloc_free(*pppRes); continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); ret = -1; break; } - + /* * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. @@ -488,15 +579,66 @@ lsqlite3_search(struct ldb_module * module, ret = 0; bLoop = FALSE; } - - + /* End the transaction */ QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); - + /* We're alll done with this query */ sqlite3_free(pSql); + + /* Were there any results? */ + if (ret != 0 || allocated == 0) { + /* Nope. We can free the results. */ + talloc_free(pppRes); + } + +cleanup: + /* Clean up our temporary tables */ + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM " RESULT_ATTR_TABLE " " + " WHERE 1;");/* avoid a schema change with WHERE 1 */ + + QUERY_NOROWS(lsqlite3, + FALSE, + "DELETE FROM " FILTER_ATTR_TABLE " " + " WHERE 1;");/* avoid a schema change with WHERE 1 */ + + + if (hTalloc != NULL) { + talloc_free(hTalloc); + } + + /* If error, return error code; otherwise return number of results */ + return ret == 0 ? allocated : ret; +} - return ret; +/* search for matching records, by expression */ +static int +lsqlite3_search(struct ldb_module * module, + const char * pBaseDN, + enum ldb_scope scope, + const char * pExpression, + const char * const * attrs, + struct ldb_message *** pppRes) +{ + int ret; + struct ldb_parse_tree * pTree; + + /* Parse the filter expression into a tree we can work with */ + if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { + return -1; + } + + /* Now use the bytree function for the remainder of processing */ + ret = lsqlite3_search_bytree(module, pBaseDN, scope, + pTree, attrs, pppRes); + + /* Free the parse tree */ + talloc_free(pTree); + + /* All done. */ + return ret; } @@ -507,15 +649,15 @@ lsqlite3_add(struct ldb_module *module, { long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; - + /* ignore ltdb specials */ if (msg->dn[0] == '@') { return 0; } - + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - + /* * Build any portions of the directory tree that don't exist. If the * final component already exists, it's an error. @@ -524,13 +666,13 @@ lsqlite3_add(struct ldb_module *module, QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); return -1; } - + /* Add attributes to this new entry */ if (msg_to_sql(module, msg, eid, FALSE) != 0) { QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); return -1; } - + /* Everything worked. Commit it! */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0; @@ -543,15 +685,15 @@ lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { struct lsqlite3_private * lsqlite3 = module->private_data; - + /* ignore ltdb specials */ if (msg->dn[0] == '@') { return 0; } - + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - + /* Everything worked. Commit it! */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0 ; @@ -565,9 +707,9 @@ lsqlite3_lock(struct ldb_module *module, if (lockname == NULL) { return -1; } - + /* TODO implement a local locking mechanism here */ - + return 0; } @@ -579,9 +721,9 @@ lsqlite3_unlock(struct ldb_module *module, if (lockname == NULL) { return -1; } - + /* TODO implement a local locking mechanism here */ - + return 0; } @@ -590,7 +732,7 @@ static const char * lsqlite3_errstring(struct ldb_module *module) { struct lsqlite3_private * lsqlite3 = module->private_data; - + return sqlite3_errmsg(lsqlite3->sqlite); } @@ -611,22 +753,22 @@ initialize(struct lsqlite3_private *lsqlite3, sqlite3_stmt * stmt; const char * schema = "-- ------------------------------------------------------" - + "PRAGMA auto_vacuum=1;" - + "-- ------------------------------------------------------" - + "BEGIN EXCLUSIVE;" - + "-- ------------------------------------------------------" - + "CREATE TABLE ldb_info AS" " SELECT 'LDB' AS database_type," " '1.0' AS version;" - + "-- ------------------------------------------------------" "-- Schema" - + "/*" " * The entry table holds the information about an entry. " " * This table is used to obtain the EID of the entry and to " @@ -638,21 +780,21 @@ initialize(struct lsqlite3_private *lsqlite3, "(" " -- Unique identifier of this LDB entry" " eid INTEGER PRIMARY KEY," - + " -- Unique identifier of the parent LDB entry" " peid INTEGER REFERENCES ldb_entry," - + " -- Distinguished name of this entry" " dn TEXT," - + " -- Time when the entry was created" " create_timestamp INTEGER," - + " -- Time when the entry was last modified" " modify_timestamp INTEGER" ");" - - + + "/*" " * The purpose of the descendant table is to support the" " * subtree search feature. For each LDB entry with a unique" @@ -671,24 +813,24 @@ initialize(struct lsqlite3_private *lsqlite3, "(" " -- The unique identifier of the ancestor LDB entry" " aeid INTEGER REFERENCES ldb_entry," - + " -- The unique identifier of the descendant LDB entry" " deid INTEGER REFERENCES ldb_entry" ");" - - + + "CREATE TABLE ldb_object_classes" "(" " -- Object classes are inserted into this table to track" " -- their class hierarchy. 'top' is the top-level class" " -- of which all other classes are subclasses." " class_name TEXT PRIMARY KEY," - + " -- tree_key tracks the position of the class in" " -- the hierarchy" " tree_key TEXT UNIQUE" ");" - + "/*" " * We keep a full listing of attribute/value pairs here" " */" @@ -698,7 +840,7 @@ initialize(struct lsqlite3_private *lsqlite3, " attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME" " attr_value TEXT" ");" - + "/*" " * There is one attribute table per searchable attribute." " */" @@ -707,20 +849,20 @@ initialize(struct lsqlite3_private *lsqlite3, "(" " -- The unique identifier of the LDB entry" " eid INTEGER REFERENCES ldb_entry," - + " -- Normalized attribute value" " attr_value TEXT" ");" "*/" - - + + "-- ------------------------------------------------------" "-- Indexes" - - + + "-- ------------------------------------------------------" "-- Triggers" - + "CREATE TRIGGER ldb_entry_insert_tr" " AFTER INSERT" " ON ldb_entry" @@ -731,7 +873,7 @@ initialize(struct lsqlite3_private *lsqlite3, " modify_timestamp = strftime('%s', 'now')" " WHERE eid = new.eid;" " END;" - + "CREATE TRIGGER ldb_entry_update_tr" " AFTER UPDATE" " ON ldb_entry" @@ -741,19 +883,19 @@ initialize(struct lsqlite3_private *lsqlite3, " SET modify_timestamp = strftime('%s', 'now')" " WHERE eid = old.eid;" " END;" - + "-- ------------------------------------------------------" "-- Table initialization" - + "/* We need an implicit 'top' level object class */" "INSERT INTO ldb_attributes (attr_name," " parent_tree_key)" " SELECT 'top', '';" - + "-- ------------------------------------------------------" - + "COMMIT;" - + "-- ------------------------------------------------------" ; @@ -761,18 +903,18 @@ initialize(struct lsqlite3_private *lsqlite3, if (strncmp(url, "sqlite://", 9) != 0) { return SQLITE_MISUSE; } - + /* Update pointer to just after the protocol indicator */ url += 9; - + /* Try to open the (possibly empty/non-existent) database */ if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) { return ret; } - + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); - + /* Determine if this is a new database. No tables means it is. */ QUERY_INT(lsqlite3, queryInt, @@ -780,13 +922,13 @@ initialize(struct lsqlite3_private *lsqlite3, "SELECT COUNT(*) " " FROM sqlite_master " " WHERE type = 'table';"); - + if (queryInt == 0) { /* * Create the database schema */ for (pTail = discard_const_p(char, schema); pTail != NULL; ) { - + if ((ret = sqlite3_prepare( lsqlite3->sqlite, pTail, @@ -795,7 +937,7 @@ initialize(struct lsqlite3_private *lsqlite3, &pTail)) != SQLITE_OK || (ret = sqlite3_step(stmt)) != SQLITE_DONE || (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); (void) sqlite3_close(lsqlite3->sqlite); return ret; @@ -825,17 +967,39 @@ initialize(struct lsqlite3_private *lsqlite3, " AND version = '1.0'" " );") != 0 || queryInt != 1) { - + /* It's not one that we created. See ya! */ QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); (void) sqlite3_close(lsqlite3->sqlite); return SQLITE_MISUSE; } } - + + /* + * Create a temporary table to hold attributes requested in the result + * set of a search. + */ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TEMPORARY TABLE " RESULT_ATTR_TABLE " " + " (" + " attr_name TEXT PRIMARY KEY " + " );"); + + /* + * Create a temporary table to hold the attributes used by filters + * during a search. + */ + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE TEMPORARY TABLE " FILTER_ATTR_TABLE " " + " (" + " attr_name TEXT PRIMARY KEY " + " );"); + /* Commit the transaction */ QUERY_NOROWS(lsqlite3, FALSE, "COMMIT;"); - + return SQLITE_OK; } @@ -843,7 +1007,7 @@ static int destructor(void *p) { struct lsqlite3_private * lsqlite3 = p; - + (void) sqlite3_close(lsqlite3->sqlite); return 0; } @@ -871,19 +1035,19 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* Begin access to variable argument list */ va_start(args, pSql); - + /* Format the query */ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { return -1; } - + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, * requiring retrying the operation. */ for (bLoop = TRUE; bLoop; ) { - + /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, pTail, @@ -905,7 +1069,7 @@ query_norows(const struct lsqlite3_private *lsqlite3, ret = -1; break; } - + /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); @@ -915,7 +1079,7 @@ query_norows(const struct lsqlite3_private *lsqlite3, ret = -1; break; } - + /* * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. @@ -923,13 +1087,13 @@ query_norows(const struct lsqlite3_private *lsqlite3, ret = 0; bLoop = FALSE; } - + /* All done with variable argument list */ va_end(args); - + /* Free the memory we allocated for our query string */ sqlite3_free(p); - + return ret; } @@ -958,19 +1122,19 @@ query_int(const struct lsqlite3_private * lsqlite3, /* Begin access to variable argument list */ va_start(args, pSql); - + /* Format the query */ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { return -1; } - + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, * requiring retrying the operation. */ for (bLoop = TRUE; bLoop; ) { - + /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, pTail, @@ -992,10 +1156,10 @@ query_int(const struct lsqlite3_private * lsqlite3, ret = -1; break; } - + /* Get the value to be returned */ *pRet = sqlite3_column_int64(pStmt, 0); - + /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); @@ -1005,7 +1169,7 @@ query_int(const struct lsqlite3_private * lsqlite3, ret = -1; break; } - + /* * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. @@ -1013,13 +1177,13 @@ query_int(const struct lsqlite3_private * lsqlite3, ret = 0; bLoop = FALSE; } - + /* All done with variable argument list */ va_end(args); - + /* Free the memory we allocated for our query string */ sqlite3_free(p); - + return ret; } @@ -1043,162 +1207,210 @@ case_fold_attr_required(void * hUserData, * add a single set of ldap message values to a ldb_message */ -#warning "add_msg_attr() not yet implemented or used" -#if 0 static int -add_msg_attr(struct ldb_context *ldb, - struct ldb_message *msg, - const char *attr, - struct berval **bval) +add_msg_attr(void * hTalloc, + long long eid, + const char * pDN, + const char * pAttrName, + const char * pAttrValue, + long long prevEID, + int * pAllocated, + struct ldb_message *** pppRes) { - int i; - int count; + void * x; + struct ldb_message * msg; struct ldb_message_element * el; - - count = ldap_count_values_len(bval); - - if (count <= 0) { - return -1; - } - - el = talloc_realloc(msg, msg->elements, struct ldb_message_element, - msg->num_elements + 1); - if (!el) { - errno = ENOMEM; - return -1; - } - - msg->elements = el; - - el = &msg->elements[msg->num_elements]; - - el->name = talloc_strdup(msg->elements, attr); - if (!el->name) { - errno = ENOMEM; - return -1; - } - el->flags = 0; - - el->num_values = 0; - el->values = talloc_array(msg->elements, struct ldb_val, count); - if (!el->values) { - errno = ENOMEM; - return -1; - } - - for (i=0;ivalues[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len); - if (!el->values[i].data) { - return -1; - } - el->values[i].length = bval[i]->bv_len; - el->num_values++; - } - - msg->num_elements++; - + + /* Is this a different EID than the previous one? */ + if (eid != prevEID) { + /* Yup. Add another result to the result array */ + if ((x = talloc_realloc(hTalloc, + *pAllocated == 0 ? NULL : pppRes, + struct ldb_message *, + *pAllocated + 1)) == NULL) { + + return -1; + } + + /* Save the new result list */ + *pppRes = x; + + /* We've allocated one more result */ + *pAllocated++; + + /* Ensure that the message is initialized */ + msg = x; + msg->dn = NULL; + msg->num_elements = 0; + msg->elements = NULL; + msg->private_data = NULL; + } else { + /* Same EID. Point to the previous most-recent message */ + msg = *pppRes[*pAllocated - 1]; + } + + /* + * Point to the most recent previous element. (If there are none, + * this will point to non-allocated memory, but the pointer will never + * be dereferenced.) + */ + el = &msg->elements[msg->num_elements - 1]; + + /* See if the most recent previous element has the same attr_name */ + if (msg->num_elements == 0 || strcmp(el->name, pAttrName) != 0) { + + /* It's a new attr_name. Allocate another message element */ + if ((el = talloc_realloc(msg, + msg->elements, + struct ldb_message_element, + msg->num_elements + 1)) == NULL) { + return -1; + } + + /* Save the new element */ + msg->elements = el; + + /* There's now one additional element */ + msg->num_elements++; + + /* Save the attribute name */ + if ((el->name = + talloc_strdup(msg->elements, pAttrName)) == NULL) { + + return -1; + } + + /* No flags */ + el->flags = 0; + + /* Initialize number of attribute values for this type */ + el->num_values = 0; + el->values = NULL; + } + + /* Increase the value array size by 1 */ + if ((el->values = + talloc_realloc(el, + el->num_values == 0 ? NULL : el->values, + struct ldb_val, + el->num_values)) == NULL) { + return -1; + } + + /* Save the new attribute value length */ + el->values[el->num_values].length = strlen(pAttrValue) + 1; + + /* Copy the new attribute value */ + if (talloc_memdup(el->values[el->num_values].data, + pAttrValue, + el->values[el->num_values].length) == NULL) { + return -1; + } + + /* We now have one additional value of this type */ + el->num_values++; + return 0; } -#endif static char * parsetree_to_sql(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t) + char * hTalloc, + const struct ldb_parse_tree *t) { int i; char * child; char * p; char * ret = NULL; char * pAttrName; - - + + switch(t->operation) { - case LDB_OP_SIMPLE: - break; - - case LDB_OP_EXTENDED: -#warning "derrell, you'll need to work out how to handle bitops" - return NULL; - - case LDB_OP_AND: - ret = parsetree_to_sql(module, - hTalloc, - t->u.list.elements[0]); - - for (i = 1; i < t->u.list.num_elements; i++) { - child = - parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "INTERSECT\n" - "%s\n", - child); - talloc_free(child); - } - - child = ret; - ret = talloc_asprintf("(\n" - "%s\n" - ")\n", - child); - talloc_free(child); - return ret; - - case LDB_OP_OR: - child = + case LDB_OP_SIMPLE: + break; + + case LDB_OP_EXTENDED: +#warning "work out how to handle bitops" + return NULL; + + case LDB_OP_AND: + ret = parsetree_to_sql(module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = parsetree_to_sql( module, hTalloc, - t->u.list.elements[0]); - - for (i = 1; i < t->u.list.num_elements; i++) { - child = - parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "UNION\n" - "%s\n", - child); - talloc_free(child); - } - child = ret; - ret = talloc_asprintf("(\n" - "%s\n" - ")\n", - child); + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "INTERSECT\n" + "%s\n", + child); talloc_free(child); - return ret; - - case LDB_OP_NOT: - child = + } + + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_OR: + child = + parsetree_to_sql( + module, + hTalloc, + t->u.list.elements[0]); + + for (i = 1; i < t->u.list.num_elements; i++) { + child = parsetree_to_sql( module, hTalloc, - t->u.not.child); - ret = talloc_asprintf(hTalloc, - "(\n" - " SELECT eid\n" - " FROM ldb_entry\n" - " WHERE eid NOT IN %s\n" - ")\n", - child); - talloc_free(child); - return ret; - - default: - /* should never occur */ - abort(); + t->u.list.elements[i]); + ret = talloc_asprintf_append(ret, + "UNION\n" + "%s\n", + child); + talloc_free(child); + } + child = ret; + ret = talloc_asprintf("(\n" + "%s\n" + ")\n", + child); + talloc_free(child); + return ret; + + case LDB_OP_NOT: + child = + parsetree_to_sql( + module, + hTalloc, + t->u.not.child); + ret = talloc_asprintf(hTalloc, + "(\n" + " SELECT eid\n" + " FROM ldb_entry\n" + " WHERE eid NOT IN %s\n" + ")\n", + child); + talloc_free(child); + return ret; + + default: + /* should never occur */ + abort(); }; - + /* Get a case-folded copy of the attribute name */ pAttrName = ldb_casefold((struct ldb_context *) module, t->u.simple.attr); - + /* * For simple searches, we want to retrieve the list of EIDs that * match the criteria. We accomplish this by searching the @@ -1219,10 +1431,10 @@ parsetree_to_sql(struct ldb_module *module, pAttrName)) == NULL) { return NULL; } - + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); - + } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { /* * For object classes, we want to search for all objectclasses @@ -1243,10 +1455,10 @@ parsetree_to_sql(struct ldb_module *module, t->u.simple.value.data)) == NULL) { return NULL; } - + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); - + } else { /* A normal query. */ if ((p = sqlite3_mprintf("(\n" @@ -1258,7 +1470,7 @@ parsetree_to_sql(struct ldb_module *module, t->u.simple.value.data)) == NULL) { return NULL; } - + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); } @@ -1266,13 +1478,177 @@ parsetree_to_sql(struct ldb_module *module, } +static int +parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, + const struct ldb_parse_tree * t) +{ + int i; + + switch(t->operation) { + case LDB_OP_SIMPLE: + break; + + case LDB_OP_EXTENDED: +#warning "work out how to handle bitops" + return -1; + + case LDB_OP_AND: + if (parsetree_to_attrlist( + lsqlite3, + t->u.list.elements[0]) != 0) { + return -1; + } + + for (i = 1; i < t->u.list.num_elements; i++) { + if (parsetree_to_attrlist( + lsqlite3, + t->u.list.elements[i]) != 0) { + return -1; + } + } + + return 0; + + case LDB_OP_OR: + if (parsetree_to_attrlist( + lsqlite3, + t->u.list.elements[0]) != 0) { + return -1; + } + + for (i = 1; i < t->u.list.num_elements; i++) { + if (parsetree_to_attrlist( + lsqlite3, + t->u.list.elements[i]) != 0) { + return -1; + } + } + + return 0; + + case LDB_OP_NOT: + if (parsetree_to_attrlist(lsqlite3, + t->u.not.child) != 0) { + return -1; + } + + return 0; + + default: + /* should never occur */ + abort(); + }; + + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT OR IGNORE INTO " FILTER_ATTR_TABLE " " + " (attr_name) " + " VALUES " + " (%Q);", + t->u.simple.attr); + return 0; +} + + +/* + * Use the already-generated FILTER_ATTR_TABLE to create a list of attribute + * table names that will be used in search queries. + */ static char * -parsetree_to_tablelist(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t) +build_attr_table_list(void * hTalloc, + struct lsqlite3_private * lsqlite3) { -#warning "obtain talloc'ed array of attribute names for table list" - return NULL; + int ret; + int bLoop; + char * p; + char * pTableList; + sqlite3_stmt * pStmt; + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + /* Initialize a string to which we'll append each table name */ + if ((pTableList = talloc_strdup(hTalloc, "")) == NULL) { + return NULL; + } + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + "SELECT attr_name " + " FROM " FILTER_ATTR_TABLE ";", + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + ret = -1; + break; + } + + /* Loop through the returned rows */ + for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { + + /* Get the next row */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { + + /* + * Get value from this row and append to table + * list + */ + p = discard_const_p(char, + sqlite3_column_text(pStmt, + 0)); + + /* Append it to the table list */ + if ((p = talloc_asprintf( + hTalloc, + "%s%s", + *pTableList == '\0' ? "" : ",", + sqlite3_column_text(pStmt, + 0))) == NULL) { + + talloc_free(pTableList); + return NULL; + } + + /* We have a new table list */ + talloc_free(pTableList); + pTableList = p; + } + } + + if (ret == SQLITE_SCHEMA) { + talloc_free(pTableList); + continue; + } + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } + + if (ret != 0) { + talloc_free(pTableList); + pTableList = NULL; + } + + return pTableList; } @@ -1291,30 +1667,30 @@ msg_to_sql(struct ldb_module * module, unsigned int i; unsigned int j; struct lsqlite3_private * lsqlite3 = module->private_data; - + for (i = 0; i < msg->num_elements; i++) { const struct ldb_message_element *el = &msg->elements[i]; - + if (! use_flags) { flags = LDB_FLAG_MOD_ADD; } else { flags = el->flags & LDB_FLAG_MOD_MASK; } - + /* Get a case-folded copy of the attribute name */ pAttrName = ldb_casefold((struct ldb_context *) module, el->name); - + if (flags == LDB_FLAG_MOD_ADD) { /* Create the attribute table if it doesn't exist */ if (new_attr(module, pAttrName) != 0) { return -1; } } - + /* For each value of the specified attribute name... */ for (j = 0; j < el->num_values; j++) { - + /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: @@ -1335,9 +1711,9 @@ msg_to_sql(struct ldb_module * module, " WHERE eid = %lld;", el->name, el->values[j].data, eid); - + break; - + case LDB_FLAG_MOD_REPLACE: QUERY_NOROWS(lsqlite3, FALSE, @@ -1357,7 +1733,7 @@ msg_to_sql(struct ldb_module * module, el->name, el->values[j].data, eid); break; - + case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ QUERY_NOROWS(lsqlite3, @@ -1381,7 +1757,7 @@ msg_to_sql(struct ldb_module * module, } } } - + return 0; } @@ -1401,7 +1777,7 @@ new_dn(struct ldb_module * module, struct ldb_dn_component * pComponent; struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; - + /* Explode and normalize the DN */ if ((pExplodedDN = ldb_explode_dn(ldb, @@ -1410,12 +1786,12 @@ new_dn(struct ldb_module * module, case_fold_attr_required)) == NULL) { return -1; } - + /* Allocate a string to hold the partial DN of each component */ if ((pPartialDN = talloc_strdup(ldb, "")) == NULL) { return -1; } - + /* For each component of the DN (starting with the last one)... */ eid = 0; for (nComponent = pExplodedDN->comp_num - 1, bFirst = TRUE; @@ -1424,7 +1800,7 @@ new_dn(struct ldb_module * module, /* Point to the component */ pComponent = pExplodedDN->components[nComponent]; - + /* Add this component on to the partial DN to date */ if ((p = talloc_asprintf(ldb, "%s%s%s", @@ -1433,13 +1809,13 @@ new_dn(struct ldb_module * module, pPartialDN)) == NULL) { return -1; } - + /* No need for the old partial DN any more */ talloc_free(pPartialDN); - + /* Save the new partial DN */ pPartialDN = p; - + /* * Ensure that an entry is in the ldb_entry table for this * component. Any component other than the last one @@ -1467,30 +1843,30 @@ new_dn(struct ldb_module * module, nComponent == 0 ? "" : "OR IGNORE", eid, pPartialDN); } - + /* Get the EID of the just inserted row (the next parent) */ eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); } - + /* Give 'em what they came for! */ *pEID = eid; - + return 0; } static int new_attr(struct ldb_module * module, - char * pAttrName) + char * pAttrName) { long long bExists; struct lsqlite3_private * lsqlite3 = module->private_data; - + /* * NOTE: * pAttrName is assumed to already be case-folded here! */ - + /* See if the table already exists */ QUERY_INT(lsqlite3, bExists, @@ -1500,7 +1876,7 @@ new_attr(struct ldb_module * module, " WHERE type = 'table' " " AND tbl_name = %Q;", pAttrName); - + /* Did it exist? */ if (! bExists) { /* Nope. Create the table */ @@ -1513,7 +1889,7 @@ new_attr(struct ldb_module * module, ");", pAttrName); } - + return 0; } -- cgit From 1491f9b6150f01ca3d20076962aa595f34c44aa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 03:37:43 +0000 Subject: r7564: added a test showing the search expression that w2k is actually giving us that triggered this work (This used to be commit 853b8cd72dbb8c50d527e66aa7b5692060b66d2b) --- source4/lib/ldb/tests/test-extended.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index 246b55f5b9..281ee00f9b 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -15,6 +15,22 @@ i1: 0x800000 dn: testrec3 i1: 0x101010101 i1: 7 + +dn: auser1 +groupType: 2147483648 +samAccountType: 805306368 + +dn: auser2 +groupType: 2147483648 +samAccountType: 805306369 + +dn: auser3 +groupType: 2147483649 +samAccountType: 805306370 + +dn: auser4 +groupType: 2147483649 +samAccountType: 805306369 EOF checkcount() { @@ -46,4 +62,7 @@ checkcount 2 '(i1:1.2.840.113556.1.4.804:=15)' checkcount 1 '(i1:1.2.840.113556.1.4.804:=0x800000)' checkcount 1 '(i1:1.2.840.113556.1.4.804:=8388608)' +# this is one that w2k gives +checkcount 3 '(|(|(&(!(groupType:1.2.840.113556.1.4.803=1))(groupType:1.2.840.113556.1.4.803=2147483648)(groupType:1.2.840.113556.1.4.804=10))(samAccountType=805306368))(samAccountType=805306369))' + rm -f $LDB_URL -- cgit From 42863aebb146a417af56876655ef08728a2d1769 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 07:48:44 +0000 Subject: r7571: fixed the generation of the filter string for extended filters (This used to be commit 348a86e64392245571204ac5004e73221ac441f5) --- source4/lib/ldb/common/ldb_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index c9a35cc255..501b82f635 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -483,7 +483,7 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) case LDB_OP_EXTENDED: s = ldb_binary_encode(mem_ctx, tree->u.extended.value); if (s == NULL) return NULL; - ret = talloc_asprintf(mem_ctx, "(%s%s%s%s=%s)", + ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", tree->u.extended.attr?tree->u.extended.attr:"", tree->u.extended.dnAttributes?":dn":"", tree->u.extended.rule_id?":":"", -- cgit From 051b93bec3a45a39cd10b5484a7bc3125e7d93af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 14 Jun 2005 07:50:18 +0000 Subject: r7572: fixed filter in test suite (This used to be commit 73d2e5df0ccf4ab1b78a1044058efd8e2479aa1a) --- source4/lib/ldb/tests/test-extended.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index 281ee00f9b..ede66ec567 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -63,6 +63,6 @@ checkcount 1 '(i1:1.2.840.113556.1.4.804:=0x800000)' checkcount 1 '(i1:1.2.840.113556.1.4.804:=8388608)' # this is one that w2k gives -checkcount 3 '(|(|(&(!(groupType:1.2.840.113556.1.4.803=1))(groupType:1.2.840.113556.1.4.803=2147483648)(groupType:1.2.840.113556.1.4.804=10))(samAccountType=805306368))(samAccountType=805306369))' +checkcount 3 '(|(|(&(!(groupType:1.2.840.113556.1.4.803:=1))(groupType:1.2.840.113556.1.4.803:=2147483648)(groupType:1.2.840.113556.1.4.804:=10))(samAccountType=805306368))(samAccountType=805306369))' rm -f $LDB_URL -- cgit From 9189833a8753a723a8b8d0af9c8b096571b06a84 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Jun 2005 19:15:17 +0000 Subject: r7582: Better way to have a fast path searching for a specific DN. Old way was ugly and had a bug, you couldn't add an attribute named dn or distinguishedName and search for it, tdb would change that search in a dn search. This makes it also possible to search by dn against an ldap server as the old method was not supported by ldap syntaxes. sss (This used to be commit a614466dec2484a0d39bdfae53da822cfcf80926) --- source4/lib/gendb.c | 31 +++++++++++++++++++++++++++++-- source4/lib/ldb/Makefile.in | 2 ++ source4/lib/ldb/ldb_ldap/ldb_ldap.c | 4 ++++ source4/lib/ldb/ldb_tdb/ldb_search.c | 23 +++++++++++------------ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 +- source4/lib/ldb/tests/start_slapd.sh | 2 ++ 6 files changed, 49 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index 5b4f7b251e..dc5b7f39aa 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -61,7 +61,7 @@ int gendb_search_v(struct ldb_context *ldb, /* search the LDB for the specified attributes - varargs variant */ -int gendb_search(struct ldb_context *sam_ldb, +int gendb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *basedn, struct ldb_message ***res, @@ -72,12 +72,39 @@ int gendb_search(struct ldb_context *sam_ldb, int count; va_start(ap, format); - count = gendb_search_v(sam_ldb, mem_ctx, basedn, res, attrs, format, ap); + count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); va_end(ap); return count; } +int gendb_search_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *dn, + struct ldb_message ***res, + const char * const *attrs) +{ + va_list ap; + int count; + + *res = NULL; + + count = ldb_search(ldb, dn, LDB_SCOPE_BASE, "", attrs, res); + + if (count > 1) { + DEBUG(1, ("DB Corruption ? - Found more then one entry for dn: %s", dn)); + return -1; + } + + if (*res) talloc_steal(mem_ctx, *res); + + DEBUG(4,("gendb_search_dn: %s -> %d (%s)\n", + dn, count, count==-1?ldb_errstring(ldb):"OK")); + + return count; +} + + /* setup some initial ldif in a ldb */ diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 3bfae08c27..88935b6f3a 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -148,9 +148,11 @@ test-sqlite3: @echo "SKIP SQLITE3 TEST - NO SQLITE3 SUPPORT" endif +ifeq (1,0) test-schema: @echo "STARTING SCHEMA MODULE TEST" tests/test-schema.sh +endif test: $(BINS) test-tdb test-ldap test-sqlite3 test-schema diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index fceaf02196..b3d8fcc1a5 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -196,6 +196,10 @@ static int lldb_search(struct ldb_module *module, const char *base, base = ""; } + if (expression == NULL || expression[0] == '\0') { + expression = "objectClass=*"; + } + lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, expression, discard_const_p(char *, attrs), diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 17eff6f0a6..d210510ff2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -272,7 +272,7 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag /* search the database for a single simple dn */ -int ltdb_search_dn(struct ldb_module *module, char *dn, +int ltdb_search_dn(struct ldb_module *module, const char *dn, const char * const attrs[], struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; @@ -482,17 +482,9 @@ int ltdb_search_bytree(struct ldb_module *module, const char *base, *res = NULL; - if (tree->operation == LDB_OP_SIMPLE && - (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0 || - ldb_attr_cmp(tree->u.simple.attr, "distinguishedName") == 0) && - !ltdb_has_wildcard(module, tree->u.simple.attr, &tree->u.simple.value)) { - /* yay! its a nice simple one */ - ret = ltdb_search_dn(module, tree->u.simple.value.data, attrs, res); - } else { - ret = ltdb_search_indexed(module, base, scope, tree, attrs, res); - if (ret == -1) { - ret = ltdb_search_full(module, base, scope, tree, attrs, res); - } + ret = ltdb_search_indexed(module, base, scope, tree, attrs, res); + if (ret == -1) { + ret = ltdb_search_full(module, base, scope, tree, attrs, res); } ltdb_unlock_read(module); @@ -513,6 +505,13 @@ int ltdb_search(struct ldb_module *module, const char *base, struct ldb_parse_tree *tree; int ret; + /* check if we are looking for a simple dn */ + if (scope == LDB_SCOPE_BASE && (expression == NULL || expression[0] == '\0')) { + ret = ltdb_search_dn(module, base, attrs, res); + ltdb_unlock_read(module); + return ret; + } + tree = ldb_parse_tree(ltdb, expression); if (tree == NULL) { ltdb->last_err_string = "expression parse failed"; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 891522f300..b77e02fba5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -91,7 +91,7 @@ int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val); void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg); int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg); -int ltdb_search_dn(struct ldb_module *module, char *dn, +int ltdb_search_dn(struct ldb_module *module, const char *dn, const char * const attrs[], struct ldb_message ***res); int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], diff --git a/source4/lib/ldb/tests/start_slapd.sh b/source4/lib/ldb/tests/start_slapd.sh index a7ec69c855..6dd3eaa9b8 100755 --- a/source4/lib/ldb/tests/start_slapd.sh +++ b/source4/lib/ldb/tests/start_slapd.sh @@ -3,3 +3,5 @@ mkdir -p tests/tmp/db slapd -f tests/slapd.conf -h "`tests/ldapi_url.sh`" $* + +sleep 2 -- cgit From c2747479e04761d86f0de4aa90b4d793856d0fb7 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 14 Jun 2005 21:52:35 +0000 Subject: r7586: ldb_sqlite3 making progress. add and search have indicated a willingness to operate properly on initial testing (This used to be commit 86ca8639e0ddc2525f8ed0ca9879d9f98c0cd00e) --- source4/lib/ldb/common/ldb_explode_dn.c | 12 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 522 +++++++++++++++++------------- source4/lib/ldb/ldb_sqlite3/schema | 151 +-------- 3 files changed, 306 insertions(+), 379 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index cacd9862b6..5cea4424b0 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -382,6 +382,9 @@ ldb_explode_dn(void * mem_ctx, goto failed; } + /* Save the pointer to the beginning of the string */ + component->component = dest; + /* copy each of the attributes to the normalized component */ for (i = 0; i < component->attr_num; i++) { if (i != 0) { @@ -395,9 +398,6 @@ ldb_explode_dn(void * mem_ctx, dest += size; } - /* Save the just-generated string */ - component->component = dest; - ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "component: [%s]\n", component->component); @@ -438,6 +438,9 @@ ldb_explode_dn(void * mem_ctx, goto failed; } + /* Save the pointer to the beginning of the */ + dn->dn = dest; + /* copy the normalized components into the DN */ for (i = 0; i < dn->comp_num; i++) { @@ -455,9 +458,6 @@ ldb_explode_dn(void * mem_ctx, dest += size; } - /* Save the just-generated string */ - dn->dn = dest; - ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); /* we don't need the copy of the DN any more */ diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index dbbb775928..09ba24022f 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -74,6 +74,12 @@ } while (0) +/* + * Static variables + */ +static int lsqlite3_debug = TRUE; + + /* * Forward declarations */ @@ -298,6 +304,7 @@ lsqlite3_rename(struct ldb_module * module, } #warning "lsqlite3_rename() is not yet supported" + return -1; } @@ -306,13 +313,23 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn) { + struct lsqlite3_private * lsqlite3 = module->private_data; + /* ignore ltdb specials */ if (dn[0] == '@') { return 0; } + /* Begin a transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + + #warning "lsqlite3_delete() is not yet supported" - return -1; + + /* Commit the transaction */ + QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + + return 0; } /* search for matching records, by tree */ @@ -324,7 +341,6 @@ lsqlite3_search_bytree(struct ldb_module * module, const char * const * attrs, struct ldb_message *** pppRes) { - int i; int ret; int allocated; int bLoop; @@ -337,6 +353,7 @@ lsqlite3_search_bytree(struct ldb_module * module, const char * pDN; const char * pAttrName; const char * pAttrValue; + const char * pResultAttrList; const char * const * pRequestedAttrs; sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -351,13 +368,18 @@ lsqlite3_search_bytree(struct ldb_module * module, /* * Obtain the eid of the base DN */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid " - " FROM ldb_attr_dn " - " WHERE attr_value = %Q;", - pBaseDN); + if ((ret = query_int(lsqlite3, + &eid, + "SELECT eid\n" + " FROM ldb_attr_DN\n" + " WHERE attr_value = %Q;", + pBaseDN)) == SQLITE_DONE) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return 0; + } else if (ret != SQLITE_OK) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return -1; + } /* Allocate a temporary talloc context */ if ((hTalloc = talloc_new(module->ldb)) == NULL) { @@ -372,33 +394,61 @@ lsqlite3_search_bytree(struct ldb_module * module, /* Ensure we're starting with an empty result attribute table */ QUERY_NOROWS(lsqlite3, FALSE, - "DELETE FROM " RESULT_ATTR_TABLE " " + "DELETE FROM " RESULT_ATTR_TABLE "\n" " WHERE 1;");/* avoid a schema change with WHERE 1 */ + /* Initially, we don't know what the requested attributes are */ + if (attrs == NULL) { + /* but they didn't give us any so we'll retrieve all of 'em */ + pResultAttrList = ""; + } else { + /* Discover the list of attributes */ + pResultAttrList = NULL; + } + /* Insert the list of requested attributes into this table */ for (pRequestedAttrs = (const char * const *) attrs; - pRequestedAttrs != NULL; + pRequestedAttrs != NULL && *pRequestedAttrs != NULL; pRequestedAttrs++) { - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT OR IGNORE INTO " RESULT_ATTR_TABLE " " - " (attr_name) " - " VALUES " - " (%Q);", - *pRequestedAttrs); + /* If any attribute in the list is "*" then... */ + if (strcmp(*pRequestedAttrs, "*") == 0) { + /* we want all attribute types */ + pResultAttrList = ""; + break; + + } else { + /* otherwise, add this name to the resuult list */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT OR IGNORE\n" + " INTO " RESULT_ATTR_TABLE "\n" + " (attr_name)\n" + " VALUES\n" + " (%Q);", + *pRequestedAttrs); + } } + /* If we didn't get a "*" for all attributes in the result list... */ + if (pResultAttrList == NULL) { + /* ... then we'll use the result attribute table */ + pResultAttrList = + " AND av.attr_name IN\n" + " (SELECT attr_name\n" + " FROM " RESULT_ATTR_TABLE ") "; + } + /* Ensure we're starting with an empty filter attribute table */ QUERY_NOROWS(lsqlite3, FALSE, - "DELETE FROM " FILTER_ATTR_TABLE " " + "DELETE FROM " FILTER_ATTR_TABLE "\n" " WHERE 1;");/* avoid a schema change with WHERE 1 */ /* * Create a table of unique attribute names for our extra table list */ - if (parsetree_to_attrlist(lsqlite3, pTree) != 0) { + if ((ret = parsetree_to_attrlist(lsqlite3, pTree)) != 0) { ret = -1; goto cleanup; } @@ -425,20 +475,17 @@ lsqlite3_search_bytree(struct ldb_module * module, " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry,\n" - " ldb_descendants,\n" - " %q\n" + " ldb_descendants\n" " WHERE ldb_descendants.aeid = %lld\n" " AND ldb_entry.eid = ldb_descendants.deid\n" - " AND ldap_entry.eid IN\n%s\n" - " ) " - " AND av.eid = entry.eid " - " AND av.attr_name IN " - " (SELECT attr_name " - " FROM " RESULT_ATTR_TABLE ") " + " AND ldb_entry.eid IN\n%s\n" + " )\n" + " AND av.eid = entry.eid\n" + " %s\n" " ORDER BY av.eid, av.attr_name;", - pTableList, eid, - pSqlConstraints); + pSqlConstraints, + pResultAttrList); break; case LDB_SCOPE_BASE: @@ -451,18 +498,16 @@ lsqlite3_search_bytree(struct ldb_module * module, " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" - " FROM %q\n" + " FROM ldb_entry\n" " WHERE ldb_entry.eid = %lld\n" " AND ldb_entry.eid IN\n%s\n" - " ) " - " AND av.eid = entry.eid " - " AND av.attr_name IN " - " (SELECT attr_name " - " FROM " RESULT_ATTR_TABLE ") " + " )\n" + " AND av.eid = entry.eid\n" + " %s\n" " ORDER BY av.eid, av.attr_name;", - pTableList, eid, - pSqlConstraints); + pSqlConstraints, + pResultAttrList); break; case LDB_SCOPE_ONELEVEL: @@ -475,23 +520,24 @@ lsqlite3_search_bytree(struct ldb_module * module, " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry AS pchild, " - " %q\n" - " WHERE ldb_entry.eid = pchild.eid " - " AND pchild.peid = %lld " + " FROM ldb_entry AS pchild\n" + " WHERE ldb_entry.eid = pchild.eid\n" + " AND pchild.peid = %lld\n" " AND ldb_entry.eid IN\n%s\n" - " ) " - " AND av.eid = entry.eid " - " AND av.attr_name IN " - " (SELECT attr_name " - " FROM " RESULT_ATTR_TABLE ") " - " ORDER BY av.eid, av.attr_name;", - pTableList, + " )\n" + " AND av.eid = entry.eid\n" + " %s\n" + " ORDER BY av.eid, av.attr_name;\n", eid, - pSqlConstraints); + pSqlConstraints, + pResultAttrList); break; } + if (lsqlite3_debug) { + printf("%s\n", pSql); + } + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, @@ -500,9 +546,8 @@ lsqlite3_search_bytree(struct ldb_module * module, for (bLoop = TRUE; bLoop; ) { /* There are no allocate message structures yet */ allocated = 0; - - for (i = 0; i < allocated; i++) { - (*pppRes)[i] = NULL; + if (pppRes != NULL) { + *pppRes = NULL; } /* Compile the SQL statement into sqlite virtual machine */ @@ -511,7 +556,9 @@ lsqlite3_search_bytree(struct ldb_module * module, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { - talloc_free(*pppRes); + if (pppRes != NULL && *pppRes != NULL) { + talloc_free(*pppRes); + } continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -548,12 +595,13 @@ lsqlite3_search_bytree(struct ldb_module * module, break; } } -#warning "finish returning the result set of the search here" } if (ret == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); - talloc_free(*pppRes); + if (pppRes != NULL && *pppRes != NULL) { + talloc_free(*pppRes); + } continue; } else if (ret != SQLITE_DONE) { (void) sqlite3_finalize(pStmt); @@ -564,7 +612,9 @@ lsqlite3_search_bytree(struct ldb_module * module, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); - talloc_free(*pppRes); + if (pppRes != NULL && *pppRes != NULL) { + talloc_free(*pppRes); + } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -589,19 +639,21 @@ lsqlite3_search_bytree(struct ldb_module * module, /* Were there any results? */ if (ret != 0 || allocated == 0) { /* Nope. We can free the results. */ - talloc_free(pppRes); + if (pppRes != NULL && *pppRes != NULL) { + talloc_free(*pppRes); + } } cleanup: /* Clean up our temporary tables */ QUERY_NOROWS(lsqlite3, FALSE, - "DELETE FROM " RESULT_ATTR_TABLE " " + "DELETE FROM " RESULT_ATTR_TABLE "\n" " WHERE 1;");/* avoid a schema change with WHERE 1 */ QUERY_NOROWS(lsqlite3, FALSE, - "DELETE FROM " FILTER_ATTR_TABLE " " + "DELETE FROM " FILTER_ATTR_TABLE "\n" " WHERE 1;");/* avoid a schema change with WHERE 1 */ @@ -694,6 +746,8 @@ lsqlite3_modify(struct ldb_module *module, /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); +#warning "modify() not yet implemented" + /* Everything worked. Commit it! */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); return 0 ; @@ -752,116 +806,105 @@ initialize(struct lsqlite3_private *lsqlite3, const char * pTail; sqlite3_stmt * stmt; const char * schema = - "-- ------------------------------------------------------" - - "PRAGMA auto_vacuum=1;" - - "-- ------------------------------------------------------" - "BEGIN EXCLUSIVE;" - "-- ------------------------------------------------------" - - "CREATE TABLE ldb_info AS" + "CREATE TABLE ldb_info AS " " SELECT 'LDB' AS database_type," " '1.0' AS version;" - "-- ------------------------------------------------------" - "-- Schema" - - "/*" - " * The entry table holds the information about an entry. " - " * This table is used to obtain the EID of the entry and to " - " * support scope=one and scope=base. The parent and child" - " * table is included in the entry table since all the other" - " * attributes are dependent on EID." - " */" - "CREATE TABLE ldb_entry" + /* + * The entry table holds the information about an entry. + * This table is used to obtain the EID of the entry and to + * support scope=one and scope=base. The parent and child + * table is included in the entry table since all the other + * attributes are dependent on EID. + */ + "CREATE TABLE ldb_entry " "(" - " -- Unique identifier of this LDB entry" " eid INTEGER PRIMARY KEY," - - " -- Unique identifier of the parent LDB entry" " peid INTEGER REFERENCES ldb_entry," - - " -- Distinguished name of this entry" - " dn TEXT," - - " -- Time when the entry was created" + " dn TEXT UNIQUE," " create_timestamp INTEGER," - - " -- Time when the entry was last modified" " modify_timestamp INTEGER" ");" - - "/*" - " * The purpose of the descendant table is to support the" - " * subtree search feature. For each LDB entry with a unique" - " * ID (AEID), this table contains the unique identifiers" - " * (DEID) of the descendant entries." - " *" - " * For evern entry in the directory, a row exists in this" - " * table for each of its ancestors including itself. The " - " * size of the table depends on the depth of each entry. In " - " * the worst case, if all the entries were at the same " - " * depth, the number of rows in the table is O(nm) where " - " * n is the number of nodes in the directory and m is the " - " * depth of the tree. " - " */" - "CREATE TABLE ldb_descendants" - "(" - " -- The unique identifier of the ancestor LDB entry" + + /* + * The purpose of the descendant table is to support the + * subtree search feature. For each LDB entry with a unique + * ID (AEID), this table contains the unique identifiers + * (DEID) of the descendant entries. + * + * For evern entry in the directory, a row exists in this + * table for each of its ancestors including itself. The + * size of the table depends on the depth of each entry. In + * the worst case, if all the entries were at the same + * depth, the number of rows in the table is O(nm) where + * n is the number of nodes in the directory and m is the + * depth of the tree. + */ + "CREATE TABLE ldb_descendants " + "( " " aeid INTEGER REFERENCES ldb_entry," - - " -- The unique identifier of the descendant LDB entry" " deid INTEGER REFERENCES ldb_entry" ");" "CREATE TABLE ldb_object_classes" "(" - " -- Object classes are inserted into this table to track" - " -- their class hierarchy. 'top' is the top-level class" - " -- of which all other classes are subclasses." " class_name TEXT PRIMARY KEY," - - " -- tree_key tracks the position of the class in" - " -- the hierarchy" " tree_key TEXT UNIQUE" ");" - "/*" - " * We keep a full listing of attribute/value pairs here" - " */" + /* + * We keep a full listing of attribute/value pairs here + */ "CREATE TABLE ldb_attribute_values" "(" " eid INTEGER REFERENCES ldb_entry," - " attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME" + " attr_name TEXT," " attr_value TEXT" ");" - "/*" - " * There is one attribute table per searchable attribute." - " */" - "/*" + /* + * There is one attribute table per searchable attribute. + */ + /* "CREATE TABLE ldb_attr_ATTRIBUTE_NAME" "(" - " -- The unique identifier of the LDB entry" " eid INTEGER REFERENCES ldb_entry," + " attr_value TEXT" + ");" + */ - " -- Normalized attribute value" + /* + * We pre-create the dn attribute table + */ + "CREATE TABLE ldb_attr_DN" + "(" + " eid INTEGER REFERENCES ldb_entry," " attr_value TEXT" ");" - "*/" + + /* + * We pre-create the objectclass attribute table + */ + "CREATE TABLE ldb_attr_OBJECTCLASS" + "(" + " eid INTEGER REFERENCES ldb_entry," + " attr_value TEXT" + ");" + - "-- ------------------------------------------------------" - "-- Indexes" + /* + * Indexes + */ - "-- ------------------------------------------------------" - "-- Triggers" + /* + * Triggers + */ "CREATE TRIGGER ldb_entry_insert_tr" " AFTER INSERT" @@ -884,19 +927,22 @@ initialize(struct lsqlite3_private *lsqlite3, " WHERE eid = old.eid;" " END;" - "-- ------------------------------------------------------" - "-- Table initialization" - - "/* We need an implicit 'top' level object class */" - "INSERT INTO ldb_attributes (attr_name," - " parent_tree_key)" - " SELECT 'top', '';" - - "-- ------------------------------------------------------" - - "COMMIT;" - - "-- ------------------------------------------------------" + /* + * Table initialization + */ + + /* The root node */ + "INSERT INTO ldb_entry " + " (eid, peid, dn) " + " VALUES " + " (0, NULL, '');" + + /* And the root node "dn" attribute */ + "INSERT INTO ldb_attr_DN " + " (eid, attr_value) " + " VALUES " + " (0, '');" + ; /* Skip protocol indicator of url */ @@ -912,6 +958,9 @@ initialize(struct lsqlite3_private *lsqlite3, return ret; } + /* In case this is a new database, enable auto_vacuum */ + QUERY_NOROWS(lsqlite3, FALSE, "PRAGMA auto_vacuum=1;"); + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); @@ -919,15 +968,21 @@ initialize(struct lsqlite3_private *lsqlite3, QUERY_INT(lsqlite3, queryInt, TRUE, - "SELECT COUNT(*) " - " FROM sqlite_master " + "SELECT COUNT(*)\n" + " FROM sqlite_master\n" " WHERE type = 'table';"); if (queryInt == 0) { /* * Create the database schema */ - for (pTail = discard_const_p(char, schema); pTail != NULL; ) { + for (pTail = discard_const_p(char, schema); + pTail != NULL && *pTail != '\0'; + ) { + + if (lsqlite3_debug) { + printf("Execute first query in:\n%s\n", pTail); + } if ((ret = sqlite3_prepare( lsqlite3->sqlite, @@ -981,9 +1036,9 @@ initialize(struct lsqlite3_private *lsqlite3, */ QUERY_NOROWS(lsqlite3, FALSE, - "CREATE TEMPORARY TABLE " RESULT_ATTR_TABLE " " - " (" - " attr_name TEXT PRIMARY KEY " + "CREATE TEMPORARY TABLE " RESULT_ATTR_TABLE "\n" + " (\n" + " attr_name TEXT PRIMARY KEY\n" " );"); /* @@ -992,9 +1047,9 @@ initialize(struct lsqlite3_private *lsqlite3, */ QUERY_NOROWS(lsqlite3, FALSE, - "CREATE TEMPORARY TABLE " FILTER_ATTR_TABLE " " - " (" - " attr_name TEXT PRIMARY KEY " + "CREATE TEMPORARY TABLE " FILTER_ATTR_TABLE "\n" + " (\n" + " attr_name TEXT PRIMARY KEY\n" " );"); /* Commit the transaction */ @@ -1029,7 +1084,6 @@ query_norows(const struct lsqlite3_private *lsqlite3, int ret; int bLoop; char * p; - const char * pTail; sqlite3_stmt * pStmt; va_list args; @@ -1041,6 +1095,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, return -1; } + if (lsqlite3_debug) { + printf("%s\n", p); + } + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, @@ -1050,10 +1108,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, + p, -1, &pStmt, - &pTail)) == SQLITE_SCHEMA) { + NULL)) == SQLITE_SCHEMA) { continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -1116,7 +1174,6 @@ query_int(const struct lsqlite3_private * lsqlite3, int ret; int bLoop; char * p; - const char * pTail; sqlite3_stmt * pStmt; va_list args; @@ -1125,9 +1182,13 @@ query_int(const struct lsqlite3_private * lsqlite3, /* Format the query */ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return -1; + return SQLITE_NOMEM; } + if (lsqlite3_debug) { + printf("%s\n", p); + } + /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, @@ -1137,13 +1198,12 @@ query_int(const struct lsqlite3_private * lsqlite3, /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pTail, + p, -1, &pStmt, - &pTail)) == SQLITE_SCHEMA) { + NULL)) == SQLITE_SCHEMA) { continue; } else if (ret != SQLITE_OK) { - ret = -1; break; } @@ -1153,7 +1213,6 @@ query_int(const struct lsqlite3_private * lsqlite3, continue; } else if (ret != SQLITE_ROW) { (void) sqlite3_finalize(pStmt); - ret = -1; break; } @@ -1166,7 +1225,6 @@ query_int(const struct lsqlite3_private * lsqlite3, continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); - ret = -1; break; } @@ -1174,7 +1232,6 @@ query_int(const struct lsqlite3_private * lsqlite3, * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. */ - ret = 0; bLoop = FALSE; } @@ -1432,6 +1489,10 @@ parsetree_to_sql(struct ldb_module *module, return NULL; } + if (lsqlite3_debug) { + printf("%s\n", p); + } + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); @@ -1443,7 +1504,7 @@ parsetree_to_sql(struct ldb_module *module, if ((p = sqlite3_mprintf( "(\n" " SELECT eid\n" - " FROM ldb_attr_objectclass\n" + " FROM ldb_attr_OBJECTCLASS\n" " WHERE attr_name IN\n" " (SELECT class_name\n" " FROM ldb_objectclasses\n" @@ -1456,6 +1517,10 @@ parsetree_to_sql(struct ldb_module *module, return NULL; } + if (lsqlite3_debug) { + printf("%s\n", p); + } + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); @@ -1471,6 +1536,10 @@ parsetree_to_sql(struct ldb_module *module, return NULL; } + if (lsqlite3_debug) { + printf("%s\n", p); + } + ret = talloc_strdup(hTalloc, p); sqlite3_free(p); } @@ -1541,9 +1610,9 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, QUERY_NOROWS(lsqlite3, FALSE, - "INSERT OR IGNORE INTO " FILTER_ATTR_TABLE " " - " (attr_name) " - " VALUES " + "INSERT OR IGNORE INTO " FILTER_ATTR_TABLE "\n" + " (attr_name)\n" + " VALUES\n" " (%Q);", t->u.simple.attr); return 0; @@ -1561,6 +1630,7 @@ build_attr_table_list(void * hTalloc, int ret; int bLoop; char * p; + char * pAttrName; char * pTableList; sqlite3_stmt * pStmt; @@ -1602,13 +1672,17 @@ build_attr_table_list(void * hTalloc, sqlite3_column_text(pStmt, 0)); + pAttrName = + ldb_casefold( + hTalloc, + sqlite3_column_text(pStmt, 0)); + /* Append it to the table list */ if ((p = talloc_asprintf( hTalloc, - "%s%s", + "%sldb_attr_%s", *pTableList == '\0' ? "" : ",", - sqlite3_column_text(pStmt, - 0))) == NULL) { + pAttrName)) == NULL) { talloc_free(pTableList); return NULL; @@ -1696,63 +1770,63 @@ msg_to_sql(struct ldb_module * module, case LDB_FLAG_MOD_ADD: QUERY_NOROWS(lsqlite3, FALSE, - "INSERT INTO ldb_attr_%q " - " (eid, attr_value) " - " VALUES " + "INSERT INTO ldb_attr_%q\n" + " (eid, attr_value)\n" + " VALUES\n" " (%lld, %Q);", pAttrName, eid, el->values[j].data); QUERY_NOROWS(lsqlite3, FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " add_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); + "INSERT INTO ldb_attribute_values" + " (eid, attr_name, attr_value)" + " VALUES " + " (%lld, %Q, %Q);", + eid, + el->name, + el->values[j].data); break; case LDB_FLAG_MOD_REPLACE: QUERY_NOROWS(lsqlite3, FALSE, - "UPDATE ldb_attr_%q " - " SET attr_value = %Q " + "UPDATE ldb_attr_%q\n" + " SET attr_value = %Q\n" " WHERE eid = %lld;", pAttrName, el->values[j].data, eid); QUERY_NOROWS(lsqlite3, FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " mod_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); + "UPDATE ldb_attribute_values " + " SET attr_value = %Q " + " WHERE eid = %lld " + " AND attr_name = %Q;", + el->values[j].data, + eid, + el->name); break; case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ QUERY_NOROWS(lsqlite3, FALSE, - "DELETE FROM ldb_attr_%q " - " WHERE eid = %lld " + "DELETE FROM ldb_attr_%q\n" + " WHERE eid = %lld\n" " AND attr_value = %Q;", pAttrName, eid, el->values[j].data); QUERY_NOROWS(lsqlite3, FALSE, - "UPDATE ldb_entry " - " SET entry_data = " - " del_attr(entry_data, " - " %Q, %Q) " - " WHERE eid = %lld;", - el->name, el->values[j].data, - eid); + "DELETE FROM ldb_attribute_values" + " WHERE eid = %lld " + " AND attr_name = %Q " + " AND attr_value = %Q;", + eid, + el->name, + el->values[j].data); break; } } @@ -1823,29 +1897,29 @@ new_dn(struct ldb_module * module, * component 0 (the full DN requested to be be inserted) * already exists. */ - if (bFirst) { - /* This is a top-level entry. Parent EID is null. */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_entry " - " (peid, dn) " - " VALUES " - " (NULL, %q);", - nComponent == 0 ? "" : "OR IGNORE", - pPartialDN); - } else { + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT %s INTO ldb_entry\n" + " (peid, dn)\n" + " VALUES\n" + " (%lld, %Q);", + nComponent == 0 ? "" : "OR IGNORE", + eid, pPartialDN); + + /* Get the EID of the just inserted row (the next parent) */ + eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); + + /* If this is the final component, also add DN attribute */ + if (nComponent == 0) { QUERY_NOROWS(lsqlite3, FALSE, - "INSERT %s INTO ldb_entry " - " (peid, dn) " + "INSERT %s INTO ldb_attr_DN\n" + " (eid, attr_value) " " VALUES " - " (%lld, %q);", + " (%lld, %Q);", nComponent == 0 ? "" : "OR IGNORE", eid, pPartialDN); } - - /* Get the EID of the just inserted row (the next parent) */ - eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); } /* Give 'em what they came for! */ @@ -1871,10 +1945,10 @@ new_attr(struct ldb_module * module, QUERY_INT(lsqlite3, bExists, FALSE, - "SELECT COUNT(*) <> 0" - " FROM sqlite_master " - " WHERE type = 'table' " - " AND tbl_name = %Q;", + "SELECT COUNT(*) <> 0\n" + " FROM sqlite_master\n" + " WHERE type = 'table'\n" + " AND tbl_name = 'ldb_attr_%q';", pAttrName); /* Did it exist? */ @@ -1882,10 +1956,10 @@ new_attr(struct ldb_module * module, /* Nope. Create the table */ QUERY_NOROWS(lsqlite3, FALSE, - "CREATE TABLE ldb_attr_%q " - "(" - " eid INTEGER REFERENCES ldb_entry, " - " attr_value TEXT" + "CREATE TABLE ldb_attr_%q\n" + "(\n" + " eid INTEGER REFERENCES ldb_entry,\n" + " attr_value TEXT\n" ");", pAttrName); } diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index b02b806150..c44351c543 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -146,58 +146,13 @@ -- ------------------------------------------------------ +/*** TESTS ***/ + /* * dn: o=University of Michigan,c=US * objectclass: organization * objectclass: domainRelatedObject */ --- newDN -BEGIN; - -INSERT OR IGNORE INTO ldb_object - (parent_tree_key - dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('', - 'c=US', - 'c', 'US', 1, 0); - -INSERT INTO ldb_object - (parent_tree_key, - dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('0001', - 'o=University of Michigan,c=US', - 'o', 'University of Michigan', 1, 0); - --- newObjectClass -INSERT OR IGNORE INTO ldb_attributes - (attr_name, parent_tree_key, objectclass_p) - VALUES - ('objectclass', '', 1); - -INSERT INTO ldb_object - (parent_tree_key, - dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', - NULL, - 'objectclass', 'organization', 2, 0); - -INSERT OR IGNORE INTO ldb_attributes - (attr_name, parent_tree_key, objectclass_p) - VALUES - ('objectclass', '', 1); - -INSERT INTO ldb_object - (parent_tree_key, - dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', - NULL, - 'objectclass', 'domainRelatedObject', 2, 0); - -COMMIT; /* @@ -209,48 +164,6 @@ COMMIT; * seeAlso: * telephonenumber: +1 313 764-1817 */ --- addAttrValuePair -BEGIN; - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'l', 'Ann Arbor, Michigan', 2, 0); - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'st', 'Michigan', 2, 0); - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'o', 'University of Michigan', 2, 0); - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'o', 'UMICH', 2, 0); - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'seeAlso', '', 2, 0); - -INSERT INTO ldb_object - (parent_tree_key, dn, - attr_name, attr_value, object_type, max_child_num) - VALUES ('00010001', NULL, - 'telephonenumber', '+1 313 764-1817', 2, 0); - -COMMIT; - --- ---------------------------------------------------------------------- /* * dn: @ATTRIBUTES @@ -259,44 +172,6 @@ COMMIT; * ou: CASE_INSENSITIVE * dn: CASE_INSENSITIVE */ --- newAttribute - -BEGIN; - -INSERT OR IGNORE INTO ldb_attributes - (attr_name, parent_tree_key, objectclass_p) - VALUES - ('uid', '', 0); - -UPDATE ldb_attributes - SET case_insensitive_p = 1, - wildcard_p = 1, - hidden_p = 0, - integer_p = 0 - WHERE attr_name = 'uid' - -UPDATE ldb_attributes - SET case_insensitive_p = 1, - wildcard_p = 0, - hidden_p = 0, - integer_p = 0 - WHERE attr_name = 'cn' - -UPDATE ldb_attributes - SET case_insensitive_p = 1, - wildcard_p = 0, - hidden_p = 0, - integer_p = 0 - WHERE attr_name = 'ou' - -UPDATE ldb_attributes - SET case_insensitive_p = 1, - wildcard_p = 0, - hidden_p = 0, - integer_p = 0 - WHERE attr_name = 'dn' - --- ---------------------------------------------------------------------- /* * dn: @SUBCLASSES @@ -309,25 +184,3 @@ UPDATE ldb_attributes * organizationalPerson: OpenLDAPperson * user: computer */ --- insertSubclass - -/* NOT YET UPDATED!!! * - - -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'domain', /* next_tree_key('top') */ '00010001'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'person', /* next_tree_key('top') */ '00010002'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'domainDNS', /* next_tree_key('domain') */ '000100010001'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'organizationalPerson', /* next_tree_key('person') */ '000100020001'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'fooPerson', /* next_tree_key('person') */ '000100020002'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'user', /* next_tree_key('organizationalPerson') */ '0001000200010001'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002'; -INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) - SELECT 'computer', /* next_tree_key('user') */ '0001000200010001'; - -- cgit From 3e92471d4cfa169b97da73752b6eb6d1ea8cb466 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 15 Jun 2005 01:02:53 +0000 Subject: r7596: next step in ldap cleanup. I'm aiming to get rid of the cut&pasted ldif parsing code in libcli/ldap/ldap_ldif.c, and instead use the ldb ldif code. To do that I have changed the ldap code to use 'struct ldb_message_element' instead of 'struct ldap_attribute'. They are essentially the same structure anyway, so by making them really the same it will be much easier to use the ldb code in libcli/ldap/ I have also made 'struct ldb_val' the same as a DATA_BLOB, which will simplify data handling in quite a few places (I haven't yet removed all the code that maps between these two, that will come later) (This used to be commit 87fc3073392236221a3a6b933284e9e477c24ae5) --- source4/lib/ldb/include/ldb.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 7a28d05b38..4bf2f9581f 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -57,10 +57,12 @@ sensible, but it can be to anything you like, including binary data blobs of arbitrary size. */ +#ifndef ldb_val struct ldb_val { - unsigned int length; - void *data; + uint8_t *data; + size_t length; }; +#endif /* these flags are used in ldd_message_element.flags fields. The LDA_FLAGS_MOD_* flags are used in ldap_modify() calls to specify @@ -82,7 +84,7 @@ struct ldb_val { */ struct ldb_message_element { unsigned int flags; - char *name; + const char *name; unsigned int num_values; struct ldb_val *values; }; -- cgit From 6be47e9bc2484340f40264eb0852b2c1619ee900 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 15 Jun 2005 01:08:54 +0000 Subject: r7597: removed the bogus get_myfullname() and get_mydomname() calls, and put them in the ntlmssp code, which is the only place they are used. Andrew, please remove them completely once you have some more reliable way to get this info they are bogus as gethostname() may give us a short hostname (and does on lot of systems), so the calls often give totally the wrong result anyway (This used to be commit 35ec292f86bf663618b4bd03133d9bbd6e2faf10) --- source4/lib/util.c | 56 ------------------------------------------------------ 1 file changed, 56 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 93559d9518..59d83a966a 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -280,62 +280,6 @@ char* get_myname(void) return hostname; } -/**************************************************************************** - Get my own name, including domain. -****************************************************************************/ - -BOOL get_myfullname(char *my_name) -{ - pstring hostname; - - *hostname = 0; - - /* get my host name */ - if (gethostname(hostname, sizeof(hostname)) == -1) { - DEBUG(0,("gethostname failed\n")); - return False; - } - - /* Ensure null termination. */ - hostname[sizeof(hostname)-1] = '\0'; - - if (my_name) - fstrcpy(my_name, hostname); - return True; -} - -/**************************************************************************** - Get my own domain name. -****************************************************************************/ - -BOOL get_mydomname(char *my_domname) -{ - pstring hostname; - char *p; - - *hostname = 0; - /* get my host name */ - if (gethostname(hostname, sizeof(hostname)) == -1) { - DEBUG(0,("gethostname failed\n")); - return False; - } - - /* Ensure null termination. */ - hostname[sizeof(hostname)-1] = '\0'; - - p = strchr_m(hostname, '.'); - - if (!p) - return False; - - p++; - - if (my_domname) - fstrcpy(my_domname, p); - - return True; -} - /**************************************************************************** Interpret a protocol description string, with a default. ****************************************************************************/ -- cgit From f021dffb6991138213967521c743f03f474f9af9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 15 Jun 2005 02:43:42 +0000 Subject: r7601: ldb_sqlite3 work in progress (This used to be commit 0a64948152a446b5e127578d49b1ed8a90a1a222) --- source4/lib/ldb/common/ldb_explode_dn.c | 5 +- source4/lib/ldb/common/ldb_utf8.c | 18 ++- source4/lib/ldb/include/ldb.h | 5 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 243 +++++++++++++++++++++++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 7 +- 5 files changed, 231 insertions(+), 47 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 5cea4424b0..79cbe12d61 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -138,10 +138,13 @@ ldb_explode_dn(void * mem_ctx, } /* Copy the provided DN so we can manipulate it */ - if ((dn_copy = p = talloc_strdup(mem_ctx, orig_dn)) == NULL) { + if ((p = ldb_dn_fold(mem_ctx, orig_dn, + hUserData, case_fold_attr_fn)) == NULL) { goto failed; } + dn_copy = p; + /* Our copy may end shorter than the original as we unescape chars */ dn_end = dn_copy + orig_len + 1; diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index dc25d6cf13..35249c4b70 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -95,11 +95,13 @@ int ldb_attr_cmp(const char *dn1, const char *dn2) attribute values of case insensitive attributes. We also need to remove extraneous spaces between elements */ -char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_attr_fn)(struct ldb_module * module, char * attr)) +char *ldb_dn_fold(void * mem_ctx, + const char * dn, + void * user_data, + int (* case_fold_attr_fn)(void * user_data, char * attr)) { const char *dn_orig = dn; - struct ldb_context *ldb = module->ldb; - TALLOC_CTX *tmp_ctx = talloc_new(ldb); + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); char *ret; size_t len; @@ -133,14 +135,14 @@ char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_att } if (*value == 0) goto failed; - case_fold_required = (* case_fold_attr_fn)(module, attr); + case_fold_required = (* case_fold_attr_fn)(user_data, attr); - attr = ldb_casefold(ldb, attr); + attr = ldb_casefold(tmp_ctx, attr); if (attr == NULL) goto failed; talloc_steal(tmp_ctx, attr); if (case_fold_required) { - value = ldb_casefold(ldb, value); + value = ldb_casefold(tmp_ctx, value); if (value == NULL) goto failed; talloc_steal(tmp_ctx, value); } @@ -156,12 +158,12 @@ char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_att if (*dn == ',') dn++; } - talloc_steal(ldb, ret); + talloc_steal(mem_ctx, ret); talloc_free(tmp_ctx); return ret; failed: talloc_free(tmp_ctx); - return ldb_casefold(ldb, dn_orig); + return ldb_casefold(mem_ctx, dn_orig); } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 4bf2f9581f..fabaec5da2 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -275,7 +275,10 @@ int ldb_dn_cmp(const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); /* case-fold a DN */ -char *ldb_dn_fold(struct ldb_module *module, const char *dn, int (*case_fold_attr_fn)(struct ldb_module * module, char * attr)); +char *ldb_dn_fold(void * mem_ctx, + const char * dn, + void * user_data, + int (* case_fold_attr_fn)(void * user_data, char * attr)); /* create an empty message */ struct ldb_message *ldb_msg_new(void *mem_ctx); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 09ba24022f..51830db94c 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -167,9 +167,11 @@ static int parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, const struct ldb_parse_tree * t); +#ifdef NEED_TABLE_LIST static char * build_attr_table_list(void * hTalloc, struct lsqlite3_private * lsqlite3); +#endif static int msg_to_sql(struct ldb_module * module, @@ -295,36 +297,140 @@ failed: /* rename a record */ static int lsqlite3_rename(struct ldb_module * module, - const char * olddn, - const char * newdn) + const char * pOldDN, + const char * pNewDN) { - /* ignore ltdb specials */ - if (olddn[0] == '@' ||newdn[0] == '@') { - return 0; - } - -#warning "lsqlite3_rename() is not yet supported" + struct lsqlite3_private * lsqlite3 = module->private_data; + + /* Case-fold each of the DNs */ + pOldDN = ldb_dn_fold(module->ldb, pOldDN, + module, case_fold_attr_required); + pNewDN = ldb_dn_fold(module->ldb, pNewDN, + module, case_fold_attr_required); - return -1; + QUERY_NOROWS(lsqlite3, + FALSE, + "UPDATE ldb_entry " + " SET dn = %Q " + " WHERE dn = %Q;", + pNewDN, pOldDN); + + return 0; } /* delete a record */ static int -lsqlite3_delete(struct ldb_module *module, - const char *dn) +lsqlite3_delete(struct ldb_module * module, + const char * pDN) { + int ret; + int bLoop; + long long eid; + char * pSql; + const char * pAttrName; + sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; - /* ignore ltdb specials */ - if (dn[0] == '@') { - return 0; - } - /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + /* Determine the eid of the DN being deleted */ + QUERY_INT(lsqlite3, + eid, + TRUE, + "SELECT eid\n" + " FROM ldb_entry\n" + " WHERE dn = %Q;", + pDN); + + /* Obtain the list of attribute names in use by this DN */ + if ((pSql = talloc_asprintf(module->ldb, + "SELECT attr_name " + " FROM ldb_attribute_values " + " WHERE eid = %lld;", + eid)) == NULL) { + return -1; + } + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pSql, + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + ret = -1; + break; + } + + /* Loop through the returned rows */ + for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { + + /* Get the next row */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { + + /* Get the values from this row */ + pAttrName = sqlite3_column_text(pStmt, 0); + + /* + * Delete any entries from the specified + * attribute table that pertain to this eid. + */ + QUERY_NOROWS(lsqlite3, + TRUE, + "DELETE FROM ldb_attr_%q " + " WHERE eid = %lld;", + pAttrName, eid); + } + } + + if (ret == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_DONE) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } + + /* Delete the descendants records */ + QUERY_NOROWS(lsqlite3, + TRUE, + "DELETE FROM ldb_descendants " + " WHERE deid = %lld;", + eid); -#warning "lsqlite3_delete() is not yet supported" + /* Delete attribute/value table entries pertaining to this DN */ + QUERY_NOROWS(lsqlite3, + TRUE, + "DELETE FROM ldb_attribute_value " + " WHERE eid = %lld;", + eid); /* Commit the transaction */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); @@ -348,7 +454,9 @@ lsqlite3_search_bytree(struct ldb_module * module, long long prevEID; char * pSql = NULL; char * pSqlConstraints; +#ifdef NEED_TABLE_LIST char * pTableList; +#endif char * hTalloc = NULL; const char * pDN; const char * pAttrName; @@ -362,6 +470,18 @@ lsqlite3_search_bytree(struct ldb_module * module, pBaseDN = ""; } + /* Allocate a temporary talloc context */ + if ((hTalloc = talloc_new(module->ldb)) == NULL) { + return -1; + } + + /* Case-fold the base DN */ + if ((pBaseDN = ldb_dn_fold(hTalloc, pBaseDN, + module, case_fold_attr_required)) == NULL) { + talloc_free(hTalloc); + return -1; + } + /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); @@ -375,19 +495,14 @@ lsqlite3_search_bytree(struct ldb_module * module, " WHERE attr_value = %Q;", pBaseDN)) == SQLITE_DONE) { QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + talloc_free(hTalloc); return 0; } else if (ret != SQLITE_OK) { QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + talloc_free(hTalloc); return -1; } - /* Allocate a temporary talloc context */ - if ((hTalloc = talloc_new(module->ldb)) == NULL) { - ret = -1; - talloc_free(pTree); - goto cleanup; - } - /* Convert filter into a series of SQL conditions (constraints) */ pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree); @@ -453,14 +568,15 @@ lsqlite3_search_bytree(struct ldb_module * module, goto cleanup; } +#ifdef NEED_TABLE_LIST /* * Build the attribute table list from the list of unique names. */ - if ((pTableList = build_attr_table_list(hTalloc, lsqlite3)) == NULL) { ret = -1; goto cleanup; } +#endif switch(scope) { case LDB_SCOPE_DEFAULT: @@ -534,6 +650,11 @@ lsqlite3_search_bytree(struct ldb_module * module, break; } + if (pSql == NULL) { + ret = -1; + goto cleanup; + } + if (lsqlite3_debug) { printf("%s\n", pSql); } @@ -630,12 +751,12 @@ lsqlite3_search_bytree(struct ldb_module * module, bLoop = FALSE; } - /* End the transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); - /* We're alll done with this query */ sqlite3_free(pSql); + /* End the transaction */ + QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); + /* Were there any results? */ if (ret != 0 || allocated == 0) { /* Nope. We can free the results. */ @@ -733,9 +854,11 @@ lsqlite3_add(struct ldb_module *module, /* modify a record */ static int -lsqlite3_modify(struct ldb_module *module, - const struct ldb_message *msg) +lsqlite3_modify(struct ldb_module * module, + const struct ldb_message * msg) { + char * pDN; + long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -746,7 +869,25 @@ lsqlite3_modify(struct ldb_module *module, /* Begin a transaction */ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); -#warning "modify() not yet implemented" + /* Case-fold the DN so we can compare it to what's in the database */ + pDN = ldb_dn_fold(module->ldb, msg->dn, + module, case_fold_attr_required); + + /* Determine the eid of the DN being deleted */ + QUERY_INT(lsqlite3, + eid, + TRUE, + "SELECT eid\n" + " FROM ldb_entry\n" + " WHERE dn = %Q;", + pDN); + + /* Apply the message attributes */ + if (msg_to_sql(module, msg, eid, TRUE) != 0) { + QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + return -1; + } + /* Everything worked. Commit it! */ QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); @@ -1409,7 +1550,8 @@ parsetree_to_sql(struct ldb_module *module, } child = ret; - ret = talloc_asprintf("(\n" + ret = talloc_asprintf(hTalloc, + "(\n" "%s\n" ")\n", child); @@ -1436,7 +1578,8 @@ parsetree_to_sql(struct ldb_module *module, talloc_free(child); } child = ret; - ret = talloc_asprintf("(\n" + ret = talloc_asprintf(hTalloc, + "(\n" "%s\n" ")\n", child); @@ -1495,7 +1638,7 @@ parsetree_to_sql(struct ldb_module *module, ret = talloc_strdup(hTalloc, p); sqlite3_free(p); - + } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { /* * For object classes, we want to search for all objectclasses @@ -1543,6 +1686,7 @@ parsetree_to_sql(struct ldb_module *module, ret = talloc_strdup(hTalloc, p); sqlite3_free(p); } + return ret; } @@ -1619,6 +1763,7 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, } +#ifdef NEED_TABLE_LIST /* * Use the already-generated FILTER_ATTR_TABLE to create a list of attribute * table names that will be used in search queries. @@ -1724,6 +1869,7 @@ build_attr_table_list(void * hTalloc, return pTableList; } +#endif /* @@ -1847,6 +1993,7 @@ new_dn(struct ldb_module * module, char * p; char * pPartialDN; long long eid; + long long peid; struct ldb_dn * pExplodedDN; struct ldb_dn_component * pComponent; struct ldb_context * ldb = module->ldb; @@ -1906,9 +2053,35 @@ new_dn(struct ldb_module * module, nComponent == 0 ? "" : "OR IGNORE", eid, pPartialDN); - /* Get the EID of the just inserted row (the next parent) */ + /* Save the parent EID */ + peid = eid; + + /* Get the EID of the just inserted row */ eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); + /* + * Popoulate the descendant table + */ + + /* This table has an entry for itself as well as descendants */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_descendants " + " (aeid, deid) " + " VALUES " + " (%lld, %lld);", + eid, eid); + + /* Now insert rows for all of our ancestors */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_descendants " + " (aeid, deid) " + " SELECT aeid, %lld " + " FROM ldb_descendants " + " WHERE aeid = %lld;", + eid, peid); + /* If this is the final component, also add DN attribute */ if (nComponent == 0) { QUERY_NOROWS(lsqlite3, diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 0366809c33..6516787a5a 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -47,8 +47,10 @@ callback function used in call to ldb_dn_fold() for determining whether an attribute type requires case folding. */ -static int ltdb_case_fold_attr_required(struct ldb_module *module, char *attr) +static int ltdb_case_fold_attr_required(void * user_data, char *attr) { + struct ldb_module *module = user_data; + return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE; } @@ -106,7 +108,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) } talloc_free(attr_name); } else { - dn_folded = ldb_dn_fold(module, dn, ltdb_case_fold_attr_required); + dn_folded = ldb_dn_fold(module->ldb, dn, + module, ltdb_case_fold_attr_required); } if (!dn_folded) { -- cgit From 93e03bd27215a54d79ca996941468d1c33099ff3 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 15 Jun 2005 02:45:11 +0000 Subject: r7602: fix some compiler warnings (This used to be commit ce9966e091d36f66d409ac6f7b5e462c9dc37325) --- source4/lib/ldb/common/ldb_msg.c | 2 +- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 8d921b989b..295c74c90d 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -443,7 +443,7 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, el2->values, sizeof(struct ldb_val) * el2->num_values); el1->num_values += el2->num_values; - talloc_free(el2->name); + talloc_free(discard_const_p(char, el2->name)); if (i+1num_elements) { memmove(el2, el2+1, sizeof(struct ldb_message_element) * (msg2->num_elements - (i+1))); diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index b3d8fcc1a5..828bcc5d61 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -351,7 +351,7 @@ static LDAPMod **lldb_msg_to_mods(struct ldb_context *ldb, break; } } - mods[num_mods]->mod_type = el->name; + mods[num_mods]->mod_type = discard_const_p(char, el->name); mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], struct berval *, 1+el->num_values); diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index d210510ff2..3644d046e0 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -169,7 +169,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, talloc_free(ret); return NULL; } - talloc_free(el2.name); + talloc_free(discard_const_p(char, el2.name)); continue; } -- cgit From 9378cca1aeda2f12a997cd6017d6d983a20e34bf Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 15 Jun 2005 13:01:39 +0000 Subject: r7608: bug fix after yesterday's change (This used to be commit 0218fc678e375a05fbc4da5500706199340918e2) --- source4/lib/ldb/common/ldb_modules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 7df9901ae9..d4f35c0e56 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -140,7 +140,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) const char * const attrs[] = { "@LIST" , NULL}; struct ldb_message **msg = NULL; - ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg); + ret = ldb_search(ldb, "@MODULES", LDB_SCOPE_BASE, "", attrs, &msg); if (ret == 0 || (ret == 1 && msg[0]->num_elements == 0)) { ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); } else { -- cgit From 4864c329c4633de2ccbefa7890651a92a5db0d4c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 15 Jun 2005 17:15:01 +0000 Subject: r7615: fix the build and simplify gendb_search_dn (This used to be commit b38bb63175ae0bdcf833c017e5fbbfc2c0769506) --- source4/lib/gendb.c | 43 ++++++++++++----------------------- source4/lib/ldb/tests/test-generic.sh | 2 +- 2 files changed, 16 insertions(+), 29 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index dc5b7f39aa..de3e49e652 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -35,22 +35,27 @@ int gendb_search_v(struct ldb_context *ldb, const char *format, va_list ap) _PRINTF_ATTRIBUTE(6,0) { + enum ldb_scope scope = LDB_SCOPE_SUBTREE; char *expr = NULL; int count; - vasprintf(&expr, format, ap); - if (expr == NULL) { - return -1; + if (format) { + vasprintf(&expr, format, ap); + if (expr == NULL) { + return -1; + } + } else { + scope = LDB_SCOPE_BASE; } *res = NULL; - count = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, attrs, res); + count = ldb_search(ldb, basedn, scope, expr, attrs, res); if (*res) talloc_steal(mem_ctx, *res); DEBUG(4,("gendb_search_v: %s %s -> %d (%s)\n", - basedn?basedn:"NULL", expr, count, + basedn?basedn:"NULL", expr?expr:"NULL", count, count==-1?ldb_errstring(ldb):"OK")); free(expr); @@ -79,31 +84,13 @@ int gendb_search(struct ldb_context *ldb, } int gendb_search_dn(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - const char *dn, - struct ldb_message ***res, - const char * const *attrs) + TALLOC_CTX *mem_ctx, + const char *dn, + struct ldb_message ***res, + const char * const *attrs) { - va_list ap; - int count; - - *res = NULL; - - count = ldb_search(ldb, dn, LDB_SCOPE_BASE, "", attrs, res); - - if (count > 1) { - DEBUG(1, ("DB Corruption ? - Found more then one entry for dn: %s", dn)); - return -1; - } - - if (*res) talloc_steal(mem_ctx, *res); - - DEBUG(4,("gendb_search_dn: %s -> %d (%s)\n", - dn, count, count==-1?ldb_errstring(ldb):"OK")); - - return count; + return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); } - /* setup some initial ldif in a ldb diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 7b5c24512e..7b82c672be 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -39,7 +39,7 @@ $VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \ $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 $VALGRIND bin/ldbsearch '((' uid && exit 1 $VALGRIND bin/ldbsearch '(objectclass=)' uid || exit 1 -$VALGRIND bin/ldbsearch 'dn=cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US' uid || exit 1 +$VALGRIND bin/ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US' -s base "" sn || exit 1 echo "Starting ldbtest indexed" time $VALGRIND bin/ldbtest -r 1000 -s 5000 || exit 1 -- cgit From bab977dad76e9204278c7afe0bb905cda064f488 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 16 Jun 2005 05:39:40 +0000 Subject: r7626: a new ldap client library. Main features are: - hooked into events system, so requests can be truly async and won't interfere with other processing happening at the same time - uses NTSTATUS codes for errors (previously errors were mostly ignored). In a similar fashion to the DOS error handling, I have reserved a range of the NTSTATUS code 32 bit space for LDAP error codes, so a function can return a LDAP error code in a NTSTATUS - much cleaner packet handling (This used to be commit 2e3c660b2fc20e046d82bf1cc296422b6e7dfad0) --- source4/lib/socket/config.mk | 3 +- source4/lib/socket/connect.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ source4/lib/socket/socket.c | 5 +-- source4/lib/socket/socket.h | 5 +++ 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 source4/lib/socket/connect.c (limited to 'source4/lib') diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index e4719c3f67..13fe584373 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -35,7 +35,8 @@ NOPROTO=YES INIT_OBJ_FILES = \ lib/socket/socket.o ADD_OBJ_FILES = \ - lib/socket/access.o + lib/socket/access.o \ + lib/socket/connect.o NOPROTO=YES # End SUBSYSTEM SOCKET ################################################ diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c new file mode 100644 index 0000000000..f3f9134f26 --- /dev/null +++ b/source4/lib/socket/connect.c @@ -0,0 +1,74 @@ +/* + Unix SMB/CIFS implementation. + + implements a non-blocking connect operation that is aware of the samba4 events + system + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/socket/socket.h" +#include "lib/events/events.h" + + +/* + handle write events on connect completion +*/ +static void socket_connect_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *private) +{ + NTSTATUS *status = (NTSTATUS *)private; + *status = NT_STATUS_OK; +} + + +/* + just like socket_connect() but other events can happen while the + connect is ongoing. This isn't as good as making the calling code + fully async during its connect phase, but at least it means that any + calling code that uses this won't interfere with code that is + properly async + */ +NTSTATUS socket_connect_ev(struct socket_context *sock, + const char *my_address, int my_port, + const char *server_address, int server_port, + uint32_t flags, struct event_context *ev) +{ + TALLOC_CTX *tmp_ctx = talloc_new(sock); + NTSTATUS status; + + set_blocking(socket_get_fd(sock), False); + + status = socket_connect(sock, my_address, my_port, + server_address, server_port, flags); + + event_add_fd(ev, tmp_ctx, socket_get_fd(sock), EVENT_FD_WRITE, + socket_connect_handler, &status); + + while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + if (event_loop_once(ev) != 0) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_ERROR; + } + } + + status = socket_connect_complete(sock, flags); + + talloc_free(tmp_ctx); + return status; +} diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 39379be678..9d5b67a966 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -243,13 +243,10 @@ NTSTATUS socket_sendto(struct socket_context *sock, /* - ask for the number of bytes in a pending incoming datagram + ask for the number of bytes in a pending incoming packet */ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending) { - if (sock->type != SOCKET_TYPE_DGRAM) { - return NT_STATUS_INVALID_PARAMETER; - } if (!sock->ops->fn_pending) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index e2879e5247..8645ba28bc 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -139,4 +139,9 @@ BOOL socket_check_access(struct socket_context *sock, const char *service_name, const char **allow_list, const char **deny_list); +NTSTATUS socket_connect_ev(struct socket_context *sock, + const char *my_address, int my_port, + const char *server_address, int server_port, + uint32_t flags, struct event_context *ev); + #endif /* _SAMBA_SOCKET_H */ -- cgit From 289845ff77d87ce6dd8bfc03f62432f3868049c2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 16 Jun 2005 06:39:41 +0000 Subject: r7627: Fix warning in unused (?) function. (This used to be commit a4d05988637b4e607c3cdad83bfb1e9cf923b7f0) --- source4/lib/util_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 557baa716d..e02198754d 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -115,7 +115,7 @@ read a line from a file with possible \ continuation chars. Blanks at the start or end of a line are stripped. The string will be allocated if s2 is NULL ****************************************************************************/ -char *fgets_slash(char *s2,int maxlen,FILE *f) +char *fgets_slash(char *s2,int maxlen,XFILE *f) { char *s=s2; int len = 0; -- cgit From af237084ecd4f9928c6c282b9c5c73598d5c73d6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 16 Jun 2005 11:36:09 +0000 Subject: r7633: this patch started as an attempt to make the dcerpc code use a given event_context for the socket_connect() call, so that when things that use dcerpc are running alongside anything else it doesn't block the whole process during a connect. Then of course I needed to change any code that created a dcerpc connection (such as the auth code) to also take an event context, and anything that called that and so on .... thus the size of the patch. There were 3 places where I punted: - abartlet wanted me to add a gensec_set_event_context() call instead of adding it to the gensec init calls. Andrew, my apologies for not doing this. I didn't do it as adding a new parameter allowed me to catch all the callers with the compiler. Now that its done, we could go back and use gensec_set_event_context() - the ejs code calls auth initialisation, which means it should pass in the event context from the web server. I punted on that. Needs fixing. - I used a NULL event context in dcom_get_pipe(). This is equivalent to what we did already, but should be fixed to use a callers event context. Jelmer, can you think of a clean way to do that? I also cleaned up a couple of things: - libnet_context_destroy() makes no sense. I removed it. - removed some unused vars in various places (This used to be commit 3a3025485bdb8f600ab528c0b4b4eef0c65e3fc9) --- source4/lib/com/com.h | 1 + source4/lib/com/dcom/main.c | 14 +++++++++----- source4/lib/com/main.c | 7 ++++++- source4/lib/registry/reg_backend_rpc.c | 5 +++-- source4/lib/registry/tools/regdiff.c | 6 ++++-- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 2 +- source4/lib/registry/tools/regtree.c | 2 +- 8 files changed, 26 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h index 97841e14c3..0a26a568b0 100644 --- a/source4/lib/com/com.h +++ b/source4/lib/com/com.h @@ -26,6 +26,7 @@ struct IUnknown_vtable; struct com_context { struct dcom_client_context *dcom; + struct event_context *event_ctx; }; typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid); diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index 08a928cda6..bc47cb7c68 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -84,7 +84,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** return dcerpc_pipe_connect(ctx, p, "ncalrpc", DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->credentials); + ctx->dcom->credentials, ctx->event_ctx); } /* Allow server name to contain a binding string */ @@ -92,7 +92,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect_b(ctx, p, bd, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->credentials); + ctx->dcom->credentials, ctx->event_ctx); talloc_free(mem_ctx); return status; @@ -109,7 +109,7 @@ static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe ** status = dcerpc_pipe_connect(ctx, p, binding, DCERPC_IREMOTEACTIVATION_UUID, DCERPC_IREMOTEACTIVATION_VERSION, - ctx->dcom->credentials); + ctx->dcom->credentials, ctx->event_ctx); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); @@ -256,7 +256,7 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const return WERR_OK; } -NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) +NTSTATUS dcom_get_pipe(struct IUnknown *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding *binding; struct GUID iid; @@ -301,9 +301,13 @@ NTSTATUS dcom_get_pipe (struct IUnknown *iface, struct dcerpc_pipe **pp) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error parsing string binding")); } else { + /* TODO: jelmer, please look at this. The + "NULL" here should be a real event + context */ status = dcerpc_pipe_connect_b(NULL, &p, binding, uuid, 0.0, - iface->ctx->dcom->credentials); + iface->ctx->dcom->credentials, + NULL); } talloc_free(binding); i++; diff --git a/source4/lib/com/main.c b/source4/lib/com/main.c index 378c3738b9..210e8ba79c 100644 --- a/source4/lib/com/main.c +++ b/source4/lib/com/main.c @@ -21,11 +21,16 @@ #include "includes.h" #include "dlinklist.h" #include "lib/com/com.h" +#include "lib/events/events.h" #include "librpc/gen_ndr/com_dcom.h" -WERROR com_init(struct com_context **ctx) +WERROR com_init(struct com_context **ctx, struct event_context *event_ctx) { *ctx = talloc(NULL, struct com_context); + if (event_ctx == NULL) { + event_ctx = event_context_init(*ctx); + } + (*ctx)->event_ctx = event_ctx; return WERR_OK; } diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 88cce2584e..3c38b5d312 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -362,7 +362,8 @@ static struct hive_operations reg_backend_rpc = { .num_values = rpc_num_values, }; -WERROR reg_open_remote (struct registry_context **ctx, struct cli_credentials *credentials, const char *location) +WERROR reg_open_remote(struct registry_context **ctx, struct cli_credentials *credentials, + const char *location, struct event_context *ev) { NTSTATUS status; struct dcerpc_pipe *p; @@ -378,7 +379,7 @@ WERROR reg_open_remote (struct registry_context **ctx, struct cli_credentials *c &p, location, DCERPC_WINREG_UUID, DCERPC_WINREG_VERSION, - credentials); + credentials, ev); (*ctx)->backend_data = p; if(NT_STATUS_IS_ERR(status)) { diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index f86c0ae383..a9d189c033 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -144,8 +144,10 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, break; case 'R': if (!h1 && !from_null) - error = reg_open_remote(&h1, cmdline_credentials, poptGetOptArg(pc)); - else if (!h2) error = reg_open_remote(&h2, cmdline_credentials, poptGetOptArg(pc)); + error = reg_open_remote(&h1, cmdline_credentials, + poptGetOptArg(pc), NULL); + else if (!h2) error = reg_open_remote(&h2, cmdline_credentials, + poptGetOptArg(pc), NULL); break; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 02ef4d4655..3ada9f66e2 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -763,7 +763,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd } if (remote) { - error = reg_open_remote (&h, cmdline_credentials, remote); + error = reg_open_remote (&h, cmdline_credentials, remote, NULL); } else { error = reg_open_local (&h); } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 0c53f737b8..108cc17336 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -390,7 +390,7 @@ static char **reg_completion(const char *text, int start, int end) } if (remote) { - error = reg_open_remote (&h, cmdline_credentials, remote); + error = reg_open_remote (&h, cmdline_credentials, remote, NULL); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); } else { diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index f18467b523..2385123b7f 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -99,7 +99,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) } if (remote) { - error = reg_open_remote(&h, cmdline_credentials, remote); + error = reg_open_remote(&h, cmdline_credentials, remote, NULL); } else if (backend) { error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); } else { -- cgit From f4183d9be26fdc00b1d3ba477485223486e9a5bc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 16 Jun 2005 11:58:31 +0000 Subject: r7635: change the license of this file to lgpl like the rest of ldb (This used to be commit 8735188b46d4bb6c3d63d22a8c6f3fad2c82df89) --- source4/lib/ldb/common/ldb_explode_dn.c | 44 ++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 79cbe12d61..30e5740652 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -1,24 +1,40 @@ /* - Unix SMB/CIFS implementation. - LDAP server + ldb database library + Copyright (C) Simo Sorce 2004 Copyright (C) Derrell Lipman 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + * Name: ldb + * + * Component: ldb dn parsing + * + * Description: explode a dn into it's own basic elements + * and put them in a structure + * + * Author: Simo Sorce + * Author: Derrell Lipman + */ + #include #include "includes.h" #include "ldb/include/ldb.h" -- cgit From fcb339c087de567c860cc9e5e92253a642b982a4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Jun 2005 16:43:23 +0000 Subject: r7641: Fix based on work from "Shlomi Yaakobovich" to catch loops in corrupted tdb files. Jeremy. (This used to be commit f9f3037d6855259edd56fd5a23d63dbb37f0a751) --- source4/lib/tdb/common/tdb.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index e9cbc12b91..44533aad27 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1295,12 +1295,6 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, tdb_off current; if (rec_read(tdb, tlock->off, rec) == -1) goto fail; - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } /* Detect infinite loops. From "Shlomi Yaakobovich" . */ if (tlock->off == rec->next) { @@ -1308,6 +1302,13 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, goto fail; } + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + /* Try to clean dead ones from old traverses */ current = tlock->off; tlock->off = rec->next; -- cgit From 11bc3f3589007cfc3dcce1a37d824a8c83b01d1a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jun 2005 00:10:13 +0000 Subject: r7660: improved error handling in socket_connect_ev() (it matters when name resolution fails) (This used to be commit 4013c2ddea0cd03f875e2acf40d2a34344017d05) --- source4/lib/socket/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c index f3f9134f26..e7f2a11daf 100644 --- a/source4/lib/socket/connect.c +++ b/source4/lib/socket/connect.c @@ -56,6 +56,9 @@ NTSTATUS socket_connect_ev(struct socket_context *sock, status = socket_connect(sock, my_address, my_port, server_address, server_port, flags); + if (NT_STATUS_IS_ERR(status)) { + return status; + } event_add_fd(ev, tmp_ctx, socket_get_fd(sock), EVENT_FD_WRITE, socket_connect_handler, &status); -- cgit From 52400f0f7d26727a59797e21c09a1433daf094e4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jun 2005 02:46:25 +0000 Subject: r7666: fixed a memory leak in the ldap ldb backend (This used to be commit ac3f33c61555a2afa30fe446676013564982e257) --- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 828bcc5d61..16beed58f8 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -76,14 +76,13 @@ static int lldb_rename(struct ldb_module *module, const char *olddn, const char int ret = 0; char *newrdn, *p; const char *parentdn = ""; - TALLOC_CTX *mem_ctx = talloc_new(lldb); /* ignore ltdb specials */ if (olddn[0] == '@' ||newdn[0] == '@') { return 0; } - newrdn = talloc_strdup(mem_ctx, newdn); + newrdn = talloc_strdup(lldb, newdn); if (!newrdn) { return -1; } @@ -99,7 +98,7 @@ static int lldb_rename(struct ldb_module *module, const char *olddn, const char ret = -1; } - talloc_free(mem_ctx); + talloc_free(newrdn); return ret; } -- cgit From 03b0f279ed7d1ed7083e0c2301af94ff39f0e8a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jun 2005 02:47:26 +0000 Subject: r7667: added a ldb ildap backend, using our internal ldap client library. Next step is to remove the check for the ldap libraries in configure (This used to be commit 74841dbb2a86bb1c584b5c26c4cd24a818a65a34) --- source4/lib/ldb/common/ldb.c | 6 +- source4/lib/ldb/config.mk | 12 + source4/lib/ldb/include/ldb_private.h | 3 + source4/lib/ldb/ldb_ildap/ldb_ildap.c | 401 ++++++++++++++++++++++++++++++++++ 4 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 source4/lib/ldb/ldb_ildap/ldb_ildap.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index f5c6d551ea..2d0d09de3e 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -56,7 +56,11 @@ struct ldb_context *ldb_connect(const char *url, unsigned int flags, ldb_ctx = ltdb_connect(url, flags, options); } -#if HAVE_LDAP +#if HAVE_ILDAP + if (strncmp(url, "ldap", 4) == 0) { + ldb_ctx = ildb_connect(url, flags, options); + } +#elif HAVE_LDAP if (strncmp(url, "ldap", 4) == 0) { ldb_ctx = lldb_connect(url, flags, options); } diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 03855017ba..1a6f006ea0 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -28,6 +28,18 @@ NOPROTO = YES # End MODULE libldb_ldap ################################################ +################################################ +# Start MODULE libldb_ildap +[MODULE::libldb_ildap] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/ldb_ildap/ldb_ildap.o +REQUIRED_SUBSYSTEMS = \ + LIBCLI_LDAP +NOPROTO = YES +# End MODULE libldb_ildap +################################################ + ################################################ # Start MODULE libldb_sqlite3 [MODULE::libldb_sqlite3] diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index e022d68ec7..4acdd543f2 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -120,6 +120,9 @@ struct ldb_context *ltdb_connect(const char *url, struct ldb_context *lldb_connect(const char *url, unsigned int flags, const char *options[]); +struct ldb_context *ildb_connect(const char *url, + unsigned int flags, + const char *options[]); struct ldb_context *lsqlite3_connect(const char *url, unsigned int flags, const char *options[]); diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c new file mode 100644 index 0000000000..c35d9de6b1 --- /dev/null +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -0,0 +1,401 @@ +/* + ldb database library - ildap backend + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + This is a ldb backend for the internal ldap client library in + Samba4. By using this backend we are independent of a system ldap + library +*/ + + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "libcli/ldap/ldap.h" +#include "libcli/ldap/ldap_client.h" + +struct ildb_private { + const char *basedn; + struct ldap_connection *ldap; + NTSTATUS last_rc; +}; + +/* + rename a record +*/ +static int ildb_rename(struct ldb_module *module, const char *olddn, const char *newdn) +{ + struct ildb_private *ildb = module->private_data; + int ret = 0; + char *newrdn, *p; + const char *parentdn = ""; + + /* ignore ltdb specials */ + if (olddn[0] == '@' ||newdn[0] == '@') { + return 0; + } + + newrdn = talloc_strdup(ildb, newdn); + if (!newrdn) { + return -1; + } + + p = strchr(newrdn, ','); + if (p) { + *p++ = '\0'; + parentdn = p; + } + + ildb->last_rc = ildap_rename(ildb->ldap, olddn, newrdn, parentdn, True); + if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ret = -1; + } + + talloc_free(newrdn); + + return ret; +} + +/* + delete a record +*/ +static int ildb_delete(struct ldb_module *module, const char *dn) +{ + struct ildb_private *ildb = module->private_data; + int ret = 0; + + /* ignore ltdb specials */ + if (dn[0] == '@') { + return 0; + } + + ildb->last_rc = ildap_delete(ildb->ldap, dn); + if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ret = -1; + } + + return ret; +} + + +/* + search for matching records +*/ +static int ildb_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + struct ildb_private *ildb = module->private_data; + int count, i; + struct ldap_message **ldapres, *msg; + + if (base == NULL) { + base = ""; + } + + if (expression == NULL || expression[0] == '\0') { + expression = "objectClass=*"; + } + + ildb->last_rc = ildap_search(ildb->ldap, base, scope, expression, attrs, + 0, &ldapres); + if (!NT_STATUS_IS_OK(ildb->last_rc)) { + return -1; + } + + count = ildap_count_entries(ildb->ldap, ldapres); + if (count == -1 || count == 0) { + talloc_free(ldapres); + return count; + } + + (*res) = talloc_array(ildb, struct ldb_message *, count+1); + if (! *res) { + talloc_free(ldapres); + return -1; + } + + (*res)[0] = NULL; + + /* loop over all messages */ + for (i=0;ir.SearchResultEntry; + + (*res)[i] = talloc(*res, struct ldb_message); + if (!(*res)[i]) { + goto failed; + } + (*res)[i+1] = NULL; + + (*res)[i]->dn = talloc_steal((*res)[i], search->dn); + (*res)[i]->num_elements = search->num_attributes; + (*res)[i]->elements = talloc_steal((*res)[i], search->attributes); + (*res)[i]->private_data = NULL; + } + + talloc_free(ldapres); + + return count; + +failed: + if (*res) talloc_free(*res); + return -1; +} + + +/* + search for matching records using a ldb_parse_tree +*/ +static int ildb_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct ildb_private *ildb = module->private_data; + char *expression; + int ret; + + expression = ldb_filter_from_tree(ildb, tree); + if (expression == NULL) { + return -1; + } + ret = ildb_search(module, base, scope, expression, attrs, res); + talloc_free(expression); + return ret; +} + + +/* + convert a ldb_message structure to a list of ldap_mod structures + ready for ildap_add() or ildap_modify() +*/ +static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb, + const struct ldb_message *msg, int use_flags) +{ + struct ldap_mod **mods; + unsigned int i; + int num_mods = 0; + + /* allocate maximum number of elements needed */ + mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1); + if (!mods) { + errno = ENOMEM; + return NULL; + } + mods[0] = NULL; + + for (i=0;inum_elements;i++) { + const struct ldb_message_element *el = &msg->elements[i]; + + mods[num_mods] = talloc(ldb, struct ldap_mod); + if (!mods[num_mods]) { + goto failed; + } + mods[num_mods+1] = NULL; + mods[num_mods]->type = 0; + mods[num_mods]->attrib = *el; + if (use_flags) { + switch (el->flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + mods[num_mods]->type = LDAP_MODIFY_ADD; + break; + case LDB_FLAG_MOD_DELETE: + mods[num_mods]->type = LDAP_MODIFY_DELETE; + break; + case LDB_FLAG_MOD_REPLACE: + mods[num_mods]->type = LDAP_MODIFY_REPLACE; + break; + } + } + num_mods++; + } + + return mods; + +failed: + talloc_free(mods); + return NULL; +} + + +/* + add a record +*/ +static int ildb_add(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_context *ldb = module->ldb; + struct ildb_private *ildb = module->private_data; + struct ldap_mod **mods; + int ret = 0; + + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + + mods = ildb_msg_to_mods(ldb, msg, 0); + + ildb->last_rc = ildap_add(ildb->ldap, msg->dn, mods); + if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ret = -1; + } + + talloc_free(mods); + + return ret; +} + + +/* + modify a record +*/ +static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_context *ldb = module->ldb; + struct ildb_private *ildb = module->private_data; + struct ldap_mod **mods; + int ret = 0; + + /* ignore ltdb specials */ + if (msg->dn[0] == '@') { + return 0; + } + + mods = ildb_msg_to_mods(ldb, msg, 1); + + ildb->last_rc = ildap_modify(ildb->ldap, msg->dn, mods); + if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ret = -1; + } + + talloc_free(mods); + + return ret; +} + +static int ildb_lock(struct ldb_module *module, const char *lockname) +{ + int ret = 0; + + if (lockname == NULL) { + return -1; + } + + /* TODO implement a local locking mechanism here */ + + return ret; +} + +static int ildb_unlock(struct ldb_module *module, const char *lockname) +{ + int ret = 0; + + if (lockname == NULL) { + return -1; + } + + /* TODO implement a local unlocking mechanism here */ + + return ret; +} + +/* + return extended error information +*/ +static const char *ildb_errstring(struct ldb_module *module) +{ + struct ildb_private *ildb = module->private_data; + return ldap_errstr(ildb->ldap, ildb->last_rc); +} + + +static const struct ldb_module_ops ildb_ops = { + .name = "ldap", + .search = ildb_search, + .search_bytree = ildb_search_bytree, + .add_record = ildb_add, + .modify_record = ildb_modify, + .delete_record = ildb_delete, + .rename_record = ildb_rename, + .named_lock = ildb_lock, + .named_unlock = ildb_unlock, + .errstring = ildb_errstring +}; + + +/* + connect to the database +*/ +struct ldb_context *ildb_connect(const char *url, + unsigned int flags, + const char *options[]) +{ + struct ldb_context *ldb = NULL; + struct ildb_private *ildb = NULL; + NTSTATUS status; + + ldb = talloc(NULL, struct ldb_context); + if (!ldb) { + errno = ENOMEM; + goto failed; + } + + ldb->debug_ops.debug = NULL; + + ildb = talloc(ldb, struct ildb_private); + if (!ildb) { + errno = ENOMEM; + goto failed; + } + + ildb->ldap = ldap_new_connection(ildb, NULL); + if (!ildb->ldap) { + errno = ENOMEM; + goto failed; + } + + status = ldap_connect(ildb->ldap, url); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + + ldb->modules = talloc(ldb, struct ldb_module); + if (!ldb->modules) { + errno = ENOMEM; + goto failed; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = ildb; + ldb->modules->ops = &ildb_ops; + + return ldb; + +failed: + talloc_free(ldb); + return NULL; +} + -- cgit From 44a04d74cdcc4b4dc75312a40b34d60e1d9a001b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jun 2005 02:48:48 +0000 Subject: r7668: - setup HAVE_ILDAP to enable the ildap backend in ldb - fixed a bug in socket_connect_ev() (This used to be commit 3f77b879a035929a843e02b798d54eba6625bde7) --- source4/lib/socket/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c index e7f2a11daf..abe474720c 100644 --- a/source4/lib/socket/connect.c +++ b/source4/lib/socket/connect.c @@ -56,7 +56,8 @@ NTSTATUS socket_connect_ev(struct socket_context *sock, status = socket_connect(sock, my_address, my_port, server_address, server_port, flags); - if (NT_STATUS_IS_ERR(status)) { + if (NT_STATUS_IS_ERR(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { return status; } -- cgit From 1f052665f304360e4c3a59f19dc98b9c70fa1299 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jun 2005 03:07:30 +0000 Subject: r7669: removed ldap from our configure tests This takes our link dependencies from this: tridge@blu:~/samba/samba4/source$ ldd bin/ldbsearch libdl.so.2 => /lib/tls/libdl.so.2 (0xb7fc9000) libldap_r.so.2 => /usr/lib/libldap_r.so.2 (0xb7f92000) liblber.so.2 => /usr/local/lib/liblber.so.2 (0xb7f85000) libpam.so.0 => /lib/libpam.so.0 (0xb7f7d000) libc.so.6 => /lib/tls/libc.so.6 (0xb7e48000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7fea000) libresolv.so.2 => /lib/tls/libresolv.so.2 (0xb7e36000) libcrypt.so.1 => /lib/tls/libcrypt.so.1 (0xb7e09000) libsasl2.so.2 => /usr/lib/libsasl2.so.2 (0xb7df3000) libgnutls.so.11 => /usr/lib/libgnutls.so.11 (0xb7d8c000) libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb7d7d000) libtasn1.so.2 => /usr/lib/libtasn1.so.2 (0xb7d6d000) libgcrypt.so.11 => /usr/lib/libgcrypt.so.11 (0xb7d20000) libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0xb7d1c000) libz.so.1 => /usr/lib/libz.so.1 (0xb7d09000) libnsl.so.1 => /lib/tls/libnsl.so.1 (0xb7cf5000) to this: tridge@blu:~/samba/samba4/source$ ldd bin/ldbsearch libdl.so.2 => /lib/tls/libdl.so.2 (0xb7fc9000) libpam.so.0 => /lib/libpam.so.0 (0xb7fc0000) libc.so.6 => /lib/tls/libc.so.6 (0xb7e8b000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7fea000) this finally gets rid of the implicit dependency on pthreads! Yay! (This used to be commit 844d2a20830a4666b6c38f6a58305be64b6b76fa) --- source4/lib/ldb/config.m4 | 5 ----- source4/lib/ldb/config.mk | 12 ------------ 2 files changed, 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index dfa72e4cd3..2b251befbb 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,8 +1,3 @@ -SMB_MODULE_DEFAULT(libldb_ldap,NOT) -if test x"$with_ldap_support" = x"yes"; then - SMB_MODULE_DEFAULT(libldb_ldap,STATIC) -fi - SMB_MODULE_DEFAULT(libldb_sqlite3,NOT) if test x"$with_sqlite3_support" = x"yes"; then SMB_MODULE_DEFAULT(libldb_sqlite3,STATIC) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 1a6f006ea0..05255fdec5 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -16,18 +16,6 @@ INIT_OBJ_FILES = \ # End MODULE libldb_schema ################################################ -################################################ -# Start MODULE libldb_ldap -[MODULE::libldb_ldap] -SUBSYSTEM = LIBLDB -INIT_OBJ_FILES = \ - lib/ldb/ldb_ldap/ldb_ldap.o -REQUIRED_SUBSYSTEMS = \ - EXT_LIB_LDAP -NOPROTO = YES -# End MODULE libldb_ldap -################################################ - ################################################ # Start MODULE libldb_ildap [MODULE::libldb_ildap] -- cgit From 5b19286df08d6cf10654d6e20c323ba44f7d2054 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 Jun 2005 13:12:13 +0000 Subject: r7690: Move the NT hash generation into the credentials system, rather than in all the callers. This also allows us to be more flexible in the type of password we store. Andrew Bartlett (This used to be commit 00b8588c68526e1d86fda0bd81c0b86f690b62c3) --- source4/lib/credentials.c | 80 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 1dbb536f9e..aaaa2cf05d 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -24,6 +24,7 @@ #include "system/filesys.h" #include "include/secrets.h" #include "lib/ldb/include/ldb.h" +#include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */ /** * Create a new credentials structure @@ -101,6 +102,46 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, if (obtained >= cred->password_obtained) { cred->password = talloc_strdup(cred, val); cred->password_obtained = obtained; + + cred->nt_hash = NULL; + return True; + } + + return False; +} + +/** + * Obtain the password for this credentials context. + * @param cred credentials context + * @retval If set, the cleartext password, otherwise NULL + */ +const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx) +{ + const char *password = cli_credentials_get_password(cred); + + if (password) { + struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password); + if (!nt_hash) { + return NULL; + } + + E_md4hash(password, nt_hash->hash); + + return nt_hash; + } else { + return cred->nt_hash; + } +} + +BOOL cli_credentials_set_nt_hash(struct cli_credentials *cred, + const struct samr_Password *nt_hash, + enum credentials_obtained obtained) +{ + if (obtained >= cred->password_obtained) { + cli_credentials_set_password(cred, NULL, obtained); + cred->nt_hash = talloc(cred, struct samr_Password); + *cred->nt_hash = *nt_hash; return True; } @@ -462,6 +503,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) "flatname", "realm", "secureChannelType", + "ntPwdHash", NULL }; @@ -500,14 +542,9 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } password = ldb_msg_find_string(msgs[0], "secret", NULL); - if (!password) { - DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", - cli_credentials_get_domain(cred))); - talloc_free(mem_ctx); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - + machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); + if (!machine_account) { DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", cli_credentials_get_domain(cred))); @@ -516,14 +553,32 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0); - if (sct) { - cli_credentials_set_secure_channel_type(cred, sct); - } else { + if (!sct) { DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n", machine_account)); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } + if (!password) { + const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash"); + struct samr_Password hash; + ZERO_STRUCT(hash); + if (nt_password_hash) { + memcpy(hash.hash, nt_password_hash->data, + MIN(nt_password_hash->length, sizeof(hash.hash))); + + cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED); + } else { + + DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", + cli_credentials_get_domain(cred))); + talloc_free(mem_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + } + + cli_credentials_set_secure_channel_type(cred, sct); + domain = ldb_msg_find_string(msgs[0], "flatname", NULL); if (domain) { cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); @@ -535,7 +590,10 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) } cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); - cli_credentials_set_password(cred, password, CRED_SPECIFIED); + if (password) { + cli_credentials_set_password(cred, password, CRED_SPECIFIED); + } + talloc_free(mem_ctx); return NT_STATUS_OK; -- cgit From ed3d8091ce2b2014350a2f7f22202dde6846a130 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 07:42:21 +0000 Subject: r7709: - convert ldb to use popt, so that it can interact with the samba cmdline credentials code (which will be done soon) - added a ldb_init() call, and changed ldb_connect() to take a ldb context. This allows for much better error handling in ldb_connect(), and also made the popt conversion easier - fixed up all the existing backends with the new syntax - improved error handling in *_connect() - fixed a crash bug in the new case_fold_required() code - ensured that ltdb_rename() and all ltdb_search() paths get the read lock - added a ldb_oom() macro to make it easier to report out of memory situations in ldb code (This used to be commit f648fdf187669d6d87d01dd4e786b03cd420f220) --- source4/lib/ldb/Makefile.in | 34 +++---- source4/lib/ldb/common/ldb.c | 48 ++++++---- source4/lib/ldb/common/ldb_utf8.c | 2 +- source4/lib/ldb/common/util.c | 57 ----------- source4/lib/ldb/config.mk | 23 +++-- source4/lib/ldb/configure.in | 3 + source4/lib/ldb/include/ldb.h | 7 +- source4/lib/ldb/include/ldb_private.h | 33 ++++--- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 28 ++---- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 82 +++------------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 23 ++--- source4/lib/ldb/ldb_tdb/ldb_search.c | 38 ++++++-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 43 ++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 - source4/lib/ldb/tests/test-extended.sh | 4 +- source4/lib/ldb/tests/test-generic.sh | 4 +- source4/lib/ldb/tools/ldbadd.c | 78 +++++---------- source4/lib/ldb/tools/ldbdel.c | 64 ++++--------- source4/lib/ldb/tools/ldbedit.c | 103 ++++---------------- source4/lib/ldb/tools/ldbmodify.c | 59 ++++-------- source4/lib/ldb/tools/ldbrename.c | 58 ++++-------- source4/lib/ldb/tools/ldbsearch.c | 87 ++++------------- source4/lib/ldb/tools/ldbtest.c | 152 ++++++++++-------------------- 23 files changed, 343 insertions(+), 689 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 88935b6f3a..a633320d06 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -39,7 +39,7 @@ endif CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) @CFLAGS@ -LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) +LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) @LIBS@ TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o TALLOC_OBJ=$(TALLOCDIR)/talloc.o @@ -49,7 +49,7 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_cache.o -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ +COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ common/ldb_debug.o common/ldb_modules.o \ common/ldb_explode_dn.o @@ -80,26 +80,26 @@ bin: lib/libldb.a: $(OBJS) -bin/ldbadd: tools/ldbadd.o $(LIBS) - $(CC) -o bin/ldbadd tools/ldbadd.o $(LIB_FLAGS) +bin/ldbadd: tools/ldbadd.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbadd tools/ldbadd.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbsearch: tools/ldbsearch.o $(LIBS) - $(CC) -o bin/ldbsearch tools/ldbsearch.o $(LIB_FLAGS) +bin/ldbsearch: tools/ldbsearch.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbsearch tools/ldbsearch.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbdel: tools/ldbdel.o $(LIBS) - $(CC) -o bin/ldbdel tools/ldbdel.o $(LIB_FLAGS) +bin/ldbdel: tools/ldbdel.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbdel tools/ldbdel.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbmodify: tools/ldbmodify.o $(LIBS) - $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) +bin/ldbmodify: tools/ldbmodify.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbmodify tools/ldbmodify.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbedit: tools/ldbedit.o $(LIBS) - $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) +bin/ldbedit: tools/ldbedit.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbedit tools/ldbedit.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbrename: tools/ldbrename.o $(LIBS) - $(CC) -o bin/ldbrename tools/ldbrename.o $(LIB_FLAGS) +bin/ldbrename: tools/ldbrename.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbrename tools/ldbrename.o tools/cmdline.o $(LIB_FLAGS) -bin/ldbtest: tools/ldbtest.o $(LIBS) - $(CC) -o bin/ldbtest tools/ldbtest.o $(LIB_FLAGS) +bin/ldbtest: tools/ldbtest.o tools/cmdline.o $(LIBS) + $(CC) -o bin/ldbtest tools/ldbtest.o tools/cmdline.o $(LIB_FLAGS) .SUFFIXES: .1 .2 .3 .yo @@ -126,7 +126,7 @@ distclean: clean etags: etags */*.[ch] -test-tdb: +test-tdb: $(BINS) @echo "STARTING TDB BACKEND TEST" tests/test-tdb.sh diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 2d0d09de3e..d2dbac95ea 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -36,6 +36,16 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +/* + initialise a ldb context + The mem_ctx is optional +*/ +struct ldb_context *ldb_init(void *mem_ctx) +{ + struct ldb_context *ldb = talloc_zero(mem_ctx, struct ldb_context); + return ldb; +} + /* connect to a database. The URL can either be one of the following forms ldb://path @@ -46,45 +56,45 @@ the options are passed uninterpreted to the backend, and are backend specific */ -struct ldb_context *ldb_connect(const char *url, unsigned int flags, - const char *options[]) +int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]) { - struct ldb_context *ldb_ctx = NULL; + int ret; if (strncmp(url, "tdb:", 4) == 0 || strchr(url, ':') == NULL) { - ldb_ctx = ltdb_connect(url, flags, options); + ret = ltdb_connect(ldb, url, flags, options); } #if HAVE_ILDAP - if (strncmp(url, "ldap", 4) == 0) { - ldb_ctx = ildb_connect(url, flags, options); + else if (strncmp(url, "ldap", 4) == 0) { + ret = ildb_connect(ldb, url, flags, options); } #elif HAVE_LDAP - if (strncmp(url, "ldap", 4) == 0) { - ldb_ctx = lldb_connect(url, flags, options); + else if (strncmp(url, "ldap", 4) == 0) { + ret = lldb_connect(ldb, url, flags, options); } #endif - #if HAVE_SQLITE3 - if (strncmp(url, "sqlite:", 7) == 0) { + else if (strncmp(url, "sqlite:", 7) == 0) { ldb_ctx = lsqlite3_connect(url, flags, options); } #endif + else { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'", url); + return -1; + } - - if (!ldb_ctx) { - errno = EINVAL; - return NULL; + if (ret != 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'", url); + return ret; } - if (ldb_load_modules(ldb_ctx, options) != 0) { - talloc_free(ldb_ctx); - errno = EINVAL; - return NULL; + if (ldb_load_modules(ldb, options) != 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'", url); + return -1; } - return ldb_ctx; + return 0; } /* diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 35249c4b70..ae35ad81b6 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -135,7 +135,7 @@ char *ldb_dn_fold(void * mem_ctx, } if (*value == 0) goto failed; - case_fold_required = (* case_fold_attr_fn)(user_data, attr); + case_fold_required = case_fold_attr_fn(user_data, attr); attr = ldb_casefold(tmp_ctx, attr); if (attr == NULL) goto failed; diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index c2fd72acd1..e69de29bb2 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -1,57 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb utility functions - * - * Description: miscellanous utility functions for ldb - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" - - -/* - common code for parsing -o options in ldb tools -*/ -const char **ldb_options_parse(const char **options, int *ldbopts, const char *arg) -{ - if (*ldbopts == 0) { - options = malloc(sizeof(char *) * 2); - } else { - options = realloc(options, sizeof(char *)*((*ldbopts)+2)); - } - if (options == NULL) { - fprintf(stderr, "Out of memory in options parsing!\n"); - exit(-1); - } - options[(*ldbopts)++] = arg; - options[*ldbopts] = NULL; - return options; -} diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 05255fdec5..4d4dc121e1 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -91,13 +91,22 @@ REQUIRED_SUBSYSTEMS = \ # End LIBRARY LIBLDB ################################################ +################################################ +# Start SUBSYSTEM LIBLDB_CMDLINE +[SUBSYSTEM::LIBLDB_CMDLINE] +OBJ_FILES= \ + lib/ldb/tools/cmdline.o +REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE +# End SUBSYSTEM LIBLDB_CMDLINE +################################################ + ################################################ # Start BINARY ldbadd [BINARY::ldbadd] OBJ_FILES= \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbadd ################################################ @@ -107,7 +116,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbdel ################################################ @@ -117,7 +126,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbmodify ################################################ @@ -127,7 +136,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbsearch ################################################ @@ -137,7 +146,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbedit ################################################ @@ -147,7 +156,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbrename.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbrename ################################################ @@ -157,6 +166,6 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/ldb/tools/ldbtest.o REQUIRED_SUBSYSTEMS = \ - LIBLDB + LIBLDB_CMDLINE # End BINARY ldbtest ################################################ diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index fcb87cdb3a..7ae339c103 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -23,6 +23,9 @@ AC_PATH_PROG(XSLTPROC,xsltproc) AC_PATH_PROG(GCOV,gcov) AC_CHECK_HEADERS(stdint.h) AC_CONFIG_HEADER(include/config.h) + +AC_CHECK_LIB(popt, poptGetContext) + sinclude(ldap.m4) WITH_LDAP=$with_ldap_support AC_SUBST(WITH_LDAP) diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index fabaec5da2..ecfa77f436 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -184,6 +184,10 @@ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s); char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree); char *ldb_binary_encode(void *ctx, struct ldb_val val); +/* + initialise a ldb context +*/ +struct ldb_context *ldb_init(void *mem_ctx); /* connect to a database. The URL can either be one of the following forms @@ -195,8 +199,7 @@ char *ldb_binary_encode(void *ctx, struct ldb_val val); the options are passed uninterpreted to the backend, and are backend specific */ -struct ldb_context *ldb_connect(const char *url, unsigned int flags, - const char *options[]); +int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]); /* search the database given a LDAP-like search expression diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 4acdd543f2..76a43cdbc2 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -86,6 +86,11 @@ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) #endif +/* + simplify out of memory handling +*/ +#define ldb_oom(ldb) ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb out of memory at %s:%d\n", __FILE__, __LINE__) + /* The following definitions come from lib/ldb/common/ldb_modules.c */ int ldb_load_modules(struct ldb_context *ldb, const char *options[]); @@ -114,21 +119,21 @@ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char * char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len); int ldb_should_b64_encode(const struct ldb_val *val); -struct ldb_context *ltdb_connect(const char *url, - unsigned int flags, - const char *options[]); -struct ldb_context *lldb_connect(const char *url, - unsigned int flags, - const char *options[]); -struct ldb_context *ildb_connect(const char *url, - unsigned int flags, - const char *options[]); -struct ldb_context *lsqlite3_connect(const char *url, - unsigned int flags, - const char *options[]); +int ltdb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, + const char *options[]); +int lldb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, + const char *options[]); +int ildb_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[]); +int lsqlite3_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[]); struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); -const char **ldb_options_parse(const char **options, int *ldbopts, const char *arg); - #endif diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index c35d9de6b1..aa0efee481 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -349,42 +349,34 @@ static const struct ldb_module_ops ildb_ops = { /* connect to the database */ -struct ldb_context *ildb_connect(const char *url, - unsigned int flags, - const char *options[]) +int ildb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[]) { - struct ldb_context *ldb = NULL; struct ildb_private *ildb = NULL; NTSTATUS status; - ldb = talloc(NULL, struct ldb_context); - if (!ldb) { - errno = ENOMEM; - goto failed; - } - - ldb->debug_ops.debug = NULL; - ildb = talloc(ldb, struct ildb_private); if (!ildb) { - errno = ENOMEM; + ldb_oom(ldb); goto failed; } ildb->ldap = ldap_new_connection(ildb, NULL); if (!ildb->ldap) { - errno = ENOMEM; + ldb_oom(ldb); goto failed; } status = ldap_connect(ildb->ldap, url); if (!NT_STATUS_IS_OK(status)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n", + url, ldap_errstr(ildb->ldap, status)); goto failed; } ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { - errno = ENOMEM; + ldb_oom(ldb); goto failed; } ldb->modules->ldb = ldb; @@ -392,10 +384,10 @@ struct ldb_context *ildb_connect(const char *url, ldb->modules->private_data = ildb; ldb->modules->ops = &ildb_ops; - return ldb; + return 0; failed: - talloc_free(ldb); - return NULL; + talloc_free(ildb); + return -1; } diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 16beed58f8..d7f589e2e5 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -37,36 +37,6 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_ldap/ldb_ldap.h" -#if 0 -/* - we don't need this right now, but will once we add some backend - options -*/ - -/* - find an option in an option list (a null terminated list of strings) - - this assumes the list is short. If it ever gets long then we really - should do this in some smarter way - */ -static const char *lldb_option_find(const struct lldb_private *lldb, const char *name) -{ - int i; - size_t len = strlen(name); - - if (!lldb->options) return NULL; - - for (i=0;lldb->options[i];i++) { - if (strncmp(lldb->options[i], name, len) == 0 && - lldb->options[i][len] == '=') { - return &lldb->options[i][len+1]; - } - } - - return NULL; -} -#endif - /* rename a record */ @@ -494,25 +464,17 @@ static int lldb_destructor(void *p) /* connect to the database */ -struct ldb_context *lldb_connect(const char *url, - unsigned int flags, - const char *options[]) +int lldb_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[]) { - struct ldb_context *ldb = NULL; struct lldb_private *lldb = NULL; - int i, version = 3; - - ldb = talloc(NULL, struct ldb_context); - if (!ldb) { - errno = ENOMEM; - goto failed; - } - - ldb->debug_ops.debug = NULL; + int version = 3; lldb = talloc(ldb, struct lldb_private); if (!lldb) { - errno = ENOMEM; + ldb_oom(ldb); goto failed; } @@ -521,6 +483,8 @@ struct ldb_context *lldb_connect(const char *url, lldb->last_rc = ldap_initialize(&lldb->ldap, url); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n", + url, ldap_err2string(lldb->last_rc)); goto failed; } @@ -528,12 +492,13 @@ struct ldb_context *lldb_connect(const char *url, lldb->last_rc = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); if (lldb->last_rc != LDAP_SUCCESS) { - goto failed; + ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n", + ldap_err2string(lldb->last_rc)); } ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { - errno = ENOMEM; + ldb_oom(ldb); goto failed; } ldb->modules->ldb = ldb; @@ -541,29 +506,10 @@ struct ldb_context *lldb_connect(const char *url, ldb->modules->private_data = lldb; ldb->modules->ops = &lldb_ops; - if (options) { - /* take a copy of the options array, so we don't have to rely - on the caller keeping it around (it might be dynamic) */ - for (i=0;options[i];i++) ; - - lldb->options = talloc_array(lldb, char *, i+1); - if (!lldb->options) { - goto failed; - } - - for (i=0;options[i];i++) { - lldb->options[i+1] = NULL; - lldb->options[i] = talloc_strdup(lldb->options, options[i]); - if (!lldb->options[i]) { - goto failed; - } - } - } - - return ldb; + return 0; failed: - talloc_free(ldb); - return NULL; + talloc_free(lldb); + return -1; } diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 51830db94c..3d36043044 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -216,21 +216,16 @@ static const struct ldb_module_ops lsqlite3_ops = { /* * connect to the database */ -struct ldb_context * -lsqlite3_connect(const char *url, - unsigned int flags, - const char *options[]) +int lsqlite3_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[]) { int i; int ret; struct ldb_context * ldb = NULL; struct lsqlite3_private * lsqlite3 = NULL; - ldb = talloc(NULL, struct ldb_context); - if (!ldb) { - goto failed; - } - lsqlite3 = talloc(ldb, struct lsqlite3_private); if (!lsqlite3) { goto failed; @@ -279,14 +274,14 @@ lsqlite3_connect(const char *url, } } - return ldb; + return 0; failed: if (lsqlite3->sqlite != NULL) { (void) sqlite3_close(lsqlite3->sqlite); } - talloc_free(ldb); - return NULL; + talloc_free(lsqlite3); + return -1; } @@ -1204,7 +1199,9 @@ destructor(void *p) { struct lsqlite3_private * lsqlite3 = p; - (void) sqlite3_close(lsqlite3->sqlite); + if (lsqlite3->sqlite) { + sqlite3_close(lsqlite3->sqlite); + } return 0; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 3644d046e0..d6e7d66f68 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -272,44 +272,63 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag /* search the database for a single simple dn */ -int ltdb_search_dn(struct ldb_module *module, const char *dn, - const char * const attrs[], struct ldb_message ***res) +static int ltdb_search_dn(struct ldb_module *module, const char *dn, + const char * const attrs[], struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; + struct ltdb_private *ltdb = module->private_data; int ret; struct ldb_message *msg, *msg2; + *res = NULL; + + if (ltdb_lock_read(module) != 0) { + return -1; + } + + ltdb->last_err_string = NULL; + + if (ltdb_cache_load(module) != 0) { + ltdb_unlock_read(module); + return -1; + } + *res = talloc_array(ldb, struct ldb_message *, 2); if (! *res) { - return -1; + goto failed; } msg = talloc(*res, struct ldb_message); if (msg == NULL) { - talloc_free(*res); - *res = NULL; - return -1; + goto failed; } ret = ltdb_search_dn1(module, dn, msg); if (ret != 1) { talloc_free(*res); *res = NULL; - return ret; + ltdb_unlock_read(module); + return 0; } msg2 = ltdb_pull_attrs(module, msg, attrs); talloc_free(msg); - if (!msg2) { - return -1; + goto failed; } (*res)[0] = talloc_steal(*res, msg2); (*res)[1] = NULL; + ltdb_unlock_read(module); + return 1; + +failed: + talloc_free(*res); + ltdb_unlock_read(module); + return -1; } @@ -508,7 +527,6 @@ int ltdb_search(struct ldb_module *module, const char *base, /* check if we are looking for a simple dn */ if (scope == LDB_SCOPE_BASE && (expression == NULL || expression[0] == '\0')) { ret = ltdb_search_dn(module, base, attrs, res); - ltdb_unlock_read(module); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 6516787a5a..596ede8a4e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -49,9 +49,9 @@ */ static int ltdb_case_fold_attr_required(void * user_data, char *attr) { - struct ldb_module *module = user_data; + struct ldb_module *module = talloc_get_type(user_data, struct ldb_module); - return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE; + return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE; } /* @@ -746,6 +746,11 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char return -1; } + if (ltdb_cache_load(module) != 0) { + ltdb_unlock(module, LDBLOCK); + return -1; + } + msg = talloc(module, struct ldb_message); if (msg == NULL) { goto failed; @@ -829,28 +834,19 @@ static int ltdb_destructor(void *p) /* connect to the database */ -struct ldb_context *ltdb_connect(const char *url, - unsigned int flags, - const char *options[]) +int ltdb_connect(struct ldb_context *ldb, const char *url, + unsigned int flags, const char *options[]) { const char *path; int tdb_flags, open_flags; struct ltdb_private *ltdb; TDB_CONTEXT *tdb; - struct ldb_context *ldb; - - ldb = talloc_zero(NULL, struct ldb_context); - if (!ldb) { - errno = ENOMEM; - return NULL; - } /* parse the url */ if (strchr(url, ':')) { if (strncmp(url, "tdb://", 6) != 0) { - errno = EINVAL; - talloc_free(ldb); - return NULL; + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url); + return -1; } path = url+6; } else { @@ -868,16 +864,15 @@ struct ldb_context *ltdb_connect(const char *url, /* note that we use quite a large default hash size */ tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); if (!tdb) { - talloc_free(ldb); - return NULL; + ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'", path); + return -1; } ltdb = talloc_zero(ldb, struct ltdb_private); if (!ltdb) { tdb_close(tdb); - talloc_free(ldb); - errno = ENOMEM; - return NULL; + ldb_oom(ldb); + return -1; } ltdb->tdb = tdb; @@ -887,14 +882,14 @@ struct ldb_context *ltdb_connect(const char *url, ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { - talloc_free(ldb); - errno = ENOMEM; - return NULL; + ldb_oom(ldb); + talloc_free(ltdb); + return -1; } ldb->modules->ldb = ldb; ldb->modules->prev = ldb->modules->next = NULL; ldb->modules->private_data = ltdb; ldb->modules->ops = <db_ops; - return ldb; + return 0; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index b77e02fba5..6377092a21 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -91,8 +91,6 @@ int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val); void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg); int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg); -int ltdb_search_dn(struct ldb_module *module, const char *dn, - const char * const attrs[], struct ldb_message ***res); int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], int *count, diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index ede66ec567..93ac2db6bd 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -1,8 +1,10 @@ #!/bin/sh +echo "Running extended search tests" + rm -f $LDB_URL -cat <url, 0, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - if (argc == 0) { - usage(); - } - - for (i=0;iargc == 0) { + count += process_file(ldb, stdin); + } else { + for (i=0;iargc;i++) { + const char *fname = options->argv[i]; + FILE *f; + f = fopen(fname, "r"); + if (!f) { + perror(fname); + exit(1); + } + count += process_file(ldb, f); fclose(f); } } diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index ec2e302b20..fcf1d26d53 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" @@ -77,72 +78,41 @@ static void usage(void) exit(1); } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { struct ldb_context *ldb; - const char **options = NULL; - int ldbopts; int ret, i; - const char *ldb_url; - int opt, recursive=0; - - ldb_url = getenv("LDB_URL"); - - ldbopts = 0; - while ((opt = getopt(argc, argv, "hH:ro:")) != EOF) { - switch (opt) { - case 'H': - ldb_url = optarg; - break; - - case 'r': - recursive=1; - break; - - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; - - case 'h': - default: - usage(); - break; - } - } + struct ldb_cmdline *options; - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); - } + ldb = ldb_init(NULL); - argc -= optind; - argv += optind; + options = ldb_cmdline_process(ldb, argc, argv, usage); - if (argc < 1) { + if (options->argc < 1) { usage(); exit(1); } - ldb = ldb_connect(ldb_url, 0, options); - if (!ldb) { - perror("ldb_connect"); + ret = ldb_connect(ldb, options->url, 0, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - for (i=0;iargc;i++) { + const char *dn = options->argv[i]; + if (options->recursive) { + ret = ldb_delete_recursive(ldb, dn); } else { - ret = ldb_delete(ldb, argv[i]); + ret = ldb_delete(ldb, dn); if (ret == 0) { printf("Deleted 1 record\n"); } } if (ret != 0) { - printf("delete of '%s' failed - %s\n", - argv[i], ldb_errstring(ldb)); + printf("delete of '%s' failed - %s\n", dn, ldb_errstring(ldb)); } } diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 851eaeebdf..6c599ee2ec 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" @@ -272,109 +273,45 @@ static void usage(void) exit(1); } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { struct ldb_context *ldb; struct ldb_message **msgs; int ret; const char *expression = NULL; - const char *ldb_url; - const char *basedn = NULL; - const char **options = NULL; - int ldbopts; - int opt; - enum ldb_scope scope = LDB_SCOPE_SUBTREE; - const char *editor; const char * const * attrs = NULL; + struct ldb_cmdline *options; - ldb_url = getenv("LDB_URL"); + ldb = ldb_init(NULL); - /* build the editor command to run - - use the same editor priorities as vipw */ - editor = getenv("VISUAL"); - if (!editor) { - editor = getenv("EDITOR"); - } - if (!editor) { - editor = "vi"; - } - - ldbopts = 0; - while ((opt = getopt(argc, argv, "hab:e:H:s:vo:")) != EOF) { - switch (opt) { - case 'b': - basedn = optarg; - break; - - case 'H': - ldb_url = optarg; - break; - - case 's': - if (strcmp(optarg, "base") == 0) { - scope = LDB_SCOPE_BASE; - } else if (strcmp(optarg, "sub") == 0) { - scope = LDB_SCOPE_SUBTREE; - } else if (strcmp(optarg, "one") == 0) { - scope = LDB_SCOPE_ONELEVEL; - } - break; - - case 'e': - editor = optarg; - break; - - case 'a': - expression = "(|(objectclass=*)(dn=*))"; - break; - - case 'v': - verbose++; - break; - - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; - - case 'h': - default: - usage(); - break; - } - } + options = ldb_cmdline_process(ldb, argc, argv, usage); - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); + if (options->all_records) { + expression = "(|(objectclass=*)(dn=*))"; } - argc -= optind; - argv += optind; - if (!expression) { - if (argc == 0) { + if (options->argc == 0) { usage(); } - expression = argv[0]; - argc--; - argv++; + expression = options->argv[0]; + options->argc--; + options->argv++; } - if (argc > 0) { - attrs = (const char * const *)argv; + if (options->argc > 0) { + attrs = (const char * const *)options->argv; } - ldb = ldb_connect(ldb_url, 0, options); - - if (!ldb) { - perror("ldb_connect"); + ret = ldb_connect(ldb, options->url, LDB_FLG_RDONLY, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs); - + ret = ldb_search(ldb, options->basedn, options->scope, expression, attrs, &msgs); if (ret == -1) { printf("search failed - %s\n", ldb_errstring(ldb)); exit(1); @@ -385,7 +322,7 @@ static void usage(void) return 0; } - do_edit(ldb, msgs, ret, editor); + do_edit(ldb, msgs, ret, options->editor); if (ret > 0) { ret = talloc_free(msgs); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 78baa0e36c..c54c573ab0 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" @@ -88,66 +89,40 @@ static int process_file(struct ldb_context *ldb, FILE *f) return count; } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { struct ldb_context *ldb; int count=0; - const char *ldb_url; - const char **options = NULL; - int ldbopts; - int opt, i; - - ldb_url = getenv("LDB_URL"); - - ldbopts = 0; - while ((opt = getopt(argc, argv, "hH:o:")) != EOF) { - switch (opt) { - case 'H': - ldb_url = optarg; - break; + int i, ret; + struct ldb_cmdline *options; - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; + ldb = ldb_init(NULL); - case 'h': - default: - usage(); - break; - } - } + options = ldb_cmdline_process(ldb, argc, argv, usage); - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); - } - - argc -= optind; - argv += optind; - - ldb = ldb_connect(ldb_url, 0, options); - - if (!ldb) { - perror("ldb_connect"); + ret = ldb_connect(ldb, options->url, 0, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - if (argc == 0) { + if (options->argc == 0) { usage(); exit(1); } - for (i=0;iargc;i++) { + const char *fname = options->argv[i]; FILE *f; - if (strcmp(argv[i],"-") == 0) { + if (strcmp(fname,"-") == 0) { f = stdin; } else { - f = fopen(argv[i], "r"); + f = fopen(fname, "r"); } if (!f) { - perror(argv[i]); + perror(fname); exit(1); } count += process_file(ldb, f); diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 273c792584..5566c3d7d7 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -37,6 +37,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" @@ -55,61 +56,38 @@ static void usage(void) } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { struct ldb_context *ldb; - const char *ldb_url; - const char **options = NULL; - int ldbopts; - int opt, ret; - - ldb_url = getenv("LDB_URL"); - - ldbopts = 0; - while ((opt = getopt(argc, argv, "hH:o:")) != EOF) { - switch (opt) { - case 'H': - ldb_url = optarg; - break; - - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; - - case 'h': - default: - usage(); - break; - } - } - - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); - } + int ret; + struct ldb_cmdline *options; + const char *dn1, *dn2; - argc -= optind; - argv += optind; + ldb = ldb_init(NULL); - ldb = ldb_connect(ldb_url, 0, options); + options = ldb_cmdline_process(ldb, argc, argv, usage); - if (!ldb) { - perror("ldb_connect"); + ret = ldb_connect(ldb, options->url, 0, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - if (argc < 2) { + if (options->argc < 2) { usage(); } - ret = ldb_rename(ldb, argv[0], argv[1]); + dn1 = options->argv[0]; + dn2 = options->argv[1]; + + ret = ldb_rename(ldb, dn1, dn2); if (ret == 0) { printf("Renamed 1 record\n"); } else { printf("rename of '%s' to '%s' failed - %s\n", - argv[0], argv[1], ldb_errstring(ldb)); + dn1, dn2, ldb_errstring(ldb)); } talloc_free(ldb); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 4bf9db8d90..04f83ca366 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -35,6 +35,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" @@ -113,93 +114,45 @@ static int do_search(struct ldb_context *ldb, return 0; } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { struct ldb_context *ldb; const char * const * attrs = NULL; - const char *ldb_url; - const char *basedn = NULL; - const char **options = NULL; - int opt, ldbopts; - enum ldb_scope scope = LDB_SCOPE_SUBTREE; - int interactive = 0, sort_attribs=0, ret=0; - - ldb_url = getenv("LDB_URL"); - - ldbopts = 0; - while ((opt = getopt(argc, argv, "b:H:s:o:hiS")) != EOF) { - switch (opt) { - case 'b': - basedn = optarg; - break; - - case 'H': - ldb_url = optarg; - break; - - case 's': - if (strcmp(optarg, "base") == 0) { - scope = LDB_SCOPE_BASE; - } else if (strcmp(optarg, "sub") == 0) { - scope = LDB_SCOPE_SUBTREE; - } else if (strcmp(optarg, "one") == 0) { - scope = LDB_SCOPE_ONELEVEL; - } - break; - - case 'i': - interactive = 1; - break; - - case 'S': - sort_attribs = 1; - break; + struct ldb_cmdline *options; + int ret; - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; - - case 'h': - default: - usage(); - break; - } - } + ldb = ldb_init(NULL); - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); - } - - argc -= optind; - argv += optind; - - if (argc < 1 && !interactive) { + options = ldb_cmdline_process(ldb, argc, argv, usage); + + if (options->argc < 1 && !options->interactive) { usage(); exit(1); } - if (argc > 1) { - attrs = (const char * const *)(argv+1); + if (options->argc > 1) { + attrs = (const char * const *)(options->argv+1); } - ldb = ldb_connect(ldb_url, LDB_FLG_RDONLY, options); - if (!ldb) { - perror("ldb_connect"); + ret = ldb_connect(ldb, options->url, LDB_FLG_RDONLY, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); exit(1); } - ldb_set_debug_stderr(ldb); - - if (interactive) { + if (options->interactive) { char line[1024]; while (fgets(line, sizeof(line), stdin)) { - if (do_search(ldb, basedn, scope, sort_attribs, line, attrs) == -1) { + if (do_search(ldb, options->basedn, + options->scope, options->sorted, line, attrs) == -1) { ret = -1; } } } else { - ret = do_search(ldb, basedn, scope, sort_attribs, argv[0], attrs); + ret = do_search(ldb, options->basedn, options->scope, options->sorted, + options->argv[0], attrs); } talloc_free(ldb); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index fc1f3e3098..a7c9a3123a 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -35,16 +35,15 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" #ifdef _SAMBA_BUILD_ #include "system/filesys.h" #include "system/time.h" #endif -static const char *ldb_url; -static const char *base_dn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; - static struct timeval tp1,tp2; +static struct ldb_cmdline *options; static void _start_timer(void) { @@ -69,51 +68,51 @@ static void add_records(struct ldb_context *ldb, struct ldb_message_element el[6]; struct ldb_val vals[6][1]; char *name; - int j; + TALLOC_CTX *tmp_ctx = talloc_new(ldb); asprintf(&name, "Test%d", i); - asprintf(&msg.dn, "cn=%s,%s", name, basedn); + msg.dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, basedn); msg.num_elements = 6; msg.elements = el; el[0].flags = 0; - el[0].name = strdup("cn"); + el[0].name = talloc_strdup(tmp_ctx, "cn"); el[0].num_values = 1; el[0].values = vals[0]; vals[0][0].data = name; vals[0][0].length = strlen(name); el[1].flags = 0; - el[1].name = strdup("title"); + el[1].name = talloc_strdup(tmp_ctx, "title"); el[1].num_values = 1; el[1].values = vals[1]; - asprintf((char **)&vals[1][0].data, "The title of %s", name); + vals[1][0].data = talloc_asprintf(tmp_ctx, "The title of %s", name); vals[1][0].length = strlen(vals[1][0].data); el[2].flags = 0; - el[2].name = strdup("uid"); + el[2].name = talloc_strdup(tmp_ctx, "uid"); el[2].num_values = 1; el[2].values = vals[2]; - vals[2][0].data = ldb_casefold(ldb, name); + vals[2][0].data = ldb_casefold(tmp_ctx, name); vals[2][0].length = strlen(vals[2][0].data); el[3].flags = 0; - el[3].name = strdup("mail"); + el[3].name = talloc_strdup(tmp_ctx, "mail"); el[3].num_values = 1; el[3].values = vals[3]; - asprintf((char **)&vals[3][0].data, "%s@example.com", name); + vals[3][0].data = talloc_asprintf(tmp_ctx, "%s@example.com", name); vals[3][0].length = strlen(vals[3][0].data); el[4].flags = 0; - el[4].name = strdup("objectClass"); + el[4].name = talloc_strdup(tmp_ctx, "objectClass"); el[4].num_values = 1; el[4].values = vals[4]; - vals[4][0].data = strdup("OpenLDAPperson"); + vals[4][0].data = talloc_strdup(tmp_ctx, "OpenLDAPperson"); vals[4][0].length = strlen(vals[4][0].data); el[5].flags = 0; - el[5].name = strdup("sn"); + el[5].name = talloc_strdup(tmp_ctx, "sn"); el[5].num_values = 1; el[5].values = vals[5]; vals[5][0].data = name; @@ -129,15 +128,7 @@ static void add_records(struct ldb_context *ldb, printf("adding uid %s\r", name); fflush(stdout); - for (j=0;jbasedn, LDB_SCOPE_SUBTREE, expr, NULL, &res); if (uid < nrecords && ret != 1) { printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb)); @@ -263,7 +248,7 @@ static void search_uid(struct ldb_context *ldb, int nrecords, int nsearches) static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) { printf("Adding %d records\n", nrecords); - add_records(ldb, base_dn, nrecords); + add_records(ldb, options->basedn, nrecords); printf("Starting search on uid\n"); _start_timer(); @@ -271,10 +256,10 @@ static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) printf("uid search took %.2f seconds\n", _end_timer()); printf("Modifying records\n"); - modify_records(ldb, base_dn, nrecords); + modify_records(ldb, options->basedn, nrecords); printf("Deleting records\n"); - delete_records(ldb, base_dn, nrecords); + delete_records(ldb, options->basedn, nrecords); } @@ -312,7 +297,7 @@ static void start_test_index(struct ldb_context **ldb) } memset(msg, 0, sizeof(*msg)); - asprintf(&msg->dn, "cn=%s,%s", "test", base_dn); + asprintf(&msg->dn, "cn=%s,%s", "test", options->basedn); ldb_msg_add_string(*ldb, msg, "cn", strdup("test")); ldb_msg_add_string(*ldb, msg, "sn", strdup("test")); ldb_msg_add_string(*ldb, msg, "uid", strdup("test")); @@ -328,14 +313,15 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - *ldb = ldb_connect(ldb_url, 0, NULL); - - if (!*ldb) { - perror("ldb_connect"); + (*ldb) = ldb_init(options); + + ret = ldb_connect(*ldb, options->url, 0, NULL); + if (ret != 0) { + printf("failed to connect to %s\n", options->url); exit(1); } - ret = ldb_search(*ldb, base_dn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); + ret = ldb_search(*ldb, options->basedn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); if (ret != 1) { printf("Should have found 1 record - found %d\n", ret); exit(1); @@ -363,71 +349,37 @@ static void usage(void) exit(1); } - int main(int argc, char * const argv[]) + int main(int argc, const char **argv) { + TALLOC_CTX *mem_ctx = talloc_new(NULL); struct ldb_context *ldb; - const char **options = NULL; - int ldbopts; - int opt; - int nrecords = 5000; - int nsearches = 2000; - - ldb_url = getenv("LDB_URL"); - - ldbopts = 0; - while ((opt = getopt(argc, argv, "hH:r:s:b:o:")) != EOF) { - switch (opt) { - case 'H': - ldb_url = optarg; - break; - - case 'r': - nrecords = atoi(optarg); - break; - - case 'b': - base_dn = optarg; - break; - - case 's': - nsearches = atoi(optarg); - break; - - case 'o': - options = ldb_options_parse(options, &ldbopts, optarg); - break; - - case 'h': - default: - usage(); - break; - } - } + int ret; - if (!ldb_url) { - fprintf(stderr, "You must specify a ldb URL\n\n"); - usage(); - } + ldb = ldb_init(mem_ctx); - argc -= optind; - argv += optind; + options = ldb_cmdline_process(ldb, argc, argv, usage); - ldb = ldb_connect(ldb_url, 0, options); + talloc_steal(mem_ctx, options); - if (!ldb) { - perror("ldb_connect"); - exit(1); + if (options->basedn == NULL) { + options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; } - ldb_set_debug_stderr(ldb); + ret = ldb_connect(ldb, options->url, 0, options->options); + if (ret != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + options->url, ldb_errstring(ldb)); + talloc_free(ldb); + exit(1); + } srandom(1); - start_test(ldb, nrecords, nsearches); + start_test(ldb, options->num_records, options->num_searches); start_test_index(&ldb); - talloc_free(ldb); + talloc_free(mem_ctx); return 0; } -- cgit From f52b42c75fda1069664fdbedf392e4fca87d7fc0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 07:43:52 +0000 Subject: r7710: new command line handling code for ldb (This used to be commit 5e8db1c9b3bb6c5196652a7af877b4204148c305) --- source4/lib/ldb/common/util.c | 0 source4/lib/ldb/tools/cmdline.c | 142 ++++++++++++++++++++++++++++++++++++++++ source4/lib/ldb/tools/cmdline.h | 47 +++++++++++++ 3 files changed, 189 insertions(+) delete mode 100644 source4/lib/ldb/common/util.c create mode 100644 source4/lib/ldb/tools/cmdline.c create mode 100644 source4/lib/ldb/tools/cmdline.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c new file mode 100644 index 0000000000..a7bfac8bb4 --- /dev/null +++ b/source4/lib/ldb/tools/cmdline.c @@ -0,0 +1,142 @@ +/* + ldb database library - command line handling for ldb tools + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" + +/* + process command line options +*/ +struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, + void (*usage)(void)) +{ + struct ldb_cmdline options, *ret; + poptContext pc; + int num_options = 0; + char opt; + struct poptOption popt_options[] = { + POPT_AUTOHELP + { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, + { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" }, + { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" }, + { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" }, + { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL }, + { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL }, + { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL }, + { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, + { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, + { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "dn=*", NULL }, + { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, + { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, + POPT_TABLEEND + }; + + ret = talloc_zero(ldb, struct ldb_cmdline); + if (ret == NULL) { + ldb_oom(ldb); + goto failed; + } + + options = *ret; + + /* pull in URL */ + options.url = getenv("LDB_URL"); + + /* and editor (used by ldbedit) */ + options.editor = getenv("VISUAL"); + if (!options.editor) { + options.editor = getenv("EDITOR"); + } + if (!options.editor) { + options.editor = "vi"; + } + + pc = poptGetContext(argv[0], argc, argv, popt_options, + POPT_CONTEXT_KEEP_FIRST); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 's': { + const char *arg = poptGetOptArg(pc); + if (strcmp(arg, "base") == 0) { + options.scope = LDB_SCOPE_BASE; + } else if (strcmp(arg, "sub") == 0) { + options.scope = LDB_SCOPE_SUBTREE; + } else if (strcmp(arg, "one") == 0) { + options.scope = LDB_SCOPE_ONELEVEL; + } else { + fprintf(stderr, "Invalid scope '%s'\n", arg); + goto failed; + } + break; + } + + case 'v': + options.verbose++; + break; + + case 'o': + options.options = talloc_realloc(ret, options.options, + const char *, num_options+2); + if (options.options == NULL) { + ldb_oom(ldb); + goto failed; + } + options.options[num_options++] = poptGetOptArg(pc); + options.options[num_options+1] = NULL; + break; + + default: + fprintf(stderr, "Invalid option %s: %s\n", + poptBadOption(pc, 0), poptStrerror(opt)); + if (usage) usage(); + goto failed; + } + } + + /* setup the remaining options for the main program to use */ + options.argv = poptGetArgs(pc); + if (options.argv) { + options.argv++; + while (options.argv[options.argc]) options.argc++; + } + + *ret = options; + + /* all utils need some option */ + if (ret->url == NULL) { + fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); + if (usage) usage(); + goto failed; + } + + return ret; + +failed: + talloc_free(ret); + exit(1); + return NULL; +} diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h new file mode 100644 index 0000000000..f3eae26cce --- /dev/null +++ b/source4/lib/ldb/tools/cmdline.h @@ -0,0 +1,47 @@ +/* + ldb database library - command line handling for ldb tools + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +struct ldb_cmdline { + const char *url; + enum ldb_scope scope; + const char *basedn; + int interactive; + int sorted; + const char *editor; + int verbose; + int recursive; + int all_records; + const char **options; + int argc; + const char **argv; + int num_records; + int num_searches; +}; + +struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, + void (*usage)(void)); + + -- cgit From 74037cbe92fccb7a7a4a3497e3942e08b0945ea9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 07:44:36 +0000 Subject: r7711: update callers of ldb_connect() for new syntax (This used to be commit f852661463624714ad8e7adc0547b2f07b8f9f6d) --- source4/lib/db_wrap.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index a3a9ee9b86..33c2af2851 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -75,12 +75,13 @@ static int ldb_wrap_destructor(void *ctx) to close just talloc_free() the returned ldb_context */ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, - const char *url, - unsigned int flags, - const char *options[]) + const char *url, + unsigned int flags, + const char *options[]) { struct ldb_context *ldb; struct ldb_wrap *w; + int ret; for (w = ldb_list; w; w = w->next) { if (strcmp(url, w->url) == 0) { @@ -88,10 +89,16 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, } } - ldb = ldb_connect(url, flags, options); + ldb = ldb_init(talloc_autofree_context()); if (ldb == NULL) { return NULL; } + + ret = ldb_connect(ldb, url, flags, options); + if (ret == -1) { + talloc_free(ldb); + return NULL; + } w = talloc(ldb, struct ldb_wrap); if (w == NULL) { -- cgit From f8b60c8b1a81fab3c12eff7905e7852e07f5118f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 07:48:59 +0000 Subject: r7712: ldb/common/util.c is gone (This used to be commit aec0544962483b3cd8507b2de6d1552691e72932) --- source4/lib/ldb/config.mk | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 4d4dc121e1..82083e3137 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -67,7 +67,6 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_ldif.o \ lib/ldb/common/ldb_parse.o \ lib/ldb/common/ldb_msg.o \ - lib/ldb/common/util.o \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_debug.o \ lib/ldb/common/ldb_modules.o \ -- cgit From f40e69da2633771a42ec2b74fca63bd0b0a37e4a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 09:01:09 +0000 Subject: r7714: enable samba credentials handling in ldb tools. So you can now do a encrypted ldbedit against w2k3 (This used to be commit 6277c3923e7d9c26753424b1e77ac62f8e0729a4) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 14 ++++++++++++++ source4/lib/ldb/tools/cmdline.c | 21 +++++++++++++++++++++ source4/lib/ldb/tools/cmdline.h | 1 + source4/lib/ldb/tools/ldbadd.c | 10 +--------- source4/lib/ldb/tools/ldbdel.c | 8 -------- source4/lib/ldb/tools/ldbedit.c | 8 -------- source4/lib/ldb/tools/ldbmodify.c | 8 -------- source4/lib/ldb/tools/ldbrename.c | 8 -------- source4/lib/ldb/tools/ldbsearch.c | 10 +--------- source4/lib/ldb/tools/ldbtest.c | 8 -------- 10 files changed, 38 insertions(+), 58 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index aa0efee481..9cccec0313 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -34,6 +34,7 @@ #include "ldb/include/ldb_private.h" #include "libcli/ldap/ldap.h" #include "libcli/ldap/ldap_client.h" +#include "lib/cmdline/popt_common.h" struct ildb_private { const char *basedn; @@ -110,6 +111,10 @@ static int ildb_search(struct ldb_module *module, const char *base, int count, i; struct ldap_message **ldapres, *msg; + if (scope == LDB_SCOPE_DEFAULT) { + scope = LDB_SCOPE_SUBTREE; + } + if (base == NULL) { base = ""; } @@ -384,6 +389,15 @@ int ildb_connect(struct ldb_context *ldb, const char *url, ldb->modules->private_data = ildb; ldb->modules->ops = &ildb_ops; + if (cmdline_credentials->username_obtained > CRED_GUESSED) { + status = ldap_bind_sasl(ildb->ldap, cmdline_credentials); + if (!NT_STATUS_IS_OK(status)) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n", + ldap_errstr(ildb->ldap, status)); + goto failed; + } + } + return 0; failed: diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index a7bfac8bb4..1f4a7544a5 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -26,6 +26,9 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "ldb/tools/cmdline.h" +#ifdef _SAMBA_BUILD_ +#include "lib/cmdline/popt_common.h" +#endif /* process command line options @@ -50,10 +53,20 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "dn=*", NULL }, { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, + { "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" }, { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, +#ifdef _SAMBA_BUILD_ + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + POPT_COMMON_VERSION +#endif POPT_TABLEEND }; +#ifdef _SAMBA_BUILD_ + ldbsearch_init_subsystems; +#endif + ret = talloc_zero(ldb, struct ldb_cmdline); if (ret == NULL) { ldb_oom(ldb); @@ -74,6 +87,8 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const options.editor = "vi"; } + options.scope = LDB_SCOPE_DEFAULT; + pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST); @@ -133,6 +148,12 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const goto failed; } + if (ldb_connect(ldb, ret->url, 0, ret->options) != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + ret->url, ldb_errstring(ldb)); + goto failed; + } + return ret; failed: diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h index f3eae26cce..8e479c5538 100644 --- a/source4/lib/ldb/tools/cmdline.h +++ b/source4/lib/ldb/tools/cmdline.h @@ -39,6 +39,7 @@ struct ldb_cmdline { const char **argv; int num_records; int num_searches; + const char *sasl_mechanism; }; struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 35a41527be..7794b9de39 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -90,21 +90,13 @@ static int process_file(struct ldb_context *ldb, FILE *f) int main(int argc, const char **argv) { struct ldb_context *ldb; - int i, ret, count=0; + int i, count=0; struct ldb_cmdline *options; ldb = ldb_init(NULL); options = ldb_cmdline_process(ldb, argc, argv, usage); - ret = ldb_connect(ldb, options->url, 0, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - if (options->argc == 0) { count += process_file(ldb, stdin); } else { diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index fcf1d26d53..fdb1f7ef3b 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -93,14 +93,6 @@ static void usage(void) exit(1); } - ret = ldb_connect(ldb, options->url, 0, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - for (i=0;iargc;i++) { const char *dn = options->argv[i]; if (options->recursive) { diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 6c599ee2ec..73fb77dfd1 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -303,14 +303,6 @@ static void usage(void) attrs = (const char * const *)options->argv; } - ret = ldb_connect(ldb, options->url, LDB_FLG_RDONLY, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - ret = ldb_search(ldb, options->basedn, options->scope, expression, attrs, &msgs); if (ret == -1) { printf("search failed - %s\n", ldb_errstring(ldb)); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index c54c573ab0..39725b195d 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -100,14 +100,6 @@ static int process_file(struct ldb_context *ldb, FILE *f) options = ldb_cmdline_process(ldb, argc, argv, usage); - ret = ldb_connect(ldb, options->url, 0, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - if (options->argc == 0) { usage(); exit(1); diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index 5566c3d7d7..c74516869e 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -67,14 +67,6 @@ static void usage(void) options = ldb_cmdline_process(ldb, argc, argv, usage); - ret = ldb_connect(ldb, options->url, 0, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - if (options->argc < 2) { usage(); } diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 04f83ca366..0e81da5de3 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -119,7 +119,7 @@ static int do_search(struct ldb_context *ldb, struct ldb_context *ldb; const char * const * attrs = NULL; struct ldb_cmdline *options; - int ret; + int ret = -1; ldb = ldb_init(NULL); @@ -134,14 +134,6 @@ static int do_search(struct ldb_context *ldb, attrs = (const char * const *)(options->argv+1); } - ret = ldb_connect(ldb, options->url, LDB_FLG_RDONLY, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - if (options->interactive) { char line[1024]; while (fgets(line, sizeof(line), stdin)) { diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index a7c9a3123a..28ac7545a4 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -365,14 +365,6 @@ static void usage(void) options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; } - ret = ldb_connect(ldb, options->url, 0, options->options); - if (ret != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - options->url, ldb_errstring(ldb)); - talloc_free(ldb); - exit(1); - } - srandom(1); start_test(ldb, options->num_records, options->num_searches); -- cgit From 97318cdb45f1022ca2beebbf24ab11af80c07dc2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 09:48:17 +0000 Subject: r7719: make the ildap ldb backend use the defaultNamingContext if the basedn is not specified, so: ldbsearch ldap://hostname '(objectclass=user)' works without knowing the domain name (This used to be commit f6c2c5190737ca11f55a147f5295ccca505fb58b) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 9cccec0313..3f63af482f 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -37,9 +37,9 @@ #include "lib/cmdline/popt_common.h" struct ildb_private { - const char *basedn; struct ldap_connection *ldap; NTSTATUS last_rc; + struct ldb_message *rootDSE; }; /* @@ -100,6 +100,8 @@ static int ildb_delete(struct ldb_module *module, const char *dn) } +static void ildb_rootdse(struct ldb_module *module); + /* search for matching records */ @@ -116,7 +118,13 @@ static int ildb_search(struct ldb_module *module, const char *base, } if (base == NULL) { - base = ""; + if (ildb->rootDSE == NULL) { + ildb_rootdse(module); + } + if (ildb->rootDSE != NULL) { + base = ldb_msg_find_string(ildb->rootDSE, + "defaultNamingContext", ""); + } } if (expression == NULL || expression[0] == '\0') { @@ -351,6 +359,22 @@ static const struct ldb_module_ops ildb_ops = { }; +/* + fetch the rootDSE +*/ +static void ildb_rootdse(struct ldb_module *module) +{ + struct ildb_private *ildb = module->private_data; + struct ldb_message **res = NULL; + int ret; + ret = ildb_search(module, "", LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res); + if (ret == 1) { + ildb->rootDSE = talloc_steal(ildb, res[0]); + } + talloc_free(res); +} + + /* connect to the database */ @@ -366,6 +390,8 @@ int ildb_connect(struct ldb_context *ldb, const char *url, goto failed; } + ildb->rootDSE = NULL; + ildb->ldap = ldap_new_connection(ildb, NULL); if (!ildb->ldap) { ldb_oom(ldb); -- cgit From bf75ae41556a67739cd089a7e3182cf2a994448c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 13:18:43 +0000 Subject: r7726: - removed some unused variables - handle ldb_errstring() calls on failed connect (This used to be commit 8698a20fcc6a04ccbe533afd742e7a5df94423ee) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 9 ++++++++- source4/lib/ldb/tools/ldbmodify.c | 2 +- source4/lib/ldb/tools/ldbtest.c | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 3f63af482f..6560485be5 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -340,7 +340,11 @@ static int ildb_unlock(struct ldb_module *module, const char *lockname) */ static const char *ildb_errstring(struct ldb_module *module) { - struct ildb_private *ildb = module->private_data; + struct ildb_private *ildb = talloc_get_type(module->private_data, + struct ildb_private); + if (ildb == NULL) { + return "ildap not connected"; + } return ldap_errstr(ildb->ldap, ildb->last_rc); } @@ -427,6 +431,9 @@ int ildb_connect(struct ldb_context *ldb, const char *url, return 0; failed: + if (ldb->modules) { + ldb->modules->private_data = NULL; + } talloc_free(ildb); return -1; } diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 39725b195d..8fa0dcf0b6 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -93,7 +93,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) { struct ldb_context *ldb; int count=0; - int i, ret; + int i; struct ldb_cmdline *options; ldb = ldb_init(NULL); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 28ac7545a4..7c7164c785 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -353,7 +353,6 @@ static void usage(void) { TALLOC_CTX *mem_ctx = talloc_new(NULL); struct ldb_context *ldb; - int ret; ldb = ldb_init(mem_ctx); -- cgit From 0dde0612b420d12b92d22bd64baa500af2c00b2f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Jun 2005 13:39:51 +0000 Subject: r7728: handle 64 bit integers in INTEGER match (This used to be commit 57132344b4e39a670e683b3db00665e5f7a899fd) --- source4/lib/ldb/ldb_tdb/ldb_match.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c index 4c11542971..b5b023bc09 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ b/source4/lib/ldb/ldb_tdb/ldb_match.c @@ -44,10 +44,10 @@ */ static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2) { - int i1, i2; + uint64_t i1, i2; - i1 = strtol(v1->data, NULL, 0); - i2 = strtol(v2->data, NULL, 0); + i1 = strtoull(v1->data, NULL, 0); + i2 = strtoull(v2->data, NULL, 0); return i1 == i2; } -- cgit From 814d5a5011038164dd55dd9e593989f69cedef0d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 01:17:29 +0000 Subject: r7739: fixed an off by one bug in the base64 decoder for ldb ldif (This used to be commit fe2b77af2352f1964402a4286105916e990dc36f) --- source4/lib/ldb/common/ldb_ldif.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 546cf461f8..225fa3f3c9 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -71,6 +71,9 @@ static int base64_decode(char *s) } s++; i++; } + if (bit_offset >= 3) { + n--; + } if (*s && !p) { /* the only termination allowed */ -- cgit From 56cc32800036472ebc29362d65e422c0b410e3fc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 01:31:27 +0000 Subject: r7740: get rid of our duplicate base64 routines (This used to be commit cf17f90a83cf04815544c5408eb56d00546b3e88) --- source4/lib/ldb/common/ldb_ldif.c | 8 ++-- source4/lib/ldb/include/ldb.h | 2 + source4/lib/ldb/include/ldb_private.h | 1 - source4/lib/util_str.c | 86 ++++------------------------------- 4 files changed, 15 insertions(+), 82 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 225fa3f3c9..9492aa3634 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -46,7 +46,7 @@ this base64 decoder was taken from jitterbug (written by tridge). we might need to replace it with a new version */ -static int base64_decode(char *s) +int ldb_base64_decode(char *s) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i, n; @@ -92,7 +92,7 @@ static int base64_decode(char *s) encode as base64 caller frees */ -char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) +char *ldb_base64_encode(void *mem_ctx, const char *buf, int len) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; @@ -100,7 +100,7 @@ char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len) int bytes = (len*8 + 5)/6; char *out; - out = talloc_array(ldb, char, bytes+2); + out = talloc_array(mem_ctx, char, bytes+2); if (!out) return NULL; for (i=0;idata); + int len = ldb_base64_decode(value->data); if (len == -1) { /* it wasn't valid base64 data */ return -1; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index ecfa77f436..e980633a62 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -270,6 +270,8 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f); struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s); int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); +char *ldb_base64_encode(void *mem_ctx, const char *buf, int len); +int ldb_base64_decode(char *s); /* useful functions for ldb_message structure manipulation */ diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 76a43cdbc2..92588e13fd 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -116,7 +116,6 @@ const char *ldb_next_errstring(struct ldb_module *module); void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); /* The following definitions come from lib/ldb/common/ldb_ldif.c */ -char *ldb_base64_encode(struct ldb_context *ldb, const char *buf, int len); int ldb_should_b64_encode(const struct ldb_val *val); int ltdb_connect(struct ldb_context *ldb, const char *url, diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 69a4395cfb..fea7170014 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -24,6 +24,7 @@ #include "includes.h" #include "system/iconv.h" #include "pstring.h" +#include "lib/ldb/include/ldb.h" /** * @file @@ -895,37 +896,11 @@ void rfc1738_unescape(char *buf) /** * Decode a base64 string into a DATA_BLOB - simple and slow algorithm **/ -DATA_BLOB base64_decode_data_blob(const char *s) +DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s) { - const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - int bit_offset, byte_offset, idx, i, n; - DATA_BLOB decoded = data_blob(s, strlen(s)+1); - uint8_t *d = decoded.data; - char *p; - - n=i=0; - - while (*s && (p=strchr_m(b64,*s))) { - idx = (int)(p - b64); - byte_offset = (i*6)/8; - bit_offset = (i*6)%8; - d[byte_offset] &= ~((1<<(8-bit_offset))-1); - if (bit_offset < 3) { - d[byte_offset] |= (idx << (2-bit_offset)); - n = byte_offset+1; - } else { - d[byte_offset] |= (idx >> (bit_offset-2)); - d[byte_offset+1] = 0; - d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF; - n = byte_offset+2; - } - s++; i++; - } - - /* fix up length */ - decoded.length = n; - return decoded; + DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1); + ret.length = ldb_base64_decode(ret.data); + return ret; } /** @@ -933,58 +908,15 @@ DATA_BLOB base64_decode_data_blob(const char *s) **/ void base64_decode_inplace(char *s) { - DATA_BLOB decoded = base64_decode_data_blob(s); - memcpy(s, decoded.data, decoded.length); - data_blob_free(&decoded); - - /* null terminate */ - s[decoded.length] = '\0'; + ldb_base64_decode(s); } /** - * Encode a base64 string into a malloc()ed string caller to free. - * - *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments + * Encode a base64 string into a talloc()ed string caller to free. **/ -char * base64_encode_data_blob(DATA_BLOB data) +char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) { - const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int bits = 0; - int char_count = 0; - size_t out_cnt = 0; - size_t len = data.length; - size_t output_len = data.length * 2; - char *result = malloc(output_len); /* get us plenty of space */ - - while (len-- && out_cnt < (data.length * 2) - 5) { - int c = (uint8_t) *(data.data++); - bits += c; - char_count++; - if (char_count == 3) { - result[out_cnt++] = b64[bits >> 18]; - result[out_cnt++] = b64[(bits >> 12) & 0x3f]; - result[out_cnt++] = b64[(bits >> 6) & 0x3f]; - result[out_cnt++] = b64[bits & 0x3f]; - bits = 0; - char_count = 0; - } else { - bits <<= 8; - } - } - if (char_count != 0) { - bits <<= 16 - (8 * char_count); - result[out_cnt++] = b64[bits >> 18]; - result[out_cnt++] = b64[(bits >> 12) & 0x3f]; - if (char_count == 1) { - result[out_cnt++] = '='; - result[out_cnt++] = '='; - } else { - result[out_cnt++] = b64[(bits >> 6) & 0x3f]; - result[out_cnt++] = '='; - } - } - result[out_cnt] = '\0'; /* terminate */ - return result; + return ldb_base64_encode(mem_ctx, data.data, data.length); } #ifdef VALGRIND -- cgit From aa6b2dcb9bdff582ac7628f0c2511de12da57242 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 01:32:47 +0000 Subject: r7741: fixed the verbose option in ldbedit (This used to be commit a440133140a6adb5ea62d37690b9c4ae74dc6be0) --- source4/lib/ldb/tools/ldbedit.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 73fb77dfd1..e8497ba18f 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -41,7 +41,7 @@ #include "system/filesys.h" #endif -static int verbose; +static struct ldb_cmdline *options; /* debug routine @@ -77,16 +77,16 @@ static int modify_record(struct ldb_context *ldb, return 0; } + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod); + } + if (ldb_modify(ldb, mod) != 0) { fprintf(stderr, "failed to modify %s - %s\n", msg1->dn, ldb_errstring(ldb)); return -1; } - if (verbose > 0) { - ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod); - } - return mod->num_elements; } @@ -121,14 +121,14 @@ static int merge_edits(struct ldb_context *ldb, for (i=0;idn); if (!msg) { + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); + } if (ldb_add(ldb, msgs2[i]) != 0) { fprintf(stderr, "failed to add %s - %s\n", msgs2[i]->dn, ldb_errstring(ldb)); return -1; } - if (verbose > 0) { - ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); - } adds++; } else { if (modify_record(ldb, msg, msgs2[i]) > 0) { @@ -141,14 +141,14 @@ static int merge_edits(struct ldb_context *ldb, for (i=0;idn); if (!msg) { + if (options->verbose > 0) { + ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); + } if (ldb_delete(ldb, msgs1[i]->dn) != 0) { fprintf(stderr, "failed to delete %s - %s\n", msgs1[i]->dn, ldb_errstring(ldb)); return -1; } - if (verbose > 0) { - ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); - } deletes++; } } @@ -280,7 +280,6 @@ static void usage(void) int ret; const char *expression = NULL; const char * const * attrs = NULL; - struct ldb_cmdline *options; ldb = ldb_init(NULL); -- cgit From 225d5a334fca1a52714f0120d0961236db0f236c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 04:20:27 +0000 Subject: r7742: abstracted out the tls code from the web server, so that our other servers can easily become tls enabled. This will be used to add support for ldaps (This used to be commit 950500f603725349d2a0e22878e83dd1b5975f9f) --- source4/lib/tls/config.mk | 12 ++ source4/lib/tls/tls.c | 420 ++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/tls/tls.h | 61 +++++++ source4/lib/tls/tlscert.c | 153 +++++++++++++++++ 4 files changed, 646 insertions(+) create mode 100644 source4/lib/tls/config.mk create mode 100644 source4/lib/tls/tls.c create mode 100644 source4/lib/tls/tls.h create mode 100644 source4/lib/tls/tlscert.c (limited to 'source4/lib') diff --git a/source4/lib/tls/config.mk b/source4/lib/tls/config.mk new file mode 100644 index 0000000000..0800a69829 --- /dev/null +++ b/source4/lib/tls/config.mk @@ -0,0 +1,12 @@ +################################################ +# Start SUBSYSTEM LIBTLS +[SUBSYSTEM::LIBTLS] +ADD_OBJ_FILES = \ + lib/tls/tls.o \ + lib/tls/tlscert.o +REQUIRED_SUBSYSTEMS = \ + LIBTALLOC EXT_LIB_GNUTLS +NOPROTO = YES +# +# End SUBSYSTEM LIBTLS +################################################ diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c new file mode 100644 index 0000000000..3b166b27a0 --- /dev/null +++ b/source4/lib/tls/tls.c @@ -0,0 +1,420 @@ +/* + Unix SMB/CIFS implementation. + + transport layer security handling code + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "lib/socket/socket.h" +#include "lib/tls/tls.h" + +#if HAVE_LIBGNUTLS +#include "gnutls/gnutls.h" + +#define DH_BITS 1024 + +/* hold persistent tls data */ +struct tls_params { + gnutls_certificate_credentials x509_cred; + gnutls_dh_params dh_params; + BOOL tls_enabled; +}; + +/* hold per connection tls data */ +struct tls_context { + struct tls_params *params; + struct socket_context *socket; + struct fd_event *fde; + gnutls_session session; + BOOL done_handshake; + BOOL have_first_byte; + uint8_t first_byte; + BOOL tls_enabled; + BOOL tls_detect; + const char *plain_chars; + BOOL output_pending; +}; + + +/* + callback for reading from a socket +*/ +static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size) +{ + struct tls_context *tls = talloc_get_type(ptr, struct tls_context); + NTSTATUS status; + size_t nread; + + if (tls->have_first_byte) { + *(uint8_t *)buf = tls->first_byte; + tls->have_first_byte = False; + return 1; + } + + status = socket_recv(tls->socket, buf, size, &nread, 0); + if (!NT_STATUS_IS_OK(status)) { + EVENT_FD_READABLE(tls->fde); + EVENT_FD_NOT_WRITEABLE(tls->fde); + return -1; + } + if (tls->output_pending) { + EVENT_FD_WRITEABLE(tls->fde); + } + if (size != nread) { + EVENT_FD_READABLE(tls->fde); + } + return nread; +} + +/* + callback for writing to a socket +*/ +static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size) +{ + struct tls_context *tls = talloc_get_type(ptr, struct tls_context); + NTSTATUS status; + size_t nwritten; + DATA_BLOB b; + + if (!tls->tls_enabled) { + return size; + } + + b.data = discard_const(buf); + b.length = size; + + status = socket_send(tls->socket, &b, &nwritten, 0); + if (!NT_STATUS_IS_OK(status)) { + EVENT_FD_WRITEABLE(tls->fde); + return -1; + } + if (size != nwritten) { + EVENT_FD_WRITEABLE(tls->fde); + } + return nwritten; +} + +/* + destroy a tls session + */ +static int tls_destructor(void *ptr) +{ + struct tls_context *tls = talloc_get_type(ptr, struct tls_context); + int ret; + ret = gnutls_bye(tls->session, GNUTLS_SHUT_WR); + if (ret < 0) { + DEBUG(0,("TLS gnutls_bye failed - %s\n", gnutls_strerror(ret))); + } + return 0; +} + + +/* + possibly continue the handshake process +*/ +static NTSTATUS tls_handshake(struct tls_context *tls) +{ + int ret; + + if (tls->done_handshake) { + return NT_STATUS_OK; + } + + ret = gnutls_handshake(tls->session); + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + return STATUS_MORE_ENTRIES; + } + if (ret < 0) { + DEBUG(0,("TLS gnutls_handshake failed - %s\n", gnutls_strerror(ret))); + return NT_STATUS_UNEXPECTED_NETWORK_ERROR; + } + tls->done_handshake = True; + return NT_STATUS_OK; +} + + +/* + receive data either by tls or normal socket_recv +*/ +NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, + size_t *nread) +{ + int ret; + NTSTATUS status; + if (tls->tls_enabled && tls->tls_detect) { + status = socket_recv(tls->socket, &tls->first_byte, 1, nread, 0); + NT_STATUS_NOT_OK_RETURN(status); + if (*nread == 0) return NT_STATUS_OK; + tls->tls_detect = False; + /* look for the first byte of a valid HTTP operation */ + if (strchr(tls->plain_chars, tls->first_byte)) { + /* not a tls link */ + tls->tls_enabled = False; + *(uint8_t *)buf = tls->first_byte; + return NT_STATUS_OK; + } + tls->have_first_byte = True; + } + + if (!tls->tls_enabled) { + return socket_recv(tls->socket, buf, wantlen, nread, 0); + } + + status = tls_handshake(tls); + NT_STATUS_NOT_OK_RETURN(status); + + ret = gnutls_record_recv(tls->session, buf, wantlen); + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + return STATUS_MORE_ENTRIES; + } + if (ret < 0) { + DEBUG(0,("gnutls_record_recv failed - %s\n", gnutls_strerror(ret))); + return NT_STATUS_UNEXPECTED_NETWORK_ERROR; + } + *nread = ret; + return NT_STATUS_OK; +} + + +/* + send data either by tls or normal socket_recv +*/ +NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t *sendlen) +{ + NTSTATUS status; + int ret; + + if (!tls->tls_enabled) { + return socket_send(tls->socket, blob, sendlen, 0); + } + + status = tls_handshake(tls); + NT_STATUS_NOT_OK_RETURN(status); + + ret = gnutls_record_send(tls->session, blob->data, blob->length); + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + return STATUS_MORE_ENTRIES; + } + if (ret < 0) { + DEBUG(0,("gnutls_record_send failed - %s\n", gnutls_strerror(ret))); + return NT_STATUS_UNEXPECTED_NETWORK_ERROR; + } + *sendlen = ret; + tls->output_pending = (ret < blob->length); + return NT_STATUS_OK; +} + + +/* + initialise global tls state +*/ +struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) +{ + struct tls_params *params; + int ret; + const char *keyfile = lp_tls_keyfile(); + const char *certfile = lp_tls_certfile(); + const char *cafile = lp_tls_cafile(); + const char *crlfile = lp_tls_crlfile(); + void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *); + + params = talloc(mem_ctx, struct tls_params); + if (params == NULL) return NULL; + + if (!lp_tls_enabled() || keyfile == NULL || *keyfile == 0) { + params->tls_enabled = False; + return params; + } + + if (!file_exist(cafile)) { + tls_cert_generate(params, keyfile, certfile, cafile); + } + + ret = gnutls_global_init(); + if (ret < 0) goto init_failed; + + gnutls_certificate_allocate_credentials(¶ms->x509_cred); + if (ret < 0) goto init_failed; + + if (cafile && *cafile) { + ret = gnutls_certificate_set_x509_trust_file(params->x509_cred, cafile, + GNUTLS_X509_FMT_PEM); + if (ret < 0) { + DEBUG(0,("TLS failed to initialise cafile %s\n", cafile)); + goto init_failed; + } + } + + if (crlfile && *crlfile) { + ret = gnutls_certificate_set_x509_crl_file(params->x509_cred, + crlfile, + GNUTLS_X509_FMT_PEM); + if (ret < 0) { + DEBUG(0,("TLS failed to initialise crlfile %s\n", crlfile)); + goto init_failed; + } + } + + ret = gnutls_certificate_set_x509_key_file(params->x509_cred, + certfile, keyfile, + GNUTLS_X509_FMT_PEM); + if (ret < 0) { + DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s\n", + certfile, keyfile)); + goto init_failed; + } + + ret = gnutls_dh_params_init(¶ms->dh_params); + if (ret < 0) goto init_failed; + + ret = gnutls_dh_params_generate2(params->dh_params, DH_BITS); + if (ret < 0) goto init_failed; + + gnutls_certificate_set_dh_params(params->x509_cred, params->dh_params); + + params->tls_enabled = True; + return params; + +init_failed: + DEBUG(0,("GNUTLS failed to initialise - %s\n", gnutls_strerror(ret))); + params->tls_enabled = False; + return params; +} + + +/* + setup for a new connection +*/ +struct tls_context *tls_init_server(struct tls_params *params, + struct socket_context *socket, + struct fd_event *fde, + const char *plain_chars) +{ + struct tls_context *tls; + int ret; + + tls = talloc(socket, struct tls_context); + if (tls == NULL) return NULL; + + tls->socket = socket; + tls->fde = fde; + + if (!params->tls_enabled) { + tls->tls_enabled = False; + return tls; + } + +#define TLSCHECK(call) do { \ + ret = call; \ + if (ret < 0) { \ + DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \ + goto failed; \ + } \ +} while (0) + + TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER)); + + talloc_set_destructor(tls, tls_destructor); + + TLSCHECK(gnutls_set_default_priority(tls->session)); + TLSCHECK(gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, + params->x509_cred)); + gnutls_certificate_server_set_request(tls->session, GNUTLS_CERT_REQUEST); + gnutls_dh_set_prime_bits(tls->session, DH_BITS); + gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls); + gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull); + gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push); + gnutls_transport_set_lowat(tls->session, 0); + + tls->plain_chars = plain_chars; + if (plain_chars) { + tls->tls_detect = True; + } else { + tls->tls_detect = False; + } + + tls->output_pending = False; + tls->params = params; + tls->done_handshake = False; + tls->have_first_byte = False; + tls->tls_enabled = True; + + return tls; + +failed: + DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret))); + tls->tls_enabled = False; + params->tls_enabled = False; + return tls; +} + +BOOL tls_enabled(struct tls_context *tls) +{ + return tls->tls_enabled; +} + +BOOL tls_support(struct tls_params *params) +{ + return params->tls_enabled; +} + + +#else + +/* for systems without tls we just map the tls socket calls to the + normal socket calls */ + +struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) +{ + return talloc_new(mem_ctx); +} + +struct tls_context *tls_init_server(struct tls_params *params, + struct socket_context *sock, + struct fd_event *fde, + const char *plain_chars) +{ + if (plain_chars == NULL) return NULL; + return (struct tls_context *)sock; +} + + +NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, + size_t *nread) +{ + return socket_recv((struct socket_context *)tls, buf, wantlen, nread, 0); +} + +NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t *sendlen) +{ + return socket_send((struct socket_context *)tls, blob, sendlen, 0); +} + +BOOL tls_enabled(struct tls_context *tls) +{ + return False; +} + +BOOL tls_support(struct tls_params *params) +{ + return False; +} + +#endif diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h new file mode 100644 index 0000000000..f87d49d9eb --- /dev/null +++ b/source4/lib/tls/tls.h @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + + transport layer security handling code + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + call tls_initialise() once per task to startup the tls subsystem +*/ +struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx); + +/* + call tls_init_server() on each new server connection + + the 'plain_chars' parameter is a list of chars that when they occur + as the first character from the client on the connection tell the + tls code that this is a non-tls connection. This can be used to have + tls and non-tls servers on the same port. If this is NULL then only + tls connections will be allowed +*/ +struct tls_context *tls_init_server(struct tls_params *parms, + struct socket_context *sock, + struct fd_event *fde, + const char *plain_chars); + +/* + call these to send and receive data. They behave like socket_send() and socket_recv() + */ +NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, + size_t *nread); +NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, + size_t *sendlen); + +/* + return True if a connection used tls +*/ +BOOL tls_enabled(struct tls_context *tls); + + +/* + true if tls support is compiled in +*/ +BOOL tls_support(struct tls_params *parms); + + diff --git a/source4/lib/tls/tlscert.c b/source4/lib/tls/tlscert.c new file mode 100644 index 0000000000..2cd46ff432 --- /dev/null +++ b/source4/lib/tls/tlscert.c @@ -0,0 +1,153 @@ +/* + Unix SMB/CIFS implementation. + + auto-generate self signed TLS certificates + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#if HAVE_LIBGNUTLS +#include "gnutls/gnutls.h" +#include "gnutls/x509.h" + +#define ORGANISATION_NAME "Samba Administration" +#define UNIT_NAME "Samba - temporary autogenerated certificate" +#define COMMON_NAME "Samba" +#define LIFETIME 700*24*60*60 + +/* + auto-generate a set of self signed certificates +*/ +void tls_cert_generate(TALLOC_CTX *mem_ctx, + const char *keyfile, const char *certfile, + const char *cafile) +{ + gnutls_x509_crt cacrt, crt; + gnutls_x509_privkey key, cakey; + uint32_t serial = (uint32_t)time(NULL); + char keyid[100]; + char buf[4096]; + size_t bufsize; + size_t keyidsize = sizeof(keyid); + time_t activation = time(NULL), expiry = activation + LIFETIME; + int ret; + + if (file_exist(keyfile) || file_exist(certfile) || file_exist(cafile)) { + DEBUG(0,("TLS autogeneration skipped - some TLS files already exist\n")); + return; + } + +#define TLSCHECK(call) do { \ + ret = call; \ + if (ret < 0) { \ + DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \ + goto failed; \ + } \ +} while (0) + + TLSCHECK(gnutls_global_init()); + + DEBUG(0,("Attempting to autogenerate TLS self-signed keys for https\n")); + + DEBUG(3,("Generating private key\n")); + TLSCHECK(gnutls_x509_privkey_init(&key)); + TLSCHECK(gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 1024, 0)); + + DEBUG(3,("Generating CA private key\n")); + TLSCHECK(gnutls_x509_privkey_init(&cakey)); + TLSCHECK(gnutls_x509_privkey_generate(cakey, GNUTLS_PK_RSA, 1024, 0)); + + DEBUG(3,("Generating CA certificate\n")); + TLSCHECK(gnutls_x509_crt_init(&cacrt)); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, + GNUTLS_OID_X520_ORGANIZATION_NAME, 0, + ORGANISATION_NAME, strlen(ORGANISATION_NAME))); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, + GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, + UNIT_NAME, strlen(UNIT_NAME))); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt, + GNUTLS_OID_X520_COMMON_NAME, 0, + COMMON_NAME, strlen(COMMON_NAME))); + TLSCHECK(gnutls_x509_crt_set_key(cacrt, cakey)); + TLSCHECK(gnutls_x509_crt_set_serial(cacrt, &serial, sizeof(serial))); + TLSCHECK(gnutls_x509_crt_set_activation_time(cacrt, activation)); + TLSCHECK(gnutls_x509_crt_set_expiration_time(cacrt, expiry)); + TLSCHECK(gnutls_x509_crt_set_ca_status(cacrt, 0)); +#ifdef GNUTLS_KP_TLS_WWW_SERVER + TLSCHECK(gnutls_x509_crt_set_key_purpose_oid(cacrt, GNUTLS_KP_TLS_WWW_SERVER, 0)); +#endif + TLSCHECK(gnutls_x509_crt_set_version(cacrt, 3)); + TLSCHECK(gnutls_x509_crt_get_key_id(cacrt, 0, keyid, &keyidsize)); + TLSCHECK(gnutls_x509_crt_set_subject_key_id(cacrt, keyid, keyidsize)); + TLSCHECK(gnutls_x509_crt_sign(cacrt, cacrt, cakey)); + + DEBUG(3,("Generating TLS certificate\n")); + TLSCHECK(gnutls_x509_crt_init(&crt)); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt, + GNUTLS_OID_X520_ORGANIZATION_NAME, 0, + ORGANISATION_NAME, strlen(ORGANISATION_NAME))); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt, + GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, + UNIT_NAME, strlen(UNIT_NAME))); + TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt, + GNUTLS_OID_X520_COMMON_NAME, 0, + COMMON_NAME, strlen(COMMON_NAME))); + TLSCHECK(gnutls_x509_crt_set_key(crt, key)); + TLSCHECK(gnutls_x509_crt_set_serial(crt, &serial, sizeof(serial))); + TLSCHECK(gnutls_x509_crt_set_activation_time(crt, activation)); + TLSCHECK(gnutls_x509_crt_set_expiration_time(crt, expiry)); + TLSCHECK(gnutls_x509_crt_set_ca_status(crt, 0)); +#ifdef GNUTLS_KP_TLS_WWW_SERVER + TLSCHECK(gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0)); +#endif + TLSCHECK(gnutls_x509_crt_set_version(crt, 3)); + TLSCHECK(gnutls_x509_crt_get_key_id(crt, 0, keyid, &keyidsize)); + TLSCHECK(gnutls_x509_crt_set_subject_key_id(crt, keyid, keyidsize)); + TLSCHECK(gnutls_x509_crt_sign(crt, crt, key)); + + DEBUG(3,("Exporting TLS keys\n")); + + bufsize = sizeof(buf); + TLSCHECK(gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buf, &bufsize)); + file_save(certfile, buf, bufsize); + + bufsize = sizeof(buf); + TLSCHECK(gnutls_x509_crt_export(cacrt, GNUTLS_X509_FMT_PEM, buf, &bufsize)); + file_save(cafile, buf, bufsize); + + bufsize = sizeof(buf); + TLSCHECK(gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buf, &bufsize)); + file_save(keyfile, buf, bufsize); + + gnutls_x509_privkey_deinit(key); + gnutls_x509_privkey_deinit(cakey); + gnutls_x509_crt_deinit(cacrt); + gnutls_x509_crt_deinit(crt); + gnutls_global_deinit(); + + DEBUG(0,("TLS self-signed keys generated OK\n")); + return; + +failed: + DEBUG(0,("TLS certificate generation failed\n")); +} + +#else + void tls_cert_dummy(void) {} +#endif -- cgit From e485e80b512f17aba0b6b1dd5acc3f738f4189c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 04:20:54 +0000 Subject: r7743: be consistent in how stdin is supported for ldbadd and ldbmodify (This used to be commit 3d60b3a8eea5ac6c35cf2e579ae12cef3dc1794e) --- source4/lib/ldb/tools/ldbmodify.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 8fa0dcf0b6..901a4c9628 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -101,25 +101,17 @@ static int process_file(struct ldb_context *ldb, FILE *f) options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { - usage(); - exit(1); - } - - for (i=0;iargc;i++) { - const char *fname = options->argv[i]; - FILE *f; - if (strcmp(fname,"-") == 0) { - f = stdin; - } else { + count += process_file(ldb, stdin); + } else { + for (i=0;iargc;i++) { + const char *fname = options->argv[i]; + FILE *f; f = fopen(fname, "r"); - } - if (!f) { - perror(fname); - exit(1); - } - count += process_file(ldb, f); - if (f != stdin) { - fclose(f); + if (!f) { + perror(fname); + exit(1); + } + count += process_file(ldb, f); } } -- cgit From 28fd9ea80befe049ee786a9e4c7454181a576e9a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 07:19:42 +0000 Subject: r7745: better handling of recv errors in tls library (This used to be commit 42d8a1a222430bd64962da7cc4ac0193b5c003f7) --- source4/lib/tls/tls.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 3b166b27a0..8f443c67d7 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -69,9 +69,19 @@ static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size) } status = socket_recv(tls->socket, buf, size, &nread, 0); + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + return 0; + } + if (NT_STATUS_IS_ERR(status)) { + EVENT_FD_NOT_READABLE(tls->fde); + EVENT_FD_NOT_WRITEABLE(tls->fde); + errno = EBADF; + return -1; + } if (!NT_STATUS_IS_OK(status)) { EVENT_FD_READABLE(tls->fde); EVENT_FD_NOT_WRITEABLE(tls->fde); + errno = EAGAIN; return -1; } if (tls->output_pending) { @@ -185,7 +195,6 @@ NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, return STATUS_MORE_ENTRIES; } if (ret < 0) { - DEBUG(0,("gnutls_record_recv failed - %s\n", gnutls_strerror(ret))); return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } *nread = ret; -- cgit From c7496c6cdb7bdcdd483868c21457350f567ec054 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 09:31:34 +0000 Subject: r7747: - simplified the ldap server buffer handling - got rid of the special cases for sasl buffers - added a tls_socket_pending() call to determine how much data is waiting on a tls connection - removed the attempt at async handling of ldap calls. The buffers/sockets are all async, but the calls themselves are sync. (This used to be commit 73cb4aad229d08e17e22d5792580bd43a61b142a) --- source4/lib/tls/tls.c | 21 ++++++++++++++++++++- source4/lib/tls/tls.h | 5 +++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 8f443c67d7..53b689f135 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -159,6 +159,20 @@ static NTSTATUS tls_handshake(struct tls_context *tls) return NT_STATUS_OK; } +/* + see how many bytes are pending on the connection +*/ +NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending) +{ + if (!tls->tls_enabled || tls->tls_detect) { + return socket_pending(tls->socket, npending); + } + *npending = gnutls_record_check_pending(tls->session); + if (*npending == 0) { + return socket_pending(tls->socket, npending); + } + return NT_STATUS_OK; +} /* receive data either by tls or normal socket_recv @@ -222,7 +236,7 @@ NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t return STATUS_MORE_ENTRIES; } if (ret < 0) { - DEBUG(0,("gnutls_record_send failed - %s\n", gnutls_strerror(ret))); + DEBUG(0,("gnutls_record_send of %d failed - %s\n", blob->length, gnutls_strerror(ret))); return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } *sendlen = ret; @@ -426,4 +440,9 @@ BOOL tls_support(struct tls_params *params) return False; } +NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending) +{ + return socket_pending((struct socket_context *)tls, npending); +} + #endif diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h index f87d49d9eb..fe993a3804 100644 --- a/source4/lib/tls/tls.h +++ b/source4/lib/tls/tls.h @@ -59,3 +59,8 @@ BOOL tls_enabled(struct tls_context *tls); BOOL tls_support(struct tls_params *parms); +/* + ask for the number of bytes in a pending incoming packet +*/ +NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending); + -- cgit From 7267cb3312f148be8cd00eb76b8e137cd4b2a314 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 10:37:45 +0000 Subject: r7749: some bug fixes from testing with socket:testnonblock - fixed some infinite loops in asn1.c - ensure asn1 callers know if an error is end of buffer or bad data - handle npending 0 in ldap server (This used to be commit f22c3b84c8912ccd36e676a782b58f1841be8875) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 6560485be5..eefe80c919 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -124,6 +124,8 @@ static int ildb_search(struct ldb_module *module, const char *base, if (ildb->rootDSE != NULL) { base = ldb_msg_find_string(ildb->rootDSE, "defaultNamingContext", ""); + } else { + base = ""; } } -- cgit From 6720bd94b8506d652ddc273bdbe02944e5911e23 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 11:00:13 +0000 Subject: r7750: handle STATUS_MORE_ENTRIES on send in tls (This used to be commit 135c3367ff737246ea40030d3c852769666ff522) --- source4/lib/tls/tls.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 53b689f135..559a54a2f0 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -111,6 +111,10 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size) b.length = size; status = socket_send(tls->socket, &b, &nwritten, 0); + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + errno = EAGAIN; + return -1; + } if (!NT_STATUS_IS_OK(status)) { EVENT_FD_WRITEABLE(tls->fde); return -1; -- cgit From 7a17da2186c628f0d8e8a43ca34320b0f10d9d8f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 11:10:15 +0000 Subject: r7751: only enable tls on the ldaps port in ldap server, and reject non-tls connections on that port (This used to be commit 30da6a1cc41308a16a486111887f45bcf598f064) --- source4/lib/tls/tls.c | 9 +++++---- source4/lib/tls/tls.h | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 559a54a2f0..86a2ca0f0b 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -332,7 +332,8 @@ init_failed: struct tls_context *tls_init_server(struct tls_params *params, struct socket_context *socket, struct fd_event *fde, - const char *plain_chars) + const char *plain_chars, + BOOL tls_enable) { struct tls_context *tls; int ret; @@ -343,7 +344,7 @@ struct tls_context *tls_init_server(struct tls_params *params, tls->socket = socket; tls->fde = fde; - if (!params->tls_enabled) { + if (!params->tls_enabled || !tls_enable) { tls->tls_enabled = False; return tls; } @@ -402,7 +403,6 @@ BOOL tls_support(struct tls_params *params) return params->tls_enabled; } - #else /* for systems without tls we just map the tls socket calls to the @@ -416,7 +416,8 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) struct tls_context *tls_init_server(struct tls_params *params, struct socket_context *sock, struct fd_event *fde, - const char *plain_chars) + const char *plain_chars, + BOOL tls_enable) { if (plain_chars == NULL) return NULL; return (struct tls_context *)sock; diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h index fe993a3804..3046e35a1c 100644 --- a/source4/lib/tls/tls.h +++ b/source4/lib/tls/tls.h @@ -37,7 +37,8 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx); struct tls_context *tls_init_server(struct tls_params *parms, struct socket_context *sock, struct fd_event *fde, - const char *plain_chars); + const char *plain_chars, + BOOL tls_enable); /* call these to send and receive data. They behave like socket_send() and socket_recv() -- cgit From 683f3bc96ee8b388d547a64734b8c0bf356e85f1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 12:34:59 +0000 Subject: r7754: fixed the local port of accepted sockets in socket_wrapper. This fixes the problem with the ldap tests in 'make test' (This used to be commit 56fe27623ce31015a5a14f176f1445f51d57b0b8) --- source4/lib/socket_wrapper/socket_wrapper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 882ef462ea..42bac4bfae 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -242,11 +242,10 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) memset(child_si, 0, sizeof(*child_si)); child_si->fd = fd; + child_si->bound = 1; - if (addr && addrlen) { - child_si->myname_len = *addrlen; - child_si->myname = sockaddr_dup(addr, *addrlen); - } + child_si->myname_len = parent_si->myname_len; + child_si->myname = sockaddr_dup(parent_si->myname, parent_si->myname_len); child_si->peername_len = *addrlen; child_si->peername = sockaddr_dup(addr, *addrlen); -- cgit From 1601b8e9f9eecd59f82a2a18cd87438be41c611b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 13:29:07 +0000 Subject: r7759: allow ldb_errstring() to be used when not connected (This used to be commit 818ae965afad37216d804aa630359d875794612e) --- source4/lib/ldb/common/ldb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index d2dbac95ea..450fa75d8e 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -172,6 +172,9 @@ int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) */ const char *ldb_errstring(struct ldb_context *ldb) { + if (ldb->modules == NULL) { + return "ldb not connected"; + } return ldb->modules->ops->errstring(ldb->modules); } -- cgit From c4e7c6e2daf20f721c51e56bf90ac3856c30d954 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 19 Jun 2005 23:17:35 +0000 Subject: r7767: fixed ldb dependencies (This used to be commit 97e4ba84fb4cf4b95270c5d49b6bb8a9a92feaac) --- source4/lib/ldb/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 82083e3137..9206ac1081 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -95,7 +95,7 @@ REQUIRED_SUBSYSTEMS = \ [SUBSYSTEM::LIBLDB_CMDLINE] OBJ_FILES= \ lib/ldb/tools/cmdline.o -REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE +REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC # End SUBSYSTEM LIBLDB_CMDLINE ################################################ -- cgit From 64bf731865c7ea0a95d658099e7578f4bae3a9cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 01:15:47 +0000 Subject: r7769: added client support in the tls library api (This used to be commit 71ee6a1df542b95c61217de71e6f56b8ce9d81b5) --- source4/lib/tls/tls.c | 131 +++++++++++++++++++++++++++++++++++++++++++++----- source4/lib/tls/tls.h | 7 +++ 2 files changed, 126 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 86a2ca0f0b..49f7b758c0 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -39,7 +39,6 @@ struct tls_params { /* hold per connection tls data */ struct tls_context { - struct tls_params *params; struct socket_context *socket; struct fd_event *fde; gnutls_session session; @@ -50,8 +49,19 @@ struct tls_context { BOOL tls_detect; const char *plain_chars; BOOL output_pending; + gnutls_certificate_credentials xcred; + BOOL interrupted; }; +#define TLSCHECK(call) do { \ + ret = call; \ + if (ret < 0) { \ + DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \ + goto failed; \ + } \ +} while (0) + + /* callback for reading from a socket @@ -80,7 +90,6 @@ static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size) } if (!NT_STATUS_IS_OK(status)) { EVENT_FD_READABLE(tls->fde); - EVENT_FD_NOT_WRITEABLE(tls->fde); errno = EAGAIN; return -1; } @@ -153,6 +162,9 @@ static NTSTATUS tls_handshake(struct tls_context *tls) ret = gnutls_handshake(tls->session); if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(tls->session) == 1) { + EVENT_FD_WRITEABLE(tls->fde); + } return STATUS_MORE_ENTRIES; } if (ret < 0) { @@ -163,6 +175,28 @@ static NTSTATUS tls_handshake(struct tls_context *tls) return NT_STATUS_OK; } +/* + possibly continue an interrupted operation +*/ +static NTSTATUS tls_interrupted(struct tls_context *tls) +{ + int ret; + + if (!tls->interrupted) { + return NT_STATUS_OK; + } + if (gnutls_record_get_direction(tls->session) == 1) { + ret = gnutls_record_send(tls->session, NULL, 0); + } else { + ret = gnutls_record_recv(tls->session, NULL, 0); + } + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + return STATUS_MORE_ENTRIES; + } + tls->interrupted = False; + return NT_STATUS_OK; +} + /* see how many bytes are pending on the connection */ @@ -173,7 +207,12 @@ NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending) } *npending = gnutls_record_check_pending(tls->session); if (*npending == 0) { - return socket_pending(tls->socket, npending); + NTSTATUS status = socket_pending(tls->socket, npending); + if (*npending == 0) { + /* seems to be a gnutls bug */ + (*npending) = 100; + } + return status; } return NT_STATUS_OK; } @@ -208,8 +247,15 @@ NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, status = tls_handshake(tls); NT_STATUS_NOT_OK_RETURN(status); + status = tls_interrupted(tls); + NT_STATUS_NOT_OK_RETURN(status); + ret = gnutls_record_recv(tls->session, buf, wantlen); if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(tls->session) == 1) { + EVENT_FD_WRITEABLE(tls->fde); + } + tls->interrupted = True; return STATUS_MORE_ENTRIES; } if (ret < 0) { @@ -235,8 +281,15 @@ NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t status = tls_handshake(tls); NT_STATUS_NOT_OK_RETURN(status); + status = tls_interrupted(tls); + NT_STATUS_NOT_OK_RETURN(status); + ret = gnutls_record_send(tls->session, blob->data, blob->length); if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(tls->session) == 1) { + EVENT_FD_WRITEABLE(tls->fde); + } + tls->interrupted = True; return STATUS_MORE_ENTRIES; } if (ret < 0) { @@ -317,6 +370,7 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) gnutls_certificate_set_dh_params(params->x509_cred, params->dh_params); params->tls_enabled = True; + return params; init_failed: @@ -349,14 +403,6 @@ struct tls_context *tls_init_server(struct tls_params *params, return tls; } -#define TLSCHECK(call) do { \ - ret = call; \ - if (ret < 0) { \ - DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \ - goto failed; \ - } \ -} while (0) - TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER)); talloc_set_destructor(tls, tls_destructor); @@ -379,10 +425,10 @@ struct tls_context *tls_init_server(struct tls_params *params, } tls->output_pending = False; - tls->params = params; tls->done_handshake = False; tls->have_first_byte = False; tls->tls_enabled = True; + tls->interrupted = False; return tls; @@ -393,6 +439,60 @@ failed: return tls; } + +/* + setup for a new client connection +*/ +struct tls_context *tls_init_client(struct socket_context *socket, + struct fd_event *fde, + BOOL tls_enable) +{ + struct tls_context *tls; + int ret; + const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; + tls = talloc(socket, struct tls_context); + if (tls == NULL) return NULL; + + tls->socket = socket; + tls->fde = fde; + tls->tls_enabled = tls_enable; + + if (!tls->tls_enabled) { + return tls; + } + + gnutls_global_init(); + + gnutls_certificate_allocate_credentials(&tls->xcred); + gnutls_certificate_set_x509_trust_file(tls->xcred, lp_tls_cafile(), + GNUTLS_X509_FMT_PEM); + TLSCHECK(gnutls_init(&tls->session, GNUTLS_CLIENT)); + TLSCHECK(gnutls_set_default_priority(tls->session)); + gnutls_certificate_type_set_priority(tls->session, cert_type_priority); + TLSCHECK(gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, tls->xcred)); + + talloc_set_destructor(tls, tls_destructor); + + gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls); + gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull); + gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push); + gnutls_transport_set_lowat(tls->session, 0); + tls->tls_detect = False; + + tls->output_pending = False; + tls->done_handshake = False; + tls->have_first_byte = False; + tls->tls_enabled = True; + tls->interrupted = False; + + return tls; + +failed: + DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret))); + tls->tls_enabled = False; + return tls; +} + BOOL tls_enabled(struct tls_context *tls) { return tls->tls_enabled; @@ -423,6 +523,13 @@ struct tls_context *tls_init_server(struct tls_params *params, return (struct tls_context *)sock; } +struct tls_context *tls_init_client(struct socket_context *sock, + struct fd_event *fde, + BOOL tls_enable) +{ + return (struct tls_context *)sock; +} + NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen, size_t *nread) diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h index 3046e35a1c..a046b91637 100644 --- a/source4/lib/tls/tls.h +++ b/source4/lib/tls/tls.h @@ -40,6 +40,13 @@ struct tls_context *tls_init_server(struct tls_params *parms, const char *plain_chars, BOOL tls_enable); +/* + call tls_init_client() on each new client connection +*/ +struct tls_context *tls_init_client(struct socket_context *sock, + struct fd_event *fde, + BOOL tls_enable); + /* call these to send and receive data. They behave like socket_send() and socket_recv() */ -- cgit From 30b68a0af2df78958aa6ec73b00014e55711a777 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 04:18:23 +0000 Subject: r7773: fixed the tls code for the non-GNUTLS case (This used to be commit bc6bc84ef4ad3434c6cb8d94a8d7a105ad2fd8c2) --- source4/lib/tls/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index 49f7b758c0..f89e2f1028 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -519,7 +519,7 @@ struct tls_context *tls_init_server(struct tls_params *params, const char *plain_chars, BOOL tls_enable) { - if (plain_chars == NULL) return NULL; + if (tls_enable && plain_chars == NULL) return NULL; return (struct tls_context *)sock; } -- cgit From bd7a474b1967423711ff93c0080ce0f89270e3f9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 04:56:43 +0000 Subject: r7776: add a method for getting arbitrary opaque data into a ldb context, for use by backends. Currently only EventContext is used in this way. (This used to be commit 9fa21b245843371f7777682ee4e5b98e2925b4d0) --- source4/lib/ldb/common/ldb.c | 31 +++++++++++++++++++++++++++++++ source4/lib/ldb/include/ldb.h | 4 ++++ source4/lib/ldb/include/ldb_private.h | 7 +++++++ source4/lib/ldb/ldb_ildap/ldb_ildap.c | 5 +++-- 4 files changed, 45 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 450fa75d8e..e268a8d0d7 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -178,3 +178,34 @@ const char *ldb_errstring(struct ldb_context *ldb) return ldb->modules->ops->errstring(ldb->modules); } + +/* + set backend specific opaque parameters +*/ +int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) +{ + struct ldb_opaque *o = talloc(ldb, struct ldb_opaque); + if (o == NULL) { + ldb_oom(ldb); + return -1; + } + o->next = ldb->opaque; + o->name = name; + o->value = value; + ldb->opaque = o; + return 0; +} + +/* + get a previously set opaque value +*/ +void *ldb_get_opaque(struct ldb_context *ldb, const char *name) +{ + struct ldb_opaque *o; + for (o=ldb->opaque;o;o=o->next) { + if (strcmp(o->name, name) == 0) { + return o->value; + } + } + return NULL; +} diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index e980633a62..9a3186b41c 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -372,4 +372,8 @@ int ldb_set_debug(struct ldb_context *ldb, /* this sets up debug to print messages on stderr */ int ldb_set_debug_stderr(struct ldb_context *ldb); +/* control backend specific opaque values */ +int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value); +void *ldb_get_opaque(struct ldb_context *ldb, const char *name); + #endif diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 92588e13fd..8f91b0d9b1 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -77,6 +77,13 @@ struct ldb_context { /* debugging operations */ struct ldb_debug_ops debug_ops; + + /* backend specific opaque parameters */ + struct ldb_opaque { + struct ldb_opaque *next; + const char *name; + void *value; + } *opaque; }; /* the modules init function */ diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index eefe80c919..b51139aa6f 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -398,7 +398,7 @@ int ildb_connect(struct ldb_context *ldb, const char *url, ildb->rootDSE = NULL; - ildb->ldap = ldap_new_connection(ildb, NULL); + ildb->ldap = ldap_new_connection(ildb, ldb_get_opaque(ldb, "EventContext")); if (!ildb->ldap) { ldb_oom(ldb); goto failed; @@ -421,7 +421,8 @@ int ildb_connect(struct ldb_context *ldb, const char *url, ldb->modules->private_data = ildb; ldb->modules->ops = &ildb_ops; - if (cmdline_credentials->username_obtained > CRED_GUESSED) { + if (cmdline_credentials != NULL && + cmdline_credentials->username_obtained > CRED_GUESSED) { status = ldap_bind_sasl(ildb->ldap, cmdline_credentials); if (!NT_STATUS_IS_OK(status)) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n", -- cgit From 545203d9154a9ce0f5cc3800796581f62380074b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 05:03:54 +0000 Subject: r7778: added talloc_find_parent_bytype() and talloc_find_parent_byname() These provide a way to find a parent of a ptr that is of a given type. I will be using this to find the event context in smbd, relying on the fact that everything is a child of the top level event context. I did look at the alternatives, and found that passing the event context to just about every call in smbd was getting way too complex (we need to get it to anything that can do a ldb operation, as that can invoke ldap). So this method avoids a global, and seems to work nicely (This used to be commit bdb55c7a10a516b75652065e14f5acd09d24ab35) --- source4/lib/talloc/talloc.c | 24 ++++++++++++++++++++++++ source4/lib/talloc/talloc.h | 3 +++ source4/lib/talloc/talloc_guide.txt | 13 +++++++++++++ 3 files changed, 40 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 6b6eb87f21..c6f748ea3b 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -1108,3 +1108,27 @@ size_t talloc_get_size(const void *context) return tc->size; } + +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc->prev) { + tc = tc->prev; + } + while (tc->parent && (!tc->name || strcmp(tc->name, name))) { + tc = tc->parent; + } + if (tc == NULL) { + return NULL; + } + return (void *)(tc+1); +} diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index ab549cf624..5160a3874a 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -65,6 +65,8 @@ typedef void TALLOC_CTX; #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) + #if TALLOC_DEPRECATED #define talloc_zero_p(ctx, type) talloc_zero(ctx, type) @@ -127,6 +129,7 @@ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); #endif diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index d30538bf9f..7477dad266 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -567,3 +567,16 @@ This function lets you know the amount of memory alloced so far by this context. It does NOT account for subcontext memory. This can be used to calculate the size of an array. +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +void *talloc_find_parent_byname(const void *ctx, const char *name); + +Find a parent memory context of the current context that has the given +name. This can be very useful in complex programs where it may be +difficult to pass all information down to the level you need, but you +know the structure you want is a parent of another context. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +(type *)talloc_find_parent_bytype(ctx, type); + +Like talloc_find_parent_byname() but takes a type, making it typesafe. + -- cgit From e3eec57b06f7e0f7c6c3e4dbbc814db27cc19a25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 05:04:45 +0000 Subject: r7779: use the parent event context in ldb_wrap_connect(). See the comment in the previous commit for the method. (This used to be commit b0ad505510b9df8e7f05fb646046114eb6b997ed) --- source4/lib/db_wrap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 33c2af2851..c277f2d975 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -82,6 +82,8 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, struct ldb_context *ldb; struct ldb_wrap *w; int ret; + struct event_context *ev; + for (w = ldb_list; w; w = w->next) { if (strcmp(url, w->url) == 0) { @@ -93,6 +95,14 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, if (ldb == NULL) { return NULL; } + + /* we want to use the existing event context if possible. This + relies on the fact that in smbd, everything is a child of + the main event_context */ + ev = talloc_find_parent_bytype(mem_ctx, struct event_context); + if (ev) { + ldb_set_opaque(ldb, "EventContext", ev); + } ret = ldb_connect(ldb, url, flags, options); if (ret == -1) { -- cgit From bb8d0c76b4f2ad61421f33aae6b268f3de98870f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 05:21:11 +0000 Subject: r7780: fixed a bug in talloc_find_parent_byname() (This used to be commit ee3fe42fb16821eedd564201d953042190f7826f) --- source4/lib/talloc/talloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index c6f748ea3b..9dd7ef36c7 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -1127,7 +1127,7 @@ void *talloc_find_parent_byname(const void *context, const char *name) while (tc->parent && (!tc->name || strcmp(tc->name, name))) { tc = tc->parent; } - if (tc == NULL) { + if (tc == NULL || tc->name == NULL || strcmp(tc->name, name)) { return NULL; } return (void *)(tc+1); -- cgit From a124028b660ba5de566442302a8ee3b925595850 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 06:15:35 +0000 Subject: r7781: finding the parent of a talloc ptr is trickier than it looks due to the two-way tree nature of the data structure. I think I've finally got it right also added talloc_show_parents() for debugging (This used to be commit 5760ed20eed509b0b6e09e78c942dd0f70350fa9) --- source4/lib/talloc/talloc.c | 33 ++++++++++++++++++++++++++------- source4/lib/talloc/talloc.h | 1 + 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 9dd7ef36c7..08d4cb93a6 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -1121,14 +1121,33 @@ void *talloc_find_parent_byname(const void *context, const char *name) } tc = talloc_chunk_from_ptr(context); - while (tc->prev) { - tc = tc->prev; - } - while (tc->parent && (!tc->name || strcmp(tc->name, name))) { + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return (void*)(tc+1); + } + while (tc && tc->prev) tc = tc->prev; tc = tc->parent; } - if (tc == NULL || tc->name == NULL || strcmp(tc->name, name)) { - return NULL; + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(tc+1)); + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; } - return (void *)(tc+1); } diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 5160a3874a..04d5cbb9af 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -130,6 +130,7 @@ void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); size_t talloc_get_size(const void *ctx); void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); #endif -- cgit From b7be627e35b81fb2df8cdd83d129713aa8f0127a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Jun 2005 08:50:53 +0000 Subject: r7784: give an error in ldb_tdb for invalid modify flags. The "whenChanged" bug was being silently ignored with the tdb backend because of this bug. A case where the ldap backend was right, and the tdb backend was wrong! (This used to be commit ddb26db763c314049043d80d27113226c0f2e656) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 596ede8a4e..f8c98d6712 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -679,6 +679,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } } break; + default: + ltdb->last_err_string = "Invalid ldb_modify flags"; + goto failed; } } -- cgit From eb0a13025aa6d693c7e9fa213ef04fa58cf60e3e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Jun 2005 06:35:55 +0000 Subject: r7803: added support in ldb for callers to setup ldif read/write functions, so that ldbedit, ldbsearch etc can display nice human readable ldif, while storing the data as binary blobs. This will be used for storing NDR encoded objectSid and similar attributes, while making the command line interface sane (This used to be commit 37e283089a846fc0608fef3981a3447300e33728) --- source4/lib/ldb/common/ldb_ldif.c | 79 ++++++++++++++++++++++++++++++----- source4/lib/ldb/include/ldb.h | 13 ++++++ source4/lib/ldb/include/ldb_private.h | 4 ++ 3 files changed, 86 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 9492aa3634..88ef9fae45 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -41,6 +41,44 @@ #include "ldb/include/ldb_private.h" #include +/* + default function for ldif read/write +*/ +static int ldb_ldif_default(struct ldb_context *ldb, const struct ldb_val *in, + struct ldb_val *out) +{ + *out = *in; + return 0; +} + + +/* + return a function for reading an ldif encoded attributes into a ldb_val +*/ +static ldb_ldif_handler_t ldb_ldif_read_fn(struct ldb_context *ldb, const char *attr) +{ + int i; + for (i=0;ildif_num_handlers;i++) { + if (strcmp(attr, ldb->ldif_handlers[i].attr) == 0) { + return ldb->ldif_handlers[i].read_fn; + } + } + return ldb_ldif_default; +} + +/* + return a function for writing an ldif encoded attribute from a ldb_val +*/ +static ldb_ldif_handler_t ldb_ldif_write_fn(struct ldb_context *ldb, const char *attr) +{ + int i; + for (i=0;ildif_num_handlers;i++) { + if (strcmp(attr, ldb->ldif_handlers[i].attr) == 0) { + return ldb->ldif_handlers[i].write_fn; + } + } + return ldb_ldif_default; +} /* this base64 decoder was taken from jitterbug (written by tridge). @@ -49,9 +87,9 @@ int ldb_base64_decode(char *s) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int bit_offset, byte_offset, idx, i, n; + int bit_offset=0, byte_offset, idx, i, n; uint8_t *d = (uint8_t *)s; - char *p; + char *p=NULL; n=i=0; @@ -254,13 +292,17 @@ int ldb_ldif_write(struct ldb_context *ldb, } for (j=0;jelements[i].num_values;j++) { - if (ldb_should_b64_encode(&msg->elements[i].values[j])) { + ldb_ldif_handler_t write_fn = ldb_ldif_write_fn(ldb, + msg->elements[i].name); + struct ldb_val v; + ret = write_fn(ldb, &msg->elements[i].values[j], &v); + CHECK_RET; + if (ldb_should_b64_encode(&v)) { ret = fprintf_fn(private_data, "%s:: ", msg->elements[i].name); CHECK_RET; ret = base64_encode_f(ldb, fprintf_fn, private_data, - msg->elements[i].values[j].data, - msg->elements[i].values[j].length, + v.data, v.length, strlen(msg->elements[i].name)+3); CHECK_RET; ret = fprintf_fn(private_data, "\n"); @@ -269,13 +311,15 @@ int ldb_ldif_write(struct ldb_context *ldb, ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name); CHECK_RET; ret = fold_string(fprintf_fn, private_data, - msg->elements[i].values[j].data, - msg->elements[i].values[j].length, + v.data, v.length, strlen(msg->elements[i].name)+2); CHECK_RET; ret = fprintf_fn(private_data, "\n"); CHECK_RET; } + if (v.data != msg->elements[i].values[j].data) { + talloc_free(v.data); + } } if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { fprintf_fn(private_data, "-\n"); @@ -510,8 +554,9 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, msg->dn = value.data; while (next_attr(&s, &attr, &value) == 0) { + ldb_ldif_handler_t read_fn; struct ldb_message_element *el; - int empty = 0; + int ret, empty = 0; if (ldb_attr_cmp(attr, "changetype") == 0) { int i; @@ -555,6 +600,8 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, el = &msg->elements[msg->num_elements-1]; + read_fn = ldb_ldif_read_fn(ldb, attr); + if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) { /* its a continuation */ @@ -564,7 +611,13 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, if (!el->values) { goto failed; } - el->values[el->num_values] = value; + ret = read_fn(ldb, &value, &el->values[el->num_values]); + if (ret != 0) { + goto failed; + } + if (value.data != el->values[el->num_values].data) { + talloc_steal(el->values, el->values[el->num_values].data); + } el->num_values++; } else { /* its a new attribute */ @@ -582,7 +635,13 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, goto failed; } el->num_values = 1; - el->values[0] = value; + ret = read_fn(ldb, &value, &el->values[0]); + if (ret != 0) { + goto failed; + } + if (value.data != el->values[0].data) { + talloc_steal(el->values, el->values[0].data); + } msg->num_elements++; } } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 9a3186b41c..48290beb92 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -184,6 +184,19 @@ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s); char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree); char *ldb_binary_encode(void *ctx, struct ldb_val val); + +/* + functions for controlling ldif encode/decode +*/ +typedef int (*ldb_ldif_handler_t)(struct ldb_context *, const struct ldb_val *, struct ldb_val *); + +struct ldb_ldif_handler { + const char *attr; + ldb_ldif_handler_t read_fn; + ldb_ldif_handler_t write_fn; +}; + + /* initialise a ldb context */ diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 8f91b0d9b1..f6c1c7ff46 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -84,6 +84,10 @@ struct ldb_context { const char *name; void *value; } *opaque; + + /* ldif attribute handling table */ + unsigned ldif_num_handlers; + struct ldb_ldif_handler *ldif_handlers; }; /* the modules init function */ -- cgit From 5be159f304411b58c417a979c819f9ab211a0337 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Jun 2005 07:52:00 +0000 Subject: r7804: added the samba specific ldif handlers into the tree, but don't enable them just yet. I have tested them, and they work fine, but enabling them will break code in rpc_server/ and samdb, so we need to fix that first (This used to be commit 07d459406b4c63e49141e0e533e1274b4052abf9) --- source4/lib/ldb/common/ldb_ldif.c | 28 ++++++++++- source4/lib/ldb/config.mk | 10 +++- source4/lib/ldb/include/ldb.h | 3 ++ source4/lib/ldb/samba/README | 7 +++ source4/lib/ldb/samba/ldif_handlers.c | 95 +++++++++++++++++++++++++++++++++++ source4/lib/ldb/tools/cmdline.c | 8 ++- 6 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 source4/lib/ldb/samba/README create mode 100644 source4/lib/ldb/samba/ldif_handlers.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 88ef9fae45..94109ce224 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -41,6 +41,30 @@ #include "ldb/include/ldb_private.h" #include + +/* + add to the list of ldif handlers for this ldb context +*/ +int ldb_ldif_add_handlers(struct ldb_context *ldb, + const struct ldb_ldif_handler *handlers, + unsigned num_handlers) +{ + struct ldb_ldif_handler *h; + h = talloc_realloc(ldb, ldb->ldif_handlers, + struct ldb_ldif_handler, + ldb->ldif_num_handlers + num_handlers); + if (h == NULL) { + ldb_oom(ldb); + return -1; + } + ldb->ldif_handlers = h; + memcpy(h + ldb->ldif_num_handlers, + handlers, sizeof(*h) * num_handlers); + ldb->ldif_num_handlers += num_handlers; + return 0; +} + + /* default function for ldif read/write */ @@ -59,7 +83,7 @@ static ldb_ldif_handler_t ldb_ldif_read_fn(struct ldb_context *ldb, const char * { int i; for (i=0;ildif_num_handlers;i++) { - if (strcmp(attr, ldb->ldif_handlers[i].attr) == 0) { + if (ldb_attr_cmp(attr, ldb->ldif_handlers[i].attr) == 0) { return ldb->ldif_handlers[i].read_fn; } } @@ -73,7 +97,7 @@ static ldb_ldif_handler_t ldb_ldif_write_fn(struct ldb_context *ldb, const char { int i; for (i=0;ildif_num_handlers;i++) { - if (strcmp(attr, ldb->ldif_handlers[i].attr) == 0) { + if (ldb_attr_cmp(attr, ldb->ldif_handlers[i].attr) == 0) { return ldb->ldif_handlers[i].write_fn; } } diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 9206ac1081..00568aeda8 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -90,12 +90,20 @@ REQUIRED_SUBSYSTEMS = \ # End LIBRARY LIBLDB ################################################ +################################################ +# Start SUBSYSTEM LDBSAMBA +[SUBSYSTEM::LDBSAMBA] +OBJ_FILES = \ + lib/ldb/samba/ldif_handlers.o +# End SUBSYSTEM LDBSAMBA +################################################ + ################################################ # Start SUBSYSTEM LIBLDB_CMDLINE [SUBSYSTEM::LIBLDB_CMDLINE] OBJ_FILES= \ lib/ldb/tools/cmdline.o -REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC +REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC LDBSAMBA # End SUBSYSTEM LIBLDB_CMDLINE ################################################ diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 48290beb92..3102676327 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -285,6 +285,9 @@ struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s); int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); char *ldb_base64_encode(void *mem_ctx, const char *buf, int len); int ldb_base64_decode(char *s); +int ldb_ldif_add_handlers(struct ldb_context *ldb, + const struct ldb_ldif_handler *handlers, + unsigned num_handlers); /* useful functions for ldb_message structure manipulation */ diff --git a/source4/lib/ldb/samba/README b/source4/lib/ldb/samba/README new file mode 100644 index 0000000000..3fa47159ca --- /dev/null +++ b/source4/lib/ldb/samba/README @@ -0,0 +1,7 @@ +This directory contains Samba specific extensions to ldb. It also +serves as example code on how to extend ldb for your own application. + +The main extension Samba uses is to provide ldif encode/decode +routines for specific attributes, so users can get nice pretty +printing of attributes in ldbedit, while the attributes are stored in +the standard NDR format in the database. diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c new file mode 100644 index 0000000000..7252d081f1 --- /dev/null +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -0,0 +1,95 @@ +/* + ldb database library - ldif handlers for Samba + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* + convert a ldif formatted objectSid to a NDR formatted blob +*/ +static int ldif_read_objectSid(struct ldb_context *ldb, const struct ldb_val *in, + struct ldb_val *out) +{ + struct dom_sid *sid; + NTSTATUS status; + sid = dom_sid_parse_talloc(ldb, in->data); + if (sid == NULL) { + return -1; + } + status = ndr_push_struct_blob(out, ldb, sid, + (ndr_push_flags_fn_t)ndr_push_dom_sid); + talloc_free(sid); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + return 0; +} + +/* + convert a NDR formatted blob to a ldif formatted objectSid +*/ +static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *in, + struct ldb_val *out) +{ + struct dom_sid *sid; + NTSTATUS status; + sid = talloc(ldb, struct dom_sid); + if (sid == NULL) { + return -1; + } + status = ndr_pull_struct_blob(in, sid, sid, + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(sid); + return -1; + } + out->data = dom_sid_string(ldb, sid); + talloc_free(sid); + if (out->data == NULL) { + return -1; + } + out->length = strlen(out->data); + return 0; +} + + +static const struct ldb_ldif_handler samba_handlers[] = { + { "objectSid", ldif_read_objectSid, ldif_write_objectSid } +}; + +/* + register the samba ldif handlers +*/ +int ldb_register_samba_handlers(struct ldb_context *ldb) +{ +#if 0 + /* we can't enable this until we fix the sam code to handle + non-string elements */ + return ldb_ldif_add_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers)); +#else + return 0; +#endif +} diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 1f4a7544a5..31d3f2662a 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -36,9 +36,9 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, void (*usage)(void)) { - struct ldb_cmdline options, *ret; + struct ldb_cmdline options, *ret=NULL; poptContext pc; - int num_options = 0; + int r, num_options = 0; char opt; struct poptOption popt_options[] = { POPT_AUTOHELP @@ -65,6 +65,10 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const #ifdef _SAMBA_BUILD_ ldbsearch_init_subsystems; + r = ldb_register_samba_handlers(ldb); + if (r != 0) { + goto failed; + } #endif ret = talloc_zero(ldb, struct ldb_cmdline); -- cgit From 064d71c9d494835a8bfb76624e00d8330fc2523a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 21 Jun 2005 11:14:54 +0000 Subject: r7805: add support to read binary files into attributes data like ldap tools does (This used to be commit 38a14396262eeb279d67c2f0da06bfa0706a3be4) --- source4/lib/ldb/common/ldb_ldif.c | 76 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 94109ce224..70dd2267b5 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -104,6 +104,62 @@ static ldb_ldif_handler_t ldb_ldif_write_fn(struct ldb_context *ldb, const char return ldb_ldif_default; } +/* + +*/ +static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value) +{ + struct stat statbuf; + char *buf; + int count, size, bytes; + int ret; + int f; + + f = open(value->data, O_RDONLY); + if (f == -1) { + return -1; + } + + if (fstat(f, &statbuf) != 0) { + ret = -1; + goto done; + } + + if (statbuf.st_size == 0) { + ret = -1; + goto done; + } + + value->data = talloc_size(mem_ctx, statbuf.st_size + 1); + if (value->data == NULL) { + ret = -1; + goto done; + } + value->data[statbuf.st_size] = 0; + + count = 0; + size = statbuf.st_size; + buf = value->data; + while (count < statbuf.st_size) { + bytes = read(f, buf, size); + if (bytes == -1) { + talloc_free(value->data); + ret = -1; + goto done; + } + count += bytes; + buf += bytes; + size -= bytes; + } + + value->length = statbuf.st_size; + ret = statbuf.st_size; + +done: + close(f); + return ret; +} + /* this base64 decoder was taken from jitterbug (written by tridge). we might need to replace it with a new version @@ -426,10 +482,11 @@ static char *next_chunk(struct ldb_context *ldb, /* simple ldif attribute parser */ -static int next_attr(char **s, const char **attr, struct ldb_val *value) +static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value) { char *p; int base64_encoded = 0; + int binary_file = 0; if (strncmp(*s, "-\n", 2) == 0) { value->length = 0; @@ -450,6 +507,11 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) p++; } + if (*p == '<') { + binary_file = 1; + p++; + } + *attr = *s; while (*p == ' ' || *p == '\t') { @@ -478,6 +540,14 @@ static int next_attr(char **s, const char **attr, struct ldb_val *value) value->length = len; } + if (binary_file) { + int len = ldb_read_data_file(mem_ctx, value); + if (len == -1) { + /* an error occured hile trying to retrieve the file */ + return -1; + } + } + return 0; } @@ -564,7 +634,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, msg->private_data = chunk; s = chunk; - if (next_attr(&s, &attr, &value) != 0) { + if (next_attr(ldif, &s, &attr, &value) != 0) { goto failed; } @@ -577,7 +647,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, msg->dn = value.data; - while (next_attr(&s, &attr, &value) == 0) { + while (next_attr(ldif, &s, &attr, &value) == 0) { ldb_ldif_handler_t read_fn; struct ldb_message_element *el; int ret, empty = 0; -- cgit From 7f46f89257aa47b6362daf7c68242dae4aae8ae9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 21 Jun 2005 11:22:05 +0000 Subject: r7806: add test for binary files as attribute values (This used to be commit 2b2675055e5113eccb0b876799b226d480335495) --- source4/lib/ldb/tests/photo.ldif | 5 +++++ source4/lib/ldb/tests/samba4.png | Bin 0 -> 6239 bytes source4/lib/ldb/tests/test-generic.sh | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 source4/lib/ldb/tests/photo.ldif create mode 100644 source4/lib/ldb/tests/samba4.png (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/photo.ldif b/source4/lib/ldb/tests/photo.ldif new file mode 100644 index 0000000000..24485f1203 --- /dev/null +++ b/source4/lib/ldb/tests/photo.ldif @@ -0,0 +1,5 @@ +dn: cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US +changetype: modify +add: photo +photo:< tests/samba4.png + diff --git a/source4/lib/ldb/tests/samba4.png b/source4/lib/ldb/tests/samba4.png new file mode 100644 index 0000000000..c8096889a6 Binary files /dev/null and b/source4/lib/ldb/tests/samba4.png differ diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 5e0cc9cec6..2df22e756c 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -50,3 +50,6 @@ if [ "$count" != 3 ]; then echo returned $count records - expected 3 exit 1 fi + +echo "Testing binary file attribute value" +$VALGRIND bin/ldbmodify tests/photo.ldif || exit 1 -- cgit From 062e0f83258b6c8d8fa48e42e157331de5ce4686 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Jun 2005 13:18:09 +0000 Subject: r7808: fixed the build of ldb after the binary file support in ldif was added (This used to be commit 0a8c722c8017e20635223b2c5dfc58759478312c) --- source4/lib/ldb/common/ldb_ldif.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 70dd2267b5..f3bc5c6207 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -40,7 +40,9 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include - +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif /* add to the list of ldif handlers for this ldb context -- cgit From 8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Jun 2005 02:12:26 +0000 Subject: r7827: Add in-memory keytab to Samba4, using the new MEMORY_WILDCARD keytab support in Heimdal. This removes the 'ext_keytab' step from my Samba4/WinXP client howto. In doing this work, I realised that the replay cache in Heimdal is currently a no-op, so I have removed the calls to it, and therefore the mutex calls from passdb/secrets.c. This patch also includes a replacement 'magic' mechanism detection, that does not issue extra error messages from deep inside the GSSAPI code. Andrew Bartlett (This used to be commit c19d5706f4fa760415b727b970bc99e7f1abd064) --- source4/lib/basic.mk | 1 - source4/lib/server_mutex.c | 58 ---------------------------------------------- 2 files changed, 59 deletions(-) delete mode 100644 source4/lib/server_mutex.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 6a463b8ec6..58cbca0198 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -73,7 +73,6 @@ ADD_OBJ_FILES = \ lib/ms_fnmatch.o \ lib/select.o \ lib/mutex.o \ - lib/server_mutex.o \ lib/idtree.o \ lib/unix_privs.o \ lib/db_wrap.o \ diff --git a/source4/lib/server_mutex.c b/source4/lib/server_mutex.c deleted file mode 100644 index 878e5497d8..0000000000 --- a/source4/lib/server_mutex.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Authenticate against a remote domain - Copyright (C) Andrew Tridgell 1992-2002 - Copyright (C) Andrew Bartlett 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* For reasons known only to MS, many of their NT/Win2k versions - need serialised access only. Two connections at the same time - may (in certain situations) cause connections to be reset, - or access to be denied. - - This locking allows smbd's mutlithread architecture to look - like the single-connection that NT makes. */ - -static char *mutex_server_name; -/* FIXME. ref_count should be allocated per name... JRA. */ -size_t ref_count; - -BOOL grab_server_mutex(const char *name) -{ - mutex_server_name = strdup(name); - if (!mutex_server_name) { - DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name)); - return False; - } - if (!secrets_named_mutex(mutex_server_name, 10, &ref_count)) { - DEBUG(10,("grab_server_mutex: failed for %s\n", name)); - SAFE_FREE(mutex_server_name); - return False; - } - - return True; -} - -void release_server_mutex(void) -{ - if (mutex_server_name) { - secrets_named_mutex_release(mutex_server_name, &ref_count); - SAFE_FREE(mutex_server_name); - } -} -- cgit From fdc0450db25021eddcc65d032fd3fd8ca5976928 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 22 Jun 2005 02:39:07 +0000 Subject: r7828: Although there is still plenty to do, ldb_sqlite3 now passes the set of tests in tests/test-sqlite3.sh (tests/test-generic.sh). There are lots of optimizations still TBD, and some things are REALLY slow right now (e.g. each add() operation takes 1/3 - 1/2 second) but it's ready for interested parties to poke it and prod it and see how (un)reasonable it is. Play away. Still to be implemented or improved: - tdb specials (@MODULES, @SUBCLASSES, etc.) - all DNs are case-folded in their entirty right now (since doing otherwise would require @ATTRIBUTES to be implemented) - speed improvements and optimizations. I am quite confident that the excessively slow add() operation can be much improved, and other areas can be somewhat improved. (This used to be commit 1dd865005594671e7effe06fb088fa97fa08de0b) --- source4/lib/ldb/common/ldb.c | 18 +- source4/lib/ldb/include/ldb.h | 10 + source4/lib/ldb/ldb_sqlite3/base160.c | 3 +- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 1102 ++++++++++++++++++++++------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 8 +- source4/lib/ldb/ldb_sqlite3/schema | 367 +++++++--- source4/lib/ldb/tests/test-sqlite3.sh | 2 +- source4/lib/ldb/tools/ldbtest.c | 10 + 8 files changed, 1156 insertions(+), 364 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index e268a8d0d7..63526dfe2e 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -76,7 +76,7 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co #endif #if HAVE_SQLITE3 else if (strncmp(url, "sqlite:", 7) == 0) { - ldb_ctx = lsqlite3_connect(url, flags, options); + ret = lsqlite3_connect(ldb, url, flags, options); } #endif else { @@ -167,6 +167,22 @@ int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); } +/* + create a named lock +*/ +int ldb_lock(struct ldb_context *ldb, const char *lockname) +{ + return ldb->modules->ops->named_lock(ldb->modules, lockname); +} + +/* + release a named lock +*/ +int ldb_unlock(struct ldb_context *ldb, const char *lockname) +{ + return ldb->modules->ops->named_unlock(ldb->modules, lockname); +} + /* return extended error information */ diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 3102676327..1b5c7c4f57 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -254,6 +254,16 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn); +/* + create a named lock +*/ +int ldb_lock(struct ldb_context *ldb, const char *lockname); + +/* + release a named lock +*/ +int ldb_unlock(struct ldb_context *ldb, const char *lockname); + /* delete a record from the database */ diff --git a/source4/lib/ldb/ldb_sqlite3/base160.c b/source4/lib/ldb/ldb_sqlite3/base160.c index e7220433fc..4286979123 100644 --- a/source4/lib/ldb/ldb_sqlite3/base160.c +++ b/source4/lib/ldb/ldb_sqlite3/base160.c @@ -115,6 +115,7 @@ char * lsqlite3_base160Next(char base160[]) { int i; + int len; unsigned char * pTab; char * pBase160 = base160; @@ -122,7 +123,7 @@ lsqlite3_base160Next(char base160[]) * We need a minimum of four digits, and we will always get a multiple of * four digits. */ - if (*pBase160 != '\0') + if (len = strlen(pBase160)) >= 4) { pBase160 += strlen(pBase160) - 1; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 3d36043044..ff19ff737a 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -51,34 +51,50 @@ #define FILTER_ATTR_TABLE "temp_filter_attrs" #define RESULT_ATTR_TABLE "temp_result_attrs" -#define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ - do { \ - if (query_norows(lsqlite3, sql) != 0) { \ - if (bRollbackOnError) { \ - query_norows(lsqlite3, \ - "ROLLBACK;"); \ - } \ - return -1; \ - } \ +//#define TEMPTAB /* for testing, create non-temporary table */ +#define TEMPTAB "TEMPORARY" + +//#define DEBUG_LOCKS + +#ifndef DEBUG_LOCKS +# define LOCK_DB(mod, name) lsqlite3_lock(mod, name) +# define UNLOCK_DB(mod, name) lsqlite3_unlock(mod, name) +#else +# define LOCK_DB(mod, name) lock_debug(mod, name, __FILE__, __LINE__) +# define UNLOCK_DB(mod, name) unlock_debug(mod, name, __FILE__, __LINE__) +#endif + +#define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ + do { \ + if (query_norows(lsqlite3, sql) != 0) { \ + if (bRollbackOnError) { \ + UNLOCK_DB(module, "rollback"); \ + } \ + return -1; \ + } \ } while (0) #define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \ do { \ if (query_int(lsqlite3, &result_var, sql) != 0) { \ if (bRollbackOnError) { \ - query_norows(lsqlite3, \ - "ROLLBACK;"); \ + UNLOCK_DB(module, "rollback"); \ } \ return -1; \ } \ } while (0) +#define SQLITE3_DEBUG_QUERY (1 << 0) +#define SQLITE3_DEBUG_INIT (1 << 1) +#define SQLITE3_DEBUG_ADD (1 << 2) +#define SQLITE3_DEBUG_NEWDN (1 << 3) +#define SQLITE3_DEBUG_SEARCH (1 << 4) + /* * Static variables */ -static int lsqlite3_debug = TRUE; - +static int lsqlite3_debug = FALSE; /* * Forward declarations @@ -164,7 +180,7 @@ parsetree_to_sql(struct ldb_module *module, const struct ldb_parse_tree *t); static int -parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, +parsetree_to_attrlist(struct ldb_module *module, const struct ldb_parse_tree * t); #ifdef NEED_TABLE_LIST @@ -188,6 +204,28 @@ static int new_attr(struct ldb_module * module, char * pAttrName); +static void +base160_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv); + +static void +base160next_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv); + +#ifdef DEBUG_LOCKS +static int lock_debug(struct ldb_module * module, + const char * lockname, + const char * pFileName, + int linenum); + +static int unlock_debug(struct ldb_module * module, + const char * lockname, + const char * pFileName, + int linenum); +#endif + /* * Table of operations for the sqlite3 backend @@ -223,7 +261,6 @@ int lsqlite3_connect(struct ldb_context *ldb, { int i; int ret; - struct ldb_context * ldb = NULL; struct lsqlite3_private * lsqlite3 = NULL; lsqlite3 = talloc(ldb, struct lsqlite3_private); @@ -295,21 +332,55 @@ lsqlite3_rename(struct ldb_module * module, const char * pOldDN, const char * pNewDN) { + long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; + /* ignore ltdb specials */ + if (*pOldDN == '@' || *pNewDN == '@') { + return 0; + } + /* Case-fold each of the DNs */ pOldDN = ldb_dn_fold(module->ldb, pOldDN, module, case_fold_attr_required); pNewDN = ldb_dn_fold(module->ldb, pNewDN, module, case_fold_attr_required); + /* Begin a transaction */ + if (LOCK_DB(module, "transaction") < 0) { + return -1; + } + + /* Determine the eid of the DN being deleted */ + QUERY_INT(lsqlite3, + eid, + TRUE, + "SELECT eid\n" + " FROM ldb_entry\n" + " WHERE dn = %Q;", + pOldDN); + QUERY_NOROWS(lsqlite3, - FALSE, + TRUE, "UPDATE ldb_entry " " SET dn = %Q " - " WHERE dn = %Q;", - pNewDN, pOldDN); + " WHERE eid = %lld;", + pNewDN, eid); + QUERY_NOROWS(lsqlite3, + TRUE, + "UPDATE ldb_attr_DN " + " SET attr_value = %Q " + " WHERE eid = %lld;", + pNewDN, + eid); + + /* Commit the transaction */ + if (UNLOCK_DB(module, "transaction") < 0) { + UNLOCK_DB(module, "rollback"); + return -1; + } + return 0; } @@ -326,8 +397,18 @@ lsqlite3_delete(struct ldb_module * module, sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; + /* ignore ltdb specials */ + if (*pDN == '@') { + return 0; + } + /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + if (LOCK_DB(module, "transaction") < 0) { + return -1; + } + + /* Case-fold the DNs */ + pDN = ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ QUERY_INT(lsqlite3, @@ -340,7 +421,7 @@ lsqlite3_delete(struct ldb_module * module, /* Obtain the list of attribute names in use by this DN */ if ((pSql = talloc_asprintf(module->ldb, - "SELECT attr_name " + "SELECT upper(attr_name) " " FROM ldb_attribute_values " " WHERE eid = %lld;", eid)) == NULL) { @@ -413,22 +494,32 @@ lsqlite3_delete(struct ldb_module * module, bLoop = FALSE; } - /* Delete the descendants records */ + /* Delete the DN attribute entry */ QUERY_NOROWS(lsqlite3, TRUE, - "DELETE FROM ldb_descendants " - " WHERE deid = %lld;", + "DELETE FROM ldb_attr_DN " + " WHERE eid = %lld;", eid); /* Delete attribute/value table entries pertaining to this DN */ QUERY_NOROWS(lsqlite3, TRUE, - "DELETE FROM ldb_attribute_value " + "DELETE FROM ldb_attribute_values " + " WHERE eid = %lld;", + eid); + + /* Delete this entry */ + QUERY_NOROWS(lsqlite3, + TRUE, + "DELETE FROM ldb_entry " " WHERE eid = %lld;", eid); /* Commit the transaction */ - QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + if (UNLOCK_DB(module, "transaction") < 0) { + UNLOCK_DB(module, "rollback"); + return -1; + } return 0; } @@ -478,7 +569,9 @@ lsqlite3_search_bytree(struct ldb_module * module, } /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;"); + if (LOCK_DB(module, "transaction") < 0) { + return -1; + } /* * Obtain the eid of the base DN @@ -489,11 +582,11 @@ lsqlite3_search_bytree(struct ldb_module * module, " FROM ldb_attr_DN\n" " WHERE attr_value = %Q;", pBaseDN)) == SQLITE_DONE) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); return 0; } else if (ret != SQLITE_OK) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); return -1; } @@ -508,13 +601,7 @@ lsqlite3_search_bytree(struct ldb_module * module, " WHERE 1;");/* avoid a schema change with WHERE 1 */ /* Initially, we don't know what the requested attributes are */ - if (attrs == NULL) { - /* but they didn't give us any so we'll retrieve all of 'em */ - pResultAttrList = ""; - } else { - /* Discover the list of attributes */ - pResultAttrList = NULL; - } + pResultAttrList = NULL; /* Insert the list of requested attributes into this table */ for (pRequestedAttrs = (const char * const *) attrs; @@ -544,7 +631,7 @@ lsqlite3_search_bytree(struct ldb_module * module, if (pResultAttrList == NULL) { /* ... then we'll use the result attribute table */ pResultAttrList = - " AND av.attr_name IN\n" + " AND upper(av.attr_name) IN\n" " (SELECT attr_name\n" " FROM " RESULT_ATTR_TABLE ") "; } @@ -558,7 +645,7 @@ lsqlite3_search_bytree(struct ldb_module * module, /* * Create a table of unique attribute names for our extra table list */ - if ((ret = parsetree_to_attrlist(lsqlite3, pTree)) != 0) { + if ((ret = parsetree_to_attrlist(module, pTree)) != 0) { ret = -1; goto cleanup; } @@ -581,22 +668,31 @@ lsqlite3_search_bytree(struct ldb_module * module, " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" - " FROM ldb_entry AS entry,\n" - " ldb_attribute_values AS av\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + " %s\n" + " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry,\n" - " ldb_descendants\n" - " WHERE ldb_descendants.aeid = %lld\n" - " AND ldb_entry.eid = ldb_descendants.deid\n" - " AND ldb_entry.eid IN\n%s\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.tree_key >=\n" + " (SELECT tree_key\n" + " FROM ldb_entry\n" + " WHERE eid = %lld)\n" + " AND ldb_entry.tree_key <\n" + " (SELECT base160_next(tree_key)\n" + " FROM ldb_entry\n" + " WHERE eid = %lld)\n" + " AND ldb_entry.eid IN\n(%s)\n" " )\n" - " AND av.eid = entry.eid\n" - " %s\n" - " ORDER BY av.eid, av.attr_name;", + " ORDER BY entry.tree_key DESC,\n" + " COALESCE(av.attr_name, '');", + pResultAttrList, + eid, eid, - pSqlConstraints, - pResultAttrList); + pSqlConstraints); break; case LDB_SCOPE_BASE: @@ -605,20 +701,23 @@ lsqlite3_search_bytree(struct ldb_module * module, " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" - " FROM ldb_entry AS entry,\n" - " ldb_attribute_values AS av\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + " %s\n" + " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry\n" " WHERE ldb_entry.eid = %lld\n" - " AND ldb_entry.eid IN\n%s\n" + " AND ldb_entry.eid IN\n(%s)\n" " )\n" - " AND av.eid = entry.eid\n" - " %s\n" - " ORDER BY av.eid, av.attr_name;", + " ORDER BY entry.tree_key DESC,\n" + " COALESCE(av.attr_name, '');", + pResultAttrList, eid, - pSqlConstraints, - pResultAttrList); + pSqlConstraints); break; case LDB_SCOPE_ONELEVEL: @@ -627,21 +726,37 @@ lsqlite3_search_bytree(struct ldb_module * module, " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" - " FROM ldb_entry AS entry,\n" - " ldb_attribute_values AS av\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + " %s\n" + " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry AS pchild\n" - " WHERE ldb_entry.eid = pchild.eid\n" - " AND pchild.peid = %lld\n" - " AND ldb_entry.eid IN\n%s\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.tree_key >=\n" + " (SELECT tree_key\n" + " FROM ldb_entry\n" + " WHERE eid = %lld)\n" + " AND ldb_entry.tree_key <\n" + " (SELECT base160_next(tree_key)\n" + " FROM ldb_entry\n" + " WHERE eid = %lld)\n" + " AND length(ldb_entry.tree_key) =\n" + " (SELECT length(tree_key) + 4\n" + " FROM ldb_entry\n" + " WHERE eid = %lld)\n" + " AND ldb_entry.eid IN\n(%s)\n" " )\n" - " AND av.eid = entry.eid\n" - " %s\n" - " ORDER BY av.eid, av.attr_name;\n", + + " ORDER BY entry.tree_key DESC,\n" + " COALESCE(av.attr_name, '');\n", + pResultAttrList, + eid, + eid, eid, - pSqlConstraints, - pResultAttrList); + pSqlConstraints); break; } @@ -650,7 +765,7 @@ lsqlite3_search_bytree(struct ldb_module * module, goto cleanup; } - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_SEARCH) { printf("%s\n", pSql); } @@ -697,19 +812,22 @@ lsqlite3_search_bytree(struct ldb_module * module, pAttrValue = sqlite3_column_text(pStmt, 3); /* Add this result to the result set */ - if ((ret = add_msg_attr(hTalloc, - eid, - pDN, - pAttrName, - pAttrValue, - prevEID, - &allocated, - pppRes)) != 0) { + if (add_msg_attr(hTalloc, + eid, + pDN, + pAttrName, + pAttrValue, + prevEID, + &allocated, + pppRes) != 0) { (void) sqlite3_finalize(pStmt); ret = -1; break; } + + /* Save the most recent EID */ + prevEID = eid; } } @@ -750,7 +868,7 @@ lsqlite3_search_bytree(struct ldb_module * module, sqlite3_free(pSql); /* End the transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); + UNLOCK_DB(module, "rollback"); /* Were there any results? */ if (ret != 0 || allocated == 0) { @@ -793,6 +911,17 @@ lsqlite3_search(struct ldb_module * module, int ret; struct ldb_parse_tree * pTree; + /* Handle tdb specials */ + if (pBaseDN != NULL && *pBaseDN == '@') { +#warning "handle tdb specials" + return 0; + } + + /* Handle the special case of requesting all */ + if (pExpression != NULL && *pExpression == '\0') { + pExpression = "dn=*"; + } + /* Parse the filter expression into a tree we can work with */ if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { return -1; @@ -816,33 +945,48 @@ lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) { long long eid; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* ignore ltdb specials */ - if (msg->dn[0] == '@') { - return 0; - } + /* See if this is an ltdb special */ + if (*msg->dn == '@') { + /* Yup. We handle a few of these and ignore others */ + if (strcmp(msg->dn, "@SUBCLASSES") == 0) { +#warning "insert subclasses into object class tree" + } + + if (strcmp(msg->dn, "@INDEXLIST") == 0) { + /* explicitly ignored */ + return 0; + } + + /* Others are implicitly ignored */ + return 0; + } + /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + if (LOCK_DB(module, "transaction") < 0) { + return -1; + } /* * Build any portions of the directory tree that don't exist. If the * final component already exists, it's an error. */ if (new_dn(module, msg->dn, &eid) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + UNLOCK_DB(module, "rollback"); return -1; } /* Add attributes to this new entry */ if (msg_to_sql(module, msg, eid, FALSE) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + UNLOCK_DB(module, "rollback"); return -1; } /* Everything worked. Commit it! */ - QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + if (UNLOCK_DB(module, "transaction") < 0) { + UNLOCK_DB(module, "rollback"); + return -1; + } return 0; } @@ -856,13 +1000,15 @@ lsqlite3_modify(struct ldb_module * module, long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; - /* ignore ltdb specials */ - if (msg->dn[0] == '@') { - return 0; - } - + /* ignore ltdb specials */ + if (*msg->dn == '@') { + return 0; + } + /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + if (LOCK_DB(module, "transaction") < 0) { + return -1; + } /* Case-fold the DN so we can compare it to what's in the database */ pDN = ldb_dn_fold(module->ldb, msg->dn, @@ -879,26 +1025,38 @@ lsqlite3_modify(struct ldb_module * module, /* Apply the message attributes */ if (msg_to_sql(module, msg, eid, TRUE) != 0) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + UNLOCK_DB(module, "rollback"); return -1; } /* Everything worked. Commit it! */ - QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;"); + if (UNLOCK_DB(module, "transaction") < 0) { + UNLOCK_DB(module, "rollback"); + return -1; + } return 0 ; } /* obtain a named lock */ static int -lsqlite3_lock(struct ldb_module *module, - const char *lockname) +lsqlite3_lock(struct ldb_module * module, + const char * lockname) { + struct lsqlite3_private * lsqlite3 = module->private_data; + if (lockname == NULL) { return -1; } - /* TODO implement a local locking mechanism here */ + if (strcmp(lockname, "transaction") == 0) { + if (lsqlite3->lock_count == 0) { + if (query_norows(lsqlite3, "BEGIN EXCLUSIVE;") != 0) { + return -1; + } + } + ++lsqlite3->lock_count; + } return 0; } @@ -908,11 +1066,23 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname) { + struct lsqlite3_private * lsqlite3 = module->private_data; + if (lockname == NULL) { return -1; } - /* TODO implement a local locking mechanism here */ + if (strcmp(lockname, "transaction") == 0) { + if (lsqlite3->lock_count == 1) { + if (query_norows(lsqlite3, "COMMIT;") != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + } + } else if (lsqlite3->lock_count > 0) { + --lsqlite3->lock_count; + } + } else if (strcmp(lockname, "rollback") == 0) { + query_norows(lsqlite3, "ROLLBACK;"); + } return 0; } @@ -959,37 +1129,20 @@ initialize(struct lsqlite3_private *lsqlite3, "(" " eid INTEGER PRIMARY KEY," " peid INTEGER REFERENCES ldb_entry," - " dn TEXT UNIQUE," + " dn TEXT UNIQUE NOT NULL," + " tree_key TEXT UNIQUE," + " max_child_num INTEGER DEFAULT 0," " create_timestamp INTEGER," " modify_timestamp INTEGER" ");" - /* - * The purpose of the descendant table is to support the - * subtree search feature. For each LDB entry with a unique - * ID (AEID), this table contains the unique identifiers - * (DEID) of the descendant entries. - * - * For evern entry in the directory, a row exists in this - * table for each of its ancestors including itself. The - * size of the table depends on the depth of each entry. In - * the worst case, if all the entries were at the same - * depth, the number of rows in the table is O(nm) where - * n is the number of nodes in the directory and m is the - * depth of the tree. - */ - "CREATE TABLE ldb_descendants " - "( " - " aeid INTEGER REFERENCES ldb_entry," - " deid INTEGER REFERENCES ldb_entry" - ");" - - "CREATE TABLE ldb_object_classes" "(" " class_name TEXT PRIMARY KEY," - " tree_key TEXT UNIQUE" + " parent_class_name TEXT," + " tree_key TEXT UNIQUE," + " max_child_num INTEGER DEFAULT 0" ");" /* @@ -1018,8 +1171,8 @@ initialize(struct lsqlite3_private *lsqlite3, */ "CREATE TABLE ldb_attr_DN" "(" - " eid INTEGER REFERENCES ldb_entry," - " attr_value TEXT" + " eid INTEGER PRIMARY KEY REFERENCES ldb_entry," + " attr_value TEXT" ");" @@ -1036,8 +1189,16 @@ initialize(struct lsqlite3_private *lsqlite3, /* * Indexes */ + "CREATE INDEX ldb_entry_tree_key_idx " + " ON ldb_entry (tree_key);" + + "CREATE INDEX ldb_attribute_values_eid_idx " + " ON ldb_attribute_values (eid);" + "CREATE INDEX ldb_attr_DN_attr_value_idx " + " ON ldb_attr_DN (attr_value);" + /* * Triggers */ @@ -1047,10 +1208,23 @@ initialize(struct lsqlite3_private *lsqlite3, " ON ldb_entry" " FOR EACH ROW" " BEGIN" + " UPDATE ldb_entry" " SET create_timestamp = strftime('%s', 'now')," " modify_timestamp = strftime('%s', 'now')" - " WHERE eid = new.eid;" + " ," + " tree_key = COALESCE(tree_key, " + " (" + " SELECT tree_key || " + " (SELECT base160(max_child_num + 1)" + " FROM ldb_entry" + " WHERE eid = new.peid)" + " FROM ldb_entry " + " WHERE eid = new.peid " + " ));" + " UPDATE ldb_entry " + " SET max_child_num = max_child_num + 1" + " WHERE eid = new.peid;" " END;" "CREATE TRIGGER ldb_entry_update_tr" @@ -1063,15 +1237,36 @@ initialize(struct lsqlite3_private *lsqlite3, " WHERE eid = old.eid;" " END;" + "CREATE TRIGGER ldb_object_classes_insert_tr" + " AFTER INSERT" + " ON ldb_object_classes" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_object_classes" + " SET tree_key = COALESCE(tree_key, " + " (" + " SELECT tree_key || " + " (SELECT base160(max_child_num + 1)" + " FROM ldb_object_classes" + " WHERE class_name = " + " new.parent_class_name)" + " FROM ldb_object_classes " + " WHERE class_name = new.parent_class_name " + " ));" + " UPDATE ldb_object_classes " + " SET max_child_num = max_child_num + 1" + " WHERE class_name = new.parent_class_name;" + " END;" + /* * Table initialization */ /* The root node */ "INSERT INTO ldb_entry " - " (eid, peid, dn) " + " (eid, peid, dn, tree_key) " " VALUES " - " (0, NULL, '');" + " (0, NULL, '', '0001');" /* And the root node "dn" attribute */ "INSERT INTO ldb_attr_DN " @@ -1079,6 +1274,11 @@ initialize(struct lsqlite3_private *lsqlite3, " VALUES " " (0, '');" + "INSERT INTO ldb_object_classes " + " (class_name, tree_key) " + " VALUES " + " ('TOP', '0001');" + ; /* Skip protocol indicator of url */ @@ -1095,18 +1295,58 @@ initialize(struct lsqlite3_private *lsqlite3, } /* In case this is a new database, enable auto_vacuum */ - QUERY_NOROWS(lsqlite3, FALSE, "PRAGMA auto_vacuum=1;"); + if (query_norows(lsqlite3, "PRAGMA auto_vacuum=1;") != 0) { + return -1; + } + /* Establish a busy timeout of 30 seconds */ + if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, + 30000)) != SQLITE_OK) { + return ret; + } + + /* Create a function, callable from sql, to increment a tree_key */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160_next", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160next_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } + + /* Create a function, callable from sql, to convert int to base160 */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } + /* Begin a transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;"); + if ((ret = query_norows(lsqlite3, "BEGIN EXCLUSIVE;")) != 0) { + return ret; + } /* Determine if this is a new database. No tables means it is. */ - QUERY_INT(lsqlite3, - queryInt, - TRUE, - "SELECT COUNT(*)\n" - " FROM sqlite_master\n" - " WHERE type = 'table';"); + if (query_int(lsqlite3, + &queryInt, + "SELECT COUNT(*)\n" + " FROM sqlite_master\n" + " WHERE type = 'table';") != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return -1; + } if (queryInt == 0) { /* @@ -1116,7 +1356,7 @@ initialize(struct lsqlite3_private *lsqlite3, pTail != NULL && *pTail != '\0'; ) { - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_INIT) { printf("Execute first query in:\n%s\n", pTail); } @@ -1129,7 +1369,13 @@ initialize(struct lsqlite3_private *lsqlite3, (ret = sqlite3_step(stmt)) != SQLITE_DONE || (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + if (lsqlite3_debug & SQLITE3_DEBUG_INIT) { + printf("%s\n", + sqlite3_errmsg(lsqlite3->sqlite)); + printf("pTail = [%s]\n", pTail); + } + + query_norows(lsqlite3, "ROLLBACK;"); (void) sqlite3_close(lsqlite3->sqlite); return ret; } @@ -1141,13 +1387,14 @@ initialize(struct lsqlite3_private *lsqlite3, if (query_int(lsqlite3, &queryInt, "SELECT " - " (SELECT COUNT(*) = 3" + " (SELECT COUNT(*) = 4" " FROM sqlite_master " " WHERE type = 'table' " " AND name IN " " (" " 'ldb_entry', " - " 'ldb_descendants', " + " 'ldb_attr_DN', " + " 'ldb_attr_OBJECTCLASS', " " 'ldb_object_classes' " " ) " " ) " @@ -1160,7 +1407,7 @@ initialize(struct lsqlite3_private *lsqlite3, queryInt != 1) { /* It's not one that we created. See ya! */ - QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;"); + query_norows(lsqlite3, "ROLLBACK;"); (void) sqlite3_close(lsqlite3->sqlite); return SQLITE_MISUSE; } @@ -1170,26 +1417,37 @@ initialize(struct lsqlite3_private *lsqlite3, * Create a temporary table to hold attributes requested in the result * set of a search. */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TEMPORARY TABLE " RESULT_ATTR_TABLE "\n" - " (\n" - " attr_name TEXT PRIMARY KEY\n" - " );"); - + query_norows(lsqlite3, "DROP TABLE " RESULT_ATTR_TABLE ";\n"); + if ((ret = + query_norows(lsqlite3, + "CREATE " TEMPTAB " TABLE " RESULT_ATTR_TABLE "\n" + " (\n" + " attr_name TEXT PRIMARY KEY\n" + " );")) != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return ret; + } + /* * Create a temporary table to hold the attributes used by filters * during a search. */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TEMPORARY TABLE " FILTER_ATTR_TABLE "\n" - " (\n" - " attr_name TEXT PRIMARY KEY\n" - " );"); - + query_norows(lsqlite3, "DROP TABLE " FILTER_ATTR_TABLE ";\n"); + if ((ret = + query_norows(lsqlite3, + "CREATE " TEMPTAB " TABLE " FILTER_ATTR_TABLE "\n" + " (\n" + " attr_name TEXT PRIMARY KEY\n" + " );")) != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return ret; + } + /* Commit the transaction */ - QUERY_NOROWS(lsqlite3, FALSE, "COMMIT;"); + if ((ret = query_norows(lsqlite3, "COMMIT;")) != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return ret; + } return SQLITE_OK; } @@ -1224,7 +1482,14 @@ query_norows(const struct lsqlite3_private *lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; + double t0; + double t1; + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + /* Begin access to variable argument list */ va_start(args, pSql); @@ -1233,10 +1498,6 @@ query_norows(const struct lsqlite3_private *lsqlite3, return -1; } - if (lsqlite3_debug) { - printf("%s\n", p); - } - /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, @@ -1287,6 +1548,15 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* All done with variable argument list */ va_end(args); + gettimeofday(&tv, NULL); + t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + printf("%1.6lf %s\n%s\n\n", t1 - t0, + ret == 0 ? "SUCCESS" : "FAIL", + p); + } + /* Free the memory we allocated for our query string */ sqlite3_free(p); @@ -1314,7 +1584,14 @@ query_int(const struct lsqlite3_private * lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; + double t0; + double t1; + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + /* Begin access to variable argument list */ va_start(args, pSql); @@ -1323,7 +1600,7 @@ query_int(const struct lsqlite3_private * lsqlite3, return SQLITE_NOMEM; } - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { printf("%s\n", p); } @@ -1376,6 +1653,15 @@ query_int(const struct lsqlite3_private * lsqlite3, /* All done with variable argument list */ va_end(args); + gettimeofday(&tv, NULL); + t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + printf("%1.6lf %s\n%s\n\n", t1 - t0, + ret == 0 ? "SUCCESS" : "FAIL", + p); + } + /* Free the memory we allocated for our query string */ sqlite3_free(p); @@ -1420,7 +1706,7 @@ add_msg_attr(void * hTalloc, if (eid != prevEID) { /* Yup. Add another result to the result array */ if ((x = talloc_realloc(hTalloc, - *pAllocated == 0 ? NULL : pppRes, + *pAllocated == 0 ? NULL : *pppRes, struct ldb_message *, *pAllocated + 1)) == NULL) { @@ -1429,81 +1715,99 @@ add_msg_attr(void * hTalloc, /* Save the new result list */ *pppRes = x; - + + /* Allocate a new result structure */ + if ((x = talloc(*pppRes, struct ldb_message)) == NULL) { + return -1; + } + + /* Save the new result */ + (*pppRes)[*pAllocated] = x; + + /* Steal the initial result and put it in its own context */ + talloc_steal(NULL, *pppRes); + /* We've allocated one more result */ - *pAllocated++; + ++*pAllocated; /* Ensure that the message is initialized */ msg = x; - msg->dn = NULL; + if ((msg->dn = talloc_strdup(msg, pDN)) == NULL) { + return -1; + } msg->num_elements = 0; msg->elements = NULL; msg->private_data = NULL; } else { /* Same EID. Point to the previous most-recent message */ - msg = *pppRes[*pAllocated - 1]; + msg = (*pppRes)[*pAllocated - 1]; } - /* - * Point to the most recent previous element. (If there are none, - * this will point to non-allocated memory, but the pointer will never - * be dereferenced.) - */ - el = &msg->elements[msg->num_elements - 1]; + if (pAttrName != NULL && pAttrValue != NULL) { + /* + * Point to the most recent previous element. (If there are none, + * this will point to non-allocated memory, but the pointer will + * never be dereferenced.) + */ + el = &msg->elements[msg->num_elements - 1]; - /* See if the most recent previous element has the same attr_name */ - if (msg->num_elements == 0 || strcmp(el->name, pAttrName) != 0) { + /* + * See if the most recent previous element has the same attr_name + */ + if (msg->num_elements == 0 || strcmp(el->name, pAttrName) != 0) { /* It's a new attr_name. Allocate another message element */ if ((el = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements + 1)) == NULL) { - return -1; + return -1; } /* Save the new element */ msg->elements = el; - /* There's now one additional element */ - msg->num_elements++; - /* Save the attribute name */ if ((el->name = talloc_strdup(msg->elements, pAttrName)) == NULL) { - return -1; + return -1; } + /* There's now one additional element */ + msg->num_elements++; + /* No flags */ el->flags = 0; /* Initialize number of attribute values for this type */ el->num_values = 0; el->values = NULL; - } + } - /* Increase the value array size by 1 */ - if ((el->values = - talloc_realloc(el, - el->num_values == 0 ? NULL : el->values, - struct ldb_val, - el->num_values)) == NULL) { + /* Increase the value array size by 1 */ + if ((el->values = + talloc_realloc(el, + el->num_values == 0 ? NULL : el->values, + struct ldb_val, + el->num_values + 1)) == NULL) { return -1; - } + } - /* Save the new attribute value length */ - el->values[el->num_values].length = strlen(pAttrValue) + 1; + /* Save the new attribute value length */ + el->values[el->num_values].length = strlen(pAttrValue); - /* Copy the new attribute value */ - if (talloc_memdup(el->values[el->num_values].data, - pAttrValue, - el->values[el->num_values].length) == NULL) { + /* Copy the new attribute value */ + if ((el->values[el->num_values].data = + talloc_memdup(el->values, + pAttrValue, + el->values[el->num_values].length)) == NULL) { return -1; - } + } - /* We now have one additional value of this type */ - el->num_values++; + /* We now have one additional value of this type */ + el->num_values++; + } return 0; } @@ -1514,6 +1818,7 @@ parsetree_to_sql(struct ldb_module *module, const struct ldb_parse_tree *t) { int i; + char * pDN; char * child; char * p; char * ret = NULL; @@ -1548,7 +1853,7 @@ parsetree_to_sql(struct ldb_module *module, child = ret; ret = talloc_asprintf(hTalloc, - "(\n" + "SELECT * FROM (\n" "%s\n" ")\n", child); @@ -1556,11 +1861,9 @@ parsetree_to_sql(struct ldb_module *module, return ret; case LDB_OP_OR: - child = - parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[0]); + ret = parsetree_to_sql(module, + hTalloc, + t->u.list.elements[0]); for (i = 1; i < t->u.list.num_elements; i++) { child = @@ -1576,7 +1879,7 @@ parsetree_to_sql(struct ldb_module *module, } child = ret; ret = talloc_asprintf(hTalloc, - "(\n" + "SELECT * FROM (\n" "%s\n" ")\n", child); @@ -1590,11 +1893,9 @@ parsetree_to_sql(struct ldb_module *module, hTalloc, t->u.not.child); ret = talloc_asprintf(hTalloc, - "(\n" " SELECT eid\n" " FROM ldb_entry\n" - " WHERE eid NOT IN %s\n" - ")\n", + " WHERE eid NOT IN (%s)\n", child); talloc_free(child); return ret; @@ -1621,15 +1922,13 @@ parsetree_to_sql(struct ldb_module *module, * eid corresponding to all values in the specified attribute * table. */ - if ((p = sqlite3_mprintf("(\n" - " SELECT eid\n" - " FROM ldb_attr_%q\n" - ")\n", + if ((p = sqlite3_mprintf(" SELECT eid\n" + " FROM ldb_attr_%q\n", pAttrName)) == NULL) { return NULL; } - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { printf("%s\n", p); } @@ -1642,41 +1941,55 @@ parsetree_to_sql(struct ldb_module *module, * that are subclasses as well. */ if ((p = sqlite3_mprintf( - "(\n" " SELECT eid\n" " FROM ldb_attr_OBJECTCLASS\n" - " WHERE attr_name IN\n" + " WHERE attr_value IN\n" " (SELECT class_name\n" - " FROM ldb_objectclasses\n" + " FROM ldb_object_classes\n" " WHERE tree_key GLOB\n" " (SELECT tree_key\n" - " FROM ldb_objectclasses\n" - " WHERE class_name = %Q) || '*')\n" - ")\n", + " FROM ldb_object_classes\n" + " WHERE class_name = upper(%Q)) " + " || '*')\n", t->u.simple.value.data)) == NULL) { return NULL; } - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { printf("%s\n", p); } ret = talloc_strdup(hTalloc, p); sqlite3_free(p); + } else if (strcasecmp(t->u.simple.attr, "dn") == 0) { + pDN = ldb_dn_fold(module->ldb, t->u.simple.value.data, + module, case_fold_attr_required); + if ((p = sqlite3_mprintf(" SELECT eid\n" + " FROM ldb_attr_%q\n" + " WHERE attr_value = %Q\n", + pAttrName, + pDN)) == NULL) { + return NULL; + } + + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + printf("%s\n", p); + } + + ret = talloc_strdup(hTalloc, p); + sqlite3_free(p); } else { /* A normal query. */ - if ((p = sqlite3_mprintf("(\n" - " SELECT eid\n" + if ((p = sqlite3_mprintf(" SELECT eid\n" " FROM ldb_attr_%q\n" - " WHERE attr_value = %Q\n" - ")\n", + " WHERE attr_value = %Q\n", pAttrName, t->u.simple.value.data)) == NULL) { return NULL; } - if (lsqlite3_debug) { + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { printf("%s\n", p); } @@ -1689,10 +2002,11 @@ parsetree_to_sql(struct ldb_module *module, static int -parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, +parsetree_to_attrlist(struct ldb_module *module, const struct ldb_parse_tree * t) { int i; + struct lsqlite3_private * lsqlite3 = module->private_data; switch(t->operation) { case LDB_OP_SIMPLE: @@ -1704,14 +2018,14 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, case LDB_OP_AND: if (parsetree_to_attrlist( - lsqlite3, + module, t->u.list.elements[0]) != 0) { return -1; } for (i = 1; i < t->u.list.num_elements; i++) { if (parsetree_to_attrlist( - lsqlite3, + module, t->u.list.elements[i]) != 0) { return -1; } @@ -1721,14 +2035,14 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, case LDB_OP_OR: if (parsetree_to_attrlist( - lsqlite3, + module, t->u.list.elements[0]) != 0) { return -1; } for (i = 1; i < t->u.list.num_elements; i++) { if (parsetree_to_attrlist( - lsqlite3, + module, t->u.list.elements[i]) != 0) { return -1; } @@ -1737,7 +2051,7 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3, return 0; case LDB_OP_NOT: - if (parsetree_to_attrlist(lsqlite3, + if (parsetree_to_attrlist(module, t->u.not.child) != 0) { return -1; } @@ -1929,6 +2243,25 @@ msg_to_sql(struct ldb_module * module, el->name, el->values[j].data); + + /* Is this a special "objectclass"? */ + if (strcasecmp(pAttrName, + "objectclass") != 0) { + /* Nope. */ + break; + } + + /* Handle special "objectclass" type */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT OR IGNORE " + " INTO ldb_object_classes " + " (class_name, " + " parent_class_name) " + " VALUES " + " (upper(%Q), 'TOP');", + ldb_casefold(module, + el->values[j].data)); break; case LDB_FLAG_MOD_REPLACE: @@ -1991,11 +2324,20 @@ new_dn(struct ldb_module * module, char * pPartialDN; long long eid; long long peid; + double t0 = 0; + double t1 = 0; + struct timeval tv; + struct timezone tz; struct ldb_dn * pExplodedDN; struct ldb_dn_component * pComponent; struct ldb_context * ldb = module->ldb; struct lsqlite3_private * lsqlite3 = module->private_data; + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, &tz); + t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + } + /* Explode and normalize the DN */ if ((pExplodedDN = ldb_explode_dn(ldb, @@ -2005,17 +2347,34 @@ new_dn(struct ldb_module * module, return -1; } + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + printf("%1.6lf loc 1\n", t1 - t0); + t0 = t1; + } + /* Allocate a string to hold the partial DN of each component */ if ((pPartialDN = talloc_strdup(ldb, "")) == NULL) { return -1; } /* For each component of the DN (starting with the last one)... */ +#warning "convert this loop to recursive, and search backwards instead" eid = 0; + for (nComponent = pExplodedDN->comp_num - 1, bFirst = TRUE; nComponent >= 0; nComponent--, bFirst = FALSE) { + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 2\n", t1 - t0); + t0 = t1; + } + /* Point to the component */ pComponent = pExplodedDN->components[nComponent]; @@ -2028,12 +2387,28 @@ new_dn(struct ldb_module * module, return -1; } + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 3\n", t1 - t0); + t0 = t1; + } + /* No need for the old partial DN any more */ talloc_free(pPartialDN); /* Save the new partial DN */ pPartialDN = p; + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 4\n", t1 - t0); + t0 = t1; + } + /* * Ensure that an entry is in the ldb_entry table for this * component. Any component other than the last one @@ -2053,45 +2428,50 @@ new_dn(struct ldb_module * module, /* Save the parent EID */ peid = eid; + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 5\n", t1 - t0); + t0 = t1; + } + /* Get the EID of the just inserted row */ - eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); - - /* - * Popoulate the descendant table - */ - - /* This table has an entry for itself as well as descendants */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_descendants " - " (aeid, deid) " - " VALUES " - " (%lld, %lld);", - eid, eid); + QUERY_INT(lsqlite3, + eid, + FALSE, + "SELECT eid " + " FROM ldb_entry " + " WHERE dn = %Q;", + pPartialDN); + + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 8\n", t1 - t0); + t0 = t1; + } - /* Now insert rows for all of our ancestors */ + /* Also add DN attribute */ QUERY_NOROWS(lsqlite3, FALSE, - "INSERT INTO ldb_descendants " - " (aeid, deid) " - " SELECT aeid, %lld " - " FROM ldb_descendants " - " WHERE aeid = %lld;", - eid, peid); - - /* If this is the final component, also add DN attribute */ - if (nComponent == 0) { - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_attr_DN\n" - " (eid, attr_value) " - " VALUES " - " (%lld, %Q);", - nComponent == 0 ? "" : "OR IGNORE", - eid, pPartialDN); - } + "INSERT %s INTO ldb_attr_DN\n" + " (eid, attr_value) " + " VALUES " + " (%lld, %Q);", + nComponent == 0 ? "" : "OR IGNORE", + eid, pPartialDN); } + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 9\n", t1 - t0); + t0 = t1; + } + /* Give 'em what they came for! */ *pEID = eid; @@ -2132,9 +2512,207 @@ new_attr(struct ldb_module * module, " attr_value TEXT\n" ");", pAttrName); + + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE INDEX ldb_attr_%q_eid_idx\n" + " ON ldb_attr_%q (eid);", + pAttrName, + pAttrName); + + QUERY_NOROWS(lsqlite3, + FALSE, + "CREATE INDEX ldb_attr_%q_attr_value_idx " + " ON ldb_attr_%q (attr_value);", + pAttrName, + pAttrName); + } return 0; } +static unsigned char base160tab[161] = { + 48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */ + 58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */ + 73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 , /* I-R */ + 83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,97 ,98 , /* S-Z , a-b */ + 99 ,100,101,102,103,104,105,106,107,108, /* c-l */ + 109,110,111,112,113,114,115,116,117,118, /* m-v */ + 119,120,121,122,160,161,162,163,164,165, /* w-z, latin1 */ + 166,167,168,169,170,171,172,173,174,175, /* latin1 */ + 176,177,178,179,180,181,182,183,184,185, /* latin1 */ + 186,187,188,189,190,191,192,193,194,195, /* latin1 */ + 196,197,198,199,200,201,202,203,204,205, /* latin1 */ + 206,207,208,209,210,211,212,213,214,215, /* latin1 */ + 216,217,218,219,220,221,222,223,224,225, /* latin1 */ + 226,227,228,229,230,231,232,233,234,235, /* latin1 */ + 236,237,238,239,240,241,242,243,244,245, /* latin1 */ + 246,247,248,249,250,251,252,253,254,255, /* latin1 */ + '\0' +}; + + +/* + * base160() + * + * Convert an unsigned long integer into a base160 representation of the + * number. + * + * Parameters: + * val -- + * value to be converted + * + * result -- + * character array, 5 bytes long, into which the base160 representation + * will be placed. The result will be a four-digit representation of the + * number (with leading zeros prepended as necessary), and null + * terminated. + * + * Returns: + * Nothing + */ +static void +base160_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + long long val; + char result[5]; + + val = sqlite3_value_int64(argv[0]); + + for (i = 3; i >= 0; i--) { + + result[i] = base160tab[val % 160]; + val /= 160; + } + + result[4] = '\0'; + + sqlite3_result_text(hContext, result, -1, SQLITE_TRANSIENT); +} + + +/* + * base160next_sql() + * + * This function enhances sqlite by adding a "base160_next()" function which is + * accessible via queries. + * + * Retrieve the next-greater number in the base160 sequence for the terminal + * tree node (the last four digits). Only one tree level (four digits) is + * operated on. + * + * Input: + * A character string: either an empty string (in which case no operation is + * performed), or a string of base160 digits with a length of a multiple of + * four digits. + * + * Output: + * Upon return, the trailing four digits (one tree level) will have been + * incremented by 1. + */ +static void +base160next_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + int len; + unsigned char * pTab; + unsigned char * pBase160 = + strdup(sqlite3_value_text(argv[0])); + unsigned char * pStart = pBase160; + + /* + * We need a minimum of four digits, and we will always get a multiple + * of four digits. + */ + if (pBase160 != NULL && + (len = strlen(pBase160)) >= 4 && + len % 4 == 0) { + + if (pBase160 == NULL) { + + sqlite3_result_null(hContext); + return; + } + + pBase160 += strlen(pBase160) - 1; + + /* We only carry through four digits: one level in the tree */ + for (i = 0; i < 4; i++) { + + /* What base160 value does this digit have? */ + pTab = strchr(base160tab, *pBase160); + + /* Is there a carry? */ + if (pTab < base160tab + sizeof(base160tab) - 1) { + + /* + * Nope. Just increment this value and we're + * done. + */ + *pBase160 = *++pTab; + break; + } else { + + /* + * There's a carry. This value gets + * base160tab[0], we decrement the buffer + * pointer to get the next higher-order digit, + * and continue in the loop. + */ + *pBase160-- = base160tab[0]; + } + } + + sqlite3_result_text(hContext, + pStart, + strlen(pStart), + free); + } else { + sqlite3_result_value(hContext, argv[0]); + if (pBase160 != NULL) { + free(pBase160); + } + } +} + + +#ifdef DEBUG_LOCKS +static int lock_debug(struct ldb_module * module, + const char * lockname, + const char * pFileName, + int linenum) +{ + int ret; + struct lsqlite3_private * lsqlite3 = module->private_data; + + printf("%s(%d): LOCK (%d) ", + pFileName, linenum, lsqlite3->lock_count); + ret = lsqlite3_lock(module, lockname); + printf("got %d\n", ret); + + return ret; +} + + +static int unlock_debug(struct ldb_module * module, + const char * lockname, + const char * pFileName, + int linenum) +{ + int ret; + struct lsqlite3_private * lsqlite3 = module->private_data; + + ret = lsqlite3_unlock(module, lockname); + printf("%s(%d): UNLOCK (%d) got %d\n", + pFileName, linenum, lsqlite3->lock_count, ret); + + return ret; +} +#endif diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 192e28f3dc..3d3c63397b 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -1,10 +1,10 @@ #include struct lsqlite3_private { - char **options; - const char *basedn; - sqlite3 * sqlite; - int lock_count; + char ** options; + const char * basedn; + sqlite3 * sqlite; + int lock_count; }; void diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index c44351c543..08dc50de08 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -12,130 +12,160 @@ SELECT 'LDB' AS database_type, '1.0' AS version; - -- ------------------------------------------------------ - -- Schema - /* - * The entry table holds the information about an entry. This - * table is used to obtain the EID of the entry and to support - * scope="one" and scope="base". The parent and child table - * is included in the entry table since all the other - * attributes are dependent on EID. + * Get the next USN value with: + * BEGIN EXCLUSIVE; + * UPDATE usn SET value = value + 1; + * SELECT value FROM usn; + * COMMIT; */ - CREATE TABLE ldb_entry + CREATE TABLE usn ( - -- Unique identifier of this LDB entry - eid INTEGER PRIMARY KEY, - - -- Unique identifier of the parent LDB entry - peid INTEGER REFERENCES ldb_entry, - - -- Distinguished name of this entry - dn TEXT, - - -- Time when the entry was created - create_timestamp INTEGER, - - -- Time when the entry was last modified - modify_timestamp INTEGER + value INTEGER ); - - /* - * The purpose of the descendant table is to support the - * subtree search feature. For each LDB entry with a unique - * ID (AEID), this table contains the unique identifiers - * (DEID) of the descendant entries. - * - * For evern entry in the directory, a row exists in this - * table for each of its ancestors including itself. The size - * of the table depends on the depth of each entry. In the - * worst case, if all the entries were at the same depth, the - * number of rows in the table is O(nm) where n is the number - * of nodes in the directory and m is the depth of the tree. - */ - CREATE TABLE ldb_descendants + CREATE TABLE ldb_object ( - -- The unique identifier of the ancestor LDB entry - aeid INTEGER REFERENCES ldb_entry, - - -- The unique identifier of the descendant LDB entry - deid INTEGER REFERENCES ldb_entry - ); - - - CREATE TABLE ldb_object_classes - ( - -- Object classes are inserted into this table to track - -- their class hierarchy. 'top' is the top-level class - -- of which all other classes are subclasses. - class_name TEXT PRIMARY KEY, - - -- tree_key tracks the position of the class in - -- the hierarchy - tree_key TEXT UNIQUE + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT PRIMARY KEY, + + parent_tree_key TEXT, + dn TEXT, + + attr_name TEXT REFERENCES ldb_attributes, + attr_value TEXT, + + /* + * object_type can take on these values (to date): + * 1: object is a node of a DN + * 2: object is an attribute/value pair of its parent DN + */ + object_type INTEGER, + + /* + * if object_type is 1, the node can have children. + * this tracks the maximum previously assigned child + * number so we can generate a new unique tree key for + * a new child object. note that this is always incremented, + * so if children are deleted, this will not represent + * the _number_ of children. + */ + max_child_num INTEGER, + + /* + * Automatically maintained meta-data (a gift for metze) + */ + object_guid TEXT UNIQUE, + timestamp INTEGER, -- originating_time + invoke_id TEXT, -- GUID: originating_invocation_id + usn INTEGER, -- hyper: originating_usn + + /* do not allow duplicate name/value pairs */ + UNIQUE (parent_tree_key, attr_name, attr_value, object_type) ); - /* - * We keep a full listing of attribute/value pairs here - */ - CREATE TABLE ldb_attribute_values + CREATE TABLE ldb_attributes ( - eid INTEGER REFERENCES ldb_entry, - - attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME + attr_name TEXT PRIMARY KEY, + parent_tree_key TEXT, - attr_value TEXT - ); + objectclass_p BOOLEAN DEFAULT 0, + case_insensitive_p BOOLEAN DEFAULT 0, + wildcard_p BOOLEAN DEFAULT 0, + hidden_p BOOLEAN DEFAULT 0, + integer_p BOOLEAN DEFAULT 0, - /* - * There is one attribute table per searchable attribute. - */ -/* - CREATE TABLE ldb_attr_ATTRIBUTE_NAME - ( - -- The unique identifier of the LDB entry - eid INTEGER REFERENCES ldb_entry, - - -- Normalized attribute value - attr_value TEXT + /* tree_key is auto-generated by the insert trigger */ + tree_key TEXT, -- null if not a object/sub class + -- level 1 if an objectclass + -- level 1-n if a subclass + max_child_num INTEGER ); -*/ - -- ------------------------------------------------------ - -- Indexes + CREATE INDEX ldb_object_dn_idx + ON ldb_object (dn); + + CREATE INDEX ldb_attributes_tree_key_ids + ON ldb_attributes (tree_key); -- ------------------------------------------------------ - -- Triggers - CREATE TRIGGER ldb_entry_insert_tr + /* Gifts for metze. Automatically updated meta-data */ + CREATE TRIGGER ldb_object_insert_tr AFTER INSERT - ON ldb_entry + ON ldb_object FOR EACH ROW BEGIN - UPDATE ldb_entry - SET create_timestamp = strftime('%s', 'now'), - modify_timestamp = strftime('%s', 'now') - WHERE eid = new.eid; + UPDATE ldb_object + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_object + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0, + object_guid = random_guid(), + timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; END; - CREATE TRIGGER ldb_entry_update_tr + CREATE TRIGGER ldb_object_update_tr AFTER UPDATE - ON ldb_entry + ON ldb_object FOR EACH ROW BEGIN - UPDATE ldb_entry - SET modify_timestamp = strftime('%s', 'now') - WHERE eid = old.eid; + UPDATE usn SET value = value + 1; + UPDATE ldb_object + SET timestamp = strftime('%s', 'now'), + usn = (SELECT value FROM usn); + WHERE tree_key = new.tree_key; END; + CREATE TRIGGER ldb_attributes_insert_tr + AFTER INSERT + ON ldb_attributes + FOR EACH ROW + BEGIN + UPDATE ldb_attributes + SET max_child_num = max_child_num + 1 + WHERE tree_key = new.parent_tree_key; + UPDATE ldb_attributes + SET tree_key = + (SELECT + new.tree_key || + base160(SELECT max_child_num + FROM ldb_attributes + WHERE tree_key = + new.parent_tree_key)); + max_child_num = 0 + WHERE tree_key = new.tree_key; + END; + + -- ------------------------------------------------------ - -- Table initialization - /* We need an implicit 'top' level object class */ + /* Initialize usn */ + INSERT INTO usn (value) VALUES (0); + + /* Create root object */ + INSERT INTO ldb_object + (tree_key, parent_tree_key, + dn, + object_type, max_child_num) + VALUES ('', NULL, + '', + 1, 0); + + /* We need an implicit "top" level object class */ INSERT INTO ldb_attributes (attr_name, parent_tree_key) SELECT 'top', ''; @@ -146,13 +176,58 @@ -- ------------------------------------------------------ -/*** TESTS ***/ - /* * dn: o=University of Michigan,c=US * objectclass: organization * objectclass: domainRelatedObject */ +-- newDN +BEGIN; + +INSERT OR IGNORE INTO ldb_object + (parent_tree_key + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('', + 'c=US', + 'c', 'US', 1, 0); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('0001', + 'o=University of Michigan,c=US', + 'o', 'University of Michigan', 1, 0); + +-- newObjectClass +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'organization', 2, 0); + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('objectclass', '', 1); + +INSERT INTO ldb_object + (parent_tree_key, + dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', + NULL, + 'objectclass', 'domainRelatedObject', 2, 0); + +COMMIT; /* @@ -164,6 +239,48 @@ * seeAlso: * telephonenumber: +1 313 764-1817 */ +-- addAttrValuePair +BEGIN; + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'l', 'Ann Arbor, Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'st', 'Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'University of Michigan', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'o', 'UMICH', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'seeAlso', '', 2, 0); + +INSERT INTO ldb_object + (parent_tree_key, dn, + attr_name, attr_value, object_type, max_child_num) + VALUES ('00010001', NULL, + 'telephonenumber', '+1 313 764-1817', 2, 0); + +COMMIT; + +-- ---------------------------------------------------------------------- /* * dn: @ATTRIBUTES @@ -172,6 +289,44 @@ * ou: CASE_INSENSITIVE * dn: CASE_INSENSITIVE */ +-- newAttribute + +BEGIN; + +INSERT OR IGNORE INTO ldb_attributes + (attr_name, parent_tree_key, objectclass_p) + VALUES + ('uid', '', 0); + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 1, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'uid' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'cn' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'ou' + +UPDATE ldb_attributes + SET case_insensitive_p = 1, + wildcard_p = 0, + hidden_p = 0, + integer_p = 0 + WHERE attr_name = 'dn' + +-- ---------------------------------------------------------------------- /* * dn: @SUBCLASSES @@ -184,3 +339,25 @@ * organizationalPerson: OpenLDAPperson * user: computer */ +-- insertSubclass + +/* NOT YET UPDATED!!! * + + +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'domain', /* next_tree_key('top') */ '00010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'person', /* next_tree_key('top') */ '00010002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'domainDNS', /* next_tree_key('domain') */ '000100010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'organizationalPerson', /* next_tree_key('person') */ '000100020001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'fooPerson', /* next_tree_key('person') */ '000100020002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'user', /* next_tree_key('organizationalPerson') */ '0001000200010001'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002'; +INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key) + SELECT 'computer', /* next_tree_key('user') */ '0001000200010001'; + diff --git a/source4/lib/ldb/tests/test-sqlite3.sh b/source4/lib/ldb/tests/test-sqlite3.sh index cf443bb8a1..95babeac8d 100755 --- a/source4/lib/ldb/tests/test-sqlite3.sh +++ b/source4/lib/ldb/tests/test-sqlite3.sh @@ -1,7 +1,7 @@ #!/bin/sh -export LDB_URL="sqlite://sqltest.ldb" +export LDB_URL="sqlite:///var/tmp/test.ldb" rm -f sqltest.ldb diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 7c7164c785..aff1eaadda 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -64,6 +64,11 @@ static void add_records(struct ldb_context *ldb, struct ldb_message msg; int i; + if (ldb_lock(ldb, "transaction") != 0) { + printf("transaction lock failed\n"); + exit(1); + } + for (i=0;i Date: Wed, 22 Jun 2005 03:08:06 +0000 Subject: r7831: use cn=TEST as base of test DNs so we don't interfere with potentially real records (This used to be commit 2a426f654db668f4bfc899771dd11598e295b774) --- source4/lib/ldb/tests/init.ldif | 2 +- source4/lib/ldb/tests/slapd.conf | 4 +- source4/lib/ldb/tests/test-extended.sh | 14 ++--- source4/lib/ldb/tests/test-generic.sh | 8 +-- source4/lib/ldb/tests/test-modify.ldif | 2 +- source4/lib/ldb/tests/test.ldif | 102 ++++++++++++++++----------------- 6 files changed, 66 insertions(+), 66 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/init.ldif b/source4/lib/ldb/tests/init.ldif index 3b0eeffe2f..1e647e6521 100644 --- a/source4/lib/ldb/tests/init.ldif +++ b/source4/lib/ldb/tests/init.ldif @@ -1,4 +1,4 @@ -dn: o=University of Michigan,c=US +dn: o=University of Michigan,c=TEST objectclass: organization objectclass: domainRelatedObject l: Ann Arbor, Michigan diff --git a/source4/lib/ldb/tests/slapd.conf b/source4/lib/ldb/tests/slapd.conf index 61c8627e18..332b3f9063 100644 --- a/source4/lib/ldb/tests/slapd.conf +++ b/source4/lib/ldb/tests/slapd.conf @@ -17,11 +17,11 @@ allow update_anon bind_anon_dn #modulepath /usr/lib/ldap #moduleload back_bdb -defaultsearchbase "o=University of Michigan,c=US" +defaultsearchbase "o=University of Michigan,c=TEST" backend bdb database bdb -suffix "o=University of Michigan,c=US" +suffix "o=University of Michigan,c=TEST" directory tests/tmp/db index objectClass eq index uid eq diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index 93ac2db6bd..0bcb3ebcaa 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -5,32 +5,32 @@ echo "Running extended search tests" rm -f $LDB_URL cat < Date: Wed, 22 Jun 2005 03:09:25 +0000 Subject: r7832: missed one (This used to be commit 20c84f5c5219c6f306888771b56e0dfdeb8fd774) --- source4/lib/ldb/tests/photo.ldif | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/photo.ldif b/source4/lib/ldb/tests/photo.ldif index 24485f1203..53b24f0488 100644 --- a/source4/lib/ldb/tests/photo.ldif +++ b/source4/lib/ldb/tests/photo.ldif @@ -1,4 +1,4 @@ -dn: cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=US +dn: cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST changetype: modify add: photo photo:< tests/samba4.png -- cgit From 0eb6bc1257f5f3638d8ed524c61d0ab43c8c7f02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Jun 2005 03:10:40 +0000 Subject: r7833: changed ldbsearch and ldbedit to have command line syntax closer to ldapsearch. They look for an '=' in the first argument to see if it is a search expression, and if not then it does an 'all records' search (This used to be commit 91cc009fedefa7b263b345dfa511800e0f4f66a8) --- source4/lib/ldb/tests/test-generic.sh | 2 +- source4/lib/ldb/tools/ldbedit.c | 17 ++++++----------- source4/lib/ldb/tools/ldbsearch.c | 19 ++++++++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 02325b8356..aa5c5dfb88 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -37,7 +37,7 @@ $VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' | $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 $VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 -$VALGRIND bin/ldbsearch '((' uid && exit 1 +$VALGRIND bin/ldbsearch '((' uid || exit 1 $VALGRIND bin/ldbsearch '(objectclass=)' uid || exit 1 $VALGRIND bin/ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index e8497ba18f..12bf12bfff 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -278,28 +278,23 @@ static void usage(void) struct ldb_context *ldb; struct ldb_message **msgs; int ret; - const char *expression = NULL; + const char *expression = "(|(objectclass=*)(dn=*))"; const char * const * attrs = NULL; ldb = ldb_init(NULL); options = ldb_cmdline_process(ldb, argc, argv, usage); - if (options->all_records) { - expression = "(|(objectclass=*)(dn=*))"; - } - - if (!expression) { - if (options->argc == 0) { - usage(); - } + /* the check for '=' is for compatibility with ldapsearch */ + if (options->argc > 0 && + strchr(options->argv[0], '=')) { expression = options->argv[0]; - options->argc--; options->argv++; + options->argc--; } if (options->argc > 0) { - attrs = (const char * const *)options->argv; + attrs = (const char * const *)(options->argv); } ret = ldb_search(ldb, options->basedn, options->scope, expression, attrs, &msgs); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 0e81da5de3..396bb7797a 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -120,18 +120,23 @@ static int do_search(struct ldb_context *ldb, const char * const * attrs = NULL; struct ldb_cmdline *options; int ret = -1; + const char *expression = "(|(objectclass=*)(dn=*))"; ldb = ldb_init(NULL); options = ldb_cmdline_process(ldb, argc, argv, usage); - - if (options->argc < 1 && !options->interactive) { - usage(); - exit(1); + + /* the check for '=' is for compatibility with ldapsearch */ + if (!options->interactive && + options->argc > 0 && + strchr(options->argv[0], '=')) { + expression = options->argv[0]; + options->argv++; + options->argc--; } - if (options->argc > 1) { - attrs = (const char * const *)(options->argv+1); + if (options->argc > 0) { + attrs = (const char * const *)(options->argv); } if (options->interactive) { @@ -144,7 +149,7 @@ static int do_search(struct ldb_context *ldb, } } else { ret = do_search(ldb, options->basedn, options->scope, options->sorted, - options->argv[0], attrs); + expression, attrs); } talloc_free(ldb); -- cgit From 9f51b5716df0843e33bec259f5fc4afa0b5eeabd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 22 Jun 2005 04:01:27 +0000 Subject: r7834: added comment about the "((" search test (This used to be commit 42c42f6611fa295ca60782661781d023c4fdaf8b) --- source4/lib/ldb/tests/test-generic.sh | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index aa5c5dfb88..9b59261003 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -37,6 +37,10 @@ $VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' | $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 $VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 $VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 + +# note that the "((" is treated as an attribute not an expression +# this matches the openldap ldapsearch behaviour of looking for a '=' +# to see if the first argument is an expression or not $VALGRIND bin/ldbsearch '((' uid || exit 1 $VALGRIND bin/ldbsearch '(objectclass=)' uid || exit 1 $VALGRIND bin/ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 -- cgit From f1a853664ca143466ebd12958c1b1ac7f3c039dd Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 23 Jun 2005 04:26:23 +0000 Subject: r7844: eliminate superfluous attribute tables (This used to be commit 863beef35b769c5a531819c974754aea2a790921) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 473 ++++++------------------------ 1 file changed, 91 insertions(+), 382 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index ff19ff737a..b21365d3f8 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -200,10 +200,6 @@ new_dn(struct ldb_module * module, char * pDN, long long * pEID); -static int -new_attr(struct ldb_module * module, - char * pAttrName); - static void base160_sql(sqlite3_context * hContext, int argc, @@ -351,7 +347,7 @@ lsqlite3_rename(struct ldb_module * module, return -1; } - /* Determine the eid of the DN being deleted */ + /* Determine the eid of the DN being renamed */ QUERY_INT(lsqlite3, eid, TRUE, @@ -369,9 +365,12 @@ lsqlite3_rename(struct ldb_module * module, QUERY_NOROWS(lsqlite3, TRUE, - "UPDATE ldb_attr_DN " - " SET attr_value = %Q " - " WHERE eid = %lld;", + "UPDATE ldb_attribute_values " + " SET attr_value = %Q, " + " attr_value_normalized = upper(%Q) " + " WHERE eid = %lld " + " AND attr_name = 'DN';", + pNewDN, pNewDN, eid); @@ -389,12 +388,7 @@ static int lsqlite3_delete(struct ldb_module * module, const char * pDN) { - int ret; - int bLoop; long long eid; - char * pSql; - const char * pAttrName; - sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; /* ignore ltdb specials */ @@ -415,92 +409,11 @@ lsqlite3_delete(struct ldb_module * module, eid, TRUE, "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE dn = %Q;", + " FROM ldb_attribute_values\n" + " WHERE attr_name = 'DN'\n" + " AND attr_value_normalized = upper(%Q);", pDN); - /* Obtain the list of attribute names in use by this DN */ - if ((pSql = talloc_asprintf(module->ldb, - "SELECT upper(attr_name) " - " FROM ldb_attribute_values " - " WHERE eid = %lld;", - eid)) == NULL) { - return -1; - } - - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pSql, - -1, - &pStmt, - NULL)) == SQLITE_SCHEMA) { - continue; - } else if (ret != SQLITE_OK) { - ret = -1; - break; - } - - /* Loop through the returned rows */ - for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { - - /* Get the next row */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { - - /* Get the values from this row */ - pAttrName = sqlite3_column_text(pStmt, 0); - - /* - * Delete any entries from the specified - * attribute table that pertain to this eid. - */ - QUERY_NOROWS(lsqlite3, - TRUE, - "DELETE FROM ldb_attr_%q " - " WHERE eid = %lld;", - pAttrName, eid); - } - } - - if (ret == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_DONE) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } - - /* Delete the DN attribute entry */ - QUERY_NOROWS(lsqlite3, - TRUE, - "DELETE FROM ldb_attr_DN " - " WHERE eid = %lld;", - eid); - /* Delete attribute/value table entries pertaining to this DN */ QUERY_NOROWS(lsqlite3, TRUE, @@ -579,8 +492,9 @@ lsqlite3_search_bytree(struct ldb_module * module, if ((ret = query_int(lsqlite3, &eid, "SELECT eid\n" - " FROM ldb_attr_DN\n" - " WHERE attr_value = %Q;", + " FROM ldb_attribute_values\n" + " WHERE attr_name = 'DN'\n" + " AND attr_value_normalized = upper(%Q);", pBaseDN)) == SQLITE_DONE) { UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); @@ -917,10 +831,13 @@ lsqlite3_search(struct ldb_module * module, return 0; } +#if 0 +/* (|(objectclass=*)(dn=*)) is passed by the command line tool now instead */ /* Handle the special case of requesting all */ if (pExpression != NULL && *pExpression == '\0') { pExpression = "dn=*"; } +#endif /* Parse the filter expression into a tree we can work with */ if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { @@ -1152,40 +1069,11 @@ initialize(struct lsqlite3_private *lsqlite3, "(" " eid INTEGER REFERENCES ldb_entry," " attr_name TEXT," - " attr_value TEXT" - ");" - - /* - * There is one attribute table per searchable attribute. - */ - /* - "CREATE TABLE ldb_attr_ATTRIBUTE_NAME" - "(" - " eid INTEGER REFERENCES ldb_entry," - " attr_value TEXT" + " attr_value TEXT," + " attr_value_normalized TEXT " ");" - */ - - /* - * We pre-create the dn attribute table - */ - "CREATE TABLE ldb_attr_DN" - "(" - " eid INTEGER PRIMARY KEY REFERENCES ldb_entry," - " attr_value TEXT" - ");" - - - /* - * We pre-create the objectclass attribute table - */ - "CREATE TABLE ldb_attr_OBJECTCLASS" - "(" - " eid INTEGER REFERENCES ldb_entry," - " attr_value TEXT" - ");" - + /* * Indexes */ @@ -1195,8 +1083,6 @@ initialize(struct lsqlite3_private *lsqlite3, "CREATE INDEX ldb_attribute_values_eid_idx " " ON ldb_attribute_values (eid);" - "CREATE INDEX ldb_attr_DN_attr_value_idx " - " ON ldb_attr_DN (attr_value);" /* @@ -1269,10 +1155,10 @@ initialize(struct lsqlite3_private *lsqlite3, " (0, NULL, '', '0001');" /* And the root node "dn" attribute */ - "INSERT INTO ldb_attr_DN " - " (eid, attr_value) " + "INSERT INTO ldb_attribute_values " + " (eid, attr_name, attr_value, attr_value_normalized) " " VALUES " - " (0, '');" + " (0, 'DN', '', '');" "INSERT INTO ldb_object_classes " " (class_name, tree_key) " @@ -1387,14 +1273,12 @@ initialize(struct lsqlite3_private *lsqlite3, if (query_int(lsqlite3, &queryInt, "SELECT " - " (SELECT COUNT(*) = 4" + " (SELECT COUNT(*) = 2" " FROM sqlite_master " " WHERE type = 'table' " " AND name IN " " (" " 'ldb_entry', " - " 'ldb_attr_DN', " - " 'ldb_attr_OBJECTCLASS', " " 'ldb_object_classes' " " ) " " ) " @@ -1911,9 +1795,7 @@ parsetree_to_sql(struct ldb_module *module, /* * For simple searches, we want to retrieve the list of EIDs that - * match the criteria. We accomplish this by searching the - * appropriate table, ldb_attr_, for the eid - * corresponding to all matching values. + * match the criteria. */ if (t->u.simple.value.length == 1 && (*(const char *) t->u.simple.value.data) == '*') { @@ -1923,8 +1805,9 @@ parsetree_to_sql(struct ldb_module *module, * table. */ if ((p = sqlite3_mprintf(" SELECT eid\n" - " FROM ldb_attr_%q\n", - pAttrName)) == NULL) { + " FROM ldb_attribute_values\n" + " WHERE attr_name = %Q", + pAttrName)) == NULL) { return NULL; } @@ -1942,8 +1825,9 @@ parsetree_to_sql(struct ldb_module *module, */ if ((p = sqlite3_mprintf( " SELECT eid\n" - " FROM ldb_attr_OBJECTCLASS\n" - " WHERE attr_value IN\n" + " FROM ldb_attribute_values\n" + " WHERE attr_name = 'OBJECTCLASS' " + " AND attr_value_normalized IN\n" " (SELECT class_name\n" " FROM ldb_object_classes\n" " WHERE tree_key GLOB\n" @@ -1965,11 +1849,13 @@ parsetree_to_sql(struct ldb_module *module, } else if (strcasecmp(t->u.simple.attr, "dn") == 0) { pDN = ldb_dn_fold(module->ldb, t->u.simple.value.data, module, case_fold_attr_required); - if ((p = sqlite3_mprintf(" SELECT eid\n" - " FROM ldb_attr_%q\n" - " WHERE attr_value = %Q\n", - pAttrName, - pDN)) == NULL) { + if ((p = sqlite3_mprintf( + " SELECT eid\n" + " FROM ldb_attribute_values\n" + " WHERE attr_name = %Q\n" + " AND attr_value_normalized = upper(%Q)\n", + pAttrName, + pDN)) == NULL) { return NULL; } @@ -1981,11 +1867,13 @@ parsetree_to_sql(struct ldb_module *module, sqlite3_free(p); } else { /* A normal query. */ - if ((p = sqlite3_mprintf(" SELECT eid\n" - " FROM ldb_attr_%q\n" - " WHERE attr_value = %Q\n", - pAttrName, - t->u.simple.value.data)) == NULL) { + if ((p = sqlite3_mprintf( + " SELECT eid\n" + " FROM ldb_attribute_values\n" + " WHERE attr_name = %Q\n" + " AND attr_value_normalized = upper(%Q)\n", + pAttrName, + t->u.simple.value.data)) == NULL) { return NULL; } @@ -2074,115 +1962,6 @@ parsetree_to_attrlist(struct ldb_module *module, } -#ifdef NEED_TABLE_LIST -/* - * Use the already-generated FILTER_ATTR_TABLE to create a list of attribute - * table names that will be used in search queries. - */ -static char * -build_attr_table_list(void * hTalloc, - struct lsqlite3_private * lsqlite3) -{ - int ret; - int bLoop; - char * p; - char * pAttrName; - char * pTableList; - sqlite3_stmt * pStmt; - - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - /* Initialize a string to which we'll append each table name */ - if ((pTableList = talloc_strdup(hTalloc, "")) == NULL) { - return NULL; - } - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - "SELECT attr_name " - " FROM " FILTER_ATTR_TABLE ";", - -1, - &pStmt, - NULL)) == SQLITE_SCHEMA) { - continue; - } else if (ret != SQLITE_OK) { - ret = -1; - break; - } - - /* Loop through the returned rows */ - for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { - - /* Get the next row */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { - - /* - * Get value from this row and append to table - * list - */ - p = discard_const_p(char, - sqlite3_column_text(pStmt, - 0)); - - pAttrName = - ldb_casefold( - hTalloc, - sqlite3_column_text(pStmt, 0)); - - /* Append it to the table list */ - if ((p = talloc_asprintf( - hTalloc, - "%sldb_attr_%s", - *pTableList == '\0' ? "" : ",", - pAttrName)) == NULL) { - - talloc_free(pTableList); - return NULL; - } - - /* We have a new table list */ - talloc_free(pTableList); - pTableList = p; - } - } - - if (ret == SQLITE_SCHEMA) { - talloc_free(pTableList); - continue; - } - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } - - if (ret != 0) { - talloc_free(pTableList); - pTableList = NULL; - } - - return pTableList; -} -#endif - - /* * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE * requests in the ldb_message @@ -2212,37 +1991,26 @@ msg_to_sql(struct ldb_module * module, pAttrName = ldb_casefold((struct ldb_context *) module, el->name); - if (flags == LDB_FLAG_MOD_ADD) { - /* Create the attribute table if it doesn't exist */ - if (new_attr(module, pAttrName) != 0) { - return -1; - } - } - /* For each value of the specified attribute name... */ for (j = 0; j < el->num_values; j++) { /* ... bind the attribute value, if necessary */ switch (flags) { case LDB_FLAG_MOD_ADD: - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_attr_%q\n" - " (eid, attr_value)\n" - " VALUES\n" - " (%lld, %Q);", - pAttrName, - eid, el->values[j].data); - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_attribute_values" - " (eid, attr_name, attr_value)" - " VALUES " - " (%lld, %Q, %Q);", - eid, - el->name, - el->values[j].data); - + QUERY_NOROWS( + lsqlite3, + FALSE, + "INSERT INTO ldb_attribute_values\n" + " (eid,\n" + " attr_name,\n" + " attr_value,\n" + " attr_value_normalized)\n" + " VALUES\n" + " (%lld, %Q, %Q, upper(%Q));", + eid, + pAttrName, + el->values[j].data, /* FIX ME */ + el->values[j].data); /* Is this a special "objectclass"? */ if (strcasecmp(pAttrName, @@ -2265,44 +2033,34 @@ msg_to_sql(struct ldb_module * module, break; case LDB_FLAG_MOD_REPLACE: - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_attr_%q\n" - " SET attr_value = %Q\n" - " WHERE eid = %lld;", - pAttrName, - el->values[j].data, - eid); - QUERY_NOROWS(lsqlite3, - FALSE, - "UPDATE ldb_attribute_values " - " SET attr_value = %Q " - " WHERE eid = %lld " - " AND attr_name = %Q;", - el->values[j].data, - eid, - el->name); + QUERY_NOROWS( + lsqlite3, + FALSE, + "UPDATE ldb_attribute_values\n" + " SET attr_value = %Q,\n" + " attr_value_normalized =\n" + " upper(%Q)\n" + " WHERE eid = %lld\n" + " AND attr_name = %Q;", + el->values[j].data, /* FIX ME */ + el->values[j].data, + eid, + pAttrName); break; case LDB_FLAG_MOD_DELETE: /* No additional parameters to this query */ - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM ldb_attr_%q\n" - " WHERE eid = %lld\n" - " AND attr_value = %Q;", - pAttrName, - eid, - el->values[j].data); - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM ldb_attribute_values" - " WHERE eid = %lld " - " AND attr_name = %Q " - " AND attr_value = %Q;", - eid, - el->name, - el->values[j].data); + QUERY_NOROWS( + lsqlite3, + FALSE, + "DELETE FROM ldb_attribute_values" + " WHERE eid = %lld " + " AND attr_name = %Q " + " AND attr_value_normalized =\n" + " upper(%Q);", + eid, + el->name, + el->values[j].data); break; } } @@ -2456,12 +2214,17 @@ new_dn(struct ldb_module * module, /* Also add DN attribute */ QUERY_NOROWS(lsqlite3, FALSE, - "INSERT %s INTO ldb_attr_DN\n" - " (eid, attr_value) " + "INSERT %s INTO ldb_attribute_values\n" + " (eid,\n" + " attr_name,\n" + " attr_value,\n" + " attr_value_normalized) " " VALUES " - " (%lld, %Q);", + " (%lld, 'DN', %Q, upper(%Q));", nComponent == 0 ? "" : "OR IGNORE", - eid, pPartialDN); + eid, + pPartialDN, /* FIX ME */ + pPartialDN); } if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { @@ -2479,60 +2242,6 @@ new_dn(struct ldb_module * module, } -static int -new_attr(struct ldb_module * module, - char * pAttrName) -{ - long long bExists; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* - * NOTE: - * pAttrName is assumed to already be case-folded here! - */ - - /* See if the table already exists */ - QUERY_INT(lsqlite3, - bExists, - FALSE, - "SELECT COUNT(*) <> 0\n" - " FROM sqlite_master\n" - " WHERE type = 'table'\n" - " AND tbl_name = 'ldb_attr_%q';", - pAttrName); - - /* Did it exist? */ - if (! bExists) { - /* Nope. Create the table */ - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE TABLE ldb_attr_%q\n" - "(\n" - " eid INTEGER REFERENCES ldb_entry,\n" - " attr_value TEXT\n" - ");", - pAttrName); - - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE INDEX ldb_attr_%q_eid_idx\n" - " ON ldb_attr_%q (eid);", - pAttrName, - pAttrName); - - QUERY_NOROWS(lsqlite3, - FALSE, - "CREATE INDEX ldb_attr_%q_attr_value_idx " - " ON ldb_attr_%q (attr_value);", - pAttrName, - pAttrName); - - } - - return 0; -} - - static unsigned char base160tab[161] = { 48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */ 58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */ -- cgit From 66a52992ff6a9f2f926249ac428d6fad72303637 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Jun 2005 22:30:26 +0000 Subject: r7850: Support mkdir() with just one parameter. Patch from Steven Edwards . I've moved the Win32-specific tests to win32.m4 so it does not make any of the POSIX configure stuff more complicated. (This used to be commit bf85fdd01552f75b745fdf3159a7a87cd6521ed2) --- source4/lib/messaging/messaging.c | 1 + source4/lib/replace/win32.m4 | 20 ++++++++++++++++++++ source4/lib/util.c | 3 ++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 source4/lib/replace/win32.m4 (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 70eb2e7680..6209c36554 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -22,6 +22,7 @@ #include "includes.h" #include "lib/events/events.h" +#include "system/dir.h" #include "system/filesys.h" #include "system/time.h" #include "messages.h" diff --git a/source4/lib/replace/win32.m4 b/source4/lib/replace/win32.m4 new file mode 100644 index 0000000000..6b9c4e6b13 --- /dev/null +++ b/source4/lib/replace/win32.m4 @@ -0,0 +1,20 @@ +AC_CHECK_HEADERS(direct.h) + +####################################### +# Check for mkdir mode +AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, + AC_TRY_COMPILE([ + #include + #ifdef HAVE_DIRECT_H + #include + #endif],[ + mkdir("foo",0777); + return 0; + ], + ac_mkdir_has_mode="yes", + ac_mkdir_has_mode="no") ) + +if test "$ac_mkdir_has_mode" = "yes" +then + AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) +fi diff --git a/source4/lib/util.c b/source4/lib/util.c index 59d83a966a..ba2c0e1ae4 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -26,9 +26,10 @@ #include "dynconfig.h" #include "system/network.h" #include "system/iconv.h" +#include "system/dir.h" #include "system/filesys.h" -/**************************************************************************n +/*************************************************************************** Find a suitable temporary directory. The result should be copied immediately as it may be overwritten by a subsequent call. ****************************************************************************/ -- cgit From ce2e35309e26d7fc23ba54f1caeb8aeeefa7ccc2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 23 Jun 2005 23:19:31 +0000 Subject: r7851: We are case preserving let the DN be returned the same the user put it into. sss (This used to be commit 5b41e3202456549250e6e5b1c63bd45ea7500fa3) --- source4/lib/ldb/common/ldb_explode_dn.c | 23 ++--- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 138 +++++++++++++++--------------- 2 files changed, 83 insertions(+), 78 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 30e5740652..0dcca5dc70 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -154,12 +154,11 @@ ldb_explode_dn(void * mem_ctx, } /* Copy the provided DN so we can manipulate it */ - if ((p = ldb_dn_fold(mem_ctx, orig_dn, - hUserData, case_fold_attr_fn)) == NULL) { + if ((dn_copy = talloc_strdup(mem_ctx, orig_dn)) == NULL) { goto failed; } - dn_copy = p; + p = dn_copy; /* Our copy may end shorter than the original as we unescape chars */ dn_end = dn_copy + orig_len + 1; @@ -224,13 +223,17 @@ ldb_explode_dn(void * mem_ctx, goto failed; } - /* attribute names are always case-folded */ - p = attribute->name; - if ((attribute->name = - ldb_casefold(attribute, p)) == NULL) { - goto failed; - } - talloc_free(p); + /* see if this attribute name needs case folding */ + if (case_fold_attr_fn != NULL && + (* case_fold_attr_fn)(hUserData, + attribute->name)) { + p = attribute->name; + if ((attribute->name = + ldb_casefold(attribute, p)) == NULL) { + goto failed; + } + talloc_free(p); + } ldb_debug(mem_ctx, LDB_DEBUG_TRACE, diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index b21365d3f8..019c0eebf1 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -164,6 +164,9 @@ query_int(const struct lsqlite3_private * lsqlite3, static int case_fold_attr_required(void * hUserData, char *attr); +static int case_fold_attr_not_required(void * hUserData, + char *attr); + static int add_msg_attr(void * hTalloc, long long eid, @@ -183,12 +186,6 @@ static int parsetree_to_attrlist(struct ldb_module *module, const struct ldb_parse_tree * t); -#ifdef NEED_TABLE_LIST -static char * -build_attr_table_list(void * hTalloc, - struct lsqlite3_private * lsqlite3); -#endif - static int msg_to_sql(struct ldb_module * module, const struct ldb_message * msg, @@ -328,6 +325,8 @@ lsqlite3_rename(struct ldb_module * module, const char * pOldDN, const char * pNewDN) { + const char *pOldNormalizedDN; + const char *pNewNormalizedDN; long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -337,9 +336,9 @@ lsqlite3_rename(struct ldb_module * module, } /* Case-fold each of the DNs */ - pOldDN = ldb_dn_fold(module->ldb, pOldDN, + pOldNormalizedDN = ldb_dn_fold(module->ldb, pOldDN, module, case_fold_attr_required); - pNewDN = ldb_dn_fold(module->ldb, pNewDN, + pNewNormalizedDN = ldb_dn_fold(module->ldb, pNewDN, module, case_fold_attr_required); /* Begin a transaction */ @@ -353,25 +352,26 @@ lsqlite3_rename(struct ldb_module * module, TRUE, "SELECT eid\n" " FROM ldb_entry\n" - " WHERE dn = %Q;", - pOldDN); + " WHERE normalized_dn = %Q;", + pOldNormalizedDN); QUERY_NOROWS(lsqlite3, TRUE, "UPDATE ldb_entry " - " SET dn = %Q " + " SET dn = %Q, " + " normalized_dn = %Q " " WHERE eid = %lld;", - pNewDN, eid); + pNewDN, pNewNormalizedDN, eid); QUERY_NOROWS(lsqlite3, TRUE, "UPDATE ldb_attribute_values " " SET attr_value = %Q, " - " attr_value_normalized = upper(%Q) " + " attr_value_normalized = %Q " " WHERE eid = %lld " " AND attr_name = 'DN';", pNewDN, - pNewDN, + pNewNormalizedDN, eid); /* Commit the transaction */ @@ -388,6 +388,7 @@ static int lsqlite3_delete(struct ldb_module * module, const char * pDN) { + char *pNormalizedDN; long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -402,7 +403,7 @@ lsqlite3_delete(struct ldb_module * module, } /* Case-fold the DNs */ - pDN = ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); + pNormalizedDN = ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ QUERY_INT(lsqlite3, @@ -411,8 +412,8 @@ lsqlite3_delete(struct ldb_module * module, "SELECT eid\n" " FROM ldb_attribute_values\n" " WHERE attr_name = 'DN'\n" - " AND attr_value_normalized = upper(%Q);", - pDN); + " AND attr_value_normalized = %Q;", + pNormalizedDN); /* Delete attribute/value table entries pertaining to this DN */ QUERY_NOROWS(lsqlite3, @@ -453,11 +454,9 @@ lsqlite3_search_bytree(struct ldb_module * module, long long prevEID; char * pSql = NULL; char * pSqlConstraints; -#ifdef NEED_TABLE_LIST - char * pTableList; -#endif char * hTalloc = NULL; const char * pDN; + const char * pNormalizedBaseDN; const char * pAttrName; const char * pAttrValue; const char * pResultAttrList; @@ -465,17 +464,13 @@ lsqlite3_search_bytree(struct ldb_module * module, sqlite3_stmt * pStmt; struct lsqlite3_private * lsqlite3 = module->private_data; - if (pBaseDN == NULL) { - pBaseDN = ""; - } - /* Allocate a temporary talloc context */ if ((hTalloc = talloc_new(module->ldb)) == NULL) { return -1; } /* Case-fold the base DN */ - if ((pBaseDN = ldb_dn_fold(hTalloc, pBaseDN, + if ((pNormalizedBaseDN = ldb_dn_fold(hTalloc, pBaseDN?pBaseDN:"", module, case_fold_attr_required)) == NULL) { talloc_free(hTalloc); return -1; @@ -492,10 +487,9 @@ lsqlite3_search_bytree(struct ldb_module * module, if ((ret = query_int(lsqlite3, &eid, "SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = 'DN'\n" - " AND attr_value_normalized = upper(%Q);", - pBaseDN)) == SQLITE_DONE) { + " FROM ldb_entry\n" + " WHERE normalized_dn = %Q;", + pNormalizedBaseDN)) == SQLITE_DONE) { UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); return 0; @@ -564,16 +558,6 @@ lsqlite3_search_bytree(struct ldb_module * module, goto cleanup; } -#ifdef NEED_TABLE_LIST - /* - * Build the attribute table list from the list of unique names. - */ - if ((pTableList = build_attr_table_list(hTalloc, lsqlite3)) == NULL) { - ret = -1; - goto cleanup; - } -#endif - switch(scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: @@ -913,7 +897,7 @@ static int lsqlite3_modify(struct ldb_module * module, const struct ldb_message * msg) { - char * pDN; + char * pNormalizedDN; long long eid; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -928,7 +912,7 @@ lsqlite3_modify(struct ldb_module * module, } /* Case-fold the DN so we can compare it to what's in the database */ - pDN = ldb_dn_fold(module->ldb, msg->dn, + pNormalizedDN = ldb_dn_fold(module->ldb, msg->dn, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ @@ -937,8 +921,8 @@ lsqlite3_modify(struct ldb_module * module, TRUE, "SELECT eid\n" " FROM ldb_entry\n" - " WHERE dn = %Q;", - pDN); + " WHERE normalized_dn = %Q;", + pNormalizedDN); /* Apply the message attributes */ if (msg_to_sql(module, msg, eid, TRUE) != 0) { @@ -1047,6 +1031,7 @@ initialize(struct lsqlite3_private *lsqlite3, " eid INTEGER PRIMARY KEY," " peid INTEGER REFERENCES ldb_entry," " dn TEXT UNIQUE NOT NULL," + " normalized_dn TEXT UNIQUE NOT NULL," " tree_key TEXT UNIQUE," " max_child_num INTEGER DEFAULT 0," " create_timestamp INTEGER," @@ -1150,9 +1135,9 @@ initialize(struct lsqlite3_private *lsqlite3, /* The root node */ "INSERT INTO ldb_entry " - " (eid, peid, dn, tree_key) " + " (eid, peid, dn, normalized_dn, tree_key) " " VALUES " - " (0, NULL, '', '0001');" + " (0, NULL, '', '', '0001');" /* And the root node "dn" attribute */ "INSERT INTO ldb_attribute_values " @@ -1371,8 +1356,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, struct timeval tv; struct timezone tz; - gettimeofday(&tv, &tz); - t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + gettimeofday(&tv, &tz); + t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + } /* Begin access to variable argument list */ va_start(args, pSql); @@ -1432,10 +1419,9 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* All done with variable argument list */ va_end(args); - gettimeofday(&tv, NULL); - t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + gettimeofday(&tv, NULL); + t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); printf("%1.6lf %s\n%s\n\n", t1 - t0, ret == 0 ? "SUCCESS" : "FAIL", p); @@ -1473,8 +1459,10 @@ query_int(const struct lsqlite3_private * lsqlite3, struct timeval tv; struct timezone tz; - gettimeofday(&tv, &tz); - t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + gettimeofday(&tv, &tz); + t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + } /* Begin access to variable argument list */ va_start(args, pSql); @@ -1537,10 +1525,10 @@ query_int(const struct lsqlite3_private * lsqlite3, /* All done with variable argument list */ va_end(args); - gettimeofday(&tv, NULL); - t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { + gettimeofday(&tv, NULL); + t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); printf("%1.6lf %s\n%s\n\n", t1 - t0, ret == 0 ? "SUCCESS" : "FAIL", p); @@ -1563,10 +1551,18 @@ case_fold_attr_required(void * hUserData, { // struct ldb_module * module = hUserData; -#warning "currently, all attributes require case folding" return TRUE; } +static int +case_fold_attr_not_required(void * hUserData, + char *attr) +{ +// struct ldb_module * module = hUserData; + + return FALSE; +} + /* * add a single set of ldap message values to a ldb_message @@ -1702,7 +1698,7 @@ parsetree_to_sql(struct ldb_module *module, const struct ldb_parse_tree *t) { int i; - char * pDN; + char * pNormalizedDN; char * child; char * p; char * ret = NULL; @@ -1847,15 +1843,15 @@ parsetree_to_sql(struct ldb_module *module, sqlite3_free(p); } else if (strcasecmp(t->u.simple.attr, "dn") == 0) { - pDN = ldb_dn_fold(module->ldb, t->u.simple.value.data, + pNormalizedDN = ldb_dn_fold(module->ldb, t->u.simple.value.data, module, case_fold_attr_required); if ((p = sqlite3_mprintf( " SELECT eid\n" " FROM ldb_attribute_values\n" " WHERE attr_name = %Q\n" - " AND attr_value_normalized = upper(%Q)\n", + " AND attr_value_normalized = %Q\n", pAttrName, - pDN)) == NULL) { + pNormalizedDN)) == NULL) { return NULL; } @@ -2080,6 +2076,7 @@ new_dn(struct ldb_module * module, int bFirst; char * p; char * pPartialDN; + char * pPartialNormalizedDN; long long eid; long long peid; double t0 = 0; @@ -2096,12 +2093,12 @@ new_dn(struct ldb_module * module, t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); } - /* Explode and normalize the DN */ + /* Explode the DN */ if ((pExplodedDN = ldb_explode_dn(ldb, pDN, ldb, - case_fold_attr_required)) == NULL) { + case_fold_attr_not_required)) == NULL) { return -1; } @@ -2117,6 +2114,10 @@ new_dn(struct ldb_module * module, return -1; } + if ((pPartialNormalizedDN = talloc_strdup(pPartialDN, "")) == NULL) { + return -1; + } + /* For each component of the DN (starting with the last one)... */ #warning "convert this loop to recursive, and search backwards instead" eid = 0; @@ -2158,6 +2159,7 @@ new_dn(struct ldb_module * module, /* Save the new partial DN */ pPartialDN = p; + pPartialNormalizedDN = ldb_dn_fold(pPartialDN, p, module, case_fold_attr_required); if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { gettimeofday(&tv, NULL); @@ -2177,11 +2179,11 @@ new_dn(struct ldb_module * module, QUERY_NOROWS(lsqlite3, FALSE, "INSERT %s INTO ldb_entry\n" - " (peid, dn)\n" + " (peid, dn, normalized_dn)\n" " VALUES\n" - " (%lld, %Q);", + " (%lld, %Q, %Q);", nComponent == 0 ? "" : "OR IGNORE", - eid, pPartialDN); + eid, pPartialDN, pPartialNormalizedDN); /* Save the parent EID */ peid = eid; @@ -2200,8 +2202,8 @@ new_dn(struct ldb_module * module, FALSE, "SELECT eid " " FROM ldb_entry " - " WHERE dn = %Q;", - pPartialDN); + " WHERE normalized_dn = %Q;", + pPartialNormalizedDN); if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { gettimeofday(&tv, NULL); @@ -2220,11 +2222,11 @@ new_dn(struct ldb_module * module, " attr_value,\n" " attr_value_normalized) " " VALUES " - " (%lld, 'DN', %Q, upper(%Q));", + " (%lld, 'DN', %Q, %Q);", nComponent == 0 ? "" : "OR IGNORE", eid, pPartialDN, /* FIX ME */ - pPartialDN); + pPartialNormalizedDN); } if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { -- cgit From bdee131f30e1bef31498b08bb648ddee35ea4892 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Jun 2005 00:18:20 +0000 Subject: r7860: switch our ldb storage format to use a NDR encoded objectSid. This is quite a large change as we had lots of code that assumed that objectSid was a string in S- format. metze and simo tried to convince me to use NDR format months ago, but I didn't listen, so its fair that I have the pain of fixing all the code now :-) This builds on the ldb_register_samba_handlers() and ldif handlers code I did earlier this week. There are still three parts of this conversion I have not finished: - the ltdb index records need to use the string form of the objectSid (to keep the DNs sane). Until that it done I have disabled indexing on objectSid, which is a big performance hit, but allows us to pass all our tests while I rejig the indexing system to use a externally supplied conversion function - I haven't yet put in place the code that allows client to use the "S-xxx-yyy" form for objectSid in ldap search expressions. w2k3 supports this, presumably by looking for the "S-" prefix to determine what type of objectSid form is being used by the client. I have been working on ways to handle this, but am not happy with them yet so they aren't part of this patch - I need to change pidl to generate push functions that take a "const void *" instead of a "void*" for the data pointer. That will fix the couple of new warnings this code generates. Luckily it many places the conversion to NDR formatted records actually simplified the code, as it means we no longer need as many calls to dom_sid_parse_talloc(). In some places it got more complex, but not many. (This used to be commit d40bc2fa8ddd43560315688eebdbe98bdd02756c) --- source4/lib/db_wrap.c | 9 +++++++++ source4/lib/ldb/config.mk | 4 ++-- source4/lib/ldb/samba/ldif_handlers.c | 6 ------ 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index c277f2d975..b000225bbf 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -102,6 +102,15 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, ev = talloc_find_parent_bytype(mem_ctx, struct event_context); if (ev) { ldb_set_opaque(ldb, "EventContext", ev); + } else { + DEBUG(0,("WARNING: event_context not found\n")); + talloc_show_parents(mem_ctx, stdout); + } + + ret = ldb_register_samba_handlers(ldb); + if (ret == -1) { + talloc_free(ldb); + return NULL; } ret = ldb_connect(ldb, url, flags, options); diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 00568aeda8..cf3a7fa93d 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -72,7 +72,7 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_modules.o \ lib/ldb/common/ldb_explode_dn.o REQUIRED_SUBSYSTEMS = \ - LIBREPLACE LIBTALLOC + LIBREPLACE LIBTALLOC LDBSAMBA NOPROTO = YES # # End SUBSYSTEM LIBLDB @@ -103,7 +103,7 @@ OBJ_FILES = \ [SUBSYSTEM::LIBLDB_CMDLINE] OBJ_FILES= \ lib/ldb/tools/cmdline.o -REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC LDBSAMBA +REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC # End SUBSYSTEM LIBLDB_CMDLINE ################################################ diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index 7252d081f1..17a45df78d 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -85,11 +85,5 @@ static const struct ldb_ldif_handler samba_handlers[] = { */ int ldb_register_samba_handlers(struct ldb_context *ldb) { -#if 0 - /* we can't enable this until we fix the sam code to handle - non-string elements */ return ldb_ldif_add_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers)); -#else - return 0; -#endif } -- cgit From d5888fbb60d6b16b20ee95e434a94048ef1806bc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 24 Jun 2005 01:27:34 +0000 Subject: r7866: Remove some unused autoconf macro calls. Some of these should probably be re-added again later when we need them. They should then be added to the appropriate config.m4 file in the source tree rather then in rewrite.m4. (This used to be commit 4eca613470139f6425f454aea016566f9deffa3e) --- source4/lib/replace/win32.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/win32.m4 b/source4/lib/replace/win32.m4 index 6b9c4e6b13..9ac84cdf2a 100644 --- a/source4/lib/replace/win32.m4 +++ b/source4/lib/replace/win32.m4 @@ -1,4 +1,4 @@ -AC_CHECK_HEADERS(direct.h) +AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) ####################################### # Check for mkdir mode -- cgit From b818ff3ede56ab905418dddbc0bdc2011ebf62ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Jun 2005 01:58:40 +0000 Subject: r7868: canonicalise the message before using ldb_add() in the ldbadd utility. (This used to be commit 56f4af5f210da472d41d9bcf6918647181f6ad16) --- source4/lib/ldb/tools/ldbadd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 7794b9de39..5be3b7fc75 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -71,6 +71,8 @@ static int process_file(struct ldb_context *ldb, FILE *f) break; } + ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg); + ret = ldb_add(ldb, ldif->msg); if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", -- cgit From 49736de46a340ed9256d7a914631a67453aa7530 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Jun 2005 05:17:36 +0000 Subject: r7873: hopefully fixed build of ldb_explode_dn() on AIX I'd really rather see this code completely replaced, but I'll leave that to simo (he has volunteered) :-) (This used to be commit cc2e08d68e27aa203ccc26e8d544a86de3399877) --- source4/lib/ldb/common/ldb_explode_dn.c | 36 +++++++++------------------------ 1 file changed, 9 insertions(+), 27 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c index 0dcca5dc70..0e2efa876c 100644 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ b/source4/lib/ldb/common/ldb_explode_dn.c @@ -35,7 +35,6 @@ * Author: Derrell Lipman */ -#include #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" @@ -496,35 +495,18 @@ failed: } -static char * -parse_slash(char *p, - char *end) +static char *parse_slash(char *p, char *end) { - switch (*(p + 1)) { - case ',': - case '=': - case '\n': - case '+': - case '<': - case '>': - case '#': - case ';': - case '\\': - case '"': + unsigned x; + if (strchr(",=\n+<>#;\\\"", p[1])) { memmove(p, p + 1, end - (p + 1)); return (end - 1); - - default: - if (isxdigit(p[1]) && isxdigit(p[2])) { - int x; - - sscanf(p + 1, "%02x", &x); - *p = (char) x; - memmove(p + 1, p + 3, end - (p + 3)); - return (end - 2); - } else { - return NULL; - } } + if (sscanf(p + 1, "%02x", &x) == 1) { + *p = (unsigned char)x; + memmove(p + 1, p + 3, end - (p + 3)); + return (end - 2); + } + return NULL; } -- cgit From 1603fd94666d3175e9df12652f9ff4e1d14de064 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 25 Jun 2005 03:43:33 +0000 Subject: r7897: work in progress (This used to be commit 8e1431efcf0df797bc50ef584c38fce6a03429b3) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 312 +++++++++++++++++++++--------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 8 - source4/lib/ldb/tools/cmdline.c | 5 +- 3 files changed, 223 insertions(+), 102 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 019c0eebf1..76ef703ca5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -84,6 +84,16 @@ } \ } while (0) +#define GET_EID(lsqlite3, result_var, bRollbackOnError, pDN) \ + do { \ + if (getEID(lsqlite3, &result_var, pDN) != 0) { \ + if (bRollbackOnError) { \ + UNLOCK_DB(module, "rollback"); \ + } \ + return -1; \ + } \ + } while (0) + #define SQLITE3_DEBUG_QUERY (1 << 0) #define SQLITE3_DEBUG_INIT (1 << 1) @@ -95,6 +105,7 @@ * Static variables */ static int lsqlite3_debug = FALSE; +sqlite3_stmt * stmtGetEID = NULL; /* * Forward declarations @@ -161,6 +172,11 @@ query_int(const struct lsqlite3_private * lsqlite3, const char * pSql, ...); +static int +getEID(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pNormalizedDN); + static int case_fold_attr_required(void * hUserData, char *attr); @@ -336,10 +352,10 @@ lsqlite3_rename(struct ldb_module * module, } /* Case-fold each of the DNs */ - pOldNormalizedDN = ldb_dn_fold(module->ldb, pOldDN, - module, case_fold_attr_required); - pNewNormalizedDN = ldb_dn_fold(module->ldb, pNewDN, - module, case_fold_attr_required); + pOldNormalizedDN = + ldb_dn_fold(module->ldb, pOldDN, module, case_fold_attr_required); + pNewNormalizedDN = + ldb_dn_fold(module->ldb, pNewDN, module, case_fold_attr_required); /* Begin a transaction */ if (LOCK_DB(module, "transaction") < 0) { @@ -347,13 +363,7 @@ lsqlite3_rename(struct ldb_module * module, } /* Determine the eid of the DN being renamed */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE normalized_dn = %Q;", - pOldNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pOldNormalizedDN); QUERY_NOROWS(lsqlite3, TRUE, @@ -403,17 +413,11 @@ lsqlite3_delete(struct ldb_module * module, } /* Case-fold the DNs */ - pNormalizedDN = ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); + pNormalizedDN = + ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = 'DN'\n" - " AND attr_value_normalized = %Q;", - pNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); /* Delete attribute/value table entries pertaining to this DN */ QUERY_NOROWS(lsqlite3, @@ -470,26 +474,26 @@ lsqlite3_search_bytree(struct ldb_module * module, } /* Case-fold the base DN */ - if ((pNormalizedBaseDN = ldb_dn_fold(hTalloc, pBaseDN?pBaseDN:"", - module, case_fold_attr_required)) == NULL) { + if ((pNormalizedBaseDN = + ldb_dn_fold(hTalloc, + pBaseDN == NULL ? "" : pBaseDN, + module, + case_fold_attr_required)) == NULL) { + talloc_free(hTalloc); return -1; } /* Begin a transaction */ if (LOCK_DB(module, "transaction") < 0) { + talloc_free(hTalloc); return -1; } /* * Obtain the eid of the base DN */ - if ((ret = query_int(lsqlite3, - &eid, - "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE normalized_dn = %Q;", - pNormalizedBaseDN)) == SQLITE_DONE) { + if ((ret = getEID(lsqlite3, &eid, pNormalizedBaseDN)) == SQLITE_DONE) { UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); return 0; @@ -685,9 +689,15 @@ lsqlite3_search_bytree(struct ldb_module * module, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); } + continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -730,6 +740,11 @@ lsqlite3_search_bytree(struct ldb_module * module, } if (ret == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + (void) sqlite3_finalize(pStmt); if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); @@ -743,7 +758,11 @@ lsqlite3_search_bytree(struct ldb_module * module, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); } @@ -916,13 +935,7 @@ lsqlite3_modify(struct ldb_module * module, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE normalized_dn = %Q;", - pNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); /* Apply the message attributes */ if (msg_to_sql(module, msg, eid, TRUE) != 0) { @@ -1068,6 +1081,9 @@ initialize(struct lsqlite3_private *lsqlite3, "CREATE INDEX ldb_attribute_values_eid_idx " " ON ldb_attribute_values (eid);" + "CREATE INDEX ldb_attribute_values_name_value_idx " + " ON ldb_attribute_values (attr_name, attr_value_normalized);" + /* @@ -1351,7 +1367,7 @@ query_norows(const struct lsqlite3_private *lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; - double t0; + double t0 = 0; double t1; struct timeval tv; struct timezone tz; @@ -1382,6 +1398,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -1390,6 +1410,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* No rows expected, so just step through machine code once */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } (void) sqlite3_finalize(pStmt); continue; } else if (ret != SQLITE_DONE) { @@ -1400,7 +1424,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -1454,7 +1481,7 @@ query_int(const struct lsqlite3_private * lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; - double t0; + double t0 = 0; double t1; struct timeval tv; struct timezone tz; @@ -1489,6 +1516,10 @@ query_int(const struct lsqlite3_private * lsqlite3, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { break; @@ -1496,6 +1527,10 @@ query_int(const struct lsqlite3_private * lsqlite3, /* One row expected */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } (void) sqlite3_finalize(pStmt); continue; } else if (ret != SQLITE_ROW) { @@ -1508,7 +1543,10 @@ query_int(const struct lsqlite3_private * lsqlite3, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -1541,6 +1579,92 @@ query_int(const struct lsqlite3_private * lsqlite3, } +/* + * getEID() + * + * This function is used for the very common case of retrieving an EID value + * given a normalized DN. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. + */ +static int +getEID(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pNormalizedDN) +{ + int ret; + int bLoop; + const char * query = + "SELECT eid\n" + " FROM ldb_attribute_values\n" + " WHERE attr_name = 'DN'\n" + " AND attr_value_normalized = :dn;"; + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + ret = SQLITE_OK; + if (stmtGetEID == NULL && + (ret = sqlite3_prepare(lsqlite3->sqlite, + query, + -1, + &stmtGetEID, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + break; + } + + /* Bind our parameter */ + if ((ret = sqlite3_bind_text(stmtGetEID, + 1, + pNormalizedDN, + -1, + SQLITE_STATIC)) != SQLITE_OK) { + break; + } + + /* One row expected */ + if ((ret = sqlite3_step(stmtGetEID)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_reset(stmtGetEID); + break; + } + + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(stmtGetEID, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_reset(stmtGetEID)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + bLoop = FALSE; + } + + return ret; +} + + /* callback function used in call to ldb_dn_fold() for determining whether an attribute type requires case folding. @@ -2072,8 +2196,9 @@ new_dn(struct ldb_module * module, char * pDN, long long * pEID) { - int nComponent; + int ret; int bFirst; + int nComponent; char * p; char * pPartialDN; char * pPartialNormalizedDN; @@ -2159,7 +2284,10 @@ new_dn(struct ldb_module * module, /* Save the new partial DN */ pPartialDN = p; - pPartialNormalizedDN = ldb_dn_fold(pPartialDN, p, module, case_fold_attr_required); + pPartialNormalizedDN = ldb_dn_fold(pPartialDN, + p, + module, + case_fold_attr_required); if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { gettimeofday(&tv, NULL); @@ -2171,62 +2299,60 @@ new_dn(struct ldb_module * module, /* * Ensure that an entry is in the ldb_entry table for this - * component. Any component other than the last one - * (component 0) may already exist. It is an error if - * component 0 (the full DN requested to be be inserted) - * already exists. + * component. */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_entry\n" - " (peid, dn, normalized_dn)\n" - " VALUES\n" - " (%lld, %Q, %Q);", - nComponent == 0 ? "" : "OR IGNORE", - eid, pPartialDN, pPartialNormalizedDN); - - /* Save the parent EID */ - peid = eid; + if ((ret = getEID(lsqlite3, + &eid, + pPartialNormalizedDN)) == SQLITE_DONE) { + + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_entry\n" + " (peid, dn, normalized_dn)\n" + " VALUES\n" + " (%lld, %Q, %Q);", + eid, pPartialDN, pPartialNormalizedDN); + + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 5\n", t1 - t0); + t0 = t1; + } - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 5\n", t1 - t0); - t0 = t1; - } + /* Get the EID of the just inserted row */ + eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); + + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 8\n", t1 - t0); + t0 = t1; + } - /* Get the EID of the just inserted row */ - QUERY_INT(lsqlite3, - eid, - FALSE, - "SELECT eid " - " FROM ldb_entry " - " WHERE normalized_dn = %Q;", - pPartialNormalizedDN); + /* Also add DN attribute */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_attribute_values\n" + " (eid,\n" + " attr_name,\n" + " attr_value,\n" + " attr_value_normalized) " + " VALUES " + " (%lld, 'DN', %Q, %Q);", + eid, + pPartialDN, /* FIX ME */ + pPartialNormalizedDN); - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 8\n", t1 - t0); - t0 = t1; + } else if (ret != SQLITE_OK) { + UNLOCK_DB(module, "rollback"); + return -1; } - - /* Also add DN attribute */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_attribute_values\n" - " (eid,\n" - " attr_name,\n" - " attr_value,\n" - " attr_value_normalized) " - " VALUES " - " (%lld, 'DN', %Q, %Q);", - nComponent == 0 ? "" : "OR IGNORE", - eid, - pPartialDN, /* FIX ME */ - pPartialNormalizedDN); + + /* Save the parent EID */ + peid = eid; } if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 3d3c63397b..46ee1e93ba 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -2,14 +2,6 @@ struct lsqlite3_private { char ** options; - const char * basedn; sqlite3 * sqlite; int lock_count; }; - -void -lsqlite3_base160(unsigned long val, - unsigned char result[5]); - -char * -lsqlite3_base160Next(char base160[]); diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 31d3f2662a..606c511600 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -38,7 +38,10 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { struct ldb_cmdline options, *ret=NULL; poptContext pc; - int r, num_options = 0; +#ifdef _SAMBA_BUILD_ + int r; +#endif + int num_options = 0; char opt; struct poptOption popt_options[] = { POPT_AUTOHELP -- cgit From 2ea96684bc1e649940818429c5edf3a03338fe10 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Jun 2005 23:35:37 +0000 Subject: r7909: don't consider not finding a list of network interfaces from the kernel a fatal error, the individual services that need at least one known interface check for it anyway this should fix provisioning on macosx (This used to be commit 5ad0dc97d01e28dbce8bc9d6793db01809ad09b0) --- source4/lib/netif/interface.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 78f4456cd8..80041d5350 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -219,7 +219,6 @@ void load_interfaces(void) if (!ptr || !*ptr || !**ptr) { if (total_probed <= 0) { DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); - exit(1); } for (i=0;i Date: Sat, 25 Jun 2005 23:38:03 +0000 Subject: r7910: fixed typo in _SAMBA_BUILD_ macro (This used to be commit d2e9e95ea2cab80badc23f0f1d416295f0a4bf9c) --- source4/lib/socket_wrapper/socket_wrapper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 42bac4bfae..d283e12f23 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -19,7 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifdef _SAMBA_BUILD +#ifdef _SAMBA_BUILD_ #include "includes.h" #include "system/network.h" #include "system/filesys.h" @@ -35,8 +35,8 @@ #include #include #include -#include "dlinklist.h" #endif +#include "dlinklist.h" /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support * for now */ -- cgit From 8c53aba485e7986baacf91b2c99ef7999142aee4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Jun 2005 00:12:44 +0000 Subject: r7912: make private_path() recognise a non-relative filename, so we can have sam database = sam.ldb and it will know to put it in the private dir, but if you use sam database = ldap://server it knows to use it as-is (This used to be commit c5bccbc366db144d3e1cb7b21f0e3284d841dd06) --- source4/lib/db_wrap.c | 12 ++++++++++-- source4/lib/tls/tls.c | 28 +++++++++++++++++++++------- source4/lib/util.c | 8 +++++++- 3 files changed, 38 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index b000225bbf..c0240aa62d 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -83,7 +83,7 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, struct ldb_wrap *w; int ret; struct event_context *ev; - + char *real_url = NULL; for (w = ldb_list; w; w = w->next) { if (strcmp(url, w->url) == 0) { @@ -112,13 +112,21 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, talloc_free(ldb); return NULL; } + + real_url = private_path(ldb, url); + if (real_url == NULL) { + talloc_free(ldb); + return NULL; + } - ret = ldb_connect(ldb, url, flags, options); + ret = ldb_connect(ldb, real_url, flags, options); if (ret == -1) { talloc_free(ldb); return NULL; } + talloc_free(real_url); + w = talloc(ldb, struct ldb_wrap); if (w == NULL) { talloc_free(ldb); diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c index f89e2f1028..12087639c1 100644 --- a/source4/lib/tls/tls.c +++ b/source4/lib/tls/tls.c @@ -309,17 +309,22 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) { struct tls_params *params; int ret; - const char *keyfile = lp_tls_keyfile(); - const char *certfile = lp_tls_certfile(); - const char *cafile = lp_tls_cafile(); - const char *crlfile = lp_tls_crlfile(); + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + const char *keyfile = private_path(tmp_ctx, lp_tls_keyfile()); + const char *certfile = private_path(tmp_ctx, lp_tls_certfile()); + const char *cafile = private_path(tmp_ctx, lp_tls_cafile()); + const char *crlfile = private_path(tmp_ctx, lp_tls_crlfile()); void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *); params = talloc(mem_ctx, struct tls_params); - if (params == NULL) return NULL; + if (params == NULL) { + talloc_free(tmp_ctx); + return NULL; + } if (!lp_tls_enabled() || keyfile == NULL || *keyfile == 0) { params->tls_enabled = False; + talloc_free(tmp_ctx); return params; } @@ -371,11 +376,13 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx) params->tls_enabled = True; + talloc_free(tmp_ctx); return params; init_failed: DEBUG(0,("GNUTLS failed to initialise - %s\n", gnutls_strerror(ret))); params->tls_enabled = False; + talloc_free(tmp_ctx); return params; } @@ -450,6 +457,8 @@ struct tls_context *tls_init_client(struct socket_context *socket, struct tls_context *tls; int ret; const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; + char *cafile; + tls = talloc(socket, struct tls_context); if (tls == NULL) return NULL; @@ -461,11 +470,16 @@ struct tls_context *tls_init_client(struct socket_context *socket, return tls; } + cafile = private_path(tls, lp_tls_cafile()); + if (!cafile || !*cafile) { + goto failed; + } + gnutls_global_init(); gnutls_certificate_allocate_credentials(&tls->xcred); - gnutls_certificate_set_x509_trust_file(tls->xcred, lp_tls_cafile(), - GNUTLS_X509_FMT_PEM); + gnutls_certificate_set_x509_trust_file(tls->xcred, cafile, GNUTLS_X509_FMT_PEM); + talloc_free(cafile); TLSCHECK(gnutls_init(&tls->session, GNUTLS_CLIENT)); TLSCHECK(gnutls_set_default_priority(tls->session)); gnutls_certificate_type_set_priority(tls->session, cert_type_priority); diff --git a/source4/lib/util.c b/source4/lib/util.c index ba2c0e1ae4..308d1b6f45 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -657,13 +657,19 @@ char *lib_path(TALLOC_CTX* mem_ctx, const char *name) * @brief Returns an absolute path to a file in the Samba private directory. * * @param name File to find, relative to PRIVATEDIR. + * if name is not relative, then use it as-is * * @retval Pointer to a talloc'ed string containing the full path. **/ - char *private_path(TALLOC_CTX* mem_ctx, const char *name) { char *fname; + if (name == NULL) { + return NULL; + } + if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) { + return talloc_strdup(mem_ctx, name); + } fname = talloc_asprintf(mem_ctx, "%s/%s", lp_private_dir(), name); return fname; } -- cgit From eb11eeb5dbeccd7710f92dc0639df36aad06c46b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Jun 2005 00:20:22 +0000 Subject: r7913: prevent recursion in the socket wrapper code (This used to be commit c1a0c2042d5bfce5781197919482481c007ff1b3) --- source4/lib/socket_wrapper/socket_wrapper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index d283e12f23..940883a45f 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -21,6 +21,7 @@ #ifdef _SAMBA_BUILD_ #include "includes.h" +#undef SOCKET_WRAPPER #include "system/network.h" #include "system/filesys.h" #else -- cgit From 6a7119fc83326b8243a1ce4598fe6b6c4b013e45 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Jun 2005 06:09:03 +0000 Subject: r7926: poptGetNextOpt() returns int, not char this was breaking ldbadd on some platforms (This used to be commit dd0ac3f68d709c0364d992673e76db73398c0369) --- source4/lib/ldb/tools/cmdline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 606c511600..48dc8ddd47 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -42,7 +42,7 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const int r; #endif int num_options = 0; - char opt; + int opt; struct poptOption popt_options[] = { POPT_AUTOHELP { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, -- cgit From 1702f52498168c0437416dec1014cedead634774 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 26 Jun 2005 23:59:22 +0000 Subject: r7936: new ldb_dn_explode and ldb_dn_casefold functions and co (This used to be commit 7ccf21ab4eeb9821e457308a239f2103a106fb12) --- source4/lib/ldb/Makefile.in | 2 +- source4/lib/ldb/common/ldb_utf8.c | 80 +-------------------------------------- source4/lib/ldb/config.mk | 2 +- source4/lib/ldb/include/ldb.h | 1 + source4/lib/ldb/ldb_tdb/ldb_tdb.c | 48 ++++++++++++++++++++--- source4/lib/talloc/talloc.c | 22 +++++++++++ source4/lib/talloc/talloc.h | 1 + 7 files changed, 70 insertions(+), 86 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index a633320d06..ac3155f27e 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -52,7 +52,7 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ common/ldb_debug.o common/ldb_modules.o \ - common/ldb_explode_dn.o + common/ldb_dn.o MODULES_OBJ=modules/timestamps.o modules/schema.o diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index ae35ad81b6..0c1ea6ca81 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -59,7 +59,7 @@ char *ldb_casefold(void *mem_ctx, const char *s) a caseless compare, optimised for 7 bit TODO: doesn't yet handle UTF8 */ -static int ldb_caseless_cmp(const char *s1, const char *s2) +int ldb_caseless_cmp(const char *s1, const char *s2) { int i; for (i=0;s1[i] != 0;i++) { @@ -89,81 +89,3 @@ int ldb_attr_cmp(const char *dn1, const char *dn2) return ldb_caseless_cmp(dn1, dn2); } - -/* - casefold a dn. We need to uppercase the attribute names, and the - attribute values of case insensitive attributes. We also need to remove - extraneous spaces between elements -*/ -char *ldb_dn_fold(void * mem_ctx, - const char * dn, - void * user_data, - int (* case_fold_attr_fn)(void * user_data, char * attr)) -{ - const char *dn_orig = dn; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - char *ret; - size_t len; - - ret = talloc_strdup(tmp_ctx, ""); - if (ret == NULL) goto failed; - - while ((len = strcspn(dn, ",")) > 0) { - char *p = strchr(dn, '='); - char *attr, *value; - int case_fold_required; - - if (p == NULL || (p-dn) > len) goto failed; - - attr = talloc_strndup(tmp_ctx, dn, p-dn); - if (attr == NULL) goto failed; - - /* trim spaces from the attribute name */ - while (' ' == *attr) attr++; - while (' ' == attr[strlen(attr)-1]) { - attr[strlen(attr)-1] = 0; - } - if (*attr == 0) goto failed; - - value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn)); - if (value == NULL) goto failed; - - /* trim spaces from the value */ - while (' ' == *value) value++; - while (' ' == value[strlen(value)-1]) { - value[strlen(value)-1] = 0; - } - if (*value == 0) goto failed; - - case_fold_required = case_fold_attr_fn(user_data, attr); - - attr = ldb_casefold(tmp_ctx, attr); - if (attr == NULL) goto failed; - talloc_steal(tmp_ctx, attr); - - if (case_fold_required) { - value = ldb_casefold(tmp_ctx, value); - if (value == NULL) goto failed; - talloc_steal(tmp_ctx, value); - } - - if (dn[len] == ',') { - ret = talloc_asprintf_append(ret, "%s=%s,", attr, value); - } else { - ret = talloc_asprintf_append(ret, "%s=%s", attr, value); - } - if (ret == NULL) goto failed; - - dn += len; - if (*dn == ',') dn++; - } - - talloc_steal(mem_ctx, ret); - talloc_free(tmp_ctx); - return ret; - -failed: - talloc_free(tmp_ctx); - return ldb_casefold(mem_ctx, dn_orig); -} - diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index cf3a7fa93d..61bd8f0152 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -70,7 +70,7 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_debug.o \ lib/ldb/common/ldb_modules.o \ - lib/ldb/common/ldb_explode_dn.o + lib/ldb/common/ldb_dn.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE LIBTALLOC LDBSAMBA NOPROTO = YES diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 1b5c7c4f57..8feec9e002 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -279,6 +279,7 @@ const char *ldb_errstring(struct ldb_context *ldb); casefold a string (should be UTF8, but at the moment it isn't) */ char *ldb_casefold(void *mem_ctx, const char *s); +int ldb_caseless_cmp(const char *s1, const char *s2); /* ldif manipulation functions diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index f8c98d6712..bc61378f18 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -38,6 +38,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" +#include "ldb/include/ldb_dn.h" #include "ldb/ldb_tdb/ldb_tdb.h" #define LDBLOCK "INT_LDBLOCK" @@ -107,9 +108,30 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) talloc_free(attr_name_folded); } talloc_free(attr_name); - } else { - dn_folded = ldb_dn_fold(module->ldb, dn, - module, ltdb_case_fold_attr_required); + } + /* special cases for tdb */ + else if (*dn == '@' || strncmp(LDBLOCK, dn, strlen(LDBLOCK)) == 0) { + + dn_folded = talloc_strdup(ldb, dn); + } + else { + struct ldb_dn *edn, *cedn; + + edn = ldb_dn_explode(ldb, dn); + if (!edn) + goto failed; + + cedn = ldb_dn_casefold(ldb, edn, module, + ltdb_case_fold_attr_required); + if (!edn) + goto failed; + + dn_folded = ldb_dn_linearize(ldb, cedn); + if (!dn_folded) + goto failed; + + talloc_free(edn); + talloc_free(cedn); } if (!dn_folded) { @@ -141,6 +163,7 @@ failed: static int ltdb_lock(struct ldb_module *module, const char *lockname) { struct ltdb_private *ltdb = module->private_data; + char *lock_dn; TDB_DATA key; int ret; @@ -148,14 +171,21 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) return -1; } - key = ltdb_key(module, lockname); + lock_dn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + if (lock_dn == NULL) { + return -1; + } + + key = ltdb_key(module, lock_dn); if (!key.dptr) { + talloc_free(lock_dn); return -1; } ret = tdb_chainlock(ltdb->tdb, key); talloc_free(key.dptr); + talloc_free(lock_dn); return ret; } @@ -166,20 +196,28 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) static int ltdb_unlock(struct ldb_module *module, const char *lockname) { struct ltdb_private *ltdb = module->private_data; + char *lock_dn; TDB_DATA key; if (lockname == NULL) { return -1; } - key = ltdb_key(module, lockname); + lock_dn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + if (lock_dn == NULL) { + return -1; + } + + key = ltdb_key(module, lock_dn); if (!key.dptr) { + talloc_free(lock_dn); return -1; } tdb_chainunlock(ltdb->tdb, key); talloc_free(key.dptr); + talloc_free(lock_dn); return 0; } diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 08d4cb93a6..3adf741870 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -917,6 +917,28 @@ char *talloc_strdup(const void *t, const char *p) return ret; } +/* + append to a talloced string +*/ +char *talloc_append_string(const void *t, char *orig, const char *append) +{ + char *ret; + size_t olen = strlen(orig); + size_t alenz = strlen(append) + 1; + + if (!append) + return orig; + + ret = talloc_realloc(t, orig, char, olen + alenz); + if (!ret) + return NULL; + + /* append the string with the trailing \0 */ + memcpy(&ret[olen], append, alenz); + + return ret; +} + /* strndup with a talloc */ diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 04d5cbb9af..d68510abef 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -119,6 +119,7 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name); void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); char *talloc_strdup(const void *t, const char *p); char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, -- cgit From e1e95277c0c7f86b15acd70ee3151ec2b3131c5e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 27 Jun 2005 00:00:50 +0000 Subject: r7937: main file was missing (This used to be commit 3898cdb0dc4722a7eb60a61b54ef778dab475aed) --- source4/lib/ldb/common/ldb_dn.c | 471 ++++++++++++++++++++++++++++ source4/lib/ldb/common/ldb_explode_dn.c | 512 ------------------------------- source4/lib/ldb/include/ldb_dn.h | 42 +++ source4/lib/ldb/include/ldb_explode_dn.h | 46 --- 4 files changed, 513 insertions(+), 558 deletions(-) create mode 100644 source4/lib/ldb/common/ldb_dn.c delete mode 100644 source4/lib/ldb/common/ldb_explode_dn.c create mode 100644 source4/lib/ldb/include/ldb_dn.h delete mode 100644 source4/lib/ldb/include/ldb_explode_dn.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c new file mode 100644 index 0000000000..7ae314e46c --- /dev/null +++ b/source4/lib/ldb/common/ldb_dn.c @@ -0,0 +1,471 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb dn explode and utility functions + * + * Description: - explode a dn into it's own basic elements + * and put them in a structure + * - manipulate ldb_dn structures + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/include/ldb_dn.h" + + +#define LDB_DN_NULL_RETURN(x) do { if (!x) return NULL; } while(0) + +static char *escape_string(void *mem_ctx, const char *src) +{ + const char *p, *s; + char *d, *dst; + + LDB_DN_NULL_RETURN(src); + + /* allocate destination string, it will be at most 3 times the source */ + dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1); + LDB_DN_NULL_RETURN(dst); + + p = s = src; + + while (p) { + p += strcspn(p, ",=\n+<>#;\\\""); + if (*p == '\0') /* no special s found, all ok */ + break; + + if (*p) { /* copy part of the string and escape */ + memcpy(d, s, p - s); + d += (p - s); + *d++ = '\\'; + *d++ = *p++; + s = p; + } + } + + /* copy the last part (with zero) and return */ + memcpy(d, s, &src[strlen(src)] - s + 1); + + return dst; +} + +static char *unescape_string(void *mem_ctx, const char *src) +{ + unsigned x; + char *p, *dst, *end; + + LDB_DN_NULL_RETURN(src); + + dst = p = talloc_strdup(mem_ctx, src); + LDB_DN_NULL_RETURN(dst); + + end = &dst[strlen(dst)]; + + while (*p) { + p += strcspn(p, ",=\n+<>#;\\\""); + if (*p == '\0') /* no escapes or specials found, all ok */ + return dst; + + if (*p == '\\') { + if (strchr(",=\n+<>#;\\\"", p[1])) { + memmove(p, p + 1, end - (p + 1) + 1); + end--; + p++; + continue; + } + + if (sscanf(p + 1, "%02x", &x) == 1) { + *p = (unsigned char)x; + memmove(p + 1, p + 3, end - (p + 3) + 1); + end -= 2; + p++; + continue; + } + } + + /* a string with not escaped specials is invalid */ + + return NULL; + } + + return dst; +} + +static char *seek_to_separator(char *string, const char *separator) +{ + char *p; + + p = strchr(string, '='); + + LDB_DN_NULL_RETURN(p); + + p++; + + /* check if there are quotes surrounding the value */ + p += strspn(p, " \n"); /* skip white spaces after '=' */ + + if (*p == '\"') { + p++; + while (*p != '\"') { + p = strchr(p, '\"'); + LDB_DN_NULL_RETURN(p); + + if (*(p - 1) == '\\') + p++; + } + } + + p += strcspn(p, separator); + + return p; +} + +static char *ldb_dn_trim_string(char *string, const char *edge) +{ + char *s, *p; + + /* seek out edge from start of string */ + s = string + strspn(string, edge); + + /* backwards skip from end of string */ + p = &s[strlen(s) - 1]; + while (p > s && strchr(edge, *p)) { + *p = '\0'; + p--; + } + + return s; +} + +static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *raw_attribute) +{ + struct ldb_dn_attribute *at; + char *p; + + at = talloc(mem_ctx, struct ldb_dn_attribute); + LDB_DN_NULL_RETURN(at); + + p = strchr(raw_attribute, '='); + + LDB_DN_NULL_RETURN(p); + + *p = '\0'; + + at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n")); + LDB_DN_NULL_RETURN(at->name); + + p++; + + p = ldb_dn_trim_string(p, " \n"); + + if (*p == '\"') { /* quotes at start means there must be quotes at the end */ + if (p[strlen(p) - 1] != '\"') /* malformed value */ + return NULL; + + p++; + p[strlen(p) - 1] = '\0'; + at->value = talloc_strdup(at, p); + + return at; + } + /* no quotes means we must unescape the string */ + at->value = unescape_string(at, p); + LDB_DN_NULL_RETURN(at->value); + + return at; +} + +static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component) +{ + struct ldb_dn_component *dc; + char *p; + + dc = talloc(mem_ctx, struct ldb_dn_component); + LDB_DN_NULL_RETURN(dc); + + dc->attr_num = 0; + dc->attributes = NULL; + + p = raw_component; + + /* get the components */ + do { + char *t; + + /* terminate the current attribute and return pointer to the next one */ + t = seek_to_separator(p, "+"); + LDB_DN_NULL_RETURN(t); + + if (*t) { /* here there is a separator */ + *t = '\0'; /*terminate */ + t++; /* a separtor means there's another attribute that follows */ + } + + /* allocate attributes pointer */ + dc->attributes = talloc_realloc(dc, dc->attributes, + struct ldb_dn_attribute *, + dc->attr_num + 1); + LDB_DN_NULL_RETURN(dc->attributes); + + /* store the exploded attirbute in the main structure */ + dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p); + LDB_DN_NULL_RETURN(dc->attributes[dc->attr_num]); + + dc->attr_num++; + + /* jump to the next attribute if any */ + p = t; + + } while(*p); + + return dc; +} + +/* FIXME: currently consider a dn composed of only case insensitive attributes + this is not correct and need to be fixed soon */ +static void ldb_dn_sort_attributes(struct ldb_dn *edn) +{ + struct ldb_dn_attribute *at0, *at1; + int i, j, k, l; + + for (i = 0; i < edn->comp_num; i++) { + if (edn->components[i]->attr_num > 1) { + + /* it is very unlikely that there is a multivalued RDN. In that + unlikely case it is very unlikely you will find more than 2 + values. So the use of bubble sort here seem to be acceptable */ + for (j = 0; (j + 1) < edn->components[i]->attr_num; j++) { + for (k = j; k >= 0; k--) { + at0 = edn->components[i]->attributes[k]; + at1 = edn->components[i]->attributes[k + 1]; + l = ldb_caseless_cmp(at0->name, at1->name); + if (l > 0) { + /* already sorted, so no bubbles to move exit inner loop */ + break; + } + if (l == 0) { + if (ldb_caseless_cmp(at0->value, at1->value) >= 0) { + /* already sorted, so no bubbles to move exit inner loop */ + break; + } + } + + edn->components[i]->attributes[k] = at1; + edn->components[i]->attributes[k + 1] = at0; + } + } + } + } +} + +struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) +{ + struct ldb_dn *edn; /* the exploded dn */ + char *pdn, *p; + + /* Allocate a structure to hold the exploded DN */ + edn = talloc(mem_ctx, struct ldb_dn); + LDB_DN_NULL_RETURN(edn); + + /* Initially there are no components */ + edn->comp_num = 0; + edn->components = NULL; + + pdn = p = talloc_strdup(edn, dn); + if (!pdn) + goto error; + + /* get the components */ + do { + char *t; + + /* terminate the current component and return pointer to the next one */ + t = seek_to_separator(p, ",;"); + if (t == NULL) + goto error; + + if (*t) { /* here there is a separator */ + *t = '\0'; /*terminate */ + t++; /* a separtor means there's another component that follows */ + } + + /* allocate space to hold the dn component */ + edn->components = talloc_realloc(edn, edn->components, + struct ldb_dn_component *, + edn->comp_num + 1); + if (edn->components == NULL) + goto error; + + /* store the exploded component in the main structure */ + edn->components[edn->comp_num] = explode_component(edn->components, p); + if (edn->components[edn->comp_num] == NULL) + goto error; + + edn->comp_num++; + + /* jump to the next component if any */ + p = t; + + } while(*p); + + /* sort attributes if there's any multivalued component */ + ldb_dn_sort_attributes(edn); + + talloc_free(pdn); + return edn; + +error: + talloc_free(edn); + return NULL; +} + +char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn) +{ + char *dn, *format, *ename, *evalue; + int i, j; + + dn = talloc_strdup(mem_ctx, ""); + LDB_DN_NULL_RETURN(dn); + + for (i = 0; i < edn->comp_num; i++) { + if (i != 0) { + dn = talloc_append_string(mem_ctx, dn, ","); + } + for (j = 0; j < edn->components[i]->attr_num; j++) { + if (i != 0 && j == 0) + format = ",%s=%s"; + else if (i == 0 && j == 0) + format = "%s=%s"; + else + format = "+%s=%s"; + + ename = escape_string(mem_ctx, edn->components[i]->attributes[j]->name); + LDB_DN_NULL_RETURN(ename); + + evalue = escape_string(mem_ctx, edn->components[i]->attributes[j]->value); + LDB_DN_NULL_RETURN(evalue); + + dn = talloc_asprintf_append(dn, format, ename, evalue); + LDB_DN_NULL_RETURN(dn); + + talloc_free(ename); + talloc_free(evalue); + } + } + + return dn; +} + +/* FIXME: currently consider a dn composed of only case insensitive attributes + this is not correct and need to be fixed soon */ +int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1) +{ + struct ldb_dn_attribute *at0, *at1; + int i, j, k; + + /* if the number of components doesn't match they differ */ + if (edn0->comp_num != edn1->comp_num) + return (edn1->comp_num - edn0->comp_num); + + for (i = 0; i < edn0->comp_num; i++) { + + /* if the number of attributes per component doesn't match they differ */ + if (edn0->components[i]->attr_num != edn1->components[i]->attr_num) + return (edn1->components[i]->attr_num - edn0->components[i]->attr_num); + + for (j = 0; j < edn0->components[i]->attr_num; j++) { + at0 = edn0->components[i]->attributes[j]; + at1 = edn1->components[i]->attributes[j]; + + /* compare names */ + k = ldb_caseless_cmp(at0->name, at1->name); + if (k) + return k; + + /* names match, compare values */ + k = ldb_caseless_cmp(at0->value, at1->value); + if (k) + return k; + } + } +} + +/* + casefold a dn. We need to uppercase the attribute names, and the + attribute values of case insensitive attributes. We also need to remove + extraneous spaces between elements +*/ +struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data, + int (* case_fold_attr_fn)(void * user_data, char * attr)) +{ + struct ldb_dn *cedn; + int i, j; + + cedn = talloc(mem_ctx, struct ldb_dn); + LDB_DN_NULL_RETURN(cedn); + + cedn->comp_num = edn->comp_num; + cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num); + LDB_DN_NULL_RETURN(cedn->components); + + for (i = 0; i < edn->comp_num; i++) { + struct ldb_dn_component *dc; + + dc = talloc(cedn->components, struct ldb_dn_component); + LDB_DN_NULL_RETURN(dc); + + dc->attr_num = edn->components[i]->attr_num; + dc->attributes = edn->components[i]->attributes; + LDB_DN_NULL_RETURN(dc->attributes); + + for (j = 0; j < edn->components[i]->attr_num; j++) { + struct ldb_dn_attribute *at; + + at = talloc(dc->attributes, struct ldb_dn_attribute); + LDB_DN_NULL_RETURN(at); + + at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name); + LDB_DN_NULL_RETURN(at->name); + + if (case_fold_attr_fn(user_data, at->name)) { + at->value = ldb_casefold(at, edn->components[i]->attributes[j]->value); + } else { + at->value = talloc_strdup(at, edn->components[i]->attributes[j]->value); + } + LDB_DN_NULL_RETURN(at->value); + + dc->attributes[j] = at; + } + + cedn->components[i] = dc; + } + + return cedn; +} + diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c deleted file mode 100644 index 0e2efa876c..0000000000 --- a/source4/lib/ldb/common/ldb_explode_dn.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2004 - Copyright (C) Derrell Lipman 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb dn parsing - * - * Description: explode a dn into it's own basic elements - * and put them in a structure - * - * Author: Simo Sorce - * Author: Derrell Lipman - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" -#include "ldb/include/ldb_explode_dn.h" - -#define LDB_PARSE_DN_INVALID(x) do { \ - if (x) { \ - goto failed; \ - } \ -} while(0) - - -/* - * Forward declarations - */ - -static char * -parse_slash(char *p, - char *end); - - - -/* - * Public functions - */ - -/* - * ldb_explode_dn() - * - * Explode, normalize, and optionally case-fold a DN string. The result is a - * structure containing arrays of the constituent RDNs. - * - * Parameters: - * mem_ctx - - * talloc context on which all allocated memory is hung - * - * orig_dn - - * The distinguished name, in string format, to be exploded - * - * hUserData - - * Data handle provided by the caller, and passed back to the caller in - * the case_fold_attr_fn callback function. This handle is not otherwise - * used within this function. - * - * case_fold_attr_fn - - * Pointer to a callback function which will be called to determine if a - * particular attribute type (name) requires case-folding of its values. - * If this function pointer is non-null, then attribute names will always - * be case-folded. Additionally, the function pointed to by - * case_fold_attr_fn will be called with the data handle (hUserData) and - * an attribute name as its parameters, and should return TRUE or FALSE to - * indicate whether values of that attribute type should be case-folded. - * - * If case_fold_attr_fn is null, then neither attribute names nor - * attribute values will be case-folded. - * - * Returns: - * Upon success, an ldb_dn structure pointer is returned, containing the - * exploded DN. - * - * If memory could not be allocated or if the DN was improperly formatted, - * NULL is returned. - */ -struct ldb_dn * -ldb_explode_dn(void * mem_ctx, - const char * orig_dn, - void * hUserData, - int (*case_fold_attr_fn)(void * hUserData, - char * attr)) -{ - struct ldb_dn * dn; - struct ldb_dn_component * component; - struct ldb_dn_attribute * attribute; - char * p; - char * start; - char * separator; - char * src; - char * dest; - char * dn_copy; - char * dn_end; - int i; - int size; - int orig_len; - - /* Allocate a structure to hold the exploded DN */ - if ((dn = talloc(mem_ctx, struct ldb_dn)) == NULL) { - return NULL; - } - - /* Initially there are no components */ - dn->comp_num = 0; - - /* Allocate the component array, with space for one component */ - if ((dn->components = - talloc_array(dn, struct ldb_dn_component *, 1)) == NULL) { - - goto failed; - } - - /* Allocate the first component */ - if ((component = talloc(dn, struct ldb_dn_component)) == NULL) { - goto failed; - } - - /* This component has no attributes yet */ - component->attr_num = 0; - - /* Get the length of the provided DN */ - if ((orig_len = strlen(orig_dn)) == 0) { - - /* We found a zero-length DN. Return it. */ - if ((dn->dn = talloc_strdup(dn, orig_dn)) == NULL) { - goto failed; - } - return dn; - } - - /* Copy the provided DN so we can manipulate it */ - if ((dn_copy = talloc_strdup(mem_ctx, orig_dn)) == NULL) { - goto failed; - } - - p = dn_copy; - - /* Our copy may end shorter than the original as we unescape chars */ - dn_end = dn_copy + orig_len + 1; - - /* For each attribute/value pair... */ - do { - /* Allocate an array to hold the attributes, initially len 1 */ - if ((component->attributes = - talloc_array(component, - struct ldb_dn_attribute *, 1)) == NULL) { - goto failed; - } - - /* Allocate this attribute */ - if ((attribute = - talloc(component, struct ldb_dn_attribute)) == NULL) { - goto failed; - } - - /* skip white space */ - while (*p == ' ' || *p == '\n') { - p++; - } - - /* start parsing this component */ - do { - /* Save pointer to beginning of attribute name */ - start = p; - - /* find our attribute/value separator '=' */ - while (*p != '\0' && *p != '=') { - if (*p == '\\') { - if ((dn_end = - parse_slash(p, dn_end)) == NULL) { - goto failed; - } - } - p++; - } - - /* Ensure we found the attribute/value separator */ - if (*p != '=') { - goto failed; - } - - /* Save pointer to separator */ - separator = p; - - /* remove trailing white space from attribute name */ - while (p > start && - (*(p - 1) == ' ' || *(p - 1) == '\n')) { - - p--; - } - LDB_PARSE_DN_INVALID((p - start) < 1); - - /* save attribute name */ - if ((attribute->name = - talloc_strndup(attribute, - start, - p - start)) == NULL) { - goto failed; - } - - /* see if this attribute name needs case folding */ - if (case_fold_attr_fn != NULL && - (* case_fold_attr_fn)(hUserData, - attribute->name)) { - p = attribute->name; - if ((attribute->name = - ldb_casefold(attribute, p)) == NULL) { - goto failed; - } - talloc_free(p); - } - - ldb_debug(mem_ctx, - LDB_DEBUG_TRACE, - "attribute name: [%s]\n", attribute->name); - - /* skip white space after the separator */ - p = separator + 1; - p += strspn(p, " \n"); - - /* ensure there's a value here */ - if (*p == '\0') { - goto failed; - } - - /* check if the value is enclosed in QUOTATION */ - if (*p == '"') { - /* save pointer to beginning of attr value */ - start = p + 1; - - /* find the trailing QUOTE */ - while (*p != '\0' && *p != '"') { - if (*p == '\\') { - if ((dn_end = - parse_slash(p, dn_end)) == NULL) { - goto failed; - } - } - - p++; - } - - /* skip spaces until the separator */ - if (*p == '\0') { - /* We're already at end of string */ - separator = p; - } else { - /* Skip spaces */ - separator = p + 1 + strspn(p+1, " \n"); - } - - /* must be end of string or a separator here */ - if (*separator != '\0' && - *separator != ',' && - *separator != ';' && - *separator != '+') { - /* Error Malformed DN */ - goto failed; - } - } else { - /* - * Value is not quouted. - */ - - /* save pointer to beginning of value */ - start = p; - - /* find end of value */ - while (*p != '\0' && - *p != ',' && - *p != ';' && - *p != '+') { - - if (*p == '\\') { - if ((dn_end = - parse_slash(p, dn_end)) == NULL) { - goto failed; - } - } - - p++; - } - - /* save pointer to the terminating separator */ - separator = p; - - /* remove trailing whitespace */ - while (p > start && - (*(p - 1) == ' ' || - *(p - 1) == '\n')) { - - p--; - } - } - LDB_PARSE_DN_INVALID((p - start) < 1); - - /* save the value */ - if ((attribute->value = - talloc_strndup(attribute, - start, - p - start)) == NULL) { - goto failed; - } - - /* see if this attribute value needs case folding */ - if (case_fold_attr_fn != NULL && - (* case_fold_attr_fn)(hUserData, - attribute->name)) { - /* yup, case-fold it. */ - p = attribute->value; - if ((attribute->value = - ldb_casefold(attribute, p)) == NULL) { - goto failed; - } - talloc_free(p); - } - - ldb_debug(mem_ctx, - LDB_DEBUG_TRACE, - "attribute value: [%s]\n", attribute->value); - - /* save the entire RDN */ - if ((attribute->rdn = - talloc_asprintf(attribute, - "%s=%s", - attribute->name, - attribute->value)) == NULL) { - goto failed; - } - - ldb_debug(mem_ctx, - LDB_DEBUG_TRACE, - "attribute: [%s]\n", attribute->rdn); - - /* add this attribute to the attribute list */ - component->attributes[component->attr_num] = attribute; - component->attr_num++; - - /* is this a multi-valued attribute? */ - if (*separator == '+') { - /* Yup. prepare for the next value. */ - if ((component->attributes = - talloc_realloc(component, - component->attributes, - struct ldb_dn_attribute *, - component->attr_num + 1)) == NULL) { - goto failed; - } - - /* allocate new attribute structure */ - if ((attribute = - talloc(component, - struct ldb_dn_attribute)) == NULL) { - goto failed; - } - } - - /* if we're not at end of string, skip white space */ - if (*separator != '\0') { - /* skip spaces past the separator */ - p = separator + 1; - p += strspn(p, " \n"); - } - - } while (*separator == '+'); - - /* find total length of all attributes */ - for (i = 0, size = 0; i < component->attr_num; i++) { - size += strlen(component->attributes[i]->rdn) + 1; - } - - /* - * rebuild the normalized component - */ - - /* allocate space for the normalized component */ - if ((dest = talloc_size(component, size)) == NULL) { - - goto failed; - } - - /* Save the pointer to the beginning of the string */ - component->component = dest; - - /* copy each of the attributes to the normalized component */ - for (i = 0; i < component->attr_num; i++) { - if (i != 0) { - *dest++ = '+'; - } - src = component->attributes[i]->rdn; - - /* we are guaranteed to have enough space in dest */ - size = strlen(src); - strncpy(dest, src, size + 1); - dest += size; - } - - ldb_debug(mem_ctx, - LDB_DEBUG_TRACE, - "component: [%s]\n", component->component); - - /* insert the component into the component list */ - dn->components[dn->comp_num] = component; - dn->comp_num++; - - /* if there are additional components... */ - if (*separator == ',' || *separator == ';') { - /* ... then prepare to parse them */ - if ((dn->components = - talloc_realloc(dn, - dn->components, - struct ldb_dn_component *, - dn->comp_num + 1)) == NULL || - (component = - talloc(dn, struct ldb_dn_component)) == NULL) { - - goto failed; - } - - component->attr_num = 0; - } - - /* update pointer to after the separator */ - p = separator + 1; - - } while(*separator == ',' || *separator == ';'); - - /* find total length of all components */ - for (i = 0, size = 0; i < dn->comp_num; i++) { - size = size + strlen(dn->components[i]->component) + 1; - } - - /* rebuild the normalized DN */ - if ((dest = talloc_size(dn, size)) == NULL) { - goto failed; - } - - /* Save the pointer to the beginning of the */ - dn->dn = dest; - - /* copy the normalized components into the DN */ - for (i = 0; i < dn->comp_num; i++) { - - /* add a separator between DN components */ - if (i != 0) { - *dest++ = ','; - } - - /* point to this component of the DN */ - src = dn->components[i]->component; - - /* we are guaranteed to have enough space in dest */ - size = strlen(src); - strncpy(dest, src, size + 1); - dest += size; - } - - ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn); - - /* we don't need the copy of the DN any more */ - talloc_free(dn_copy); - - /* give 'em what they came for! */ - return dn; - -failed: - /* something went wrong. free memory and tell 'em it failed */ - talloc_free(dn); - ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn); - return NULL; -} - - -static char *parse_slash(char *p, char *end) -{ - unsigned x; - if (strchr(",=\n+<>#;\\\"", p[1])) { - memmove(p, p + 1, end - (p + 1)); - return (end - 1); - } - if (sscanf(p + 1, "%02x", &x) == 1) { - *p = (unsigned char)x; - memmove(p + 1, p + 3, end - (p + 3)); - return (end - 2); - } - return NULL; -} - diff --git a/source4/lib/ldb/include/ldb_dn.h b/source4/lib/ldb/include/ldb_dn.h new file mode 100644 index 0000000000..f355ee4879 --- /dev/null +++ b/source4/lib/ldb/include/ldb_dn.h @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + LDAP server + Copyright (C) Simo Sorce 2004 + Copyright (C) Derrell Lipman 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct ldb_dn_attribute { + char *name; + char *value; +}; + +struct ldb_dn_component { + int attr_num; + struct ldb_dn_attribute **attributes; +}; + +struct ldb_dn { + int comp_num; + struct ldb_dn_component **components; +}; + + +struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); +char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); +int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); +struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data, + int (* case_fold_attr_fn)(void * user_data, char * attr)); diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_explode_dn.h deleted file mode 100644 index af9829ba40..0000000000 --- a/source4/lib/ldb/include/ldb_explode_dn.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Unix SMB/CIFS implementation. - LDAP server - Copyright (C) Simo Sorce 2004 - Copyright (C) Derrell Lipman 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -struct ldb_dn_attribute { - char * rdn; - char * name; - char * value; -}; - -struct ldb_dn_component { - char * component; - int attr_num; - struct ldb_dn_attribute ** attributes; -}; - -struct ldb_dn { - char * dn; - int comp_num; - struct ldb_dn_component ** components; -}; - - -extern struct ldb_dn * -ldb_explode_dn(void * mem_ctx, - const char * orig_dn, - void * hUserData, - int (*case_fold_attr_fn)(void * hUserData, - char * attr)); -- cgit From fa8d539e0fbce952266a246364e5e9cd537b29fd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 27 Jun 2005 12:09:52 +0000 Subject: r7943: Add 'make manpages', fix 'make installman' and 'make uninstallman'. Not part of the "all" make target yet, as it requires xsltproc (This used to be commit fd3f4636438cf1d9c0dd802064033271b9e4d935) --- source4/lib/ldb/config.mk | 9 ++++++++- source4/lib/registry/config.mk | 4 ++++ source4/lib/talloc/config.mk | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 61bd8f0152..39de5ea1c0 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -74,6 +74,7 @@ ADD_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ LIBREPLACE LIBTALLOC LDBSAMBA NOPROTO = YES +MANPAGE = lib/ldb/man/man3/ldb.3 # # End SUBSYSTEM LIBLDB ################################################ @@ -110,10 +111,11 @@ REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC ################################################ # Start BINARY ldbadd [BINARY::ldbadd] -OBJ_FILES= \ +OBJ_FILES = \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbadd.1 # End BINARY ldbadd ################################################ @@ -124,6 +126,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbdel.1 # End BINARY ldbdel ################################################ @@ -134,6 +137,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbmodify.1 # End BINARY ldbmodify ################################################ @@ -144,6 +148,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbsearch.1 # End BINARY ldbsearch ################################################ @@ -154,6 +159,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbedit.1 # End BINARY ldbedit ################################################ @@ -164,6 +170,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbrename.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE +MANPAGE = lib/ldb/man/man1/ldbrename.1 # End BINARY ldbrename ################################################ diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index af9fb83bab..ab699a8ac0 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -98,6 +98,7 @@ OBJ_FILES= \ lib/registry/tools/regdiff.o REQUIRED_SUBSYSTEMS = \ CONFIG LIBCMDLINE REGISTRY +MANPAGE = lib/registry/man/regdiff.1 # End BINARY regdiff ################################################ @@ -108,6 +109,7 @@ OBJ_FILES= \ lib/registry/tools/regpatch.o REQUIRED_SUBSYSTEMS = \ CONFIG LIBCMDLINE REGISTRY +MANPAGE = lib/registry/man/regpatch.1 # End BINARY regpatch ################################################ @@ -118,6 +120,7 @@ OBJ_FILES= \ lib/registry/tools/regshell.o REQUIRED_SUBSYSTEMS = \ CONFIG LIBCMDLINE REGISTRY +MANPAGE = lib/registry/man/regshell.1 # End BINARY regshell ################################################ @@ -128,5 +131,6 @@ OBJ_FILES= \ lib/registry/tools/regtree.o REQUIRED_SUBSYSTEMS = \ CONFIG LIBCMDLINE REGISTRY +MANPAGE = lib/registry/man/regtree.1 # End BINARY regtree ################################################ diff --git a/source4/lib/talloc/config.mk b/source4/lib/talloc/config.mk index fe8f0e929f..a1032a6e41 100644 --- a/source4/lib/talloc/config.mk +++ b/source4/lib/talloc/config.mk @@ -6,6 +6,7 @@ INIT_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ LIBREPLACE NOPROTO = YES +MANPAGE = lib/talloc/talloc.3 # # End SUBSYSTEM LIBTALLOC ################################################ -- cgit From 65cc3f5d5cb6e2b816e6d730960c2141ed0eecd6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 27 Jun 2005 22:07:28 +0000 Subject: r7958: More debian packaging updates; packages build now with a few minor issues. Move ldb manpages one level higher - there is no longer a need to have subdirectories. (This used to be commit e8e3524b2394f4107230715ea38fb619332e0251) --- source4/lib/ldb/Makefile.in | 2 +- source4/lib/ldb/config.mk | 14 +- source4/lib/ldb/man/ldb.3.xml | 262 +++++++++++++++++++++++++++++++ source4/lib/ldb/man/ldbadd.1.xml | 99 ++++++++++++ source4/lib/ldb/man/ldbdel.1.xml | 97 ++++++++++++ source4/lib/ldb/man/ldbedit.1.xml | 125 +++++++++++++++ source4/lib/ldb/man/ldbmodify.1.xml | 87 ++++++++++ source4/lib/ldb/man/ldbrename.1.xml | 101 ++++++++++++ source4/lib/ldb/man/ldbsearch.1.xml | 113 +++++++++++++ source4/lib/ldb/man/man1/ldbadd.1.xml | 99 ------------ source4/lib/ldb/man/man1/ldbdel.1.xml | 97 ------------ source4/lib/ldb/man/man1/ldbedit.1.xml | 125 --------------- source4/lib/ldb/man/man1/ldbmodify.1.xml | 87 ---------- source4/lib/ldb/man/man1/ldbrename.1.xml | 101 ------------ source4/lib/ldb/man/man1/ldbsearch.1.xml | 113 ------------- source4/lib/ldb/man/man3/ldb.3.xml | 262 ------------------------------- 16 files changed, 892 insertions(+), 892 deletions(-) create mode 100644 source4/lib/ldb/man/ldb.3.xml create mode 100644 source4/lib/ldb/man/ldbadd.1.xml create mode 100644 source4/lib/ldb/man/ldbdel.1.xml create mode 100644 source4/lib/ldb/man/ldbedit.1.xml create mode 100644 source4/lib/ldb/man/ldbmodify.1.xml create mode 100644 source4/lib/ldb/man/ldbrename.1.xml create mode 100644 source4/lib/ldb/man/ldbsearch.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbadd.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbdel.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbedit.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbmodify.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbrename.1.xml delete mode 100644 source4/lib/ldb/man/man1/ldbsearch.1.xml delete mode 100644 source4/lib/ldb/man/man3/ldb.3.xml (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index ac3155f27e..4a065ba83f 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -112,7 +112,7 @@ bin/ldbtest: tools/ldbtest.o tools/cmdline.o $(LIBS) %.html: %.xml test -z "$(XSLTPROC)" || $(XSLTPROC) -o $@ http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl $< -manpages: $(patsubst %.xml,%,$(wildcard man/*/*.xml)) +manpages: $(patsubst %.xml,%,$(wildcard man/*.xml)) clean: rm -f */*.o *.gcov */*.gc?? *~ */*~ $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) man/man?/*.[13] diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 39de5ea1c0..691af8bcfa 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -74,7 +74,7 @@ ADD_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ LIBREPLACE LIBTALLOC LDBSAMBA NOPROTO = YES -MANPAGE = lib/ldb/man/man3/ldb.3 +MANPAGE = lib/ldb/man/ldb.3 # # End SUBSYSTEM LIBLDB ################################################ @@ -115,7 +115,7 @@ OBJ_FILES = \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbadd.1 +MANPAGE = lib/ldb/man/ldbadd.1 # End BINARY ldbadd ################################################ @@ -126,7 +126,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbdel.1 +MANPAGE = lib/ldb/man/ldbdel.1 # End BINARY ldbdel ################################################ @@ -137,7 +137,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbmodify.1 +MANPAGE = lib/ldb/man/ldbmodify.1 # End BINARY ldbmodify ################################################ @@ -148,7 +148,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbsearch.1 +MANPAGE = lib/ldb/man/ldbsearch.1 # End BINARY ldbsearch ################################################ @@ -159,7 +159,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbedit.1 +MANPAGE = lib/ldb/man/ldbedit.1 # End BINARY ldbedit ################################################ @@ -170,7 +170,7 @@ OBJ_FILES= \ lib/ldb/tools/ldbrename.o REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE -MANPAGE = lib/ldb/man/man1/ldbrename.1 +MANPAGE = lib/ldb/man/ldbrename.1 # End BINARY ldbrename ################################################ diff --git a/source4/lib/ldb/man/ldb.3.xml b/source4/lib/ldb/man/ldb.3.xml new file mode 100644 index 0000000000..d9ed135f20 --- /dev/null +++ b/source4/lib/ldb/man/ldb.3.xml @@ -0,0 +1,262 @@ + + + + + + ldb + 3 + + + + ldb + The Samba Project + A light-weight database library + + + + #include <ldb.h> + + + + description + + +ldb is a light weight embedded database library and API. With a +programming interface that is very similar to LDAP, ldb can store its +data either in a tdb(3) database or in a real LDAP database. + + + +When used with the tdb backend ldb does not require any database +daemon. Instead, ldb function calls are processed immediately by the +ldb library, which does IO directly on the database, while allowing +multiple readers/writers using operating system byte range locks. This +leads to an API with very low overheads, often resulting in speeds of +more than 10x what can be achieved with a more traditional LDAP +architecture. + + + +It a taxonomy of databases ldb would sit half way between key/value +pair databases (such as berkley db or tdb) and a full LDAP +database. With a structured attribute oriented API like LDAP and good +indexing capabilities, ldb can be used for quite sophisticated +applications that need a light weight database, without the +administrative overhead of a full LDAP installation. + + + +Included with ldb are a number of useful command line tools for +manipulating a ldb database. These tools are similar in style to the +equivalent ldap command line tools. + + + +In its default mode of operation with a tdb backend, ldb can also be +seen as a "schema-less LDAP". By default ldb does not require a +schema, which greatly reduces the complexity of getting started with +ldb databases. As the complexity of you application grows you can take +advantage of some of the optional schema-like attributes that ldb +offers, or you can migrate to using the full LDAP api while keeping +your exiting ldb code. + + + +If you are new to ldb, then I suggest starting with the manual pages +for ldbsearch(1) and ldbedit(1), and experimenting with a local +database. Then I suggest you look at the ldb_connect(3) and +ldb_search(3) manual pages. + + + + + TOOLS + + + + ldbsearch(1) + - command line ldb search utility + + + + ldbedit(1) + - edit all or part of a ldb database using your favourite editor + + + + ldbadd(1) + - add records to a ldb database using LDIF formatted input + + + + ldbdel(1) + - delete records from a ldb database + + + + ldbmodify(1) + - modify records in a ldb database using LDIF formatted input + + + + + + FUNCTIONS + + + + ldb_connect(3) + - connect to a ldb backend + + + + ldb_search(3) + - perform a database search + + + + ldb_add(3) + - add a record to the database + + + + ldb_delete(3) + - delete a record from the database + + + + ldb_modify(3) + - modify a record in the database + + + + ldb_errstring(3) + - retrieve extended error information from the last operation + + + + ldb_ldif_write(3) + - write a LDIF formatted message + + + + ldb_ldif_write_file(3) + - write a LDIF formatted message to a file + + + + ldb_ldif_read(3) + - read a LDIF formatted message + + + + ldb_ldif_read_free(3) + - free the result of a ldb_ldif_read() + + + + ldb_ldif_read_file(3) + - read a LDIF message from a file + + + + ldb_ldif_read_string(3) + - read a LDIF message from a string + + + + ldb_msg_find_element(3) + - find an element in a ldb_message + + + + ldb_val_equal_exact(3) + - compare two ldb_val structures + + + + ldb_msg_find_val(3) + - find an element by value + + + + ldb_msg_add_empty(3) + - add an empty message element to a ldb_message + + + + + ldb_msg_add(3) + - add a non-empty message element to a ldb_message + + + + + ldb_msg_element_compare(3) + - compare two ldb_message_element structures + + + + + ldb_msg_find_int(3) + - return an integer value from a ldb_message + + + + + ldb_msg_find_uint(3) + - return an unsigned integer value from a ldb_message + + + + + ldb_msg_find_double(3) + - return a double value from a ldb_message + + + + + ldb_msg_find_string(3) + - return a string value from a ldb_message + + + + + ldb_set_alloc(3) + - set the memory allocation function to be used by ldb + + + + + ldb_set_debug(3) + - set a debug handler to be used by ldb + + + + + ldb_set_debug_stderr(3) + - set a debug handler for stderr output + + + + + + description + + + ldb was written by + Andrew Tridgell. + + + +If you wish to report a problem or make a suggestion then please see +the web site for +current contact and maintainer information. + + + +ldb is released under the GNU Lesser General Public License version 2 +or later. Please see the file COPYING for license details. + + + diff --git a/source4/lib/ldb/man/ldbadd.1.xml b/source4/lib/ldb/man/ldbadd.1.xml new file mode 100644 index 0000000000..0b3122ab32 --- /dev/null +++ b/source4/lib/ldb/man/ldbadd.1.xml @@ -0,0 +1,99 @@ + + + + + + ldbadd + 1 + + + + + ldbadd + Command-line utility for adding records to an LDB + + + + + ldbadd + -h + -H LDB-URL + ldif-file1 + ldif-file2 + ... + + + + + DESCRIPTION + + ldbadd adds records to an ldb(7) database. It reads + the ldif(5) files specified on the command line and adds + the records from these files to the LDB database, which is specified + by the -H option or the LDB_URL environment variable. + + + If - is specified as a ldb file, the ldif input is read from + standard input. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbadd was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/ldbdel.1.xml b/source4/lib/ldb/man/ldbdel.1.xml new file mode 100644 index 0000000000..2f98f9d427 --- /dev/null +++ b/source4/lib/ldb/man/ldbdel.1.xml @@ -0,0 +1,97 @@ + + + + + + ldbdel + 1 + + + + + ldbdel + Command-line program for deleting LDB records + + + + + ldbdel + -h + -H LDB-URL + dn + ... + + + + + DESCRIPTION + + ldbdel deletes records from an ldb(7) database. + It deletes the records identified by the dn's specified + on the command-line. + + ldbdel uses either the database that is specified with + the -H option or the database specified by the LDB_URL environment + variable. + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbadd, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbdel was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/ldbedit.1.xml b/source4/lib/ldb/man/ldbedit.1.xml new file mode 100644 index 0000000000..0b5c63a17a --- /dev/null +++ b/source4/lib/ldb/man/ldbedit.1.xml @@ -0,0 +1,125 @@ + + + + + + ldbedit + 1 + + + + + ldbedit + Edit LDB databases using your favorite editor + + + + + ldbedit + -h + -s base|one|sub + -b basedn + -a + -e editor + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbedit is a utility that allows you to edit LDB files using + your favorite editor. ldbedit generates an LDIF file based on + your query, allows you to edit it and then merges it back + into the LDB database. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -a + Edit all records. + + + + -e editor + Specify the editor that should be used (overrides + the VISUAL and EDITOR environment variables). + + + + -b basedn + Specify Base DN to use. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + VISUAL and EDITOR + Environment variables used to determine what + editor to use. If VISUAL isn't set, EDITOR is used. + + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbedit was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/ldbmodify.1.xml b/source4/lib/ldb/man/ldbmodify.1.xml new file mode 100644 index 0000000000..e39f74fffa --- /dev/null +++ b/source4/lib/ldb/man/ldbmodify.1.xml @@ -0,0 +1,87 @@ + + + + + + ldbmodify + 1 + + + + + ldbmodify + Modify records in a LDB database + + + + + ldbmodify + -H LDB-URL + ldif-file + + + + + DESCRIPTION + + + ldbmodify changes, adds and deletes records in a LDB database. + The changes that should be made to the LDB database are read from + the specified LDIF-file. If - is specified as the filename, input is read from stdin. + + + For now, see ldapmodify(1) for details on the LDIF file format. + + + + + + OPTIONS + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbedit + + + + + AUTHOR + + &man.credits.samba; + + ldbmodify was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/ldbrename.1.xml b/source4/lib/ldb/man/ldbrename.1.xml new file mode 100644 index 0000000000..32456243af --- /dev/null +++ b/source4/lib/ldb/man/ldbrename.1.xml @@ -0,0 +1,101 @@ + + + + + + ldbrename + 1 + + + + + ldbrename + Edit LDB databases using your favorite editor + + + + + ldbrename + -h + -o options + olddn + newdb + + + + + DESCRIPTION + + ldbrename is a utility that allows you to rename trees in + an LDB database based by DN. This utility takes + two arguments: the original + DN name of the top element and the DN to change it to. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -o options + Extra ldb options, such as + modules. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbmodify, ldbdel, ldif(5) + + + + + AUTHOR + + &man.credits.samba; + + ldbrename was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/ldbsearch.1.xml b/source4/lib/ldb/man/ldbsearch.1.xml new file mode 100644 index 0000000000..8361aa97ff --- /dev/null +++ b/source4/lib/ldb/man/ldbsearch.1.xml @@ -0,0 +1,113 @@ + + + + + + ldbsearch + 1 + + + + + ldbsearch + Search for records in a LDB database + + + + + ldbsearch + -h + -s base|one|sub + -b basedn + -i + -H LDB-URL + expression + attributes + + + + + DESCRIPTION + + ldbsearch searches a LDB database for records matching the + specified expression (see the ldapsearch(1) manpage for + a description of the expression format). For each + record, the specified attributes are printed. + + + + + + + OPTIONS + + + + -h + + Show list of available options. + + + + -H <ldb-url> + + LDB URL to connect to. See ldb(7) for details. + + + + + -s one|sub|base + Search scope to use. One-level, subtree or base. + + + + -i + Read search expressions from stdin. + + + + -b basedn + Specify Base DN to use. + + + + + + + + ENVIRONMENT + + + LDB_URL + LDB URL to connect to (can be overrided by using the + -H command-line option.) + + + + + + + VERSION + + This man page is correct for version 4.0 of the Samba suite. + + + + SEE ALSO + + ldb(7), ldbedit + + + + + AUTHOR + + &man.credits.samba; + + ldbsearch was written by Andrew Tridgell. + + This manpage was written by Jelmer Vernooij. + + + + diff --git a/source4/lib/ldb/man/man1/ldbadd.1.xml b/source4/lib/ldb/man/man1/ldbadd.1.xml deleted file mode 100644 index 0b3122ab32..0000000000 --- a/source4/lib/ldb/man/man1/ldbadd.1.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - ldbadd - 1 - - - - - ldbadd - Command-line utility for adding records to an LDB - - - - - ldbadd - -h - -H LDB-URL - ldif-file1 - ldif-file2 - ... - - - - - DESCRIPTION - - ldbadd adds records to an ldb(7) database. It reads - the ldif(5) files specified on the command line and adds - the records from these files to the LDB database, which is specified - by the -H option or the LDB_URL environment variable. - - - If - is specified as a ldb file, the ldif input is read from - standard input. - - - - - - OPTIONS - - - - -h - - Show list of available options. - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbmodify, ldbdel, ldif(5) - - - - - AUTHOR - - &man.credits.samba; - - ldbadd was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man1/ldbdel.1.xml b/source4/lib/ldb/man/man1/ldbdel.1.xml deleted file mode 100644 index 2f98f9d427..0000000000 --- a/source4/lib/ldb/man/man1/ldbdel.1.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - ldbdel - 1 - - - - - ldbdel - Command-line program for deleting LDB records - - - - - ldbdel - -h - -H LDB-URL - dn - ... - - - - - DESCRIPTION - - ldbdel deletes records from an ldb(7) database. - It deletes the records identified by the dn's specified - on the command-line. - - ldbdel uses either the database that is specified with - the -H option or the database specified by the LDB_URL environment - variable. - - - - - - OPTIONS - - - - -h - - Show list of available options. - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbmodify, ldbadd, ldif(5) - - - - - AUTHOR - - &man.credits.samba; - - ldbdel was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man1/ldbedit.1.xml b/source4/lib/ldb/man/man1/ldbedit.1.xml deleted file mode 100644 index 0b5c63a17a..0000000000 --- a/source4/lib/ldb/man/man1/ldbedit.1.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - ldbedit - 1 - - - - - ldbedit - Edit LDB databases using your favorite editor - - - - - ldbedit - -h - -s base|one|sub - -b basedn - -a - -e editor - -H LDB-URL - expression - attributes - - - - - DESCRIPTION - - ldbedit is a utility that allows you to edit LDB files using - your favorite editor. ldbedit generates an LDIF file based on - your query, allows you to edit it and then merges it back - into the LDB database. - - - - - - - OPTIONS - - - - -h - - Show list of available options. - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - -s one|sub|base - Search scope to use. One-level, subtree or base. - - - - -a - Edit all records. - - - - -e editor - Specify the editor that should be used (overrides - the VISUAL and EDITOR environment variables). - - - - -b basedn - Specify Base DN to use. - - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - VISUAL and EDITOR - Environment variables used to determine what - editor to use. If VISUAL isn't set, EDITOR is used. - - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbmodify, ldbdel, ldif(5) - - - - - AUTHOR - - &man.credits.samba; - - ldbedit was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man1/ldbmodify.1.xml b/source4/lib/ldb/man/man1/ldbmodify.1.xml deleted file mode 100644 index e39f74fffa..0000000000 --- a/source4/lib/ldb/man/man1/ldbmodify.1.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - ldbmodify - 1 - - - - - ldbmodify - Modify records in a LDB database - - - - - ldbmodify - -H LDB-URL - ldif-file - - - - - DESCRIPTION - - - ldbmodify changes, adds and deletes records in a LDB database. - The changes that should be made to the LDB database are read from - the specified LDIF-file. If - is specified as the filename, input is read from stdin. - - - For now, see ldapmodify(1) for details on the LDIF file format. - - - - - - OPTIONS - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbedit - - - - - AUTHOR - - &man.credits.samba; - - ldbmodify was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man1/ldbrename.1.xml b/source4/lib/ldb/man/man1/ldbrename.1.xml deleted file mode 100644 index 32456243af..0000000000 --- a/source4/lib/ldb/man/man1/ldbrename.1.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - ldbrename - 1 - - - - - ldbrename - Edit LDB databases using your favorite editor - - - - - ldbrename - -h - -o options - olddn - newdb - - - - - DESCRIPTION - - ldbrename is a utility that allows you to rename trees in - an LDB database based by DN. This utility takes - two arguments: the original - DN name of the top element and the DN to change it to. - - - - - - - OPTIONS - - - - -h - - Show list of available options. - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - -o options - Extra ldb options, such as - modules. - - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbmodify, ldbdel, ldif(5) - - - - - AUTHOR - - &man.credits.samba; - - ldbrename was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man1/ldbsearch.1.xml b/source4/lib/ldb/man/man1/ldbsearch.1.xml deleted file mode 100644 index 8361aa97ff..0000000000 --- a/source4/lib/ldb/man/man1/ldbsearch.1.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - ldbsearch - 1 - - - - - ldbsearch - Search for records in a LDB database - - - - - ldbsearch - -h - -s base|one|sub - -b basedn - -i - -H LDB-URL - expression - attributes - - - - - DESCRIPTION - - ldbsearch searches a LDB database for records matching the - specified expression (see the ldapsearch(1) manpage for - a description of the expression format). For each - record, the specified attributes are printed. - - - - - - - OPTIONS - - - - -h - - Show list of available options. - - - - -H <ldb-url> - - LDB URL to connect to. See ldb(7) for details. - - - - - -s one|sub|base - Search scope to use. One-level, subtree or base. - - - - -i - Read search expressions from stdin. - - - - -b basedn - Specify Base DN to use. - - - - - - - - ENVIRONMENT - - - LDB_URL - LDB URL to connect to (can be overrided by using the - -H command-line option.) - - - - - - - VERSION - - This man page is correct for version 4.0 of the Samba suite. - - - - SEE ALSO - - ldb(7), ldbedit - - - - - AUTHOR - - &man.credits.samba; - - ldbsearch was written by Andrew Tridgell. - - This manpage was written by Jelmer Vernooij. - - - - diff --git a/source4/lib/ldb/man/man3/ldb.3.xml b/source4/lib/ldb/man/man3/ldb.3.xml deleted file mode 100644 index d9ed135f20..0000000000 --- a/source4/lib/ldb/man/man3/ldb.3.xml +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - ldb - 3 - - - - ldb - The Samba Project - A light-weight database library - - - - #include <ldb.h> - - - - description - - -ldb is a light weight embedded database library and API. With a -programming interface that is very similar to LDAP, ldb can store its -data either in a tdb(3) database or in a real LDAP database. - - - -When used with the tdb backend ldb does not require any database -daemon. Instead, ldb function calls are processed immediately by the -ldb library, which does IO directly on the database, while allowing -multiple readers/writers using operating system byte range locks. This -leads to an API with very low overheads, often resulting in speeds of -more than 10x what can be achieved with a more traditional LDAP -architecture. - - - -It a taxonomy of databases ldb would sit half way between key/value -pair databases (such as berkley db or tdb) and a full LDAP -database. With a structured attribute oriented API like LDAP and good -indexing capabilities, ldb can be used for quite sophisticated -applications that need a light weight database, without the -administrative overhead of a full LDAP installation. - - - -Included with ldb are a number of useful command line tools for -manipulating a ldb database. These tools are similar in style to the -equivalent ldap command line tools. - - - -In its default mode of operation with a tdb backend, ldb can also be -seen as a "schema-less LDAP". By default ldb does not require a -schema, which greatly reduces the complexity of getting started with -ldb databases. As the complexity of you application grows you can take -advantage of some of the optional schema-like attributes that ldb -offers, or you can migrate to using the full LDAP api while keeping -your exiting ldb code. - - - -If you are new to ldb, then I suggest starting with the manual pages -for ldbsearch(1) and ldbedit(1), and experimenting with a local -database. Then I suggest you look at the ldb_connect(3) and -ldb_search(3) manual pages. - - - - - TOOLS - - - - ldbsearch(1) - - command line ldb search utility - - - - ldbedit(1) - - edit all or part of a ldb database using your favourite editor - - - - ldbadd(1) - - add records to a ldb database using LDIF formatted input - - - - ldbdel(1) - - delete records from a ldb database - - - - ldbmodify(1) - - modify records in a ldb database using LDIF formatted input - - - - - - FUNCTIONS - - - - ldb_connect(3) - - connect to a ldb backend - - - - ldb_search(3) - - perform a database search - - - - ldb_add(3) - - add a record to the database - - - - ldb_delete(3) - - delete a record from the database - - - - ldb_modify(3) - - modify a record in the database - - - - ldb_errstring(3) - - retrieve extended error information from the last operation - - - - ldb_ldif_write(3) - - write a LDIF formatted message - - - - ldb_ldif_write_file(3) - - write a LDIF formatted message to a file - - - - ldb_ldif_read(3) - - read a LDIF formatted message - - - - ldb_ldif_read_free(3) - - free the result of a ldb_ldif_read() - - - - ldb_ldif_read_file(3) - - read a LDIF message from a file - - - - ldb_ldif_read_string(3) - - read a LDIF message from a string - - - - ldb_msg_find_element(3) - - find an element in a ldb_message - - - - ldb_val_equal_exact(3) - - compare two ldb_val structures - - - - ldb_msg_find_val(3) - - find an element by value - - - - ldb_msg_add_empty(3) - - add an empty message element to a ldb_message - - - - - ldb_msg_add(3) - - add a non-empty message element to a ldb_message - - - - - ldb_msg_element_compare(3) - - compare two ldb_message_element structures - - - - - ldb_msg_find_int(3) - - return an integer value from a ldb_message - - - - - ldb_msg_find_uint(3) - - return an unsigned integer value from a ldb_message - - - - - ldb_msg_find_double(3) - - return a double value from a ldb_message - - - - - ldb_msg_find_string(3) - - return a string value from a ldb_message - - - - - ldb_set_alloc(3) - - set the memory allocation function to be used by ldb - - - - - ldb_set_debug(3) - - set a debug handler to be used by ldb - - - - - ldb_set_debug_stderr(3) - - set a debug handler for stderr output - - - - - - description - - - ldb was written by - Andrew Tridgell. - - - -If you wish to report a problem or make a suggestion then please see -the web site for -current contact and maintainer information. - - - -ldb is released under the GNU Lesser General Public License version 2 -or later. Please see the file COPYING for license details. - - - -- cgit From 3433a464c2e46301a2ef51642577ef731a3ae1ce Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 28 Jun 2005 00:52:10 +0000 Subject: r7967: We don't have the ms_krb5 stuff any more. Andrew Bartlett (This used to be commit 56a5ccd7d924343609698b034b91b4891fb3f08a) --- source4/lib/cmdline/popt_common.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index fb7356dc0e..b8f8a675eb 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -235,7 +235,6 @@ static void popt_common_credentials_callback(poptContext con, exit(1); #else lp_set_cmdline("gensec:krb5", "True"); - lp_set_cmdline("gensec:ms_krb5", "True"); #endif break; -- cgit From f62a70fe54c1b1f6172d1d3fbc8b34c03dd96b86 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 29 Jun 2005 02:28:57 +0000 Subject: r7988: Store the KVNO for the machine account, and set it up in the provision. Andrew Bartlett (This used to be commit 90e94a4630c24282cd93ee05e258877b38e24a57) --- source4/lib/credentials.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index aaaa2cf05d..58a1b8c0e3 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -504,6 +504,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) "realm", "secureChannelType", "ntPwdHash", + "msDS-KeyVersionNumber", NULL }; @@ -594,6 +595,8 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) cli_credentials_set_password(cred, password, CRED_SPECIFIED); } + cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0)); + talloc_free(mem_ctx); return NT_STATUS_OK; @@ -651,6 +654,25 @@ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_creden return cred->secure_channel_type; } +/** + * Set Kerberos KVNO + */ + +void cli_credentials_set_kvno(struct cli_credentials *cred, + int kvno) +{ + cred->kvno = kvno; +} + +/** + * Return Kerberos KVNO + */ + +int cli_credentials_get_kvno(struct cli_credentials *cred) +{ + return cred->kvno; +} + /** * Fill in a credentials structure as the anonymous user */ -- cgit From c58c7c416412fd2ae90427f500b2d94996c36c48 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Jun 2005 01:26:52 +0000 Subject: r8002: favor addresses on our local interfaces in NBT name resolution if possible. This is needed because w2k3 will return bogus IPs in its name resolution replies when it has an unplugged network interface. (This used to be commit 2fafc230520fb5bbe9f763de94aaba87b56f5411) --- source4/lib/netif/interface.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 80041d5350..670913ab6f 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -353,3 +353,16 @@ const char *iface_best_ip(const char *dest) } return iface_n_ip(0); } + +/* + return True if an IP is one one of our local networks +*/ +BOOL iface_is_local(const char *dest) +{ + struct in_addr ip; + ip.s_addr = interpret_addr(dest); + if (iface_find(ip, True)) { + return True; + } + return False; +} -- cgit From c645eba60b611b0dd1ee5a5c96c0ed1d188bf91d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Jun 2005 01:57:57 +0000 Subject: r8005: escape '"' characters in ldap expressions. Makes scripting easier. (This used to be commit 2de986455c9b616132f06a69c2f135019da2bb8b) --- source4/lib/ldb/common/ldb_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 501b82f635..841a785de5 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -172,7 +172,7 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val) unsigned char *buf = val.data; for (i=0;i Date: Thu, 30 Jun 2005 03:32:43 +0000 Subject: r8009: expanded the ldb test suite. It worried me that some changes I have pending, which I know break lots of features, still passed our test suite! Now they don't. (This used to be commit 5801167c8dfc8a61bfeac396bca8ffd3d5270296) --- source4/lib/ldb/tests/test-tdb-features.sh | 78 ++++++++++++++++++++++++++++++ source4/lib/ldb/tests/test-tdb.sh | 4 +- 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 source4/lib/ldb/tests/test-tdb-features.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh new file mode 100644 index 0000000000..7ed55430f7 --- /dev/null +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +echo "Running tdb feature tests" + +rm -f $LDB_URL + +checkcount() { + count=$1 + expression="$2" + n=`bin/ldbsearch "$expression" | grep ^dn | wc -l` + if [ $n != $count ]; then + echo "Got $n but expected $count for $expression" + bin/ldbsearch "$expression" + exit 1 + fi + echo "OK: $count $expression" +} + +echo "Testing case sensitve search" +cat < Date: Thu, 30 Jun 2005 03:56:55 +0000 Subject: r8010: added testing of wildcard attributes (This used to be commit 25d3872a6ebbc152a83695e667f5d08e69c8c8ea) --- source4/lib/ldb/tests/test-tdb-features.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index 7ed55430f7..3a7c50eae7 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -74,5 +74,25 @@ EOF checkcount 1 '(i=0x100)' checkcount 1 '(i=256)' +echo "adding j" +cat < Date: Thu, 30 Jun 2005 03:59:02 +0000 Subject: r8011: arrgh, commit the right version this time (This used to be commit 5efea40ea63b6951b3bd4362f1ae57f960fefecf) --- source4/lib/ldb/tests/test-tdb-features.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index 3a7c50eae7..80da8fc2ad 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -81,18 +81,17 @@ changetype: modify add: j j: 0x100 EOF -checkcount 1 '(i=0x100)' -checkcount 0 '(i=256)' +checkcount 1 '(j=0x100)' +checkcount 0 '(j=256)' echo "Adding wildcard attribute" -echo "marking i as INTEGER" cat < Date: Fri, 1 Jul 2005 01:25:55 +0000 Subject: r8032: added loop detection into talloc. Robert Collins found a way to make a memory loop with talloc_unlink(), so now we detect it and handle it (This used to be commit 563058e78b8c74e821fabf6a43fa861c1ad09944) --- source4/lib/talloc/talloc.c | 62 +++++++++++++++++++++++++++++++----------- source4/lib/talloc/testsuite.c | 21 ++++++++++++++ 2 files changed, 67 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 3adf741870..3a068f4eaa 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -59,8 +59,9 @@ #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC 0xe814ec70 +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -100,7 +101,7 @@ struct talloc_chunk { talloc_destructor_t destructor; const char *name; union { - unsigned magic; + unsigned flags; double align_dummy; } u; }; @@ -109,14 +110,12 @@ struct talloc_chunk { static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->u.magic != TALLOC_MAGIC) { - if (tc->u.magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } + if ((tc->u.flags & ~0xF) != TALLOC_MAGIC) { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + if (tc->u.flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); } - return tc; } @@ -183,7 +182,7 @@ void *_talloc(const void *context, size_t size) if (tc == NULL) return NULL; tc->size = size; - tc->u.magic = TALLOC_MAGIC; + tc->u.flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -537,6 +536,11 @@ int talloc_free(void *ptr) return -1; } + if (tc->u.flags & TALLOC_FLAG_LOOP) { + /* we have a free loop - stop looping */ + return 0; + } + if (tc->destructor) { talloc_destructor_t d = tc->destructor; if (d == (talloc_destructor_t)-1) { @@ -550,6 +554,8 @@ int talloc_free(void *ptr) tc->destructor = NULL; } + tc->u.flags |= TALLOC_FLAG_LOOP; + talloc_free_children(ptr); if (tc->parent) { @@ -562,7 +568,7 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->u.magic = TALLOC_MAGIC_FREE; + tc->u.flags |= TALLOC_FLAG_FREE; free(tc); return 0; @@ -602,7 +608,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } /* by resetting magic we catch users of the old memory */ - tc->u.magic = TALLOC_MAGIC_FREE; + tc->u.flags |= TALLOC_FLAG_FREE; #if ALWAYS_REALLOC new_ptr = malloc(size + sizeof(*tc)); @@ -614,12 +620,12 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n new_ptr = realloc(tc, size + sizeof(*tc)); #endif if (!new_ptr) { - tc->u.magic = TALLOC_MAGIC; + tc->u.flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = new_ptr; - tc->u.magic = TALLOC_MAGIC; + tc->u.flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { tc->parent->child = new_ptr; } @@ -714,10 +720,19 @@ off_t talloc_total_size(const void *ptr) tc = talloc_chunk_from_ptr(ptr); + if (tc->u.flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->u.flags |= TALLOC_FLAG_LOOP; + total = tc->size; for (c=tc->child;c;c=c->next) { total += talloc_total_size(c+1); } + + tc->u.flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -729,10 +744,19 @@ off_t talloc_total_blocks(const void *ptr) off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->u.flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->u.flags |= TALLOC_FLAG_LOOP; + total++; for (c=tc->child;c;c=c->next) { total += talloc_total_blocks(c+1); } + + tc->u.flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -758,6 +782,12 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth) { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->u.flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->u.flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { struct talloc_reference_handle *handle = (void *)(c+1); @@ -774,7 +804,7 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth) talloc_report_depth(c+1, f, depth+1); } } - + tc->u.flags &= ~TALLOC_FLAG_LOOP; } /* diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 60da1c3f87..422cb8fee5 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -818,6 +818,26 @@ static BOOL test_speed(void) } +BOOL test_lifeless(void) +{ + char *top = talloc_new(NULL); + char *parent, *child; + char *child_owner = talloc_new(NULL); + + printf("TESTING TALLOC_UNLINK LOOP\n"); + + parent = talloc_strdup(top, "parent"); + child = talloc_strdup(parent, "child"); + talloc_reference(child, parent); + talloc_reference(child_owner, child); + talloc_unlink(top, parent); + talloc_free(child); + talloc_report_full(top, stdout); + talloc_free(top); + return True; +} + + BOOL torture_local_talloc(void) { BOOL ret = True; @@ -834,6 +854,7 @@ BOOL torture_local_talloc(void) ret &= test_unref_reparent(); ret &= test_realloc_fn(); ret &= test_type(); + ret &= test_lifeless(); if (ret) { ret &= test_speed(); } -- cgit From 64307e63513bd47de25c031321c91ebc56a4aef3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 02:17:38 +0000 Subject: r8033: - add easier valgrind testing - add tests for the @SUBCLASSES ltdb special (This used to be commit ad6e62fdcf0432fcf4d41edb1727cbba1b7528b7) --- source4/lib/ldb/tests/test-tdb-features.sh | 36 +++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index 80da8fc2ad..8e9d9dab3c 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -10,41 +10,41 @@ checkcount() { n=`bin/ldbsearch "$expression" | grep ^dn | wc -l` if [ $n != $count ]; then echo "Got $n but expected $count for $expression" - bin/ldbsearch "$expression" + $VALGRIND bin/ldbsearch "$expression" exit 1 fi echo "OK: $count $expression" } echo "Testing case sensitve search" -cat < Date: Fri, 1 Jul 2005 05:20:08 +0000 Subject: r8035: added indexing tests. current ldb fails the integer indexing, will be fixed shortly (This used to be commit a9c32445035a09978c5fdbc189a2767e7650dfc2) --- source4/lib/ldb/tests/test-tdb-features.sh | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index 8e9d9dab3c..a78d2d3dd5 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -22,10 +22,6 @@ dn: cn=t1,cn=TEST objectClass: testclass test: foo EOF - - -echo $ldif | $VALGRIND bin/ldbadd || exit 1 - checkcount 1 '(test=foo)' checkcount 0 '(test=FOO)' checkcount 0 '(test=fo*)' @@ -108,4 +104,28 @@ EOF checkcount 1 '(objectClass=otherclass)' checkcount 1 '(objectClass=testclass)' +echo "Adding index" +cat < Date: Fri, 1 Jul 2005 06:21:26 +0000 Subject: r8037: a fairly major update to the internals of ldb. Changes are: - moved the knowledge of attribute types out of ldb_tdb and into the generic ldb code. This allows the ldb_match() message match logic to be generic, so it can be used by other backend - added the generic ability to load attribute handlers, for canonicalisation, compare, ldif read and ldif write. In the future this will be used by the schema module to allow us to correctly obey the attributetype schema elements - added attribute handlers for some of the core ldap attribute types, Integer, DirectoryString, DN, ObjectClass etc - added automatic registration of attribute handlers for well-known attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass' - converted the objectSid special handlers for Samba to the new system - added more correct handling of indexing in tdb backend based on the attribute canonicalisation function - added generic support for subclasses, moving it out of the tdb backend. This will be used in future by the schema module - fixed several bugs in the dn_explode code. It still needs more work, but doesn't corrupt ldb dbs any more. (This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9) --- source4/lib/ldb/Makefile.in | 5 +- source4/lib/ldb/common/attrib_handlers.c | 335 ++++++++++++++++++++++++ source4/lib/ldb/common/ldb.c | 8 + source4/lib/ldb/common/ldb_attributes.c | 281 ++++++++++++++++++++ source4/lib/ldb/common/ldb_dn.c | 132 ++++++---- source4/lib/ldb/common/ldb_ldif.c | 78 +----- source4/lib/ldb/common/ldb_match.c | 260 +++++++++++++++++++ source4/lib/ldb/common/ldb_utf8.c | 4 +- source4/lib/ldb/config.mk | 4 +- source4/lib/ldb/include/ldb.h | 40 ++- source4/lib/ldb/include/ldb_dn.h | 3 +- source4/lib/ldb/include/ldb_private.h | 51 +++- source4/lib/ldb/ldb_tdb/ldb_cache.c | 188 +++++++++++++- source4/lib/ldb/ldb_tdb/ldb_index.c | 112 +++++--- source4/lib/ldb/ldb_tdb/ldb_match.c | 426 ------------------------------- source4/lib/ldb/ldb_tdb/ldb_search.c | 15 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 65 +---- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 19 -- source4/lib/ldb/samba/ldif_handlers.c | 26 +- 19 files changed, 1368 insertions(+), 684 deletions(-) create mode 100644 source4/lib/ldb/common/attrib_handlers.c create mode 100644 source4/lib/ldb/common/ldb_attributes.c create mode 100644 source4/lib/ldb/common/ldb_match.c delete mode 100644 source4/lib/ldb/ldb_tdb/ldb_match.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 4a065ba83f..2f82f63714 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -44,7 +44,7 @@ LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) @LIBS@ TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o TALLOC_OBJ=$(TALLOCDIR)/talloc.o -LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ +LDB_TDB_OBJ=ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ ldb_tdb/ldb_cache.o @@ -52,7 +52,8 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ common/ldb_parse.o common/ldb_msg.o common/ldb_utf8.o \ common/ldb_debug.o common/ldb_modules.o \ - common/ldb_dn.o + common/ldb_dn.o common/ldb_match.o common/ldb_attributes.o \ + common/attrib_handlers.o MODULES_OBJ=modules/timestamps.o modules/schema.o diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c new file mode 100644 index 0000000000..fcff4113b4 --- /dev/null +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -0,0 +1,335 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + attribute handlers for well known attribute types, selected by syntax OID + see rfc2252 +*/ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +/* + default handler that just copies a ldb_val. +*/ +int ldb_handler_copy(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out) +{ + *out = ldb_val_dup(ldb, in); + if (out->data == NULL) { + ldb_oom(ldb); + return -1; + } + return 0; +} + +/* + a case folding copy handler, removing leading and trailing spaces and + multiple internal spaces +*/ +static int ldb_handler_fold(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out) +{ + uint8_t *s1, *s2; + out->data = talloc_size(ldb, strlen(in->data)+1); + if (out->data == NULL) { + ldb_oom(ldb); + return -1; + } + s1 = in->data; + s2 = out->data; + while (*s1 == ' ') s1++; + while (*s1) { + *s2 = toupper(*s1); + if (s1[0] == ' ') { + while (s1[0] == s1[1]) s1++; + } + s2++; s1++; + } + *s2 = 0; + out->length = strlen(out->data); + return 0; +} + + +/* + a case folding copy handler, removing leading and trailing spaces and + multiple internal spaces, and checking for wildcard characters +*/ +static int ldb_handler_fold_wildcard(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out) +{ + if (strchr(in->data, '*')) { + return -1; + } + return ldb_handler_fold(ldb, in, out); +} + +/* + canonicalise a ldap Integer + rfc2252 specifies it should be in decimal form +*/ +static int ldb_canonicalise_Integer(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out) +{ + char *end; + long long i = strtoll(in->data, &end, 0); + if (*end != 0) { + return -1; + } + out->data = talloc_asprintf(ldb, "%lld", i); + if (out->data == NULL) { + return -1; + } + out->length = strlen(out->data); + return 0; +} + +/* + compare two Integers +*/ +static int ldb_comparison_Integer(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0); +} + +/* + compare two binary blobs +*/ +int ldb_comparison_binary(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return memcmp(v1->data, v2->data, v1->length); +} + +/* + compare two case insensitive strings, ignoring multiple whitespace + and leading and trailing whitespace + see rfc2252 section 8.1 +*/ +static int ldb_comparison_fold(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + const char *s1=v1->data, *s2=v2->data; + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + /* TODO: make utf8 safe, possibly with helper function from application */ + while (*s1 && *s2) { + if (toupper(*s1) != toupper(*s2)) break; + if (*s1 == ' ') { + while (s1[0] == s1[1]) s1++; + while (s2[0] == s2[1]) s2++; + } + s1++; s2++; + } + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + return (int)(*s1) - (int)(*s2); +} + +/* + compare two case insensitive strings, ignoring multiple whitespace + and leading and trailing whitespace + see rfc2252 section 8.1 + handles wildcards +*/ +static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, + const struct ldb_val *v1, + const struct ldb_val *v2) +{ + const char *s1=v1->data, *s2=v2->data; + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + /* TODO: make utf8 safe, possibly with helper function from application */ + while (*s1 && *s2) { + if (s1[0] == '*' && s1[1] == 0) { + return 0; + } + if (toupper(*s1) != toupper(*s2)) break; + if (*s1 == ' ') { + while (s1[0] == s1[1]) s1++; + while (s2[0] == s2[1]) s2++; + } + s1++; s2++; + } + while (*s1 == ' ') s1++; + while (*s2 == ' ') s2++; + return (int)(*s1) - (int)(*s2); +} + + +/* + canonicalise a attribute in DN format +*/ +static int ldb_canonicalise_dn(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out) +{ + struct ldb_dn *dn2=NULL, *dn1 = ldb_dn_explode(ldb, in->data); + out->data = NULL; + if (dn1 == NULL) { + goto failed; + } + dn2 = ldb_dn_casefold(ldb, dn1); + if (dn2 == NULL) goto failed; + + out->data = ldb_dn_linearize(ldb, dn2); + if (out->data == NULL) goto failed; + + talloc_free(dn1); + talloc_free(dn2); + return 0; + +failed: + talloc_free(dn1); + talloc_free(dn2); + return -1; +} + +/* + compare two dns +*/ +static int ldb_comparison_dn(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + struct ldb_val cv1, cv2; + int ret; + if (ldb_canonicalise_dn(ldb, v1, &cv1) != 0 || + ldb_canonicalise_dn(ldb, v2, &cv2) != 0) { + goto failed; + } + ret = strcmp(cv1.data, cv2.data); + talloc_free(cv1.data); + talloc_free(cv2.data); + return ret; +failed: + talloc_free(cv1.data); + talloc_free(cv2.data); + return -1; +} + +/* + compare two objectclasses, looking at subclasses +*/ +static int ldb_comparison_objectclass(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + int ret, i; + const char **subclasses; + ret = ldb_comparison_fold(ldb, v1, v2); + if (ret == 0) { + return 0; + } + fprintf(stderr, "looing for %s %s\n", v1->data, v2->data); + subclasses = ldb_subclass_list(ldb, v1->data); + if (subclasses == NULL) { + return ret; + } + for (i=0;subclasses[i];i++) { + struct ldb_val vs; + vs.data = discard_const(subclasses[i]); + vs.length = strlen(subclasses[i]); + if (ldb_comparison_objectclass(ldb, &vs, v2) == 0) { + return 0; + } + } + return ret; +} + +/* + table of standard attribute handlers +*/ +static const struct ldb_attrib_handler ldb_standard_attribs[] = { + { + .attr = LDB_SYNTAX_INTEGER, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_Integer, + .comparison_fn = ldb_comparison_Integer + }, + { + .attr = LDB_SYNTAX_OCTET_STRING, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_copy, + .comparison_fn = ldb_comparison_binary + }, + { + .attr = LDB_SYNTAX_DIRECTORY_STRING, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_fold, + .comparison_fn = ldb_comparison_fold + }, + { + .attr = LDB_SYNTAX_WILDCARD, + .flags = LDB_ATTR_FLAG_WILDCARD, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_fold_wildcard, + .comparison_fn = ldb_comparison_fold_wildcard + }, + { + .attr = LDB_SYNTAX_DN, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_dn, + .comparison_fn = ldb_comparison_dn + }, + { + .attr = LDB_SYNTAX_OBJECTCLASS, + .flags = 0, + .ldif_read_fn = ldb_handler_copy, + .ldif_write_fn = ldb_handler_copy, + .canonicalise_fn = ldb_handler_fold, + .comparison_fn = ldb_comparison_objectclass + } +}; + + +/* + return the attribute handlers for a given syntax name +*/ +const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb, + const char *syntax) +{ + int i; + unsigned num_handlers = sizeof(ldb_standard_attribs)/sizeof(ldb_standard_attribs[0]); + /* TODO: should be replaced with a binary search */ + for (i=0;ischema.attrib_handlers, + struct ldb_attrib_handler, + ldb->schema.num_attrib_handlers + num_handlers); + if (h == NULL) { + ldb_oom(ldb); + return -1; + } + ldb->schema.attrib_handlers = h; + memcpy(h + ldb->schema.num_attrib_handlers, + handlers, sizeof(*h) * num_handlers); + ldb->schema.num_attrib_handlers += num_handlers; + return 0; +} + + +/* + default function for read/write/canonicalise +*/ +static int ldb_default_copy(struct ldb_context *ldb, + const struct ldb_val *in, + struct ldb_val *out) +{ + *out = *in; + return 0; +} + +/* + default function for comparison +*/ +static int ldb_default_cmp(struct ldb_context *ldb, + const struct ldb_val *v1, + const struct ldb_val *v2) +{ + if (v1->length != v2->length) { + return v1->length - v2->length; + } + return memcmp(v1->data, v2->data, v1->length); +} + +/* + default handler function pointers +*/ +static const struct ldb_attrib_handler ldb_default_attrib_handler = { + .attr = NULL, + .ldif_read_fn = ldb_default_copy, + .ldif_write_fn = ldb_default_copy, + .canonicalise_fn = ldb_default_copy, + .comparison_fn = ldb_default_cmp, +}; + +/* + return the attribute handlers for a given attribute +*/ +const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, + const char *attrib) +{ + int i; + const struct ldb_attrib_handler *def = &ldb_default_attrib_handler; + /* TODO: should be replaced with a binary search, with a sort on add */ + for (i=0;ischema.num_attrib_handlers;i++) { + if (strcmp(ldb->schema.attrib_handlers[i].attr, "*") == 0) { + def = &ldb->schema.attrib_handlers[i]; + } + if (ldb_attr_cmp(attrib, ldb->schema.attrib_handlers[i].attr) == 0) { + return &ldb->schema.attrib_handlers[i]; + } + } + return def; +} + + +/* + add to the list of ldif handlers for this ldb context +*/ +void ldb_remove_attrib_handler(struct ldb_context *ldb, const char *attrib) +{ + const struct ldb_attrib_handler *h; + int i; + h = ldb_attrib_handler(ldb, attrib); + if (h == &ldb_default_attrib_handler) { + return; + } + i = h - ldb->schema.attrib_handlers; + if (i < ldb->schema.num_attrib_handlers - 1) { + memmove(&ldb->schema.attrib_handlers[i], + h+1, sizeof(*h) * (ldb->schema.num_attrib_handlers-(i+1))); + } + ldb->schema.num_attrib_handlers--; +} + + +/* + setup the attribute handles for well known attributes +*/ +int ldb_setup_wellknown_attributes(struct ldb_context *ldb) +{ + const struct { + const char *attr; + const char *syntax; + } wellknown[] = { + { "dn", LDB_SYNTAX_DN }, + { "distinguishedName", LDB_SYNTAX_DN }, + { "cn", LDB_SYNTAX_DIRECTORY_STRING }, + { "dc", LDB_SYNTAX_DIRECTORY_STRING }, + { "ou", LDB_SYNTAX_DIRECTORY_STRING }, + { "objectClass", LDB_SYNTAX_OBJECTCLASS } + }; + int i; + for (i=0;ischema.num_classes;i++) { + if (ldb_attr_cmp(class, ldb->schema.classes[i].name) == 0) { + return (const char **)ldb->schema.classes[i].subclasses; + } + } + return NULL; +} + + +/* + add a new subclass +*/ +static int ldb_subclass_new(struct ldb_context *ldb, const char *class, const char *subclass) +{ + struct ldb_subclass *s, *c; + s = talloc_realloc(ldb, ldb->schema.classes, struct ldb_subclass, ldb->schema.num_classes+1); + if (s == NULL) goto failed; + + ldb->schema.classes = s; + c = &s[ldb->schema.num_classes]; + c->name = talloc_strdup(s, class); + if (c->name == NULL) goto failed; + + c->subclasses = talloc_array(s, char *, 2); + if (c->subclasses == NULL) goto failed; + + c->subclasses[0] = talloc_strdup(c->subclasses, subclass); + if (c->subclasses[0] == NULL) goto failed; + c->subclasses[1] = NULL; + + ldb->schema.num_classes++; + + return 0; +failed: + ldb_oom(ldb); + return -1; +} + +/* + add a subclass +*/ +int ldb_subclass_add(struct ldb_context *ldb, const char *class, const char *subclass) +{ + int i, n; + struct ldb_subclass *c; + char **s; + + for (i=0;ischema.num_classes;i++) { + if (ldb_attr_cmp(class, ldb->schema.classes[i].name) == 0) { + break; + } + } + if (i == ldb->schema.num_classes) { + return ldb_subclass_new(ldb, class, subclass); + } + c = &ldb->schema.classes[i]; + + for (n=0;c->subclasses[n];n++) /* noop */; + + s = talloc_realloc(ldb->schema.classes, c->subclasses, char *, n+2); + if (s == NULL) { + ldb_oom(ldb); + return -1; + } + + c->subclasses = s; + s[n] = talloc_strdup(s, subclass); + if (s[n] == NULL) { + ldb_oom(ldb); + return -1; + } + s[n+1] = NULL; + + return 0; +} + +/* + remove a set of subclasses for a class +*/ +void ldb_subclass_remove(struct ldb_context *ldb, const char *class) +{ + int i; + struct ldb_subclass *c; + + for (i=0;ischema.num_classes;i++) { + if (ldb_attr_cmp(class, ldb->schema.classes[i].name) == 0) { + break; + } + } + if (i == ldb->schema.num_classes) { + return; + } + + c = &ldb->schema.classes[i]; + talloc_free(c->name); + talloc_free(c->subclasses); + if (ldb->schema.num_classes-(i+1) > 0) { + memmove(c, c+1, sizeof(*c) * ldb->schema.num_classes-(i+1)); + } + ldb->schema.num_classes--; + if (ldb->schema.num_classes == 0) { + talloc_free(ldb->schema.classes); + ldb->schema.classes = NULL; + } +} diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 7ae314e46c..f147197499 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -1,7 +1,7 @@ /* ldb database library - Copyright (C) Simo Sorce 2004 + Copyright (C) Simo Sorce 2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -40,22 +40,22 @@ #include "ldb/include/ldb_dn.h" -#define LDB_DN_NULL_RETURN(x) do { if (!x) return NULL; } while(0) +#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed static char *escape_string(void *mem_ctx, const char *src) { const char *p, *s; - char *d, *dst; + char *d, *dst=NULL; - LDB_DN_NULL_RETURN(src); + LDB_DN_NULL_FAILED(src); /* allocate destination string, it will be at most 3 times the source */ dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1); - LDB_DN_NULL_RETURN(dst); + LDB_DN_NULL_FAILED(dst); p = s = src; - while (p) { + while (*p) { p += strcspn(p, ",=\n+<>#;\\\""); if (*p == '\0') /* no special s found, all ok */ break; @@ -73,17 +73,20 @@ static char *escape_string(void *mem_ctx, const char *src) memcpy(d, s, &src[strlen(src)] - s + 1); return dst; +failed: + talloc_free(dst); + return NULL; } static char *unescape_string(void *mem_ctx, const char *src) { unsigned x; - char *p, *dst, *end; + char *p, *dst=NULL, *end; - LDB_DN_NULL_RETURN(src); + LDB_DN_NULL_FAILED(src); dst = p = talloc_strdup(mem_ctx, src); - LDB_DN_NULL_RETURN(dst); + LDB_DN_NULL_FAILED(dst); end = &dst[strlen(dst)]; @@ -115,6 +118,9 @@ static char *unescape_string(void *mem_ctx, const char *src) } return dst; +failed: + talloc_free(dst); + return NULL; } static char *seek_to_separator(char *string, const char *separator) @@ -123,7 +129,7 @@ static char *seek_to_separator(char *string, const char *separator) p = strchr(string, '='); - LDB_DN_NULL_RETURN(p); + LDB_DN_NULL_FAILED(p); p++; @@ -134,7 +140,7 @@ static char *seek_to_separator(char *string, const char *separator) p++; while (*p != '\"') { p = strchr(p, '\"'); - LDB_DN_NULL_RETURN(p); + LDB_DN_NULL_FAILED(p); if (*(p - 1) == '\\') p++; @@ -144,6 +150,9 @@ static char *seek_to_separator(char *string, const char *separator) p += strcspn(p, separator); return p; + +failed: + return NULL; } static char *ldb_dn_trim_string(char *string, const char *edge) @@ -169,16 +178,16 @@ static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *ra char *p; at = talloc(mem_ctx, struct ldb_dn_attribute); - LDB_DN_NULL_RETURN(at); + LDB_DN_NULL_FAILED(at); p = strchr(raw_attribute, '='); - LDB_DN_NULL_RETURN(p); + LDB_DN_NULL_FAILED(p); *p = '\0'; at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n")); - LDB_DN_NULL_RETURN(at->name); + LDB_DN_NULL_FAILED(at->name); p++; @@ -196,9 +205,13 @@ static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *ra } /* no quotes means we must unescape the string */ at->value = unescape_string(at, p); - LDB_DN_NULL_RETURN(at->value); + LDB_DN_NULL_FAILED(at->value); return at; + +failed: + talloc_free(at); + return NULL; } static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component) @@ -207,7 +220,7 @@ static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_compo char *p; dc = talloc(mem_ctx, struct ldb_dn_component); - LDB_DN_NULL_RETURN(dc); + LDB_DN_NULL_FAILED(dc); dc->attr_num = 0; dc->attributes = NULL; @@ -220,7 +233,7 @@ static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_compo /* terminate the current attribute and return pointer to the next one */ t = seek_to_separator(p, "+"); - LDB_DN_NULL_RETURN(t); + LDB_DN_NULL_FAILED(t); if (*t) { /* here there is a separator */ *t = '\0'; /*terminate */ @@ -231,11 +244,11 @@ static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_compo dc->attributes = talloc_realloc(dc, dc->attributes, struct ldb_dn_attribute *, dc->attr_num + 1); - LDB_DN_NULL_RETURN(dc->attributes); + LDB_DN_NULL_FAILED(dc->attributes); /* store the exploded attirbute in the main structure */ dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p); - LDB_DN_NULL_RETURN(dc->attributes[dc->attr_num]); + LDB_DN_NULL_FAILED(dc->attributes[dc->attr_num]); dc->attr_num++; @@ -245,6 +258,9 @@ static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_compo } while(*p); return dc; +failed: + talloc_free(dc); + return NULL; } /* FIXME: currently consider a dn composed of only case insensitive attributes @@ -291,7 +307,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) /* Allocate a structure to hold the exploded DN */ edn = talloc(mem_ctx, struct ldb_dn); - LDB_DN_NULL_RETURN(edn); + LDB_DN_NULL_FAILED(edn); /* Initially there are no components */ edn->comp_num = 0; @@ -299,7 +315,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) pdn = p = talloc_strdup(edn, dn); if (!pdn) - goto error; + goto failed; /* get the components */ do { @@ -308,7 +324,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) /* terminate the current component and return pointer to the next one */ t = seek_to_separator(p, ",;"); if (t == NULL) - goto error; + goto failed; if (*t) { /* here there is a separator */ *t = '\0'; /*terminate */ @@ -320,12 +336,12 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) struct ldb_dn_component *, edn->comp_num + 1); if (edn->components == NULL) - goto error; + goto failed; /* store the exploded component in the main structure */ edn->components[edn->comp_num] = explode_component(edn->components, p); if (edn->components[edn->comp_num] == NULL) - goto error; + goto failed; edn->comp_num++; @@ -340,39 +356,39 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) talloc_free(pdn); return edn; -error: +failed: talloc_free(edn); return NULL; } char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn) { - char *dn, *format, *ename, *evalue; + char *dn, *ename, *evalue; + const char *format; int i, j; dn = talloc_strdup(mem_ctx, ""); - LDB_DN_NULL_RETURN(dn); + LDB_DN_NULL_FAILED(dn); for (i = 0; i < edn->comp_num; i++) { if (i != 0) { dn = talloc_append_string(mem_ctx, dn, ","); } for (j = 0; j < edn->components[i]->attr_num; j++) { - if (i != 0 && j == 0) - format = ",%s=%s"; - else if (i == 0 && j == 0) + if (j == 0) { format = "%s=%s"; - else + } else { format = "+%s=%s"; + } - ename = escape_string(mem_ctx, edn->components[i]->attributes[j]->name); - LDB_DN_NULL_RETURN(ename); + ename = escape_string(dn, edn->components[i]->attributes[j]->name); + LDB_DN_NULL_FAILED(ename); - evalue = escape_string(mem_ctx, edn->components[i]->attributes[j]->value); - LDB_DN_NULL_RETURN(evalue); + evalue = escape_string(dn, edn->components[i]->attributes[j]->value); + LDB_DN_NULL_FAILED(evalue); dn = talloc_asprintf_append(dn, format, ename, evalue); - LDB_DN_NULL_RETURN(dn); + LDB_DN_NULL_FAILED(dn); talloc_free(ename); talloc_free(evalue); @@ -380,6 +396,9 @@ char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn) } return dn; +failed: + talloc_free(dn); + return NULL; } /* FIXME: currently consider a dn composed of only case insensitive attributes @@ -414,6 +433,8 @@ int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1) return k; } } + + return 0; } /* @@ -421,45 +442,50 @@ int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1) attribute values of case insensitive attributes. We also need to remove extraneous spaces between elements */ -struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data, - int (* case_fold_attr_fn)(void * user_data, char * attr)) +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn) { struct ldb_dn *cedn; int i, j; - cedn = talloc(mem_ctx, struct ldb_dn); - LDB_DN_NULL_RETURN(cedn); + cedn = talloc(ldb, struct ldb_dn); + LDB_DN_NULL_FAILED(cedn); cedn->comp_num = edn->comp_num; cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num); - LDB_DN_NULL_RETURN(cedn->components); + LDB_DN_NULL_FAILED(cedn->components); for (i = 0; i < edn->comp_num; i++) { struct ldb_dn_component *dc; dc = talloc(cedn->components, struct ldb_dn_component); - LDB_DN_NULL_RETURN(dc); + LDB_DN_NULL_FAILED(dc); dc->attr_num = edn->components[i]->attr_num; dc->attributes = edn->components[i]->attributes; - LDB_DN_NULL_RETURN(dc->attributes); + LDB_DN_NULL_FAILED(dc->attributes); for (j = 0; j < edn->components[i]->attr_num; j++) { struct ldb_dn_attribute *at; + struct ldb_val v0, v; + const struct ldb_attrib_handler *h; at = talloc(dc->attributes, struct ldb_dn_attribute); - LDB_DN_NULL_RETURN(at); + LDB_DN_NULL_FAILED(at); at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name); - LDB_DN_NULL_RETURN(at->name); - - if (case_fold_attr_fn(user_data, at->name)) { - at->value = ldb_casefold(at, edn->components[i]->attributes[j]->value); - } else { - at->value = talloc_strdup(at, edn->components[i]->attributes[j]->value); + LDB_DN_NULL_FAILED(at->name); + + h = ldb_attrib_handler(ldb, at->name); + /* at->value should be a ldb_val, work around + this for now .... */ + v0.data = edn->components[i]->attributes[j]->value; + v0.length = strlen(v0.data); + if (h->canonicalise_fn(ldb, &v0, &v) != 0) { + return NULL; } - LDB_DN_NULL_RETURN(at->value); + talloc_steal(at, v.data); + at->value = v.data; dc->attributes[j] = at; } @@ -467,5 +493,9 @@ struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_dat } return cedn; + +failed: + talloc_free(cedn); + return NULL; } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index f3bc5c6207..deeb84b3c0 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -44,68 +44,6 @@ #include "system/filesys.h" #endif -/* - add to the list of ldif handlers for this ldb context -*/ -int ldb_ldif_add_handlers(struct ldb_context *ldb, - const struct ldb_ldif_handler *handlers, - unsigned num_handlers) -{ - struct ldb_ldif_handler *h; - h = talloc_realloc(ldb, ldb->ldif_handlers, - struct ldb_ldif_handler, - ldb->ldif_num_handlers + num_handlers); - if (h == NULL) { - ldb_oom(ldb); - return -1; - } - ldb->ldif_handlers = h; - memcpy(h + ldb->ldif_num_handlers, - handlers, sizeof(*h) * num_handlers); - ldb->ldif_num_handlers += num_handlers; - return 0; -} - - -/* - default function for ldif read/write -*/ -static int ldb_ldif_default(struct ldb_context *ldb, const struct ldb_val *in, - struct ldb_val *out) -{ - *out = *in; - return 0; -} - - -/* - return a function for reading an ldif encoded attributes into a ldb_val -*/ -static ldb_ldif_handler_t ldb_ldif_read_fn(struct ldb_context *ldb, const char *attr) -{ - int i; - for (i=0;ildif_num_handlers;i++) { - if (ldb_attr_cmp(attr, ldb->ldif_handlers[i].attr) == 0) { - return ldb->ldif_handlers[i].read_fn; - } - } - return ldb_ldif_default; -} - -/* - return a function for writing an ldif encoded attribute from a ldb_val -*/ -static ldb_ldif_handler_t ldb_ldif_write_fn(struct ldb_context *ldb, const char *attr) -{ - int i; - for (i=0;ildif_num_handlers;i++) { - if (ldb_attr_cmp(attr, ldb->ldif_handlers[i].attr) == 0) { - return ldb->ldif_handlers[i].write_fn; - } - } - return ldb_ldif_default; -} - /* */ @@ -356,6 +294,10 @@ int ldb_ldif_write(struct ldb_context *ldb, } for (i=0;inum_elements;i++) { + const struct ldb_attrib_handler *h; + + h = ldb_attrib_handler(ldb, msg->elements[i].name); + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { case LDB_FLAG_MOD_ADD: @@ -374,10 +316,8 @@ int ldb_ldif_write(struct ldb_context *ldb, } for (j=0;jelements[i].num_values;j++) { - ldb_ldif_handler_t write_fn = ldb_ldif_write_fn(ldb, - msg->elements[i].name); struct ldb_val v; - ret = write_fn(ldb, &msg->elements[i].values[j], &v); + ret = h->ldif_write_fn(ldb, &msg->elements[i].values[j], &v); CHECK_RET; if (ldb_should_b64_encode(&v)) { ret = fprintf_fn(private_data, "%s:: ", @@ -650,7 +590,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, msg->dn = value.data; while (next_attr(ldif, &s, &attr, &value) == 0) { - ldb_ldif_handler_t read_fn; + const struct ldb_attrib_handler *h; struct ldb_message_element *el; int ret, empty = 0; @@ -696,7 +636,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, el = &msg->elements[msg->num_elements-1]; - read_fn = ldb_ldif_read_fn(ldb, attr); + h = ldb_attrib_handler(ldb, attr); if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) { @@ -707,7 +647,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, if (!el->values) { goto failed; } - ret = read_fn(ldb, &value, &el->values[el->num_values]); + ret = h->ldif_read_fn(ldb, &value, &el->values[el->num_values]); if (ret != 0) { goto failed; } @@ -731,7 +671,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, goto failed; } el->num_values = 1; - ret = read_fn(ldb, &value, &el->values[0]); + ret = h->ldif_read_fn(ldb, &value, &el->values[0]); if (ret != 0) { goto failed; } diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c new file mode 100644 index 0000000000..45a482066e --- /dev/null +++ b/source4/lib/ldb/common/ldb_match.c @@ -0,0 +1,260 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004-2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb expression matching + * + * Description: ldb expression matching + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + + +/* + check if the scope matches in a search result +*/ +static int ldb_match_scope(const char *dn, const char *base, enum ldb_scope scope) +{ + size_t dn_len, base_len; + + if (base == NULL) { + return 1; + } + + base_len = strlen(base); + dn_len = strlen(dn); + + if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) { + return 1; + } + + if (base_len+1 >= dn_len) { + return 0; + } + + switch (scope) { + case LDB_SCOPE_BASE: + break; + + case LDB_SCOPE_ONELEVEL: + if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && + dn[dn_len - base_len - 1] == ',' && + strchr(dn, ',') == &dn[dn_len - base_len - 1]) { + return 1; + } + break; + + case LDB_SCOPE_SUBTREE: + default: + if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && + dn[dn_len - base_len - 1] == ',') { + return 1; + } + break; + } + + return 0; +} + + +/* + match a leaf node +*/ +static int ldb_match_leaf(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + unsigned int i; + struct ldb_message_element *el; + const struct ldb_attrib_handler *h; + + if (!ldb_match_scope(msg->dn, base, scope)) { + return 0; + } + + if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; + } + + el = ldb_msg_find_element(msg, tree->u.simple.attr); + if (el == NULL) { + return 0; + } + + if (strcmp(tree->u.simple.value.data, "*") == 0) { + return 1; + } + + h = ldb_attrib_handler(ldb, el->name); + + for (i=0;inum_values;i++) { + if (h->comparison_fn(ldb, &tree->u.simple.value, + &el->values[i]) == 0) { + return 1; + } + } + + return 0; +} + + +/* + bitwise-and comparator +*/ +static int ldb_comparator_and(struct ldb_val *v1, struct ldb_val *v2) +{ + uint64_t i1, i2; + i1 = strtoull(v1->data, NULL, 0); + i2 = strtoull(v2->data, NULL, 0); + return ((i1 & i2) == i2); +} + +/* + bitwise-or comparator +*/ +static int ldb_comparator_or(struct ldb_val *v1, struct ldb_val *v2) +{ + uint64_t i1, i2; + i1 = strtoull(v1->data, NULL, 0); + i2 = strtoull(v2->data, NULL, 0); + return ((i1 & i2) != 0); +} + + +/* + extended match, handles things like bitops +*/ +static int ldb_match_extended(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + int i; + const struct { + const char *oid; + int (*comparator)(struct ldb_val *, struct ldb_val *); + } rules[] = { + { LDB_OID_COMPARATOR_AND, ldb_comparator_and}, + { LDB_OID_COMPARATOR_OR, ldb_comparator_or} + }; + int (*comp)(struct ldb_val *, struct ldb_val *) = NULL; + struct ldb_message_element *el; + + if (tree->u.extended.dnAttributes) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet"); + return -1; + } + if (tree->u.extended.rule_id == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); + return -1; + } + if (tree->u.extended.attr == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); + return -1; + } + + for (i=0;iu.extended.rule_id) == 0) { + comp = rules[i].comparator; + break; + } + } + if (comp == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n", + tree->u.extended.rule_id); + return -1; + } + + /* find the message element */ + el = ldb_msg_find_element(msg, tree->u.extended.attr); + if (el == NULL) { + return 0; + } + + for (i=0;inum_values;i++) { + int ret = comp(&el->values[i], &tree->u.extended.value); + if (ret == -1 || ret == 1) return ret; + } + + return 0; +} + +/* + return 0 if the given parse tree matches the given message. Assumes + the message is in sorted order + + return 1 if it matches, and 0 if it doesn't match + + this is a recursive function, and does short-circuit evaluation + */ +int ldb_match_message(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + unsigned int i; + int v; + + switch (tree->operation) { + case LDB_OP_SIMPLE: + break; + + case LDB_OP_EXTENDED: + return ldb_match_extended(ldb, msg, tree, base, scope); + + case LDB_OP_NOT: + return ! ldb_match_message(ldb, msg, tree->u.not.child, base, scope); + + case LDB_OP_AND: + for (i=0;iu.list.num_elements;i++) { + v = ldb_match_message(ldb, msg, tree->u.list.elements[i], + base, scope); + if (!v) return 0; + } + return 1; + + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + v = ldb_match_message(ldb, msg, tree->u.list.elements[i], + base, scope); + if (v) return 1; + } + return 0; + } + + return ldb_match_leaf(ldb, msg, tree, base, scope); +} diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 0c1ea6ca81..38c117d7e0 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -84,8 +84,8 @@ int ldb_dn_cmp(const char *dn1, const char *dn2) compare two attributes return 0 for match */ -int ldb_attr_cmp(const char *dn1, const char *dn2) +int ldb_attr_cmp(const char *attr1, const char *attr2) { - return ldb_caseless_cmp(dn1, dn2); + return ldb_caseless_cmp(attr1, attr2); } diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 691af8bcfa..83de5730d4 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -50,7 +50,6 @@ ADD_OBJ_FILES = \ lib/ldb/ldb_tdb/ldb_search.o \ lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ - lib/ldb/ldb_tdb/ldb_match.o \ lib/ldb/ldb_tdb/ldb_cache.o REQUIRED_SUBSYSTEMS = \ LIBTDB @@ -70,6 +69,9 @@ ADD_OBJ_FILES = \ lib/ldb/common/ldb_utf8.o \ lib/ldb/common/ldb_debug.o \ lib/ldb/common/ldb_modules.o \ + lib/ldb/common/ldb_match.o \ + lib/ldb/common/ldb_attributes.o \ + lib/ldb/common/attrib_handlers.o \ lib/ldb/common/ldb_dn.o REQUIRED_SUBSYSTEMS = \ LIBREPLACE LIBTALLOC LDBSAMBA diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 8feec9e002..868d005399 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -186,16 +186,40 @@ char *ldb_binary_encode(void *ctx, struct ldb_val val); /* - functions for controlling ldif encode/decode + functions for controlling attribute handling */ -typedef int (*ldb_ldif_handler_t)(struct ldb_context *, const struct ldb_val *, struct ldb_val *); +typedef int (*ldb_attr_handler_t)(struct ldb_context *, const struct ldb_val *, struct ldb_val *); +typedef int (*ldb_attr_comparison_t)(struct ldb_context *, const struct ldb_val *, const struct ldb_val *); -struct ldb_ldif_handler { +struct ldb_attrib_handler { const char *attr; - ldb_ldif_handler_t read_fn; - ldb_ldif_handler_t write_fn; + + /* LDB_ATTR_FLAG_* */ + unsigned flags; + + /* convert from ldif to binary format */ + ldb_attr_handler_t ldif_read_fn; + + /* convert from binary to ldif format */ + ldb_attr_handler_t ldif_write_fn; + + /* canonicalise a value, for use by indexing and dn construction */ + ldb_attr_handler_t canonicalise_fn; + + /* compare two values */ + ldb_attr_comparison_t comparison_fn; }; +#define LDB_ATTR_FLAG_HIDDEN (1<<0) +#define LDB_ATTR_FLAG_WILDCARD (1<<1) + +/* well-known ldap attribute syntaxes - see rfc2252 section 4.3.2 */ +#define LDB_SYNTAX_DN "1.3.6.1.4.1.1466.115.121.1.12" +#define LDB_SYNTAX_DIRECTORY_STRING "1.3.6.1.4.1.1466.115.121.1.15" +#define LDB_SYNTAX_INTEGER "1.3.6.1.4.1.1466.115.121.1.27" +#define LDB_SYNTAX_OCTET_STRING "1.3.6.1.4.1.1466.115.121.1.40" +#define LDB_SYNTAX_WILDCARD "LDB_SYNTAX_WILDCARD" +#define LDB_SYNTAX_OBJECTCLASS "LDB_SYNTAX_OBJECTCLASS" /* initialise a ldb context @@ -296,9 +320,9 @@ struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s); int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); char *ldb_base64_encode(void *mem_ctx, const char *buf, int len); int ldb_base64_decode(char *s); -int ldb_ldif_add_handlers(struct ldb_context *ldb, - const struct ldb_ldif_handler *handlers, - unsigned num_handlers); +int ldb_attrib_add_handlers(struct ldb_context *ldb, + const struct ldb_attrib_handler *handlers, + unsigned num_handlers); /* useful functions for ldb_message structure manipulation */ diff --git a/source4/lib/ldb/include/ldb_dn.h b/source4/lib/ldb/include/ldb_dn.h index f355ee4879..723b89e316 100644 --- a/source4/lib/ldb/include/ldb_dn.h +++ b/source4/lib/ldb/include/ldb_dn.h @@ -38,5 +38,4 @@ struct ldb_dn { struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); -struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data, - int (* case_fold_attr_fn)(void * user_data, char * attr)); +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn); diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index f6c1c7ff46..43c925e036 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -68,6 +68,23 @@ struct ldb_module_ops { const char * (*errstring)(struct ldb_module *); }; + +/* + schema related information needed for matching rules +*/ +struct ldb_schema { + /* attribute handling table */ + unsigned num_attrib_handlers; + struct ldb_attrib_handler *attrib_handlers; + + /* objectclass information */ + unsigned num_classes; + struct ldb_subclass { + char *name; + char **subclasses; + } *classes; +}; + /* every ldb connection is started by establishing a ldb_context */ @@ -85,9 +102,7 @@ struct ldb_context { void *value; } *opaque; - /* ldif attribute handling table */ - unsigned ldif_num_handlers; - struct ldb_ldif_handler *ldif_handlers; + struct ldb_schema schema; }; /* the modules init function */ @@ -146,4 +161,34 @@ int lsqlite3_connect(struct ldb_context *ldb, struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); +const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, + const char *attrib); + +int ldb_match_message(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope); + +void ldb_remove_attrib_handler(struct ldb_context *ldb, const char *attrib); +const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb, + const char *syntax); +int ldb_set_attrib_handlers(struct ldb_context *ldb, + const struct ldb_attrib_handler *handlers, + unsigned num_handlers); +int ldb_setup_wellknown_attributes(struct ldb_context *ldb); + +struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); +char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); +int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn); +const char **ldb_subclass_list(struct ldb_context *ldb, const char *class); +void ldb_subclass_remove(struct ldb_context *ldb, const char *class); +int ldb_subclass_add(struct ldb_context *ldb, const char *class, const char *subclass); + +int ldb_handler_copy(struct ldb_context *ldb, + const struct ldb_val *in, struct ldb_val *out); +int ldb_comparison_binary(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2); + #endif diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 0bc2d7b123..0b7ddad5db 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -37,6 +37,11 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" +#define LTDB_FLAG_CASE_INSENSITIVE (1<<0) +#define LTDB_FLAG_INTEGER (1<<1) +#define LTDB_FLAG_WILDCARD (1<<2) +#define LTDB_FLAG_HIDDEN (1<<3) +#define LTDB_FLAG_OBJECTCLASS (1<<4) /* valid attribute flags */ static const struct { @@ -47,11 +52,181 @@ static const struct { { "INTEGER", LTDB_FLAG_INTEGER }, { "WILDCARD", LTDB_FLAG_WILDCARD }, { "HIDDEN", LTDB_FLAG_HIDDEN }, - { "NONE", LTDB_FLAG_NONE }, + { "NONE", 0 }, { NULL, 0 } }; +/* + de-register any special handlers for @ATTRIBUTES +*/ +static void ltdb_attributes_unload(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + struct ldb_message *msg; + int i; + + if (ltdb->cache->attributes == NULL) { + /* no previously loaded attributes */ + return; + } + + msg = ltdb->cache->attributes; + for (i=0;inum_elements;i++) { + const struct ldb_attrib_handler *h; + /* this is rather ugly - a consequence of const handling */ + h = ldb_attrib_handler(module->ldb, msg->elements[i].name); + ldb_remove_attrib_handler(module->ldb, msg->elements[i].name); + if (strcmp(h->attr, msg->elements[i].name) == 0) { + talloc_steal(msg, h->attr); + } + } + + talloc_free(ltdb->cache->attributes); + ltdb->cache->attributes = NULL; +} + +/* + add up the attrib flags for a @ATTRIBUTES element +*/ +static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v) +{ + int i; + unsigned value = 0; + for (i=0;inum_values;i++) { + int j; + for (j=0;ltdb_valid_attr_flags[j].name;j++) { + if (strcmp(ltdb_valid_attr_flags[j].name, + el->values[i].data) == 0) { + value |= ltdb_valid_attr_flags[j].value; + break; + } + } + if (ltdb_valid_attr_flags[j].name == NULL) { + return -1; + } + } + *v = value; + return 0; +} + +/* + register any special handlers from @ATTRIBUTES +*/ +static int ltdb_attributes_load(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + struct ldb_message *msg = ltdb->cache->attributes; + int i; + + if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, msg) == -1) { + goto failed; + } + /* mapping these flags onto ldap 'syntaxes' isn't strictly correct, + but its close enough for now */ + for (i=0;inum_elements;i++) { + unsigned flags; + const char *syntax; + const struct ldb_attrib_handler *h; + struct ldb_attrib_handler h2; + + if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name); + goto failed; + } + switch (flags & ~LTDB_FLAG_HIDDEN) { + case 0: + syntax = LDB_SYNTAX_OCTET_STRING; + break; + case LTDB_FLAG_WILDCARD: + case LTDB_FLAG_WILDCARD | LTDB_FLAG_CASE_INSENSITIVE: + syntax = LDB_SYNTAX_WILDCARD; + break; + case LTDB_FLAG_CASE_INSENSITIVE: + syntax = LDB_SYNTAX_DIRECTORY_STRING; + break; + case LTDB_FLAG_INTEGER: + syntax = LDB_SYNTAX_INTEGER; + break; + default: + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n", + flags, msg->elements[i].name); + goto failed; + } + + h = ldb_attrib_handler_syntax(module->ldb, syntax); + if (h == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, + "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n", + syntax, msg->elements[i].name); + goto failed; + } + h2 = *h; + h2.attr = talloc_strdup(module, msg->elements[i].name); + if (ldb_set_attrib_handlers(module->ldb, &h2, 1) != 0) { + goto failed; + } + } + + return 0; +failed: + return -1; +} + + +/* + register any subclasses from @SUBCLASSES +*/ +static int ltdb_subclasses_load(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + struct ldb_message *msg = ltdb->cache->subclasses; + int i, j; + + if (ltdb_search_dn1(module, LTDB_SUBCLASSES, msg) == -1) { + goto failed; + } + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg->elements[i]; + for (j=0;jnum_values;j++) { + if (ldb_subclass_add(module->ldb, el->name, el->values[j].data) != 0) { + goto failed; + } + } + } + + return 0; +failed: + return -1; +} + + +/* + de-register any @SUBCLASSES +*/ +static void ltdb_subclasses_unload(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + struct ldb_message *msg; + int i; + + if (ltdb->cache->subclasses == NULL) { + /* no previously loaded subclasses */ + return; + } + + msg = ltdb->cache->subclasses; + for (i=0;inum_elements;i++) { + ldb_subclass_remove(module->ldb, msg->elements[i].name); + } + + talloc_free(ltdb->cache->subclasses); + ltdb->cache->subclasses = NULL; +} + + /* initialise the baseinfo record */ @@ -122,6 +297,8 @@ static void ltdb_cache_free(struct ldb_module *module) */ int ltdb_cache_reload(struct ldb_module *module) { + ltdb_attributes_unload(module); + ltdb_subclasses_unload(module); ltdb_cache_free(module); return ltdb_cache_load(module); } @@ -176,9 +353,11 @@ int ltdb_cache_load(struct ldb_module *module) talloc_free(ltdb->cache->last_attribute.name); memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute)); + ltdb_attributes_unload(module); + ltdb_subclasses_unload(module); + talloc_free(ltdb->cache->indexlist); talloc_free(ltdb->cache->subclasses); - talloc_free(ltdb->cache->attributes); ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message); ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message); @@ -192,10 +371,11 @@ int ltdb_cache_load(struct ldb_module *module) if (ltdb_search_dn1(module, LTDB_INDEXLIST, ltdb->cache->indexlist) == -1) { goto failed; } - if (ltdb_search_dn1(module, LTDB_SUBCLASSES, ltdb->cache->subclasses) == -1) { + + if (ltdb_attributes_load(module) == -1) { goto failed; } - if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, ltdb->cache->attributes) == -1) { + if (ltdb_subclasses_load(module) == -1) { goto failed; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 00b124a9cf..4d8a14f7f0 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -101,17 +101,45 @@ static char *ldb_dn_key(struct ldb_context *ldb, const char *attr, const struct ldb_val *value) { char *ret = NULL; + struct ldb_val v; + const struct ldb_attrib_handler *h; + char *attr_folded; - if (ldb_should_b64_encode(value)) { + attr_folded = ldb_casefold(ldb, attr); + if (!attr_folded) { + return NULL; + } + + h = ldb_attrib_handler(ldb, attr); + if (h->canonicalise_fn(ldb, value, &v) != 0) { + /* canonicalisation can be refused. For example, + a attribute that takes wildcards will refuse to canonicalise + if the value contains a wildcard */ + talloc_free(attr_folded); + return NULL; + } + + if (ldb_should_b64_encode(&v)) { char *vstr = ldb_base64_encode(ldb, value->data, value->length); if (!vstr) return NULL; - ret = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr, vstr); + ret = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); talloc_free(vstr); + if (v.data != value->data) { + talloc_free(v.data); + } + talloc_free(attr_folded); return ret; } - return talloc_asprintf(ldb, "%s:%s:%.*s", - LTDB_INDEX, attr, value->length, (char *)value->data); + ret = talloc_asprintf(ldb, "%s:%s:%.*s", + LTDB_INDEX, attr_folded, v.length, (char *)v.data); + + if (v.data != value->data) { + talloc_free(v.data); + } + talloc_free(attr_folded); + + return ret; } /* @@ -234,46 +262,50 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, struct dn_list *list) { struct ldb_context *ldb = module->ldb; - struct ltdb_private *ltdb = module->private_data; unsigned int i; int ret; const char *target = tree->u.simple.value.data; + const char **subclasses; list->count = 0; list->dn = NULL; ret = ltdb_index_dn_simple(module, tree, index_list, list); - for (i=0;icache->subclasses->num_elements;i++) { - struct ldb_message_element *el = <db->cache->subclasses->elements[i]; - if (ldb_attr_cmp(el->name, target) == 0) { - unsigned int j; - for (j=0;jnum_values;j++) { - struct ldb_parse_tree tree2; - struct dn_list *list2; - tree2.operation = LDB_OP_SIMPLE; - tree2.u.simple.attr = talloc_strdup(list, LTDB_OBJECTCLASS); - if (!tree2.u.simple.attr) { - return -1; - } - tree2.u.simple.value = el->values[j]; - list2 = talloc(list, struct dn_list); - if (list2 == NULL) { - return -1; - } - if (ltdb_index_dn_objectclass(module, &tree2, - index_list, list2) == 1) { - if (list->count == 0) { - *list = *list2; - ret = 1; - } else { - list_union(ldb, list, list2); - talloc_free(list2); - } - } - talloc_free(tree2.u.simple.attr); + subclasses = ldb_subclass_list(module->ldb, target); + + if (subclasses == NULL) { + return ret; + } + + for (i=0;subclasses[i];i++) { + struct ldb_parse_tree tree2; + struct dn_list *list2; + tree2.operation = LDB_OP_SIMPLE; + tree2.u.simple.attr = talloc_strdup(list, LTDB_OBJECTCLASS); + if (!tree2.u.simple.attr) { + return -1; + } + tree2.u.simple.value.data = talloc_strdup(tree2.u.simple.attr, subclasses[i]); + if (tree2.u.simple.value.data == NULL) { + return -1; + } + tree2.u.simple.value.length = strlen(subclasses[i]); + list2 = talloc(list, struct dn_list); + if (list2 == NULL) { + return -1; + } + if (ltdb_index_dn_objectclass(module, &tree2, + index_list, list2) == 1) { + if (list->count == 0) { + *list = *list2; + ret = 1; + } else { + list_union(ldb, list, list2); + talloc_free(list2); } } + talloc_free(tree2.u.simple.attr); } return ret; @@ -607,7 +639,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr } ret = 0; - if (ltdb_message_match(module, msg, tree, base, scope) == 1) { + if (ldb_match_message(module->ldb, msg, tree, base, scope) == 1) { ret = ltdb_add_attr_results(module, msg, attrs, &count, res); } talloc_free(msg); @@ -799,6 +831,10 @@ int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) int ret; unsigned int i, j; + if (msg->dn[0] == '@') { + return 0; + } + if (ltdb->cache->indexlist->num_elements == 0) { /* no indexed fields */ return 0; @@ -834,6 +870,10 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, int ret, i; unsigned int j; + if (dn[0] == '@') { + return 0; + } + dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); if (!dn_key) { return -1; @@ -895,6 +935,10 @@ int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) int ret; unsigned int i, j; + if (msg->dn[0] == '@') { + return 0; + } + /* find the list of indexed fields */ if (ltdb->cache->indexlist->num_elements == 0) { /* no indexed fields */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_match.c b/source4/lib/ldb/ldb_tdb/ldb_match.c deleted file mode 100644 index b5b023bc09..0000000000 --- a/source4/lib/ldb/ldb_tdb/ldb_match.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - ldb database library - - Copyright (C) Andrew Tridgell 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb expression matching - * - * Description: ldb expression matching for tdb backend - * - * Author: Andrew Tridgell - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" -#include "ldb/ldb_tdb/ldb_tdb.h" -#include - -/* - see if two ldb_val structures contain the same data as integers - return 1 for a match, 0 for a mis-match -*/ -static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2) -{ - uint64_t i1, i2; - - i1 = strtoull(v1->data, NULL, 0); - i2 = strtoull(v2->data, NULL, 0); - - return i1 == i2; -} - -/* - see if two ldb_val structures contain the same data as case insensitive strings - return 1 for a match, 0 for a mis-match -*/ -static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1, - const struct ldb_val *v2) -{ - if (v1->length != v2->length) { - return 0; - } - if (strncasecmp(v1->data, v2->data, v1->length) == 0) { - return 1; - } - return 0; -} - -/* - see if two ldb_val structures contain the same data with wildcards - and case insensitive - return 1 for a match, 0 for a mis-match -*/ -static int ltdb_val_equal_wildcard_ci(struct ldb_module *module, - const struct ldb_val *v1, - const struct ldb_val *v2) -{ - struct ldb_context *ldb = module->ldb; - char *s1, *s2; - int ret; - - if (!v1->data || !v2->data) { - return v1->data == v2->data; - } - - s1 = ldb_casefold(ldb, v1->data); - if (!s1) { - return -1; - } - - s2 = ldb_casefold(ldb, v2->data); - if (!s2) { - talloc_free(s1); - return -1; - } - - ret = fnmatch(s2, s1, 0); - - talloc_free(s1); - talloc_free(s2); - - if (ret == 0) { - return 1; - } - - return 0; -} - -/* - see if two ldb_val structures contain the same data with wildcards - return 1 for a match, 0 for a mis-match -*/ -static int ltdb_val_equal_wildcard(struct ldb_module *module, - const struct ldb_val *v1, - const struct ldb_val *v2, - int flags) -{ - if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - return ltdb_val_equal_wildcard_ci(module, v1, v2); - } - if (!v1->data || !v2->data) { - return v1->data == v2->data; - } - if (fnmatch(v2->data, v1->data, 0) == 0) { - return 1; - } - return 0; -} - - -/* - see if two objectclasses are considered equal. This handles - the subclass attributes - - v1 contains the in-database value, v2 contains the value - that the user gave - - return 1 for a match, 0 for a mis-match -*/ -static int ltdb_val_equal_objectclass(struct ldb_module *module, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - struct ltdb_private *ltdb = module->private_data; - unsigned int i; - - if (ltdb_val_equal_case_insensitive(v1, v2) == 1) { - return 1; - } - - for (i=0;icache->subclasses->num_elements;i++) { - struct ldb_message_element *el = <db->cache->subclasses->elements[i]; - if (ldb_attr_cmp(el->name, v2->data) == 0) { - unsigned int j; - for (j=0;jnum_values;j++) { - if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) { - return 1; - } - } - } - } - - return 0; -} - - -/* - see if two ldb_val structures contain the same data - - v1 contains the in-database value, v2 contains the value - that the user gave - - return 1 for a match, 0 for a mis-match -*/ -int ltdb_val_equal(struct ldb_module *module, - const char *attr_name, - const struct ldb_val *v1, const struct ldb_val *v2) -{ - int flags = ltdb_attribute_flags(module, attr_name); - - if (flags & LTDB_FLAG_OBJECTCLASS) { - return ltdb_val_equal_objectclass(module, v1, v2); - } - - if (flags & LTDB_FLAG_INTEGER) { - return ltdb_val_equal_integer(v1, v2); - } - - if (flags & LTDB_FLAG_WILDCARD) { - return ltdb_val_equal_wildcard(module, v1, v2, flags); - } - - if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - return ltdb_val_equal_case_insensitive(v1, v2); - } - - if (v1->length != v2->length) return 0; - - if (v1->length == 0) return 1; - - if (memcmp(v1->data, v2->data, v1->length) == 0) { - return 1; - } - - return 0; -} - -/* - check if the scope matches in a search result -*/ -static int scope_match(const char *dn, const char *base, enum ldb_scope scope) -{ - size_t dn_len, base_len; - - if (base == NULL) { - return 1; - } - - base_len = strlen(base); - dn_len = strlen(dn); - - if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) { - return 1; - } - - if (base_len+1 >= dn_len) { - return 0; - } - - switch (scope) { - case LDB_SCOPE_BASE: - break; - - case LDB_SCOPE_ONELEVEL: - if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && - dn[dn_len - base_len - 1] == ',' && - strchr(dn, ',') == &dn[dn_len - base_len - 1]) { - return 1; - } - break; - - case LDB_SCOPE_SUBTREE: - default: - if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && - dn[dn_len - base_len - 1] == ',') { - return 1; - } - break; - } - - return 0; -} - - -/* - match a leaf node -*/ -static int match_leaf(struct ldb_module *module, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) -{ - unsigned int i; - struct ldb_message_element *el; - - if (!scope_match(msg->dn, base, scope)) { - return 0; - } - - if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; - } - return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; - } - - el = ldb_msg_find_element(msg, tree->u.simple.attr); - if (el == NULL) { - return 0; - } - - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; - } - - for (i=0;inum_values;i++) { - if (ltdb_val_equal(module, el->name, &el->values[i], - &tree->u.simple.value)) { - return 1; - } - } - - return 0; -} - - -/* - bitwise-and comparator -*/ -static int comparator_and(struct ldb_val *v1, struct ldb_val *v2) -{ - uint64_t i1, i2; - i1 = strtoull(v1->data, NULL, 0); - i2 = strtoull(v2->data, NULL, 0); - return ((i1 & i2) == i2); -} - -/* - bitwise-or comparator -*/ -static int comparator_or(struct ldb_val *v1, struct ldb_val *v2) -{ - uint64_t i1, i2; - i1 = strtoull(v1->data, NULL, 0); - i2 = strtoull(v2->data, NULL, 0); - return ((i1 & i2) != 0); -} - - -/* - extended match, handles things like bitops -*/ -static int ltdb_extended_match(struct ldb_module *module, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) -{ - int i; - const struct { - const char *oid; - int (*comparator)(struct ldb_val *, struct ldb_val *); - } rules[] = { - { LDB_OID_COMPARATOR_AND, comparator_and}, - { LDB_OID_COMPARATOR_OR, comparator_or} - }; - int (*comp)(struct ldb_val *, struct ldb_val *) = NULL; - struct ldb_message_element *el; - - if (tree->u.extended.dnAttributes) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet"); - return -1; - } - if (tree->u.extended.rule_id == NULL) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); - return -1; - } - if (tree->u.extended.attr == NULL) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); - return -1; - } - - for (i=0;iu.extended.rule_id) == 0) { - comp = rules[i].comparator; - break; - } - } - if (comp == NULL) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n", - tree->u.extended.rule_id); - return -1; - } - - /* find the message element */ - el = ldb_msg_find_element(msg, tree->u.extended.attr); - if (el == NULL) { - return 0; - } - - for (i=0;inum_values;i++) { - int ret = comp(&el->values[i], &tree->u.extended.value); - if (ret == -1 || ret == 1) return ret; - } - - return 0; -} - -/* - return 0 if the given parse tree matches the given message. Assumes - the message is in sorted order - - return 1 if it matches, and 0 if it doesn't match - - this is a recursive function, and does short-circuit evaluation - */ -int ltdb_message_match(struct ldb_module *module, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) -{ - unsigned int i; - int v; - - switch (tree->operation) { - case LDB_OP_SIMPLE: - break; - - case LDB_OP_EXTENDED: - return ltdb_extended_match(module, msg, tree, base, scope); - - case LDB_OP_NOT: - return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope); - - case LDB_OP_AND: - for (i=0;iu.list.num_elements;i++) { - v = ltdb_message_match(module, msg, tree->u.list.elements[i], - base, scope); - if (!v) return 0; - } - return 1; - - case LDB_OP_OR: - for (i=0;iu.list.num_elements;i++) { - v = ltdb_message_match(module, msg, tree->u.list.elements[i], - base, scope); - if (v) return 1; - } - return 0; - } - - return match_leaf(module, msg, tree, base, scope); -} diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index d6e7d66f68..e48043da88 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -92,8 +92,9 @@ static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *r unsigned int i; for (i=0;inum_elements;i++) { - int flags = ltdb_attribute_flags(module, msg->elements[i].name); - if ((msg->dn[0] != '@') && (flags & LTDB_FLAG_HIDDEN)) { + const struct ldb_attrib_handler *h; + h = ldb_attrib_handler(ldb, msg->elements[i].name); + if ((msg->dn[0] != '@') && (h->flags & LDB_ATTR_FLAG_HIDDEN)) { continue; } if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { @@ -195,7 +196,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val) { - int flags; + const struct ldb_attrib_handler *h; /* all attribute types recognise the "*" wildcard */ if (val->length == 1 && strncmp((char *)val->data, "*", 1) == 0) { @@ -206,8 +207,8 @@ int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, return 0; } - flags = ltdb_attribute_flags(module, attr_name); - if (flags & LTDB_FLAG_WILDCARD) { + h = ldb_attrib_handler(module->ldb, attr_name); + if (h->flags & LDB_ATTR_FLAG_WILDCARD) { return 1; } @@ -415,8 +416,8 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* see if it matches the given expression */ - if (!ltdb_message_match(sinfo->module, msg, sinfo->tree, - sinfo->base, sinfo->scope)) { + if (!ldb_match_message(sinfo->module->ldb, msg, sinfo->tree, + sinfo->base, sinfo->scope)) { talloc_free(msg); return 0; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index bc61378f18..22797b96d1 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -41,20 +41,9 @@ #include "ldb/include/ldb_dn.h" #include "ldb/ldb_tdb/ldb_tdb.h" -#define LDBLOCK "INT_LDBLOCK" +#define LDBLOCK "@INT_LDBLOCK" -/* - callback function used in call to ldb_dn_fold() for determining whether an - attribute type requires case folding. -*/ -static int ltdb_case_fold_attr_required(void * user_data, char *attr) -{ - struct ldb_module *module = talloc_get_type(user_data, struct ldb_module); - - return ltdb_attribute_flags(module, attr) & LTDB_FLAG_CASE_INSENSITIVE; -} - /* form a TDB_DATA for a record key caller frees @@ -68,9 +57,6 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) TDB_DATA key; char *key_str = NULL; char *dn_folded = NULL; - const char *prefix = LTDB_INDEX ":"; - const char *s; - int flags; /* most DNs are case insensitive. The exception is index DNs for @@ -78,52 +64,22 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) there are 3 cases dealt with in this code: - 1) if the dn doesn't start with @INDEX: then uppercase the attribute + 1) if the dn doesn't start with @ then uppercase the attribute names and the attributes values of case insensitive attributes - 2) if the dn starts with @INDEX:attr and 'attr' is a case insensitive - attribute then uppercase whole dn - 3) if the dn starts with @INDEX:attr and 'attr' is a case sensitive - attribute then uppercase up to the value of the attribute, but - not the value itself + 2) if the dn starts with @ then leave it alone - the indexing code handles + the rest */ - if (strncmp(dn, prefix, strlen(prefix)) == 0 && - (s = strchr(dn+strlen(prefix), ':'))) { - char *attr_name, *attr_name_folded; - attr_name = talloc_strndup(ldb, dn+strlen(prefix), (s-(dn+strlen(prefix)))); - if (!attr_name) { - goto failed; - } - flags = ltdb_attribute_flags(module, attr_name); - - if (flags & LTDB_FLAG_CASE_INSENSITIVE) { - dn_folded = ldb_casefold(ldb, dn); - } else { - attr_name_folded = ldb_casefold(ldb, attr_name); - if (!attr_name_folded) { - goto failed; - } - dn_folded = talloc_asprintf(ldb, "%s:%s:%s", - prefix, attr_name_folded, - s+1); - talloc_free(attr_name_folded); - } - talloc_free(attr_name); - } - /* special cases for tdb */ - else if (*dn == '@' || strncmp(LDBLOCK, dn, strlen(LDBLOCK)) == 0) { - + if (*dn == '@') { dn_folded = talloc_strdup(ldb, dn); - } - else { + } else { struct ldb_dn *edn, *cedn; edn = ldb_dn_explode(ldb, dn); if (!edn) goto failed; - cedn = ldb_dn_casefold(ldb, edn, module, - ltdb_case_fold_attr_required); - if (!edn) + cedn = ldb_dn_casefold(ldb, edn); + if (!cedn) goto failed; dn_folded = ldb_dn_linearize(ldb, cedn); @@ -563,6 +519,7 @@ static int msg_delete_element(struct ldb_module *module, unsigned int i; int found; struct ldb_message_element *el; + const struct ldb_attrib_handler *h; found = find_element(msg, name); if (found == -1) { @@ -571,8 +528,10 @@ static int msg_delete_element(struct ldb_module *module, el = &msg->elements[found]; + h = ldb_attrib_handler(ldb, el->name); + for (i=0;inum_values;i++) { - if (ltdb_val_equal(module, msg->elements[i].name, &el->values[i], val)) { + if (h->comparison_fn(ldb, &el->values[i], val) == 0) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], sizeof(el->values[i])*(el->num_values-(i+1))); diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 6377092a21..46c5843d60 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -45,20 +45,11 @@ struct ltdb_private { #define LTDB_SEQUENCE_NUMBER "sequenceNumber" #define LTDB_OBJECTCLASS "objectClass" -/* well known attribute flags */ -#define LTDB_FLAG_CASE_INSENSITIVE (1<<0) -#define LTDB_FLAG_INTEGER (1<<1) -#define LTDB_FLAG_WILDCARD (1<<2) -#define LTDB_FLAG_OBJECTCLASS (1<<3) -#define LTDB_FLAG_HIDDEN (1<<4) -#define LTDB_FLAG_NONE 0 - /* The following definitions come from lib/ldb/ldb_tdb/ldb_cache.c */ int ltdb_cache_reload(struct ldb_module *module); int ltdb_cache_load(struct ldb_module *module); int ltdb_increase_sequence_number(struct ldb_module *module); -int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name); int ltdb_check_at_attributes_values(const struct ldb_val *value); /* The following definitions come from lib/ldb/ldb_tdb/ldb_index.c */ @@ -111,16 +102,6 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms int ltdb_lock_read(struct ldb_module *module); int ltdb_unlock_read(struct ldb_module *module); -/* The following definitions come from lib/ldb/ldb_tdb/ldb_match.c */ -int ltdb_val_equal(struct ldb_module *module, - const char *attr_name, - const struct ldb_val *v1, const struct ldb_val *v2); -int ltdb_message_match(struct ldb_module *module, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope); - int ltdb_index_del_value(struct ldb_module *module, const char *dn, struct ldb_message_element *el, int v_idx); diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index 17a45df78d..13499b8428 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -75,9 +75,29 @@ static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *i return 0; } +/* + compare two objectSids +*/ +static int ldb_comparison_objectSid(struct ldb_context *ldb, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (strncmp(v1->data, "S-", 2) == 0 && + strncmp(v2->data, "S-", 2) == 0) { + return strcmp(v1->data, v2->data); + } + return ldb_comparison_binary(ldb, v1, v2); +} + -static const struct ldb_ldif_handler samba_handlers[] = { - { "objectSid", ldif_read_objectSid, ldif_write_objectSid } +static const struct ldb_attrib_handler samba_handlers[] = { + { + .attr = "objectSid", + .flags = 0, + .ldif_read_fn = ldif_read_objectSid, + .ldif_write_fn = ldif_write_objectSid, + .canonicalise_fn = ldb_handler_copy, + .comparison_fn = ldb_comparison_objectSid + } }; /* @@ -85,5 +105,5 @@ static const struct ldb_ldif_handler samba_handlers[] = { */ int ldb_register_samba_handlers(struct ldb_context *ldb) { - return ldb_ldif_add_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers)); + return ldb_set_attrib_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers)); } -- cgit From bd7812be319556162b22562a7c9670dce00d90f9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 07:02:26 +0000 Subject: r8038: - fixed indexing on binary values that need base64 encoding and canonicalisation - added support for recognising the S- form of objectsid in search expressions. I thought this could be done with just a comparison modified comparison function, but it turns out it also needs a canonicalisation function so that indexing can work (This used to be commit 7d2bee2c5619f284375ecbed14371c5e8639ed1c) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 3 +-- source4/lib/ldb/samba/ldif_handlers.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 4d8a14f7f0..089c24eae4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -118,9 +118,8 @@ static char *ldb_dn_key(struct ldb_context *ldb, talloc_free(attr_folded); return NULL; } - if (ldb_should_b64_encode(&v)) { - char *vstr = ldb_base64_encode(ldb, value->data, value->length); + char *vstr = ldb_base64_encode(ldb, v.data, v.length); if (!vstr) return NULL; ret = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); talloc_free(vstr); diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index 13499b8428..e364bf716d 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -85,9 +85,31 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, strncmp(v2->data, "S-", 2) == 0) { return strcmp(v1->data, v2->data); } + if (strncmp(v1->data, "S-", 2) == 0) { + struct ldb_val v; + int ret; + if (ldif_read_objectSid(ldb, v1, &v) != 0) { + return -1; + } + ret = ldb_comparison_binary(ldb, &v, v2); + talloc_free(v.data); + return ret; + } return ldb_comparison_binary(ldb, v1, v2); } +/* + canonicalise a objectSid +*/ +static int ldb_canonicalise_objectSid(struct ldb_context *ldb, const struct ldb_val *in, + struct ldb_val *out) +{ + if (strncmp(in->data, "S-", 2) == 0) { + return ldif_read_objectSid(ldb, in, out); + } + return ldb_handler_copy(ldb, in, out); +} + static const struct ldb_attrib_handler samba_handlers[] = { { @@ -95,7 +117,7 @@ static const struct ldb_attrib_handler samba_handlers[] = { .flags = 0, .ldif_read_fn = ldif_read_objectSid, .ldif_write_fn = ldif_write_objectSid, - .canonicalise_fn = ldb_handler_copy, + .canonicalise_fn = ldb_canonicalise_objectSid, .comparison_fn = ldb_comparison_objectSid } }; -- cgit From 036a7dd9f8310d8bf380c8947f3ee76c51bcf6d0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 07:23:14 +0000 Subject: r8039: allow ldb test suite to be run outside of the ldb directory (This used to be commit f3e3b2ccd93b87c1c240cf7e44106389b089b526) --- source4/lib/ldb/tests/test-generic.sh | 44 +++++++++++++++++------------------ source4/lib/ldb/tests/test-schema.sh | 14 +++++------ source4/lib/ldb/tests/test-sqlite3.sh | 2 +- source4/lib/ldb/tests/test-tdb.sh | 14 ++++++++--- 4 files changed, 41 insertions(+), 33 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 9b59261003..607b3f7851 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -3,57 +3,57 @@ echo "LDB_URL: $LDB_URL" echo "Adding base elements" -$VALGRIND bin/ldbadd tests/test.ldif || exit 1 +$VALGRIND ldbadd $LDBDIR/tests/test.ldif || exit 1 echo "Modifying elements" -$VALGRIND bin/ldbmodify tests/test-modify.ldif || exit 1 +$VALGRIND ldbmodify $LDBDIR/tests/test-modify.ldif || exit 1 echo "Showing modified record" -$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 +$VALGRIND ldbsearch '(uid=uham)' || exit 1 echo "Rename entry" OLDDN="cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST" NEWDN="cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST" -$VALGRIND bin/ldbrename "$OLDDN" "$NEWDN" || exit 1 +$VALGRIND ldbrename "$OLDDN" "$NEWDN" || exit 1 echo "Showing renamed record" -$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 +$VALGRIND ldbsearch '(uid=uham)' || exit 1 echo "Starting ldbtest" -time $VALGRIND bin/ldbtest --num-records 1000 --num-searches 10 || exit 1 +time $VALGRIND ldbtest --num-records 1000 --num-searches 10 || exit 1 echo "Adding index" -$VALGRIND bin/ldbadd tests/test-index.ldif || exit 1 +$VALGRIND ldbadd $LDBDIR/tests/test-index.ldif || exit 1 echo "Adding attributes" -$VALGRIND bin/ldbadd tests/test-wrong_attributes.ldif || exit 1 +$VALGRIND ldbadd $LDBDIR/tests/test-wrong_attributes.ldif || exit 1 echo "testing indexed search" -$VALGRIND bin/ldbsearch '(uid=uham)' || exit 1 -$VALGRIND bin/ldbsearch '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 -$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham))' || exit 1 -$VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham))' || exit 1 -$VALGRIND bin/ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' || exit 1 -$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 -$VALGRIND bin/ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 -$VALGRIND bin/ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 +$VALGRIND ldbsearch '(uid=uham)' || exit 1 +$VALGRIND ldbsearch '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uham))' || exit 1 +$VALGRIND ldbsearch '(|(uid=uham)(uid=uham))' || exit 1 +$VALGRIND ldbsearch '(|(uid=uham)(uid=uham)(objectclass=OpenLDAPperson))' || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uham)(!(objectclass=xxx)))' || exit 1 +$VALGRIND ldbsearch '(&(objectclass=person)(uid=uham)(!(uid=uhamxx)))' uid \* \+ dn || exit 1 +$VALGRIND ldbsearch '(&(uid=uham)(uid=uha*)(title=*))' uid || exit 1 # note that the "((" is treated as an attribute not an expression # this matches the openldap ldapsearch behaviour of looking for a '=' # to see if the first argument is an expression or not -$VALGRIND bin/ldbsearch '((' uid || exit 1 -$VALGRIND bin/ldbsearch '(objectclass=)' uid || exit 1 -$VALGRIND bin/ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 +$VALGRIND ldbsearch '((' uid || exit 1 +$VALGRIND ldbsearch '(objectclass=)' uid || exit 1 +$VALGRIND ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 echo "Starting ldbtest indexed" -time $VALGRIND bin/ldbtest --num-records 1000 --num-searches 5000 || exit 1 +time $VALGRIND ldbtest --num-records 1000 --num-searches 5000 || exit 1 echo "Testing one level search" -count=`$VALGRIND bin/ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep ^dn | wc -l` +count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep ^dn | wc -l` if [ "$count" != 3 ]; then echo returned $count records - expected 3 exit 1 fi echo "Testing binary file attribute value" -$VALGRIND bin/ldbmodify tests/photo.ldif || exit 1 +$VALGRIND ldbmodify $LDBDIR/tests/photo.ldif || exit 1 diff --git a/source4/lib/ldb/tests/test-schema.sh b/source4/lib/ldb/tests/test-schema.sh index 08595a0a9c..a8af8a38e2 100755 --- a/source4/lib/ldb/tests/test-schema.sh +++ b/source4/lib/ldb/tests/test-schema.sh @@ -7,22 +7,22 @@ rm -f schema.ldb echo "LDB_URL: $LDB_URL" echo "Adding schema" -$VALGRIND bin/ldbadd tests/schema-tests/schema.ldif || exit 1 +$VALGRIND bin/ldbadd $LDBDIR/tests/schema-tests/schema.ldif || exit 1 echo "Adding few test elements (no failure expected here)" -$VALGRIND bin/ldbadd tests/schema-tests/schema-add-test.ldif || exit 1 +$VALGRIND bin/ldbadd $LDBDIR/tests/schema-tests/schema-add-test.ldif || exit 1 echo "Modifying elements (2 failures expected here)" -$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-1.ldif || exit 1 -$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-2.ldif || exit 1 -$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-3.ldif || exit 1 -$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-4.ldif +$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-1.ldif || exit 1 +$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-2.ldif || exit 1 +$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-3.ldif || exit 1 +$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-4.ldif if [ "$?" == "0" ]; then echo "test failed!" exit 1 fi -$VALGRIND bin/ldbmodify tests/schema-tests/schema-mod-test-5.ldif +$VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-5.ldif if [ "$?" == "0" ]; then echo "test failed!" exit 1 diff --git a/source4/lib/ldb/tests/test-sqlite3.sh b/source4/lib/ldb/tests/test-sqlite3.sh index 95babeac8d..7e0c96feaf 100755 --- a/source4/lib/ldb/tests/test-sqlite3.sh +++ b/source4/lib/ldb/tests/test-sqlite3.sh @@ -5,5 +5,5 @@ export LDB_URL="sqlite:///var/tmp/test.ldb" rm -f sqltest.ldb -. tests/test-generic.sh +. $LDBDIR/tests/test-generic.sh diff --git a/source4/lib/ldb/tests/test-tdb.sh b/source4/lib/ldb/tests/test-tdb.sh index 470975e8b8..3d461b0b3f 100755 --- a/source4/lib/ldb/tests/test-tdb.sh +++ b/source4/lib/ldb/tests/test-tdb.sh @@ -3,10 +3,18 @@ export LDB_URL="tdbtest.ldb" +PATH=bin:$PATH +export PATH + rm -f tdbtest.ldb -. tests/test-generic.sh +if [ -z "$LDBDIR" ]; then + LDBDIR="." + export LDBDIR +fi + +. $LDBDIR/tests/test-generic.sh -. tests/test-extended.sh +. $LDBDIR/tests/test-extended.sh -. tests/test-tdb-features.sh +. $LDBDIR/tests/test-tdb-features.sh -- cgit From 978335ae94ef00bc7f2242cb06dcf23a803245c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 08:04:48 +0000 Subject: r8041: remove a mis-spelled debug message :-) (This used to be commit 912fa269d293b3b55fc5fa65f9532614fe2e202d) --- source4/lib/ldb/common/attrib_handlers.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index fcff4113b4..6c5692bcbe 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -245,7 +245,6 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb, if (ret == 0) { return 0; } - fprintf(stderr, "looing for %s %s\n", v1->data, v2->data); subclasses = ldb_subclass_list(ldb, v1->data); if (subclasses == NULL) { return ret; -- cgit From 4a8c3a9e623e40a3fd927c4ed5fa3a8fa41f3012 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 Jul 2005 08:14:21 +0000 Subject: r8042: give better error message metze (This used to be commit 70118e9529aaf7af9129df7cb3a6749598b17568) --- source4/lib/messaging/messaging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 6209c36554..7cf488c7d0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -393,7 +393,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id status = socket_listen(msg->sock, msg->path, 0, 50, 0); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Unable to setup messaging listener for '%s'\n", msg->path)); + DEBUG(0,("Unable to setup messaging listener for '%s':%s\n", msg->path, nt_errstr(status))); talloc_free(msg); return NULL; } -- cgit From f450b0a02a71370865094a9e3ac5271c4cde9c88 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 08:18:48 +0000 Subject: r8043: increase shell compatibility of ldb tests (This used to be commit 60863b6faf7f78566052491340607cbb4b3f2e72) --- source4/lib/ldb/tests/test-generic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 607b3f7851..d3965fb176 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -50,7 +50,7 @@ time $VALGRIND ldbtest --num-records 1000 --num-searches 5000 || exit 1 echo "Testing one level search" count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep ^dn | wc -l` -if [ "$count" != 3 ]; then +if [ $count != 3 ]; then echo returned $count records - expected 3 exit 1 fi -- cgit From 5d55ee570beded36f985c907fcf952659557849c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 Jul 2005 08:27:23 +0000 Subject: r8044: give a better error code metze (This used to be commit fdbf822f1c90cba110d91720ea586ceef9de38b2) --- source4/lib/socket/socket_unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index f27076b5d8..9c19aaace5 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -101,7 +101,7 @@ static NTSTATUS unixdom_connect(struct socket_context *sock, int ret; if (strlen(srv_address)+1 > sizeof(srv_addr.sun_path)) { - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_OBJECT_PATH_INVALID; } ZERO_STRUCT(srv_addr); @@ -124,7 +124,7 @@ static NTSTATUS unixdom_listen(struct socket_context *sock, int ret; if (strlen(my_address)+1 > sizeof(my_addr.sun_path)) { - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_OBJECT_PATH_INVALID; } /* delete if it already exists */ @@ -259,7 +259,7 @@ static NTSTATUS unixdom_sendto(struct socket_context *sock, struct sockaddr_un srv_addr; if (strlen(dest_addr)+1 > sizeof(srv_addr.sun_path)) { - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_OBJECT_PATH_INVALID; } ZERO_STRUCT(srv_addr); -- cgit From 8139838acf6a211a3984dac71babe7778148aa8b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Jul 2005 05:18:01 +0000 Subject: r8067: added a method for disabling the password prompt in programs that want cmdline credentials, but don't want a prompt if none are supplied (This used to be commit d7d7f7292b7032dcad6d6245510af229f12f7085) --- source4/lib/cmdline/popt_common.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index b8f8a675eb..b7b7bdc286 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -181,7 +181,15 @@ struct poptOption popt_common_version[] = { */ -static BOOL dont_ask = False; +static BOOL dont_ask; + +/* + disable asking for a password +*/ +void popt_common_dont_ask(void) +{ + dont_ask = True; +} static void popt_common_credentials_callback(poptContext con, enum poptCallbackReason reason, -- cgit From 75883a2237f52863df2eff1fe9d9ee8408b40feb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Jul 2005 06:32:06 +0000 Subject: r8071: reduce the size of the default ldb tests. We run on some pretty low powered machines in the farm, and don't want to chew too much cpu needlessly. (This used to be commit c03753faa46d52ae4606546b57962e10c41ea3ad) --- source4/lib/ldb/tests/test-generic.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index d3965fb176..db6377d078 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -20,7 +20,7 @@ echo "Showing renamed record" $VALGRIND ldbsearch '(uid=uham)' || exit 1 echo "Starting ldbtest" -time $VALGRIND ldbtest --num-records 1000 --num-searches 10 || exit 1 +time $VALGRIND ldbtest --num-records 100 --num-searches 10 || exit 1 echo "Adding index" $VALGRIND ldbadd $LDBDIR/tests/test-index.ldif || exit 1 @@ -46,7 +46,7 @@ $VALGRIND ldbsearch '(objectclass=)' uid || exit 1 $VALGRIND ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 echo "Starting ldbtest indexed" -time $VALGRIND ldbtest --num-records 1000 --num-searches 5000 || exit 1 +time $VALGRIND ldbtest --num-records 100 --num-searches 500 || exit 1 echo "Testing one level search" count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep ^dn | wc -l` -- cgit From 1c5105065a44173667de2a022dd2417e56b527d6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 2 Jul 2005 17:30:03 +0000 Subject: r8082: large rewite of ldb_dn.c - we do not support multpiple attribute components anymore, makes code a lot easier they will be readded later if we found out they are really used, so far my tests show w2k3 do not handle them as well - fix escaping issues, move component value to be in an ldb_val structure still need to handle binary values case - make cononicalize functions leak less memory by giving a specific memory context - fix tests scripts so that test-ldap can start - make test not delete databases on completion so that I can inspect them (This used to be commit 624a73148d125690ce18515f19231d26df207738) --- source4/lib/ldb/common/attrib_handlers.c | 68 +++-- source4/lib/ldb/common/ldb_attributes.c | 9 +- source4/lib/ldb/common/ldb_dn.c | 410 ++++++++++++----------------- source4/lib/ldb/common/ldb_ldif.c | 6 +- source4/lib/ldb/common/ldb_match.c | 2 +- source4/lib/ldb/include/ldb.h | 4 +- source4/lib/ldb/include/ldb_dn.h | 41 --- source4/lib/ldb/include/ldb_private.h | 28 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 3 +- source4/lib/ldb/samba/ldif_handlers.c | 32 +-- source4/lib/ldb/tests/test-extended.sh | 3 +- source4/lib/ldb/tests/test-ldap.sh | 16 +- source4/lib/ldb/tests/test-tdb-features.sh | 3 +- source4/lib/ldb/tests/test-tdb.sh | 2 + 15 files changed, 284 insertions(+), 345 deletions(-) delete mode 100644 source4/lib/ldb/include/ldb_dn.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 6c5692bcbe..a35a450670 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -34,10 +34,10 @@ /* default handler that just copies a ldb_val. */ -int ldb_handler_copy(struct ldb_context *ldb, +int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - *out = ldb_val_dup(ldb, in); + *out = ldb_val_dup(mem_ctx, in); if (out->data == NULL) { ldb_oom(ldb); return -1; @@ -49,11 +49,11 @@ int ldb_handler_copy(struct ldb_context *ldb, a case folding copy handler, removing leading and trailing spaces and multiple internal spaces */ -static int ldb_handler_fold(struct ldb_context *ldb, +static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { uint8_t *s1, *s2; - out->data = talloc_size(ldb, strlen(in->data)+1); + out->data = talloc_size(mem_ctx, strlen(in->data)+1); if (out->data == NULL) { ldb_oom(ldb); return -1; @@ -78,20 +78,20 @@ static int ldb_handler_fold(struct ldb_context *ldb, a case folding copy handler, removing leading and trailing spaces and multiple internal spaces, and checking for wildcard characters */ -static int ldb_handler_fold_wildcard(struct ldb_context *ldb, +static int ldb_handler_fold_wildcard(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { if (strchr(in->data, '*')) { return -1; } - return ldb_handler_fold(ldb, in, out); + return ldb_handler_fold(ldb, mem_ctx, in, out); } /* canonicalise a ldap Integer rfc2252 specifies it should be in decimal form */ -static int ldb_canonicalise_Integer(struct ldb_context *ldb, +static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { char *end; @@ -99,7 +99,7 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb, if (*end != 0) { return -1; } - out->data = talloc_asprintf(ldb, "%lld", i); + out->data = talloc_asprintf(mem_ctx, "%lld", i); if (out->data == NULL) { return -1; } @@ -110,7 +110,7 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb, /* compare two Integers */ -static int ldb_comparison_Integer(struct ldb_context *ldb, +static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0); @@ -119,7 +119,7 @@ static int ldb_comparison_Integer(struct ldb_context *ldb, /* compare two binary blobs */ -int ldb_comparison_binary(struct ldb_context *ldb, +int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { if (v1->length != v2->length) { @@ -133,7 +133,7 @@ int ldb_comparison_binary(struct ldb_context *ldb, and leading and trailing whitespace see rfc2252 section 8.1 */ -static int ldb_comparison_fold(struct ldb_context *ldb, +static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { const char *s1=v1->data, *s2=v2->data; @@ -159,7 +159,8 @@ static int ldb_comparison_fold(struct ldb_context *ldb, see rfc2252 section 8.1 handles wildcards */ -static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, +static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, + void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { @@ -187,40 +188,49 @@ static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, /* canonicalise a attribute in DN format */ -static int ldb_canonicalise_dn(struct ldb_context *ldb, +static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - struct ldb_dn *dn2=NULL, *dn1 = ldb_dn_explode(ldb, in->data); + struct ldb_dn *dn1, *dn2; + int ret = -1; + + out->length = 0; out->data = NULL; + + dn1 = ldb_dn_explode(mem_ctx, in->data); if (dn1 == NULL) { - goto failed; + return -1; } dn2 = ldb_dn_casefold(ldb, dn1); - if (dn2 == NULL) goto failed; + if (dn2 == NULL) { + goto done; + } - out->data = ldb_dn_linearize(ldb, dn2); - if (out->data == NULL) goto failed; + out->data = ldb_dn_linearize(mem_ctx, dn2); + if (out->data == NULL) { + goto done; + } + out->length = strlen(out->data); - talloc_free(dn1); - talloc_free(dn2); - return 0; + ret = 0; -failed: +done: talloc_free(dn1); talloc_free(dn2); - return -1; + + return ret; } /* compare two dns */ -static int ldb_comparison_dn(struct ldb_context *ldb, +static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { struct ldb_val cv1, cv2; int ret; - if (ldb_canonicalise_dn(ldb, v1, &cv1) != 0 || - ldb_canonicalise_dn(ldb, v2, &cv2) != 0) { + if (ldb_canonicalise_dn(ldb, mem_ctx, v1, &cv1) != 0 || + ldb_canonicalise_dn(ldb, mem_ctx, v2, &cv2) != 0) { goto failed; } ret = strcmp(cv1.data, cv2.data); @@ -236,12 +246,12 @@ failed: /* compare two objectclasses, looking at subclasses */ -static int ldb_comparison_objectclass(struct ldb_context *ldb, +static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { int ret, i; const char **subclasses; - ret = ldb_comparison_fold(ldb, v1, v2); + ret = ldb_comparison_fold(ldb, mem_ctx, v1, v2); if (ret == 0) { return 0; } @@ -253,7 +263,7 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb, struct ldb_val vs; vs.data = discard_const(subclasses[i]); vs.length = strlen(subclasses[i]); - if (ldb_comparison_objectclass(ldb, &vs, v2) == 0) { + if (ldb_comparison_objectclass(ldb, mem_ctx, &vs, v2) == 0) { return 0; } } diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index e053ccbbf2..3d4f24771f 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -60,10 +60,16 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb, default function for read/write/canonicalise */ static int ldb_default_copy(struct ldb_context *ldb, + void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - *out = *in; + *out = ldb_val_dup(mem_ctx, in); + + if (out->length == 0) { + return -1; + } + return 0; } @@ -71,6 +77,7 @@ static int ldb_default_copy(struct ldb_context *ldb, default function for comparison */ static int ldb_default_cmp(struct ldb_context *ldb, + void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index f147197499..18b620b506 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -37,63 +37,74 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include "ldb/include/ldb_dn.h" #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed -static char *escape_string(void *mem_ctx, const char *src) +static char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value) { - const char *p, *s; - char *d, *dst=NULL; + const char *p, *s, *src; + char *d, *dst; + int len; - LDB_DN_NULL_FAILED(src); + if (!value.length) + return NULL; + + p = s = src = (const char *)value.data; + len = value.length; /* allocate destination string, it will be at most 3 times the source */ - dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1); + dst = d = talloc_array(mem_ctx, char, len * 3 + 1); LDB_DN_NULL_FAILED(dst); - p = s = src; + while (p - src < len) { - while (*p) { p += strcspn(p, ",=\n+<>#;\\\""); - if (*p == '\0') /* no special s found, all ok */ + + if (p - src == len) /* found no escapable chars */ break; - if (*p) { /* copy part of the string and escape */ - memcpy(d, s, p - s); - d += (p - s); + memcpy(d, s, p - s); /* copy the part of the string before the stop */ + d += (p - s); /* move to current position */ + + if (*p) { /* it is a normal escapable character */ *d++ = '\\'; *d++ = *p++; - s = p; + } else { /* we have a zero byte in the string */ + strncpy(d, "\00", 3); /* escape the zero */ + d = d + 3; + p++; /* skip the zero */ } + s = p; /* move forward */ } /* copy the last part (with zero) and return */ - memcpy(d, s, &src[strlen(src)] - s + 1); + memcpy(d, s, &src[len] - s + 1); return dst; + failed: talloc_free(dst); return NULL; } -static char *unescape_string(void *mem_ctx, const char *src) +static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src) { + struct ldb_val value; unsigned x; - char *p, *dst=NULL, *end; + char *p, *dst = NULL, *end; + + value.length = 0; LDB_DN_NULL_FAILED(src); - dst = p = talloc_strdup(mem_ctx, src); + dst = p = talloc_memdup(mem_ctx, src, strlen(src) + 1); LDB_DN_NULL_FAILED(dst); end = &dst[strlen(dst)]; while (*p) { p += strcspn(p, ",=\n+<>#;\\\""); - if (*p == '\0') /* no escapes or specials found, all ok */ - return dst; if (*p == '\\') { if (strchr(",=\n+<>#;\\\"", p[1])) { @@ -112,31 +123,41 @@ static char *unescape_string(void *mem_ctx, const char *src) } } - /* a string with not escaped specials is invalid */ - - return NULL; + /* a string with not escaped specials is invalid (tested) */ + if (*p != '\0') { + goto failed; + } } - return dst; + value.length = end - dst; + value.data = dst; + return value; + failed: talloc_free(dst); - return NULL; + return value; } -static char *seek_to_separator(char *string, const char *separator) -{ - char *p; - - p = strchr(string, '='); +/* check if the string contains quotes + * skips leading and trailing spaces + * - returns 0 if no quotes found + * - returns 1 if quotes are found and put their position + * in *quote_start and *quote_end parameters + * - return -1 if there are open quotes + */ - LDB_DN_NULL_FAILED(p); +static int get_quotes_position(const char *source, int *quote_start, int *quote_end) +{ + const char *p; - p++; + p = source; /* check if there are quotes surrounding the value */ - p += strspn(p, " \n"); /* skip white spaces after '=' */ + p += strspn(p, " \n"); /* skip white spaces */ if (*p == '\"') { + *quote_start = p - source; + p++; while (*p != '\"') { p = strchr(p, '\"'); @@ -145,11 +166,50 @@ static char *seek_to_separator(char *string, const char *separator) if (*(p - 1) == '\\') p++; } + + *quote_end = p - source; + return 1; + } + + return 0; + +failed: + return -1; +} + +static char *seek_to_separator(char *string, const char *separators) +{ + char *p; + int ret, qs, qe; + + p = strchr(string, '='); + LDB_DN_NULL_FAILED(p); + + p++; + + /* check if there are quotes surrounding the value */ + + ret = get_quotes_position(p, &qs, &qe); + if (ret == -1) + return NULL; + + if (ret == 1) { /* quotes found */ + + p += qe; /* positioning after quotes */ + p += strspn(p, " \n"); /* skip white spaces after the quote */ + + if (strcspn(p, separators) != 0) /* if there are characters between quotes */ + return NULL; /* and separators, the dn is invalid */ + + return p; /* return on the separator */ } - p += strcspn(p, separator); + /* no quotes found seek to separators */ + ret = strcspn(p, separators); + if (ret == 0) /* no separators ?! bail out */ + return NULL; - return p; + return p + ret; failed: return NULL; @@ -172,132 +232,53 @@ static char *ldb_dn_trim_string(char *string, const char *edge) return s; } -static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *raw_attribute) +/* we choosed to not support multpile valued components */ +static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component) { - struct ldb_dn_attribute *at; + struct ldb_dn_component dc; char *p; + int ret, qs, qe; - at = talloc(mem_ctx, struct ldb_dn_attribute); - LDB_DN_NULL_FAILED(at); - - p = strchr(raw_attribute, '='); - + /* find attribute type/value separator */ + p = strchr(raw_component, '='); LDB_DN_NULL_FAILED(p); - *p = '\0'; + *p++ = '\0'; /* terminate name and point to value */ - at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n")); - LDB_DN_NULL_FAILED(at->name); + /* copy and trim name in the component */ + dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n")); + if (!dc.name) + return dc; - p++; + ret = get_quotes_position(p, &qs, &qe); - p = ldb_dn_trim_string(p, " \n"); + switch (ret) { + case 0: /* no quotes trim the string */ + p = ldb_dn_trim_string(p, " \n"); + dc.value = ldb_dn_unescape_value(mem_ctx, p); + break; - if (*p == '\"') { /* quotes at start means there must be quotes at the end */ - if (p[strlen(p) - 1] != '\"') /* malformed value */ - return NULL; - - p++; - p[strlen(p) - 1] = '\0'; - at->value = talloc_strdup(at, p); + case 1: /* quotes found get the unquoted string */ + p[qe] = '\0'; + p = p + qs + 1; + dc.value.length = strlen(p); + dc.value.data = talloc_memdup(mem_ctx, p, dc.value.length + 1); + break; - return at; + default: /* mismatched quotes ot other error, bail out */ + goto failed; } - /* no quotes means we must unescape the string */ - at->value = unescape_string(at, p); - LDB_DN_NULL_FAILED(at->value); - - return at; - -failed: - talloc_free(at); - return NULL; -} -static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component) -{ - struct ldb_dn_component *dc; - char *p; - - dc = talloc(mem_ctx, struct ldb_dn_component); - LDB_DN_NULL_FAILED(dc); - - dc->attr_num = 0; - dc->attributes = NULL; - - p = raw_component; - - /* get the components */ - do { - char *t; - - /* terminate the current attribute and return pointer to the next one */ - t = seek_to_separator(p, "+"); - LDB_DN_NULL_FAILED(t); - - if (*t) { /* here there is a separator */ - *t = '\0'; /*terminate */ - t++; /* a separtor means there's another attribute that follows */ - } - - /* allocate attributes pointer */ - dc->attributes = talloc_realloc(dc, dc->attributes, - struct ldb_dn_attribute *, - dc->attr_num + 1); - LDB_DN_NULL_FAILED(dc->attributes); - - /* store the exploded attirbute in the main structure */ - dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p); - LDB_DN_NULL_FAILED(dc->attributes[dc->attr_num]); - - dc->attr_num++; - - /* jump to the next attribute if any */ - p = t; - - } while(*p); + if (dc.value.length == 0) { + goto failed; + } return dc; -failed: - talloc_free(dc); - return NULL; -} - -/* FIXME: currently consider a dn composed of only case insensitive attributes - this is not correct and need to be fixed soon */ -static void ldb_dn_sort_attributes(struct ldb_dn *edn) -{ - struct ldb_dn_attribute *at0, *at1; - int i, j, k, l; - for (i = 0; i < edn->comp_num; i++) { - if (edn->components[i]->attr_num > 1) { - - /* it is very unlikely that there is a multivalued RDN. In that - unlikely case it is very unlikely you will find more than 2 - values. So the use of bubble sort here seem to be acceptable */ - for (j = 0; (j + 1) < edn->components[i]->attr_num; j++) { - for (k = j; k >= 0; k--) { - at0 = edn->components[i]->attributes[k]; - at1 = edn->components[i]->attributes[k + 1]; - l = ldb_caseless_cmp(at0->name, at1->name); - if (l > 0) { - /* already sorted, so no bubbles to move exit inner loop */ - break; - } - if (l == 0) { - if (ldb_caseless_cmp(at0->value, at1->value) >= 0) { - /* already sorted, so no bubbles to move exit inner loop */ - break; - } - } - - edn->components[i]->attributes[k] = at1; - edn->components[i]->attributes[k + 1] = at0; - } - } - } - } +failed: + talloc_free(dc.name); + dc.name = NULL; + return dc; } struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) @@ -305,6 +286,8 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) struct ldb_dn *edn; /* the exploded dn */ char *pdn, *p; + pdn = NULL; + /* Allocate a structure to hold the exploded DN */ edn = talloc(mem_ctx, struct ldb_dn); LDB_DN_NULL_FAILED(edn); @@ -314,8 +297,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) edn->components = NULL; pdn = p = talloc_strdup(edn, dn); - if (!pdn) - goto failed; + LDB_DN_NULL_FAILED(pdn); /* get the components */ do { @@ -323,25 +305,23 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) /* terminate the current component and return pointer to the next one */ t = seek_to_separator(p, ",;"); - if (t == NULL) - goto failed; + LDB_DN_NULL_FAILED(t); if (*t) { /* here there is a separator */ *t = '\0'; /*terminate */ - t++; /* a separtor means there's another component that follows */ + t++; /* a separtor means another component follows */ } /* allocate space to hold the dn component */ edn->components = talloc_realloc(edn, edn->components, - struct ldb_dn_component *, + struct ldb_dn_component, edn->comp_num + 1); if (edn->components == NULL) goto failed; /* store the exploded component in the main structure */ - edn->components[edn->comp_num] = explode_component(edn->components, p); - if (edn->components[edn->comp_num] == NULL) - goto failed; + edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p); + LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name); edn->comp_num++; @@ -350,87 +330,71 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) } while(*p); - /* sort attributes if there's any multivalued component */ - ldb_dn_sort_attributes(edn); - talloc_free(pdn); return edn; failed: + talloc_free(pdn); talloc_free(edn); return NULL; } -char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn) +char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) { - char *dn, *ename, *evalue; - const char *format; - int i, j; + char *dn, *value; + const char *format = "%s=%s"; + int i; dn = talloc_strdup(mem_ctx, ""); LDB_DN_NULL_FAILED(dn); for (i = 0; i < edn->comp_num; i++) { + if (i != 0) { - dn = talloc_append_string(mem_ctx, dn, ","); + format = ",%s=%s"; } - for (j = 0; j < edn->components[i]->attr_num; j++) { - if (j == 0) { - format = "%s=%s"; - } else { - format = "+%s=%s"; - } - - ename = escape_string(dn, edn->components[i]->attributes[j]->name); - LDB_DN_NULL_FAILED(ename); - evalue = escape_string(dn, edn->components[i]->attributes[j]->value); - LDB_DN_NULL_FAILED(evalue); + value = ldb_dn_escape_value(dn, edn->components[i].value); + LDB_DN_NULL_FAILED(value); - dn = talloc_asprintf_append(dn, format, ename, evalue); - LDB_DN_NULL_FAILED(dn); + dn = talloc_asprintf_append(dn, format, edn->components[i].name, value); + LDB_DN_NULL_FAILED(dn); - talloc_free(ename); - talloc_free(evalue); - } + talloc_free(value); } return dn; + failed: talloc_free(dn); return NULL; } -/* FIXME: currently consider a dn composed of only case insensitive attributes - this is not correct and need to be fixed soon */ -int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1) +/* compare DNs using casefolding compare functions */ +int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1) { - struct ldb_dn_attribute *at0, *at1; - int i, j, k; + int i, ret; /* if the number of components doesn't match they differ */ if (edn0->comp_num != edn1->comp_num) return (edn1->comp_num - edn0->comp_num); for (i = 0; i < edn0->comp_num; i++) { + const struct ldb_attrib_handler *h; - /* if the number of attributes per component doesn't match they differ */ - if (edn0->components[i]->attr_num != edn1->components[i]->attr_num) - return (edn1->components[i]->attr_num - edn0->components[i]->attr_num); - - for (j = 0; j < edn0->components[i]->attr_num; j++) { - at0 = edn0->components[i]->attributes[j]; - at1 = edn1->components[i]->attributes[j]; - - /* compare names */ - k = ldb_caseless_cmp(at0->name, at1->name); - if (k) - return k; + /* compare names (attribute names are guaranteed to be ASCII only) */ + ret = ldb_caseless_cmp(edn0->components[i].name, + edn1->components[i].name); + if (ret) { + return ret; + } - /* names match, compare values */ - k = ldb_caseless_cmp(at0->value, at1->value); - if (k) - return k; + /* names match, compare values */ + h = ldb_attrib_handler(ldb, edn0->components[i].name); + ret = h->comparison_fn(ldb, ldb, &(edn0->components[i].value), + &(edn1->components[i].value)); + if (ret) { + return ret; } } @@ -438,55 +402,31 @@ int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1) } /* - casefold a dn. We need to uppercase the attribute names, and the - attribute values of case insensitive attributes. We also need to remove - extraneous spaces between elements + casefold a dn. We need to casefold the attribute names, and canonicalize + attribute values of case insensitive attributes. */ -struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn) +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn) { struct ldb_dn *cedn; - int i, j; + int i; cedn = talloc(ldb, struct ldb_dn); LDB_DN_NULL_FAILED(cedn); cedn->comp_num = edn->comp_num; - cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num); + cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num); LDB_DN_NULL_FAILED(cedn->components); for (i = 0; i < edn->comp_num; i++) { - struct ldb_dn_component *dc; + struct ldb_dn_component dc; + const struct ldb_attrib_handler *h; - dc = talloc(cedn->components, struct ldb_dn_component); - LDB_DN_NULL_FAILED(dc); + dc.name = ldb_casefold(cedn, edn->components[i].name); + LDB_DN_NULL_FAILED(dc.name); - dc->attr_num = edn->components[i]->attr_num; - dc->attributes = edn->components[i]->attributes; - LDB_DN_NULL_FAILED(dc->attributes); - - for (j = 0; j < edn->components[i]->attr_num; j++) { - struct ldb_dn_attribute *at; - struct ldb_val v0, v; - const struct ldb_attrib_handler *h; - - at = talloc(dc->attributes, struct ldb_dn_attribute); - LDB_DN_NULL_FAILED(at); - - at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name); - LDB_DN_NULL_FAILED(at->name); - - h = ldb_attrib_handler(ldb, at->name); - /* at->value should be a ldb_val, work around - this for now .... */ - v0.data = edn->components[i]->attributes[j]->value; - v0.length = strlen(v0.data); - if (h->canonicalise_fn(ldb, &v0, &v) != 0) { - return NULL; - } - - talloc_steal(at, v.data); - at->value = v.data; - dc->attributes[j] = at; + h = ldb_attrib_handler(ldb, dc.name); + if (h->canonicalise_fn(ldb, cedn, &(edn->components[i].value), &(dc.value)) != 0) { + goto failed; } cedn->components[i] = dc; diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index deeb84b3c0..79ec857cbd 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -317,7 +317,7 @@ int ldb_ldif_write(struct ldb_context *ldb, for (j=0;jelements[i].num_values;j++) { struct ldb_val v; - ret = h->ldif_write_fn(ldb, &msg->elements[i].values[j], &v); + ret = h->ldif_write_fn(ldb, ldb, &msg->elements[i].values[j], &v); CHECK_RET; if (ldb_should_b64_encode(&v)) { ret = fprintf_fn(private_data, "%s:: ", @@ -647,7 +647,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, if (!el->values) { goto failed; } - ret = h->ldif_read_fn(ldb, &value, &el->values[el->num_values]); + ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]); if (ret != 0) { goto failed; } @@ -671,7 +671,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, goto failed; } el->num_values = 1; - ret = h->ldif_read_fn(ldb, &value, &el->values[0]); + ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[0]); if (ret != 0) { goto failed; } diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 45a482066e..462c078d81 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -120,7 +120,7 @@ static int ldb_match_leaf(struct ldb_context *ldb, h = ldb_attrib_handler(ldb, el->name); for (i=0;inum_values;i++) { - if (h->comparison_fn(ldb, &tree->u.simple.value, + if (h->comparison_fn(ldb, ldb, &tree->u.simple.value, &el->values[i]) == 0) { return 1; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 868d005399..1f642d3bff 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -188,8 +188,8 @@ char *ldb_binary_encode(void *ctx, struct ldb_val val); /* functions for controlling attribute handling */ -typedef int (*ldb_attr_handler_t)(struct ldb_context *, const struct ldb_val *, struct ldb_val *); -typedef int (*ldb_attr_comparison_t)(struct ldb_context *, const struct ldb_val *, const struct ldb_val *); +typedef int (*ldb_attr_handler_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, struct ldb_val *); +typedef int (*ldb_attr_comparison_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, const struct ldb_val *); struct ldb_attrib_handler { const char *attr; diff --git a/source4/lib/ldb/include/ldb_dn.h b/source4/lib/ldb/include/ldb_dn.h deleted file mode 100644 index 723b89e316..0000000000 --- a/source4/lib/ldb/include/ldb_dn.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Unix SMB/CIFS implementation. - LDAP server - Copyright (C) Simo Sorce 2004 - Copyright (C) Derrell Lipman 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -struct ldb_dn_attribute { - char *name; - char *value; -}; - -struct ldb_dn_component { - int attr_num; - struct ldb_dn_attribute **attributes; -}; - -struct ldb_dn { - int comp_num; - struct ldb_dn_component **components; -}; - - -struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); -char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); -int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); -struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn); diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 43c925e036..1d7d453767 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -1,8 +1,9 @@ /* ldb database library - Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Tridgell 2004 Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2004 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -105,6 +106,16 @@ struct ldb_context { struct ldb_schema schema; }; +/* internal ldb exploded dn structures */ +struct ldb_dn_component { + char *name; + struct ldb_val value; +}; +struct ldb_dn { + int comp_num; + struct ldb_dn_component *components; +}; + /* the modules init function */ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); @@ -178,17 +189,22 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb, unsigned num_handlers); int ldb_setup_wellknown_attributes(struct ldb_context *ldb); + +/* The following definitions come from lib/ldb/common/ldb_dn.c */ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); -char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn); -int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1); -struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, struct ldb_dn *edn); +char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn); +int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1); +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn); + + +/* The following definitions come from lib/ldb/common/ldb_attributes.c */ const char **ldb_subclass_list(struct ldb_context *ldb, const char *class); void ldb_subclass_remove(struct ldb_context *ldb, const char *class); int ldb_subclass_add(struct ldb_context *ldb, const char *class, const char *subclass); -int ldb_handler_copy(struct ldb_context *ldb, +int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out); -int ldb_comparison_binary(struct ldb_context *ldb, +int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2); #endif diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 089c24eae4..a3317a8765 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -111,7 +111,7 @@ static char *ldb_dn_key(struct ldb_context *ldb, } h = ldb_attrib_handler(ldb, attr); - if (h->canonicalise_fn(ldb, value, &v) != 0) { + if (h->canonicalise_fn(ldb, ldb, value, &v) != 0) { /* canonicalisation can be refused. For example, a attribute that takes wildcards will refuse to canonicalise if the value contains a wildcard */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 22797b96d1..eb72e665f5 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -38,7 +38,6 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include "ldb/include/ldb_dn.h" #include "ldb/ldb_tdb/ldb_tdb.h" #define LDBLOCK "@INT_LDBLOCK" @@ -531,7 +530,7 @@ static int msg_delete_element(struct ldb_module *module, h = ldb_attrib_handler(ldb, el->name); for (i=0;inum_values;i++) { - if (h->comparison_fn(ldb, &el->values[i], val) == 0) { + if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) { if (inum_values-1) { memmove(&el->values[i], &el->values[i+1], sizeof(el->values[i])*(el->num_values-(i+1))); diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index e364bf716d..a6095cddbc 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -30,16 +30,16 @@ /* convert a ldif formatted objectSid to a NDR formatted blob */ -static int ldif_read_objectSid(struct ldb_context *ldb, const struct ldb_val *in, - struct ldb_val *out) +static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) { struct dom_sid *sid; NTSTATUS status; - sid = dom_sid_parse_talloc(ldb, in->data); + sid = dom_sid_parse_talloc(mem_ctx, in->data); if (sid == NULL) { return -1; } - status = ndr_push_struct_blob(out, ldb, sid, + status = ndr_push_struct_blob(out, mem_ctx, sid, (ndr_push_flags_fn_t)ndr_push_dom_sid); talloc_free(sid); if (!NT_STATUS_IS_OK(status)) { @@ -51,12 +51,12 @@ static int ldif_read_objectSid(struct ldb_context *ldb, const struct ldb_val *in /* convert a NDR formatted blob to a ldif formatted objectSid */ -static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *in, - struct ldb_val *out) +static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) { struct dom_sid *sid; NTSTATUS status; - sid = talloc(ldb, struct dom_sid); + sid = talloc(mem_ctx, struct dom_sid); if (sid == NULL) { return -1; } @@ -66,7 +66,7 @@ static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *i talloc_free(sid); return -1; } - out->data = dom_sid_string(ldb, sid); + out->data = dom_sid_string(mem_ctx, sid); talloc_free(sid); if (out->data == NULL) { return -1; @@ -78,7 +78,7 @@ static int ldif_write_objectSid(struct ldb_context *ldb, const struct ldb_val *i /* compare two objectSids */ -static int ldb_comparison_objectSid(struct ldb_context *ldb, +static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { if (strncmp(v1->data, "S-", 2) == 0 && @@ -88,26 +88,26 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, if (strncmp(v1->data, "S-", 2) == 0) { struct ldb_val v; int ret; - if (ldif_read_objectSid(ldb, v1, &v) != 0) { + if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) { return -1; } - ret = ldb_comparison_binary(ldb, &v, v2); + ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2); talloc_free(v.data); return ret; } - return ldb_comparison_binary(ldb, v1, v2); + return ldb_comparison_binary(ldb, mem_ctx, v1, v2); } /* canonicalise a objectSid */ -static int ldb_canonicalise_objectSid(struct ldb_context *ldb, const struct ldb_val *in, - struct ldb_val *out) +static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) { if (strncmp(in->data, "S-", 2) == 0) { - return ldif_read_objectSid(ldb, in, out); + return ldif_read_objectSid(ldb, mem_ctx, in, out); } - return ldb_handler_copy(ldb, in, out); + return ldb_handler_copy(ldb, mem_ctx, in, out); } diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index 0bcb3ebcaa..c3958cf01c 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -2,7 +2,7 @@ echo "Running extended search tests" -rm -f $LDB_URL +mv $LDB_URL $LDB_URL.1 cat < Date: Sat, 2 Jul 2005 18:34:13 +0000 Subject: r8083: check attribute type is valid (only ascii alphanum chars and '-' char) fail if not (This used to be commit b1a61cd5d03b4c61b81c810123ffeb3621831617) --- source4/lib/ldb/common/ldb_dn.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 18b620b506..8b9cf4e129 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -41,6 +41,21 @@ #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed +static int ldb_dn_is_valid_attribute_name(const char *name) +{ + while (*name) { + if (! isascii(*name)) { + return 0; + } + if (! (isalnum(*name) || *name == '-')) { + return 0; + } + name++; + } + + return 1; +} + static char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value) { const char *p, *s, *src; @@ -250,6 +265,10 @@ static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw if (!dc.name) return dc; + if (! ldb_dn_is_valid_attribute_name(dc.name)) { + goto failed; + } + ret = get_quotes_position(p, &qs, &qe); switch (ret) { -- cgit From 3fe6ca1c189f43e8e9f7059943ab7e2939c7582e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 2 Jul 2005 18:43:22 +0000 Subject: r8084: do not leak memory on errors (This used to be commit 2e328e6c2fc2c66b0d0de910cd43ab232049bc90) --- source4/lib/ldb/common/ldb_dn.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 8b9cf4e129..7556a144e2 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -37,7 +37,7 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" - +#include #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index eb72e665f5..df94b0691d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -56,6 +56,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) TDB_DATA key; char *key_str = NULL; char *dn_folded = NULL; + struct ldb_dn *edn = NULL; + struct ldb_dn *cedn = NULL; /* most DNs are case insensitive. The exception is index DNs for @@ -71,8 +73,6 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) if (*dn == '@') { dn_folded = talloc_strdup(ldb, dn); } else { - struct ldb_dn *edn, *cedn; - edn = ldb_dn_explode(ldb, dn); if (!edn) goto failed; @@ -89,10 +89,6 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) talloc_free(cedn); } - if (!dn_folded) { - goto failed; - } - key_str = talloc_asprintf(ldb, "DN=%s", dn_folded); talloc_free(dn_folded); @@ -101,11 +97,13 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) } key.dptr = key_str; - key.dsize = strlen(key_str)+1; + key.dsize = strlen(key_str) + 1; return key; failed: + talloc_free(edn); + talloc_free(cedn); errno = ENOMEM; key.dptr = NULL; key.dsize = 0; -- cgit From b9e8935188c75a007683979b208757e6c5c7aa67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 4 Jul 2005 07:10:21 +0000 Subject: r8126: - moved to 16 byte alignment for talloc. This is in response to a bug report from robert collins. - updated talloc guide to reflect the fact that over the last few months talloc overhead compared to malloc has dropped, probably due to a bunch of small changes. It now costs about 4% more than malloc on my box (This used to be commit 689a9ccf91f9de560a500787d85321abe096b948) --- source4/lib/talloc/talloc.c | 103 +++++++++++++++++++----------------- source4/lib/talloc/talloc_guide.txt | 2 +- 2 files changed, 54 insertions(+), 51 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 3a068f4eaa..1081302d09 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -97,23 +97,26 @@ struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; - size_t size; talloc_destructor_t destructor; const char *name; - union { - unsigned flags; - double align_dummy; - } u; + size_t size; + unsigned flags; }; +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if ((tc->u.flags & ~0xF) != TALLOC_MAGIC) { + const char *pp = ptr; + pp -= TC_HDR_SIZE; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp); + if ((tc->flags & ~0xF) != TALLOC_MAGIC) { TALLOC_ABORT("Bad talloc magic value - unknown value"); } - if (tc->u.flags & TALLOC_FLAG_FREE) { + if (tc->flags & TALLOC_FLAG_FREE) { TALLOC_ABORT("Bad talloc magic value - double free"); } return tc; @@ -160,7 +163,7 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr) void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } /* @@ -178,11 +181,11 @@ void *_talloc(const void *context, size_t size) return NULL; } - tc = malloc(sizeof(*tc)+size); + tc = malloc(TC_HDR_SIZE+size); if (tc == NULL) return NULL; tc->size = size; - tc->u.flags = TALLOC_MAGIC; + tc->flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -202,7 +205,7 @@ void *_talloc(const void *context, size_t size) tc->next = tc->prev = tc->parent = NULL; } - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } @@ -287,7 +290,7 @@ static int talloc_unreference(const void *context, const void *ptr) for (h=tc->refs;h;h=h->next) { struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; + if ((p==NULL && context==NULL) || TC_PTR_FROM_CHUNK(p) == context) break; } if (h == NULL) { return -1; @@ -338,7 +341,7 @@ int talloc_unlink(const void *context, void *ptr) new_p = talloc_parent_chunk(tc_p->refs); if (new_p) { - new_parent = new_p+1; + new_parent = TC_PTR_FROM_CHUNK(new_p); } else { new_parent = NULL; } @@ -497,16 +500,16 @@ void talloc_free_children(void *ptr) choice is owner of any remaining reference to this pointer, the second choice is our parent, and the final choice is the null context. */ - void *child = tc->child+1; + void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; if (tc->child->refs) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (talloc_free(child) == -1) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } talloc_steal(new_parent, child); } @@ -536,7 +539,7 @@ int talloc_free(void *ptr) return -1; } - if (tc->u.flags & TALLOC_FLAG_LOOP) { + if (tc->flags & TALLOC_FLAG_LOOP) { /* we have a free loop - stop looping */ return 0; } @@ -554,7 +557,7 @@ int talloc_free(void *ptr) tc->destructor = NULL; } - tc->u.flags |= TALLOC_FLAG_LOOP; + tc->flags |= TALLOC_FLAG_LOOP; talloc_free_children(ptr); @@ -568,7 +571,7 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->u.flags |= TALLOC_FLAG_FREE; + tc->flags |= TALLOC_FLAG_FREE; free(tc); return 0; @@ -608,24 +611,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } /* by resetting magic we catch users of the old memory */ - tc->u.flags |= TALLOC_FLAG_FREE; + tc->flags |= TALLOC_FLAG_FREE; #if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); + new_ptr = malloc(size + TC_HDR_SIZE); if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); free(tc); } #else - new_ptr = realloc(tc, size + sizeof(*tc)); + new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif if (!new_ptr) { - tc->u.flags &= ~TALLOC_FLAG_FREE; + tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = new_ptr; - tc->u.flags &= ~TALLOC_FLAG_FREE; + tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { tc->parent->child = new_ptr; } @@ -641,9 +644,9 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } tc->size = size; - talloc_set_name_const(tc+1, name); + talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } /* @@ -720,18 +723,18 @@ off_t talloc_total_size(const void *ptr) tc = talloc_chunk_from_ptr(ptr); - if (tc->u.flags & TALLOC_FLAG_LOOP) { + if (tc->flags & TALLOC_FLAG_LOOP) { return 0; } - tc->u.flags |= TALLOC_FLAG_LOOP; + tc->flags |= TALLOC_FLAG_LOOP; total = tc->size; for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); } - tc->u.flags &= ~TALLOC_FLAG_LOOP; + tc->flags &= ~TALLOC_FLAG_LOOP; return total; } @@ -744,18 +747,18 @@ off_t talloc_total_blocks(const void *ptr) off_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - if (tc->u.flags & TALLOC_FLAG_LOOP) { + if (tc->flags & TALLOC_FLAG_LOOP) { return 0; } - tc->u.flags |= TALLOC_FLAG_LOOP; + tc->flags |= TALLOC_FLAG_LOOP; total++; for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); } - tc->u.flags &= ~TALLOC_FLAG_LOOP; + tc->flags &= ~TALLOC_FLAG_LOOP; return total; } @@ -782,29 +785,29 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth) { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - if (tc->u.flags & TALLOC_FLAG_LOOP) { + if (tc->flags & TALLOC_FLAG_LOOP) { return; } - tc->u.flags |= TALLOC_FLAG_LOOP; + tc->flags |= TALLOC_FLAG_LOOP; for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { - const char *name = talloc_get_name(c+1); + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", depth*4, "", name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); } } - tc->u.flags &= ~TALLOC_FLAG_LOOP; + tc->flags &= ~TALLOC_FLAG_LOOP; } /* @@ -847,9 +850,9 @@ void talloc_report(const void *ptr, FILE *f) for (c=tc->child;c;c=c->next) { fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); + talloc_get_name(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); } fflush(f); } @@ -1175,7 +1178,7 @@ void *talloc_find_parent_byname(const void *context, const char *name) tc = talloc_chunk_from_ptr(context); while (tc) { if (tc->name && strcmp(tc->name, name) == 0) { - return (void*)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } while (tc && tc->prev) tc = tc->prev; tc = tc->parent; @@ -1198,7 +1201,7 @@ void talloc_show_parents(const void *context, FILE *file) tc = talloc_chunk_from_ptr(context); fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); while (tc) { - fprintf(file, "\t'%s'\n", talloc_get_name(tc+1)); + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); while (tc && tc->prev) tc = tc->prev; tc = tc->parent; } diff --git a/source4/lib/talloc/talloc_guide.txt b/source4/lib/talloc/talloc_guide.txt index 7477dad266..13ceae9d82 100644 --- a/source4/lib/talloc/talloc_guide.txt +++ b/source4/lib/talloc/talloc_guide.txt @@ -43,7 +43,7 @@ Performance All the additional features of talloc() over malloc() do come at a price. We have a simple performance test in Samba4 that measures talloc() versus malloc() performance, and it seems that talloc() is -about 10% slower than malloc() on my x86 Debian Linux box. For Samba, +about 4% slower than malloc() on my x86 Debian Linux box. For Samba, the great reduction in code complexity that we get by using talloc makes this worthwhile, especially as the total overhead of talloc/malloc in Samba is already quite small. -- cgit From ab65303fe8e7123b1567e9159adbfd6bd4697e78 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 4 Jul 2005 07:26:27 +0000 Subject: r8127: fixed code in function error (This used to be commit 46632e2048f0b87de351cd3f26229cfc4b3384ca) --- source4/lib/talloc/talloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 1081302d09..6af08a2ac9 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -111,8 +111,7 @@ struct talloc_chunk { static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { const char *pp = ptr; - pp -= TC_HDR_SIZE; - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp); + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); if ((tc->flags & ~0xF) != TALLOC_MAGIC) { TALLOC_ABORT("Bad talloc magic value - unknown value"); } -- cgit From 8f9e87d858ae1cf2209cfd8332ad54a750252e24 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 4 Jul 2005 15:06:05 +0000 Subject: r8146: fix compiler warning metze (This used to be commit 5fcaa21d67e399aab4af15f4f6f919203c1152e5) --- source4/lib/ldb/common/ldb_dn.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 7556a144e2..1eaf4c486b 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -361,22 +361,20 @@ failed: char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) { char *dn, *value; - const char *format = "%s=%s"; int i; dn = talloc_strdup(mem_ctx, ""); LDB_DN_NULL_FAILED(dn); for (i = 0; i < edn->comp_num; i++) { - - if (i != 0) { - format = ",%s=%s"; - } - value = ldb_dn_escape_value(dn, edn->components[i].value); LDB_DN_NULL_FAILED(value); - dn = talloc_asprintf_append(dn, format, edn->components[i].name, value); + if (i == 0) { + dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value); + } else { + dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value); + } LDB_DN_NULL_FAILED(dn); talloc_free(value); -- cgit From 372f3fae88799ce321342dd976a317a8afc375e2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 6 Jul 2005 01:53:34 +0000 Subject: r8171: According to Samba 3 and Ethereal, the winreg_OpenUnkown stuff is actually a uint16 * without the [string] attribute, a la the the system_name argument to samr_Connect(). Initialising the pointer to NULL is sufficient and we still pass the RPC-WINREG test against win2k3. (This used to be commit 407d962dacf7c833b36cb739e48fe97226968a34) --- source4/lib/registry/reg_backend_rpc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 3c38b5d312..73d2d54687 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -43,12 +43,9 @@ static void init_winreg_String(struct winreg_String *name, const char *s) #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ { \ struct winreg_Open ## u r; \ - struct winreg_OpenUnknown unknown; \ NTSTATUS status; \ \ - unknown.unknown0 = 0x84e0; \ - unknown.unknown1 = 0x0000; \ - r.in.unknown = &unknown; \ + r.in.system_name = 0; \ r.in.access_required = SEC_FLAG_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ \ -- cgit From 5a176571d8aad1c0923e18f8c77ed00261b8d53a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Jul 2005 05:14:46 +0000 Subject: r8224: - add objectGUID ldif_handler - fix some compiler warnings metze (This used to be commit e6c39241bf93336d4c94c43f9d8beb69018fb74a) --- source4/lib/ldb/samba/ldif_handlers.c | 154 ++++++++++++++++++++++++++++++---- 1 file changed, 140 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index a6095cddbc..cd97fb08b0 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -35,7 +35,7 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx, { struct dom_sid *sid; NTSTATUS status; - sid = dom_sid_parse_talloc(mem_ctx, in->data); + sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data); if (sid == NULL) { return -1; } @@ -75,25 +75,34 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, return 0; } +static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v) +{ + /* see if the input if null-terninated */ + if (v->data[v->length] != '\0') return False; + + if (strncmp("S-", v->data, 2) != 0) return False; + return True; +} + /* compare two objectSids */ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { - if (strncmp(v1->data, "S-", 2) == 0 && - strncmp(v2->data, "S-", 2) == 0) { - return strcmp(v1->data, v2->data); - } - if (strncmp(v1->data, "S-", 2) == 0) { - struct ldb_val v; - int ret; - if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) { - return -1; + if (ldb_comparision_objectSid_isString(v1)) { + if (ldb_comparision_objectSid_isString(v1)) { + return strcmp(v1->data, v2->data); + } else { + struct ldb_val v; + int ret; + if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) { + return -1; + } + ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2); + talloc_free(v.data); + return ret; } - ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2); - talloc_free(v.data); - return ret; } return ldb_comparison_binary(ldb, mem_ctx, v1, v2); } @@ -104,12 +113,105 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - if (strncmp(in->data, "S-", 2) == 0) { + if (ldb_comparision_objectSid_isString(in)) { return ldif_read_objectSid(ldb, mem_ctx, in, out); } return ldb_handler_copy(ldb, mem_ctx, in, out); } +/* + convert a ldif formatted objectGUID to a NDR formatted blob +*/ +static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct GUID guid; + NTSTATUS status; + + status = GUID_from_string(in->data, &guid); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + + status = ndr_push_struct_blob(out, mem_ctx, &guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + return 0; +} + +/* + convert a NDR formatted blob to a ldif formatted objectGUID +*/ +static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct GUID guid; + NTSTATUS status; + status = ndr_pull_struct_blob(in, mem_ctx, &guid, + (ndr_pull_flags_fn_t)ndr_pull_GUID); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + out->data = GUID_string(mem_ctx, &guid); + if (out->data == NULL) { + return -1; + } + out->length = strlen(out->data); + return 0; +} + +static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v) +{ + struct GUID guid; + NTSTATUS status; + + /* see if the input if null-terninated */ + if (v->data[v->length] != '\0') return False; + + status = GUID_from_string(v->data, &guid); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + return True; +} + +/* + compare two objectGUIDs +*/ +static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, const struct ldb_val *v2) +{ + if (ldb_comparision_objectGUID_isString(v1)) { + if (ldb_comparision_objectGUID_isString(v2)) { + return strcmp(v1->data, v2->data); + } else { + struct ldb_val v; + int ret; + if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) { + return -1; + } + ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2); + talloc_free(v.data); + return ret; + } + } + return ldb_comparison_binary(ldb, mem_ctx, v1, v2); +} + +/* + canonicalise a objectGUID +*/ +static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + if (ldb_comparision_objectGUID_isString(in)) { + return ldif_read_objectGUID(ldb, mem_ctx, in, out); + } + return ldb_handler_copy(ldb, mem_ctx, in, out); +} static const struct ldb_attrib_handler samba_handlers[] = { { @@ -119,6 +221,30 @@ static const struct ldb_attrib_handler samba_handlers[] = { .ldif_write_fn = ldif_write_objectSid, .canonicalise_fn = ldb_canonicalise_objectSid, .comparison_fn = ldb_comparison_objectSid + }, + { + .attr = "securityIdentifier", + .flags = 0, + .ldif_read_fn = ldif_read_objectSid, + .ldif_write_fn = ldif_write_objectSid, + .canonicalise_fn = ldb_canonicalise_objectSid, + .comparison_fn = ldb_comparison_objectSid + }, + { + .attr = "objectGUID", + .flags = 0, + .ldif_read_fn = ldif_read_objectGUID, + .ldif_write_fn = ldif_write_objectGUID, + .canonicalise_fn = ldb_canonicalise_objectGUID, + .comparison_fn = ldb_comparison_objectGUID + }, + { + .attr = "invocationId", + .flags = 0, + .ldif_read_fn = ldif_read_objectGUID, + .ldif_write_fn = ldif_write_objectGUID, + .canonicalise_fn = ldb_canonicalise_objectGUID, + .comparison_fn = ldb_comparison_objectGUID } }; -- cgit From d9129a77bd333176cd333fe36b92978061ff1773 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Jul 2005 05:27:47 +0000 Subject: r8228: fix compiler warnings metze (This used to be commit 93c1d18021cbf08be1782b129c40d8769b1b559c) --- source4/lib/ldb/samba/ldif_handlers.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index cd97fb08b0..6cd4b7e849 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -66,12 +66,12 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, talloc_free(sid); return -1; } - out->data = dom_sid_string(mem_ctx, sid); + out->data = (uint8_t *)dom_sid_string(mem_ctx, sid); talloc_free(sid); if (out->data == NULL) { return -1; } - out->length = strlen(out->data); + out->length = strlen((const char *)out->data); return 0; } @@ -80,7 +80,7 @@ static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v) /* see if the input if null-terninated */ if (v->data[v->length] != '\0') return False; - if (strncmp("S-", v->data, 2) != 0) return False; + if (strncmp("S-", (const char *)v->data, 2) != 0) return False; return True; } @@ -92,7 +92,7 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx, { if (ldb_comparision_objectSid_isString(v1)) { if (ldb_comparision_objectSid_isString(v1)) { - return strcmp(v1->data, v2->data); + return strcmp((const char *)v1->data, (const char *)v2->data); } else { struct ldb_val v; int ret; @@ -128,7 +128,7 @@ static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx, struct GUID guid; NTSTATUS status; - status = GUID_from_string(in->data, &guid); + status = GUID_from_string((const char *)in->data, &guid); if (!NT_STATUS_IS_OK(status)) { return -1; } @@ -154,11 +154,11 @@ static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx, if (!NT_STATUS_IS_OK(status)) { return -1; } - out->data = GUID_string(mem_ctx, &guid); + out->data = (uint8_t *)GUID_string(mem_ctx, &guid); if (out->data == NULL) { return -1; } - out->length = strlen(out->data); + out->length = strlen((const char *)out->data); return 0; } @@ -170,7 +170,7 @@ static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v) /* see if the input if null-terninated */ if (v->data[v->length] != '\0') return False; - status = GUID_from_string(v->data, &guid); + status = GUID_from_string((const char *)v->data, &guid); if (!NT_STATUS_IS_OK(status)) { return False; } @@ -186,7 +186,7 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx, { if (ldb_comparision_objectGUID_isString(v1)) { if (ldb_comparision_objectGUID_isString(v2)) { - return strcmp(v1->data, v2->data); + return strcmp((const char *)v1->data, (const char *)v2->data); } else { struct ldb_val v; int ret; -- cgit From aa37e5483b5f86d8b8c6a803acf5bb68f37ae022 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 8 Jul 2005 10:39:16 +0000 Subject: r8240: support comparing pointers in ejs. This allows for if (io.output.samr == NULL) { print("no result\n"); } (This used to be commit 89db5c68a5ee6875ccddcfe70a6e1232b40039b3) --- source4/lib/ejs/ejsParser.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 8d0aa7ba2c..57cb569cdb 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -1659,10 +1659,13 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) case MPR_TYPE_CFUNCTION: case MPR_TYPE_FUNCTION: case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); return 0; + case MPR_TYPE_PTR: + mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0); + return 0; + case MPR_TYPE_BOOL: rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); break; -- cgit From 3191ed9ae97f7cb6da9dd1034ec416e6e892150a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 9 Jul 2005 01:53:01 +0000 Subject: r8245: Add const. Andrew Bartlett (This used to be commit 8c079ce1631433f6bf1da8f378ea5f1a271a02ae) --- source4/lib/samba3/smbpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index 587d038a3d..bcbb5e56d8 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -58,12 +58,12 @@ /*! Convert 32 hex characters into a 16 byte array. */ -struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, char *p) +struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, const char *p) { int i; unsigned char lonybble, hinybble; const char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; + const char *p1, *p2; struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password); if (!p) return NULL; -- cgit From 514731b0ee7d8f9c79cbc88672a7957b7ba1eacd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 9 Jul 2005 05:23:47 +0000 Subject: r8253: fixed two crash bugs in ejs. I will send these fixes off to the appweb guys soon. (This used to be commit 3fe83b48c3fe4cdc1e7ec0271e08f7bd77e90de9) --- source4/lib/ejs/ejsParser.c | 2 ++ source4/lib/ejs/var.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 57cb569cdb..72b0889c55 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -1555,6 +1555,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) if (lhs->type == MPR_TYPE_STRING) { if (isdigit((int) lhs->string[0])) { num = mprVarToNumber(lhs); + lhs->allocatedVar = 0; mprDestroyVar(lhs); *lhs = mprCreateNumberVar(num); /* Examine further below */ @@ -1564,6 +1565,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) * Convert the RHS to a string */ mprVarToString(&str, MPR_MAX_STRING, 0, rhs); + rhs->allocatedVar = 0; mprDestroyVar(rhs); *rhs = mprCreateStringVar(str, 1); mprFree(str); diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 6ef1c4d3a3..63c0b7b98d 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -602,7 +602,8 @@ MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) for (prop = getObjChain(obj->properties, property); prop; prop = prop->forw) { - if (prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { + if (prop->name && + prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { break; } } -- cgit From c6881d1e650fd284a366af76f5a214a5de05cc0c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 01:08:10 +0000 Subject: r8272: added the hooks for adding a name to a messaging context, so we will be able to send a message to the "ldap_server" task without having to know its task ID. (This used to be commit 8f69867867857e0c9a9246c2dec9612ccc234724) --- source4/lib/messaging/irpc.h | 1 + source4/lib/messaging/messaging.c | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index cba17a2c97..0482e9a957 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -86,6 +86,7 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void NTSTATUS irpc_register(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, int call, irpc_function_t fn, void *private); +NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 7cf488c7d0..9bf5071e90 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -690,3 +690,13 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, table, callnum, r); return irpc_call_recv(irpc); } + +/* + add a string name that this irpc server can be called on +*/ +NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name) +{ + return NT_STATUS_OK; +} + + -- cgit From 76ecf81428c161a98a5621b55a64cb8515f80585 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 01:10:09 +0000 Subject: r8273: fixed some memory leaks in smbscript. This required converting file_load() to use talloc, which impacted quite a few bits of code, including our smb.conf processing. took the opportunity to remove the gloabls in params.c while doing this (This used to be commit b220756cb4f1d201ba3e771ca67e4bfae5eae748) --- source4/lib/util_file.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index e02198754d..a7d29d1a1d 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -190,18 +190,18 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f) load a file into memory from a fd. ****************************************************************************/ -char *fd_load(int fd, size_t *size) +char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx) { struct stat sbuf; char *p; if (fstat(fd, &sbuf) != 0) return NULL; - p = (char *)malloc(sbuf.st_size+1); + p = (char *)talloc_size(mem_ctx, sbuf.st_size+1); if (!p) return NULL; if (read(fd, p, sbuf.st_size) != sbuf.st_size) { - SAFE_FREE(p); + talloc_free(p); return NULL; } p[sbuf.st_size] = 0; @@ -214,7 +214,7 @@ char *fd_load(int fd, size_t *size) /**************************************************************************** load a file into memory ****************************************************************************/ -char *file_load(const char *fname, size_t *size) +char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx) { int fd; char *p; @@ -224,7 +224,7 @@ char *file_load(const char *fname, size_t *size) fd = open(fname,O_RDONLY); if (fd == -1) return NULL; - p = fd_load(fd, size); + p = fd_load(fd, size, mem_ctx); close(fd); @@ -254,12 +254,12 @@ void *map_file(char *fname, size_t size) } #endif if (!p) { - p = file_load(fname, &s2); + p = file_load(fname, &s2, talloc_autofree_context()); if (!p) return NULL; if (s2 != size) { DEBUG(1,("incorrect size for %s - got %d expected %d\n", fname, s2, size)); - if (p) free(p); + talloc_free(p); return NULL; } } @@ -308,12 +308,12 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) load a file into memory and return an array of pointers to lines in the file must be freed with file_lines_free(). ****************************************************************************/ -char **file_lines_load(const char *fname, int *numlines) +char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx) { char *p; size_t size; - p = file_load(fname, &size); + p = file_load(fname, &size, mem_ctx); if (!p) return NULL; return file_lines_parse(p, size, numlines); @@ -324,29 +324,18 @@ load a fd into memory and return an array of pointers to lines in the file must be freed with file_lines_free(). If convert is true calls unix_to_dos on the list. ****************************************************************************/ -char **fd_lines_load(int fd, int *numlines) +char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) { char *p; size_t size; - p = fd_load(fd, &size); + p = fd_load(fd, &size, mem_ctx); if (!p) return NULL; return file_lines_parse(p, size, numlines); } -/**************************************************************************** -free lines loaded with file_lines_load -****************************************************************************/ -void file_lines_free(char **lines) -{ - if (!lines) return; - SAFE_FREE(lines[0]); - SAFE_FREE(lines); -} - - /**************************************************************************** take a lislist of lines and modify them to produce a list where \ continues a line -- cgit From 144b88b3a0ac91ef8263cdb8cc044d04c2d65f62 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 04:54:21 +0000 Subject: r8277: filled in the code for finding irpc server ids by name, storing the names in a tdb (This used to be commit b603a52f27bf90e71d605440d44267dcd94c6939) --- source4/lib/messaging/irpc.h | 5 +- source4/lib/messaging/messaging.c | 123 +++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 0482e9a957..4fb1acfedb 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -86,7 +86,6 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void NTSTATUS irpc_register(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, int call, irpc_function_t fn, void *private); -NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, @@ -97,3 +96,7 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, const struct dcerpc_interface_table *table, int callnum, void *r); +NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); +uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *name); +void irpc_remove_name(struct messaging_context *msg_ctx, const char *name); + diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 9bf5071e90..8345c79c77 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -30,6 +30,9 @@ #include "lib/socket/socket.h" #include "librpc/gen_ndr/ndr_irpc.h" #include "lib/messaging/irpc.h" +#include "db_wrap.h" +#include "lib/tdb/include/tdb.h" +#include "lib/tdb/include/tdbutil.h" /* change the message version with any incompatible changes in the protocol */ #define MESSAGING_VERSION 1 @@ -43,6 +46,7 @@ struct messaging_context { struct messaging_rec *pending; struct irpc_list *irpc; struct idr_context *idr; + const char **names; struct { struct event_context *ev; @@ -350,6 +354,9 @@ static int messaging_destructor(void *ptr) { struct messaging_context *msg = ptr; unlink(msg->path); + while (msg->names && msg->names[0]) { + irpc_remove_name(msg, msg->names[0]); + } return 0; } @@ -380,6 +387,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id msg->pending = NULL; msg->idr = idr_init(msg); msg->irpc = NULL; + msg->names = NULL; status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0); if (!NT_STATUS_IS_OK(status)) { @@ -691,12 +699,125 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, return irpc_call_recv(irpc); } +/* + open the naming database +*/ +static struct tdb_wrap *irpc_namedb_open(struct messaging_context *msg_ctx) +{ + struct tdb_wrap *t; + char *path = talloc_asprintf(msg_ctx, "%s/names.tdb", msg_ctx->base_path); + if (path == NULL) { + return NULL; + } + t = tdb_wrap_open(msg_ctx, path, 0, 0, O_RDWR|O_CREAT, 0660); + talloc_free(path); + return t; +} + + /* add a string name that this irpc server can be called on */ NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name) { - return NT_STATUS_OK; + struct tdb_wrap *t; + TDB_DATA rec; + int count; + NTSTATUS status = NT_STATUS_OK; + + t = irpc_namedb_open(msg_ctx); + NT_STATUS_HAVE_NO_MEMORY(t); + + rec = tdb_fetch_bystring(t->tdb, name); + count = rec.dsize / sizeof(uint32_t); + rec.dptr = (char *)realloc_p(rec.dptr, uint32_t, count+1); + rec.dsize += sizeof(uint32_t); + if (rec.dptr == NULL) { + talloc_free(t); + return NT_STATUS_NO_MEMORY; + } + ((uint32_t *)rec.dptr)[count] = msg_ctx->server_id; + if (tdb_store_bystring(t->tdb, name, rec, 0) != 0) { + status = NT_STATUS_INTERNAL_ERROR; + } + free(rec.dptr); + talloc_free(t); + + msg_ctx->names = str_list_add(msg_ctx->names, name); + talloc_steal(msg_ctx, msg_ctx->names); + + return status; } +/* + return a list of server ids for a server name +*/ +uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *name) +{ + struct tdb_wrap *t; + TDB_DATA rec; + int count, i; + uint32_t *ret; + + t = irpc_namedb_open(msg_ctx); + if (t == NULL) { + return NULL; + } + rec = tdb_fetch_bystring(t->tdb, name); + if (rec.dptr == NULL) { + talloc_free(t); + return NULL; + } + count = rec.dsize / sizeof(uint32_t); + ret = talloc_array(msg_ctx, uint32_t, count); + if (ret == NULL) { + talloc_free(t); + return NULL; + } + for (i=0;inames, name); + + t = irpc_namedb_open(msg_ctx); + if (t == NULL) { + return; + } + + rec = tdb_fetch_bystring(t->tdb, name); + count = rec.dsize / sizeof(uint32_t); + if (count == 0) { + talloc_free(t); + return; + } + ids = (uint32_t *)rec.dptr; + for (i=0;iserver_id) { + if (i < count-1) { + memmove(ids+i, ids+i+1, count-(i+1)); + } + rec.dsize -= sizeof(uint32_t); + break; + } + } + tdb_store_bystring(t->tdb, name, rec, 0); + free(rec.dptr); + talloc_free(t); +} -- cgit From d084d6d24109ae615af89776519e7ebd722e9a4c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 06:17:39 +0000 Subject: r8279: make sure we hold a lock when manipulating the irpc names db (This used to be commit 9c408d5d7cb82e910ffb5963ddc78e5759513385) --- source4/lib/messaging/messaging.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 8345c79c77..5afcf91bab 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -728,11 +728,16 @@ NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name) t = irpc_namedb_open(msg_ctx); NT_STATUS_HAVE_NO_MEMORY(t); + if (tdb_lock_bystring(t->tdb, name) != 0) { + talloc_free(t); + return NT_STATUS_LOCK_NOT_GRANTED; + } rec = tdb_fetch_bystring(t->tdb, name); count = rec.dsize / sizeof(uint32_t); rec.dptr = (char *)realloc_p(rec.dptr, uint32_t, count+1); rec.dsize += sizeof(uint32_t); if (rec.dptr == NULL) { + tdb_unlock_bystring(t->tdb, name); talloc_free(t); return NT_STATUS_NO_MEMORY; } @@ -741,6 +746,7 @@ NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name) status = NT_STATUS_INTERNAL_ERROR; } free(rec.dptr); + tdb_unlock_bystring(t->tdb, name); talloc_free(t); msg_ctx->names = str_list_add(msg_ctx->names, name); @@ -764,21 +770,29 @@ uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *nam return NULL; } + if (tdb_lock_bystring(t->tdb, name) != 0) { + talloc_free(t); + return NULL; + } rec = tdb_fetch_bystring(t->tdb, name); if (rec.dptr == NULL) { + tdb_unlock_bystring(t->tdb, name); talloc_free(t); return NULL; } count = rec.dsize / sizeof(uint32_t); - ret = talloc_array(msg_ctx, uint32_t, count); + ret = talloc_array(msg_ctx, uint32_t, count+1); if (ret == NULL) { + tdb_unlock_bystring(t->tdb, name); talloc_free(t); return NULL; } for (i=0;itdb, name); talloc_free(t); return ret; @@ -801,9 +815,14 @@ void irpc_remove_name(struct messaging_context *msg_ctx, const char *name) return; } + if (tdb_lock_bystring(t->tdb, name) != 0) { + talloc_free(t); + return; + } rec = tdb_fetch_bystring(t->tdb, name); count = rec.dsize / sizeof(uint32_t); if (count == 0) { + tdb_unlock_bystring(t->tdb, name); talloc_free(t); return; } @@ -819,5 +838,6 @@ void irpc_remove_name(struct messaging_context *msg_ctx, const char *name) } tdb_store_bystring(t->tdb, name, rec, 0); free(rec.dptr); + tdb_unlock_bystring(t->tdb, name); talloc_free(t); } -- cgit From 056096c30ba73cbc5304c99af5d5a08d89111aab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 08:35:18 +0000 Subject: r8284: - fixed some uninitialised variables in the irpc code - added code to send multiple irpc calls in parallel, to all servers that have registered the given name, with output going in io.results[i]. This allows you to make rpc calls to multiple servers at once, which is needed for clients like smbstatus (This used to be commit 061e20e509d95ffe16d7dd6fba7db39fc7a165ed) --- source4/lib/messaging/messaging.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 5afcf91bab..a29f14f065 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -375,6 +375,10 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id return NULL; } + if (ev == NULL) { + ev = event_context_init(msg); + } + /* create the messaging directory if needed */ path = smbd_tmp_path(msg, "messaging"); mkdir(path, 0700); @@ -483,6 +487,7 @@ static void irpc_handler_reply(struct messaging_context *msg_ctx, irpc->status = header->status; } irpc->done = True; + talloc_steal(irpc, ndr); if (irpc->async.fn) { irpc->async.fn(irpc); } @@ -572,7 +577,9 @@ static void irpc_handler(struct messaging_context *msg_ctx, void *private, irpc_handler_reply(msg_ctx, ndr, &header); } else { irpc_handler_request(msg_ctx, ndr, &header, src); + talloc_free(ndr); } + return; failed: talloc_free(ndr); @@ -674,16 +681,13 @@ failed: */ NTSTATUS irpc_call_recv(struct irpc_request *irpc) { - NTSTATUS status; NT_STATUS_HAVE_NO_MEMORY(irpc); while (!irpc->done) { if (event_loop_once(irpc->msg_ctx->event.ev) != 0) { return NT_STATUS_CONNECTION_DISCONNECTED; } } - status = irpc->status; - talloc_free(irpc); - return status; + return irpc->status; } /* -- cgit From 747cae71519c7883ac4b1d6046f933659b765c95 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 10 Jul 2005 21:41:49 +0000 Subject: r8294: Add PLAN file for samba3->samba4 upgrade (Google Summer of Code) project. (This used to be commit 7ebf81adce49d495c4fe8efdbb2e480db541fe35) --- source4/lib/samba3/PLAN | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 source4/lib/samba3/PLAN (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN new file mode 100644 index 0000000000..a75c60018c --- /dev/null +++ b/source4/lib/samba3/PLAN @@ -0,0 +1,9 @@ +- Each of the various password database backends(tdb,ldap,smbpaswd) available in Samba3 need to be accessible and converted to the SAM database in Samba4. +- Printer database needs to be read from the Samba3 TDB and added to the apprioprate LDAP subtree. +- The WINS database needs to be converted from both plain text file and TDB file to LDAP/LDB. +- The account policy database needs to be read in from a TDB and applied to the data in LDAP/LDB. +- The privilege database needs to be read from a TDB and added to the SAM database in LDB. +- Group mappings need to be read from the TDB and added to the SAM database. +- The share info database and the configuration file from Samba3 need to be read and converted to either xattrs or a TDB in Samba4 +- Secrets.tdb, containing the domain formation, needs to be merged into the SAM database. +- Last, but not least, a Samba3 configuration file should be parsable in Samba4. This file can be used for producing a Samba4 smb.conf file as well as for updating the various databases mentioned above. -- cgit From 54ffd4fdbf470cb71cbf9a9c9e5aa37f73acc559 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Jul 2005 04:17:54 +0000 Subject: r8313: moved PRINTF_ATTRIBUTE to replace.h to try to get irix building with heimdal (This used to be commit 7d4e309f02cfcef661ebf3bbe9c227938318077c) --- source4/lib/replace/replace.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index e0cb1420ec..c7c343ef38 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -111,4 +111,16 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); typedef int (*comparison_fn_t)(const void *, const void *); #endif +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + #endif -- cgit From 3e0aa2e756ec5fb3f03c9029ee442ed0aede5c53 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Jul 2005 15:42:27 +0000 Subject: r8321: Fix some uninitalized variable warnings (This used to be commit 126cb3db4b0cf9c382ba7496ba08311f3b669f00) --- source4/lib/ejs/var.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 63c0b7b98d..70a277ae73 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -1706,7 +1706,7 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) MprVar mprParseVar(char *buf, MprType preferredType) { - MprType type; + MprType type = MPR_TYPE_UNDEFINED; char *cp; mprAssert(buf); -- cgit From ba1ee57df43fe93c8b650478324ddd6cc1a3c7bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Jul 2005 22:40:32 +0000 Subject: r8333: merged with latest upstream ejs sources (This used to be commit b0f9ddafe95d4e8d846bc72a39e94d22da271348) --- source4/lib/ejs/config.mk | 2 +- source4/lib/ejs/ejs.c | 1060 ---------------------------------------- source4/lib/ejs/ejs.h | 16 +- source4/lib/ejs/ejsInternal.h | 5 +- source4/lib/ejs/ejsLex.c | 5 +- source4/lib/ejs/ejsLib.c | 1061 +++++++++++++++++++++++++++++++++++++++++ source4/lib/ejs/ejsParser.c | 16 +- source4/lib/ejs/ejsProcs.c | 2 +- source4/lib/ejs/var.c | 50 +- source4/lib/ejs/var.h | 25 +- 10 files changed, 1134 insertions(+), 1108 deletions(-) delete mode 100644 source4/lib/ejs/ejs.c create mode 100644 source4/lib/ejs/ejsLib.c (limited to 'source4/lib') diff --git a/source4/lib/ejs/config.mk b/source4/lib/ejs/config.mk index 2d436cbe0b..f2c0e62f1e 100644 --- a/source4/lib/ejs/config.mk +++ b/source4/lib/ejs/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM EJS [SUBSYSTEM::EJS] ADD_OBJ_FILES = \ - lib/ejs/ejs.o \ + lib/ejs/ejsLib.o \ lib/ejs/ejsLex.o \ lib/ejs/ejsParser.o \ lib/ejs/ejsProcs.o \ diff --git a/source4/lib/ejs/ejs.c b/source4/lib/ejs/ejs.c deleted file mode 100644 index 41af795370..0000000000 --- a/source4/lib/ejs/ejs.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * @file ejs.c - * @brief Embedded JavaScript (EJS) - * @overview Main module interface logic. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "lib/ejs/ejsInternal.h" - -#if BLD_FEATURE_EJS - -/********************************** Local Data ********************************/ - -/* - * These fields must be locked before any access when multithreaded - */ -static MprVar master; /* Master object */ -static MprArray *ejsList; /* List of ej handles */ - -#if BLD_FEATURE_MULTITHREAD -static EjsLock lock; -static EjsUnlock unlock; -static void *lockData; -#define ejsLock() if (lock) { (lock)(lockData); } else -#define ejsUnlock() if (unlock) { (unlock)(lockData); } else -#else -#define ejsLock() -#define ejsUnlock() -#endif - -/****************************** Forward Declarations **************************/ - -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); - -/************************************* Code ***********************************/ -/* - * Initialize the EJ subsystem - */ - -int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) -{ - MprVar *np; - -#if BLD_FEATURE_MULTITHREAD - if (lockFn) { - lock = lockFn; - unlock = unlockFn; - lockData = data; - } -#endif - ejsLock(); - - /* - * Master is the top level object (above global). It is used to clone its - * contents into the global scope for each. This is never visible to the - * user, so don't use ejsCreateObj(). - */ - master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); - if (master.type == MPR_TYPE_UNDEFINED) { - ejsUnlock(); - return MPR_ERR_CANT_ALLOCATE; - } - - ejsList = mprCreateArray(); - ejsDefineStandardProperties(&master); - - /* - * Make these objects immutable - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprSetVarReadonly(np, 1); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - ejsUnlock(); - return 0; -} - -/******************************************************************************/ - -void ejsClose() -{ - ejsLock(); - mprDestroyArray(ejsList); - mprDestroyVar(&master); - ejsUnlock(); -} - -/******************************************************************************/ -/* - * Create and initialize an EJS engine - */ - -EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) -{ - MprVar *np; - Ejs *ep; - - ep = mprMalloc(sizeof(Ejs)); - if (ep == 0) { - return (EjsId) -1; - } - memset(ep, 0, sizeof(Ejs)); - - ejsLock(); - ep->eid = (EjsId) mprAddToArray(ejsList, ep); - ejsUnlock(); - - /* - * Create array of local variable frames - */ - ep->frames = mprCreateArray(); - if (ep->frames == 0) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - ep->primaryHandle = primaryHandle; - ep->altHandle = altHandle; - - /* - * Create first frame: global variables - */ - ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); - if (ep->global->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->global); - - /* - * Create first local variable frame - */ - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); - if (ep->local->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->local); - - /* - * Clone all master variables into the global frame. This does a - * reference copy. - * - * ejsDefineStandardProperties(ep->global); - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprCreateProperty(ep->global, np->name, np); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - - mprCreateProperty(ep->global, "global", ep->global); - mprCreateProperty(ep->global, "this", ep->global); - mprCreateProperty(ep->local, "local", ep->local); - - return ep->eid; -} - -/******************************************************************************/ -/* - * Close an EJS instance - */ - -void ejsCloseEngine(EjsId eid) -{ - Ejs *ep; - MprVar *vp; - void **handles; - int i; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - - mprFree(ep->error); - mprDestroyVar(&ep->result); - mprDestroyVar(&ep->tokenNumber); - - mprDeleteProperty(ep->local, "local"); - mprDeleteProperty(ep->global, "this"); - mprDeleteProperty(ep->global, "global"); - - handles = ep->frames->handles; - for (i = 0; i < ep->frames->max; i++) { - vp = handles[i]; - if (vp) { -#if BLD_DEBUG - if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { - mprLog(7, "ejsCloseEngine: %s has ref count %d\n", - vp->name, vp->properties->refCount); - } -#endif - mprDestroyVar(vp); - mprFree(vp); - mprRemoveFromArray(ep->frames, i); - } - } - mprDestroyArray(ep->frames); - - ejsLock(); - mprRemoveFromArray(ejsList, (int) ep->eid); - ejsUnlock(); - - mprFree(ep); -} - -/******************************************************************************/ -/* - * Evaluate an EJS script file - */ - -int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) -{ - struct stat sbuf; - Ejs *ep; - char *script; - int rc, fd; - - mprAssert(path && *path); - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - goto error; - } - - if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { - ejsError(ep, "Can't open %s\n", path); - goto error; - } - - if (stat(path, &sbuf) < 0) { - close(fd); - ejsError(ep, "Cant stat %s", path); - goto error; - } - - if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { - close(fd); - ejsError(ep, "Cant malloc %d", (int)sbuf.st_size); - goto error; - } - - if (read(fd, script, sbuf.st_size) != (int)sbuf.st_size) { - close(fd); - mprFree(script); - ejsError(ep, "Error reading %s", path); - goto error; - } - - script[sbuf.st_size] = '\0'; - close(fd); - - rc = ejsEvalBlock(eid, script, result, emsg); - mprFree(script); - - return rc; - -/* - * Error return - */ -error: - *emsg = mprStrdup(ep->error); - return -1; -} - -/******************************************************************************/ -/* - * Create a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsOpenBlock(EjsId eid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); - - mprCreateProperty(ep->local, "local", ep->local); - - return mprAddToArray(ep->frames, ep->local); -} - -/******************************************************************************/ -/* - * Close a variable scope block opened via ejsOpenBlock. Pop back the old - * local variables frame. - */ - -int ejsCloseBlock(EjsId eid, int fid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - /* - * Must remove self-references before destroying "local" - */ - mprDeleteProperty(ep->local, "local"); - - mprDestroyVar(ep->local); - mprFree(ep->local); - - mprRemoveFromArray(ep->frames, fid); - ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; - - return 0; -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All frames - * created during this context will be automatically deleted when complete. - * vp and emsg are optional. i.e. created local variables will be discarded - * when this routine returns. - */ - -int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - int rc, fid; - - mprAssert(script); - - fid = ejsOpenBlock(eid); - rc = ejsEvalScript(eid, script, vp, emsg); - ejsCloseBlock(eid, fid); - - return rc; -} - -/******************************************************************************/ -/* - * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" - * by EJ and the caller must not free it. Returns -1 on errors and zero - * for success. On errors, emsg will be set to the reason. The caller must - * free emsg. - */ - -int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - Ejs *ep; - EjsInput *oldBlock; - int state; - void *endlessLoopTest; - int loopCounter; - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - mprDestroyVar(&ep->result); - - if (script == 0) { - return 0; - } - - /* - * Allocate a new evaluation block, and save the old one - */ - oldBlock = ep->input; - ejsLexOpenScript(ep, script); - - /* - * Do the actual parsing and evaluation - */ - loopCounter = 0; - endlessLoopTest = NULL; - ep->exitStatus = 0; - - do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); - - if (state == EJS_STATE_RET) { - state = EJS_STATE_EOF; - } - /* - * Stuck parser and endless recursion protection. - */ - if (endlessLoopTest == ep->input->scriptServp) { - if (loopCounter++ > 10) { - state = EJS_STATE_ERR; - ejsError(ep, "Syntax error"); - } - } else { - endlessLoopTest = ep->input->scriptServp; - loopCounter = 0; - } - } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); - - ejsLexCloseScript(ep); - - /* - * Return any error string to the user - */ - if (state == EJS_STATE_ERR && emsg) { - *emsg = mprStrdup(ep->error); - } - - /* - * Restore the old evaluation block - */ - ep->input = oldBlock; - - if (state == EJS_STATE_ERR) { - return -1; - } - - if (vp) { - *vp = ep->result; - } - - return ep->exitStatus; -} - -/******************************************************************************/ -/* - * Core error handling - */ - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) PRINTF_ATTRIBUTE(2, 0); - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) -{ - EjsInput *ip; - char *errbuf, *msgbuf; - - mprAssert(ep); - mprAssert(args); - - msgbuf = NULL; - mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); - - if (ep) { - ip = ep->input; - if (ip) { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, - "%s\nError on line %d. Offending line: %s\n\n", - msgbuf, ip->lineNumber, ip->line); - } else { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); - } - mprFree(ep->error); - ep->error = errbuf; - } - mprFree(msgbuf); -} - -/******************************************************************************/ -/* - * Internal use function to set the error message - */ - -void ejsError(Ejs* ep, const char* fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Public routine to set the error message - */ - -void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) -{ - va_list args; - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejsGetLineNumber(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Return the local object - */ - -MprVar *ejsGetLocalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->local; -} - -/******************************************************************************/ -/* - * Return the global object - */ - -MprVar *ejsGetGlobalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->global; -} - -/******************************************************************************/ -/* - * Copy the value of an object property. Return value is in "value". - * If deepCopy is true, copy all object/strings. Otherwise, object reference - * counts are incremented. Callers must always call mprDestroyVar on the - * return value to prevent leaks. - * - * Returns: -1 on errors or if the variable is not found. - */ - -int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprCopyProperty(value, vp, deepCopy); -} - -/******************************************************************************/ -/* - * Return the value of an object property. Return value is in "value". - * Objects and strings are not copied and reference counts are not modified. - * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the - * variable is not found. - */ - -int ejsReadVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprReadProperty(vp, value); -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { - return -1; - } - mprAssert(vp); - - /* - * Only copy the value. Don't overwrite the object's name - */ - mprWriteProperty(vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) -{ - return ejsWriteVar(eid, var, &value); -} - -/******************************************************************************/ -/* - * Delete a variable - */ - -int ejsDeleteVar(EjsId eid, const char *var) -{ - Ejs *ep; - MprVar *vp; - MprVar *obj; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { - return -1; - } - mprDeleteProperty(obj, vp->name); - return 0; -} - -/******************************************************************************/ -/* - * Set the expression return value - */ - -void ejsSetReturnValue(EjsId eid, MprVar value) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Set the expression return value to a string value - */ - -void ejsSetReturnString(EjsId eid, const char *str) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Get the expression return value - */ - -MprVar *ejsGetReturnValue(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return &ep->result; -} - -/******************************************************************************/ -/* - * Define a C function. If eid < 0, then update the master object with this - * function. NOTE: in this case, functionName must be simple without any "." or - * "[]" elements. If eid >= 0, add to the specified script engine. In this - * case, functionName can be an arbitrary object reference and can contain "." - * or "[]". - */ - -void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, - void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a C function with String arguments - */ - -void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a JavaScript function. Args should be comma separated. - * Body should not contain braces. - */ - -void ejsDefineFunction(EjsId eid, const char *functionName, char *args, char *body) -{ - MprVar v; - - v = mprCreateFunctionVar(args, body, 0); - if (eid < 0) { - ejsLock(); - mprCreateProperty(&master, functionName, &v); - ejsUnlock(); - } else { - ejsWriteVar(eid, functionName, &v); - } - mprDestroyVar(&v); -} - -/******************************************************************************/ - -void *ejsGetThisPtr(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->thisPtr; -} - -/******************************************************************************/ -/* - * Find a variable given a variable name and return the parent object and - * the variable itself, the variable . This routine supports variable names - * that may be objects or arrays but may NOT have expressions in the array - * indicies. Returns -1 on errors or if the variable is not found. - */ - -int ejsGetVarCore(Ejs *ep, const char *varName_c, MprVar **obj, MprVar **varValue, - int flags) -{ - MprVar *currentObj; - MprVar *currentVar; - char tokBuf[EJS_MAX_ID]; - char *propertyName, *token, *next, *cp, *varName; - - if (obj) { - *obj = 0; - } - if (varValue) { - *varValue = 0; - } - currentObj = ejsFindObj(ep, 0, varName_c, flags); - currentVar = 0; - propertyName = 0; - - varName = mprStrdup(varName_c); - next = varName; - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - while (currentObj != 0 && token != 0 && *token) { - - if (*token == '[') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - propertyName = token; - if (*propertyName == '\"') { - propertyName++; - if ((cp = strchr(propertyName, '\"')) != 0) { - *cp = '\0'; - } - } else if (*propertyName == '\'') { - propertyName++; - if ((cp = strchr(propertyName, '\'')) != 0) { - *cp = '\0'; - } - } - - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (*token != ']') { - mprFree(varName); - return -1; - } - - } else if (*token == '.') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (!isalpha((int) token[0]) && - token[0] != '_' && token[0] != '$') { - mprFree(varName); - return -1; - } - - propertyName = token; - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - - } else { - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - } - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - } - mprFree(varName); - - if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { - currentVar = mprCreatePropertyValue(currentObj, propertyName, - mprCreateUndefinedVar()); - } - if (obj) { - *obj = currentObj; - } - - /* - * Don't use mprCopyVar as it will copy the data - */ - if (varValue) { - *varValue = currentVar; - } - return currentVar ? 0 : -1; -} - -/******************************************************************************/ -/* - * Get the next token as part of a variable specification. This will return - * a pointer to the next token and will return a pointer to the next token - * (after this one) in "next". The tokBuf holds the parsed token. - */ -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) -{ - char *start, *cp; - int len; - - start = *next; - while (isspace((int) *start) || *start == '\n' || *start == '\r') { - start++; - } - cp = start; - - if (*cp == '.' || *cp == '[' || *cp == ']') { - cp++; - } else { - while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && - !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { - cp++; - } - } - len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); - tokBuf[len] = '\0'; - - *next = cp; - return tokBuf; -} - -/******************************************************************************/ -/* - * Get the EJS structure pointer - */ - -Ejs *ejsPtr(EjsId eid) -{ - Ejs *handle; - int intId; - - intId = (int) eid; - - ejsLock(); - mprAssert(0 <= intId && intId < ejsList->max); - - if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { - mprAssert(0); - ejsUnlock(); - return NULL; - } - handle = ejsList->handles[intId]; - ejsUnlock(); - return handle; -} - -/******************************************************************************/ -/* - * Utility routine to crack JavaScript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { - * mprError("Insufficient args\n"); - * return -1; - * } - */ - -int ejsParseArgs(int argc, char **argv, char *fmt, ...) -{ - va_list vargs; - bool *bp; - char *cp, **sp, *s; - int *ip, argn; - - va_start(vargs, fmt); - - if (argv == 0) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - s = argv[argn]; - switch (*cp) { - case 'b': - bp = va_arg(vargs, bool*); - if (bp) { - if (strcmp(s, "true") == 0 || s[0] == '1') { - *bp = 1; - } else { - *bp = 0; - } - } else { - *bp = 0; - } - break; - - case 'd': - ip = va_arg(vargs, int*); - *ip = atoi(s); - break; - - case 's': - sp = va_arg(vargs, char**); - *sp = s; - break; - - default: - mprAssert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ - -#else -void ejsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejs.h b/source4/lib/ejs/ejs.h index 79216d4712..f1d2bb4c6e 100644 --- a/source4/lib/ejs/ejs.h +++ b/source4/lib/ejs/ejs.h @@ -44,8 +44,8 @@ #ifndef _h_EJS #define _h_EJS 1 -#include "lib/ejs/miniMpr.h" -#include "lib/ejs/var.h" +#include "miniMpr.h" +#include "var.h" #ifdef __cplusplus extern "C" { @@ -75,7 +75,7 @@ extern void ejsCloseEngine(EjsId eid); * Evaluation functions */ extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); -extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, +extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, char **emsg); extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, MprArray *args); @@ -87,7 +87,8 @@ extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, extern MprVar ejsCreateObj(const char *name, int hashSize); extern MprVar ejsCreateArray(const char *name, int hashSize); extern bool ejsDestroyVar(MprVar *obj); -extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool copyRef); +extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, + bool copyRef); extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); @@ -99,8 +100,8 @@ extern MprVar *ejsGetGlobalObject(EjsId eid); /* * Function routines */ -extern void ejsDefineFunction(EjsId eid, const char *functionName, char *args, - char *body); +extern void ejsDefineFunction(EjsId eid, const char *functionName, + char *args, char *body); extern void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, void *thisPtr, int flags); extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, @@ -109,7 +110,8 @@ extern void *ejsGetThisPtr(EjsId eid); extern MprVar *ejsGetReturnValue(EjsId eid); extern int ejsGetLineNumber(EjsId eid); extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); -extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) + PRINTF_ATTRIBUTE(2,3); extern void ejsSetReturnValue(EjsId eid, MprVar value); extern void ejsSetReturnString(EjsId eid, const char *str); diff --git a/source4/lib/ejs/ejsInternal.h b/source4/lib/ejs/ejsInternal.h index 4d54c4e8c6..3bf99d88b9 100644 --- a/source4/lib/ejs/ejsInternal.h +++ b/source4/lib/ejs/ejsInternal.h @@ -39,7 +39,7 @@ #ifndef _h_EJS_INTERNAL #define _h_EJS_INTERNAL 1 -#include "lib/ejs/ejs.h" +#include "ejs.h" /********************************** Defines ***********************************/ @@ -253,7 +253,8 @@ extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); /* * Parsing */ -extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags); +extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, + int flags); extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, int flags); extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c index b0d6483c2a..6dcc1c7b78 100644 --- a/source4/lib/ejs/ejsLex.c +++ b/source4/lib/ejs/ejsLex.c @@ -36,7 +36,7 @@ */ /********************************** Includes **********************************/ -#include "lib/ejs/ejsInternal.h" +#include "ejsInternal.h" #if BLD_FEATURE_EJS @@ -439,6 +439,9 @@ static int getLexicalToken(Ejs *ep, int state) */ while (1) { if ((c = inputGetc(ep)) < 0) { + if (style == '/') { + return EJS_TOK_EOF; + } ejsError(ep, "Syntax Error"); return EJS_TOK_ERR; } diff --git a/source4/lib/ejs/ejsLib.c b/source4/lib/ejs/ejsLib.c new file mode 100644 index 0000000000..caae5b6495 --- /dev/null +++ b/source4/lib/ejs/ejsLib.c @@ -0,0 +1,1061 @@ +/* + * @file ejs.c + * @brief Embedded JavaScript (EJS) + * @overview Main module interface logic. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "ejsInternal.h" + +#if BLD_FEATURE_EJS + +/********************************** Local Data ********************************/ + +/* + * These fields must be locked before any access when multithreaded + */ +static MprVar master; /* Master object */ +static MprArray *ejsList; /* List of ej handles */ + +#if BLD_FEATURE_MULTITHREAD +static EjsLock lock; +static EjsUnlock unlock; +static void *lockData; +#define ejsLock() if (lock) { (lock)(lockData); } else +#define ejsUnlock() if (unlock) { (unlock)(lockData); } else +#else +#define ejsLock() +#define ejsUnlock() +#endif + +/****************************** Forward Declarations **************************/ + +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); + +/************************************* Code ***********************************/ +/* + * Initialize the EJ subsystem + */ + +int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) +{ + MprVar *np; + +#if BLD_FEATURE_MULTITHREAD + if (lockFn) { + lock = lockFn; + unlock = unlockFn; + lockData = data; + } +#endif + ejsLock(); + + /* + * Master is the top level object (above global). It is used to clone its + * contents into the global scope for each. This is never visible to the + * user, so don't use ejsCreateObj(). + */ + master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); + if (master.type == MPR_TYPE_UNDEFINED) { + ejsUnlock(); + return MPR_ERR_CANT_ALLOCATE; + } + + ejsList = mprCreateArray(); + ejsDefineStandardProperties(&master); + + /* + * Make these objects immutable + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprSetVarReadonly(np, 1); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + ejsUnlock(); + return 0; +} + +/******************************************************************************/ + +void ejsClose() +{ + ejsLock(); + mprDestroyArray(ejsList); + mprDestroyVar(&master); + ejsUnlock(); +} + +/******************************************************************************/ +/* + * Create and initialize an EJS engine + */ + +EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) +{ + MprVar *np; + Ejs *ep; + + ep = mprMalloc(sizeof(Ejs)); + if (ep == 0) { + return (EjsId) -1; + } + memset(ep, 0, sizeof(Ejs)); + + ejsLock(); + ep->eid = (EjsId) mprAddToArray(ejsList, ep); + ejsUnlock(); + + /* + * Create array of local variable frames + */ + ep->frames = mprCreateArray(); + if (ep->frames == 0) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + ep->primaryHandle = primaryHandle; + ep->altHandle = altHandle; + + /* + * Create first frame: global variables + */ + ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); + if (ep->global->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->global); + + /* + * Create first local variable frame + */ + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); + if (ep->local->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->local); + + /* + * Clone all master variables into the global frame. This does a + * reference copy. + * + * ejsDefineStandardProperties(ep->global); + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprCreateProperty(ep->global, np->name, np); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + + mprCreateProperty(ep->global, "global", ep->global); + mprCreateProperty(ep->global, "this", ep->global); + mprCreateProperty(ep->local, "local", ep->local); + + return ep->eid; +} + +/******************************************************************************/ +/* + * Close an EJS instance + */ + +void ejsCloseEngine(EjsId eid) +{ + Ejs *ep; + MprVar *vp; + void **handles; + int i; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + + mprFree(ep->error); + mprDestroyVar(&ep->result); + mprDestroyVar(&ep->tokenNumber); + + mprDeleteProperty(ep->local, "local"); + mprDeleteProperty(ep->global, "this"); + mprDeleteProperty(ep->global, "global"); + + handles = ep->frames->handles; + for (i = 0; i < ep->frames->max; i++) { + vp = handles[i]; + if (vp) { +#if BLD_DEBUG + if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { + mprLog(7, "ejsCloseEngine: %s has ref count %d\n", + vp->name, vp->properties->refCount); + } +#endif + mprDestroyVar(vp); + mprFree(vp); + mprRemoveFromArray(ep->frames, i); + } + } + mprDestroyArray(ep->frames); + + ejsLock(); + mprRemoveFromArray(ejsList, (int) ep->eid); + ejsUnlock(); + + mprFree(ep); +} + +/******************************************************************************/ +/* + * Evaluate an EJS script file + */ + +int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) +{ + struct stat sbuf; + Ejs *ep; + char *script; + int rc, fd; + + mprAssert(path && *path); + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + goto error; + } + + if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { + ejsError(ep, "Can't open %s\n", path); + goto error; + } + + if (stat(path, &sbuf) < 0) { + close(fd); + ejsError(ep, "Cant stat %s", path); + goto error; + } + + if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { + close(fd); + ejsError(ep, "Cant malloc %d", (int) sbuf.st_size); + goto error; + } + + if (read(fd, script, sbuf.st_size) != (int) sbuf.st_size) { + close(fd); + mprFree(script); + ejsError(ep, "Error reading %s", path); + goto error; + } + + script[sbuf.st_size] = '\0'; + close(fd); + + rc = ejsEvalBlock(eid, script, result, emsg); + mprFree(script); + + return rc; + +/* + * Error return + */ +error: + *emsg = mprStrdup(ep->error); + return -1; +} + +/******************************************************************************/ +/* + * Create a new variable scope block. This pushes the old local frame down + * the stack and creates a new local variables frame. + */ + +int ejsOpenBlock(EjsId eid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); + + mprCreateProperty(ep->local, "local", ep->local); + + return mprAddToArray(ep->frames, ep->local); +} + +/******************************************************************************/ +/* + * Close a variable scope block opened via ejsOpenBlock. Pop back the old + * local variables frame. + */ + +int ejsCloseBlock(EjsId eid, int fid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + /* + * Must remove self-references before destroying "local" + */ + mprDeleteProperty(ep->local, "local"); + + mprDestroyVar(ep->local); + mprFree(ep->local); + + mprRemoveFromArray(ep->frames, fid); + ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; + + return 0; +} + +/******************************************************************************/ +/* + * Create a new variable scope block and evaluate a script. All frames + * created during this context will be automatically deleted when complete. + * vp and emsg are optional. i.e. created local variables will be discarded + * when this routine returns. + */ + +int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + int rc, fid; + + mprAssert(script); + + fid = ejsOpenBlock(eid); + rc = ejsEvalScript(eid, script, vp, emsg); + ejsCloseBlock(eid, fid); + + return rc; +} + +/******************************************************************************/ +/* + * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" + * by EJ and the caller must not free it. Returns -1 on errors and zero + * for success. On errors, emsg will be set to the reason. The caller must + * free emsg. + */ + +int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + Ejs *ep; + EjsInput *oldBlock; + int state; + void *endlessLoopTest; + int loopCounter; + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + mprDestroyVar(&ep->result); + + if (script == 0) { + return 0; + } + + /* + * Allocate a new evaluation block, and save the old one + */ + oldBlock = ep->input; + ejsLexOpenScript(ep, script); + + /* + * Do the actual parsing and evaluation + */ + loopCounter = 0; + endlessLoopTest = NULL; + ep->exitStatus = 0; + + do { + state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); + + if (state == EJS_STATE_RET) { + state = EJS_STATE_EOF; + } + /* + * Stuck parser and endless recursion protection. + */ + if (endlessLoopTest == ep->input->scriptServp) { + if (loopCounter++ > 10) { + state = EJS_STATE_ERR; + ejsError(ep, "Syntax error"); + } + } else { + endlessLoopTest = ep->input->scriptServp; + loopCounter = 0; + } + } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); + + ejsLexCloseScript(ep); + + /* + * Return any error string to the user + */ + if (state == EJS_STATE_ERR && emsg) { + *emsg = mprStrdup(ep->error); + } + + /* + * Restore the old evaluation block + */ + ep->input = oldBlock; + + if (state == EJS_STATE_ERR) { + return -1; + } + + if (vp) { + *vp = ep->result; + } + + return ep->exitStatus; +} + +/******************************************************************************/ +/* + * Core error handling + */ + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) + PRINTF_ATTRIBUTE(2, 0); + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) +{ + EjsInput *ip; + char *errbuf, *msgbuf; + + mprAssert(ep); + mprAssert(args); + + msgbuf = NULL; + mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); + + if (ep) { + ip = ep->input; + if (ip) { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, + "%s\nError on line %d. Offending line: %s\n\n", + msgbuf, ip->lineNumber, ip->line); + } else { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); + } + mprFree(ep->error); + ep->error = errbuf; + } + mprFree(msgbuf); +} + +/******************************************************************************/ +/* + * Internal use function to set the error message + */ + +void ejsError(Ejs* ep, const char* fmt, ...) +{ + va_list args; + + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Public routine to set the error message + */ + +void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) +{ + va_list args; + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Get the current line number + */ + +int ejsGetLineNumber(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + return ep->input->lineNumber; +} + +/******************************************************************************/ +/* + * Return the local object + */ + +MprVar *ejsGetLocalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->local; +} + +/******************************************************************************/ +/* + * Return the global object + */ + +MprVar *ejsGetGlobalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->global; +} + +/******************************************************************************/ +/* + * Copy the value of an object property. Return value is in "value". + * If deepCopy is true, copy all object/strings. Otherwise, object reference + * counts are incremented. Callers must always call mprDestroyVar on the + * return value to prevent leaks. + * + * Returns: -1 on errors or if the variable is not found. + */ + +int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprCopyProperty(value, vp, deepCopy); +} + +/******************************************************************************/ +/* + * Return the value of an object property. Return value is in "value". + * Objects and strings are not copied and reference counts are not modified. + * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the + * variable is not found. + */ + +int ejsReadVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprReadProperty(vp, value); +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { + return -1; + } + mprAssert(vp); + + /* + * Only copy the value. Don't overwrite the object's name + */ + mprWriteProperty(vp, value); + + return 0; +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) +{ + return ejsWriteVar(eid, var, &value); +} + +/******************************************************************************/ +/* + * Delete a variable + */ + +int ejsDeleteVar(EjsId eid, const char *var) +{ + Ejs *ep; + MprVar *vp; + MprVar *obj; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { + return -1; + } + mprDeleteProperty(obj, vp->name); + return 0; +} + +/******************************************************************************/ +/* + * Set the expression return value + */ + +void ejsSetReturnValue(EjsId eid, MprVar value) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Set the expression return value to a string value + */ + +void ejsSetReturnString(EjsId eid, const char *str) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Get the expression return value + */ + +MprVar *ejsGetReturnValue(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return &ep->result; +} + +/******************************************************************************/ +/* + * Define a C function. If eid < 0, then update the master object with this + * function. NOTE: in this case, functionName must be simple without any "." or + * "[]" elements. If eid >= 0, add to the specified script engine. In this + * case, functionName can be an arbitrary object reference and can contain "." + * or "[]". + */ + +void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, + void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a C function with String arguments + */ + +void ejsDefineStringCFunction(EjsId eid, const char *functionName, + MprStringCFunction fn, void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a JavaScript function. Args should be comma separated. + * Body should not contain braces. + */ + +void ejsDefineFunction(EjsId eid, const char *functionName, char *args, + char *body) +{ + MprVar v; + + v = mprCreateFunctionVar(args, body, 0); + if (eid < 0) { + ejsLock(); + mprCreateProperty(&master, functionName, &v); + ejsUnlock(); + } else { + ejsWriteVar(eid, functionName, &v); + } + mprDestroyVar(&v); +} + +/******************************************************************************/ + +void *ejsGetThisPtr(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->thisPtr; +} + +/******************************************************************************/ +/* + * Find a variable given a variable name and return the parent object and + * the variable itself, the variable . This routine supports variable names + * that may be objects or arrays but may NOT have expressions in the array + * indicies. Returns -1 on errors or if the variable is not found. + */ + +int ejsGetVarCore(Ejs *ep, const char *vname, MprVar **obj, + MprVar **varValue, int flags) +{ + MprVar *currentObj; + MprVar *currentVar; + char tokBuf[EJS_MAX_ID]; + char *propertyName, *token, *next, *cp, *varName; + + if (obj) { + *obj = 0; + } + if (varValue) { + *varValue = 0; + } + currentObj = ejsFindObj(ep, 0, vname, flags); + currentVar = 0; + propertyName = 0; + + next = varName = mprStrdup(vname); + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + while (currentObj != 0 && token != 0 && *token) { + + if (*token == '[') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + propertyName = token; + if (*propertyName == '\"') { + propertyName++; + if ((cp = strchr(propertyName, '\"')) != 0) { + *cp = '\0'; + } + } else if (*propertyName == '\'') { + propertyName++; + if ((cp = strchr(propertyName, '\'')) != 0) { + *cp = '\0'; + } + } + + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (*token != ']') { + mprFree(varName); + return -1; + } + + } else if (*token == '.') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (!isalpha((int) token[0]) && + token[0] != '_' && token[0] != '$') { + mprFree(varName); + return -1; + } + + propertyName = token; + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + + } else { + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + } + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + } + mprFree(varName); + + if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { + currentVar = mprCreatePropertyValue(currentObj, propertyName, + mprCreateUndefinedVar()); + } + if (obj) { + *obj = currentObj; + } + + /* + * Don't use mprCopyVar as it will copy the data + */ + if (varValue) { + *varValue = currentVar; + } + return currentVar ? 0 : -1; +} + +/******************************************************************************/ +/* + * Get the next token as part of a variable specification. This will return + * a pointer to the next token and will return a pointer to the next token + * (after this one) in "next". The tokBuf holds the parsed token. + */ +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) +{ + char *start, *cp; + int len; + + start = *next; + while (isspace((int) *start) || *start == '\n' || *start == '\r') { + start++; + } + cp = start; + + if (*cp == '.' || *cp == '[' || *cp == ']') { + cp++; + } else { + while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && + !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { + cp++; + } + } + len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); + tokBuf[len] = '\0'; + + *next = cp; + return tokBuf; +} + +/******************************************************************************/ +/* + * Get the EJS structure pointer + */ + +Ejs *ejsPtr(EjsId eid) +{ + Ejs *handle; + int intId; + + intId = (int) eid; + + ejsLock(); + mprAssert(0 <= intId && intId < ejsList->max); + + if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { + mprAssert(0); + ejsUnlock(); + return NULL; + } + handle = ejsList->handles[intId]; + ejsUnlock(); + return handle; +} + +/******************************************************************************/ +/* + * Utility routine to crack JavaScript arguments. Return the number of args + * seen. This routine only supports %s and %d type args. + * + * Typical usage: + * + * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { + * mprError("Insufficient args\n"); + * return -1; + * } + */ + +int ejsParseArgs(int argc, char **argv, char *fmt, ...) +{ + va_list vargs; + bool *bp; + char *cp, **sp, *s; + int *ip, argn; + + va_start(vargs, fmt); + + if (argv == 0) { + return 0; + } + + for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { + if (*cp++ != '%') { + continue; + } + + s = argv[argn]; + switch (*cp) { + case 'b': + bp = va_arg(vargs, bool*); + if (bp) { + if (strcmp(s, "true") == 0 || s[0] == '1') { + *bp = 1; + } else { + *bp = 0; + } + } else { + *bp = 0; + } + break; + + case 'd': + ip = va_arg(vargs, int*); + *ip = atoi(s); + break; + + case 's': + sp = va_arg(vargs, char**); + *sp = s; + break; + + default: + mprAssert(0); + } + argn++; + } + + va_end(vargs); + return argn; +} + +/******************************************************************************/ + +#else +void ejsDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/******************************************************************************/ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index 72b0889c55..a5c40e593d 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -35,7 +35,7 @@ /********************************** Includes **********************************/ -#include "lib/ejs/ejsInternal.h" +#include "ejsInternal.h" #if BLD_FEATURE_EJS @@ -1128,9 +1128,11 @@ static int parseFunctionDec(Ejs *ep, int state, int flags) mprDestroyVar(&v); return EJS_STATE_ERR; } - - /* register the function name early to allow for recursive - function calls (see note in ECMA standard, page 71) */ + + /* + * Register the function name early to allow for recursive + * function calls (see note in ECMA standard, page 71) + */ if (!(flags & EJS_FLAGS_ASSIGNMENT)) { currentObj = ejsFindObj(ep, 0, procName, flags); vp = mprSetProperty(currentObj, procName, &v); @@ -2127,7 +2129,8 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) * Run a function */ -int ejsRunFunction(int eid, MprVar *obj, const char *functionName, MprArray *args) +int ejsRunFunction(int eid, MprVar *obj, const char *functionName, + MprArray *args) { EjsProc proc, *saveProc; Ejs *ep; @@ -2284,7 +2287,8 @@ static void appendValue(MprVar *dest, MprVar *src) oldLen = strlen(oldBuf); buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); dest->string = buf; - strncpy(&buf[oldLen], value, len+1); + strcpy(&buf[oldLen], value); + } else { *dest = mprCreateStringVar(value, 1); } diff --git a/source4/lib/ejs/ejsProcs.c b/source4/lib/ejs/ejsProcs.c index e9932406ad..c01f411161 100644 --- a/source4/lib/ejs/ejsProcs.c +++ b/source4/lib/ejs/ejsProcs.c @@ -34,7 +34,7 @@ */ /********************************** Includes **********************************/ -#include "lib/ejs/ejsInternal.h" +#include "ejsInternal.h" #if BLD_FEATURE_EJS diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 70a277ae73..2ba56987dd 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -44,7 +44,7 @@ /********************************** Includes **********************************/ -#include "lib/ejs/var.h" +#include "var.h" /*********************************** Locals ***********************************/ #if VAR_DEBUG @@ -344,7 +344,8 @@ MprType mprGetVarType(MprVar *vp) * already exists in the object, then just write its value. */ -MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, MprVar *newValue) +MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, + MprVar *newValue) { MprVar *prop, *last; int bucketIndex; @@ -376,7 +377,7 @@ MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, MprVar *newValu } if (prop) { - /* FUTURE -- remove. Just for debug. */ + /* FUTURE -- remove. Just for debug. */ mprAssert(prop == 0); mprLog(0, "Attempting to create property %s in object %s\n", propertyName, obj->name); @@ -428,7 +429,8 @@ MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, MprVar *newValu * by pointer. */ -MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, MprVar newValue) +MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) { return mprCreateProperty(obj, propertyName, &newValue); } @@ -513,7 +515,8 @@ MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) * new value is passed by value rather than by pointer. */ -MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, MprVar newValue) +MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) { return mprSetProperty(obj, propertyName, &newValue); } @@ -602,7 +605,7 @@ MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) for (prop = getObjChain(obj->properties, property); prop; prop = prop->forw) { - if (prop->name && + if (prop->name && prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { break; } @@ -1170,7 +1173,8 @@ MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) * Initialize a C function. */ -MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, int flags) +MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, + int flags) { MprVar v; @@ -1183,13 +1187,14 @@ MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, int fla return v; } +/******************************************************************************/ /* - * Initialize an opaque pointer. + * Initialize an opaque pointer. */ -MprVar mprCreatePtrVar(void *ptr, const char *name) +MprVar mprCreatePtrVar(void *ptr) { - MprVar v; + MprVar v; memset(&v, 0x0, sizeof(v)); v.type = MPR_TYPE_PTR; @@ -1356,7 +1361,7 @@ MprVar mprCreateStringVar(const char *value, bool allocate) v.string = mprStrdup(value); v.allocatedData = 1; } else { - v.string = value; + v.string = (char*) value; } return v; } @@ -1410,14 +1415,14 @@ static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) dest->boolean = src->boolean; break; - case MPR_TYPE_STRING_CFUNCTION: - dest->cFunctionWithStrings = src->cFunctionWithStrings; - break; - case MPR_TYPE_PTR: dest->ptr = src->ptr; break; + case MPR_TYPE_STRING_CFUNCTION: + dest->cFunctionWithStrings = src->cFunctionWithStrings; + break; + case MPR_TYPE_CFUNCTION: dest->cFunction = src->cFunction; break; @@ -1617,6 +1622,10 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) *out = mprStrdup("null"); break; + case MPR_TYPE_PTR: + mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); + break; + case MPR_TYPE_BOOL: if (obj->boolean) { *out = mprStrdup("true"); @@ -1665,16 +1674,12 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) mprAllocSprintf(out, size, "[C StringFunction]"); break; - case MPR_TYPE_PTR: - mprAllocSprintf(out, size, "[C Pointer: %p]", obj->ptr); - break; - case MPR_TYPE_FUNCTION: mprAllocSprintf(out, size, "[JavaScript Function]"); break; case MPR_TYPE_OBJECT: - /* FUTURE -- really want: [object class: name] */ + /* FUTURE -- really want: [object class: name] */ mprAllocSprintf(out, size, "[object %s]", obj->name); break; @@ -1753,6 +1758,7 @@ MprVar mprParseVar(char *buf, MprType preferredType) case MPR_TYPE_OBJECT: case MPR_TYPE_UNDEFINED: case MPR_TYPE_NULL: + case MPR_TYPE_PTR: default: break; @@ -2157,7 +2163,7 @@ bool mprIsNan(double f) #if WIN return _isnan(f); #elif VXWORKS - /* FUTURE */ + /* FUTURE */ return (0); #else return (f == FP_NAN); @@ -2170,7 +2176,7 @@ bool mprIsInfinite(double f) #if WIN return !_finite(f); #elif VXWORKS - /* FUTURE */ + /* FUTURE */ return (0); #else return (f == FP_INFINITE); diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h index 4882aacf0f..300a0795d8 100644 --- a/source4/lib/ejs/var.h +++ b/source4/lib/ejs/var.h @@ -56,7 +56,7 @@ /********************************* Includes ***********************************/ -#include "lib/ejs/miniMpr.h" +#include "miniMpr.h" /********************************** Defines ***********************************/ @@ -92,7 +92,7 @@ typedef int MprType; #define MPR_TYPE_FUNCTION 8 /* JavaScript function */ #define MPR_TYPE_STRING 9 /* String (immutable) */ #define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ -#define MPR_TYPE_PTR 11 /* C pointer */ +#define MPR_TYPE_PTR 11 /* Opaque pointer */ /* * Create a type for the default number type @@ -140,7 +140,7 @@ typedef BLD_FEATURE_NUM_TYPE MprNum; #define mprVarIsFloating(type) \ (type == MPR_TYPE_FLOAT) #define mprVarIsPtr(type) \ - (type == MPR_TYPE_PTR) + (type == MPR_TYPE_PTR) #define mprVarIsUndefined(var) \ ((var)->type == MPR_TYPE_UNDEFINED) #define mprVarIsNull(var) \ @@ -252,9 +252,12 @@ typedef struct MprProperties { /* Collection of properties */ #endif struct MprVar **buckets; /* Hash chains */ int numItems; /* Total count of items */ + /* FUTURE - Better way of doing this */ int numDataItems; /* Enumerable data items */ uint hashSize : 8; /* Size of the hash table */ + /* FUTURE -- increase size of refCount */ uint refCount : 8; /* References to this property*/ + /* FUTURE - make these flags */ uint deleteProtect : 8; /* Don't recursively delete */ uint visited : 8; /* Node has been processed */ } MprProperties; @@ -263,8 +266,11 @@ typedef struct MprProperties { /* Collection of properties */ * Universal Variable Type */ typedef struct MprVar { + /* FUTURE - remove name to outside reference */ MprStr name; /* Property name */ + /* FUTURE - remove */ MprStr fullName; /* Full object name */ + /* FUTURE - make part of the union */ MprProperties *properties; /* Pointer to properties */ /* @@ -318,7 +324,7 @@ typedef struct MprVar { void *thisPtr; } cFunctionWithStrings; MprStr string; /* Allocated string */ - void *ptr; /* C pointer */ + void *ptr; /* Opaque pointer */ #if !BLD_DEBUG && !LINUX && !VXWORKS }; #endif @@ -355,7 +361,6 @@ extern MprVar mprCreateObjVar(const char *name, int hashSize); extern MprVar mprCreateBoolVar(bool value); extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags); -extern MprVar mprCreatePtrVar(void *ptr, const char *name); #if BLD_FEATURE_FLOATING_POINT extern MprVar mprCreateFloatVar(double value); #endif @@ -370,6 +375,7 @@ extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, int flags); extern MprVar mprCreateStringVar(const char *value, bool allocate); extern MprVar mprCreateUndefinedVar(void); +extern MprVar mprCreatePtrVar(void *ptr); extern bool mprDestroyVar(MprVar *vp); extern bool mprDestroyAllVars(MprVar* vp); extern MprType mprGetVarType(MprVar *vp); @@ -404,9 +410,12 @@ extern int mprDeleteProperty(MprVar *obj, const char *property); /* * Get/Set properties. Set will update/create. */ -extern MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value); -extern MprVar *mprSetProperty(MprVar *obj, const char *property, MprVar *value); -extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, MprVar value); +extern MprVar *mprGetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, + MprVar value); /* * Directly read/write property values (the property must already exist) -- cgit From 8435fbc4afe66848ff6732d653dc6e7b692fb622 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Jul 2005 23:16:50 +0000 Subject: r8334: fixed a ejs bug that prevented functions variables from being called in local context (This used to be commit 5ea7ae70813f615769aff7640cc19005e30ecf12) --- source4/lib/ejs/ejsParser.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c index a5c40e593d..772ed574c5 100644 --- a/source4/lib/ejs/ejsParser.c +++ b/source4/lib/ejs/ejsParser.c @@ -1280,10 +1280,6 @@ static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, tid = ejsLexGetToken(ep, state); if (tid == EJS_TOK_LPAREN) { - if (ep->currentProperty == 0) { - ejsError(ep, "Function name not defined \"%s\"\n", *id); - return -1; - } ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); return state; } @@ -1979,6 +1975,11 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) actualArgs = proc->args; argValues = (MprVar**) actualArgs->handles; + if (prototype == NULL) { + ejsError(ep, "Function name not defined '%s'\n", proc->procName); + return -1; + } + /* * Create a new variable stack frame. ie. new local variables. */ -- cgit From 36bb0ffd4c59b17c7f942d874e18865707d3c696 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 02:31:31 +0000 Subject: r8336: enable 64 bit integer support in ejs (This used to be commit 9dd41e78e1d0e5e4007d5063fbcc335abef43718) --- source4/lib/ejs/config.h | 6 +++--- source4/lib/ejs/var.c | 8 ++++---- source4/lib/ejs/var.h | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/config.h b/source4/lib/ejs/config.h index cf75d48270..e6cd603907 100644 --- a/source4/lib/ejs/config.h +++ b/source4/lib/ejs/config.h @@ -47,7 +47,7 @@ #define BLD_FEATURE_EVAL_PERIOD 30 #define BLD_FEATURE_FLOATING_POINT 0 #define BLD_FEATURE_IF_MODIFIED 0 -#define BLD_FEATURE_INT64 0 +#define BLD_FEATURE_INT64 1 #define BLD_FEATURE_KEEP_ALIVE 0 #define BLD_FEATURE_LEGACY_API 0 #define BLD_FEATURE_LIB_STDCPP 0 @@ -58,8 +58,8 @@ #define BLD_FEATURE_MALLOC_STATS 0 #define BLD_FEATURE_MALLOC_LEAK 0 #define BLD_FEATURE_MALLOC_HOOK 0 -#define BLD_FEATURE_NUM_TYPE int -#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT +#define BLD_FEATURE_NUM_TYPE int64 +#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT64 #define BLD_FEATURE_ROMFS 0 #define BLD_FEATURE_RUN_AS_SERVICE 0 #define BLD_FEATURE_SAFE_STRINGS 0 diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 2ba56987dd..843d2ff738 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -1796,7 +1796,7 @@ MprVar mprParseVar(char *buf, MprType preferredType) * Convert the variable to a boolean. Only for primitive types. */ -bool mprVarToBool(MprVar *vp) +bool mprVarToBool(const MprVar *vp) { mprAssert(vp); @@ -1886,7 +1886,7 @@ double mprVarToFloat(MprVar *vp) * Convert the variable to a number type. Only works for primitive types. */ -MprNum mprVarToNumber(MprVar *vp) +MprNum mprVarToNumber(const MprVar *vp) { #if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 return mprVarToInteger64(vp); @@ -1919,7 +1919,7 @@ MprNum mprParseNumber(char *s) * Convert the variable to an Integer64 type. Only works for primitive types. */ -int64 mprVarToInteger64(MprVar *vp) +int64 mprVarToInteger64(const MprVar *vp) { mprAssert(vp); @@ -2034,7 +2034,7 @@ int64 mprParseInteger64(char *str) * Convert the variable to an Integer type. Only works for primitive types. */ -int mprVarToInteger(MprVar *vp) +int mprVarToInteger(const MprVar *vp) { mprAssert(vp); diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h index 300a0795d8..8ed13a4995 100644 --- a/source4/lib/ejs/var.h +++ b/source4/lib/ejs/var.h @@ -446,14 +446,14 @@ extern int mprGetPropertyCount(MprVar *obj, int includeFlags); * Conversion routines */ extern MprVar mprParseVar(char *str, MprType prefType); -extern MprNum mprVarToNumber(MprVar *vp); -extern int mprVarToInteger(MprVar *vp); +extern MprNum mprVarToNumber(const MprVar *vp); +extern int mprVarToInteger(const MprVar *vp); #if BLD_FEATURE_INT64 -extern int64 mprVarToInteger64(MprVar *vp); +extern int64 mprVarToInteger64(const MprVar *vp); #endif -extern bool mprVarToBool(MprVar *vp); +extern bool mprVarToBool(const MprVar *vp); #if BLD_FEATURE_FLOATING_POINT -extern double mprVarToFloat(MprVar *vp); +extern double mprVarToFloat(const MprVar *vp); #endif extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); -- cgit From 9570e24df1397f31dbd7c8436928749da9fc378c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 05:54:21 +0000 Subject: r8341: enable floating point support in ejs (This used to be commit bdc6b67eb27cc3da6d5144bbb71096741f779aba) --- source4/lib/ejs/config.h | 6 +++++- source4/lib/ejs/miniMpr.h | 1 + source4/lib/ejs/var.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/config.h b/source4/lib/ejs/config.h index e6cd603907..320318a0b2 100644 --- a/source4/lib/ejs/config.h +++ b/source4/lib/ejs/config.h @@ -45,7 +45,7 @@ #define BLD_FEATURE_EJS 1 #define BLD_FEATURE_ESP_MODULE 1 #define BLD_FEATURE_EVAL_PERIOD 30 -#define BLD_FEATURE_FLOATING_POINT 0 +#define BLD_FEATURE_FLOATING_POINT 1 #define BLD_FEATURE_IF_MODIFIED 0 #define BLD_FEATURE_INT64 1 #define BLD_FEATURE_KEEP_ALIVE 0 @@ -135,3 +135,7 @@ #define BLD_BIN_DIR "${BLD_TOP}/bin" #define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" #define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" + +#ifndef MAX_FLOAT +#define MAX_FLOAT 3.40282347e+38F +#endif diff --git a/source4/lib/ejs/miniMpr.h b/source4/lib/ejs/miniMpr.h index 3bbd63a302..d431ebdc1b 100644 --- a/source4/lib/ejs/miniMpr.h +++ b/source4/lib/ejs/miniMpr.h @@ -74,6 +74,7 @@ #if QNX4 #include #endif + #include /********************************** Defines ***********************************/ diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 843d2ff738..7cbf8a0b7f 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -1843,7 +1843,7 @@ bool mprVarToBool(const MprVar *vp) * Convert the variable to a floating point number. Only for primitive types. */ -double mprVarToFloat(MprVar *vp) +double mprVarToFloat(const MprVar *vp) { mprAssert(vp); -- cgit From 7c78ec0e145064696552d750eaaa70f00a0882e8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 05:56:06 +0000 Subject: r8342: allow ldb_ldif_read_string() to continue in the string, so you can read multiple records (This used to be commit 4b11c00421b5152fd7d4be0be0db983bb310021d) --- source4/lib/gendb.c | 2 +- source4/lib/ldb/common/ldb_ldif.c | 9 ++++++--- source4/lib/ldb/include/ldb.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index de3e49e652..92bbd8155c 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -99,7 +99,7 @@ int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string) { struct ldb_ldif *ldif; int ret; - ldif = ldb_ldif_read_string(ldb, ldif_string); + ldif = ldb_ldif_read_string(ldb, &ldif_string); if (ldif == NULL) return -1; ret = ldb_add(ldb, ldif->msg); talloc_free(ldif); diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 79ec857cbd..463bae483b 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -728,11 +728,14 @@ static int fgetc_string(void *private_data) return EOF; } -struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s) +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s) { struct ldif_read_string_state state; - state.s = s; - return ldb_ldif_read(ldb, fgetc_string, &state); + struct ldb_ldif *ldif; + state.s = *s; + ldif = ldb_ldif_read(ldb, fgetc_string, &state); + *s = state.s; + return ldif; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 1f642d3bff..b2468b6ecb 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -316,7 +316,7 @@ void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *); struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, int (*fgetc_fn)(void *), void *private_data); struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f); -struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char *s); +struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s); int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg); char *ldb_base64_encode(void *mem_ctx, const char *buf, int len); int ldb_base64_decode(char *s); -- cgit From f0cbb1787eec4f912ce60cfcd0172cb6e32ec118 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 05:56:38 +0000 Subject: r8343: removed a debugging message (This used to be commit c12325e25291a0083446519e0b37c7bcdc3d5433) --- source4/lib/db_wrap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index c0240aa62d..57055462ff 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -103,8 +103,7 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, if (ev) { ldb_set_opaque(ldb, "EventContext", ev); } else { - DEBUG(0,("WARNING: event_context not found\n")); - talloc_show_parents(mem_ctx, stdout); + DEBUG(5,("WARNING: event_context not found\n")); } ret = ldb_register_samba_handlers(ldb); -- cgit From a7c7a9c64c01287efa100ac26863b8b8ab3f3b65 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 09:02:58 +0000 Subject: r8364: fixed a valgrind bug spotted by simo (This used to be commit ef804e8f36f1835d5d61f69565f1195a70f37e74) --- source4/lib/ldb/common/ldb_attributes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index 3d4f24771f..a915666d78 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -278,7 +278,7 @@ void ldb_subclass_remove(struct ldb_context *ldb, const char *class) talloc_free(c->name); talloc_free(c->subclasses); if (ldb->schema.num_classes-(i+1) > 0) { - memmove(c, c+1, sizeof(*c) * ldb->schema.num_classes-(i+1)); + memmove(c, c+1, sizeof(*c) * (ldb->schema.num_classes-(i+1))); } ldb->schema.num_classes--; if (ldb->schema.num_classes == 0) { -- cgit From c9b0e86a436b5b169a4c33bd25eac379cb622b17 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 12 Jul 2005 12:04:54 +0000 Subject: r8373: New wildcard matching code. This code applies correct ldap standard wildcard matching code removes WILDCARD matching from tdb @ATTRIBUTES, that's now handled independently adds some more tests for wildcard matching fixes dn comparison code in ldb_match (This used to be commit 4eb5863042011988d85092d7dde3d809aa15bd59) --- source4/lib/ldb/common/attrib_handlers.c | 95 +++------- source4/lib/ldb/common/ldb_dn.c | 64 +++++-- source4/lib/ldb/common/ldb_match.c | 229 ++++++++++++++++++++----- source4/lib/ldb/common/ldb_parse.c | 117 ++++++++++++- source4/lib/ldb/include/ldb.h | 14 +- source4/lib/ldb/include/ldb_private.h | 13 +- source4/lib/ldb/ldb_tdb/ldb_cache.c | 10 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 11 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 30 +--- source4/lib/ldb/tests/schema-tests/schema.ldif | 3 - source4/lib/ldb/tests/test-attribs.ldif | 1 - source4/lib/ldb/tests/test-generic.sh | 9 + source4/lib/ldb/tests/test-index.ldif | 1 - source4/lib/ldb/tests/test-tdb-features.sh | 19 +- 14 files changed, 413 insertions(+), 203 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index a35a450670..7f71d3574a 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -74,19 +74,6 @@ static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, } -/* - a case folding copy handler, removing leading and trailing spaces and - multiple internal spaces, and checking for wildcard characters -*/ -static int ldb_handler_fold_wildcard(struct ldb_context *ldb, void *mem_ctx, - const struct ldb_val *in, struct ldb_val *out) -{ - if (strchr(in->data, '*')) { - return -1; - } - return ldb_handler_fold(ldb, mem_ctx, in, out); -} - /* canonicalise a ldap Integer rfc2252 specifies it should be in decimal form @@ -153,60 +140,24 @@ static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, return (int)(*s1) - (int)(*s2); } -/* - compare two case insensitive strings, ignoring multiple whitespace - and leading and trailing whitespace - see rfc2252 section 8.1 - handles wildcards -*/ -static int ldb_comparison_fold_wildcard(struct ldb_context *ldb, - void *mem_ctx, - const struct ldb_val *v1, - const struct ldb_val *v2) -{ - const char *s1=v1->data, *s2=v2->data; - while (*s1 == ' ') s1++; - while (*s2 == ' ') s2++; - /* TODO: make utf8 safe, possibly with helper function from application */ - while (*s1 && *s2) { - if (s1[0] == '*' && s1[1] == 0) { - return 0; - } - if (toupper(*s1) != toupper(*s2)) break; - if (*s1 == ' ') { - while (s1[0] == s1[1]) s1++; - while (s2[0] == s2[1]) s2++; - } - s1++; s2++; - } - while (*s1 == ' ') s1++; - while (*s2 == ' ') s2++; - return (int)(*s1) - (int)(*s2); -} - - /* canonicalise a attribute in DN format */ static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { - struct ldb_dn *dn1, *dn2; + struct ldb_dn *dn; int ret = -1; out->length = 0; out->data = NULL; - dn1 = ldb_dn_explode(mem_ctx, in->data); - if (dn1 == NULL) { + dn = ldb_dn_explode_casefold(ldb, in->data); + if (dn == NULL) { return -1; } - dn2 = ldb_dn_casefold(ldb, dn1); - if (dn2 == NULL) { - goto done; - } - out->data = ldb_dn_linearize(mem_ctx, dn2); + out->data = ldb_dn_linearize(mem_ctx, dn); if (out->data == NULL) { goto done; } @@ -215,8 +166,7 @@ static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, ret = 0; done: - talloc_free(dn1); - talloc_free(dn2); + talloc_free(dn); return ret; } @@ -227,20 +177,23 @@ done: static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { - struct ldb_val cv1, cv2; + struct ldb_dn *dn1 = NULL, *dn2 = NULL; int ret; - if (ldb_canonicalise_dn(ldb, mem_ctx, v1, &cv1) != 0 || - ldb_canonicalise_dn(ldb, mem_ctx, v2, &cv2) != 0) { - goto failed; - } - ret = strcmp(cv1.data, cv2.data); - talloc_free(cv1.data); - talloc_free(cv2.data); + + dn1 = ldb_dn_explode_casefold(mem_ctx, v1->data); + if (dn1 == NULL) return -1; + + dn2 = ldb_dn_explode_casefold(mem_ctx, v2->data); + if (dn2 == NULL) { + talloc_free(dn1); + return -1; + } + + ret = ldb_dn_compare(ldb, dn1, dn2); + + talloc_free(dn1); + talloc_free(dn2); return ret; -failed: - talloc_free(cv1.data); - talloc_free(cv2.data); - return -1; } /* @@ -298,14 +251,6 @@ static const struct ldb_attrib_handler ldb_standard_attribs[] = { .canonicalise_fn = ldb_handler_fold, .comparison_fn = ldb_comparison_fold }, - { - .attr = LDB_SYNTAX_WILDCARD, - .flags = LDB_ATTR_FLAG_WILDCARD, - .ldif_read_fn = ldb_handler_copy, - .ldif_write_fn = ldb_handler_copy, - .canonicalise_fn = ldb_handler_fold_wildcard, - .comparison_fn = ldb_comparison_fold_wildcard - }, { .attr = LDB_SYNTAX_DN, .flags = 0, diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 1eaf4c486b..b421a7fe75 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -315,6 +315,19 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) edn->comp_num = 0; edn->components = NULL; + /* Special DNs case */ + if (dn[0] == '@') { + edn->comp_num = 1; + edn->components = talloc(edn, struct ldb_dn_component); + if (edn->components == NULL) goto failed; + edn->components[0].name = talloc_strdup(edn->components, "@SPECIAL"); + if (edn->components[0].name == NULL) goto failed; + edn->components[0].value.data = talloc_strdup(edn->components, dn); + if (edn->components[0].value.data== NULL) goto failed; + edn->components[0].value.length = strlen(dn); + return edn; + } + pdn = p = talloc_strdup(edn, dn); LDB_DN_NULL_FAILED(pdn); @@ -363,6 +376,12 @@ char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) char *dn, *value; int i; + /* Special DNs */ + if ((edn->comp_num == 1) && strcmp("@SPECIAL", edn->components[0].name) == 0) { + dn = talloc_strdup(mem_ctx, edn->components[0].value.data); + return dn; + } + dn = talloc_strdup(mem_ctx, ""); LDB_DN_NULL_FAILED(dn); @@ -388,28 +407,31 @@ failed: } /* compare DNs using casefolding compare functions */ -int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1) + +int ldb_dn_compare_base(struct ldb_context *ldb, + const struct ldb_dn *base, + const struct ldb_dn *dn) { int i, ret; + int n0, n1; /* if the number of components doesn't match they differ */ - if (edn0->comp_num != edn1->comp_num) - return (edn1->comp_num - edn0->comp_num); - - for (i = 0; i < edn0->comp_num; i++) { + n0 = base->comp_num - 1; + n1 = dn->comp_num - 1; + for (i = 0; i < base->comp_num; i++, n0--, n1--) { const struct ldb_attrib_handler *h; /* compare names (attribute names are guaranteed to be ASCII only) */ - ret = ldb_caseless_cmp(edn0->components[i].name, - edn1->components[i].name); + ret = ldb_caseless_cmp(base->components[n0].name, + dn->components[n1].name); if (ret) { return ret; } /* names match, compare values */ - h = ldb_attrib_handler(ldb, edn0->components[i].name); - ret = h->comparison_fn(ldb, ldb, &(edn0->components[i].value), - &(edn1->components[i].value)); + h = ldb_attrib_handler(ldb, base->components[n0].name); + ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value), + &(dn->components[n1].value)); if (ret) { return ret; } @@ -418,6 +440,16 @@ int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const str return 0; } +int ldb_dn_compare(struct ldb_context *ldb, + const struct ldb_dn *edn0, + const struct ldb_dn *edn1) +{ + if (edn0->comp_num != edn1->comp_num) + return (edn1->comp_num - edn0->comp_num); + + return ldb_dn_compare_base(ldb, edn0, edn1); +} + /* casefold a dn. We need to casefold the attribute names, and canonicalize attribute values of case insensitive attributes. @@ -456,3 +488,15 @@ failed: return NULL; } +struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn) +{ + struct ldb_dn *edn, *cdn; + + edn = ldb_dn_explode(ldb, dn); + if (edn == NULL) return NULL; + + cdn = ldb_dn_casefold(ldb, edn); + + talloc_free(edn); + return cdn; +} diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 462c078d81..b32a933df3 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -40,72 +40,111 @@ /* check if the scope matches in a search result */ -static int ldb_match_scope(const char *dn, const char *base, enum ldb_scope scope) +static int ldb_match_scope(struct ldb_context *ldb, + const char *base_str, + const char *dn_str, + enum ldb_scope scope) { - size_t dn_len, base_len; + struct ldb_dn *base; + struct ldb_dn *dn; + int ret = 0; - if (base == NULL) { + if (base_str == NULL) { return 1; } - base_len = strlen(base); - dn_len = strlen(dn); + base = ldb_dn_explode_casefold(ldb, base_str); + if (base == NULL) return 0; - if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) { - return 1; - } - - if (base_len+1 >= dn_len) { + dn = ldb_dn_explode_casefold(ldb, dn_str); + if (dn == NULL) { + talloc_free(base); return 0; } switch (scope) { case LDB_SCOPE_BASE: + if (ldb_dn_compare(ldb, base, dn) == 0) { + ret = 1; + } break; case LDB_SCOPE_ONELEVEL: - if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && - dn[dn_len - base_len - 1] == ',' && - strchr(dn, ',') == &dn[dn_len - base_len - 1]) { - return 1; + if (dn->comp_num != base->comp_num) { + if (ldb_dn_compare_base(ldb, base, dn) == 0) { + ret = 1; + } } break; case LDB_SCOPE_SUBTREE: default: - if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 && - dn[dn_len - base_len - 1] == ',') { - return 1; + if (ldb_dn_compare_base(ldb, base, dn) == 0) { + ret = 1; } break; } - return 0; + talloc_free(base); + talloc_free(dn); + return ret; } /* - match a leaf node + match if node is present +*/ +static int ldb_match_present(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + + if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { + return 1; + } + + if (ldb_msg_find_element(msg, tree->u.simple.attr)) { + return 1; + } + + return 0; +} + +/* + match a simple leaf node */ -static int ldb_match_leaf(struct ldb_context *ldb, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) +static int ldb_match_simple(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) { unsigned int i; struct ldb_message_element *el; const struct ldb_attrib_handler *h; - - if (!ldb_match_scope(msg->dn, base, scope)) { - return 0; - } + struct ldb_dn *msgdn, *valuedn; + int ret; if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; + + msgdn = ldb_dn_explode_casefold(ldb, msg->dn); + if (msgdn == NULL) return 0; + + valuedn = ldb_dn_explode_casefold(ldb, tree->u.simple.value.data); + if (valuedn == NULL) { + talloc_free(msgdn); + return 0; } - return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0; + + ret = ldb_dn_compare(ldb, msgdn, valuedn); + + talloc_free(msgdn); + talloc_free(valuedn); + + if (ret == 0) return 1; + return 0; } el = ldb_msg_find_element(msg, tree->u.simple.attr); @@ -113,10 +152,6 @@ static int ldb_match_leaf(struct ldb_context *ldb, return 0; } - if (strcmp(tree->u.simple.value.data, "*") == 0) { - return 1; - } - h = ldb_attrib_handler(ldb, el->name); for (i=0;inum_values;i++) { @@ -129,6 +164,97 @@ static int ldb_match_leaf(struct ldb_context *ldb, return 0; } +static int ldb_wildcard_compare(struct ldb_context *ldb, + struct ldb_parse_tree *tree, + const struct ldb_val value) +{ + const struct ldb_attrib_handler *h; + struct ldb_val val; + struct ldb_val cnk; + struct ldb_val *chunk; + char *p, *g; + char *save_p = NULL; + int c = 0; + + h = ldb_attrib_handler(ldb, tree->u.substring.attr); + + if(h->canonicalise_fn(ldb, ldb, &value, &val) != 0) + return -1; + + save_p = val.data; + cnk.data = NULL; + + if ( ! tree->u.substring.start_with_wildcard ) { + + chunk = tree->u.substring.chunks[c]; + if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed; + + /* FIXME: case of embedded nulls */ + if (strncmp(val.data, cnk.data, cnk.length) != 0) goto failed; + val.length -= cnk.length; + val.data += cnk.length; + c++; + talloc_free(cnk.data); + cnk.data = NULL; + } + + while (tree->u.substring.chunks[c]) { + + chunk = tree->u.substring.chunks[c]; + if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed; + + /* FIXME: case of embedded nulls */ + p = strstr(val.data, cnk.data); + if (p == NULL) goto failed; + if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { + do { /* greedy */ + g = strstr(p + cnk.length, cnk.data); + if (g) p = g; + } while(g); + } + val.length = val.length - (p - (char *)(val.data)) - cnk.length; + val.data = p + cnk.length; + c++; + talloc_free(cnk.data); + cnk.data = NULL; + } + + if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto failed; /* last chunk have not reached end of string */ + talloc_free(save_p); + return 1; + +failed: + talloc_free(save_p); + talloc_free(cnk.data); + return 0; +} + +/* + match a simple leaf node +*/ +static int ldb_match_substring(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + unsigned int i; + struct ldb_message_element *el; + + el = ldb_msg_find_element(msg, tree->u.simple.attr); + if (el == NULL) { + return 0; + } + + for (i = 0; i < el->num_values; i++) { + if (ldb_wildcard_compare(ldb, tree, el->values[i]) == 1) { + return 1; + } + } + + return 0; +} + /* bitwise-and comparator @@ -220,18 +346,24 @@ static int ldb_match_extended(struct ldb_context *ldb, this is a recursive function, and does short-circuit evaluation */ -int ldb_match_message(struct ldb_context *ldb, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) +static int ldb_match_message(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) { unsigned int i; int v; switch (tree->operation) { case LDB_OP_SIMPLE: - break; + return ldb_match_simple(ldb, msg, tree, base, scope); + + case LDB_OP_PRESENT: + return ldb_match_present(ldb, msg, tree, base, scope); + + case LDB_OP_SUBSTRING: + return ldb_match_substring(ldb, msg, tree, base, scope); case LDB_OP_EXTENDED: return ldb_match_extended(ldb, msg, tree, base, scope); @@ -256,5 +388,18 @@ int ldb_match_message(struct ldb_context *ldb, return 0; } - return ldb_match_leaf(ldb, msg, tree, base, scope); + return 0; +} + +int ldb_match_msg(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) +{ + if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { + return 0; + } + + return ldb_match_message(ldb, msg, tree, base, scope); } diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 841a785de5..b519489b48 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -194,6 +194,66 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val) return ret; } +/* find the first matching wildcard */ +static char *ldb_parse_find_wildcard(char *value) +{ + while (*value) { + value = strpbrk(value, "\\*"); + if (value == NULL) return NULL; + + if (value[0] == '\\') { + if (value[1] == '\0') return NULL; + value += 2; + continue; + } + + if (value[0] == '*') return value; + } + + return NULL; +} + +/* return a NULL terminated list of binary strings representing the value + chunks separated by wildcards that makes the value portion of the filter +*/ +static struct ldb_val **ldb_wildcard_decode(void *mem_ctx, const char *string) +{ + struct ldb_val **ret = NULL; + int val = 0; + char *wc, *str; + + wc = talloc_strdup(mem_ctx, string); + if (wc == NULL) return NULL; + + while (wc && *wc) { + str = wc; + wc = ldb_parse_find_wildcard(str); + if (wc && *wc) { + if (wc == str) { + wc++; + continue; + } + *wc = 0; + wc++; + } + + ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2); + if (ret == NULL) return NULL; + + ret[val] = talloc(mem_ctx, struct ldb_val); + if (ret[val] == NULL) return NULL; + + *(ret[val]) = ldb_binary_decode(mem_ctx, str); + if ((ret[val])->data == NULL) return NULL; + + val++; + } + + ret[val] = NULL; + + return ret; +} + static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s); @@ -214,8 +274,11 @@ static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, char *attr, char *value) { char *p1, *p2, *p3; + ret->operation = LDB_OP_EXTENDED; ret->u.extended.value = ldb_binary_decode(ret, value); + if (ret->u.extended.value.data == NULL) goto failed; + p1 = strchr(attr, ':'); if (p1 == NULL) goto failed; p2 = strchr(p1+1, ':'); @@ -241,7 +304,6 @@ static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, ret->u.extended.rule_id = talloc_strdup(ret, p1+1); if (ret->u.extended.rule_id == NULL) goto failed; } - ret->u.extended.value = ldb_binary_decode(ret, value); return ret; @@ -293,10 +355,37 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) /* its an extended match */ return ldb_parse_extended(ret, l, val); } - + + if (val && strcmp(val, "*") == 0) { + ret->operation = LDB_OP_PRESENT; + ret->u.present.attr = l; + + return ret; + } + + if (val && ldb_parse_find_wildcard(val) != NULL) { + ret->operation = LDB_OP_SUBSTRING; + ret->u.substring.attr = l; + ret->u.substring.start_with_wildcard = 0; + ret->u.substring.end_with_wildcard = 0; + ret->u.substring.chunks = ldb_wildcard_decode(ret, val); + if (ret->u.substring.chunks == NULL){ + talloc_free(ret); + return NULL; + } + if (val[0] == '*') ret->u.substring.start_with_wildcard = 1; + if (val[strlen(val) - 1] == '*') ret->u.substring.end_with_wildcard = 1; + + return ret; + } + ret->operation = LDB_OP_SIMPLE; ret->u.simple.attr = l; ret->u.simple.value = ldb_binary_decode(ret, val); + if (ret->u.simple.value.data == NULL) { + talloc_free(ret); + return NULL; + } return ret; } @@ -491,6 +580,30 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) s); talloc_free(s); return ret; + case LDB_OP_SUBSTRING: + ret = talloc_strdup(mem_ctx, (tree->u.substring.start_with_wildcard)?"*":""); + if (ret == NULL) return NULL; + for (i = 0; tree->u.substring.chunks[i]; i++) { + s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i])); + if (s2 == NULL) { + talloc_free(ret); + return NULL; + } + s = talloc_asprintf_append(ret, "%s*", s2); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + ret = s; + } + if ( ! tree->u.substring.end_with_wildcard ) { + ret[strlen(ret) - 1] = '\0'; /* remove last wildcard */ + } + return ret; + case LDB_OP_PRESENT: + ret = talloc_strdup(mem_ctx, "*"); + if (ret == NULL) return NULL; + return ret; case LDB_OP_AND: case LDB_OP_OR: ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index b2468b6ecb..8233e78f0e 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -154,7 +154,8 @@ struct ldb_debug_ops { /* structues for ldb_parse_tree handling code */ -enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_EXTENDED=2, +enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_EXTENDED=2, + LDB_OP_SUBSTRING=3, LDB_OP_PRESENT=4, LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; struct ldb_parse_tree { @@ -164,6 +165,15 @@ struct ldb_parse_tree { char *attr; struct ldb_val value; } simple; + struct { + char *attr; + } present; + struct { + char *attr; + int start_with_wildcard; + int end_with_wildcard; + struct ldb_val **chunks; + } substring; struct { char *attr; int dnAttributes; @@ -211,14 +221,12 @@ struct ldb_attrib_handler { }; #define LDB_ATTR_FLAG_HIDDEN (1<<0) -#define LDB_ATTR_FLAG_WILDCARD (1<<1) /* well-known ldap attribute syntaxes - see rfc2252 section 4.3.2 */ #define LDB_SYNTAX_DN "1.3.6.1.4.1.1466.115.121.1.12" #define LDB_SYNTAX_DIRECTORY_STRING "1.3.6.1.4.1.1466.115.121.1.15" #define LDB_SYNTAX_INTEGER "1.3.6.1.4.1.1466.115.121.1.27" #define LDB_SYNTAX_OCTET_STRING "1.3.6.1.4.1.1466.115.121.1.40" -#define LDB_SYNTAX_WILDCARD "LDB_SYNTAX_WILDCARD" #define LDB_SYNTAX_OBJECTCLASS "LDB_SYNTAX_OBJECTCLASS" /* diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 1d7d453767..da813eb588 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -175,11 +175,11 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, const char *attrib); -int ldb_match_message(struct ldb_context *ldb, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope); +int ldb_match_msg(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope); void ldb_remove_attrib_handler(struct ldb_context *ldb, const char *attrib); const struct ldb_attrib_handler *ldb_attrib_handler_syntax(struct ldb_context *ldb, @@ -193,9 +193,10 @@ int ldb_setup_wellknown_attributes(struct ldb_context *ldb); /* The following definitions come from lib/ldb/common/ldb_dn.c */ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn); +int ldb_dn_compare_base(struct ldb_context *ldb, const struct ldb_dn *base, const struct ldb_dn *dn); int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1); struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn); - +struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn); /* The following definitions come from lib/ldb/common/ldb_attributes.c */ const char **ldb_subclass_list(struct ldb_context *ldb, const char *class); diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 0b7ddad5db..be76f7085b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -39,9 +39,8 @@ #define LTDB_FLAG_CASE_INSENSITIVE (1<<0) #define LTDB_FLAG_INTEGER (1<<1) -#define LTDB_FLAG_WILDCARD (1<<2) -#define LTDB_FLAG_HIDDEN (1<<3) -#define LTDB_FLAG_OBJECTCLASS (1<<4) +#define LTDB_FLAG_HIDDEN (1<<2) +#define LTDB_FLAG_OBJECTCLASS (1<<3) /* valid attribute flags */ static const struct { @@ -50,7 +49,6 @@ static const struct { } ltdb_valid_attr_flags[] = { { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, { "INTEGER", LTDB_FLAG_INTEGER }, - { "WILDCARD", LTDB_FLAG_WILDCARD }, { "HIDDEN", LTDB_FLAG_HIDDEN }, { "NONE", 0 }, { NULL, 0 } @@ -138,10 +136,6 @@ static int ltdb_attributes_load(struct ldb_module *module) case 0: syntax = LDB_SYNTAX_OCTET_STRING; break; - case LTDB_FLAG_WILDCARD: - case LTDB_FLAG_WILDCARD | LTDB_FLAG_CASE_INSENSITIVE: - syntax = LDB_SYNTAX_WILDCARD; - break; case LTDB_FLAG_CASE_INSENSITIVE: syntax = LDB_SYNTAX_DIRECTORY_STRING; break; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index a3317a8765..03ad0612d4 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -188,13 +188,6 @@ static int ltdb_index_dn_simple(struct ldb_module *module, list->count = 0; list->dn = NULL; - /* - if the value is a wildcard then we can't do a match via indexing - */ - if (ltdb_has_wildcard(module, tree->u.simple.attr, &tree->u.simple.value)) { - return -1; - } - /* if the attribute isn't in the list of indexed attributes then this node needs a full search */ if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL, LTDB_IDXATTR) == -1) { @@ -581,6 +574,8 @@ static int ltdb_index_dn(struct ldb_module *module, ret = ltdb_index_dn_leaf(module, tree, index_list, list); break; + case LDB_OP_PRESENT: + case LDB_OP_SUBSTRING: case LDB_OP_EXTENDED: /* we can't index with fancy bitops yet */ ret = -1; @@ -638,7 +633,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr } ret = 0; - if (ldb_match_message(module->ldb, msg, tree, base, scope) == 1) { + if (ldb_match_msg(module->ldb, msg, tree, base, scope) == 1) { ret = ltdb_add_attr_results(module, msg, attrs, &count, res); } talloc_free(msg); diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index e48043da88..3ecb2d9b39 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -188,34 +188,6 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, } - -/* - see if a ldb_val is a wildcard - return 1 if yes, 0 if no -*/ -int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, - const struct ldb_val *val) -{ - const struct ldb_attrib_handler *h; - - /* all attribute types recognise the "*" wildcard */ - if (val->length == 1 && strncmp((char *)val->data, "*", 1) == 0) { - return 1; - } - - if (strpbrk(val->data, "*?") == NULL) { - return 0; - } - - h = ldb_attrib_handler(module->ldb, attr_name); - if (h->flags & LDB_ATTR_FLAG_WILDCARD) { - return 1; - } - - return 0; -} - - /* search the database for a single simple dn, returning all attributes in a single message @@ -416,7 +388,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } /* see if it matches the given expression */ - if (!ldb_match_message(sinfo->module->ldb, msg, sinfo->tree, + if (!ldb_match_msg(sinfo->module->ldb, msg, sinfo->tree, sinfo->base, sinfo->scope)) { talloc_free(msg); return 0; diff --git a/source4/lib/ldb/tests/schema-tests/schema.ldif b/source4/lib/ldb/tests/schema-tests/schema.ldif index 59757d22a9..d1ad50f2cc 100644 --- a/source4/lib/ldb/tests/schema-tests/schema.ldif +++ b/source4/lib/ldb/tests/schema-tests/schema.ldif @@ -13,11 +13,8 @@ realm: CASE_INSENSITIVE userPrincipalName: CASE_INSENSITIVE servicePrincipalName: CASE_INSENSITIVE name: CASE_INSENSITIVE -name: WILDCARD dn: CASE_INSENSITIVE -dn: WILDCARD sAMAccountName: CASE_INSENSITIVE -sAMAccountName: WILDCARD objectClass: CASE_INSENSITIVE unicodePwd: HIDDEN ntPwdHash: HIDDEN diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif index e6fe1dcf5a..0bb3ebead6 100644 --- a/source4/lib/ldb/tests/test-attribs.ldif +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -1,6 +1,5 @@ dn: @ATTRIBUTES uid: CASE_INSENSITIVE -uid: WILDCARD cn: CASE_INSENSITIVE ou: CASE_INSENSITIVE dn: CASE_INSENSITIVE diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index db6377d078..3ad17fe9d3 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -45,6 +45,15 @@ $VALGRIND ldbsearch '((' uid || exit 1 $VALGRIND ldbsearch '(objectclass=)' uid || exit 1 $VALGRIND ldbsearch -b 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' -s base "" sn || exit 1 +echo "Test wildcard match" +$VALGRIND ldbadd $LDBDIR/tests/test-wildcard.ldif || exit 1 +$VALGRIND ldbsearch '(cn=test*multi)' || exit 1 +$VALGRIND ldbsearch '(cn=*test*multi*)' || exit 1 +$VALGRIND ldbsearch '(cn=*test_multi)' || exit 1 +$VALGRIND ldbsearch '(cn=test_multi*)' || exit 1 +$VALGRIND ldbsearch '(cn=test*multi*test*multi)' || exit 1 +$VALGRIND ldbsearch '(cn=test*multi*test*multi*multi_*)' || exit 1 + echo "Starting ldbtest indexed" time $VALGRIND ldbtest --num-records 100 --num-searches 500 || exit 1 diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index 7ba0106394..a793537187 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -4,7 +4,6 @@ dn: @INDEXLIST dn: @ATTRIBUTES uid: CASE_INSENSITIVE -uid: WILDCARD dn: @SUBCLASSES top: person diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index 613afef8ad..fb68733802 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -16,7 +16,7 @@ checkcount() { echo "OK: $count $expression" } -echo "Testing case sensitve search" +echo "Testing case sensitive search" cat < Date: Tue, 12 Jul 2005 13:37:11 +0000 Subject: r8377: forgot an ldif test (This used to be commit ed804262dc6abf01ffdeb03a36d94cf40b9f033c) --- source4/lib/ldb/tests/test-wildcard.ldif | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 source4/lib/ldb/tests/test-wildcard.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-wildcard.ldif b/source4/lib/ldb/tests/test-wildcard.ldif new file mode 100644 index 0000000000..07a3d96a67 --- /dev/null +++ b/source4/lib/ldb/tests/test-wildcard.ldif @@ -0,0 +1,4 @@ +dn: cn=test_multi_test_multi_test_multi,o=University of Michigan,c=TEST +objectclass: person +cn: test_multi_test_multi_test_multi +description: test multi wildcards matching -- cgit From 61edb97bdfabf1ab313fbec5f47f5e6c8a79da1a Mon Sep 17 00:00:00 2001 From: Love Hörnquist Ã…strand Date: Tue, 12 Jul 2005 22:22:59 +0000 Subject: r8394: Make sure the argument to ctype is*(3) macros are unsigned char as required by ISO C99. (This used to be commit 56fd21c806e816cf4c3d23881f26474f858b45e2) --- source4/lib/ejs/var.c | 18 +++++++++--------- source4/lib/genrand.c | 6 +++--- source4/lib/ldb/common/attrib_handlers.c | 3 ++- source4/lib/ldb/common/ldb_dn.c | 2 +- source4/lib/ldb/common/ldb_parse.c | 12 ++++++------ source4/lib/ldb/common/ldb_utf8.c | 5 +++-- source4/lib/socket/socket_ipv6.c | 2 +- source4/lib/util_str.c | 7 ++++--- 8 files changed, 29 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c index 7cbf8a0b7f..9d2afe5306 100644 --- a/source4/lib/ejs/var.c +++ b/source4/lib/ejs/var.c @@ -1730,18 +1730,18 @@ MprVar mprParseVar(char *buf, MprType preferredType) } else if (isdigit((int) *buf)) { type = MPR_NUM_VAR; cp = buf; - if (*cp && tolower(cp[1]) == 'x') { + if (*cp && tolower((unsigned char)cp[1]) == 'x') { cp = &cp[2]; } for (cp = buf; *cp; cp++) { - if (! isdigit((int) *cp)) { + if (! isdigit((unsigned char) *cp)) { break; } } if (*cp != '\0') { #if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower(*cp) == 'e') { + if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { type = MPR_TYPE_FLOAT; } else #endif @@ -1993,11 +1993,11 @@ int64 mprParseInteger64(char *str) } } else { cp++; - if (tolower(*cp) == 'x') { + if (tolower((unsigned char)*cp) == 'x') { cp++; radix = 16; while (*cp) { - c = tolower(*cp); + c = tolower((unsigned char)*cp); if (isdigit(c)) { num64 = (c - '0') + (num64 * radix); } else if (c >= 'a' && c <= 'f') { @@ -2011,7 +2011,7 @@ int64 mprParseInteger64(char *str) } else{ radix = 8; while (*cp) { - c = tolower(*cp); + c = tolower((unsigned char)*cp); if (isdigit(c) && c < '8') { num64 = (c - '0') + (num64 * radix); } else { @@ -2110,11 +2110,11 @@ int mprParseInteger(char *str) } } else { cp++; - if (tolower(*cp) == 'x') { + if (tolower((unsigned char)*cp) == 'x') { cp++; radix = 16; while (*cp) { - c = tolower(*cp); + c = tolower((unsigned char)*cp); if (isdigit(c)) { num = (c - '0') + (num * radix); } else if (c >= 'a' && c <= 'f') { @@ -2128,7 +2128,7 @@ int mprParseInteger(char *str) } else{ radix = 8; while (*cp) { - c = tolower(*cp); + c = tolower((unsigned char)*cp); if (isdigit(c) && c < '8') { num = (c - '0') + (num * radix); } else { diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index 9d40e72afc..ca79116b6a 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -261,11 +261,11 @@ BOOL check_password_quality(const char *s) { int has_digit=0, has_capital=0, has_lower=0; while (*s) { - if (isdigit(*s)) { + if (isdigit((unsigned char)*s)) { has_digit++; - } else if (isupper(*s)) { + } else if (isupper((unsigned char)*s)) { has_capital++; - } else if (islower(*s)) { + } else if (islower((unsigned char)*s)) { has_lower++; } s++; diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 7f71d3574a..da2d945419 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -128,7 +128,8 @@ static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, while (*s2 == ' ') s2++; /* TODO: make utf8 safe, possibly with helper function from application */ while (*s1 && *s2) { - if (toupper(*s1) != toupper(*s2)) break; + if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) + break; if (*s1 == ' ') { while (s1[0] == s1[1]) s1++; while (s2[0] == s2[1]) s2++; diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index b421a7fe75..32b575dd36 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -47,7 +47,7 @@ static int ldb_dn_is_valid_attribute_name(const char *name) if (! isascii(*name)) { return 0; } - if (! (isalnum(*name) || *name == '-')) { + if (! (isalnum((unsigned char)*name) || *name == '-')) { return 0; } name++; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index b519489b48..ad3cbd883d 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -68,7 +68,7 @@ static char *ldb_parse_lex(void *ctx, const char **s, const char *sep) const char *p = *s; char *ret; - while (isspace(*p)) { + while (isspace((unsigned char)*p)) { p++; } *s = p; @@ -86,7 +86,7 @@ static char *ldb_parse_lex(void *ctx, const char **s, const char *sep) return ret; } - while (*p && (isalnum(*p) || !strchr(sep, *p))) { + while (*p && (isalnum((unsigned char)*p) || !strchr(sep, *p))) { p++; } @@ -423,7 +423,7 @@ static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, return NULL; } - while (isspace(*s)) s++; + while (isspace((unsigned char)*s)) s++; while (*s && (next = ldb_parse_filter(ret->u.list.elements, &s))) { struct ldb_parse_tree **e; @@ -438,7 +438,7 @@ static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, ret->u.list.elements = e; ret->u.list.elements[ret->u.list.num_elements] = next; ret->u.list.num_elements++; - while (isspace(*s)) s++; + while (isspace((unsigned char)*s)) s++; } return ret; @@ -474,7 +474,7 @@ static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) */ static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char *s) { - while (isspace(*s)) s++; + while (isspace((unsigned char)*s)) s++; switch (*s) { case '&': @@ -543,7 +543,7 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) */ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) { - while (isspace(*s)) s++; + while (isspace((unsigned char)*s)) s++; if (*s == '(') { return ldb_parse_filter(mem_ctx, &s); diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 38c117d7e0..5df5a6bba7 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -50,7 +50,7 @@ char *ldb_casefold(void *mem_ctx, const char *s) return NULL; } for (i=0;ret[i];i++) { - ret[i] = toupper(ret[i]); + ret[i] = toupper((unsigned char)ret[i]); } return ret; } @@ -63,7 +63,8 @@ int ldb_caseless_cmp(const char *s1, const char *s2) { int i; for (i=0;s1[i] != 0;i++) { - int c1 = toupper(s1[i]), c2 = toupper(s2[i]); + int c1 = toupper((unsigned char)s1[i]), + c2 = toupper((unsigned char)s2[i]); if (c1 != c2) { return c1 - c2; } diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 25c5ca5798..58e35d87de 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -290,7 +290,7 @@ static char *ipv6_tcp_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem return NULL; } - he = gethostbyaddr(&peer_addr.sin6_addr, sizeof(peer_addr.sin6_addr), AF_INET6); + he = gethostbyaddr((char *)&peer_addr.sin6_addr, sizeof(peer_addr.sin6_addr), AF_INET6); if (!he || !he->h_name) { return NULL; diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index fea7170014..592c38e53c 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -159,7 +159,8 @@ int strwicmp(const char *psz1, const char *psz2) psz1++; while (isspace((int)*psz2)) psz2++; - if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' + if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) + || *psz1 == '\0' || *psz2 == '\0') break; psz1++; @@ -412,12 +413,12 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex) continue; } - if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) + if (!(p1 = strchr_m(hexchars, toupper((unsigned char)strhex[i])))) break; i++; /* next hex digit */ - if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) + if (!(p2 = strchr_m(hexchars, toupper((unsigned char)strhex[i])))) break; /* get the two nybbles */ -- cgit From e5700ea5607c366ff8c4fbf272749efae886bbab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Jul 2005 23:49:08 +0000 Subject: r8397: merged an upstream fix for the expression bug tpot found yesterday (This used to be commit 93712dd894b4ddaa2281034c754c0fa15f5ec34c) --- source4/lib/ejs/ejsLex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c index 6dcc1c7b78..a5f15c2979 100644 --- a/source4/lib/ejs/ejsLex.c +++ b/source4/lib/ejs/ejsLex.c @@ -663,11 +663,11 @@ static int getLexicalToken(Ejs *ep, int state) break; } #if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { + if (c == '.' || tolower(c) == 'e' || tolower(c) == 'f') { type = MPR_TYPE_FLOAT; } - } while (isdigit(c) || c == '.' || tolower(c) == 'e' || - c == '+' || c == '-'); + } while (isdigit(c) || c == '.' || tolower(c) == 'e' || tolower(c) == 'f' || + ((type == MPR_TYPE_FLOAT) && (c == '+' || c == '-'))); #else } while (isdigit(c)); #endif -- cgit From adbb1612c12d03fa94e4ee23fbc2fa96c09d9dcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 00:06:38 +0000 Subject: r8399: move the ejs and esp code closer to the directory layout used by the upstream sources. This makes it much easier to keep it up to date. I will separate out the mpr code into lib/appweb/mpr next (This used to be commit 52db7a052baeb0f11361ed69b71cb790039e3cc9) --- source4/lib/appweb/config.mk | 24 + source4/lib/appweb/ejs/config.h | 141 ++ source4/lib/appweb/ejs/config.mk | 13 + source4/lib/appweb/ejs/ejs.h | 133 ++ source4/lib/appweb/ejs/ejsInternal.h | 293 +++++ source4/lib/appweb/ejs/ejsLex.c | 913 +++++++++++++ source4/lib/appweb/ejs/ejsLib.c | 1061 +++++++++++++++ source4/lib/appweb/ejs/ejsParser.c | 2378 ++++++++++++++++++++++++++++++++++ source4/lib/appweb/ejs/ejsProcs.c | 703 ++++++++++ source4/lib/appweb/ejs/miniMpr.c | 512 ++++++++ source4/lib/appweb/ejs/miniMpr.h | 292 +++++ source4/lib/appweb/ejs/var.c | 2197 +++++++++++++++++++++++++++++++ source4/lib/appweb/ejs/var.h | 496 +++++++ source4/lib/appweb/esp/esp.c | 1042 +++++++++++++++ source4/lib/appweb/esp/esp.h | 279 ++++ source4/lib/appweb/esp/espEnv.h | 128 ++ source4/lib/appweb/esp/espProcs.c | 246 ++++ source4/lib/ejs/config.h | 141 -- source4/lib/ejs/config.mk | 13 - source4/lib/ejs/ejs.h | 133 -- source4/lib/ejs/ejsInternal.h | 293 ----- source4/lib/ejs/ejsLex.c | 913 ------------- source4/lib/ejs/ejsLib.c | 1061 --------------- source4/lib/ejs/ejsParser.c | 2378 ---------------------------------- source4/lib/ejs/ejsProcs.c | 703 ---------- source4/lib/ejs/miniMpr.c | 512 -------- source4/lib/ejs/miniMpr.h | 292 ----- source4/lib/ejs/mprOs.h | 627 --------- source4/lib/ejs/var.c | 2197 ------------------------------- source4/lib/ejs/var.h | 496 ------- 30 files changed, 10851 insertions(+), 9759 deletions(-) create mode 100644 source4/lib/appweb/config.mk create mode 100644 source4/lib/appweb/ejs/config.h create mode 100644 source4/lib/appweb/ejs/config.mk create mode 100644 source4/lib/appweb/ejs/ejs.h create mode 100644 source4/lib/appweb/ejs/ejsInternal.h create mode 100644 source4/lib/appweb/ejs/ejsLex.c create mode 100644 source4/lib/appweb/ejs/ejsLib.c create mode 100644 source4/lib/appweb/ejs/ejsParser.c create mode 100644 source4/lib/appweb/ejs/ejsProcs.c create mode 100644 source4/lib/appweb/ejs/miniMpr.c create mode 100644 source4/lib/appweb/ejs/miniMpr.h create mode 100644 source4/lib/appweb/ejs/var.c create mode 100644 source4/lib/appweb/ejs/var.h create mode 100644 source4/lib/appweb/esp/esp.c create mode 100644 source4/lib/appweb/esp/esp.h create mode 100644 source4/lib/appweb/esp/espEnv.h create mode 100644 source4/lib/appweb/esp/espProcs.c delete mode 100644 source4/lib/ejs/config.h delete mode 100644 source4/lib/ejs/config.mk delete mode 100644 source4/lib/ejs/ejs.h delete mode 100644 source4/lib/ejs/ejsInternal.h delete mode 100644 source4/lib/ejs/ejsLex.c delete mode 100644 source4/lib/ejs/ejsLib.c delete mode 100644 source4/lib/ejs/ejsParser.c delete mode 100644 source4/lib/ejs/ejsProcs.c delete mode 100644 source4/lib/ejs/miniMpr.c delete mode 100644 source4/lib/ejs/miniMpr.h delete mode 100644 source4/lib/ejs/mprOs.h delete mode 100644 source4/lib/ejs/var.c delete mode 100644 source4/lib/ejs/var.h (limited to 'source4/lib') diff --git a/source4/lib/appweb/config.mk b/source4/lib/appweb/config.mk new file mode 100644 index 0000000000..7d1eca3437 --- /dev/null +++ b/source4/lib/appweb/config.mk @@ -0,0 +1,24 @@ +####################### +# Start SUBSYSTEM EJS +[SUBSYSTEM::EJS] +ADD_OBJ_FILES = \ + lib/appweb/ejs/ejsLib.o \ + lib/appweb/ejs/ejsLex.o \ + lib/appweb/ejs/ejsParser.o \ + lib/appweb/ejs/ejsProcs.o \ + lib/appweb/ejs/miniMpr.o \ + lib/appweb/ejs/var.o +NOPROTO=YES +# End SUBSYSTEM EJS +####################### + +####################### +# Start SUBSYSTEM ESP +[SUBSYSTEM::ESP] +ADD_OBJ_FILES = \ + lib/appweb/esp/esp.o \ + lib/appweb/esp/espProcs.o +REQUIRED_SUBSYSTEMS = EJS +NOPROTO=YES +# End SUBSYSTEM ESP +####################### diff --git a/source4/lib/appweb/ejs/config.h b/source4/lib/appweb/ejs/config.h new file mode 100644 index 0000000000..320318a0b2 --- /dev/null +++ b/source4/lib/appweb/ejs/config.h @@ -0,0 +1,141 @@ +#define BLD_PRODUCT "Samba4" +#define BLD_NAME "Samba4 SWAT" +#define BLD_VERSION "4" +#define BLD_NUMBER "1" +#define BLD_TYPE "DEBUG" +#define BLD_DEFAULTS "normal" +#define BLD_PACKAGES "" +#define BLD_APPWEB_CONFIG "normal.conf" +#define BLD_APPWEB 0 +#define BLD_COMPANY "Mbedthis" +#define BLD_DEBUG 1 +#define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" +#define BLD_HTTP_PORT 7777 +#define BLD_LIB_VERSION "1.0.0" +#define BLD_SSL_PORT 4443 +#define BLD_CLEAN_INSTALL "0" +#define BLD_LICENSE "gpl" +#define BLD_HOST_SYSTEM "i686-pc-linux-gnu" +#define BLD_BUILD_SYSTEM "i686-pc-linux-gnu" +#define BLD_HOST_OS "LINUX" +#define BLD_HOST_CPU_ARCH MPR_CPU_IX86 +#define BLD_HOST_CPU "i686" +#define BLD_HOST_UNIX 1 +#define BLD_BUILD_OS "LINUX" +#define BLD_BUILD_CPU_ARCH MPR_CPU_IX86 +#define BLD_BUILD_CPU i686 +#define BLD_BUILD_UNIX 1 +#define BLD_ROOT_PREFIX "/" +#define BLD_FEATURE_ACCESS_LOG 0 +#define BLD_FEATURE_ADMIN_MODULE 0 +#define BLD_FEATURE_ASPNET_MODULE 0 +#define BLD_FEATURE_ASSERT 1 +#define BLD_FEATURE_AUTH_MODULE 0 +#define BLD_FEATURE_C_API_MODULE 1 +#define BLD_FEATURE_C_API_CLIENT 0 +#define BLD_FEATURE_CGI_MODULE 0 +#define BLD_FEATURE_COMPAT_MODULE 0 +#define BLD_FEATURE_CONFIG_PARSE 0 +#define BLD_FEATURE_CONFIG_SAVE 0 +#define BLD_FEATURE_COOKIE 0 +#define BLD_FEATURE_COPY_MODULE 0 +#define BLD_FEATURE_DIGEST 0 +#define BLD_FEATURE_DLL 0 +#define BLD_FEATURE_EGI_MODULE 0 +#define BLD_FEATURE_EJS 1 +#define BLD_FEATURE_ESP_MODULE 1 +#define BLD_FEATURE_EVAL_PERIOD 30 +#define BLD_FEATURE_FLOATING_POINT 1 +#define BLD_FEATURE_IF_MODIFIED 0 +#define BLD_FEATURE_INT64 1 +#define BLD_FEATURE_KEEP_ALIVE 0 +#define BLD_FEATURE_LEGACY_API 0 +#define BLD_FEATURE_LIB_STDCPP 0 +#define BLD_FEATURE_LICENSE 0 +#define BLD_FEATURE_LOG 0 +#define BLD_FEATURE_MULTITHREAD 0 +#define BLD_FEATURE_MALLOC 0 +#define BLD_FEATURE_MALLOC_STATS 0 +#define BLD_FEATURE_MALLOC_LEAK 0 +#define BLD_FEATURE_MALLOC_HOOK 0 +#define BLD_FEATURE_NUM_TYPE int64 +#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT64 +#define BLD_FEATURE_ROMFS 0 +#define BLD_FEATURE_RUN_AS_SERVICE 0 +#define BLD_FEATURE_SAFE_STRINGS 0 +#define BLD_FEATURE_SAMPLES 0 +#define BLD_FEATURE_SESSION 1 +#define BLD_FEATURE_SHARED 0 +#define BLD_FEATURE_SQUEEZE 0 +#define BLD_FEATURE_SSL_MODULE 0 +#define BLD_FEATURE_STATIC 1 +#define BLD_FEATURE_STATIC_LINK_LIBC 0 +#define BLD_FEATURE_TEST 0 +#define BLD_FEATURE_UPLOAD_MODULE 0 +#define BLD_FEATURE_XDB_MODULE 0 +#define BLD_FEATURE_ADMIN_MODULE_BUILTIN 0 +#define BLD_FEATURE_ASPNET_MODULE_BUILTIN 0 +#define BLD_FEATURE_AUTH_MODULE_BUILTIN 0 +#define BLD_FEATURE_C_API_MODULE_BUILTIN 0 +#define BLD_FEATURE_CGI_MODULE_BUILTIN 0 +#define BLD_FEATURE_COMPAT_MODULE_BUILTIN 0 +#define BLD_FEATURE_COPY_MODULE_BUILTIN 0 +#define BLD_FEATURE_EGI_MODULE_BUILTIN 0 +#define BLD_FEATURE_ESP_MODULE_BUILTIN 0 +#define BLD_FEATURE_SSL_MODULE_BUILTIN 0 +#define BLD_FEATURE_UPLOAD_MODULE_BUILTIN 0 +#define BLD_FEATURE_XDB_MODULE_BUILTIN 0 +#define BLD_FEATURE_ADMIN_MODULE_LOADABLE 0 +#define BLD_FEATURE_ASPNET_MODULE_LOADABLE 0 +#define BLD_FEATURE_AUTH_MODULE_LOADABLE 0 +#define BLD_FEATURE_C_API_MODULE_LOADABLE 0 +#define BLD_FEATURE_CGI_MODULE_LOADABLE 0 +#define BLD_FEATURE_COMPAT_MODULE_LOADABLE 0 +#define BLD_FEATURE_COPY_MODULE_LOADABLE 0 +#define BLD_FEATURE_EGI_MODULE_LOADABLE 0 +#define BLD_FEATURE_ESP_MODULE_LOADABLE 0 +#define BLD_FEATURE_SSL_MODULE_LOADABLE 0 +#define BLD_FEATURE_UPLOAD_MODULE_LOADABLE 0 +#define BLD_FEATURE_XDB_MODULE_LOADABLE 0 +#define BLD_AR_FOR_BUILD "ar" +#define BLD_CC_FOR_BUILD "cc" +#define BLD_CSC_FOR_BUILD "" +#define BLD_JAVAC_FOR_BUILD "" +#define BLD_LD_FOR_BUILD "ld" +#define BLD_RANLIB_FOR_BUILD "" +#define BLD_NM_FOR_BUILD "nm" +#define BLD_CFLAGS_FOR_BUILD "" +#define BLD_IFLAGS_FOR_BUILD "" +#define BLD_LDFLAGS_FOR_BUILD "" +#define BLD_ARCHIVE_FOR_BUILD ".a" +#define BLD_EXE_FOR_BUILD "" +#define BLD_OBJ_FOR_BUILD ".o" +#define BLD_PIOBJ_FOR_BUILD ".lo" +#define BLD_CLASS_FOR_BUILD ".class" +#define BLD_SHLIB_FOR_BUILD "" +#define BLD_SHOBJ_FOR_BUILD ".so" +#define BLD_AR_FOR_HOST "ar" +#define BLD_CC_FOR_HOST "cc" +#define BLD_CSC_FOR_HOST "csc" +#define BLD_JAVAC_FOR_HOST "javac" +#define BLD_LD_FOR_HOST "ld" +#define BLD_RANLIB_FOR_HOST "true" +#define BLD_NM_FOR_HOST "nm" +#define BLD_CFLAGS_FOR_HOST "" +#define BLD_IFLAGS_FOR_HOST "" +#define BLD_LDFLAGS_FOR_HOST "" +#define BLD_ARCHIVE_FOR_HOST ".a" +#define BLD_EXE_FOR_HOST "" +#define BLD_OBJ_FOR_HOST ".o" +#define BLD_PIOBJ_FOR_HOST ".lo" +#define BLD_CLASS_FOR_HOST ".class" +#define BLD_SHLIB_FOR_HOST "" +#define BLD_SHOBJ_FOR_HOST ".so" +#define BLD_TOOLS_DIR "${BLD_TOP}/bin" +#define BLD_BIN_DIR "${BLD_TOP}/bin" +#define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" +#define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" + +#ifndef MAX_FLOAT +#define MAX_FLOAT 3.40282347e+38F +#endif diff --git a/source4/lib/appweb/ejs/config.mk b/source4/lib/appweb/ejs/config.mk new file mode 100644 index 0000000000..f2c0e62f1e --- /dev/null +++ b/source4/lib/appweb/ejs/config.mk @@ -0,0 +1,13 @@ +####################### +# Start SUBSYSTEM EJS +[SUBSYSTEM::EJS] +ADD_OBJ_FILES = \ + lib/ejs/ejsLib.o \ + lib/ejs/ejsLex.o \ + lib/ejs/ejsParser.o \ + lib/ejs/ejsProcs.o \ + lib/ejs/miniMpr.o \ + lib/ejs/var.o +NOPROTO=YES +# End SUBSYSTEM EJS +####################### diff --git a/source4/lib/appweb/ejs/ejs.h b/source4/lib/appweb/ejs/ejs.h new file mode 100644 index 0000000000..f1d2bb4c6e --- /dev/null +++ b/source4/lib/appweb/ejs/ejs.h @@ -0,0 +1,133 @@ +/* + * @file ejs.h + * @brief Primary Embedded Javascript (ECMAScript) header. + * @overview This Embedded Javascript (EJS) header defines the + * public API. This API should only be used by those directly + * using EJS without using Embedded Server Pages (ESP). ESP + * wraps all relevant APIs to expose a single consistent API. + * \n\n + * This API requires the mpr/var.h facilities to create and + * manage objects and properties. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#ifndef _h_EJS +#define _h_EJS 1 + +#include "miniMpr.h" +#include "var.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/********************************* Prototypes *********************************/ + +typedef MprVarHandle EjsId; +typedef MprVarHandle EjsHandle; + +/* + * Multithreaded lock routines + */ +typedef void (*EjsLock)(void *lockData); +typedef void (*EjsUnlock)(void *lockData); + +/********************************* Prototypes *********************************/ +/* + * Module management + */ +extern int ejsOpen(EjsLock lock, EjsUnlock unlock, void *lockData); +extern void ejsClose(void); +extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); +extern void ejsCloseEngine(EjsId eid); + +/* + * Evaluation functions + */ +extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); +extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, + char **emsg); +extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, + MprArray *args); + +/* + * Composite variable get / set routines. Can also use the MPR property + * routines on an object variable. + */ +extern MprVar ejsCreateObj(const char *name, int hashSize); +extern MprVar ejsCreateArray(const char *name, int hashSize); +extern bool ejsDestroyVar(MprVar *obj); +extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, + bool copyRef); +extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); +extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); +extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); +extern int ejsDeleteVar(EjsId eid, const char *var); + +extern MprVar *ejsGetLocalObject(EjsId eid); +extern MprVar *ejsGetGlobalObject(EjsId eid); + +/* + * Function routines + */ +extern void ejsDefineFunction(EjsId eid, const char *functionName, + char *args, char *body); +extern void ejsDefineCFunction(EjsId eid, const char *functionName, + MprCFunction fn, void *thisPtr, int flags); +extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, + MprStringCFunction fn, void *thisPtr, int flags); +extern void *ejsGetThisPtr(EjsId eid); +extern MprVar *ejsGetReturnValue(EjsId eid); +extern int ejsGetLineNumber(EjsId eid); +extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); +extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) + PRINTF_ATTRIBUTE(2,3); +extern void ejsSetReturnValue(EjsId eid, MprVar value); +extern void ejsSetReturnString(EjsId eid, const char *str); + +#ifdef __cplusplus +} +#endif +#endif /* _h_EJS */ + +/*****************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/ejsInternal.h b/source4/lib/appweb/ejs/ejsInternal.h new file mode 100644 index 0000000000..3bf99d88b9 --- /dev/null +++ b/source4/lib/appweb/ejs/ejsInternal.h @@ -0,0 +1,293 @@ +/* + * @file ejsInternal.h + * @brief Private header for Embedded Javascript (ECMAScript) + * @overview This Embedded Javascript header defines the private Embedded + * Javascript internal structures. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************* Includes ***********************************/ + +#ifndef _h_EJS_INTERNAL +#define _h_EJS_INTERNAL 1 + +#include "ejs.h" + +/********************************** Defines ***********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Constants + */ + +#if BLD_FEATURE_SQUEEZE + #define EJS_PARSE_INCR 256 /* Growth factor */ + #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ + #define EJS_MAX_ID 128 /* Maximum ID length */ + #define EJS_OBJ_HASH_SIZE 13 /* Object hash table size */ + #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ + #define EJS_LIST_INCR 8 /* Growth increment for lists */ +#else + #define EJS_PARSE_INCR 1024 /* Growth factor */ + #define EJS_MAX_RECURSE 100 /* Sanity for maximum recursion */ + #define EJS_MAX_ID 256 /* Maximum ID length */ + #define EJS_OBJ_HASH_SIZE 29 /* Object hash table size */ + #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ + #define EJS_LIST_INCR 16 /* Growth increment for lists */ +#endif +#define EJS_TOKEN_STACK 4 /* Put back token stack */ + +/* + * Lexical analyser tokens + */ +#define EJS_TOK_ERR -1 /* Any error */ +#define EJS_TOK_LPAREN 1 /* ( */ +#define EJS_TOK_RPAREN 2 /* ) */ +#define EJS_TOK_IF 3 /* if */ +#define EJS_TOK_ELSE 4 /* else */ +#define EJS_TOK_LBRACE 5 /* { */ +#define EJS_TOK_RBRACE 6 /* } */ +#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ +#define EJS_TOK_EXPR 8 /* +, -, /, % */ +#define EJS_TOK_SEMI 9 /* ; */ +#define EJS_TOK_LITERAL 10 /* literal string */ +#define EJS_TOK_FUNCTION_NAME 11 /* functionName */ +#define EJS_TOK_NEWLINE 12 /* newline white space */ +#define EJS_TOK_ID 13 /* Identifier */ +#define EJS_TOK_EOF 14 /* End of script */ +#define EJS_TOK_COMMA 15 /* Comma */ +#define EJS_TOK_VAR 16 /* var */ +#define EJS_TOK_ASSIGNMENT 17 /* = */ +#define EJS_TOK_FOR 18 /* for */ +#define EJS_TOK_INC_DEC 19 /* ++, -- */ +#define EJS_TOK_RETURN 20 /* return */ +#define EJS_TOK_PERIOD 21 /* . */ +#define EJS_TOK_LBRACKET 22 /* [ */ +#define EJS_TOK_RBRACKET 23 /* ] */ +#define EJS_TOK_NEW 24 /* new */ +#define EJS_TOK_DELETE 25 /* delete */ +#define EJS_TOK_IN 26 /* in */ +#define EJS_TOK_FUNCTION 27 /* function */ +#define EJS_TOK_NUMBER 28 /* Number */ + +/* + * Expression operators + */ +#define EJS_EXPR_LESS 1 /* < */ +#define EJS_EXPR_LESSEQ 2 /* <= */ +#define EJS_EXPR_GREATER 3 /* > */ +#define EJS_EXPR_GREATEREQ 4 /* >= */ +#define EJS_EXPR_EQ 5 /* == */ +#define EJS_EXPR_NOTEQ 6 /* != */ +#define EJS_EXPR_PLUS 7 /* + */ +#define EJS_EXPR_MINUS 8 /* - */ +#define EJS_EXPR_DIV 9 /* / */ +#define EJS_EXPR_MOD 10 /* % */ +#define EJS_EXPR_LSHIFT 11 /* << */ +#define EJS_EXPR_RSHIFT 12 /* >> */ +#define EJS_EXPR_MUL 13 /* * */ +#define EJS_EXPR_ASSIGNMENT 14 /* = */ +#define EJS_EXPR_INC 15 /* ++ */ +#define EJS_EXPR_DEC 16 /* -- */ +#define EJS_EXPR_BOOL_COMP 17 /* ! */ + +/* + * Conditional operators + */ +#define EJS_COND_AND 1 /* && */ +#define EJS_COND_OR 2 /* || */ +#define EJS_COND_NOT 3 /* ! */ + +/* + * States + */ +#define EJS_STATE_ERR -1 /* Error state */ +#define EJS_STATE_EOF 1 /* End of file */ +#define EJS_STATE_COND 2 /* Parsing a "(conditional)" stmt */ +#define EJS_STATE_COND_DONE 3 +#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ +#define EJS_STATE_RELEXP_DONE 5 +#define EJS_STATE_EXPR 6 /* Parsing an expression */ +#define EJS_STATE_EXPR_DONE 7 +#define EJS_STATE_STMT 8 /* Parsing General statement */ +#define EJS_STATE_STMT_DONE 9 +#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ +#define EJS_STATE_ARG_LIST 11 /* Function arg list */ +#define EJS_STATE_ARG_LIST_DONE 12 +#define EJS_STATE_DEC_LIST 16 /* Declaration list */ +#define EJS_STATE_DEC_LIST_DONE 17 +#define EJS_STATE_DEC 18 /* Declaration statement */ +#define EJS_STATE_DEC_DONE 19 +#define EJS_STATE_RET 20 /* Return statement */ + +#define EJS_STATE_BEGIN EJS_STATE_STMT + +/* + * General parsing flags. + */ +#define EJS_FLAGS_EXE 0x1 /* Execute statements */ +#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ +#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ +#define EJS_FLAGS_CREATE 0x8 /* Create var */ +#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ +#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ +#define EJS_FLAGS_FOREACH 0x40 /* In foreach */ +#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ +#define EJS_FLAGS_EXIT 0x100 /* Must exit */ + +/* + * Putback token + */ + +typedef struct EjsToken { + char *token; /* Token string */ + int id; /* Token ID */ +} EjsToken; + +/* + * EJ evaluation block structure + */ +typedef struct ejEval { + EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ + int putBackIndex; /* Top of stack index */ + MprStr line; /* Current line */ + int lineLength; /* Current line length */ + int lineNumber; /* Parse line number */ + int lineColumn; /* Column in line */ + MprStr script; /* Input script for parsing */ + char *scriptServp; /* Next token in the script */ + int scriptSize; /* Length of script */ + MprStr tokbuf; /* Current token */ + char *tokEndp; /* Pointer past end of token */ + char *tokServp; /* Pointer to next token char */ + int tokSize; /* Size of token buffer */ +} EjsInput; + +/* + * Function call structure + */ +typedef struct { + MprArray *args; /* Args for function */ + MprVar *fn; /* Function definition */ + char *procName; /* Function name */ +} EjsProc; + +/* + * Per EJS structure + */ +typedef struct ej { + EjsHandle altHandle; /* alternate callback handle */ + MprVar *currentObj; /* Ptr to current object */ + MprVar *currentProperty; /* Ptr to current property */ + EjsId eid; /* Halloc handle */ + char *error; /* Error message */ + int exitStatus; /* Status to exit() */ + int flags; /* Flags */ + MprArray *frames; /* List of variable frames */ + MprVar *global; /* Global object */ + EjsInput *input; /* Input evaluation block */ + MprVar *local; /* Local object */ + EjsHandle primaryHandle; /* primary callback handle */ + EjsProc *proc; /* Current function */ + MprVar result; /* Variable result */ + void *thisPtr; /* C++ ptr for functions */ + int tid; /* Current token id */ + char *token; /* Pointer to token string */ + MprVar tokenNumber; /* Parsed number */ +} Ejs; + +typedef int EjsBlock; /* Scope block id */ + +/* + * Function callback when using Alternate handles. + */ +typedef int (*EjsAltStringCFunction)(EjsHandle userHandle, EjsHandle altHandle, + int argc, char **argv); +typedef int (*EjsAltCFunction)(EjsHandle userHandle, EjsHandle altHandle, + int argc, MprVar **argv); + +/******************************** Prototypes **********************************/ +/* + * Ejs Lex + */ +extern int ejsLexOpenScript(Ejs* ep, char *script); +extern void ejsLexCloseScript(Ejs* ep); +extern int ejsInitInputState(EjsInput *ip); +extern void ejsLexSaveInputState(Ejs* ep, EjsInput* state); +extern void ejsLexFreeInputState(Ejs* ep, EjsInput* state); +extern void ejsLexRestoreInputState(Ejs* ep, EjsInput* state); +extern int ejsLexGetToken(Ejs* ep, int state); +extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); + +/* + * Parsing + */ +extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, + int flags); +extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, + char *property, int flags); +extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, + MprVar **varValue, int flags); +extern int ejsParse(Ejs *ep, int state, int flags); +extern Ejs *ejsPtr(EjsId eid); +extern void ejsSetExitStatus(int eid, int status); +extern void ejsSetFlags(int orFlags, int andFlags); + +/* + * Create variable scope blocks + */ +extern EjsBlock ejsOpenBlock(EjsId eid); +extern int ejsCloseBlock(EjsId eid, EjsBlock vid); +extern int ejsEvalBlock(EjsId eid, char *script, MprVar *v, char **err); +extern int ejsDefineStandardProperties(MprVar *objVar); + +/* + * Error handling + */ +extern void ejsError(Ejs *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +#ifdef __cplusplus +} +#endif +#endif /* _h_EJS_INTERNAL */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/ejsLex.c b/source4/lib/appweb/ejs/ejsLex.c new file mode 100644 index 0000000000..a5f15c2979 --- /dev/null +++ b/source4/lib/appweb/ejs/ejsLex.c @@ -0,0 +1,913 @@ +/* + * @file ejsLex.c + * @brief EJS Lexical Analyser + * @overview EJS lexical analyser. This implementes a lexical analyser + * for a subset of the JavaScript language. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ + +static int getLexicalToken(Ejs *ep, int state); +static int tokenAddChar(Ejs *ep, int c); +static int inputGetc(Ejs *ep); +static void inputPutback(Ejs *ep, int c); +static int charConvert(Ejs *ep, int base, int maxDig); + +/************************************* Code ***********************************/ +/* + * Open a new input script + */ + +int ejsLexOpenScript(Ejs *ep, char *script) +{ + EjsInput *ip; + + mprAssert(ep); + mprAssert(script); + + if ((ep->input = mprMalloc(sizeof(EjsInput))) == NULL) { + return -1; + } + ip = ep->input; + memset(ip, 0, sizeof(*ip)); + +/* + * Create the parse token buffer and script buffer + */ + ip->tokbuf = mprMalloc(EJS_PARSE_INCR); + ip->tokSize = EJS_PARSE_INCR; + ip->tokServp = ip->tokbuf; + ip->tokEndp = ip->tokbuf; + + ip->script = mprStrdup(script); + ip->scriptSize = strlen(script); + ip->scriptServp = ip->script; + + ip->lineNumber = 1; + ip->lineLength = 0; + ip->lineColumn = 0; + ip->line = NULL; + + ip->putBackIndex = -1; + + return 0; +} + +/******************************************************************************/ +/* + * Close the input script + */ + +void ejsLexCloseScript(Ejs *ep) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + + ip = ep->input; + mprAssert(ip); + + for (i = 0; i < EJS_TOKEN_STACK; i++) { + mprFree(ip->putBack[i].token); + ip->putBack[i].token = 0; + } + + mprFree(ip->line); + mprFree(ip->tokbuf); + mprFree(ip->script); + + mprFree(ip); +} + +/******************************************************************************/ +/* + * Initialize an input state structure + */ + +int ejsInitInputState(EjsInput *ip) +{ + mprAssert(ip); + + memset(ip, 0, sizeof(*ip)); + ip->putBackIndex = -1; + + return 0; +} +/******************************************************************************/ +/* + * Save the input state + */ + +void ejsLexSaveInputState(Ejs *ep, EjsInput *state) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + + ip = ep->input; + mprAssert(ip); + + *state = *ip; + + for (i = 0; i < ip->putBackIndex; i++) { + state->putBack[i].token = mprStrdup(ip->putBack[i].token); + state->putBack[i].id = ip->putBack[i].id; + } + for (; i < EJS_TOKEN_STACK; i++) { + state->putBack[i].token = 0; + } + + state->line = mprMalloc(ip->lineLength); + mprStrcpy(state->line, ip->lineLength, ip->line); + + state->lineColumn = ip->lineColumn; + state->lineNumber = ip->lineNumber; + state->lineLength = ip->lineLength; +} + +/******************************************************************************/ +/* + * Restore the input state + */ + +void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) +{ + EjsInput *ip; + int i; + + mprAssert(ep); + mprAssert(state); + + ip = ep->input; + mprAssert(ip); + + ip->tokbuf = state->tokbuf; + ip->tokServp = state->tokServp; + ip->tokEndp = state->tokEndp; + ip->tokSize = state->tokSize; + + ip->script = state->script; + ip->scriptServp = state->scriptServp; + ip->scriptSize = state->scriptSize; + + ip->putBackIndex = state->putBackIndex; + for (i = 0; i < ip->putBackIndex; i++) { + mprFree(ip->putBack[i].token); + ip->putBack[i].id = state->putBack[i].id; + ip->putBack[i].token = mprStrdup(state->putBack[i].token); + } + + mprFree(ip->line); + ip->line = mprMalloc(state->lineLength); + mprStrcpy(ip->line, state->lineLength, state->line); + + ip->lineColumn = state->lineColumn; + ip->lineNumber = state->lineNumber; + ip->lineLength = state->lineLength; +} + +/******************************************************************************/ +/* + * Free a saved input state + */ + +void ejsLexFreeInputState(Ejs *ep, EjsInput *state) +{ + int i; + + mprAssert(ep); + mprAssert(state); + + for (i = 0; i < EJS_TOKEN_STACK; i++) { + mprFree(state->putBack[i].token); + } + state->putBackIndex = -1; + mprFree(state->line); + state->lineLength = 0; + state->lineColumn = 0; +} + +/******************************************************************************/ +/* + * Get the next EJS token + */ + +int ejsLexGetToken(Ejs *ep, int state) +{ + mprAssert(ep); + + ep->tid = getLexicalToken(ep, state); + return ep->tid; +} + +/******************************************************************************/ + +/* + * Check for reserved words "if", "else", "var", "for", "foreach", + * "delete", "function", and "return". "new", "in" and "function" + * done below. "true", "false", "null", "undefined" are handled + * as global objects. + * + * Other reserved words not supported: + * "break", "case", "catch", "continue", "default", "do", + * "finally", "instanceof", "switch", "this", "throw", "try", + * "typeof", "while", "with" + * + * ECMA extensions reserved words (not supported): + * "abstract", "boolean", "byte", "char", "class", "const", + * "debugger", "double", "enum", "export", "extends", + * "final", "float", "goto", "implements", "import", "int", + * "interface", "long", "native", "package", "private", + * "protected", "public", "short", "static", "super", + * "synchronized", "throws", "transient", "volatile" + */ + +static int checkReservedWord(Ejs *ep, int state, int c, int tid) +{ + if (state == EJS_STATE_STMT) { + if (strcmp(ep->token, "if") == 0) { + inputPutback(ep, c); + return EJS_TOK_IF; + } else if (strcmp(ep->token, "else") == 0) { + inputPutback(ep, c); + return EJS_TOK_ELSE; + } else if (strcmp(ep->token, "var") == 0) { + inputPutback(ep, c); + return EJS_TOK_VAR; + } else if (strcmp(ep->token, "for") == 0) { + inputPutback(ep, c); + return EJS_TOK_FOR; + } else if (strcmp(ep->token, "delete") == 0) { + inputPutback(ep, c); + return EJS_TOK_DELETE; + } else if (strcmp(ep->token, "function") == 0) { + inputPutback(ep, c); + return EJS_TOK_FUNCTION; + } else if (strcmp(ep->token, "return") == 0) { + if ((c == ';') || (c == '(')) { + inputPutback(ep, c); + } + return EJS_TOK_RETURN; + } + } else if (state == EJS_STATE_EXPR) { + if (strcmp(ep->token, "new") == 0) { + inputPutback(ep, c); + return EJS_TOK_NEW; + } else if (strcmp(ep->token, "in") == 0) { + inputPutback(ep, c); + return EJS_TOK_IN; + } else if (strcmp(ep->token, "function") == 0) { + inputPutback(ep, c); + return EJS_TOK_FUNCTION; + } + } + return tid; +} + +/******************************************************************************/ +/* + * Get the next EJS token + */ + +static int getLexicalToken(Ejs *ep, int state) +{ + MprType type; + EjsInput *ip; + int done, tid, c, quote, style, idx; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + ep->tid = -1; + tid = -1; + type = BLD_FEATURE_NUM_TYPE_ID; + + /* + * Use a putback tokens first. Don't free strings as caller needs access. + */ + if (ip->putBackIndex >= 0) { + idx = ip->putBackIndex; + tid = ip->putBack[idx].id; + ep->token = (char*) ip->putBack[idx].token; + tid = checkReservedWord(ep, state, 0, tid); + ip->putBackIndex--; + return tid; + } + ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; + *ip->tokServp = '\0'; + + if ((c = inputGetc(ep)) < 0) { + return EJS_TOK_EOF; + } + + /* + * Main lexical analyser + */ + for (done = 0; !done; ) { + switch (c) { + case -1: + return EJS_TOK_EOF; + + case ' ': + case '\t': + case '\r': + do { + if ((c = inputGetc(ep)) < 0) + break; + } while (c == ' ' || c == '\t' || c == '\r'); + break; + + case '\n': + return EJS_TOK_NEWLINE; + + case '(': + tokenAddChar(ep, c); + return EJS_TOK_LPAREN; + + case ')': + tokenAddChar(ep, c); + return EJS_TOK_RPAREN; + + case '[': + tokenAddChar(ep, c); + return EJS_TOK_LBRACKET; + + case ']': + tokenAddChar(ep, c); + return EJS_TOK_RBRACKET; + + case '.': + tokenAddChar(ep, c); + return EJS_TOK_PERIOD; + + case '{': + tokenAddChar(ep, c); + return EJS_TOK_LBRACE; + + case '}': + tokenAddChar(ep, c); + return EJS_TOK_RBRACE; + + case '+': + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '+' ) { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_PLUS); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_INC); + return EJS_TOK_INC_DEC; + + case '-': + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '-' ) { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_MINUS); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_DEC); + return EJS_TOK_INC_DEC; + + case '*': + tokenAddChar(ep, EJS_EXPR_MUL); + return EJS_TOK_EXPR; + + case '%': + tokenAddChar(ep, EJS_EXPR_MOD); + return EJS_TOK_EXPR; + + case '/': + /* + * Handle the division operator and comments + */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c != '*' && c != '/') { + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_DIV); + return EJS_TOK_EXPR; + } + style = c; + /* + * Eat comments. Both C and C++ comment styles are supported. + */ + while (1) { + if ((c = inputGetc(ep)) < 0) { + if (style == '/') { + return EJS_TOK_EOF; + } + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '\n' && style == '/') { + break; + } else if (c == '*') { + c = inputGetc(ep); + if (style == '/') { + if (c == '\n') { + break; + } + } else { + if (c == '/') { + break; + } + } + } + } + /* + * Continue looking for a token, so get the next character + */ + if ((c = inputGetc(ep)) < 0) { + return EJS_TOK_EOF; + } + break; + + case '<': /* < and <= */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '<') { + tokenAddChar(ep, EJS_EXPR_LSHIFT); + return EJS_TOK_EXPR; + } else if (c == '=') { + tokenAddChar(ep, EJS_EXPR_LESSEQ); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_LESS); + inputPutback(ep, c); + return EJS_TOK_EXPR; + + case '>': /* > and >= */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '>') { + tokenAddChar(ep, EJS_EXPR_RSHIFT); + return EJS_TOK_EXPR; + } else if (c == '=') { + tokenAddChar(ep, EJS_EXPR_GREATEREQ); + return EJS_TOK_EXPR; + } + tokenAddChar(ep, EJS_EXPR_GREATER); + inputPutback(ep, c); + return EJS_TOK_EXPR; + + case '=': /* "==" */ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '=') { + tokenAddChar(ep, EJS_EXPR_EQ); + return EJS_TOK_EXPR; + } + inputPutback(ep, c); + return EJS_TOK_ASSIGNMENT; + + case '!': /* "!=" or "!"*/ + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + if (c == '=') { + tokenAddChar(ep, EJS_EXPR_NOTEQ); + return EJS_TOK_EXPR; + } + inputPutback(ep, c); + tokenAddChar(ep, EJS_EXPR_BOOL_COMP); + return EJS_TOK_EXPR; + + case ';': + tokenAddChar(ep, c); + return EJS_TOK_SEMI; + + case ',': + tokenAddChar(ep, c); + return EJS_TOK_COMMA; + + case '|': /* "||" */ + if ((c = inputGetc(ep)) < 0 || c != '|') { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + tokenAddChar(ep, EJS_COND_OR); + return EJS_TOK_LOGICAL; + + case '&': /* "&&" */ + if ((c = inputGetc(ep)) < 0 || c != '&') { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + tokenAddChar(ep, EJS_COND_AND); + return EJS_TOK_LOGICAL; + + case '\"': /* String quote */ + case '\'': + quote = c; + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Syntax Error"); + return EJS_TOK_ERR; + } + + while (c != quote) { + /* + * Check for escape sequence characters + */ + if (c == '\\') { + c = inputGetc(ep); + + if (isdigit(c)) { + /* + * Octal support, \101 maps to 65 = 'A'. Put first + * char back so converter will work properly. + */ + inputPutback(ep, c); + c = charConvert(ep, 8, 3); + + } else { + switch (c) { + case 'n': + c = '\n'; break; + case 'b': + c = '\b'; break; + case 'f': + c = '\f'; break; + case 'r': + c = '\r'; break; + case 't': + c = '\t'; break; + case 'x': + /* + * Hex support, \x41 maps to 65 = 'A' + */ + c = charConvert(ep, 16, 2); + break; + case 'u': + /* + * Unicode support, \x0401 maps to 65 = 'A' + */ + c = charConvert(ep, 16, 2); + c = c*16 + charConvert(ep, 16, 2); + + break; + case '\'': + case '\"': + case '\\': + break; + default: + ejsError(ep, "Invalid Escape Sequence"); + return EJS_TOK_ERR; + } + } + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + } else { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + } + if ((c = inputGetc(ep)) < 0) { + ejsError(ep, "Unmatched Quote"); + return EJS_TOK_ERR; + } + } + return EJS_TOK_LITERAL; + + case '0': + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + if (tolower(c) == 'x') { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + } + if (! isdigit(c)) { +#if BLD_FEATURE_FLOATING_POINT + if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { + /* Fall through */ + type = MPR_TYPE_FLOAT; + } else +#endif + { + mprDestroyVar(&ep->tokenNumber); + ep->tokenNumber = mprParseVar(ep->token, type); + inputPutback(ep, c); + return EJS_TOK_NUMBER; + } + } + /* Fall through to get more digits */ + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + if (tokenAddChar(ep, c) < 0) { + return EJS_TOK_ERR; + } + if ((c = inputGetc(ep)) < 0) { + break; + } +#if BLD_FEATURE_FLOATING_POINT + if (c == '.' || tolower(c) == 'e' || tolower(c) == 'f') { + type = MPR_TYPE_FLOAT; + } + } while (isdigit(c) || c == '.' || tolower(c) == 'e' || tolower(c) == 'f' || + ((type == MPR_TYPE_FLOAT) && (c == '+' || c == '-'))); +#else + } while (isdigit(c)); +#endif + + mprDestroyVar(&ep->tokenNumber); + ep->tokenNumber = mprParseVar(ep->token, type); + inputPutback(ep, c); + return EJS_TOK_NUMBER; + + default: + /* + * Identifiers or a function names + */ + while (1) { + if (c == '\\') { + if ((c = inputGetc(ep)) < 0) { + break; + } + if (c == '\n' || c == '\r') { + break; + } + } else if (tokenAddChar(ep, c) < 0) { + break; + } + if ((c = inputGetc(ep)) < 0) { + break; + } + if (!isalnum(c) && c != '$' && c != '_' && c != '\\') { + break; + } + } + if (*ep->token == '\0') { + c = inputGetc(ep); + break; + } + if (! isalpha((int) *ep->token) && *ep->token != '$' && + *ep->token != '_') { + ejsError(ep, "Invalid identifier %s", ep->token); + return EJS_TOK_ERR; + } + + tid = checkReservedWord(ep, state, c, EJS_TOK_ID); + if (tid != EJS_TOK_ID) { + return tid; + } + + /* + * Skip white space after token to find out whether this is + * a function or not. + */ + while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { + if ((c = inputGetc(ep)) < 0) + break; + } + + tid = EJS_TOK_ID; + done++; + } + } + + /* + * Putback the last extra character for next time + */ + inputPutback(ep, c); + return tid; +} + +/******************************************************************************/ +/* + * Convert a hex or octal character back to binary, return original char if + * not a hex digit + */ + +static int charConvert(Ejs *ep, int base, int maxDig) +{ + int i, c, lval, convChar; + + lval = 0; + for (i = 0; i < maxDig; i++) { + if ((c = inputGetc(ep)) < 0) { + break; + } + /* + * Initialize to out of range value + */ + convChar = base; + if (isdigit(c)) { + convChar = c - '0'; + } else if (c >= 'a' && c <= 'f') { + convChar = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + convChar = c - 'A' + 10; + } + /* + * If unexpected character then return it to buffer. + */ + if (convChar >= base) { + inputPutback(ep, c); + break; + } + lval = (lval * base) + convChar; + } + return lval; +} + +/******************************************************************************/ +/* + * Putback the last token read. Accept at most one push back token. + */ + +void ejsLexPutbackToken(Ejs *ep, int tid, char *string) +{ + EjsInput *ip; + int idx; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + ip->putBackIndex += 1; + idx = ip->putBackIndex; + ip->putBack[idx].id = tid; + + if (ip->putBack[idx].token) { + if (ip->putBack[idx].token == string) { + return; + } + mprFree(ip->putBack[idx].token); + } + ip->putBack[idx].token = mprStrdup(string); +} + +/******************************************************************************/ +/* + * Add a character to the token buffer + */ + +static int tokenAddChar(Ejs *ep, int c) +{ + EjsInput *ip; + uchar *oldbuf; + + mprAssert(ep); + ip = ep->input; + mprAssert(ip); + + if (ip->tokEndp >= &ip->tokbuf[ip->tokSize - 1]) { + ip->tokSize += EJS_PARSE_INCR; + oldbuf = ip->tokbuf; + ip->tokbuf = mprRealloc(ip->tokbuf, ip->tokSize); + if (ip->tokbuf == 0) { + ejsError(ep, "Token too big"); + return -1; + } + ip->tokEndp += (int) ((uchar*) ip->tokbuf - oldbuf); + ip->tokServp += (int) ((uchar*) ip->tokbuf - oldbuf); + ep->token += (int) ((uchar*) ip->tokbuf - oldbuf); + } + *ip->tokEndp++ = c; + *ip->tokEndp = '\0'; + + return 0; +} + +/******************************************************************************/ +/* + * Get another input character + */ + +static int inputGetc(Ejs *ep) +{ + EjsInput *ip; + int c; + + mprAssert(ep); + ip = ep->input; + + if (ip->scriptSize <= 0) { + return -1; + } + + c = (uchar) (*ip->scriptServp++); + ip->scriptSize--; + + /* + * For debugging, accumulate the line number and the currenly parsed line + */ + if (c == '\n') { +#if BLD_DEBUG && 0 + if (ip->lineColumn > 0) { + printf("PARSED: %s\n", ip->line); + } +#endif + ip->lineNumber++; + ip->lineColumn = 0; + } else { + if ((ip->lineColumn + 2) >= ip->lineLength) { + ip->lineLength += 80; + ip->line = mprRealloc(ip->line, ip->lineLength * sizeof(char)); + } + ip->line[ip->lineColumn++] = c; + ip->line[ip->lineColumn] = '\0'; + } + return c; +} + +/******************************************************************************/ +/* + * Putback a character onto the input queue + */ + +static void inputPutback(Ejs *ep, int c) +{ + EjsInput *ip; + + mprAssert(ep); + + if (c != 0) { + ip = ep->input; + *--ip->scriptServp = c; + ip->scriptSize++; + ip->lineColumn--; + ip->line[ip->lineColumn] = '\0'; + } +} + +/******************************************************************************/ + +#else +void ejsLexDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c new file mode 100644 index 0000000000..caae5b6495 --- /dev/null +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -0,0 +1,1061 @@ +/* + * @file ejs.c + * @brief Embedded JavaScript (EJS) + * @overview Main module interface logic. + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "ejsInternal.h" + +#if BLD_FEATURE_EJS + +/********************************** Local Data ********************************/ + +/* + * These fields must be locked before any access when multithreaded + */ +static MprVar master; /* Master object */ +static MprArray *ejsList; /* List of ej handles */ + +#if BLD_FEATURE_MULTITHREAD +static EjsLock lock; +static EjsUnlock unlock; +static void *lockData; +#define ejsLock() if (lock) { (lock)(lockData); } else +#define ejsUnlock() if (unlock) { (unlock)(lockData); } else +#else +#define ejsLock() +#define ejsUnlock() +#endif + +/****************************** Forward Declarations **************************/ + +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); + +/************************************* Code ***********************************/ +/* + * Initialize the EJ subsystem + */ + +int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) +{ + MprVar *np; + +#if BLD_FEATURE_MULTITHREAD + if (lockFn) { + lock = lockFn; + unlock = unlockFn; + lockData = data; + } +#endif + ejsLock(); + + /* + * Master is the top level object (above global). It is used to clone its + * contents into the global scope for each. This is never visible to the + * user, so don't use ejsCreateObj(). + */ + master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); + if (master.type == MPR_TYPE_UNDEFINED) { + ejsUnlock(); + return MPR_ERR_CANT_ALLOCATE; + } + + ejsList = mprCreateArray(); + ejsDefineStandardProperties(&master); + + /* + * Make these objects immutable + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprSetVarReadonly(np, 1); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + ejsUnlock(); + return 0; +} + +/******************************************************************************/ + +void ejsClose() +{ + ejsLock(); + mprDestroyArray(ejsList); + mprDestroyVar(&master); + ejsUnlock(); +} + +/******************************************************************************/ +/* + * Create and initialize an EJS engine + */ + +EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) +{ + MprVar *np; + Ejs *ep; + + ep = mprMalloc(sizeof(Ejs)); + if (ep == 0) { + return (EjsId) -1; + } + memset(ep, 0, sizeof(Ejs)); + + ejsLock(); + ep->eid = (EjsId) mprAddToArray(ejsList, ep); + ejsUnlock(); + + /* + * Create array of local variable frames + */ + ep->frames = mprCreateArray(); + if (ep->frames == 0) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + ep->primaryHandle = primaryHandle; + ep->altHandle = altHandle; + + /* + * Create first frame: global variables + */ + ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); + if (ep->global->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->global); + + /* + * Create first local variable frame + */ + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); + if (ep->local->type == MPR_TYPE_UNDEFINED) { + ejsCloseEngine(ep->eid); + return (EjsId) -1; + } + mprAddToArray(ep->frames, ep->local); + + /* + * Clone all master variables into the global frame. This does a + * reference copy. + * + * ejsDefineStandardProperties(ep->global); + */ + np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); + while (np) { + mprCreateProperty(ep->global, np->name, np); + np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | + MPR_ENUM_DATA); + } + + mprCreateProperty(ep->global, "global", ep->global); + mprCreateProperty(ep->global, "this", ep->global); + mprCreateProperty(ep->local, "local", ep->local); + + return ep->eid; +} + +/******************************************************************************/ +/* + * Close an EJS instance + */ + +void ejsCloseEngine(EjsId eid) +{ + Ejs *ep; + MprVar *vp; + void **handles; + int i; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + + mprFree(ep->error); + mprDestroyVar(&ep->result); + mprDestroyVar(&ep->tokenNumber); + + mprDeleteProperty(ep->local, "local"); + mprDeleteProperty(ep->global, "this"); + mprDeleteProperty(ep->global, "global"); + + handles = ep->frames->handles; + for (i = 0; i < ep->frames->max; i++) { + vp = handles[i]; + if (vp) { +#if BLD_DEBUG + if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { + mprLog(7, "ejsCloseEngine: %s has ref count %d\n", + vp->name, vp->properties->refCount); + } +#endif + mprDestroyVar(vp); + mprFree(vp); + mprRemoveFromArray(ep->frames, i); + } + } + mprDestroyArray(ep->frames); + + ejsLock(); + mprRemoveFromArray(ejsList, (int) ep->eid); + ejsUnlock(); + + mprFree(ep); +} + +/******************************************************************************/ +/* + * Evaluate an EJS script file + */ + +int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) +{ + struct stat sbuf; + Ejs *ep; + char *script; + int rc, fd; + + mprAssert(path && *path); + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + goto error; + } + + if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { + ejsError(ep, "Can't open %s\n", path); + goto error; + } + + if (stat(path, &sbuf) < 0) { + close(fd); + ejsError(ep, "Cant stat %s", path); + goto error; + } + + if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { + close(fd); + ejsError(ep, "Cant malloc %d", (int) sbuf.st_size); + goto error; + } + + if (read(fd, script, sbuf.st_size) != (int) sbuf.st_size) { + close(fd); + mprFree(script); + ejsError(ep, "Error reading %s", path); + goto error; + } + + script[sbuf.st_size] = '\0'; + close(fd); + + rc = ejsEvalBlock(eid, script, result, emsg); + mprFree(script); + + return rc; + +/* + * Error return + */ +error: + *emsg = mprStrdup(ep->error); + return -1; +} + +/******************************************************************************/ +/* + * Create a new variable scope block. This pushes the old local frame down + * the stack and creates a new local variables frame. + */ + +int ejsOpenBlock(EjsId eid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); + *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); + + mprCreateProperty(ep->local, "local", ep->local); + + return mprAddToArray(ep->frames, ep->local); +} + +/******************************************************************************/ +/* + * Close a variable scope block opened via ejsOpenBlock. Pop back the old + * local variables frame. + */ + +int ejsCloseBlock(EjsId eid, int fid) +{ + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + /* + * Must remove self-references before destroying "local" + */ + mprDeleteProperty(ep->local, "local"); + + mprDestroyVar(ep->local); + mprFree(ep->local); + + mprRemoveFromArray(ep->frames, fid); + ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; + + return 0; +} + +/******************************************************************************/ +/* + * Create a new variable scope block and evaluate a script. All frames + * created during this context will be automatically deleted when complete. + * vp and emsg are optional. i.e. created local variables will be discarded + * when this routine returns. + */ + +int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + int rc, fid; + + mprAssert(script); + + fid = ejsOpenBlock(eid); + rc = ejsEvalScript(eid, script, vp, emsg); + ejsCloseBlock(eid, fid); + + return rc; +} + +/******************************************************************************/ +/* + * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" + * by EJ and the caller must not free it. Returns -1 on errors and zero + * for success. On errors, emsg will be set to the reason. The caller must + * free emsg. + */ + +int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) +{ + Ejs *ep; + EjsInput *oldBlock; + int state; + void *endlessLoopTest; + int loopCounter; + + if (emsg) { + *emsg = NULL; + } + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + mprDestroyVar(&ep->result); + + if (script == 0) { + return 0; + } + + /* + * Allocate a new evaluation block, and save the old one + */ + oldBlock = ep->input; + ejsLexOpenScript(ep, script); + + /* + * Do the actual parsing and evaluation + */ + loopCounter = 0; + endlessLoopTest = NULL; + ep->exitStatus = 0; + + do { + state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); + + if (state == EJS_STATE_RET) { + state = EJS_STATE_EOF; + } + /* + * Stuck parser and endless recursion protection. + */ + if (endlessLoopTest == ep->input->scriptServp) { + if (loopCounter++ > 10) { + state = EJS_STATE_ERR; + ejsError(ep, "Syntax error"); + } + } else { + endlessLoopTest = ep->input->scriptServp; + loopCounter = 0; + } + } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); + + ejsLexCloseScript(ep); + + /* + * Return any error string to the user + */ + if (state == EJS_STATE_ERR && emsg) { + *emsg = mprStrdup(ep->error); + } + + /* + * Restore the old evaluation block + */ + ep->input = oldBlock; + + if (state == EJS_STATE_ERR) { + return -1; + } + + if (vp) { + *vp = ep->result; + } + + return ep->exitStatus; +} + +/******************************************************************************/ +/* + * Core error handling + */ + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) + PRINTF_ATTRIBUTE(2, 0); + +static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) +{ + EjsInput *ip; + char *errbuf, *msgbuf; + + mprAssert(ep); + mprAssert(args); + + msgbuf = NULL; + mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); + + if (ep) { + ip = ep->input; + if (ip) { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, + "%s\nError on line %d. Offending line: %s\n\n", + msgbuf, ip->lineNumber, ip->line); + } else { + mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); + } + mprFree(ep->error); + ep->error = errbuf; + } + mprFree(msgbuf); +} + +/******************************************************************************/ +/* + * Internal use function to set the error message + */ + +void ejsError(Ejs* ep, const char* fmt, ...) +{ + va_list args; + + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Public routine to set the error message + */ + +void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) +{ + va_list args; + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + va_start(args, fmt); + ejsErrorCore(ep, fmt, args); + va_end(args); +} + +/******************************************************************************/ +/* + * Get the current line number + */ + +int ejsGetLineNumber(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + return ep->input->lineNumber; +} + +/******************************************************************************/ +/* + * Return the local object + */ + +MprVar *ejsGetLocalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->local; +} + +/******************************************************************************/ +/* + * Return the global object + */ + +MprVar *ejsGetGlobalObject(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->global; +} + +/******************************************************************************/ +/* + * Copy the value of an object property. Return value is in "value". + * If deepCopy is true, copy all object/strings. Otherwise, object reference + * counts are incremented. Callers must always call mprDestroyVar on the + * return value to prevent leaks. + * + * Returns: -1 on errors or if the variable is not found. + */ + +int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprCopyProperty(value, vp, deepCopy); +} + +/******************************************************************************/ +/* + * Return the value of an object property. Return value is in "value". + * Objects and strings are not copied and reference counts are not modified. + * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the + * variable is not found. + */ + +int ejsReadVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + mprAssert(value); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { + return -1; + } + + return mprReadProperty(vp, value); +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVar(EjsId eid, const char *var, MprVar *value) +{ + Ejs *ep; + MprVar *vp; + + mprAssert(var && *var); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + + if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { + return -1; + } + mprAssert(vp); + + /* + * Only copy the value. Don't overwrite the object's name + */ + mprWriteProperty(vp, value); + + return 0; +} + +/******************************************************************************/ +/* + * Set a variable that may be an arbitrarily complex object or array reference. + * Will always define in the top most variable frame. + */ + +int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) +{ + return ejsWriteVar(eid, var, &value); +} + +/******************************************************************************/ +/* + * Delete a variable + */ + +int ejsDeleteVar(EjsId eid, const char *var) +{ + Ejs *ep; + MprVar *vp; + MprVar *obj; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return -1; + } + if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { + return -1; + } + mprDeleteProperty(obj, vp->name); + return 0; +} + +/******************************************************************************/ +/* + * Set the expression return value + */ + +void ejsSetReturnValue(EjsId eid, MprVar value) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Set the expression return value to a string value + */ + +void ejsSetReturnString(EjsId eid, const char *str) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); +} + +/******************************************************************************/ +/* + * Get the expression return value + */ + +MprVar *ejsGetReturnValue(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return &ep->result; +} + +/******************************************************************************/ +/* + * Define a C function. If eid < 0, then update the master object with this + * function. NOTE: in this case, functionName must be simple without any "." or + * "[]" elements. If eid >= 0, add to the specified script engine. In this + * case, functionName can be an arbitrary object reference and can contain "." + * or "[]". + */ + +void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, + void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a C function with String arguments + */ + +void ejsDefineStringCFunction(EjsId eid, const char *functionName, + MprStringCFunction fn, void *thisPtr, int flags) +{ + if (eid < 0) { + ejsLock(); + mprCreatePropertyValue(&master, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + ejsUnlock(); + } else { + ejsWriteVarValue(eid, functionName, + mprCreateStringCFunctionVar(fn, thisPtr, flags)); + } +} + +/******************************************************************************/ +/* + * Define a JavaScript function. Args should be comma separated. + * Body should not contain braces. + */ + +void ejsDefineFunction(EjsId eid, const char *functionName, char *args, + char *body) +{ + MprVar v; + + v = mprCreateFunctionVar(args, body, 0); + if (eid < 0) { + ejsLock(); + mprCreateProperty(&master, functionName, &v); + ejsUnlock(); + } else { + ejsWriteVar(eid, functionName, &v); + } + mprDestroyVar(&v); +} + +/******************************************************************************/ + +void *ejsGetThisPtr(EjsId eid) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return 0; + } + return ep->thisPtr; +} + +/******************************************************************************/ +/* + * Find a variable given a variable name and return the parent object and + * the variable itself, the variable . This routine supports variable names + * that may be objects or arrays but may NOT have expressions in the array + * indicies. Returns -1 on errors or if the variable is not found. + */ + +int ejsGetVarCore(Ejs *ep, const char *vname, MprVar **obj, + MprVar **varValue, int flags) +{ + MprVar *currentObj; + MprVar *currentVar; + char tokBuf[EJS_MAX_ID]; + char *propertyName, *token, *next, *cp, *varName; + + if (obj) { + *obj = 0; + } + if (varValue) { + *varValue = 0; + } + currentObj = ejsFindObj(ep, 0, vname, flags); + currentVar = 0; + propertyName = 0; + + next = varName = mprStrdup(vname); + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + while (currentObj != 0 && token != 0 && *token) { + + if (*token == '[') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + + propertyName = token; + if (*propertyName == '\"') { + propertyName++; + if ((cp = strchr(propertyName, '\"')) != 0) { + *cp = '\0'; + } + } else if (*propertyName == '\'') { + propertyName++; + if ((cp = strchr(propertyName, '\'')) != 0) { + *cp = '\0'; + } + } + + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); + + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (*token != ']') { + mprFree(varName); + return -1; + } + + } else if (*token == '.') { + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + if (!isalpha((int) token[0]) && + token[0] != '_' && token[0] != '$') { + mprFree(varName); + return -1; + } + + propertyName = token; + currentObj = currentVar; + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + + } else { + currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); + } + token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); + } + mprFree(varName); + + if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { + currentVar = mprCreatePropertyValue(currentObj, propertyName, + mprCreateUndefinedVar()); + } + if (obj) { + *obj = currentObj; + } + + /* + * Don't use mprCopyVar as it will copy the data + */ + if (varValue) { + *varValue = currentVar; + } + return currentVar ? 0 : -1; +} + +/******************************************************************************/ +/* + * Get the next token as part of a variable specification. This will return + * a pointer to the next token and will return a pointer to the next token + * (after this one) in "next". The tokBuf holds the parsed token. + */ +static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) +{ + char *start, *cp; + int len; + + start = *next; + while (isspace((int) *start) || *start == '\n' || *start == '\r') { + start++; + } + cp = start; + + if (*cp == '.' || *cp == '[' || *cp == ']') { + cp++; + } else { + while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && + !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { + cp++; + } + } + len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); + tokBuf[len] = '\0'; + + *next = cp; + return tokBuf; +} + +/******************************************************************************/ +/* + * Get the EJS structure pointer + */ + +Ejs *ejsPtr(EjsId eid) +{ + Ejs *handle; + int intId; + + intId = (int) eid; + + ejsLock(); + mprAssert(0 <= intId && intId < ejsList->max); + + if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { + mprAssert(0); + ejsUnlock(); + return NULL; + } + handle = ejsList->handles[intId]; + ejsUnlock(); + return handle; +} + +/******************************************************************************/ +/* + * Utility routine to crack JavaScript arguments. Return the number of args + * seen. This routine only supports %s and %d type args. + * + * Typical usage: + * + * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { + * mprError("Insufficient args\n"); + * return -1; + * } + */ + +int ejsParseArgs(int argc, char **argv, char *fmt, ...) +{ + va_list vargs; + bool *bp; + char *cp, **sp, *s; + int *ip, argn; + + va_start(vargs, fmt); + + if (argv == 0) { + return 0; + } + + for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { + if (*cp++ != '%') { + continue; + } + + s = argv[argn]; + switch (*cp) { + case 'b': + bp = va_arg(vargs, bool*); + if (bp) { + if (strcmp(s, "true") == 0 || s[0] == '1') { + *bp = 1; + } else { + *bp = 0; + } + } else { + *bp = 0; + } + break; + + case 'd': + ip = va_arg(vargs, int*); + *ip = atoi(s); + break; + + case 's': + sp = va_arg(vargs, char**); + *sp = s; + break; + + default: + mprAssert(0); + } + argn++; + } + + va_end(vargs); + return argn; +} + +/******************************************************************************/ + +#else +void ejsDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/******************************************************************************/ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c new file mode 100644 index 0000000000..772ed574c5 --- /dev/null +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -0,0 +1,2378 @@ +/* + * @file ejsParser.c + * @brief EJS Parser and Execution + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/********************************** Includes **********************************/ + +#include "ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ + +static void appendValue(MprVar *v1, MprVar *v2); +static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +#if BLD_FEATURE_FLOATING_POINT +static int evalFloatExpr(Ejs *ep, double l, int rel, double r); +#endif +static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); +static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); +static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); +static int evalFunction(Ejs *ep, MprVar *obj, int flags); +static void freeProc(EjsProc *proc); +static int parseArgs(Ejs *ep, int state, int flags); +static int parseAssignment(Ejs *ep, int state, int flags, char *id, + char *fullName); +static int parseCond(Ejs *ep, int state, int flags); +static int parseDeclaration(Ejs *ep, int state, int flags); +static int parseExpr(Ejs *ep, int state, int flags); +static int parseFor(Ejs *ep, int state, int flags); +static int parseForIn(Ejs *ep, int state, int flags); +static int parseFunctionDec(Ejs *ep, int state, int flags); +static int parseFunction(Ejs *ep, int state, int flags, char *id); +static int parseId(Ejs *ep, int state, int flags, char **id, + char **fullName, int *fullNameLen, int *done); +static int parseInc(Ejs *ep, int state, int flags); +static int parseIf(Ejs *ep, int state, int flags, int *done); +static int parseStmt(Ejs *ep, int state, int flags); +static void removeNewlines(Ejs *ep, int state); +static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); + +/************************************* Code ***********************************/ +/* + * Recursive descent parser for EJS + */ + +int ejsParse(Ejs *ep, int state, int flags) +{ + mprAssert(ep); + + switch (state) { + /* + * Any statement, function arguments or conditional expressions + */ + case EJS_STATE_STMT: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_STMT_DONE && + state != EJS_STATE_EOF && state != EJS_STATE_STMT_BLOCK_DONE && + state != EJS_STATE_RET) { + state = EJS_STATE_ERR; + } + break; + + case EJS_STATE_DEC: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_DEC_DONE && + state != EJS_STATE_EOF) { + state = EJS_STATE_ERR; + } + break; + + case EJS_STATE_EXPR: + if ((state = parseStmt(ep, state, flags)) != EJS_STATE_EXPR_DONE && + state != EJS_STATE_EOF) { + state = EJS_STATE_ERR; + } + break; + + /* + * Variable declaration list + */ + case EJS_STATE_DEC_LIST: + state = parseDeclaration(ep, state, flags); + break; + + /* + * Function argument string + */ + case EJS_STATE_ARG_LIST: + state = parseArgs(ep, state, flags); + break; + + /* + * Logical condition list (relational operations separated by &&, ||) + */ + case EJS_STATE_COND: + state = parseCond(ep, state, flags); + break; + + /* + * Expression list + */ + case EJS_STATE_RELEXP: + state = parseExpr(ep, state, flags); + break; + } + + if (state == EJS_STATE_ERR && ep->error == NULL) { + ejsError(ep, "Syntax error"); + } + return state; +} + +/******************************************************************************/ +/* + * Parse any statement including functions and simple relational operations + */ + +static int parseStmt(Ejs *ep, int state, int flags) +{ + EjsProc *saveProc; + MprVar *vp, *saveObj; + char *id, *fullName, *initToken; + int done, expectSemi, tid, fullNameLen, rel; + int initId; + + mprAssert(ep); + + expectSemi = 0; + saveProc = NULL; + id = 0; + fullName = 0; + fullNameLen = 0; + + ep->currentObj = 0; + ep->currentProperty = 0; + + for (done = 0; !done && state != EJS_STATE_ERR; ) { + tid = ejsLexGetToken(ep, state); + + switch (tid) { + default: + ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); + done++; + break; + + case EJS_TOK_EXPR: + rel = (int) *ep->token; + if (state == EJS_STATE_EXPR) { + ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); + } + done++; + break; + + case EJS_TOK_LOGICAL: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_ERR: + state = EJS_STATE_ERR; + done++; + break; + + case EJS_TOK_EOF: + state = EJS_STATE_EOF; + done++; + break; + + case EJS_TOK_NEWLINE: + break; + + case EJS_TOK_SEMI: + /* + * This case is when we discover no statement and just a lone ';' + */ + if (state != EJS_STATE_STMT) { + ejsLexPutbackToken(ep, tid, ep->token); + } + done++; + break; + + case EJS_TOK_PERIOD: + if (flags & EJS_FLAGS_EXE) { + if (ep->currentProperty == 0) { + ejsError(ep, "Undefined object \"%s\"\n", id); + goto error; + } + } + ep->currentObj = ep->currentProperty; + + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { + ejsError(ep, "Bad property after '.': %s\n", ep->token); + goto error; + } + mprFree(id); + id = mprStrdup(ep->token); + + vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); + updateResult(ep, state, flags, vp); + +#if BLD_DEBUG + fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, + 0, ".", 0); +#endif + + ep->currentProperty = vp; + ejsLexPutbackToken(ep, tid, ep->token); + break; + + case EJS_TOK_LBRACKET: + ep->currentObj = ep->currentProperty; + saveObj = ep->currentObj; + if (ejsParse(ep, EJS_STATE_RELEXP, flags) != EJS_STATE_RELEXP_DONE){ + goto error; + } + ep->currentObj = saveObj; + + mprFree(id); + mprVarToString(&id, MPR_MAX_STRING, 0, &ep->result); + + if (id[0] == '\0') { + if (flags & EJS_FLAGS_EXE) { + ejsError(ep, + "[] expression evaluates to the empty string\n"); + goto error; + } + } else { + vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); + ep->currentProperty = vp; + updateResult(ep, state, flags, vp); + } + +#if BLD_DEBUG + if (id[0] && strlen(id) < (MPR_MAX_VAR / 2)) { + /* + * If not executing yet, id may not be known + */ + fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, + fullNameLen, 0, "[", id, "]", 0); + } +#endif + + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { + ejsError(ep, "Missing ']'\n"); + goto error; + } + break; + + case EJS_TOK_ID: + state = parseId(ep, state, flags, &id, &fullName, &fullNameLen, + &done); + if (done && state == EJS_STATE_STMT) { + expectSemi++; + } + break; + + case EJS_TOK_ASSIGNMENT: + state = parseAssignment(ep, state, flags, id, fullName); + if (state == EJS_STATE_STMT) { + expectSemi++; + done++; + } + break; + + case EJS_TOK_INC_DEC: + state = parseInc(ep, state, flags); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + break; + + case EJS_TOK_NEW: + if (ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW) + != EJS_STATE_EXPR_DONE) { + goto error; + } + break; + + case EJS_TOK_DELETE: + if (ejsParse(ep, EJS_STATE_EXPR, + flags | EJS_FLAGS_DELETE) != EJS_STATE_EXPR_DONE) { + goto error; + } + mprDeleteProperty(ep->currentObj, ep->currentProperty->name); + done++; + break; + + case EJS_TOK_FUNCTION: + state = parseFunctionDec(ep, state, flags); + done++; + break; + + case EJS_TOK_LITERAL: + /* + * Set the result to the string literal + */ + mprCopyVarValue(&ep->result, mprCreateStringVar(ep->token, 0), + MPR_SHALLOW_COPY); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + done++; + break; + + case EJS_TOK_NUMBER: + /* + * Set the result to the parsed number + */ + mprCopyVar(&ep->result, &ep->tokenNumber, 0); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + done++; + break; + + case EJS_TOK_FUNCTION_NAME: + state = parseFunction(ep, state, flags, id); + if (state == EJS_STATE_STMT) { + expectSemi++; + } + if (ep->flags & EJS_FLAGS_EXIT) { + state = EJS_STATE_RET; + } + done++; + break; + + case EJS_TOK_IF: + state = parseIf(ep, state, flags, &done); + if (state == EJS_STATE_RET) { + goto doneParse; + } + break; + + case EJS_TOK_FOR: + if (state != EJS_STATE_STMT) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { + goto error; + } + /* + * Need to peek 2-3 tokens ahead and see if this is a + * for ([var] x in set) + * or + * for (init ; whileCond; incr) + */ + initId = ejsLexGetToken(ep, EJS_STATE_EXPR); + if (initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { + /* Simply eat var tokens */ + initId = ejsLexGetToken(ep, EJS_STATE_EXPR); + } + initToken = mprStrdup(ep->token); + + tid = ejsLexGetToken(ep, EJS_STATE_EXPR); + + ejsLexPutbackToken(ep, tid, ep->token); + ejsLexPutbackToken(ep, initId, initToken); + mprFree(initToken); + + if (tid == EJS_TOK_IN) { + if ((state = parseForIn(ep, state, flags)) < 0) { + goto error; + } + } else { + if ((state = parseFor(ep, state, flags)) < 0) { + goto error; + } + } + done++; + break; + + case EJS_TOK_VAR: + if (ejsParse(ep, EJS_STATE_DEC_LIST, flags) + != EJS_STATE_DEC_LIST_DONE) { + goto error; + } + done++; + break; + + case EJS_TOK_COMMA: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_LPAREN: + if (state == EJS_STATE_EXPR) { + if (ejsParse(ep, EJS_STATE_RELEXP, flags) + != EJS_STATE_RELEXP_DONE) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + goto error; + } + } + done++; + break; + + case EJS_TOK_RPAREN: + ejsLexPutbackToken(ep, tid, ep->token); + done++; + break; + + case EJS_TOK_LBRACE: + /* + * This handles any code in braces except "if () {} else {}" + */ + if (state != EJS_STATE_STMT) { + goto error; + } + + /* + * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE + * is seen. + */ + do { + state = ejsParse(ep, EJS_STATE_STMT, flags); + } while (state == EJS_STATE_STMT_DONE); + + if (state != EJS_STATE_RET) { + if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { + goto error; + } + state = EJS_STATE_STMT_DONE; + } + done++; + break; + + case EJS_TOK_RBRACE: + if (state == EJS_STATE_STMT) { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_STMT_BLOCK_DONE; + done++; + break; + } + goto error; + + case EJS_TOK_RETURN: + if (ejsParse(ep, EJS_STATE_RELEXP, flags) + != EJS_STATE_RELEXP_DONE) { + goto error; + } + if (flags & EJS_FLAGS_EXE) { + while (ejsLexGetToken(ep, state) != EJS_TOK_EOF) { + ; + } + state = EJS_STATE_RET; + done++; + } + break; + } + } + + if (expectSemi) { + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_SEMI && tid != EJS_TOK_NEWLINE && + tid != EJS_TOK_EOF) { + goto error; + } + + /* + * Skip newline after semi-colon + */ + removeNewlines(ep, state); + } + +/* + * Free resources and return the correct status + */ +doneParse: + mprFree(id); + mprFree(fullName); + + /* + * Advance the state + */ + switch (state) { + case EJS_STATE_STMT: + return EJS_STATE_STMT_DONE; + + case EJS_STATE_DEC: + return EJS_STATE_DEC_DONE; + + case EJS_STATE_EXPR: + return EJS_STATE_EXPR_DONE; + + case EJS_STATE_STMT_DONE: + case EJS_STATE_STMT_BLOCK_DONE: + case EJS_STATE_EOF: + case EJS_STATE_RET: + return state; + + default: + return EJS_STATE_ERR; + } + +/* + * Common error exit + */ +error: + state = EJS_STATE_ERR; + goto doneParse; +} + +/******************************************************************************/ +/* + * Parse function arguments + */ + +static int parseArgs(Ejs *ep, int state, int flags) +{ + int tid; + + mprAssert(ep); + + do { + /* + * Peek and see if there are no args + */ + tid = ejsLexGetToken(ep, state); + ejsLexPutbackToken(ep, tid, ep->token); + if (tid == EJS_TOK_RPAREN) { + break; + } + + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state == EJS_STATE_EOF || state == EJS_STATE_ERR) { + return state; + } + if (state == EJS_STATE_RELEXP_DONE) { + if (flags & EJS_FLAGS_EXE) { + mprAssert(ep->proc->args); + mprAddToArray(ep->proc->args, + mprDupVar(&ep->result, MPR_SHALLOW_COPY)); + } + } + /* + * Peek at the next token, continue if more args (ie. comma seen) + */ + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_COMMA) { + ejsLexPutbackToken(ep, tid, ep->token); + } + } while (tid == EJS_TOK_COMMA); + + if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { + return EJS_STATE_ERR; + } + return EJS_STATE_ARG_LIST_DONE; +} + +/******************************************************************************/ +/* + * Parse an assignment statement + */ + +static int parseAssignment(Ejs *ep, int state, int flags, char *id, + char *fullName) +{ + MprVar *vp, *saveProperty, *saveObj; + + if (id == 0) { + return -1; + } + + saveObj = ep->currentObj; + saveProperty = ep->currentProperty; + if (ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT) + != EJS_STATE_RELEXP_DONE) { + return -1; + } + ep->currentObj = saveObj; + ep->currentProperty = saveProperty; + + if (! (flags & EJS_FLAGS_EXE)) { + return state; + } + + if (ep->currentProperty) { + /* + * Update the variable. Update the property name if not + * yet defined. + */ + if (ep->currentProperty->name == 0 || + ep->currentProperty->name[0] == '\0') { + mprSetVarName(ep->currentProperty, id); + } + if (mprWriteProperty(ep->currentProperty, &ep->result) < 0){ + ejsError(ep, "Can't write to variable\n"); + return -1; + } + + } else { + /* + * Create the variable + */ + if (ep->currentObj) { + if (ep->currentObj->type != MPR_TYPE_OBJECT) { + if (strcmp(ep->currentObj->name, "session") == 0) { + ejsError(ep, "Variable \"%s\" is not an array or object." + "If using ESP, you need useSession(); in your page.", + ep->currentObj->name); + } else { + ejsError(ep, "Variable \"%s\" is not an array or object", + ep->currentObj->name); + } + return -1; + } + vp = mprCreateProperty(ep->currentObj, id, &ep->result); + + } else { + /* + * Standard says: "var x" means declare locally. + * "x = 2" means declare globally if x is undefined. + */ + if (state == EJS_STATE_DEC) { + vp = mprCreateProperty(ep->local, id, &ep->result); + } else { + vp = mprCreateProperty(ep->global, id, &ep->result); + } + } +#if BLD_DEBUG + mprSetVarFullName(vp, fullName); +#endif + } + return state; +} + +/******************************************************************************/ +/* + * Parse conditional expression (relational ops separated by ||, &&) + */ + +static int parseCond(Ejs *ep, int state, int flags) +{ + MprVar lhs, rhs; + int tid, operator; + + mprAssert(ep); + + mprDestroyVar(&ep->result); + rhs = lhs = mprCreateUndefinedVar(); + operator = 0; + + do { + /* + * Recurse to handle one side of a conditional. Accumulate the + * left hand side and the final result in ep->result. + */ + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state != EJS_STATE_RELEXP_DONE) { + state = EJS_STATE_ERR; + break; + } + + if (operator > 0) { + mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); + if (evalCond(ep, &lhs, operator, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } + mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_LOGICAL) { + operator = (int) *ep->token; + + } else if (tid == EJS_TOK_RPAREN || tid == EJS_TOK_SEMI) { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_COND_DONE; + break; + + } else { + ejsLexPutbackToken(ep, tid, ep->token); + } + tid = (state == EJS_STATE_RELEXP_DONE); + + } while (state == EJS_STATE_RELEXP_DONE); + + mprDestroyVar(&lhs); + mprDestroyVar(&rhs); + return state; +} + +/******************************************************************************/ +/* + * Parse variable declaration list. Declarations can be of the following forms: + * var x; + * var x, y, z; + * var x = 1 + 2 / 3, y = 2 + 4; + * + * We set the variable to NULL if there is no associated assignment. + */ + +static int parseDeclaration(Ejs *ep, int state, int flags) +{ + int tid; + + mprAssert(ep); + + do { + if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { + return EJS_STATE_ERR; + } + ejsLexPutbackToken(ep, tid, ep->token); + + /* + * Parse the entire assignment or simple identifier declaration + */ + if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { + return EJS_STATE_ERR; + } + + /* + * Peek at the next token, continue if comma seen + */ + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_SEMI) { + return EJS_STATE_DEC_LIST_DONE; + } else if (tid != EJS_TOK_COMMA) { + return EJS_STATE_ERR; + } + } while (tid == EJS_TOK_COMMA); + + if (tid != EJS_TOK_SEMI) { + return EJS_STATE_ERR; + } + return EJS_STATE_DEC_LIST_DONE; +} + +/******************************************************************************/ +/* + * Parse expression (leftHandSide operator rightHandSide) + */ + +static int parseExpr(Ejs *ep, int state, int flags) +{ + MprVar lhs, rhs; + int rel, tid; + + mprAssert(ep); + + mprDestroyVar(&ep->result); + rhs = lhs = mprCreateUndefinedVar(); + rel = 0; + tid = 0; + + do { + /* + * This loop will handle an entire expression list. We call parse + * to evalutate each term which returns the result in ep->result. + */ + if (tid == EJS_TOK_LOGICAL) { + state = ejsParse(ep, EJS_STATE_RELEXP, flags); + if (state != EJS_STATE_RELEXP_DONE) { + state = EJS_STATE_ERR; + break; + } + } else { + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { + lhs = mprCreateIntegerVar(0); + rel = (int) *ep->token; + } else { + ejsLexPutbackToken(ep, tid, ep->token); + } + + state = ejsParse(ep, EJS_STATE_EXPR, flags); + if (state != EJS_STATE_EXPR_DONE) { + state = EJS_STATE_ERR; + break; + } + } + + if (rel > 0) { + mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); + if (tid == EJS_TOK_LOGICAL) { + if (evalCond(ep, &lhs, rel, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } else { + if (evalExpr(ep, &lhs, rel, &rhs) < 0) { + state = EJS_STATE_ERR; + break; + } + } + } + mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); + + if ((tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || + tid == EJS_TOK_INC_DEC || tid == EJS_TOK_LOGICAL) { + rel = (int) *ep->token; + + } else { + ejsLexPutbackToken(ep, tid, ep->token); + state = EJS_STATE_RELEXP_DONE; + } + + } while (state == EJS_STATE_EXPR_DONE); + + mprDestroyVar(&lhs); + mprDestroyVar(&rhs); + + return state; +} + +/******************************************************************************/ +/* + * Parse the "for ... in" statement. Format for the statement is: + * + * for (var in expr) { + * body; + * } + */ + +static int parseForIn(Ejs *ep, int state, int flags) +{ + EjsInput endScript, bodyScript; + MprVar *iteratorVar, *setVar, *vp, v; + int forFlags, tid; + + mprAssert(ep); + + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ID) { + return -1; + } + ejsLexPutbackToken(ep, tid, ep->token); + + if (ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FOREACH | EJS_FLAGS_EXE) + != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ep->currentProperty == 0) { + return -1; + } + iteratorVar = ep->currentProperty; + + if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { + return -1; + } + + /* + * Get the set + */ + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ID) { + return -1; + } + ejsLexPutbackToken(ep, tid, ep->token); + + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ep->currentProperty == 0 && flags & EJS_FLAGS_EXE) { + return -1; + } + setVar = ep->currentProperty; + + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + + /* + * Parse the body and remember the end of the body script + */ + forFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &bodyScript); + if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + ejsInitInputState(&endScript); + ejsLexSaveInputState(ep, &endScript); + + /* + * Now actually do the for loop. + */ + if (flags & EJS_FLAGS_EXE) { + if (setVar->type == MPR_TYPE_OBJECT) { + vp = mprGetFirstProperty(setVar, MPR_ENUM_DATA); + while (vp) { + if (strcmp(vp->name, "length") != 0) { + v = mprCreateStringVar(vp->name, 0); + if (mprWriteProperty(iteratorVar, &v) < 0) { + ejsError(ep, "Can't write to variable\n"); + ejsLexFreeInputState(ep, &bodyScript); + ejsLexFreeInputState(ep, &endScript); + return -1; + } + + ejsLexRestoreInputState(ep, &bodyScript); + switch (ejsParse(ep, EJS_STATE_STMT, flags)) { + case EJS_STATE_RET: + return EJS_STATE_RET; + case EJS_STATE_STMT_DONE: + break; + default: + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + } + vp = mprGetNextProperty(setVar, vp, MPR_ENUM_DATA); + } + } else { + ejsError(ep, "Variable \"%s\" is not an array or object", + setVar->name); + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return -1; + } + } + ejsLexRestoreInputState(ep, &endScript); + + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + + return state; +} + +/******************************************************************************/ +/* + * Parse the for statement. Format for the expression is: + * + * for (initial; condition; incr) { + * body; + * } + */ + +static int parseFor(Ejs *ep, int state, int flags) +{ + EjsInput condScript, endScript, bodyScript, incrScript; + int forFlags, cond; + + ejsInitInputState(&endScript); + ejsInitInputState(&bodyScript); + ejsInitInputState(&incrScript); + ejsInitInputState(&condScript); + + mprAssert(ep); + + /* + * Evaluate the for loop initialization statement + */ + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { + return -1; + } + + /* + * The first time through, we save the current input context just prior + * to each step: prior to the conditional, the loop increment and + * the loop body. + */ + ejsLexSaveInputState(ep, &condScript); + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + goto error; + } + cond = (ep->result.boolean != 0); + + if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { + goto error; + } + + /* + * Don't execute the loop increment statement or the body + * first time. + */ + forFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &incrScript); + if (ejsParse(ep, EJS_STATE_EXPR, forFlags) != EJS_STATE_EXPR_DONE) { + goto error; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + goto error; + } + + /* + * Parse the body and remember the end of the body script + */ + ejsLexSaveInputState(ep, &bodyScript); + if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { + goto error; + } + ejsLexSaveInputState(ep, &endScript); + + /* + * Now actually do the for loop. Note loop has been rotated + */ + while (cond && (flags & EJS_FLAGS_EXE)) { + /* + * Evaluate the body + */ + ejsLexRestoreInputState(ep, &bodyScript); + + switch (ejsParse(ep, EJS_STATE_STMT, flags)) { + case EJS_STATE_RET: + return EJS_STATE_RET; + case EJS_STATE_STMT_DONE: + break; + default: + goto error; + } + /* + * Evaluate the increment script + */ + ejsLexRestoreInputState(ep, &incrScript); + if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE){ + goto error; + } + /* + * Evaluate the condition + */ + ejsLexRestoreInputState(ep, &condScript); + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + goto error; + } + mprAssert(ep->result.type == MPR_TYPE_BOOL); + cond = (ep->result.boolean != 0); + } + + ejsLexRestoreInputState(ep, &endScript); + +done: + ejsLexFreeInputState(ep, &condScript); + ejsLexFreeInputState(ep, &incrScript); + ejsLexFreeInputState(ep, &endScript); + ejsLexFreeInputState(ep, &bodyScript); + return state; + +error: + state = EJS_STATE_ERR; + goto done; +} + +/******************************************************************************/ +/* + * Parse a function declaration + */ + +static int parseFunctionDec(Ejs *ep, int state, int flags) +{ + EjsInput endScript, bodyScript; + MprVar v, *currentObj, *vp; + char *procName; + int len, tid, bodyFlags; + + mprAssert(ep); + mprAssert(ejsPtr(ep->eid)); + + /* + * function (arg, arg, arg) { body }; + * function name(arg, arg, arg) { body }; + */ + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_ID) { + procName = mprStrdup(ep->token); + tid = ejsLexGetToken(ep, state); + } else { + procName = 0; + } + if (tid != EJS_TOK_LPAREN) { + mprFree(procName); + return EJS_STATE_ERR; + } + + /* + * Hand craft the function value structure. + */ + v = mprCreateFunctionVar(0, 0, 0); + tid = ejsLexGetToken(ep, state); + while (tid == EJS_TOK_ID) { + mprAddToArray(v.function.args, mprStrdup(ep->token)); + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { + break; + } + tid = ejsLexGetToken(ep, state); + } + if (tid != EJS_TOK_RPAREN) { + mprFree(procName); + mprDestroyVar(&v); + return EJS_STATE_ERR; + } + + /* Allow new lines before opening brace */ + do { + tid = ejsLexGetToken(ep, state); + } while (tid == EJS_TOK_NEWLINE); + + if (tid != EJS_TOK_LBRACE) { + mprFree(procName); + mprDestroyVar(&v); + return EJS_STATE_ERR; + } + + /* + * Register the function name early to allow for recursive + * function calls (see note in ECMA standard, page 71) + */ + if (!(flags & EJS_FLAGS_ASSIGNMENT)) { + currentObj = ejsFindObj(ep, 0, procName, flags); + vp = mprSetProperty(currentObj, procName, &v); + } + + /* + * Parse the function body. Turn execute off. + */ + bodyFlags = flags & ~EJS_FLAGS_EXE; + ejsLexSaveInputState(ep, &bodyScript); + + do { + state = ejsParse(ep, EJS_STATE_STMT, bodyFlags); + } while (state == EJS_STATE_STMT_DONE); + + tid = ejsLexGetToken(ep, state); + if (state != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { + mprFree(procName); + mprDestroyVar(&v); + ejsLexFreeInputState(ep, &bodyScript); + return EJS_STATE_ERR; + } + ejsLexSaveInputState(ep, &endScript); + + /* + * Save the function body between the starting and ending parse positions. + * Overwrite the trailing '}' with a null. + */ + len = endScript.scriptServp - bodyScript.scriptServp; + v.function.body = mprMalloc(len + 1); + memcpy(v.function.body, bodyScript.scriptServp, len); + + if (len <= 0) { + v.function.body[0] = '\0'; + } else { + v.function.body[len - 1] = '\0'; + } + ejsLexFreeInputState(ep, &bodyScript); + ejsLexFreeInputState(ep, &endScript); + + /* + * If we are in an assignment, don't register the function name, rather + * return the function structure in the parser result. + */ + if (flags & EJS_FLAGS_ASSIGNMENT) { + mprCopyVar(&ep->result, &v, MPR_SHALLOW_COPY); + } else { + currentObj = ejsFindObj(ep, 0, procName, flags); + vp = mprSetProperty(currentObj, procName, &v); + } + + mprFree(procName); + mprDestroyVar(&v); + + return EJS_STATE_STMT; +} + +/******************************************************************************/ +/* + * Parse a function name and invoke the function + */ + +static int parseFunction(Ejs *ep, int state, int flags, char *id) +{ + EjsProc proc, *saveProc; + MprVar *saveObj; + + /* + * Must save any current ep->proc value for the current stack frame + * to allow for recursive function calls. + */ + saveProc = (ep->proc) ? ep->proc: 0; + + memset(&proc, 0, sizeof(EjsProc)); + proc.procName = mprStrdup(id); + proc.fn = ep->currentProperty; + proc.args = mprCreateArray(); + ep->proc = &proc; + + mprDestroyVar(&ep->result); + + saveObj = ep->currentObj; + if (ejsParse(ep, EJS_STATE_ARG_LIST, flags) != EJS_STATE_ARG_LIST_DONE) { + freeProc(&proc); + ep->proc = saveProc; + return -1; + } + ep->currentObj = saveObj; + + /* + * Evaluate the function if required + */ + if (flags & EJS_FLAGS_EXE) { + if (evalFunction(ep, ep->currentObj, flags) < 0) { + freeProc(&proc); + ep->proc = saveProc; + return -1; + } + } + + freeProc(&proc); + ep->proc = saveProc; + + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + return state; +} + +/******************************************************************************/ +/* + * Parse an identifier. This is a segment of a fully qualified variable. + * May come here for an initial identifier or for property names + * after a "." or "[...]". + */ + +static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, + int *fullNameLen, int *done) +{ + int tid; + + mprFree(*id); + *id = mprStrdup(ep->token); +#if BLD_DEBUG + *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, + 0, *id, 0); +#endif + if (ep->currentObj == 0) { + ep->currentObj = ejsFindObj(ep, state, *id, flags); + } + + /* + * Find the referenced variable and store it in currentProperty. + */ + ep->currentProperty = ejsFindProperty(ep, state, ep->currentObj, + *id, flags); + updateResult(ep, state, flags, ep->currentProperty); + +#if BLD_DEBUG + if (ep->currentProperty && (ep->currentProperty->name == 0 || + ep->currentProperty->name[0] == '\0')) { + mprSetVarName(ep->currentProperty, *id); + } +#endif + + tid = ejsLexGetToken(ep, state); + if (tid == EJS_TOK_LPAREN) { + ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); + return state; + } + + if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || + tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { + ejsLexPutbackToken(ep, tid, ep->token); + return state; + } + + /* + * Only come here for variable access and declarations. + * Assignment handled elsewhere. + */ + if (flags & EJS_FLAGS_EXE) { + if (state == EJS_STATE_DEC) { + /* + * Declare a variable. Standard allows: var x ; var x ; + */ +#if DISABLED + if (ep->currentProperty != 0) { + ejsError(ep, "Variable already defined \"%s\"\n", *id); + return -1; + } +#endif + /* + * Create or overwrite if it already exists + */ + mprSetPropertyValue(ep->currentObj, *id, + mprCreateUndefinedVar()); + ep->currentProperty = 0; + mprDestroyVar(&ep->result); + + } else if (flags & EJS_FLAGS_FOREACH) { + if (ep->currentProperty == 0) { + ep->currentProperty = + mprCreatePropertyValue(ep->currentObj, *id, + mprCreateUndefinedVar()); + } + + } else { + if (ep->currentProperty == 0) { + if (ep->currentObj == ep->global || + ep->currentObj == ep->local) { + ejsError(ep, "Undefined variable \"%s\"\n", *id); + return -1; + } + ep->currentProperty = mprCreatePropertyValue(ep->currentObj, + *id, mprCreateUndefinedVar()); + } + } + } + ejsLexPutbackToken(ep, tid, ep->token); + if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || + tid == EJS_TOK_IN) { + *done = 1; + } + return state; +} + +/******************************************************************************/ +/* + * Parse an "if" statement + */ + +static int parseIf(Ejs *ep, int state, int flags, int *done) +{ + bool ifResult; + int thenFlags, elseFlags, tid; + + if (state != EJS_STATE_STMT) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { + return -1; + } + + /* + * Evaluate the entire condition list "(condition)" + */ + if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { + return -1; + } + if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { + return -1; + } + + /* + * This is the "then" case. We need to always parse both cases and + * execute only the relevant case. + */ + ifResult = mprVarToBool(&ep->result); + if (ifResult) { + thenFlags = flags; + elseFlags = flags & ~EJS_FLAGS_EXE; + } else { + thenFlags = flags & ~EJS_FLAGS_EXE; + elseFlags = flags; + } + + /* + * Process the "then" case. + */ + switch (ejsParse(ep, EJS_STATE_STMT, thenFlags)) { + case EJS_STATE_RET: + state = EJS_STATE_RET; + return state; + case EJS_STATE_STMT_DONE: + break; + default: + return -1; + } + + /* + * Check to see if there is an "else" case + */ + removeNewlines(ep, state); + tid = ejsLexGetToken(ep, state); + if (tid != EJS_TOK_ELSE) { + ejsLexPutbackToken(ep, tid, ep->token); + *done = 1; + return state; + } + + /* + * Process the "else" case. + */ + switch (ejsParse(ep, EJS_STATE_STMT, elseFlags)) { + case EJS_STATE_RET: + state = EJS_STATE_RET; + return state; + case EJS_STATE_STMT_DONE: + break; + default: + return -1; + } + *done = 1; + return state; +} + +/******************************************************************************/ +/* + * Parse an "++" or "--" statement + */ + +static int parseInc(Ejs *ep, int state, int flags) +{ + MprVar one; + + if (! (flags & EJS_FLAGS_EXE)) { + return state; + } + + if (ep->currentProperty == 0) { + ejsError(ep, "Undefined variable \"%s\"\n", ep->token); + return -1; + } + one = mprCreateIntegerVar(1); + if (evalExpr(ep, ep->currentProperty, (int) *ep->token, + &one) < 0) { + return -1; + } + if (mprWriteProperty(ep->currentProperty, &ep->result) < 0) { + ejsError(ep, "Can't write to variable\n"); + return -1; + } + return state; +} + +/******************************************************************************/ +/* + * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result + * in ep->result. Returns -1 on errors, zero if successful. + */ + +static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + bool l, r, lval; + + mprAssert(rel > 0); + + l = mprVarToBool(lhs); + r = mprVarToBool(rhs); + + switch (rel) { + case EJS_COND_AND: + lval = l && r; + break; + case EJS_COND_OR: + lval = l || r; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Evaluate an operation. Returns with the result in ep->result. Returns -1 + * on errors, otherwise zero is returned. + */ + +static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + char *str; + MprNum lval, num; + int rc; + + mprAssert(rel > 0); + str = 0; + lval = 0; + + /* + * Type conversion. This is tricky and must be according to the standard. + * Only numbers (including floats) and strings can be compared. All other + * types are first converted to numbers by preference and if that fails, + * to strings. + * + * First convert objects to comparable types. The "===" operator will + * test the sameness of object references. Here, we coerce to comparable + * types first. + */ + if (lhs->type == MPR_TYPE_OBJECT) { + if (ejsRunFunction(ep->eid, lhs, "toValue", 0) == 0) { + mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); + } else { + if (ejsRunFunction(ep->eid, lhs, "toString", 0) == 0) { + mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); + } + } + /* Nothing more can be done */ + } + + if (rhs->type == MPR_TYPE_OBJECT) { + if (ejsRunFunction(ep->eid, rhs, "toValue", 0) == 0) { + mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); + } else { + if (ejsRunFunction(ep->eid, rhs, "toString", 0) == 0) { + mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); + } + } + /* Nothing more can be done */ + } + + /* + * From here on, lhs and rhs may contain allocated data (strings), so + * we must always destroy before overwriting. + */ + + /* + * Only allow a few bool operations. Otherwise convert to number. + */ + if (lhs->type == MPR_TYPE_BOOL && rhs->type == MPR_TYPE_BOOL && + (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && + rel != EJS_EXPR_BOOL_COMP)) { + num = mprVarToNumber(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + } + + /* + * Types do not match, so try to coerce the right operand to match the left + * But first, try to convert a left operand that is a numeric stored as a + * string, into a numeric. + */ + if (lhs->type != rhs->type) { + if (lhs->type == MPR_TYPE_STRING) { + if (isdigit((int) lhs->string[0])) { + num = mprVarToNumber(lhs); + lhs->allocatedVar = 0; + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + /* Examine further below */ + + } else { + /* + * Convert the RHS to a string + */ + mprVarToString(&str, MPR_MAX_STRING, 0, rhs); + rhs->allocatedVar = 0; + mprDestroyVar(rhs); + *rhs = mprCreateStringVar(str, 1); + mprFree(str); + } + +#if BLD_FEATURE_FLOATING_POINT + } else if (lhs->type == MPR_TYPE_FLOAT) { + /* + * Convert rhs to floating + */ + double f = mprVarToFloat(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateFloatVar(f); + +#endif +#if BLD_FEATURE_INT64 + } else if (lhs->type == MPR_TYPE_INT64) { + /* + * Convert the rhs to 64 bit + */ + int64 n = mprVarToInteger64(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateInteger64Var(n); +#endif + } else if (lhs->type == MPR_TYPE_BOOL || lhs->type == MPR_TYPE_INT) { + + if (rhs->type == MPR_TYPE_STRING) { + /* + * Convert to lhs to a string + */ + mprVarToString(&str, MPR_MAX_STRING, 0, lhs); + mprDestroyVar(lhs); + *lhs = mprCreateStringVar(str, 1); + mprFree(str); + +#if BLD_FEATURE_FLOATING_POINT + } else if (rhs->type == MPR_TYPE_FLOAT) { + /* + * Convert lhs to floating + */ + double f = mprVarToFloat(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateFloatVar(f); +#endif + + } else { + /* + * Convert both operands to numbers + */ + num = mprVarToNumber(lhs); + mprDestroyVar(lhs); + *lhs = mprCreateNumberVar(num); + + num = mprVarToNumber(rhs); + mprDestroyVar(rhs); + *rhs = mprCreateNumberVar(num); + } + } + } + + /* + * We have failed to coerce the types to be the same. Special case here + * for undefined and null. We need to allow comparisions against these + * special values. + */ + if (lhs->type == MPR_TYPE_UNDEFINED || lhs->type == MPR_TYPE_NULL) { + switch (rel) { + case EJS_EXPR_EQ: + lval = lhs->type == rhs->type; + break; + case EJS_EXPR_NOTEQ: + lval = lhs->type != rhs->type; + break; + default: + lval = 0; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar((bool) lval), 0); + return 0; + } + + /* + * Types are the same here + */ + switch (lhs->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + /* Should be handled above */ + mprAssert(0); + return 0; + + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); + return 0; + + case MPR_TYPE_PTR: + mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0); + return 0; + + case MPR_TYPE_BOOL: + rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); + break; +#endif + + case MPR_TYPE_INT: + rc = evalNumericExpr(ep, (MprNum) lhs->integer, rel, + (MprNum) rhs->integer); + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + rc = evalNumericExpr(ep, (MprNum) lhs->integer64, rel, + (MprNum) rhs->integer64); + break; +#endif + + case MPR_TYPE_STRING: + rc = evalStringExpr(ep, lhs, rel, rhs); + } + return rc; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Expressions with floating operands + */ + +static int evalFloatExpr(Ejs *ep, double l, int rel, double r) +{ + double lval; + bool logical; + + lval = 0; + logical = 0; + + switch (rel) { + case EJS_EXPR_PLUS: + lval = l + r; + break; + case EJS_EXPR_INC: + lval = l + 1; + break; + case EJS_EXPR_MINUS: + lval = l - r; + break; + case EJS_EXPR_DEC: + lval = l - 1; + break; + case EJS_EXPR_MUL: + lval = l * r; + break; + case EJS_EXPR_DIV: + lval = l / r; + break; + default: + logical++; + break; + } + + /* + * Logical operators + */ + if (logical) { + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_LESS: + lval = (l < r) ? 1 : 0; + break; + case EJS_EXPR_LESSEQ: + lval = (l <= r) ? 1 : 0; + break; + case EJS_EXPR_GREATER: + lval = (l > r) ? 1 : 0; + break; + case EJS_EXPR_GREATEREQ: + lval = (l >= r) ? 1 : 0; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); + + } else { + mprCopyVarValue(&ep->result, mprCreateFloatVar(lval), 0); + } + return 0; +} + +#endif /* BLD_FEATURE_FLOATING_POINT */ +/******************************************************************************/ +/* + * Expressions with boolean operands + */ + +static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) +{ + bool lval; + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Expressions with numeric operands + */ + +static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) +{ + MprNum lval; + bool logical; + + lval = 0; + logical = 0; + + switch (rel) { + case EJS_EXPR_PLUS: + lval = l + r; + break; + case EJS_EXPR_INC: + lval = l + 1; + break; + case EJS_EXPR_MINUS: + lval = l - r; + break; + case EJS_EXPR_DEC: + lval = l - 1; + break; + case EJS_EXPR_MUL: + lval = l * r; + break; + case EJS_EXPR_DIV: + if (r != 0) { + lval = l / r; + } else { + ejsError(ep, "Divide by zero"); + return -1; + } + break; + case EJS_EXPR_MOD: + if (r != 0) { + lval = l % r; + } else { + ejsError(ep, "Modulo zero"); + return -1; + } + break; + case EJS_EXPR_LSHIFT: + lval = l << r; + break; + case EJS_EXPR_RSHIFT: + lval = l >> r; + break; + + default: + logical++; + break; + } + + /* + * Logical operators + */ + if (logical) { + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_LESS: + lval = (l < r) ? 1 : 0; + break; + case EJS_EXPR_LESSEQ: + lval = (l <= r) ? 1 : 0; + break; + case EJS_EXPR_GREATER: + lval = (l > r) ? 1 : 0; + break; + case EJS_EXPR_GREATEREQ: + lval = (l >= r) ? 1 : 0; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == 0) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); + + } else { + mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); + } + return 0; +} + +/******************************************************************************/ +/* + * Expressions with string operands + */ + +static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) +{ + int lval; + + mprAssert(ep); + mprAssert(lhs); + mprAssert(rhs); + + switch (rel) { + case EJS_EXPR_LESS: + lval = strcmp(lhs->string, rhs->string) < 0; + break; + case EJS_EXPR_LESSEQ: + lval = strcmp(lhs->string, rhs->string) <= 0; + break; + case EJS_EXPR_GREATER: + lval = strcmp(lhs->string, rhs->string) > 0; + break; + case EJS_EXPR_GREATEREQ: + lval = strcmp(lhs->string, rhs->string) >= 0; + break; + case EJS_EXPR_EQ: + lval = strcmp(lhs->string, rhs->string) == 0; + break; + case EJS_EXPR_NOTEQ: + lval = strcmp(lhs->string, rhs->string) != 0; + break; + case EJS_EXPR_PLUS: + /* + * This differs from all the above operations. We append rhs to lhs. + */ + mprDestroyVar(&ep->result); + appendValue(&ep->result, lhs); + appendValue(&ep->result, rhs); + return 0; + + case EJS_EXPR_INC: + case EJS_EXPR_DEC: + case EJS_EXPR_MINUS: + case EJS_EXPR_DIV: + case EJS_EXPR_MOD: + case EJS_EXPR_LSHIFT: + case EJS_EXPR_RSHIFT: + default: + ejsError(ep, "Bad operator"); + return -1; + } + + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + +/******************************************************************************/ +/* + * Evaluate a function. obj is set to the current object if a function is being + * run. + */ + +static int evalFunction(Ejs *ep, MprVar *obj, int flags) +{ + EjsProc *proc; + MprVar arguments, callee, thisObject, *prototype, **argValues; + MprArray *formalArgs, *actualArgs; + char buf[16], **argNames, **argBuf; + int i, rc, fid; + + mprAssert(ep); + mprAssert(ejsPtr(ep->eid)); + + rc = -1; + proc = ep->proc; + prototype = proc->fn; + actualArgs = proc->args; + argValues = (MprVar**) actualArgs->handles; + + if (prototype == NULL) { + ejsError(ep, "Function name not defined '%s'\n", proc->procName); + return -1; + } + + /* + * Create a new variable stack frame. ie. new local variables. + */ + fid = ejsOpenBlock(ep->eid); + + if (flags & EJS_FLAGS_NEW) { + /* + * Create a new bare object and pass it into the constructor as the + * "this" local variable. + */ + thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); + mprCreatePropertyValue(ep->local, "this", thisObject); + + } else if (obj) { + mprCreateProperty(ep->local, "this", obj); + } + + switch (prototype->type) { + default: + mprAssert(0); + break; + + case MPR_TYPE_STRING_CFUNCTION: + if (actualArgs->used > 0) { + argBuf = mprMalloc(actualArgs->used * sizeof(char*)); + for (i = 0; i < actualArgs->used; i++) { + mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); + } + } else { + argBuf = 0; + } + + /* + * Call the function depending on the various handle flags + */ + ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; + if (prototype->flags & MPR_VAR_ALT_HANDLE) { + rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) + (ep->eid, ep->altHandle, actualArgs->used, argBuf); + } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { + rc = (prototype->cFunctionWithStrings.fn)(ep->eid, + actualArgs->used, argBuf); + } else { + rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, + actualArgs->used, argBuf); + } + + if (actualArgs->used > 0) { + for (i = 0; i < actualArgs->used; i++) { + mprFree(argBuf[i]); + } + mprFree(argBuf); + } + ep->thisPtr = 0; + break; + + case MPR_TYPE_CFUNCTION: + /* + * Call the function depending on the various handle flags + */ + ep->thisPtr = prototype->cFunction.thisPtr; + if (prototype->flags & MPR_VAR_ALT_HANDLE) { + rc = ((EjsAltCFunction) prototype->cFunction.fn) + (ep->eid, ep->altHandle, actualArgs->used, argValues); + } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { + rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, + argValues); + } else { + rc = (prototype->cFunction.fn)(ep->primaryHandle, + actualArgs->used, argValues); + } + ep->thisPtr = 0; + break; + + case MPR_TYPE_FUNCTION: + + formalArgs = prototype->function.args; + argNames = (char**) formalArgs->handles; + +#if FUTURE + if (formalArgs->used != actualArgs->used) { + ejsError(ep, "Bad number of args. Should be %d", formalArgs->used); + return -1; + } +#endif + + /* + * Create the arguments and callee variables + */ + arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); + callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); + + /* + * Overwrite the length property + */ + mprCreatePropertyValue(&arguments, "length", + mprCreateIntegerVar(actualArgs->used)); + mprCreatePropertyValue(&callee, "length", + mprCreateIntegerVar(formalArgs->used)); + + /* + * Define all the agruments to be set to the actual parameters + */ + for (i = 0; i < formalArgs->used; i++) { + mprCreateProperty(ep->local, argNames[i], argValues[i]); + } + for (i = 0; i < actualArgs->used; i++) { + mprItoa(i, buf, sizeof(buf)); + mprCreateProperty(&arguments, buf, argValues[i]); + } + + mprCreateProperty(&arguments, "callee", &callee); + mprCreateProperty(ep->local, "arguments", &arguments); + + /* + * Can destroy our variables here as they are now referenced via + * "local" + */ + mprDestroyVar(&callee); + mprDestroyVar(&arguments); + + /* + * Actually run the function + */ + rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); + break; + } + + ejsCloseBlock(ep->eid, fid); + + /* + * New statements return the newly created object as the result of the + * command + */ + if (flags & EJS_FLAGS_NEW) { + mprDestroyVar(&ep->result); + /* + * Don't copy, we want to assign the actual object into result. + * (mprCopyVar would inc the refCount to 2). + */ + ep->result = thisObject; + } + return rc; +} + +/******************************************************************************/ +/* + * Run a function + */ + +int ejsRunFunction(int eid, MprVar *obj, const char *functionName, + MprArray *args) +{ + EjsProc proc, *saveProc; + Ejs *ep; + int rc; + + mprAssert(obj); + mprAssert(functionName && *functionName); + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return MPR_ERR_NOT_FOUND; + } + saveProc = ep->proc; + ep->proc = &proc; + + memset(&proc, 0, sizeof(EjsProc)); + mprDestroyVar(&ep->result); + + proc.fn = mprGetProperty(obj, functionName, 0); + if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { + ep->proc = saveProc; + return MPR_ERR_NOT_FOUND; + } + proc.procName = mprStrdup(functionName); + if (args == 0) { + proc.args = mprCreateArray(); + rc = evalFunction(ep, obj, 0); + } else { + proc.args = args; + rc = evalFunction(ep, obj, 0); + proc.args = 0; + } + + freeProc(&proc); + ep->proc = saveProc; + + return rc; +} + +/******************************************************************************/ +/* + * Find which object contains the property given the current context. + * Only used for top level properties. + */ + +MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) +{ + MprVar *vp; + MprVar *obj; + + mprAssert(ep); + mprAssert(property && *property); + + if (flags & EJS_FLAGS_GLOBAL) { + obj = ep->global; + + } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { + obj = ep->local; + + } else { + /* First look local, then look global */ + vp = mprGetProperty(ep->local, property, 0); + if (vp) { + obj = ep->local; + } else if (mprGetProperty(ep->local, property, 0)) { + obj = ep->local; + } else { + obj = ep->global; + } + } + return obj; +} + +/******************************************************************************/ +/* + * Find an object property given a object and a property name. We + * intelligently look in the local and global namespaces depending on + * our state. If not found in local or global, try base classes for function + * names only. Returns the property or NULL. + */ + +MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, + int flags) +{ + MprVar *vp; + + mprAssert(ep); + if (flags & EJS_FLAGS_EXE) { + mprAssert(property && *property); + } + + if (obj != 0) { +#if FUTURE && MB + op = obj; + do { + vp = mprGetProperty(op, property, 0); + if (vp != 0) { + if (op != obj && mprVarIsFunction(vp->type)) { + } + break; + } + op = op->baseObj; + } while (op); +#endif + vp = mprGetProperty(obj, property, 0); + + } else { + if (state == EJS_STATE_DEC) { + vp = mprGetProperty(ep->local, property, 0); + + } else { + /* Look local first, then global */ + vp = mprGetProperty(ep->local, property, 0); + if (vp == NULL) { + vp = mprGetProperty(ep->global, property, 0); + } + } + } + return vp; +} + +/******************************************************************************/ +/* + * Update result + */ + +static void updateResult(Ejs *ep, int state, int flags, MprVar *vp) +{ + if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { + mprDestroyVar(&ep->result); + if (vp) { + mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); + } + } +} + +/******************************************************************************/ +/* + * Append to the pointer value + */ + +static void appendValue(MprVar *dest, MprVar *src) +{ + char *value, *oldBuf, *buf; + int len, oldLen; + + mprAssert(dest); + + mprVarToString(&value, MPR_MAX_STRING, 0, src); + + if (mprVarIsValid(dest)) { + len = strlen(value); + oldBuf = dest->string; + oldLen = strlen(oldBuf); + buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); + dest->string = buf; + strcpy(&buf[oldLen], value); + + } else { + *dest = mprCreateStringVar(value, 1); + } + mprFree(value); +} + +/******************************************************************************/ +/* + * Exit with status + */ + +void ejsSetExitStatus(int eid, int status) +{ + Ejs *ep; + + if ((ep = ejsPtr(eid)) == NULL) { + mprAssert(ep); + return; + } + ep->exitStatus = status; + ep->flags |= EJS_FLAGS_EXIT; +} + +/******************************************************************************/ +/* + * Free an argument list + */ + +static void freeProc(EjsProc *proc) +{ + MprVar **argValues; + int i; + + if (proc->args) { + argValues = (MprVar**) proc->args->handles; + + for (i = 0; i < proc->args->max; i++) { + if (argValues[i]) { + mprDestroyVar(argValues[i]); + mprFree(argValues[i]); + mprRemoveFromArray(proc->args, i); + } + } + + mprDestroyArray(proc->args); + } + + if (proc->procName) { + mprFree(proc->procName); + proc->procName = NULL; + } +} + +/******************************************************************************/ +/* + * This function removes any new lines. Used for else cases, etc. + */ + +static void removeNewlines(Ejs *ep, int state) +{ + int tid; + + do { + tid = ejsLexGetToken(ep, state); + } while (tid == EJS_TOK_NEWLINE); + + ejsLexPutbackToken(ep, tid, ep->token); +} + +/******************************************************************************/ + +#else +void ejsParserDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/ejsProcs.c b/source4/lib/appweb/ejs/ejsProcs.c new file mode 100644 index 0000000000..c01f411161 --- /dev/null +++ b/source4/lib/appweb/ejs/ejsProcs.c @@ -0,0 +1,703 @@ +/* + * @file ejsProc.c + * @brief EJS support functions + */ +/********************************* Copyright **********************************/ +/* + * @copy default.g + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "ejsInternal.h" + +#if BLD_FEATURE_EJS + +/****************************** Forward Declarations **************************/ +/* + * Object constructors + */ +static int objectConsProc(EjsHandle eid, int argc, MprVar **argv); +static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv); +static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv); +static int numberConsProc(EjsHandle eid, int argc, MprVar **argv); +static int stringConsProc(EjsHandle eid, int argc, MprVar **argv); + +/* + * Core functions + */ +static int toStringProc(EjsHandle eid, int argc, MprVar **argv); +static int valueOfProc(EjsHandle eid, int argc, MprVar **argv); + +/* + * Triggers + */ +static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, + MprProperties *parentProperties, MprVar *prop, MprVar *newValue, + bool copyRef); + +/******************************************************************************/ +/* + * Routine to create the base common to all object types + */ + +MprVar ejsCreateObj(const char *name, int hashSize) +{ + MprVar o; + + o = mprCreateObjVar(name, hashSize); + if (o.type == MPR_TYPE_UNDEFINED) { + mprAssert(0); + return o; + } + + mprCreatePropertyValue(&o, "toString", + mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(&o, "valueOf", + mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE)); + return o; +} + +/******************************************************************************/ +/* + * Routine to destroy a variable + */ + +bool ejsDestroyVar(MprVar *obj) +{ + return mprDestroyVar(obj); +} + +/******************************************************************************/ +/* + * Routine to create the base array type + */ + +MprVar ejsCreateArray(const char *name, int size) +{ + MprVar obj, *lp, undef; + char idx[16]; + int i; + + /* Sanity limit for size of hash table */ + + obj = ejsCreateObj(name, max(size, 503)); + if (obj.type == MPR_TYPE_UNDEFINED) { + mprAssert(0); + return obj; + } + + undef = mprCreateUndefinedVar(); + for (i = 0; i < size; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(&obj, idx, &undef); + } + + lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size)); + mprAssert(lp); + + mprSetVarReadonly(lp, 1); + mprAddVarTrigger(lp, lengthTrigger); + + return obj; +} + +/******************************************************************************/ +/******************************** Constructors ********************************/ +/******************************************************************************/ +/* + * Object constructor. Nothing really done here. For future expansion. + */ + +static int objectConsProc(EjsHandle eid, int argc, MprVar **argv) +{ +#if XX_UNUSED_XX + MprVar *obj; + Ejs *ep; + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); +#endif + return 0; +} + +/******************************************************************************/ +/* + * Array constructor + */ + +static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj, *lp, undef; + Ejs *ep; + char idx[16]; + int i, max; + + objectConsProc(eid, argc, argv); + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + + if (argc == 1 && mprVarIsNumber(argv[0]->type)) { + /* + * x = new Array(size); + */ + undef = mprCreateUndefinedVar(); + max = (int) mprVarToInteger(argv[0]); + for (i = 0; i < max; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(obj, idx, &undef); + } + } else { + /* + * x = new Array(element0, element1, ..., elementN): + */ + max = argc; + for (i = 0; i < max; i++) { + mprItoa(i, idx, sizeof(idx)); + mprCreateProperty(obj, idx, argv[i]); + } + } + + lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); + mprAssert(lp); + + mprSetVarReadonly(lp, 1); + mprAddVarTrigger(lp, lengthTrigger); + + return 0; +} + +/******************************************************************************/ +/* + * Boolean constructor + */ + +static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +#if FUTURE +/* + * Date constructor + */ + +static int dateConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +#endif +/******************************************************************************/ +/* + * Number constructor + */ + +static int numberConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +/* + * String constructor + */ + +static int stringConsProc(EjsHandle eid, int argc, MprVar **argv) +{ + objectConsProc(eid, argc, argv); + return 0; +} + +/******************************************************************************/ +/********************************** Functions *********************************/ +/******************************************************************************/ + +static int toStringProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj; + Ejs *ep; + char *buf; + int radix; + + if (argc == 0) { + radix = 10; + + } else if (argc == 1) { + radix = (int) mprVarToInteger(argv[0]); + + } else { + mprAssert(0); + return -1; + } + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + mprVarToString(&buf, MPR_MAX_STRING, 0, obj); + mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY); + mprFree(buf); + + return 0; +} + +/******************************************************************************/ + +static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *obj; + Ejs *ep; + + if (argc != 0) { + mprAssert(0); + return -1; + } + + if((ep = ejsPtr(eid)) == NULL) { + return -1; + } + + obj = mprGetProperty(ep->local, "this", 0); + mprAssert(obj); + + switch (obj->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_PTR: + mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); + break; + + case MPR_TYPE_STRING: + mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0); + break; + + case MPR_TYPE_BOOL: + case MPR_TYPE_INT: +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: +#endif +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: +#endif + mprCopyVar(&ep->result, obj, 0); + break; + } + return 0; +} + +/******************************************************************************/ +/* + * Var access trigger on the Array.length property. Return the count of + * enumerable properties (don't count functions). + */ + +static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, + MprProperties *parentProperties, MprVar *prop, MprVar *newValue, + bool copyRef) +{ + switch (op) { + case MPR_VAR_READ: + /* + * Subtract one for the length property + * FUTURE -- need an API to access parentProperties + * FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE. + * API needs finer control. + */ + *newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1); + return MPR_TRIGGER_USE_NEW_VALUE; + + case MPR_VAR_WRITE: + return MPR_TRIGGER_ABORT; + + case MPR_VAR_CREATE_PROPERTY: + case MPR_VAR_DELETE_PROPERTY: + case MPR_VAR_DELETE: + default: + break; + } + return MPR_TRIGGER_PROCEED; +} + +/******************************************************************************/ +/**************************** Extension Functions *****************************/ +/******************************************************************************/ +/* + * Assert + */ + +static int assertProc(EjsHandle eid, int argc, MprVar **argv) +{ + bool b; + + if (argc < 1) { + ejsSetErrorMsg(eid, "usage: assert(condition)\n"); + return -1; + } + b = mprVarToBool(argv[0]); + if (b == 0) { + ejsSetErrorMsg(eid, "Assertion failure\n"); + return -1; + } + ejsSetReturnValue(eid, mprCreateBoolVar(b)); + return 0; +} + +/******************************************************************************/ +/* + * Exit + */ + +static int exitProc(EjsHandle eid, int argc, MprVar **argv) +{ + int status; + + if (argc < 1) { + ejsSetErrorMsg(eid, "usage: exit(status)\n"); + return -1; + } + status = (int) mprVarToInteger(argv[0]); + ejsSetExitStatus(eid, status); + + ejsSetReturnValue(eid, mprCreateStringVar("", 0)); + return 0; +} + +/******************************************************************************/ + +static void printVar(MprVar *vp, int recurseCount, int indent) +{ + MprVar *np; + char *buf; + int i; + + if (recurseCount > 5) { + write(1, "Skipping - recursion too deep\n", 29); + return; + } + + for (i = 0; i < indent; i++) { + write(1, " ", 2); + } + + if (vp->type == MPR_TYPE_OBJECT) { + if (vp->name) { + write(1, vp->name, strlen(vp->name)); + } else { + write(1, "unknown", 7); + } + write(1, ": {\n", 4); + np = mprGetFirstProperty(vp, MPR_ENUM_DATA); + while (np) { + if (strcmp(np->name, "local") == 0 || + strcmp(np->name, "global") == 0 || + strcmp(np->name, "this") == 0) { + np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); + continue; + } + printVar(np, recurseCount + 1, indent + 1); + np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); + if (np) { + write(1, ",\n", 2); + } + } + write(1, "\n", 1); + for (i = 0; i < indent; i++) { + write(1, " ", 2); + } + write(1, "}", 1); + + } else { + if (vp->name) { + write(1, vp->name, strlen(vp->name)); + } else { + write(1, "unknown", 7); + } + write(1, ": ", 2); + + /* FUTURE -- other types ? */ + mprVarToString(&buf, MPR_MAX_STRING, 0, vp); + if (vp->type == MPR_TYPE_STRING) { + write(1, "\"", 1); + } + write(1, buf, strlen(buf)); + if (vp->type == MPR_TYPE_STRING) { + write(1, "\"", 1); + } + mprFree(buf); + } +} + +/******************************************************************************/ +/* + * Print the args to stdout + */ + +static int printVarsProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *vp; + char *buf; + int i; + + for (i = 0; i < argc; i++) { + vp = argv[i]; + switch (vp->type) { + case MPR_TYPE_OBJECT: + printVar(vp, 0, 0); + break; + default: + mprVarToString(&buf, MPR_MAX_STRING, 0, vp); + write(1, buf, strlen(buf)); + mprFree(buf); + break; + } + } + write(1, "\n", 1); + + ejsSetReturnValue(eid, mprCreateStringVar("", 0)); + return 0; +} + +/******************************************************************************/ +/* + * Print the args to stdout + */ + +static int printProc(EjsHandle eid, int argc, MprVar **argv) +{ + char *buf; + int i; + + for (i = 0; i < argc; i++) { + mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]); + write(1, buf, strlen(buf)); + mprFree(buf); + } + return 0; +} + +/******************************************************************************/ +/* + * println + */ + +static int printlnProc(EjsHandle eid, int argc, MprVar **argv) +{ + printProc(eid, argc, argv); + write(1, "\n", 1); + return 0; +} + +/******************************************************************************/ +/* + * Trace + */ + +static int traceProc(EjsHandle eid, int argc, char **argv) +{ + if (argc == 1) { + mprLog(0, "%s", argv[0]); + + } else if (argc == 2) { + mprLog(atoi(argv[0]), "%s", argv[1]); + + } else { + ejsSetErrorMsg(eid, "Usage: trace([level], message)"); + return -1; + } + ejsSetReturnString(eid, ""); + return 0; +} + +/******************************************************************************/ +/* + * Return the object reference count + */ + +static int refCountProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *vp; + int count; + + vp = argv[0]; + if (vp->type == MPR_TYPE_OBJECT) { + count = mprGetVarRefCount(vp); + ejsSetReturnValue(eid, mprCreateIntegerVar(count)); + } else { + ejsSetReturnValue(eid, mprCreateIntegerVar(0)); + } + + return 0; +} + +/******************************************************************************/ +/* + * Evaluate a sub-script. It is evaluated in the same variable scope as + * the calling script / function. + */ + +static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv) +{ + MprVar *arg; + char *emsg; + int i; + + ejsSetReturnValue(eid, mprCreateUndefinedVar()); + + for (i = 0; i < argc; i++) { + arg = argv[i]; + if (arg->type != MPR_TYPE_STRING) { + continue; + } + if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) { + ejsSetErrorMsg(eid, "%s", emsg); + mprFree(emsg); + return -1; + } + } + /* + * Return with the value of the last expression + */ + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ +/* + * Define the standard properties and functions inherited by all script engines. + */ + +int ejsDefineStandardProperties(MprVar *obj) +{ +#if BLD_FEATURE_FLOATING_POINT + double d = 0.0; + + /* FUTURE - this generates warnings on some systems. This is okay. */ + + mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d)); + d = MAX_FLOAT; + mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d)); +#endif + mprCreatePropertyValue(obj, "null", mprCreateNullVar()); + mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); + mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); + mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); + +#if BLD_FEATURE_LEGACY_API + /* + * DEPRECATED: 2.0. + * So that ESP/ASP can ignore "language=javascript" statements + */ + mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0)); +#endif + + /* + * Extension functions + */ + mprCreatePropertyValue(obj, "assert", + mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "eval", + mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "exit", + mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "refCount", + mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "print", + mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "println", + mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "printVars", + mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "trace", + mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE)); + + /* + * Constructors + */ + mprCreatePropertyValue(obj, "Array", + mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Boolean", + mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Object", + mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "Number", + mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + mprCreatePropertyValue(obj, "String", + mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + + /* mprCreatePropertyValue(obj, "Date", + * mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + * mprCreatePropertyValue(obj, "Regexp", + * mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); + */ + + /* + * Can we use on var x = "string text"; + */ + return 0; +} + +/******************************************************************************/ + +#else +void ejsProcsDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_EJS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/miniMpr.c b/source4/lib/appweb/ejs/miniMpr.c new file mode 100644 index 0000000000..7dda4e7bd7 --- /dev/null +++ b/source4/lib/appweb/ejs/miniMpr.c @@ -0,0 +1,512 @@ +/* + * @file miniMpr.cpp + * @brief Mini Mbedthis Portable Runtime (MPR) + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +#include "lib/appweb/ejs/miniMpr.h" + +/************************************ Code ************************************/ +#if !BLD_APPWEB +#if !BLD_GOAHEAD_WEBSERVER + +static void *mpr_ctx; + +/* set the memory context to be used for all ejs variables */ +void mprSetCtx(TALLOC_CTX *ctx) +{ + mpr_ctx = ctx; +} + +/* return the memory context being used for all ejs variables */ +void *mprMemCtx(void) +{ + return mpr_ctx; +} + +void mprFree(void *ptr) +{ + talloc_free(ptr); +} + +void *mprMalloc(uint size) +{ + return talloc_size(mpr_ctx, size); +} + +/******************************************************************************/ + +void *mprRealloc(void *ptr, uint size) +{ + return talloc_realloc_size(mpr_ctx, ptr, size); +} + +/******************************************************************************/ + +char *mprStrdup(const char *str) +{ + if (str == 0) { + str = ""; + } + return talloc_strdup(mpr_ctx, str); +} + +/*****************************************************************************/ + +int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) +{ + va_list args; + char *buf; + int count; + + va_start(args, fmt); + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + va_end(args); + return count; +} + +/*****************************************************************************/ + +int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) +{ + char *buf; + int count; + + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + return count; +} + + +/*****************************************************************************/ +/* + * Format a number as a string. FUTURE -- reverse args to be standard. + * ie. mprItoa(char *userBuf, int bufsize, int value); + */ + +char *mprItoa(int value, char *buf, int width) +{ + char numBuf[16]; + char *cp, *dp, *endp; + int negative; + + cp = &numBuf[sizeof(numBuf)]; + *--cp = '\0'; + + if (value < 0) { + negative = 1; + value = -value; + width--; + } else { + negative = 0; + } + + do { + *--cp = '0' + (value % 10); + value /= 10; + } while (value > 0); + + if (negative) { + *--cp = '-'; + } + + dp = buf; + endp = &buf[width]; + while (dp < endp && *cp) { + *dp++ = *cp++; + } + *dp++ = '\0'; + return buf; +} + +/*****************************************************************************/ + +void mprLog(int level, const char *fmt, ...) +{ + va_list args; + char *buf; + + if (DEBUGLVL(level)) { + va_start(args, fmt); + mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); + va_end(args); + DEBUG(level, ("mprLog: %s", buf)); + mprFree(buf); + } +} + +/*****************************************************************************/ + +void mprBreakpoint(const char *file, int line, const char *cond) +{ + char *buf; + mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", + file, line, cond); + ejs_exception(buf); +} + +#endif /* !BLD_GOAHEAD_WEBSERVER */ +/*****************************************************************************/ +/* + * Create a general growable array structure + */ + +MprArray *mprCreateArray() +{ + MprArray *array; + int size; + + array = (MprArray*) mprMalloc(sizeof(MprArray)); + if (array == 0) { + return 0; + } + memset(array, 0, sizeof(MprArray)); + + size = MPR_ARRAY_INCR * sizeof(void*); + array->handles = (void**) mprMalloc(size); + if (array->handles == 0) { + mprFree(array); + return 0; + } + memset(array->handles, 0, size); + array->max = MPR_ARRAY_INCR; + array->used = 0; + return array; +} + +/*****************************************************************************/ +/* + * Dispose of the array. Callers responsibility to dispose of handle entries. + */ + +void mprDestroyArray(MprArray *array) +{ + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + mprFree(array->handles); + mprFree(array); +} + +/*****************************************************************************/ +/* + * Add an item to the array + */ + +int mprAddToArray(MprArray *array, void *item) +{ + int memsize, idx, len; + + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + if (array->used < array->max) { + idx = array->used++; + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + + for (idx = array->used; idx < array->max; idx++) { + if (array->handles[idx] == 0) { + array->used++; + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + } + + len = array->max + MPR_ARRAY_INCR; + memsize = len * sizeof(void*); + array->handles = (void**) mprRealloc((void*) array->handles, memsize); + if (array->handles == NULL) { + return -1; + } + memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); + array->max = len; + array->used++; + + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + + array->handles[idx] = item; + return idx; +} + +/*****************************************************************************/ +/* + * Remove from the array + */ + +int mprRemoveFromArray(MprArray *array, int idx) +{ + mprAssert(array); + mprAssert(array->max > 0); + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] != 0); + mprAssert(array->used > 0); + + array->handles[idx] = 0; + return --array->used; +} + +/*****************************************************************************/ +/* + * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() + */ + +char *mprStrTok(char *str, const char *delim, char **tok) +{ + char *start, *end; + int i; + + start = str ? str : *tok; + + if (start == 0) { + return 0; + } + + i = strspn(start, delim); + start += i; + if (*start == '\0') { + *tok = 0; + return 0; + } + end = strpbrk(start, delim); + if (end) { + *end++ = '\0'; + i = strspn(end, delim); + end += i; + } + *tok = end; + return start; +} + +/*****************************************************************************/ + +static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, + const char *delim, const char *src, va_list args) +{ + va_list ap; + char *dest, *dp; + const char *str; + int sepLen, addBytes, required; + + mprAssert(destp); + mprAssert(destMax > 0); + mprAssert(src); + + dest = *destp; + sepLen = (delim) ? strlen(delim) : 0; + +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + addBytes = 0; + str = src; + while (str) { + addBytes += strlen(str) + sepLen; + str = va_arg(ap, const char*); + } + + if (existingLen > 0) { + addBytes += sepLen; + } + required = existingLen + addBytes + 1; + if (required >= destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + + if (alloc) { + if (dest == 0) { + dest = (char*) mprMalloc(required); + } else { + dest = (char*) mprRealloc(dest, required); + } + } else { + dest = (char*) *destp; + } + + dp = &dest[existingLen]; + if (delim) { + strcpy(dp, delim); + dp += sepLen; + } + + if (addBytes > 0) { +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + str = src; + while (str) { + strcpy(dp, str); + dp += strlen(str); + str = va_arg(ap, char*); + if (delim && str) { + strcpy(dp, delim); + dp += sepLen; + } + } + } else if (dest == 0) { + dest = (char*) mprMalloc(1); + } + *dp = '\0'; + + *destp = dest; + mprAssert(dp < &dest[required]); + return required - 1; +} + +/*****************************************************************************/ + +int mprReallocStrcat(char **destp, int destMax, int existingLen, + const char *delim, const char *src,...) +{ + va_list ap; + int rc; + + va_start(ap, src); + rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); + va_end(ap); + return rc; +} + +/*****************************************************************************/ +/* + * Return the directory portion of a pathname into the users buffer. + */ + +int mprGetDirName(char *buf, int bufsize, char *path) +{ + char *cp; + int dlen; + + mprAssert(path); + mprAssert(buf); + mprAssert(bufsize > 0); + + cp = strrchr(path, '/'); + if (cp == 0) { +#if WIN + cp = strrchr(path, '\\'); + if (cp == 0) +#endif + { + buf[0] = '\0'; + return 0; + } + } + + if (cp == path && cp[1] == '\0') { + strcpy(buf, "."); + return 0; + } + + dlen = cp - path; + if (dlen < bufsize) { + if (dlen == 0) { + dlen++; + } + mprMemcpy(buf, bufsize, path, dlen); + buf[dlen] = '\0'; + return 0; + } + return MPR_ERR_WONT_FIT; +} + +/*****************************************************************************/ + +int mprStrcpy(char *dest, int destMax, const char *src) +{ + int len; + + mprAssert(dest); + mprAssert(destMax > 0); + mprAssert(src); + + len = strlen(src); + if (len >= destMax && len > 0) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (len > 0) { + memcpy(dest, src, len); + dest[len] = '\0'; + } else { + *dest = '\0'; + len = 0; + } + return len; +} + +/*****************************************************************************/ + +int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) +{ + mprAssert(dest); + mprAssert(destMax > nbytes); + mprAssert(src); + mprAssert(nbytes > 0); + + if (nbytes > destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (nbytes > 0) { + memcpy(dest, src, nbytes); + return nbytes; + } else { + return 0; + } +} + +/*****************************************************************************/ +#else +void miniMprDummy() {} +#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/miniMpr.h b/source4/lib/appweb/ejs/miniMpr.h new file mode 100644 index 0000000000..d431ebdc1b --- /dev/null +++ b/source4/lib/appweb/ejs/miniMpr.h @@ -0,0 +1,292 @@ +/* + * @file miniMpr.h + * @brief Mini Mbedthis Portable Runtime (MPR) Environment. + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +#ifndef _h_MINI_MPR +#define _h_MINI_MPR 1 + +/********************************** Includes **********************************/ +/* + * Find out about our configuration + */ +#ifndef _INCLUDES_H + #include "includes.h" +#endif + +/* allow this library to use strcpy() */ +#undef strcpy + #include "config.h" + +#if BLD_APPWEB + /* + * If building within AppWeb, use the full MPR + */ + #include "mpr.h" +#else + + #include + #include + #include + #include + #include + #include + #include + +#if !WIN + #include +#endif + +#if CE + #include + #include "CE/wincompat.h" +#endif + +#if LYNX + #include +#endif + +#if QNX4 + #include +#endif + #include + +/********************************** Defines ***********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if BLD_FEATURE_SQUEEZE +/* + * Reasonable length of a file path name to use in most cases where you know + * the expected file name and it is certain to be less than this limit. + */ +#define MPR_MAX_FNAME 128 +#define MPR_MAX_STRING 512 +#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ +#define MPR_MAX_HEAP_SIZE (32 * 1024) +#else +#define MPR_MAX_FNAME 256 +#define MPR_MAX_STRING 4096 +#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ +#define MPR_MAX_HEAP_SIZE (64 * 1024) +#endif + +/* + * Useful for debugging + */ +#define MPR_L __FILE__, __LINE__ + +#if BLD_FEATURE_ASSERT +#define mprAssert(C) \ + if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) +#else + #define mprAssert(C) if (1) ; else +#endif + +/* + * Standard MPR return and error codes + */ +#define MPR_ERR_BASE (-200) /* Error code */ +#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ +#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ +#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ +#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ +#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ +#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ +#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ +#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ +#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ +#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ +#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ +#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ +#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ +#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ +#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ +#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ +#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ +#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ +#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ +#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ +#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ +#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ +#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ +#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ +#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ +#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ +#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ +#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ +#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ +#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ + +/* + * Standard error severity and trace levels. These are ored with the error + * severities below. The MPR_LOG_MASK is used to extract the trace level + * from a flags word. We expect most apps to run with level 2 trace. + */ +#define MPR_FATAL 0 /* Fatal error. Cant continue. */ +#define MPR_ERROR 1 /* Hard error */ +#define MPR_WARN 2 /* Soft warning */ +#define MPR_CONFIG 2 /* Essential configuration settings */ +#define MPR_INFO 3 /* Informational only */ +#define MPR_DEBUG 4 /* Debug information */ +#define MPR_VERBOSE 9 /* Highest level of trace */ +#define MPR_LOG_MASK 0xf /* Level mask */ + +/* + * Error flags. Specify where the error should be sent to. Note that the + * product.xml setting "headless" will modify how errors are reported. + * Assert errors are trapped when in DEV mode. Otherwise ignored. + */ +#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ +#define MPR_LOG 0x20 /* Log the error in the O/S event log */ +#define MPR_USER 0x40 /* Display to the user */ +#define MPR_ALERT 0x80 /* Send a management alert */ +#define MPR_TRACE 0x100 /* Trace */ + +/* + * Error format flags + */ +#define MPR_RAW 0x200 /* Raw trace output */ + +/* + * Error line number information + */ +#define MPR_L __FILE__, __LINE__ + +typedef char* MprStr; + +#ifndef __cplusplus +typedef unsigned char uchar; +typedef int bool; +#endif + +/* + * Porters: put other operating system type defines here + */ +#if WIN + typedef unsigned int uint; + typedef __int64 int64; + typedef unsigned __int64 uint64; +#else +#define O_BINARY 0 +#ifndef uint + #define uint unsigned +#endif + __extension__ typedef long long int int64; + __extension__ typedef unsigned long long int uint64; +#endif + +/* + * Flexible array data type + */ +typedef struct { + int max; /* Size of the handles array */ + int used; /* Count of used entries in handles */ + void **handles; +} MprArray; + +#if BLD_FEATURE_SQUEEZE +#define MPR_ARRAY_INCR 8 +#else +#define MPR_ARRAY_INCR 16 +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/********************************* Prototypes *********************************/ +/* + * If running in the GoAhead WebServer, map some MPR routines to WebServer + * equivalents. + */ + +#if BLD_GOAHEAD_WEBSERVER +#include "uemf.h" +#define mprMalloc(size) balloc(B_L, size) +#define mprFree(ptr) bfreeSafe(B_L, ptr) +#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) +#define mprStrdup(ptr) bstrdup(B_L, ptr) +#define mprAllocSprintf fmtAlloc +#define mprAllocVsprintf fmtValloc +#define mprSprintf fmtStatic +#define mprItoa stritoa +#define mprLog trace +#define mprBreakpoint(file, line, cond) \ + error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) + +#else /* !BLD_GOAHEAD_WEBSERVER */ +/* #define mprMalloc malloc */ +#define mprSprintf snprintf +#define mtVsprintf vsnprintf +extern void *mprMalloc(uint size); +extern void *mprRealloc(void *ptr, uint size); +extern void mprFree(void *ptr); +extern char *mprStrdup(const char *str); +extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, + va_list args) PRINTF_ATTRIBUTE(3,0); +extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +extern char *mprItoa(int num, char *buf, int width); +extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern void mprBreakpoint(const char *file, int line, const char *msg); +#endif /* BLD_GOAHEAD_WEBSERVER */ + +extern MprArray *mprCreateArray(void); +extern void mprDestroyArray(MprArray *array); +extern int mprAddToArray(MprArray *array, void *item); +extern int mprRemoveFromArray(MprArray *array, int idx); +extern char *mprStrTok(char *str, const char *delim, char **tok); + +extern int mprGetDirName(char *buf, int bufsize, char *path); +extern int mprReallocStrcat(char **dest, int max, int existingLen, + const char *delim, const char *src, ...); +extern int mprStrcpy(char *dest, int destMax, const char *src); +extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); + +extern void mprSetCtx(void *ctx); +extern void *mprMemCtx(void); + +#ifdef __cplusplus +} +#endif +#endif /* !BLD_APPWEB */ +#endif /* _h_MINI_MPR */ + +/*****************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/var.c b/source4/lib/appweb/ejs/var.c new file mode 100644 index 0000000000..9d2afe5306 --- /dev/null +++ b/source4/lib/appweb/ejs/var.c @@ -0,0 +1,2197 @@ +/* + * @file var.c + * @brief MPR Universal Variable Type + * @overview + * + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ + +/* + * This module is NOT multithreaded. + * + * Properties are variables that are stored in an object type variable. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. + */ + +/********************************** Includes **********************************/ + +#include "var.h" + +/*********************************** Locals ***********************************/ +#if VAR_DEBUG + +static MprProperties objectList; /* Dummy head of objects list */ +static int objectCount = -1; /* Count of objects */ + +#endif +/***************************** Forward Declarations ***************************/ + +static int adjustRefCount(MprProperties *pp, int adj); +static int adjustVarRefCount(MprVar *vp, int adj); +static MprVar *allocProperty(const char *propertyName); +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); +static MprProperties + *createProperties(const char *name, int hashSize); +static bool freeVar(MprVar *vp, int force); +static bool freeVarStorage(MprVar *vp, int force); +static MprVar *getObjChain(MprProperties *pp, const char *property); +static int hash(MprProperties *pp, const char *property); +static bool releaseProperties(MprProperties *pp, int force); + +/*********************************** Code *************************************/ +/* + * Destroy a variable and all referenced variables. Release any referenced + * object regardless of whether other users still have references. Be VERY + * careful using this routine. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyAllVars(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all vars. + */ + return freeVar(vp, 1); +} + +/******************************************************************************/ +/* + * Destroy a variable. Release any referenced object (destroy if no other + * users are referencing). + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyVar(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all that have no other + * references. + */ + return freeVar(vp, 0); +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVar(MprVar *vp, int force) +{ + bool freed; + + mprAssert(vp); + + freed = freeVarStorage(vp, force); + + mprFree(vp->name); + mprFree(vp->fullName); + + if (vp->allocatedVar) { + mprFree(vp); + } else { + vp->name = 0; + vp->fullName = 0; + vp->type = MPR_TYPE_UNDEFINED; + } + return freed; +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVarStorage(MprVar *vp, int force) +{ + MprArray *argList; + bool freed; + int i; + + freed = 1; + mprAssert(vp); + + switch (vp->type) { + default: + break; + + case MPR_TYPE_STRING: + if (vp->allocatedData && vp->string != 0) { + mprFree(vp->string); + vp->string = 0; + vp->allocatedData = 0; + } + break; + + case MPR_TYPE_OBJECT: +#if VAR_DEBUG + /* + * Recurse through all properties and release / delete. Release the + * properties hash table. + */ + if (vp->properties->refCount > 1) { + mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } else { + mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } +#endif + if (vp->allocatedData) { + freed = releaseProperties(vp->properties, force); + } + vp->properties = 0; + break; + + case MPR_TYPE_FUNCTION: + if (vp->allocatedData) { + argList = vp->function.args; + for (i = 0; i < argList->max; i++) { + if (argList->handles[i] != 0) { + mprFree(argList->handles[i]); + } + } + mprDestroyArray(argList); + vp->function.args = 0; + mprFree(vp->function.body); + vp->function.body = 0; + } + break; + } + + vp->type = MPR_TYPE_UNDEFINED; + return freed; +} + +/******************************************************************************/ +/* + * Adjust the object reference count and return the currrent count of + * users. + */ + +static int adjustVarRefCount(MprVar *vp, int adj) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, adj); +} + +/******************************************************************************/ +/* + * Get the object reference count + */ + +int mprGetVarRefCount(MprVar *vp) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, 0); +} + +/******************************************************************************/ +/* + * Update the variable's name + */ + +void mprSetVarName(MprVar *vp, char *name) +{ + mprAssert(vp); + + mprFree(vp->name); + vp->name = mprStrdup(name); +} + +/******************************************************************************/ +/* + * Append to the variable's full name + */ + +void mprSetVarFullName(MprVar *vp, char *name) +{ +#if VAR_DEBUG + mprAssert(vp); + + mprFree(vp->fullName); + vp->fullName = mprStrdup(name); + if (vp->type == MPR_TYPE_OBJECT) { + if (strcmp(vp->properties->name, "this") == 0) { + mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); + } + } +#endif +} + +/******************************************************************************/ +/* + * Make a var impervious to recursive forced deletes. + */ + +void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) +{ + mprAssert(vp); + + if (vp->type == MPR_TYPE_OBJECT && vp->properties) { + vp->properties->deleteProtect = deleteProtect; + } +} + +/******************************************************************************/ +/* + * Make a variable readonly. Can still be deleted. + */ + +void mprSetVarReadonly(MprVar *vp, int readonly) +{ + mprAssert(vp); + + vp->readonly = readonly; +} + +/******************************************************************************/ + +MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) +{ + MprVarTrigger oldTrigger; + + mprAssert(vp); + mprAssert(fn); + + oldTrigger = vp->trigger; + vp->trigger = fn; + return oldTrigger; +} + +/******************************************************************************/ + +MprType mprGetVarType(MprVar *vp) +{ + mprAssert(vp); + + return vp->type; +} + +/******************************************************************************/ +/********************************** Properties ********************************/ +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. + */ + +MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, + MprVar *newValue) +{ + MprVar *prop, *last; + int bucketIndex; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + /* + * See if property already exists and locate the bucket to hold the + * property reference. + */ + last = 0; + bucketIndex = hash(obj->properties, propertyName); + prop = obj->properties->buckets[bucketIndex]; + + /* + * Find the property in the hash chain if it exists + */ + for (last = 0; prop; last = prop, prop = prop->forw) { + if (prop->name[0] == propertyName[0] && + strcmp(prop->name, propertyName) == 0) { + break; + } + } + + if (prop) { + /* FUTURE -- remove. Just for debug. */ + mprAssert(prop == 0); + mprLog(0, "Attempting to create property %s in object %s\n", + propertyName, obj->name); + return 0; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, + newValue, 0) == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Create a new property + */ + prop = allocProperty(propertyName); + if (prop == 0) { + mprAssert(prop); + return 0; + } + + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + + prop->bucketIndex = bucketIndex; + if (last) { + last->forw = prop; + } else { + obj->properties->buckets[bucketIndex] = prop; + } + prop->parentProperties = obj->properties; + + /* + * Update the item counts + */ + obj->properties->numItems++; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems++; + } + + return prop; +} + +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. Same as + * mprCreateProperty except that the new value is passed by value rather than + * by pointer. + */ + +MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) +{ + return mprCreateProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Create a new property + */ + +static MprVar *allocProperty(const char *propertyName) +{ + MprVar *prop; + + prop = (MprVar*) mprMalloc(sizeof(MprVar)); + if (prop == 0) { + mprAssert(prop); + return 0; + } + memset(prop, 0, sizeof(MprVar)); + prop->allocatedVar = 1; + prop->name = mprStrdup(propertyName); + prop->forw = (MprVar*) 0; + + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it doesn not already exist. + */ + +MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) +{ + MprVar *prop, triggerValue; + int rc; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(0); + return 0; + } + + prop = mprGetProperty(obj, propertyName, 0); + if (prop == 0) { + return mprCreateProperty(obj, propertyName, newValue); + } + + if (obj->trigger) { + /* + * Call the trigger before the update and pass it the new value. + */ + triggerValue = *newValue; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + /* + * Trigger must copy to triggerValue a variable that is not + * a structure copy of the existing data. + */ + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return prop; + } + } + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it does not already exist. Same as mprSetProperty except that the + * new value is passed by value rather than by pointer. + */ + +MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) +{ + return mprSetProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Delete a property from this object + */ + +int mprDeleteProperty(MprVar *obj, const char *property) +{ + MprVar *prop, *last; + char *cp; + int bucketIndex; + + mprAssert(obj); + mprAssert(property && *property); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + last = 0; + bucketIndex = hash(obj->properties, property); + if ((prop = obj->properties->buckets[bucketIndex]) != 0) { + for ( ; prop; prop = prop->forw) { + cp = prop->name; + if (cp[0] == property[0] && strcmp(cp, property) == 0) { + break; + } + last = prop; + } + } + if (prop == (MprVar*) 0) { + mprAssert(prop); + return MPR_ERR_NOT_FOUND; + } + if (prop->readonly) { + mprAssert(! prop->readonly); + return MPR_ERR_READ_ONLY; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) + == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + } + } + + if (last) { + last->forw = prop->forw; + } else { + obj->properties->buckets[bucketIndex] = prop->forw; + } + + obj->properties->numItems--; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems--; + } + + mprDestroyVar(prop); + + return 0; +} + +/******************************************************************************/ +/* + * Find a property in an object and return a pointer to it. If a value arg + * is supplied, then copy the data into the var. + */ + +MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) +{ + MprVar *prop, triggerValue; + int rc; + + if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || + *property == '\0') { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + + for (prop = getObjChain(obj->properties, property); prop; + prop = prop->forw) { + if (prop->name && + prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { + break; + } + } + if (prop == 0) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + if (value) { + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + /* + * Pass the trigger the current read value and may receive + * a new value. + */ + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + } + } + /* + * Clone. No copy. + */ + *value = *prop; + } + return prop; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns the property's value. It does not + * copy object/string data but returns a pointer directly into the variable. + * The caller does not and should not call mprDestroy on the returned value. + * If value is null, just read the property and run triggers. + */ + +int mprReadProperty(MprVar *prop, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + if (value) { + *value = *prop; + + /* + * Just so that if the user calls mprDestroyVar on value, it will do no + * harm. + */ + value->allocatedVar = 0; + value->allocatedData = 0; + } + return 0; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns a copy of the property variable. + * However, if the property is an object or string, it returns a copy of the + * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, + * then the underlying objects and strings data will be copied as well. If + * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If + * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the + * user must call mprDestroyVar to free resources. This routine will run any + * registered triggers which may modify the value the user receives (without + * updating the properties real value). + * + * WARNING: the args are reversed to most other APIs. This conforms to the + * strcpy(dest, src) standard instead. + */ + +int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + mprAssert(dest); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, copyDepth); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + mprCopyVar(dest, prop, copyDepth); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWriteProperty(MprVar *vp, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(vp); + mprAssert(value); + + if (vp->readonly) { + return MPR_ERR_READ_ONLY; + } + + if (vp->trigger) { + triggerValue = *value; + + rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + /* Fall through */ + } + + copyVarCore(vp, value, MPR_SHALLOW_COPY); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWritePropertyValue(MprVar *vp, MprVar value) +{ + mprAssert(vp); + + return mprWriteProperty(vp, &value); +} + +/******************************************************************************/ +/* + * Get the count of properties. + */ + +int mprGetPropertyCount(MprVar *vp, int includeFlags) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + return 0; + } + if (includeFlags == MPR_ENUM_DATA) { + return vp->properties->numDataItems; + } else { + return vp->properties->numItems; + } +} + +/******************************************************************************/ +/* + * Get the first property in an object. Used for walking all properties in an + * object. + */ + +MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) +{ + MprVar *prop; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + for (i = 0; i < (int) obj->properties->hashSize; i++) { + for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { + if (prop) { + if (mprVarIsFunction(prop->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return prop; + } + break; + } + } + return 0; +} + +/******************************************************************************/ +/* + * Get the next property in sequence. + */ + +MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) +{ + MprProperties *properties; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + properties = obj->properties; + + if (last->forw) { + return last->forw; + } + + for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { + for (last = properties->buckets[i]; last; last = last->forw) { + if (mprVarIsFunction(last->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return last; + } + } + return 0; +} + +/******************************************************************************/ +/************************** Internal Support Routines *************************/ +/******************************************************************************/ +/* + * Create an hash table to hold and index properties. Properties are just + * variables which may contain primitive data types, functions or other + * objects. The hash table is the essence of an object. HashSize specifies + * the size of the hash table to use and should be a prime number. + */ + +static MprProperties *createProperties(const char *name, int hashSize) +{ + MprProperties *pp; + + if (hashSize < 7) { + hashSize = 7; + } + if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { + mprAssert(0); + return 0; + } + mprAssert(pp); + memset(pp, 0, sizeof(MprProperties)); + + pp->numItems = 0; + pp->numDataItems = 0; + pp->hashSize = hashSize; + pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); + mprAssert(pp->buckets); + memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); + pp->refCount = 1; + +#if VAR_DEBUG + if (objectCount == -1) { + objectCount = 0; + objectList.next = objectList.prev = &objectList; + } + + mprStrcpy(pp->name, sizeof(pp->name), name); + pp->next = &objectList; + pp->prev = objectList.prev; + objectList.prev->next = pp; + objectList.prev = pp; + objectCount++; +#endif + return pp; +} + +/******************************************************************************/ +/* + * Release an object's properties hash table. If this is the last person + * using it, free it. Return TRUE if the object is released. + */ + +static bool releaseProperties(MprProperties *obj, int force) +{ + MprProperties *pp; + MprVar *prop, *forw; + int i; + + mprAssert(obj); + mprAssert(obj->refCount > 0); + +#if VAR_DEBUG + /* + * Debug sanity check + */ + mprAssert(obj->refCount < 20); +#endif + + if (--obj->refCount > 0 && !force) { + return 0; + } + +#if VAR_DEBUG + mprAssert(obj->prev); + mprAssert(obj->next); + mprAssert(obj->next->prev); + mprAssert(obj->prev->next); + obj->next->prev = obj->prev; + obj->prev->next = obj->next; + objectCount--; +#endif + + for (i = 0; i < (int) obj->hashSize; i++) { + for (prop = obj->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->type == MPR_TYPE_OBJECT) { + + if (prop->properties == obj) { + /* Self reference */ + continue; + } + pp = prop->properties; + if (pp->visited) { + continue; + } + + pp->visited = 1; + if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { + pp->visited = 0; + } + + } else { + freeVar(prop, force); + } + } + } + + mprFree((void*) obj->buckets); + mprFree((void*) obj); + + return 1; +} + +/******************************************************************************/ +/* + * Adjust the reference count + */ + +static int adjustRefCount(MprProperties *pp, int adj) +{ + mprAssert(pp); + + /* + * Debug sanity check + */ + mprAssert(pp->refCount < 20); + + return pp->refCount += adj; +} + +/******************************************************************************/ +#if VAR_DEBUG +/* + * Print objects held + */ + +void mprPrintObjects(char *msg) +{ + MprProperties *pp, *np; + MprVar *prop, *forw; + char *buf; + int i; + + mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); + pp = objectList.next; + while (pp != &objectList) { + mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", + pp->name, pp, pp->refCount, pp->numItems); + for (i = 0; i < (int) pp->hashSize; i++) { + for (prop = pp->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->properties == pp) { + /* Self reference */ + continue; + } + mprVarToString(&buf, MPR_MAX_STRING, 0, prop); + if (prop->type == MPR_TYPE_OBJECT) { + np = objectList.next; + while (np != &objectList) { + if (prop->properties == np) { + break; + } + np = np->next; + } + if (prop->properties == np) { + mprLog(7, " %s: OBJECT 0x%x, <%s>\n", + prop->name, prop->properties, prop->fullName); + } else { + mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", + prop->name, buf, prop->fullName); + } + } else { + mprLog(7, " %s: <%s> = %s\n", prop->name, + prop->fullName, buf); + } + mprFree(buf); + } + } + pp = pp->next; + } +} + +/******************************************************************************/ + +void mprPrintObjRefCount(MprVar *vp) +{ + mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, + vp->properties->refCount); +} + +#endif +/******************************************************************************/ +/* + * Get the bucket chain containing a property. + */ + +static MprVar *getObjChain(MprProperties *obj, const char *property) +{ + mprAssert(obj); + + return obj->buckets[hash(obj, property)]; +} + +/******************************************************************************/ +/* + * Fast hash. The history of this algorithm is part of lost computer science + * folk lore. + */ + +static int hash(MprProperties *pp, const char *property) +{ + uint sum; + + mprAssert(pp); + mprAssert(property); + + sum = 0; + while (*property) { + sum += (sum * 33) + *property++; + } + + return sum % pp->hashSize; +} + +/******************************************************************************/ +/*********************************** Constructors *****************************/ +/******************************************************************************/ +/* + * Initialize an undefined value. + */ + +MprVar mprCreateUndefinedVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_UNDEFINED; + return v; +} + +/******************************************************************************/ +/* + * Initialize an null value. + */ + +MprVar mprCreateNullVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_NULL; + return v; +} + +/******************************************************************************/ + +MprVar mprCreateBoolVar(bool value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_BOOL; + v.boolean = value; + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_CFUNCTION; + v.cFunction.fn = fn; + v.cFunction.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, + int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING_CFUNCTION; + v.cFunctionWithStrings.fn = fn; + v.cFunctionWithStrings.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +/* + * Initialize an opaque pointer. + */ + +MprVar mprCreatePtrVar(void *ptr) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_PTR; + v.ptr = ptr; + + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Initialize a floating value. + */ + +MprVar mprCreateFloatVar(double value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FLOAT; + v.floating = value; + return v; +} + +#endif +/******************************************************************************/ +/* + * Initialize an integer value. + */ + +MprVar mprCreateIntegerVar(int value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT; + v.integer = value; + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Initialize a 64-bit integer value. + */ + +MprVar mprCreateInteger64Var(int64 value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT64; + v.integer64 = value; + return v; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Initialize an number variable. Type is defined by configure. + */ + +MprVar mprCreateNumberVar(MprNum value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = BLD_FEATURE_NUM_TYPE_ID; +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + v.integer64 = value; +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + v.float = value; +#else + v.integer = value; +#endif + return v; +} + +/******************************************************************************/ +/* + * Initialize a (bare) JavaScript function. args and body can be null. + */ + +MprVar mprCreateFunctionVar(char *args, char *body, int flags) +{ + MprVar v; + char *cp, *arg, *last; + int aid; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FUNCTION; + v.flags = flags; + + v.function.args = mprCreateArray(); + + if (args) { + args = mprStrdup(args); + arg = mprStrTok(args, ",", &last); + while (arg) { + while (isspace((int) *arg)) + arg++; + for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { + if (!isspace((int) *cp)) { + break; + } + } + cp[1] = '\0'; + + aid = mprAddToArray(v.function.args, mprStrdup(arg)); + arg = mprStrTok(0, ",", &last); + } + mprFree(args); + } + + if (body) { + v.function.body = mprStrdup(body); + } + v.allocatedData = 1; + return v; +} + +/******************************************************************************/ +/* + * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the + * memory allocation for the properties table failed. + */ + +MprVar mprCreateObjVar(const char *name, int hashSize) +{ + MprVar v; + + mprAssert(name && *name); + + memset(&v, 0x0, sizeof(MprVar)); + v.type = MPR_TYPE_OBJECT; + if (hashSize <= 0) { + hashSize = MPR_DEFAULT_HASH_SIZE; + } + v.properties = createProperties(name, hashSize); + if (v.properties == 0) { + /* Indicate failed memory allocation */ + v.type = MPR_TYPE_UNDEFINED; + } + v.allocatedData = 1; + v.name = mprStrdup(name); + mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); + return v; +} + +/******************************************************************************/ +/* + * Initialize a string value. + */ + +MprVar mprCreateStringVar(const char *value, bool allocate) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING; + if (value == 0) { + v.string = ""; + } else if (allocate) { + v.string = mprStrdup(value); + v.allocatedData = 1; + } else { + v.string = (char*) value; + } + return v; +} + +/******************************************************************************/ +/* + * Copy an objects core value (only). This preserves the destination object's + * name. This implements copy by reference for objects and copy by value for + * strings and other types. Caller must free dest prior to calling. + */ + +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) +{ + MprVarTrigger saveTrigger; + MprVar *srcProp, *destProp, *last; + char **srcArgs; + int i; + + mprAssert(dest); + mprAssert(src); + + if (dest == src) { + return; + } + + /* + * FUTURE: we should allow read-only triggers where the value is never + * stored in the object. Currently, triggers override the readonly + * status. + */ + + if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { + mprAssert(0); + return; + } + + if (dest->type != MPR_TYPE_UNDEFINED) { + saveTrigger = dest->trigger; + freeVarStorage(dest, 0); + } else { + saveTrigger = 0; + } + + switch (src->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + break; + + case MPR_TYPE_BOOL: + dest->boolean = src->boolean; + break; + + case MPR_TYPE_PTR: + dest->ptr = src->ptr; + break; + + case MPR_TYPE_STRING_CFUNCTION: + dest->cFunctionWithStrings = src->cFunctionWithStrings; + break; + + case MPR_TYPE_CFUNCTION: + dest->cFunction = src->cFunction; + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + dest->floating = src->floating; + break; +#endif + + case MPR_TYPE_INT: + dest->integer = src->integer; + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + dest->integer64 = src->integer64; + break; +#endif + + case MPR_TYPE_OBJECT: + if (copyDepth == MPR_DEEP_COPY) { + + dest->properties = createProperties(src->name, + src->properties->hashSize); + dest->allocatedData = 1; + + for (i = 0; i < (int) src->properties->hashSize; i++) { + last = 0; + for (srcProp = src->properties->buckets[i]; srcProp; + srcProp = srcProp->forw) { + if (srcProp->visited) { + continue; + } + destProp = allocProperty(srcProp->name); + if (destProp == 0) { + mprAssert(destProp); + return; + } + + destProp->bucketIndex = i; + if (last) { + last->forw = destProp; + } else { + dest->properties->buckets[i] = destProp; + } + destProp->parentProperties = dest->properties; + + /* + * Recursively copy the object + */ + srcProp->visited = 1; + copyVarCore(destProp, srcProp, copyDepth); + srcProp->visited = 0; + last = srcProp; + } + } + dest->properties->numItems = src->properties->numItems; + dest->properties->numDataItems = src->properties->numDataItems; + dest->allocatedData = 1; + + } else if (copyDepth == MPR_SHALLOW_COPY) { + dest->properties = src->properties; + adjustVarRefCount(src, 1); + dest->allocatedData = 1; + + } else { + dest->properties = src->properties; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_FUNCTION: + if (copyDepth != MPR_NO_COPY) { + dest->function.args = mprCreateArray(); + srcArgs = (char**) src->function.args->handles; + for (i = 0; i < src->function.args->max; i++) { + if (srcArgs[i]) { + mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); + } + } + dest->function.body = mprStrdup(src->function.body); + dest->allocatedData = 1; + } else { + dest->function.args = src->function.args; + dest->function.body = src->function.body; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_STRING: + if (src->string && copyDepth != MPR_NO_COPY) { + dest->string = mprStrdup(src->string); + dest->allocatedData = 1; + } else { + dest->string = src->string; + dest->allocatedData = 0; + } + break; + } + + dest->type = src->type; + dest->flags = src->flags; + dest->trigger = saveTrigger; + + /* + * Just for safety + */ + dest->spare = 0; +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) +{ + mprAssert(dest); + mprAssert(src); + + copyVarCore(dest, src, copyDepth); + + mprFree(dest->name); + dest->name = mprStrdup(src->name); + +#if VAR_DEBUG + if (src->type == MPR_TYPE_OBJECT) { + + mprFree(dest->fullName); + dest->fullName = mprStrdup(src->fullName); + + mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", + dest->name, dest->fullName, dest->properties, + dest->properties->refCount); + } +#endif +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) +{ + mprAssert(dest); + + mprCopyVar(dest, &src, copyDepth); +} + +/******************************************************************************/ +/* + * Copy an object. This implements copy by reference for objects and copy by + * value for strings and other types. Caller must free dest prior to calling. + */ + +MprVar *mprDupVar(MprVar *src, int copyDepth) +{ + MprVar *dest; + + mprAssert(src); + + dest = (MprVar*) mprMalloc(sizeof(MprVar)); + memset(dest, 0, sizeof(MprVar)); + + mprCopyVar(dest, src, copyDepth); + return dest; +} + +/******************************************************************************/ +/* + * Convert a value to a text based representation of its value + * FUTURE -- conver this to use the format string in all cases. Allow + * arbitrary format strings. + */ + +void mprVarToString(char** out, int size, char *fmt, MprVar *obj) +{ + char *src; + + mprAssert(out); + + *out = NULL; + + if (obj->trigger) { + mprReadProperty(obj, 0); + } + + switch (obj->type) { + case MPR_TYPE_UNDEFINED: + /* FUTURE -- spec says convert to "undefined" */ + *out = mprStrdup(""); + break; + + case MPR_TYPE_NULL: + *out = mprStrdup("null"); + break; + + case MPR_TYPE_PTR: + mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); + break; + + case MPR_TYPE_BOOL: + if (obj->boolean) { + *out = mprStrdup("true"); + } else { + *out = mprStrdup("false"); + } + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%f", obj->floating); + } else { + mprAllocSprintf(out, size, fmt, obj->floating); + } + break; +#endif + + case MPR_TYPE_INT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%d", obj->integer); + } else { + mprAllocSprintf(out, size, fmt, obj->integer); + } + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + if (fmt == NULL || *fmt == '\0') { +#if BLD_GOAHEAD_WEBSERVER + mprAllocSprintf(out, size, "%d", (int) obj->integer64); +#else + mprAllocSprintf(out, size, "%Ld", obj->integer64); +#endif + } else { + mprAllocSprintf(out, size, fmt, obj->integer64); + } + break; +#endif + + case MPR_TYPE_CFUNCTION: + mprAllocSprintf(out, size, "[C Function]"); + break; + + case MPR_TYPE_STRING_CFUNCTION: + mprAllocSprintf(out, size, "[C StringFunction]"); + break; + + case MPR_TYPE_FUNCTION: + mprAllocSprintf(out, size, "[JavaScript Function]"); + break; + + case MPR_TYPE_OBJECT: + /* FUTURE -- really want: [object class: name] */ + mprAllocSprintf(out, size, "[object %s]", obj->name); + break; + + case MPR_TYPE_STRING: + src = obj->string; + + mprAssert(src); + if (fmt && *fmt) { + mprAllocSprintf(out, size, fmt, src); + + } else if (src == NULL) { + *out = mprStrdup("null"); + + } else { + *out = mprStrdup(src); + } + break; + + default: + mprAssert(0); + } +} + +/******************************************************************************/ +/* + * Parse a string based on formatting instructions and intelligently + * create a variable. + */ + +MprVar mprParseVar(char *buf, MprType preferredType) +{ + MprType type = MPR_TYPE_UNDEFINED; + char *cp; + + mprAssert(buf); + + if (preferredType == MPR_TYPE_UNDEFINED) { + if (*buf == '-') { + type = MPR_NUM_VAR; + + } else if (!isdigit((int) *buf)) { + if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { + type = MPR_TYPE_BOOL; + } else { + type = MPR_TYPE_STRING; + } + + } else if (isdigit((int) *buf)) { + type = MPR_NUM_VAR; + cp = buf; + if (*cp && tolower((unsigned char)cp[1]) == 'x') { + cp = &cp[2]; + } + for (cp = buf; *cp; cp++) { + if (! isdigit((unsigned char) *cp)) { + break; + } + } + + if (*cp != '\0') { +#if BLD_FEATURE_FLOATING_POINT + if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { + type = MPR_TYPE_FLOAT; + } else +#endif + { + type = MPR_NUM_VAR; + } + } + } + } else { + type = preferredType; + } + + switch (type) { + case MPR_TYPE_OBJECT: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_PTR: + default: + break; + + case MPR_TYPE_BOOL: + return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); + + case MPR_TYPE_INT: + return mprCreateIntegerVar(mprParseInteger(buf)); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return mprCreateInteger64Var(mprParseInteger64(buf)); +#endif + + case MPR_TYPE_STRING: + if (strcmp(buf, "null") == 0) { + return mprCreateNullVar(); + } else if (strcmp(buf, "undefined") == 0) { + return mprCreateUndefinedVar(); + } + + return mprCreateStringVar(buf, 1); + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return mprCreateFloatVar(atof(buf)); +#endif + + } + return mprCreateUndefinedVar(); +} + +/******************************************************************************/ +/* + * Convert the variable to a boolean. Only for primitive types. + */ + +bool mprVarToBool(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_PTR: + return (vp->ptr != NULL); + + case MPR_TYPE_BOOL: + return vp->boolean; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return (vp->floating != 0 && !mprIsNan(vp->floating)); +#endif + + case MPR_TYPE_INT: + return (vp->integer != 0); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (vp->integer64 != 0); +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return (vp->string[0] != '\0'); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the variable to a floating point number. Only for primitive types. + */ + +double mprVarToFloat(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1.0 : 0.0; + + case MPR_TYPE_FLOAT: + return vp->floating; + + case MPR_TYPE_INT: + return (double) vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (double) vp->integer64; +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return atof(vp->string); + } + + /* Not reached */ + return 0; +} + +#endif +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprVarToNumber(const MprVar *vp) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprVarToInteger64(vp); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprVarToFloat(vp); +#else + return mprVarToInteger(vp); +#endif +} + +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprParseNumber(char *s) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprParseInteger64(s); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprParseFloat(s); +#else + return mprParseInteger(s); +#endif +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Convert the variable to an Integer64 type. Only works for primitive types. + */ + +int64 mprVarToInteger64(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int64) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + + case MPR_TYPE_INT64: + return vp->integer64; + + case MPR_TYPE_STRING: + return mprParseInteger64(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer64. + */ + +int64 mprParseInteger64(char *str) +{ + char *cp; + int64 num64; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num64 = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num64 = (*cp - '0') + (num64 * 10); + cp++; + } + } else { + cp++; + if (tolower((unsigned char)*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c)) { + num64 = (c - '0') + (num64 * radix); + } else if (c >= 'a' && c <= 'f') { + num64 = (c - 'a') + (num64 * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c) && c < '8') { + num64 = (c - '0') + (num64 * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num64; + } + return num64; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Convert the variable to an Integer type. Only works for primitive types. + */ + +int mprVarToInteger(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (int) vp->integer64; +#endif + + case MPR_TYPE_STRING: + return mprParseInteger(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer. + */ + +int mprParseInteger(char *str) +{ + char *cp; + int num; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num = (*cp - '0') + (num * 10); + cp++; + } + } else { + cp++; + if (tolower((unsigned char)*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c)) { + num = (c - '0') + (num * radix); + } else if (c >= 'a' && c <= 'f') { + num = (c - 'a') + (num * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c) && c < '8') { + num = (c - '0') + (num * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num; + } + return num; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the string buffer to an Floating. + */ + +double mprParseFloat(char *str) +{ + return atof(str); +} + +/******************************************************************************/ + +bool mprIsNan(double f) +{ +#if WIN + return _isnan(f); +#elif VXWORKS + /* FUTURE */ + return (0); +#else + return (f == FP_NAN); +#endif +} +/******************************************************************************/ + +bool mprIsInfinite(double f) +{ +#if WIN + return !_finite(f); +#elif VXWORKS + /* FUTURE */ + return (0); +#else + return (f == FP_INFINITE); +#endif +} + +#endif /* BLD_FEATURE_FLOATING_POINT */ +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/ejs/var.h b/source4/lib/appweb/ejs/var.h new file mode 100644 index 0000000000..8ed13a4995 --- /dev/null +++ b/source4/lib/appweb/ejs/var.h @@ -0,0 +1,496 @@ +/* + * @file var.h + * @brief MPR Universal Variable Type + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ +/* + * Variables can efficiently store primitive types and can hold references to + * objects. Objects can store properties which are themselves variables. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. A variable may store one of + * the following types: + * + * string, integer, integer-64bit, C function, C function with string args, + * Javascript function, Floating point number, boolean value, Undefined + * value and the Null value. + * + * Variables have names while objects may be referenced by multiple variables. + * Objects use reference counting for garbage collection. + * + * This module is not thread safe for performance and compactness. It relies + * on upper modules to provide thread synchronization as required. The API + * provides primitives to get variable/object references or to get copies of + * variables which will help minimize required lock times. + */ + +#ifndef _h_MPR_VAR +#define _h_MPR_VAR 1 + +/********************************* Includes ***********************************/ + +#include "miniMpr.h" + +/********************************** Defines ***********************************/ + +/* + * Define VAR_DEBUG if you want to track objects. However, this code is not + * thread safe and you need to run the server single threaded. + * + * #define VAR_DEBUG 1 + */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Forward declare types + */ +struct MprProperties; +struct MprVar; + +/* + * Possible variable types. Don't use enum because we need to be able to + * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. + */ +typedef int MprType; +#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ +#define MPR_TYPE_NULL 1 /* Value defined to be null. */ +#define MPR_TYPE_BOOL 2 /* Boolean type. */ +#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ +#define MPR_TYPE_FLOAT 4 /* Floating point number */ +#define MPR_TYPE_INT 5 /* Integer number */ +#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ +#define MPR_TYPE_OBJECT 7 /* Object reference */ +#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ +#define MPR_TYPE_STRING 9 /* String (immutable) */ +#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ +#define MPR_TYPE_PTR 11 /* Opaque pointer */ + +/* + * Create a type for the default number type + * Config.h will define the default number type. For example: + * + * BLD_FEATURE_NUM_TYPE=int + * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT + */ + +/** + * Set to the type used for MPR numeric variables. Will equate to int, int64 + * or double. + */ +typedef BLD_FEATURE_NUM_TYPE MprNum; + +/** + * Set to the MPR_TYPE used for MPR numeric variables. Will equate to + * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. + */ +#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID +#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID + +/* + * Return TRUE if a variable is a function type + */ +#define mprVarIsFunction(type) \ + (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ + type == MPR_TYPE_CFUNCTION) + +/* + * Return TRUE if a variable is a numeric type + */ +#define mprVarIsNumber(type) \ + (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) + +/* + * Return TRUE if a variable is a boolean + */ +#define mprVarIsBoolean(type) \ + (type == MPR_TYPE_BOOL) +#define mprVarIsString(type) \ + (type == MPR_TYPE_STRING) +#define mprVarIsObject(type) \ + (type == MPR_TYPE_OBJECT) +#define mprVarIsFloating(type) \ + (type == MPR_TYPE_FLOAT) +#define mprVarIsPtr(type) \ + (type == MPR_TYPE_PTR) +#define mprVarIsUndefined(var) \ + ((var)->type == MPR_TYPE_UNDEFINED) +#define mprVarIsNull(var) \ + ((var)->type == MPR_TYPE_NULL) +#define mprVarIsValid(var) \ + (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) + +#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ + +#if BLD_FEATURE_SQUEEZE +#define MPR_MAX_VAR 64 /* Max var full name */ +#else +#define MPR_MAX_VAR 512 +#endif + +#ifndef __NO_PACK +#pragma pack(2) +#endif /* _NO_PACK */ + +/* + * Function signatures + */ +typedef int MprVarHandle; +typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, + struct MprVar **argv); +typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, + char **argv); + +/* + * Triggers + */ +typedef enum { + MPR_VAR_WRITE, /* This property is being updated */ + MPR_VAR_READ, /* This property is being read */ + MPR_VAR_CREATE_PROPERTY, /* A property is being created */ + MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ + MPR_VAR_DELETE /* This object is being deleted */ +} MprVarTriggerOp; + +/* + * Trigger function return codes. + */ +typedef enum { + MPR_TRIGGER_ABORT, /* Abort the current operation */ + MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ + MPR_TRIGGER_PROCEED /* Proceed with the operation */ +} MprVarTriggerStatus; + +/* + * The MprVarTrigger arguments have the following meaning: + * + * op The operation being performed. See MprVarTriggerOp. + * parentProperties Pointer to the MprProperties structure. + * vp Pointer to the property that registered the trigger. + * newValue New value (see below for more details). + * copyDepth Specify what data items to copy. + * + * For VAR_READ, newVar is set to a temporary variable that the trigger + * function may assign a value to be returned instead of the actual + * property value. + * For VAR_WRITE, newValue holds the new value. The old existing value may be + * accessed via vp. + * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. + * For ADD_PROPERTY, vp is set to the property being added and newValue holds + * the new value. + */ +typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, + struct MprProperties *parentProperties, struct MprVar *vp, + struct MprVar *newValue, int copyDepth); + +/* + * mprCreateFunctionVar flags + */ +/** Use the alternate handle on function callbacks */ +#define MPR_VAR_ALT_HANDLE 0x1 + +/** Use the script handle on function callbacks */ +#define MPR_VAR_SCRIPT_HANDLE 0x2 + +/* + * Useful define for the copyDepth argument + */ +/** Don't copy any data. Copy only the variable name */ +#define MPR_NO_COPY 0 + +/** Copy strings. Increment object reference counts. */ +#define MPR_SHALLOW_COPY 1 + +/** Copy strings and do complete object copies. */ +#define MPR_DEEP_COPY 2 + +/* + * GetFirst / GetNext flags + */ +/** Step into data properties. */ +#define MPR_ENUM_DATA 0x1 + +/** Step into functions properties. */ +#define MPR_ENUM_FUNCTIONS 0x2 + +/* + * Collection type to hold properties in an object + */ +typedef struct MprProperties { /* Collection of properties */ +#if VAR_DEBUG + struct MprProperties *next; /* Linked list */ + struct MprProperties *prev; /* Linked list */ + char name[32]; /* Debug name */ +#endif + struct MprVar **buckets; /* Hash chains */ + int numItems; /* Total count of items */ + /* FUTURE - Better way of doing this */ + int numDataItems; /* Enumerable data items */ + uint hashSize : 8; /* Size of the hash table */ + /* FUTURE -- increase size of refCount */ + uint refCount : 8; /* References to this property*/ + /* FUTURE - make these flags */ + uint deleteProtect : 8; /* Don't recursively delete */ + uint visited : 8; /* Node has been processed */ +} MprProperties; + +/* + * Universal Variable Type + */ +typedef struct MprVar { + /* FUTURE - remove name to outside reference */ + MprStr name; /* Property name */ + /* FUTURE - remove */ + MprStr fullName; /* Full object name */ + /* FUTURE - make part of the union */ + MprProperties *properties; /* Pointer to properties */ + + /* + * Packed bit field + */ + MprType type : 8; /* Selector into union */ + uint bucketIndex : 8; /* Copy of bucket index */ + + uint flags : 5; /* Type specific flags */ + uint allocatedData : 1; /* Data needs freeing */ + uint readonly : 1; /* Unmodifiable */ + uint deleteProtect : 1; /* Don't recursively delete */ + + uint visited : 1; /* Node has been processed */ + uint allocatedVar : 1; /* Var needs freeing */ + uint spare : 6; /* Unused */ + + struct MprVar *forw; /* Hash table linkage */ + MprVarTrigger trigger; /* Trigger function */ + +#if UNUSED && KEEP + struct MprVar *baseClass; /* Pointer to class object */ +#endif + MprProperties *parentProperties; /* Pointer to parent object */ + + /* + * Union of primitive types. When debugging on Linux, don't use unions + * as the gdb debugger can't display them. + */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + union { +#endif + int boolean; /* Use int for speed */ +#if BLD_FEATURE_FLOATING_POINT + double floating; +#endif + int integer; +#if BLD_FEATURE_INT64 + int64 integer64; +#endif + struct { /* Javascript functions */ + MprArray *args; /* Null terminated */ + char *body; + } function; + struct { /* Function with MprVar args */ + MprCFunction fn; + void *thisPtr; + } cFunction; + struct { /* Function with string args */ + MprStringCFunction fn; + void *thisPtr; + } cFunctionWithStrings; + MprStr string; /* Allocated string */ + void *ptr; /* Opaque pointer */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + }; +#endif +} MprVar; + +/* + * Define a field macro so code an use numbers in a "generic" fashion. + */ +#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN +/* Default numeric type */ +#define mprNumber integer +#endif +#if MPR_NUM_VAR == MPR_TYPE_INT64 +/* Default numeric type */ +#define mprNumber integer64 +#endif +#if MPR_NUM_VAR == MPR_TYPE_FLOAT +/* Default numeric type */ +#define mprNumber floating +#endif + +typedef BLD_FEATURE_NUM_TYPE MprNumber; + + +#ifndef __NO_PACK +#pragma pack() +#endif /* __NO_PACK */ + +/********************************* Prototypes *********************************/ +/* + * Variable constructors and destructors + */ +extern MprVar mprCreateObjVar(const char *name, int hashSize); +extern MprVar mprCreateBoolVar(bool value); +extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, + int flags); +#if BLD_FEATURE_FLOATING_POINT +extern MprVar mprCreateFloatVar(double value); +#endif +extern MprVar mprCreateIntegerVar(int value); +#if BLD_FEATURE_INT64 +extern MprVar mprCreateInteger64Var(int64 value); +#endif +extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); +extern MprVar mprCreateNullVar(void); +extern MprVar mprCreateNumberVar(MprNumber value); +extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, + void *thisPtr, int flags); +extern MprVar mprCreateStringVar(const char *value, bool allocate); +extern MprVar mprCreateUndefinedVar(void); +extern MprVar mprCreatePtrVar(void *ptr); +extern bool mprDestroyVar(MprVar *vp); +extern bool mprDestroyAllVars(MprVar* vp); +extern MprType mprGetVarType(MprVar *vp); + +/* + * Copy + */ +extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); +extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); +extern MprVar *mprDupVar(MprVar *src, int copyDepth); + +/* + * Manage vars + */ +extern MprVarTrigger + mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); +extern int mprGetVarRefCount(MprVar *vp); +extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); +extern void mprSetVarFullName(MprVar *vp, char *name); +extern void mprSetVarReadonly(MprVar *vp, int readonly); +extern void mprSetVarName(MprVar *vp, char *name); + +/* + * Create properties and return a reference to the property. + */ +extern MprVar *mprCreateProperty(MprVar *obj, const char *property, + MprVar *newValue); +extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, + MprVar newValue); +extern int mprDeleteProperty(MprVar *obj, const char *property); + +/* + * Get/Set properties. Set will update/create. + */ +extern MprVar *mprGetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, + MprVar value); + +/* + * Directly read/write property values (the property must already exist) + * For mprCopyProperty, mprDestroyVar must always called on the var. + */ +extern int mprReadProperty(MprVar *prop, MprVar *value); +extern int mprWriteProperty(MprVar *prop, MprVar *newValue); +extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); + +/* + * Copy a property. NOTE: reverse of most other args: (dest, src) + */ +extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); + +/* + * Enumerate properties + */ +extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); +extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, + int includeFlags); + +/* + * Query properties characteristics + */ +extern int mprGetPropertyCount(MprVar *obj, int includeFlags); + +/* + * Conversion routines + */ +extern MprVar mprParseVar(char *str, MprType prefType); +extern MprNum mprVarToNumber(const MprVar *vp); +extern int mprVarToInteger(const MprVar *vp); +#if BLD_FEATURE_INT64 +extern int64 mprVarToInteger64(const MprVar *vp); +#endif +extern bool mprVarToBool(const MprVar *vp); +#if BLD_FEATURE_FLOATING_POINT +extern double mprVarToFloat(const MprVar *vp); +#endif +extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); + +/* + * Parsing and utility routines + */ +extern MprNum mprParseNumber(char *str); +extern int mprParseInteger(char *str); + +#if BLD_FEATURE_INT64 +extern int64 mprParseInteger64(char *str); +#endif + +#if BLD_FEATURE_FLOATING_POINT +extern double mprParseFloat(char *str); +extern bool mprIsInfinite(double f); +extern bool mprIsNan(double f); +#endif + +#if VAR_DEBUG +extern void mprPrintObjects(char *msg); +extern void mprPrintObjRefCount(MprVar *vp); +#endif + +#ifdef __cplusplus +} +#endif + +/*****************************************************************************/ +#endif /* _h_MPR_VAR */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/esp/esp.c b/source4/lib/appweb/esp/esp.c new file mode 100644 index 0000000000..ef20557f93 --- /dev/null +++ b/source4/lib/appweb/esp/esp.c @@ -0,0 +1,1042 @@ +/* + * @file esp.c + * @brief Embedded Server Pages (ESP) core processing. + * @overview The ESP handler provides an efficient way to generate + * dynamic pages using server-side Javascript. This code provides + * core processing, and should be called by an associated web + * server URL handler. + */ +/********************************* Copyright **********************************/ +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "esp.h" + +#if BLD_FEATURE_ESP_MODULE + +/*********************************** Locals ***********************************/ +/* + * Master ESP control interface with the web server + */ + +static const Esp *esp; + +/***************************** Forward Declarations ***************************/ + +static int buildScript(EspRequest *ep, char **jsBuf, char *input, char + **errMsg); + +/************************************ Code ************************************/ +/* + * Called at server initialization + */ + +int espOpen(const Esp *control) +{ + mprAssert(control); + +#if BLD_FEATURE_MULTITHREAD + ejsOpen(control->lock, control->unlock, control->lockData); +#else + ejsOpen(0, 0, 0); +#endif + + /* + * Register the standard procedures + */ + espRegisterProcs(); + + /* + * Just for brain dead systems that don't zero global memory + */ + esp = control; + return 0; +} + +/******************************************************************************/ +/* + * Called at server termination + */ + +void espClose() +{ + ejsClose(); +} + +/******************************************************************************/ +/* + * Create for new ESP request. Assumed that this is called after all the + * HTTP headers have been read but before POST data has been read. It is + * expected that any session cookies have been read and that "variables" + * contains references to all the environment objects including "session". + * requestHandle is the web server request handle. + */ + +EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri, + MprVar *variables) +{ + EspRequest *ep; + MprVar *global; +#if BLD_FEATURE_LEGACY_API + MprVar *np; + char keyBuf[ESP_MAX_HEADER]; + int i; +#endif + + mprAssert(variables); + + ep = mprMalloc(sizeof(EspRequest)); + if (ep == 0) { + return 0; + } + memset(ep, 0, sizeof(EspRequest)); + ep->requestHandle = webServerRequestHandle; + ep->esp = esp; + ep->uri = mprStrdup(uri); + ep->docPath = 0; + ep->variables = variables; + + /* + * The handle passed to ejsOpenEngine is passed to every C function + * called by JavaScript. + */ + ep->eid = ejsOpenEngine((EjsHandle) ep, (EjsHandle) webServerRequestHandle); + if (ep->eid < 0) { + mprFree(ep); + return 0; + } + + /* + * All these copies and SetProperties will only copy references + * They will increments the object ref counts. + */ + mprCopyVar(&variables[ESP_GLOBAL_OBJ], ejsGetGlobalObject(ep->eid), + MPR_SHALLOW_COPY); + mprCopyVar(&variables[ESP_LOCAL_OBJ], ejsGetLocalObject(ep->eid), + MPR_SHALLOW_COPY); + + global = &variables[ESP_GLOBAL_OBJ]; + mprCreateProperty(global, "application", &variables[ESP_APPLICATION_OBJ]); + mprCreateProperty(global, "cookies", &variables[ESP_COOKIES_OBJ]); + mprCreateProperty(global, "files", &variables[ESP_FILES_OBJ]); + mprCreateProperty(global, "form", &variables[ESP_FORM_OBJ]); + mprCreateProperty(global, "headers", &variables[ESP_HEADERS_OBJ]); + mprCreateProperty(global, "request", &variables[ESP_REQUEST_OBJ]); + + /* + * FUTURE -- could server be shared across all requests for a given host + * and be made read-only. + */ + mprCreateProperty(global, "server", &variables[ESP_SERVER_OBJ]); + +#if BLD_FEATURE_SESSION + mprCreateProperty(global, "session", &variables[ESP_SESSION_OBJ]); +#endif + +#if BLD_FEATURE_LEGACY_API + /* + * DEPRECATED: 2.0 + * Define variables as globals. headers[] are prefixed with "HTTP_". + * NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar + * does if legacy_api is defined. So variables pre-defined by MaRequest + * must be copied here into globals[]. + * + * NOTE: if a variable is in session[] and in form[], the form[] will + * override being later in the variables[] list. Use mprSetProperty + * instead of mprCreateProperty to cover for this case. + */ + for (i = 0; i < ESP_OBJ_MAX; i++) { + if (i == ESP_GLOBAL_OBJ || i == ESP_LOCAL_OBJ) { + continue; + } + if (variables[i].type != MPR_TYPE_OBJECT) { + continue; + } + np = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA); + while (np) { + if (i == ESP_HEADERS_OBJ) { + mprSprintf(keyBuf, sizeof(keyBuf) - 1, "HTTP_%s", np->name); + mprSetProperty(global, keyBuf, np); + } else { + mprSetProperty(global, np->name, np); + } + np = mprGetNextProperty(&variables[i], np, MPR_ENUM_DATA); + } + } +#endif + return ep; +} + +/******************************************************************************/ + +void espDestroyRequest(EspRequest *ep) +{ + mprAssert(ep); + mprAssert(ep->eid >= 0); + + mprFree(ep->uri); + mprFree(ep->docPath); + ejsCloseEngine(ep->eid); + mprFree(ep); +} + +/******************************************************************************/ +/* + * The callback function will be called: + * + * (fn)(EjsId eid, EspRequest *ep, argc, argv); + * + * Callers can get their web server handle by calling: + * + * rq = (requiredCast) espGetHandle(ep); + */ + +void espDefineCFunction(EspRequest *ep, const char *functionName, EspCFunction fn, + void *thisPtr) +{ + mprAssert(functionName && *functionName); + mprAssert(fn); + + if (ep) { + ejsDefineCFunction(ep->eid, functionName, (MprCFunction) fn, + thisPtr, 0); + } else { + ejsDefineCFunction(-1, functionName, (MprCFunction) fn, thisPtr, 0); + } +} + +/******************************************************************************/ + +void espDefineStringCFunction(EspRequest *ep, const char *functionName, + EspStringCFunction fn, void *thisPtr) +{ + mprAssert(functionName && *functionName); + mprAssert(fn); + + if (ep) { + ejsDefineStringCFunction(ep->eid, functionName, (MprStringCFunction) fn, + thisPtr, 0); + } else { + ejsDefineStringCFunction(-1, functionName, (MprStringCFunction) fn, + thisPtr, 0); + } +} + +/******************************************************************************/ + +void *espGetRequestHandle(EspRequest *ep) +{ + return ep->requestHandle; +} + +/******************************************************************************/ + +EjsId espGetScriptHandle(EspRequest *ep) +{ + return ep->eid; +} + +/******************************************************************************/ + +char *espGetStringVar(EspRequest *ep, EspEnvType oType, char *var, + char *defaultValue) +{ + MprVar value; + + if (espGetVar(ep, oType, var, &value) < 0 || + value.type != MPR_TYPE_STRING) { + return defaultValue; + } + return value.string; +} + +/******************************************************************************/ + +int espGetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar *value) +{ + MprVar *vp; + + mprAssert(ep); + mprAssert(var); + + vp = mprGetProperty(&ep->variables[oType], var, 0); + if (vp == 0) { + return -1; + } + *value = *vp; + return 0; +} + +/******************************************************************************/ +/* + * Process the ESP page. docBuf holds the page already. We expect that + * ep->variables holds all the pertinent environment variables. + */ + +int espProcessRequest(EspRequest *ep, const char *docPath, char *docBuf, + char **errMsg) +{ + char *jsBuf; + + mprAssert(ep); + + ep->docPath = mprStrdup(docPath); + + jsBuf = 0; + if (buildScript(ep, &jsBuf, docBuf, errMsg) < 0) { + return MPR_ERR_CANT_COMPLETE; + } + + if (jsBuf) { + mprLog(7, "esp: script is:\n%s\n", jsBuf); + + /* + * Now evaluate the entire escript + * MOB could cache the script + */ + if (ejsEvalScript(ep->eid, jsBuf, 0, errMsg) < 0) { + return MPR_ERR_ABORTED; + } + + mprFree(jsBuf); + } + return 0; +} + +/******************************************************************************/ + +void espRedirect(EspRequest *ep, int code, char *url) +{ + mprAssert(ep); + mprAssert(url); + + ep->esp->redirect(ep->requestHandle, code, url); +} + +/******************************************************************************/ + +void espError(EspRequest *ep, const char *fmt, ...) +{ + va_list args; + char *buf; + + mprAssert(ep); + mprAssert(fmt); + + va_start(args, fmt); + mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args); + ejsSetErrorMsg(ep->eid, buf); + mprFree(buf); + va_end(args); +} + +/******************************************************************************/ + +void espSetHeader(EspRequest *ep, char *header, bool allowMultiple) +{ + mprAssert(ep); + + ep->esp->setHeader(ep->requestHandle, header, allowMultiple); +} + +/******************************************************************************/ +/* + * Caller does not need to destroy the var + */ + +MprVar *espGetResult(EspRequest *ep) +{ + mprAssert(ep); + + return ejsGetReturnValue(ep->eid); +} + +/******************************************************************************/ + +void espSetReturn(EspRequest *ep, MprVar value) +{ + mprAssert(ep); + + ejsSetReturnValue(ep->eid, value); +} + +/******************************************************************************/ + +void espSetReturnString(EspRequest *ep, const char *str) +{ + mprAssert(ep); + + ejsSetReturnValue(ep->eid, mprCreateStringVar(str, 0)); +} + +/******************************************************************************/ + +void espSetResponseCode(EspRequest *ep, int code) +{ + mprAssert(ep); + + ep->esp->setResponseCode(ep->requestHandle, code); +} + +/******************************************************************************/ + +void espSetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar value) +{ + mprCreatePropertyValue(&ep->variables[oType], var, value); +} + +/******************************************************************************/ + +void espSetStringVar(EspRequest *ep, EspEnvType oType, + const char *var, const char *value) +{ + /* + * Will create or update if already existing + */ + mprCreatePropertyValue(&ep->variables[oType], var, + mprCreateStringVar(value, 0)); +} + +/******************************************************************************/ + +int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var) +{ + return mprDeleteProperty(&ep->variables[oType], var); +} + +/******************************************************************************/ + +int espWrite(EspRequest *ep, char *buf, int size) +{ + mprAssert(ep); + mprAssert(buf); + mprAssert(size >= 0); + + return ep->esp->writeBlock(ep->requestHandle, buf, size); +} + +/******************************************************************************/ + +int espWriteString(EspRequest *ep, char *buf) +{ + mprAssert(ep); + mprAssert(buf); + + return ep->esp->writeBlock(ep->requestHandle, buf, strlen(buf)); +} + +/******************************************************************************/ + +int espWriteFmt(EspRequest *ep, char *fmt, ...) +{ + va_list args; + char *buf; + int rc, len; + + mprAssert(ep); + mprAssert(fmt); + + va_start(args, fmt); + len = mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args); + rc = ep->esp->writeBlock(ep->requestHandle, buf, len); + mprFree(buf); + va_end(args); + return rc; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ +/* + * Get a javascript identifier. Must allow x.y['abc'] or x.y["abc"]. + * Must be careful about quoting and only allow quotes inside []. + */ + +static int getIdentifier(EspParse *parse) +{ + int atQuote, prevC, c; + + mprAssert(parse); + + atQuote = 0; + prevC = 0; + c = *parse->inp++; + + while (isalnum(c) || c == '_' || c == '.' || c == '[' || + c == ']' || c == '\'' || c == '\"') { + if (c == '\'' || c == '\"') { + if (c == atQuote) { + atQuote = 0; + } else if (prevC == '[') { + atQuote = c; + } else { + break; + } + } + if (parse->tokp >= parse->endp) { + parse->token = (char*) mprRealloc(parse->token, + parse->tokLen + ESP_TOK_INCR); + if (parse->token == 0) { + return MPR_ERR_CANT_ALLOCATE; + } + parse->token[parse->tokLen] = '\0'; + parse->tokLen += ESP_TOK_INCR; + parse->endp = &parse->token[parse->tokLen - 1]; + } + *parse->tokp++ = c; + prevC = c; + c = *parse->inp++; + } + + parse->inp--; + *parse->tokp = '\0'; + + return 0; +} + +/******************************************************************************/ +/* + * Get the next ESP input token. input points to the next input token. + * parse->token will hold the parsed token. The function returns the token id. + */ + +static int getEspToken(int state, EspParse *parse) +{ + char *cp; + int tid, done, c, quoted; + + tid = ESP_TOK_LITERAL; + parse->tokp = parse->token; + parse->tokp[0] = '\0'; + quoted = 0; + + c = *parse->inp++; + for (done = 0; !done; c = *parse->inp++) { + + /* + * Get room for more characters in the token buffer + */ + if (parse->tokp >= parse->endp) { + parse->token = (char*) mprRealloc(parse->token, + parse->tokLen + ESP_TOK_INCR); + if (parse->token == 0) { + return ESP_TOK_ERR; + } + parse->token[parse->tokLen] = '\0'; + parse->tokp = &parse->token[parse->tokLen - 1]; + parse->tokLen += ESP_TOK_INCR; + parse->endp = &parse->token[parse->tokLen - 1]; + } + + switch (c) { + case 0: + if (*parse->token) { + done++; + parse->inp--; + break; + } + return ESP_TOK_EOF; + + default: + if (c == '\"' && state != ESP_STATE_IN_ESP_TAG) { + *parse->tokp++ = '\\'; + } + *parse->tokp++ = c; + quoted = 0; + break; + + case '\\': + quoted = 1; + *parse->tokp++ = c; + break; + + case '@': + if (*parse->inp == '@' && state != ESP_STATE_IN_ESP_TAG) { + if (quoted) { + parse->tokp--; + quoted = 0; + } else { + if (*parse->token) { + parse->inp--; + } else { + parse->inp++; + tid = ESP_TOK_ATAT; + if (getIdentifier(parse) < 0) { + return ESP_TOK_ERR; + } + } + done++; + break; + } + } + *parse->tokp++ = c; + break; + + case '<': + if (*parse->inp == '%' && state != ESP_STATE_IN_ESP_TAG) { + if (quoted) { + parse->tokp--; + quoted = 0; + *parse->tokp++ = c; + break; + } + if (*parse->token) { + parse->inp--; + done++; + break; + } + parse->inp++; + while (isspace((int) *parse->inp)) { + parse->inp++; + } + if (*parse->inp == '=') { + parse->inp++; + while (isspace((int) *parse->inp)) { + parse->inp++; + } + tid = ESP_TOK_EQUALS; + if (getIdentifier(parse) < 0) { + return ESP_TOK_ERR; + } + done++; + break; + } + if (*parse->inp == 'i' && + strncmp(parse->inp, "include", 7) == 0 && + isspace((int) parse->inp[7])) { + tid = ESP_TOK_INCLUDE; + parse->inp += 7; + while (isspace((int) *parse->inp)) { + parse->inp++; + } + while (*parse->inp && !isspace((int) *parse->inp) && + *parse->inp != '%' && parse->tokp < parse->endp) { + *parse->tokp++ = *parse->inp++; + } + *parse->tokp = '\0'; + if (parse->token[0] == '"') { + parse->tokp = parse->token; + for (cp = &parse->token[1]; *cp; ) { + *parse->tokp++ = *cp++; + } + if (cp[-1] == '"') { + parse->tokp--; + } + *parse->tokp = '\0'; + } + + } else { + tid = ESP_TOK_START_ESP; + } + done++; + break; + } + *parse->tokp++ = c; + break; + + case '%': + if (*parse->inp == '>' && state == ESP_STATE_IN_ESP_TAG) { + if (quoted) { + parse->tokp--; + quoted = 0; + } else { + if (*parse->token) { + parse->inp--; + } else { + tid = ESP_TOK_END_ESP; + parse->inp++; + } + done++; + break; + } + } + *parse->tokp++ = c; + break; + } + } + + *parse->tokp = '\0'; + parse->inp--; + return tid; +} + +/******************************************************************************/ +/* + * Convert an ESP page into a JavaScript. We also expand include files. + */ + +static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) +{ + EspParse parse; + char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME]; + char *incBuf, *incText; + int state, tid, len, rc, maxScriptSize, incSize; + + mprAssert(ep); + mprAssert(jsBuf); + mprAssert(input); + + rc = 0; + len = 0; + state = ESP_STATE_BEGIN; + if (errMsg) { + *errMsg = 0; + } + + memset(&parse, 0, sizeof(parse)); + parse.token = (char*) mprMalloc(ESP_TOK_INCR); + if (parse.token == 0) { + return MPR_ERR_CANT_ALLOCATE; + } + parse.token[0] = '\0'; + parse.tokLen = ESP_TOK_INCR; + parse.endp = &parse.token[parse.tokLen - 1]; + parse.tokp = parse.token; + parse.inBuf = input; + parse.inp = parse.inBuf; + + maxScriptSize = esp->maxScriptSize; + + tid = getEspToken(state, &parse); + while (tid != ESP_TOK_EOF && len >= 0) { + + switch (tid) { + default: + case ESP_TOK_ERR: + mprFree(parse.token); + return MPR_ERR_BAD_SYNTAX; + + case ESP_TOK_LITERAL: + len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, + "write(\"", parse.token, "\");\n", 0); + break; + + case ESP_TOK_ATAT: + /* + * Trick to get undefined variables to evaluate to "". + * Catenate with "" to cause toString to run. + */ + len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, + "write(\"\" + ", parse.token, ");\n", 0); + break; + + case ESP_TOK_EQUALS: + len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, + "write(\"\" + ", parse.token, ");\n", 0); + state = ESP_STATE_IN_ESP_TAG; + break; + + case ESP_TOK_START_ESP: + state = ESP_STATE_IN_ESP_TAG; + tid = getEspToken(state, &parse); + while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && + tid != ESP_TOK_END_ESP && len >= 0) { + len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, + parse.token, 0); + tid = getEspToken(state, &parse); + } + state = ESP_STATE_BEGIN; + break; + + case ESP_TOK_END_ESP: + state = ESP_STATE_BEGIN; + break; + + case ESP_TOK_INCLUDE: + if (parse.token[0] == '/') { + mprStrcpy(incPath, sizeof(incPath), parse.token); + } else { + mprGetDirName(dir, sizeof(dir), ep->uri); + mprSprintf(incPath, sizeof(incPath), "%s/%s", + dir, parse.token); + } + if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), + incPath, 0) < 0) { + mprAllocSprintf(errMsg, MPR_MAX_STRING, + "Can't find include file: %s", path); + rc = MPR_ERR_CANT_OPEN; + break; + } + if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0){ + mprAllocSprintf(errMsg, MPR_MAX_STRING, + "Can't read include file: %s", path); + rc = MPR_ERR_CANT_READ; + break; + } + incText[incSize] = '\0'; + + /* + * Recurse and process the include script + */ + incBuf = 0; + if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) { + mprFree(incText); + mprFree(parse.token); + return rc; + } + + len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, 0); + mprFree(incText); + mprFree(incBuf); + state = ESP_STATE_IN_ESP_TAG; + break; + } + tid = getEspToken(state, &parse); + } + mprFree(parse.token); + if (len < 0) { + mprAllocSprintf(errMsg, MPR_MAX_STRING, + "Script token is too big in %s.\nConfigured maximum is %d.", + path, maxScriptSize); + return MPR_ERR_WONT_FIT; + } + return rc; +} + +/******************************************************************************/ +/******************************* Wrapped Routines *****************************/ +/******************************************************************************/ + +int espCopyVar(EspRequest *ep, char *var, MprVar *value, int copyDepth) +{ + return ejsCopyVar(ep->eid, var, value, copyDepth); +} + +/******************************************************************************/ + +MprVar espCreateObjVar(char *name, int hashSize) +{ + return ejsCreateObj(name, hashSize); +} + +/******************************************************************************/ + +MprVar espCreateArrayVar(char *name, int size) +{ + return ejsCreateArray(name, size); +} + +/******************************************************************************/ + +bool espDestroyVar(MprVar *obj) +{ + return ejsDestroyVar(obj); +} + +/******************************************************************************/ + +MprVar *espCreateProperty(MprVar *obj, char *property, MprVar *newValue) +{ + return mprCreateProperty(obj, property, newValue); +} + +/******************************************************************************/ + +MprVar *espCreatePropertyValue(MprVar *obj, char *property, MprVar newValue) +{ + return mprCreatePropertyValue(obj, property, newValue); +} + +/******************************************************************************/ + +void espDefineFunction(EspRequest *ep, const char *functionName, char *args, char *body) +{ + ejsDefineFunction(ep->eid, functionName, args, body); +} + +/******************************************************************************/ + +int espDeleteProperty(MprVar *obj, char *property) +{ + return mprDeleteProperty(obj, property); +} + +/******************************************************************************/ + +int espDeleteVar(EspRequest *ep, char *var) +{ + return ejsDeleteVar(ep->eid, var); +} + +/******************************************************************************/ +int espEvalFile(EspRequest *ep, char *path, MprVar *result, char **emsg) +{ + return ejsEvalFile(ep->eid, path, result, emsg); +} + +/******************************************************************************/ + +int espEvalScript(EspRequest *ep, char *script, MprVar *result, char **emsg) +{ + return ejsEvalScript(ep->eid, script, result, emsg); +} + +/******************************************************************************/ + +int espGetPropertyCount(MprVar *obj, int includeFlags) +{ + if (obj->type != MPR_TYPE_OBJECT) { + return MPR_ERR_BAD_STATE; + } + return mprGetPropertyCount(obj, includeFlags); +} + +/******************************************************************************/ + +MprVar *espGetFirstProperty(MprVar *obj, int includeFlags) +{ + return mprGetFirstProperty(obj, includeFlags); +} + +/******************************************************************************/ + +MprVar *espGetGlobalObject(EspRequest *ep) +{ + return ejsGetGlobalObject(ep->eid); +} + +/******************************************************************************/ + +MprVar *espGetLocalObject(EspRequest *ep) +{ + return ejsGetLocalObject(ep->eid); +} + +/******************************************************************************/ + +MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty, + int includeFlags) +{ + return mprGetNextProperty(obj, currentProperty, includeFlags); +} + +/******************************************************************************/ + +MprVar *espGetProperty(MprVar *obj, char *property, MprVar *value) +{ + return mprGetProperty(obj, property, value); +} + +/******************************************************************************/ + +void *espGetThisPtr(EspRequest *ep) +{ + return ejsGetThisPtr(ep->eid); +} + +/******************************************************************************/ +#if XX_UNUSED_XX + +int espReadProperty(MprVar *dest, MprVar *prop) +{ + mprAssert(prop); + mprAssert(dest); + + *dest = *prop; + return 0; +} + +#endif +/******************************************************************************/ + +int espReadVar(EspRequest *ep, char *var, MprVar *value) +{ + return ejsReadVar(ep->eid, var, value); +} + +/******************************************************************************/ + +int espRunFunction(EspRequest *ep, MprVar *obj, char *functionName, + MprArray *args) +{ + return ejsRunFunction(ep->eid, obj, functionName, args); +} + +/******************************************************************************/ + +MprVar *espSetProperty(MprVar *obj, char *property, MprVar *newValue) +{ + return mprSetProperty(obj, property, newValue); +} + +/******************************************************************************/ + +MprVar *espSetPropertyValue(MprVar *obj, char *property, MprVar newValue) +{ + return mprSetPropertyValue(obj, property, newValue); +} + +/******************************************************************************/ + +int espWriteVar(EspRequest *ep, char *var, MprVar *value) +{ + return ejsWriteVar(ep->eid, var, value); +} + +/******************************************************************************/ + +int espWriteVarValue(EspRequest *ep, char *var, MprVar value) +{ + return ejsWriteVarValue(ep->eid, var, value); +} + +/******************************************************************************/ +#if XX_UNUSED_XX + +int espWriteProperty(MprVar *prop, MprVar *newValue) +{ + return mprWriteProperty(prop, newValue); +} + +/******************************************************************************/ + +int espWritePropertyValue(MprVar *prop, MprVar newValue) +{ + return mprWritePropertyValue(prop, newValue); +} + +#endif +/******************************************************************************/ + +#else /* !BLD_FEATURE_ESP_MODULE */ +void espDummy() {} + +/******************************************************************************/ +#endif /* BLD_FEATURE_ESP_MODULE */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h new file mode 100644 index 0000000000..ee86e8d345 --- /dev/null +++ b/source4/lib/appweb/esp/esp.h @@ -0,0 +1,279 @@ +/** + * @file esp.h + * @brief Header for Embedded Server Pages (ESP) + */ +/********************************* Copyright **********************************/ +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#ifndef _h_ESP_h +#define _h_ESP_h 1 + +#include "lib/appweb/ejs/ejs.h" +#include "lib/appweb/esp/espEnv.h" +#include "lib/appweb/ejs/var.h" +#include "lib/appweb/ejs/miniMpr.h" + +/*********************************** Defines **********************************/ + +#define ESP_STRING_ARGS MPR_TYPE_STRING_ARGS + +#if BLD_FEATURE_SQUEEZE +#define ESP_TOK_INCR 1024 +#define ESP_MAX_HEADER 1024 +#else +#define ESP_TOK_INCR 4096 +#define ESP_MAX_HEADER 4096 +#endif + +/* + * ESP lexical analyser tokens + */ +#define ESP_TOK_ERR -1 /* Any input error */ +#define ESP_TOK_EOF 0 /* End of file */ +#define ESP_TOK_START_ESP 1 /* <% */ +#define ESP_TOK_END_ESP 2 /* %> */ +#define ESP_TOK_ATAT 3 /* @@var */ +#define ESP_TOK_LITERAL 4 /* literal HTML */ +#define ESP_TOK_INCLUDE 5 /* include file.esp */ +#define ESP_TOK_EQUALS 6 /* = var */ + +/* + * ESP parser states + */ +#define ESP_STATE_BEGIN 1 /* Starting state */ +#define ESP_STATE_IN_ESP_TAG 2 /* Inside a <% %> group */ + +/*********************************** Types ************************************/ + +typedef void* EspHandle; /* Opaque Web server handle type */ + +/* + * Per request control block + */ +typedef struct EspRequest { + MprStr docPath; /* Physical path for ESP page */ + EjsId eid; /* EJS instance handle */ + const struct Esp *esp; /* Pointer to ESP control block */ + EspHandle requestHandle; /* Per request web server handle */ + MprStr uri; /* Request URI */ + MprVar *variables; /* Pointer to variables */ +} EspRequest; + +/* + * Master ESP control block. This defines the function callbacks for a + * web server handler to implement. ESP will call these functions as + * required. + */ +typedef struct Esp { + int maxScriptSize; + void (*createSession)(EspHandle handle, int timeout); + void (*destroySession)(EspHandle handle); + const char *(*getSessionId)(EspHandle handle); + int (*mapToStorage)(EspHandle handle, char *path, int len, const char *uri, + int flags); + int (*readFile)(EspHandle handle, char **buf, int *len, const char *path); + void (*redirect)(EspHandle handle, int code, char *url); + void (*setCookie)(EspHandle handle, const char *name, const char *value, + int lifetime, const char *path, bool secure); + void (*setHeader)(EspHandle handle, const char *value, bool allowMultiple); + void (*setResponseCode)(EspHandle handle, int code); + int (*writeBlock)(EspHandle handle, char *buf, int size); + int (*writeFmt)(EspHandle handle, char *fmt, ...); +#if BLD_FEATURE_MULTITHREAD + void (*lock)(void *lockData); + void (*unlock)(void *lockData); + void *lockData; +#endif +} Esp; + + +/* + * ESP parse context + */ +typedef struct { + char *inBuf; /* Input data to parse */ + char *inp; /* Next character for input */ + char *endp; /* End of storage (allow for null) */ + char *tokp; /* Pointer to current parsed token */ + char *token; /* Storage buffer for token */ + int tokLen; /* Length of buffer */ +} EspParse; + + +/******************************** Private APIs ********************************/ + +extern void espRegisterProcs(void); + +/******************************** Published API *******************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Function callback signatures + */ +typedef int (*EspCFunction)(EspRequest *ep, int argc, + struct MprVar **argv); +typedef int (*EspStringCFunction)(EspRequest *ep, int argc, + char **argv); + +/* + * APIs for those hosting the ESP module + */ +extern int espOpen(const Esp *control); +extern void espClose(void); +extern EspRequest *espCreateRequest(EspHandle webServerRequestHandle, + char *uri, MprVar *envObj); +extern void espDestroyRequest(EspRequest *ep); +extern int espProcessRequest(EspRequest *ep, const char *docPath, + char *docBuf, char **errMsg); + +/* + * Method invocation + */ +extern void espDefineCFunction(EspRequest *ep, const char *functionName, + EspCFunction fn, void *thisPtr); +extern void espDefineFunction(EspRequest *ep, const char *functionName, + char *args, char *body); +extern void espDefineStringCFunction(EspRequest *ep, + const char *functionName, EspStringCFunction fn, + void *thisPtr); +extern int espRunFunction(EspRequest *ep, MprVar *obj, + char *functionName, MprArray *args); +extern void espSetResponseCode(EspRequest *ep, int code); +extern void espSetReturn(EspRequest *ep, MprVar value); +extern void *espGetThisPtr(EspRequest *ep); + +/* + * Utility routines to use in C methods + */ +extern void espError(EspRequest *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern int espEvalFile(EspRequest *ep, char *path, MprVar *result, + char **emsg); +extern int espEvalScript(EspRequest *ep, char *script, MprVar *result, + char **emsg); +extern MprVar *espGetLocalObject(EspRequest *ep); +extern MprVar *espGetGlobalObject(EspRequest *ep); +extern EspHandle espGetRequestHandle(EspRequest *ep); +extern MprVar *espGetResult(EspRequest *ep); +extern EjsId espGetScriptHandle(EspRequest *ep); +extern void espRedirect(EspRequest *ep, int code, char *url); +extern void espSetHeader(EspRequest *ep, char *header, + bool allowMultiple); +extern void espSetReturnString(EspRequest *ep, const char *str); +extern int espWrite(EspRequest *ep, char *buf, int size); +extern int espWriteString(EspRequest *ep, char *buf); +extern int espWriteFmt(EspRequest *ep, char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/* + * ESP array[] variable access (set will update/create) + */ +extern int espGetVar(EspRequest *ep, EspEnvType oType, char *var, + MprVar *value); +extern char *espGetStringVar(EspRequest *ep, EspEnvType oType, + char *var, char *defaultValue); +extern void espSetVar(EspRequest *ep, EspEnvType oType, char *var, + MprVar value); +extern void espSetStringVar(EspRequest *ep, EspEnvType oType, + const char *var, const char *value); +extern int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var); + +/* + * Object creation and management + */ +extern MprVar espCreateObjVar(char *name, int hashSize); +extern MprVar espCreateArrayVar(char *name, int size); +extern bool espDestroyVar(MprVar *var); +extern MprVar *espCreateProperty(MprVar *obj, char *property, + MprVar *newValue); +extern MprVar *espCreatePropertyValue(MprVar *obj, char *property, + MprVar newValue); +extern int espDeleteProperty(MprVar *obj, char *property); + +/* + * JavaScript variable management. Set will create/update a property. + * All return a property reference. GetProperty will optionally return the + * property in value. + */ +extern MprVar *espGetProperty(MprVar *obj, char *property, + MprVar *value); +extern MprVar *espSetProperty(MprVar *obj, char *property, + MprVar *newValue); +extern MprVar *espSetPropertyValue(MprVar *obj, char *property, + MprVar newValue); + +#if 0 +/* + * Low-level direct read and write of properties. + * FUTURE: -- Read is not (dest, src). MUST WARN IN DOC ABOUT COPY/READ + * Will still cause triggers to run. + */ +extern int espReadProperty(MprVar *dest, MprVar *prop); +extern int espWriteProperty(MprVar *prop, MprVar *newValue); +extern int espWritePropertyValue(MprVar *prop, MprVar newValue); +#endif + + +/* + * Access JavaScript variables by their full name. Can use "." or "[]". For + * example: "global.request['REQUEST_URI']" + * For Read/write, the variables must exist. + */ +extern int espCopyVar(EspRequest *ep, char *var, MprVar *value, + int copyDepth); +extern int espDeleteVar(EspRequest *ep, char *var); +extern int espReadVar(EspRequest *ep, char *var, MprVar *value); +extern int espWriteVar(EspRequest *ep, char *var, MprVar *value); +extern int espWriteVarValue(EspRequest *ep, char *var, MprVar value); + +/* + * Object property enumeration + */ +extern MprVar *espGetFirstProperty(MprVar *obj, int includeFlags); +extern MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty, + int includeFlags); +extern int espGetPropertyCount(MprVar *obj, int includeFlags); + +#ifdef __cplusplus +} +#endif +/******************************************************************************/ +#endif /* _h_ESP_h */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/esp/espEnv.h b/source4/lib/appweb/esp/espEnv.h new file mode 100644 index 0000000000..a3c9d9f5c7 --- /dev/null +++ b/source4/lib/appweb/esp/espEnv.h @@ -0,0 +1,128 @@ +/* + * @file espEnv.h + * @brief ESP Environment Variables + */ +/********************************* Copyright **********************************/ +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************************************************************/ + +#ifndef _h_ESP_ENV_h +#define _h_ESP_ENV_h 1 + +/* + * @brief Scripting environment variable array types + */ +typedef enum EspEnvType { + ESP_UNDEFINED_OBJ = -1, + + /** + * Elements for server[]: + * DOCUMENT_ROOT GATEWAY_INTERFACE SERVER_ADDR SERVER_PORT SERVER_NAME + * SERVER_PROTOCOL SERVER_SOFTWARE SERVER_URL UPLOAD_DIR + * FUTURE: SERVER_ADMIN + * FUTURE: this could be shared across all hosts and be made read-only. + */ + ESP_SERVER_OBJ = 0, /*! server[] data */ + + /** + * Elements for session[]: are user defined + */ + ESP_SESSION_OBJ = 1, /*! session[] data */ + + /** + * Elements for request[]: + * AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE QUERY_STRING PATH_INFO + * PATH_TRANSLATED REMOTE_ADDR REMOTE_HOST REMOTE_USER REQUEST_METHOD + * REQUEST_URI SCRIPT_FILENAME SCRIPT_NAME + * FUTURE: FILEPATH_INFO REDIRECT_URL SELF REMOTE_PORT AUTH_USER + * AUTH_GROUP AUTH_ACL + */ + ESP_REQUEST_OBJ = 2, /*! request[] data */ + + /** + * Elements for headers[]: + * HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_CONNECTION HTTP_HOST + * HTTP_REFERER HTTP_USER_AGENT and any other custom headers + */ + ESP_HEADERS_OBJ = 3, /*! header [] data */ + + /** + * Elements for cookies[]: are defined by the HTTP request + */ + ESP_COOKIES_OBJ = 4, /*! cookies[] data */ + + /** + * Elements for files[]: are defined by the HTTP request + * CLIENT_FILENAME CONTENT_TYPE FILENAME SIZE + */ + ESP_FILES_OBJ = 5, /*! files[] data */ + + /** + * Elements for form[]: are defined by the HTTP request + */ + ESP_FORM_OBJ = 6, /*! form[] data */ + + /** + * Elements for application[]: are user defined + */ + ESP_APPLICATION_OBJ = 7, /*! application[] data */ + + /** + * Elements for global[]: are defined by ESP/EJS + */ + ESP_GLOBAL_OBJ = 8, /*! global [] data */ + + /* + * Elements for local[]: are defined by ESP/EJS + */ + ESP_LOCAL_OBJ = 9, /*! local [] data */ +} EspEnvType; + +#define ESP_OBJ_MAX 10 /* Total objects */ + +#if BLD_SQUEEZE +#define ESP_HASH_SIZE 19 /* Size of hash tables */ +#else +#define ESP_HASH_SIZE 37 +#endif + +/******************************************************************************/ +#endif /* _h_ESP_ENV_h */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/esp/espProcs.c b/source4/lib/appweb/esp/espProcs.c new file mode 100644 index 0000000000..28b69a8a6f --- /dev/null +++ b/source4/lib/appweb/esp/espProcs.c @@ -0,0 +1,246 @@ +/* + * @file espProcs.c + * @brief Embedded Server Pages (ESP) Procedures. + * @overview These ESP procedures can be used in ESP pages for common tasks. + */ +/********************************* Copyright **********************************/ +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +/********************************** Includes **********************************/ + +#include "esp.h" + +/************************************ Code ************************************/ +#if BLD_FEATURE_ESP_MODULE +#if BLD_FEATURE_SESSION +/* + * destroySession + */ + +static int destroySessionProc(EspRequest *ep, int argc, char **argv) +{ + ep->esp->destroySession(ep->requestHandle); + return 0; +} + +#endif /* BLD_FEATURE_SESSION */ + +/******************************************************************************/ +/* + * include + * + * This includes javascript libraries. For example: + * + * <% include("file", ...); %> + * + * Don't confuse with ESP includes: + * + * <% include file.esp %> + * + * Filenames are relative to the base document including the file. + * FUTURE -- move back to EJS. Only here now because we need ep->readFile. + */ + +static int includeProc(EspRequest *ep, int argc, char **argv) +{ + const Esp *esp; + char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME]; + char *emsg=NULL, *buf; + int size, i; + + esp = ep->esp; + mprAssert(argv); + for (i = 0; i < argc; i++) { + const char *extension; + + if (argv[i][0] != '/') { + mprGetDirName(dir, sizeof(dir), ep->docPath); + mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]); + } else { + mprSprintf(path, sizeof(path), "%s", argv[i]); + } + + if (esp->readFile(ep->requestHandle, &buf, &size, path) < 0) { + espError(ep, "Can't read include file: %s", path); + return MPR_ERR_CANT_ACCESS; + } + buf[size] = '\0'; + + extension = strrchr(argv[i], '.'); + /* this makes handling include files in esp scripts much more convenient */ + if (extension && strcasecmp(extension, ".esp") == 0) { + if (espProcessRequest(ep, path, buf, &emsg) != 0) { + espError(ep, "Cant evaluate script - %s", emsg?emsg:""); + mprFree(buf); + return -1; + } + } else { + if (ejsEvalScript(espGetScriptHandle(ep), buf, 0, &emsg) < 0) { + espError(ep, "Cant evaluate script - %s", emsg?emsg:""); + mprFree(buf); + return -1; + } + } + mprFree(buf); + } + return 0; +} + +/******************************************************************************/ +/* + * redirect + * + * This implemements <% redirect(url, code); %> command. The redirection + * code is optional. + */ + +static int redirectProc(EspRequest *ep, int argc, char **argv) +{ + char *url; + int code; + + if (argc < 1) { + espError(ep, "Bad args"); + return MPR_ERR_BAD_ARGS; + } + url = argv[0]; + if (argc == 2) { + code = atoi(argv[1]); + } else { + code = 302; + } + espRedirect(ep, code, url); + return 0; +} + +/******************************************************************************/ +#if BLD_FEATURE_SESSION +/* + * useSession + */ + +static int useSessionProc(EspRequest *ep, int argc, char **argv) +{ + int timeout; + + if (argc > 1) { + espError(ep, "Bad args"); + return MPR_ERR_BAD_ARGS; + + } else if (argc == 1) { + timeout = atoi(argv[0]); + } else { + timeout = 0; + } + + ep->esp->createSession(ep->requestHandle, timeout); + espSetReturnString(ep, ep->esp->getSessionId(ep->requestHandle)); + return 0; +} + +#endif /* BLD_FEATURE_SESSION */ +/******************************************************************************/ +/* + * setHeader + * + * This implemements <% setHeader("key: value", allowMultiple); %> command. + */ + +static int setHeaderProc(EspRequest *ep, int argc, char **argv) +{ + mprAssert(argv); + if (argc != 2) { + espError(ep, "Bad args"); + return MPR_ERR_BAD_ARGS; + } + ep->esp->setHeader(ep->requestHandle, argv[0], atoi(argv[1])); + return 0; +} + +/******************************************************************************/ +/* + * write + * + * This implemements <% write("text"); %> command. + */ + +static int writeProc(EspRequest *ep, int argc, char **argv) +{ + char *s; + int i, len; + + mprAssert(argv); + for (i = 0; i < argc; i++) { + s = argv[i]; + len = strlen(s); + if (len > 0) { + if (espWrite(ep, s, len) != len) { + espError(ep, "Can't write to client"); + return -1; + } + } + } + return 0; +} + +/******************************************************************************/ + +void espRegisterProcs() +{ + espDefineStringCFunction(0, "write", writeProc, 0); + espDefineStringCFunction(0, "setHeader", setHeaderProc, 0); + espDefineStringCFunction(0, "redirect", redirectProc, 0); + espDefineStringCFunction(0, "include", includeProc, 0); + +#if BLD_FEATURE_SESSION + /* + * Create and use are synonomous + */ + espDefineStringCFunction(0, "useSession", useSessionProc, 0); + espDefineStringCFunction(0, "createSession", useSessionProc, 0); + espDefineStringCFunction(0, "destroySession", destroySessionProc, 0); +#endif +} + +/******************************************************************************/ + +#else +void mprEspControlsDummy() {} + +#endif /* BLD_FEATURE_ESP_MODULE */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/ejs/config.h b/source4/lib/ejs/config.h deleted file mode 100644 index 320318a0b2..0000000000 --- a/source4/lib/ejs/config.h +++ /dev/null @@ -1,141 +0,0 @@ -#define BLD_PRODUCT "Samba4" -#define BLD_NAME "Samba4 SWAT" -#define BLD_VERSION "4" -#define BLD_NUMBER "1" -#define BLD_TYPE "DEBUG" -#define BLD_DEFAULTS "normal" -#define BLD_PACKAGES "" -#define BLD_APPWEB_CONFIG "normal.conf" -#define BLD_APPWEB 0 -#define BLD_COMPANY "Mbedthis" -#define BLD_DEBUG 1 -#define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" -#define BLD_HTTP_PORT 7777 -#define BLD_LIB_VERSION "1.0.0" -#define BLD_SSL_PORT 4443 -#define BLD_CLEAN_INSTALL "0" -#define BLD_LICENSE "gpl" -#define BLD_HOST_SYSTEM "i686-pc-linux-gnu" -#define BLD_BUILD_SYSTEM "i686-pc-linux-gnu" -#define BLD_HOST_OS "LINUX" -#define BLD_HOST_CPU_ARCH MPR_CPU_IX86 -#define BLD_HOST_CPU "i686" -#define BLD_HOST_UNIX 1 -#define BLD_BUILD_OS "LINUX" -#define BLD_BUILD_CPU_ARCH MPR_CPU_IX86 -#define BLD_BUILD_CPU i686 -#define BLD_BUILD_UNIX 1 -#define BLD_ROOT_PREFIX "/" -#define BLD_FEATURE_ACCESS_LOG 0 -#define BLD_FEATURE_ADMIN_MODULE 0 -#define BLD_FEATURE_ASPNET_MODULE 0 -#define BLD_FEATURE_ASSERT 1 -#define BLD_FEATURE_AUTH_MODULE 0 -#define BLD_FEATURE_C_API_MODULE 1 -#define BLD_FEATURE_C_API_CLIENT 0 -#define BLD_FEATURE_CGI_MODULE 0 -#define BLD_FEATURE_COMPAT_MODULE 0 -#define BLD_FEATURE_CONFIG_PARSE 0 -#define BLD_FEATURE_CONFIG_SAVE 0 -#define BLD_FEATURE_COOKIE 0 -#define BLD_FEATURE_COPY_MODULE 0 -#define BLD_FEATURE_DIGEST 0 -#define BLD_FEATURE_DLL 0 -#define BLD_FEATURE_EGI_MODULE 0 -#define BLD_FEATURE_EJS 1 -#define BLD_FEATURE_ESP_MODULE 1 -#define BLD_FEATURE_EVAL_PERIOD 30 -#define BLD_FEATURE_FLOATING_POINT 1 -#define BLD_FEATURE_IF_MODIFIED 0 -#define BLD_FEATURE_INT64 1 -#define BLD_FEATURE_KEEP_ALIVE 0 -#define BLD_FEATURE_LEGACY_API 0 -#define BLD_FEATURE_LIB_STDCPP 0 -#define BLD_FEATURE_LICENSE 0 -#define BLD_FEATURE_LOG 0 -#define BLD_FEATURE_MULTITHREAD 0 -#define BLD_FEATURE_MALLOC 0 -#define BLD_FEATURE_MALLOC_STATS 0 -#define BLD_FEATURE_MALLOC_LEAK 0 -#define BLD_FEATURE_MALLOC_HOOK 0 -#define BLD_FEATURE_NUM_TYPE int64 -#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT64 -#define BLD_FEATURE_ROMFS 0 -#define BLD_FEATURE_RUN_AS_SERVICE 0 -#define BLD_FEATURE_SAFE_STRINGS 0 -#define BLD_FEATURE_SAMPLES 0 -#define BLD_FEATURE_SESSION 1 -#define BLD_FEATURE_SHARED 0 -#define BLD_FEATURE_SQUEEZE 0 -#define BLD_FEATURE_SSL_MODULE 0 -#define BLD_FEATURE_STATIC 1 -#define BLD_FEATURE_STATIC_LINK_LIBC 0 -#define BLD_FEATURE_TEST 0 -#define BLD_FEATURE_UPLOAD_MODULE 0 -#define BLD_FEATURE_XDB_MODULE 0 -#define BLD_FEATURE_ADMIN_MODULE_BUILTIN 0 -#define BLD_FEATURE_ASPNET_MODULE_BUILTIN 0 -#define BLD_FEATURE_AUTH_MODULE_BUILTIN 0 -#define BLD_FEATURE_C_API_MODULE_BUILTIN 0 -#define BLD_FEATURE_CGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_COMPAT_MODULE_BUILTIN 0 -#define BLD_FEATURE_COPY_MODULE_BUILTIN 0 -#define BLD_FEATURE_EGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_ESP_MODULE_BUILTIN 0 -#define BLD_FEATURE_SSL_MODULE_BUILTIN 0 -#define BLD_FEATURE_UPLOAD_MODULE_BUILTIN 0 -#define BLD_FEATURE_XDB_MODULE_BUILTIN 0 -#define BLD_FEATURE_ADMIN_MODULE_LOADABLE 0 -#define BLD_FEATURE_ASPNET_MODULE_LOADABLE 0 -#define BLD_FEATURE_AUTH_MODULE_LOADABLE 0 -#define BLD_FEATURE_C_API_MODULE_LOADABLE 0 -#define BLD_FEATURE_CGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_COMPAT_MODULE_LOADABLE 0 -#define BLD_FEATURE_COPY_MODULE_LOADABLE 0 -#define BLD_FEATURE_EGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_ESP_MODULE_LOADABLE 0 -#define BLD_FEATURE_SSL_MODULE_LOADABLE 0 -#define BLD_FEATURE_UPLOAD_MODULE_LOADABLE 0 -#define BLD_FEATURE_XDB_MODULE_LOADABLE 0 -#define BLD_AR_FOR_BUILD "ar" -#define BLD_CC_FOR_BUILD "cc" -#define BLD_CSC_FOR_BUILD "" -#define BLD_JAVAC_FOR_BUILD "" -#define BLD_LD_FOR_BUILD "ld" -#define BLD_RANLIB_FOR_BUILD "" -#define BLD_NM_FOR_BUILD "nm" -#define BLD_CFLAGS_FOR_BUILD "" -#define BLD_IFLAGS_FOR_BUILD "" -#define BLD_LDFLAGS_FOR_BUILD "" -#define BLD_ARCHIVE_FOR_BUILD ".a" -#define BLD_EXE_FOR_BUILD "" -#define BLD_OBJ_FOR_BUILD ".o" -#define BLD_PIOBJ_FOR_BUILD ".lo" -#define BLD_CLASS_FOR_BUILD ".class" -#define BLD_SHLIB_FOR_BUILD "" -#define BLD_SHOBJ_FOR_BUILD ".so" -#define BLD_AR_FOR_HOST "ar" -#define BLD_CC_FOR_HOST "cc" -#define BLD_CSC_FOR_HOST "csc" -#define BLD_JAVAC_FOR_HOST "javac" -#define BLD_LD_FOR_HOST "ld" -#define BLD_RANLIB_FOR_HOST "true" -#define BLD_NM_FOR_HOST "nm" -#define BLD_CFLAGS_FOR_HOST "" -#define BLD_IFLAGS_FOR_HOST "" -#define BLD_LDFLAGS_FOR_HOST "" -#define BLD_ARCHIVE_FOR_HOST ".a" -#define BLD_EXE_FOR_HOST "" -#define BLD_OBJ_FOR_HOST ".o" -#define BLD_PIOBJ_FOR_HOST ".lo" -#define BLD_CLASS_FOR_HOST ".class" -#define BLD_SHLIB_FOR_HOST "" -#define BLD_SHOBJ_FOR_HOST ".so" -#define BLD_TOOLS_DIR "${BLD_TOP}/bin" -#define BLD_BIN_DIR "${BLD_TOP}/bin" -#define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" -#define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" - -#ifndef MAX_FLOAT -#define MAX_FLOAT 3.40282347e+38F -#endif diff --git a/source4/lib/ejs/config.mk b/source4/lib/ejs/config.mk deleted file mode 100644 index f2c0e62f1e..0000000000 --- a/source4/lib/ejs/config.mk +++ /dev/null @@ -1,13 +0,0 @@ -####################### -# Start SUBSYSTEM EJS -[SUBSYSTEM::EJS] -ADD_OBJ_FILES = \ - lib/ejs/ejsLib.o \ - lib/ejs/ejsLex.o \ - lib/ejs/ejsParser.o \ - lib/ejs/ejsProcs.o \ - lib/ejs/miniMpr.o \ - lib/ejs/var.o -NOPROTO=YES -# End SUBSYSTEM EJS -####################### diff --git a/source4/lib/ejs/ejs.h b/source4/lib/ejs/ejs.h deleted file mode 100644 index f1d2bb4c6e..0000000000 --- a/source4/lib/ejs/ejs.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * @file ejs.h - * @brief Primary Embedded Javascript (ECMAScript) header. - * @overview This Embedded Javascript (EJS) header defines the - * public API. This API should only be used by those directly - * using EJS without using Embedded Server Pages (ESP). ESP - * wraps all relevant APIs to expose a single consistent API. - * \n\n - * This API requires the mpr/var.h facilities to create and - * manage objects and properties. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#ifndef _h_EJS -#define _h_EJS 1 - -#include "miniMpr.h" -#include "var.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************* Prototypes *********************************/ - -typedef MprVarHandle EjsId; -typedef MprVarHandle EjsHandle; - -/* - * Multithreaded lock routines - */ -typedef void (*EjsLock)(void *lockData); -typedef void (*EjsUnlock)(void *lockData); - -/********************************* Prototypes *********************************/ -/* - * Module management - */ -extern int ejsOpen(EjsLock lock, EjsUnlock unlock, void *lockData); -extern void ejsClose(void); -extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); -extern void ejsCloseEngine(EjsId eid); - -/* - * Evaluation functions - */ -extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); -extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, - char **emsg); -extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args); - -/* - * Composite variable get / set routines. Can also use the MPR property - * routines on an object variable. - */ -extern MprVar ejsCreateObj(const char *name, int hashSize); -extern MprVar ejsCreateArray(const char *name, int hashSize); -extern bool ejsDestroyVar(MprVar *obj); -extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, - bool copyRef); -extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); -extern int ejsDeleteVar(EjsId eid, const char *var); - -extern MprVar *ejsGetLocalObject(EjsId eid); -extern MprVar *ejsGetGlobalObject(EjsId eid); - -/* - * Function routines - */ -extern void ejsDefineFunction(EjsId eid, const char *functionName, - char *args, char *body); -extern void ejsDefineCFunction(EjsId eid, const char *functionName, - MprCFunction fn, void *thisPtr, int flags); -extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags); -extern void *ejsGetThisPtr(EjsId eid); -extern MprVar *ejsGetReturnValue(EjsId eid); -extern int ejsGetLineNumber(EjsId eid); -extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); -extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern void ejsSetReturnValue(EjsId eid, MprVar value); -extern void ejsSetReturnString(EjsId eid, const char *str); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejsInternal.h b/source4/lib/ejs/ejsInternal.h deleted file mode 100644 index 3bf99d88b9..0000000000 --- a/source4/lib/ejs/ejsInternal.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * @file ejsInternal.h - * @brief Private header for Embedded Javascript (ECMAScript) - * @overview This Embedded Javascript header defines the private Embedded - * Javascript internal structures. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************* Includes ***********************************/ - -#ifndef _h_EJS_INTERNAL -#define _h_EJS_INTERNAL 1 - -#include "ejs.h" - -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Constants - */ - -#if BLD_FEATURE_SQUEEZE - #define EJS_PARSE_INCR 256 /* Growth factor */ - #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 128 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 13 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 8 /* Growth increment for lists */ -#else - #define EJS_PARSE_INCR 1024 /* Growth factor */ - #define EJS_MAX_RECURSE 100 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 256 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 29 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 16 /* Growth increment for lists */ -#endif -#define EJS_TOKEN_STACK 4 /* Put back token stack */ - -/* - * Lexical analyser tokens - */ -#define EJS_TOK_ERR -1 /* Any error */ -#define EJS_TOK_LPAREN 1 /* ( */ -#define EJS_TOK_RPAREN 2 /* ) */ -#define EJS_TOK_IF 3 /* if */ -#define EJS_TOK_ELSE 4 /* else */ -#define EJS_TOK_LBRACE 5 /* { */ -#define EJS_TOK_RBRACE 6 /* } */ -#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ -#define EJS_TOK_EXPR 8 /* +, -, /, % */ -#define EJS_TOK_SEMI 9 /* ; */ -#define EJS_TOK_LITERAL 10 /* literal string */ -#define EJS_TOK_FUNCTION_NAME 11 /* functionName */ -#define EJS_TOK_NEWLINE 12 /* newline white space */ -#define EJS_TOK_ID 13 /* Identifier */ -#define EJS_TOK_EOF 14 /* End of script */ -#define EJS_TOK_COMMA 15 /* Comma */ -#define EJS_TOK_VAR 16 /* var */ -#define EJS_TOK_ASSIGNMENT 17 /* = */ -#define EJS_TOK_FOR 18 /* for */ -#define EJS_TOK_INC_DEC 19 /* ++, -- */ -#define EJS_TOK_RETURN 20 /* return */ -#define EJS_TOK_PERIOD 21 /* . */ -#define EJS_TOK_LBRACKET 22 /* [ */ -#define EJS_TOK_RBRACKET 23 /* ] */ -#define EJS_TOK_NEW 24 /* new */ -#define EJS_TOK_DELETE 25 /* delete */ -#define EJS_TOK_IN 26 /* in */ -#define EJS_TOK_FUNCTION 27 /* function */ -#define EJS_TOK_NUMBER 28 /* Number */ - -/* - * Expression operators - */ -#define EJS_EXPR_LESS 1 /* < */ -#define EJS_EXPR_LESSEQ 2 /* <= */ -#define EJS_EXPR_GREATER 3 /* > */ -#define EJS_EXPR_GREATEREQ 4 /* >= */ -#define EJS_EXPR_EQ 5 /* == */ -#define EJS_EXPR_NOTEQ 6 /* != */ -#define EJS_EXPR_PLUS 7 /* + */ -#define EJS_EXPR_MINUS 8 /* - */ -#define EJS_EXPR_DIV 9 /* / */ -#define EJS_EXPR_MOD 10 /* % */ -#define EJS_EXPR_LSHIFT 11 /* << */ -#define EJS_EXPR_RSHIFT 12 /* >> */ -#define EJS_EXPR_MUL 13 /* * */ -#define EJS_EXPR_ASSIGNMENT 14 /* = */ -#define EJS_EXPR_INC 15 /* ++ */ -#define EJS_EXPR_DEC 16 /* -- */ -#define EJS_EXPR_BOOL_COMP 17 /* ! */ - -/* - * Conditional operators - */ -#define EJS_COND_AND 1 /* && */ -#define EJS_COND_OR 2 /* || */ -#define EJS_COND_NOT 3 /* ! */ - -/* - * States - */ -#define EJS_STATE_ERR -1 /* Error state */ -#define EJS_STATE_EOF 1 /* End of file */ -#define EJS_STATE_COND 2 /* Parsing a "(conditional)" stmt */ -#define EJS_STATE_COND_DONE 3 -#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ -#define EJS_STATE_RELEXP_DONE 5 -#define EJS_STATE_EXPR 6 /* Parsing an expression */ -#define EJS_STATE_EXPR_DONE 7 -#define EJS_STATE_STMT 8 /* Parsing General statement */ -#define EJS_STATE_STMT_DONE 9 -#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ -#define EJS_STATE_ARG_LIST 11 /* Function arg list */ -#define EJS_STATE_ARG_LIST_DONE 12 -#define EJS_STATE_DEC_LIST 16 /* Declaration list */ -#define EJS_STATE_DEC_LIST_DONE 17 -#define EJS_STATE_DEC 18 /* Declaration statement */ -#define EJS_STATE_DEC_DONE 19 -#define EJS_STATE_RET 20 /* Return statement */ - -#define EJS_STATE_BEGIN EJS_STATE_STMT - -/* - * General parsing flags. - */ -#define EJS_FLAGS_EXE 0x1 /* Execute statements */ -#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ -#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ -#define EJS_FLAGS_CREATE 0x8 /* Create var */ -#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ -#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ -#define EJS_FLAGS_FOREACH 0x40 /* In foreach */ -#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ -#define EJS_FLAGS_EXIT 0x100 /* Must exit */ - -/* - * Putback token - */ - -typedef struct EjsToken { - char *token; /* Token string */ - int id; /* Token ID */ -} EjsToken; - -/* - * EJ evaluation block structure - */ -typedef struct ejEval { - EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ - int putBackIndex; /* Top of stack index */ - MprStr line; /* Current line */ - int lineLength; /* Current line length */ - int lineNumber; /* Parse line number */ - int lineColumn; /* Column in line */ - MprStr script; /* Input script for parsing */ - char *scriptServp; /* Next token in the script */ - int scriptSize; /* Length of script */ - MprStr tokbuf; /* Current token */ - char *tokEndp; /* Pointer past end of token */ - char *tokServp; /* Pointer to next token char */ - int tokSize; /* Size of token buffer */ -} EjsInput; - -/* - * Function call structure - */ -typedef struct { - MprArray *args; /* Args for function */ - MprVar *fn; /* Function definition */ - char *procName; /* Function name */ -} EjsProc; - -/* - * Per EJS structure - */ -typedef struct ej { - EjsHandle altHandle; /* alternate callback handle */ - MprVar *currentObj; /* Ptr to current object */ - MprVar *currentProperty; /* Ptr to current property */ - EjsId eid; /* Halloc handle */ - char *error; /* Error message */ - int exitStatus; /* Status to exit() */ - int flags; /* Flags */ - MprArray *frames; /* List of variable frames */ - MprVar *global; /* Global object */ - EjsInput *input; /* Input evaluation block */ - MprVar *local; /* Local object */ - EjsHandle primaryHandle; /* primary callback handle */ - EjsProc *proc; /* Current function */ - MprVar result; /* Variable result */ - void *thisPtr; /* C++ ptr for functions */ - int tid; /* Current token id */ - char *token; /* Pointer to token string */ - MprVar tokenNumber; /* Parsed number */ -} Ejs; - -typedef int EjsBlock; /* Scope block id */ - -/* - * Function callback when using Alternate handles. - */ -typedef int (*EjsAltStringCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, char **argv); -typedef int (*EjsAltCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, MprVar **argv); - -/******************************** Prototypes **********************************/ -/* - * Ejs Lex - */ -extern int ejsLexOpenScript(Ejs* ep, char *script); -extern void ejsLexCloseScript(Ejs* ep); -extern int ejsInitInputState(EjsInput *ip); -extern void ejsLexSaveInputState(Ejs* ep, EjsInput* state); -extern void ejsLexFreeInputState(Ejs* ep, EjsInput* state); -extern void ejsLexRestoreInputState(Ejs* ep, EjsInput* state); -extern int ejsLexGetToken(Ejs* ep, int state); -extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); - -/* - * Parsing - */ -extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, - int flags); -extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, - char *property, int flags); -extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, - MprVar **varValue, int flags); -extern int ejsParse(Ejs *ep, int state, int flags); -extern Ejs *ejsPtr(EjsId eid); -extern void ejsSetExitStatus(int eid, int status); -extern void ejsSetFlags(int orFlags, int andFlags); - -/* - * Create variable scope blocks - */ -extern EjsBlock ejsOpenBlock(EjsId eid); -extern int ejsCloseBlock(EjsId eid, EjsBlock vid); -extern int ejsEvalBlock(EjsId eid, char *script, MprVar *v, char **err); -extern int ejsDefineStandardProperties(MprVar *objVar); - -/* - * Error handling - */ -extern void ejsError(Ejs *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS_INTERNAL */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejsLex.c b/source4/lib/ejs/ejsLex.c deleted file mode 100644 index a5f15c2979..0000000000 --- a/source4/lib/ejs/ejsLex.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * @file ejsLex.c - * @brief EJS Lexical Analyser - * @overview EJS lexical analyser. This implementes a lexical analyser - * for a subset of the JavaScript language. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static int getLexicalToken(Ejs *ep, int state); -static int tokenAddChar(Ejs *ep, int c); -static int inputGetc(Ejs *ep); -static void inputPutback(Ejs *ep, int c); -static int charConvert(Ejs *ep, int base, int maxDig); - -/************************************* Code ***********************************/ -/* - * Open a new input script - */ - -int ejsLexOpenScript(Ejs *ep, char *script) -{ - EjsInput *ip; - - mprAssert(ep); - mprAssert(script); - - if ((ep->input = mprMalloc(sizeof(EjsInput))) == NULL) { - return -1; - } - ip = ep->input; - memset(ip, 0, sizeof(*ip)); - -/* - * Create the parse token buffer and script buffer - */ - ip->tokbuf = mprMalloc(EJS_PARSE_INCR); - ip->tokSize = EJS_PARSE_INCR; - ip->tokServp = ip->tokbuf; - ip->tokEndp = ip->tokbuf; - - ip->script = mprStrdup(script); - ip->scriptSize = strlen(script); - ip->scriptServp = ip->script; - - ip->lineNumber = 1; - ip->lineLength = 0; - ip->lineColumn = 0; - ip->line = NULL; - - ip->putBackIndex = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the input script - */ - -void ejsLexCloseScript(Ejs *ep) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].token = 0; - } - - mprFree(ip->line); - mprFree(ip->tokbuf); - mprFree(ip->script); - - mprFree(ip); -} - -/******************************************************************************/ -/* - * Initialize an input state structure - */ - -int ejsInitInputState(EjsInput *ip) -{ - mprAssert(ip); - - memset(ip, 0, sizeof(*ip)); - ip->putBackIndex = -1; - - return 0; -} -/******************************************************************************/ -/* - * Save the input state - */ - -void ejsLexSaveInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - - *state = *ip; - - for (i = 0; i < ip->putBackIndex; i++) { - state->putBack[i].token = mprStrdup(ip->putBack[i].token); - state->putBack[i].id = ip->putBack[i].id; - } - for (; i < EJS_TOKEN_STACK; i++) { - state->putBack[i].token = 0; - } - - state->line = mprMalloc(ip->lineLength); - mprStrcpy(state->line, ip->lineLength, ip->line); - - state->lineColumn = ip->lineColumn; - state->lineNumber = ip->lineNumber; - state->lineLength = ip->lineLength; -} - -/******************************************************************************/ -/* - * Restore the input state - */ - -void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - mprAssert(state); - - ip = ep->input; - mprAssert(ip); - - ip->tokbuf = state->tokbuf; - ip->tokServp = state->tokServp; - ip->tokEndp = state->tokEndp; - ip->tokSize = state->tokSize; - - ip->script = state->script; - ip->scriptServp = state->scriptServp; - ip->scriptSize = state->scriptSize; - - ip->putBackIndex = state->putBackIndex; - for (i = 0; i < ip->putBackIndex; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].id = state->putBack[i].id; - ip->putBack[i].token = mprStrdup(state->putBack[i].token); - } - - mprFree(ip->line); - ip->line = mprMalloc(state->lineLength); - mprStrcpy(ip->line, state->lineLength, state->line); - - ip->lineColumn = state->lineColumn; - ip->lineNumber = state->lineNumber; - ip->lineLength = state->lineLength; -} - -/******************************************************************************/ -/* - * Free a saved input state - */ - -void ejsLexFreeInputState(Ejs *ep, EjsInput *state) -{ - int i; - - mprAssert(ep); - mprAssert(state); - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(state->putBack[i].token); - } - state->putBackIndex = -1; - mprFree(state->line); - state->lineLength = 0; - state->lineColumn = 0; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -int ejsLexGetToken(Ejs *ep, int state) -{ - mprAssert(ep); - - ep->tid = getLexicalToken(ep, state); - return ep->tid; -} - -/******************************************************************************/ - -/* - * Check for reserved words "if", "else", "var", "for", "foreach", - * "delete", "function", and "return". "new", "in" and "function" - * done below. "true", "false", "null", "undefined" are handled - * as global objects. - * - * Other reserved words not supported: - * "break", "case", "catch", "continue", "default", "do", - * "finally", "instanceof", "switch", "this", "throw", "try", - * "typeof", "while", "with" - * - * ECMA extensions reserved words (not supported): - * "abstract", "boolean", "byte", "char", "class", "const", - * "debugger", "double", "enum", "export", "extends", - * "final", "float", "goto", "implements", "import", "int", - * "interface", "long", "native", "package", "private", - * "protected", "public", "short", "static", "super", - * "synchronized", "throws", "transient", "volatile" - */ - -static int checkReservedWord(Ejs *ep, int state, int c, int tid) -{ - if (state == EJS_STATE_STMT) { - if (strcmp(ep->token, "if") == 0) { - inputPutback(ep, c); - return EJS_TOK_IF; - } else if (strcmp(ep->token, "else") == 0) { - inputPutback(ep, c); - return EJS_TOK_ELSE; - } else if (strcmp(ep->token, "var") == 0) { - inputPutback(ep, c); - return EJS_TOK_VAR; - } else if (strcmp(ep->token, "for") == 0) { - inputPutback(ep, c); - return EJS_TOK_FOR; - } else if (strcmp(ep->token, "delete") == 0) { - inputPutback(ep, c); - return EJS_TOK_DELETE; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } else if (strcmp(ep->token, "return") == 0) { - if ((c == ';') || (c == '(')) { - inputPutback(ep, c); - } - return EJS_TOK_RETURN; - } - } else if (state == EJS_STATE_EXPR) { - if (strcmp(ep->token, "new") == 0) { - inputPutback(ep, c); - return EJS_TOK_NEW; - } else if (strcmp(ep->token, "in") == 0) { - inputPutback(ep, c); - return EJS_TOK_IN; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } - } - return tid; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -static int getLexicalToken(Ejs *ep, int state) -{ - MprType type; - EjsInput *ip; - int done, tid, c, quote, style, idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ep->tid = -1; - tid = -1; - type = BLD_FEATURE_NUM_TYPE_ID; - - /* - * Use a putback tokens first. Don't free strings as caller needs access. - */ - if (ip->putBackIndex >= 0) { - idx = ip->putBackIndex; - tid = ip->putBack[idx].id; - ep->token = (char*) ip->putBack[idx].token; - tid = checkReservedWord(ep, state, 0, tid); - ip->putBackIndex--; - return tid; - } - ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; - *ip->tokServp = '\0'; - - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - - /* - * Main lexical analyser - */ - for (done = 0; !done; ) { - switch (c) { - case -1: - return EJS_TOK_EOF; - - case ' ': - case '\t': - case '\r': - do { - if ((c = inputGetc(ep)) < 0) - break; - } while (c == ' ' || c == '\t' || c == '\r'); - break; - - case '\n': - return EJS_TOK_NEWLINE; - - case '(': - tokenAddChar(ep, c); - return EJS_TOK_LPAREN; - - case ')': - tokenAddChar(ep, c); - return EJS_TOK_RPAREN; - - case '[': - tokenAddChar(ep, c); - return EJS_TOK_LBRACKET; - - case ']': - tokenAddChar(ep, c); - return EJS_TOK_RBRACKET; - - case '.': - tokenAddChar(ep, c); - return EJS_TOK_PERIOD; - - case '{': - tokenAddChar(ep, c); - return EJS_TOK_LBRACE; - - case '}': - tokenAddChar(ep, c); - return EJS_TOK_RBRACE; - - case '+': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '+' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_PLUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_INC); - return EJS_TOK_INC_DEC; - - case '-': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '-' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_MINUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_DEC); - return EJS_TOK_INC_DEC; - - case '*': - tokenAddChar(ep, EJS_EXPR_MUL); - return EJS_TOK_EXPR; - - case '%': - tokenAddChar(ep, EJS_EXPR_MOD); - return EJS_TOK_EXPR; - - case '/': - /* - * Handle the division operator and comments - */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '*' && c != '/') { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_DIV); - return EJS_TOK_EXPR; - } - style = c; - /* - * Eat comments. Both C and C++ comment styles are supported. - */ - while (1) { - if ((c = inputGetc(ep)) < 0) { - if (style == '/') { - return EJS_TOK_EOF; - } - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '\n' && style == '/') { - break; - } else if (c == '*') { - c = inputGetc(ep); - if (style == '/') { - if (c == '\n') { - break; - } - } else { - if (c == '/') { - break; - } - } - } - } - /* - * Continue looking for a token, so get the next character - */ - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - break; - - case '<': /* < and <= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '<') { - tokenAddChar(ep, EJS_EXPR_LSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_LESSEQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_LESS); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '>': /* > and >= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '>') { - tokenAddChar(ep, EJS_EXPR_RSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_GREATEREQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_GREATER); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '=': /* "==" */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_EQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - return EJS_TOK_ASSIGNMENT; - - case '!': /* "!=" or "!"*/ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_NOTEQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_BOOL_COMP); - return EJS_TOK_EXPR; - - case ';': - tokenAddChar(ep, c); - return EJS_TOK_SEMI; - - case ',': - tokenAddChar(ep, c); - return EJS_TOK_COMMA; - - case '|': /* "||" */ - if ((c = inputGetc(ep)) < 0 || c != '|') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_OR); - return EJS_TOK_LOGICAL; - - case '&': /* "&&" */ - if ((c = inputGetc(ep)) < 0 || c != '&') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_AND); - return EJS_TOK_LOGICAL; - - case '\"': /* String quote */ - case '\'': - quote = c; - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - - while (c != quote) { - /* - * Check for escape sequence characters - */ - if (c == '\\') { - c = inputGetc(ep); - - if (isdigit(c)) { - /* - * Octal support, \101 maps to 65 = 'A'. Put first - * char back so converter will work properly. - */ - inputPutback(ep, c); - c = charConvert(ep, 8, 3); - - } else { - switch (c) { - case 'n': - c = '\n'; break; - case 'b': - c = '\b'; break; - case 'f': - c = '\f'; break; - case 'r': - c = '\r'; break; - case 't': - c = '\t'; break; - case 'x': - /* - * Hex support, \x41 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - break; - case 'u': - /* - * Unicode support, \x0401 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - c = c*16 + charConvert(ep, 16, 2); - - break; - case '\'': - case '\"': - case '\\': - break; - default: - ejsError(ep, "Invalid Escape Sequence"); - return EJS_TOK_ERR; - } - } - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } else { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Unmatched Quote"); - return EJS_TOK_ERR; - } - } - return EJS_TOK_LITERAL; - - case '0': - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (tolower(c) == 'x') { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - } - if (! isdigit(c)) { -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { - /* Fall through */ - type = MPR_TYPE_FLOAT; - } else -#endif - { - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - } - /* Fall through to get more digits */ - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || tolower(c) == 'f') { - type = MPR_TYPE_FLOAT; - } - } while (isdigit(c) || c == '.' || tolower(c) == 'e' || tolower(c) == 'f' || - ((type == MPR_TYPE_FLOAT) && (c == '+' || c == '-'))); -#else - } while (isdigit(c)); -#endif - - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - - default: - /* - * Identifiers or a function names - */ - while (1) { - if (c == '\\') { - if ((c = inputGetc(ep)) < 0) { - break; - } - if (c == '\n' || c == '\r') { - break; - } - } else if (tokenAddChar(ep, c) < 0) { - break; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (!isalnum(c) && c != '$' && c != '_' && c != '\\') { - break; - } - } - if (*ep->token == '\0') { - c = inputGetc(ep); - break; - } - if (! isalpha((int) *ep->token) && *ep->token != '$' && - *ep->token != '_') { - ejsError(ep, "Invalid identifier %s", ep->token); - return EJS_TOK_ERR; - } - - tid = checkReservedWord(ep, state, c, EJS_TOK_ID); - if (tid != EJS_TOK_ID) { - return tid; - } - - /* - * Skip white space after token to find out whether this is - * a function or not. - */ - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if ((c = inputGetc(ep)) < 0) - break; - } - - tid = EJS_TOK_ID; - done++; - } - } - - /* - * Putback the last extra character for next time - */ - inputPutback(ep, c); - return tid; -} - -/******************************************************************************/ -/* - * Convert a hex or octal character back to binary, return original char if - * not a hex digit - */ - -static int charConvert(Ejs *ep, int base, int maxDig) -{ - int i, c, lval, convChar; - - lval = 0; - for (i = 0; i < maxDig; i++) { - if ((c = inputGetc(ep)) < 0) { - break; - } - /* - * Initialize to out of range value - */ - convChar = base; - if (isdigit(c)) { - convChar = c - '0'; - } else if (c >= 'a' && c <= 'f') { - convChar = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - convChar = c - 'A' + 10; - } - /* - * If unexpected character then return it to buffer. - */ - if (convChar >= base) { - inputPutback(ep, c); - break; - } - lval = (lval * base) + convChar; - } - return lval; -} - -/******************************************************************************/ -/* - * Putback the last token read. Accept at most one push back token. - */ - -void ejsLexPutbackToken(Ejs *ep, int tid, char *string) -{ - EjsInput *ip; - int idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ip->putBackIndex += 1; - idx = ip->putBackIndex; - ip->putBack[idx].id = tid; - - if (ip->putBack[idx].token) { - if (ip->putBack[idx].token == string) { - return; - } - mprFree(ip->putBack[idx].token); - } - ip->putBack[idx].token = mprStrdup(string); -} - -/******************************************************************************/ -/* - * Add a character to the token buffer - */ - -static int tokenAddChar(Ejs *ep, int c) -{ - EjsInput *ip; - uchar *oldbuf; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - if (ip->tokEndp >= &ip->tokbuf[ip->tokSize - 1]) { - ip->tokSize += EJS_PARSE_INCR; - oldbuf = ip->tokbuf; - ip->tokbuf = mprRealloc(ip->tokbuf, ip->tokSize); - if (ip->tokbuf == 0) { - ejsError(ep, "Token too big"); - return -1; - } - ip->tokEndp += (int) ((uchar*) ip->tokbuf - oldbuf); - ip->tokServp += (int) ((uchar*) ip->tokbuf - oldbuf); - ep->token += (int) ((uchar*) ip->tokbuf - oldbuf); - } - *ip->tokEndp++ = c; - *ip->tokEndp = '\0'; - - return 0; -} - -/******************************************************************************/ -/* - * Get another input character - */ - -static int inputGetc(Ejs *ep) -{ - EjsInput *ip; - int c; - - mprAssert(ep); - ip = ep->input; - - if (ip->scriptSize <= 0) { - return -1; - } - - c = (uchar) (*ip->scriptServp++); - ip->scriptSize--; - - /* - * For debugging, accumulate the line number and the currenly parsed line - */ - if (c == '\n') { -#if BLD_DEBUG && 0 - if (ip->lineColumn > 0) { - printf("PARSED: %s\n", ip->line); - } -#endif - ip->lineNumber++; - ip->lineColumn = 0; - } else { - if ((ip->lineColumn + 2) >= ip->lineLength) { - ip->lineLength += 80; - ip->line = mprRealloc(ip->line, ip->lineLength * sizeof(char)); - } - ip->line[ip->lineColumn++] = c; - ip->line[ip->lineColumn] = '\0'; - } - return c; -} - -/******************************************************************************/ -/* - * Putback a character onto the input queue - */ - -static void inputPutback(Ejs *ep, int c) -{ - EjsInput *ip; - - mprAssert(ep); - - if (c != 0) { - ip = ep->input; - *--ip->scriptServp = c; - ip->scriptSize++; - ip->lineColumn--; - ip->line[ip->lineColumn] = '\0'; - } -} - -/******************************************************************************/ - -#else -void ejsLexDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejsLib.c b/source4/lib/ejs/ejsLib.c deleted file mode 100644 index caae5b6495..0000000000 --- a/source4/lib/ejs/ejsLib.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * @file ejs.c - * @brief Embedded JavaScript (EJS) - * @overview Main module interface logic. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/********************************** Local Data ********************************/ - -/* - * These fields must be locked before any access when multithreaded - */ -static MprVar master; /* Master object */ -static MprArray *ejsList; /* List of ej handles */ - -#if BLD_FEATURE_MULTITHREAD -static EjsLock lock; -static EjsUnlock unlock; -static void *lockData; -#define ejsLock() if (lock) { (lock)(lockData); } else -#define ejsUnlock() if (unlock) { (unlock)(lockData); } else -#else -#define ejsLock() -#define ejsUnlock() -#endif - -/****************************** Forward Declarations **************************/ - -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); - -/************************************* Code ***********************************/ -/* - * Initialize the EJ subsystem - */ - -int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) -{ - MprVar *np; - -#if BLD_FEATURE_MULTITHREAD - if (lockFn) { - lock = lockFn; - unlock = unlockFn; - lockData = data; - } -#endif - ejsLock(); - - /* - * Master is the top level object (above global). It is used to clone its - * contents into the global scope for each. This is never visible to the - * user, so don't use ejsCreateObj(). - */ - master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); - if (master.type == MPR_TYPE_UNDEFINED) { - ejsUnlock(); - return MPR_ERR_CANT_ALLOCATE; - } - - ejsList = mprCreateArray(); - ejsDefineStandardProperties(&master); - - /* - * Make these objects immutable - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprSetVarReadonly(np, 1); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - ejsUnlock(); - return 0; -} - -/******************************************************************************/ - -void ejsClose() -{ - ejsLock(); - mprDestroyArray(ejsList); - mprDestroyVar(&master); - ejsUnlock(); -} - -/******************************************************************************/ -/* - * Create and initialize an EJS engine - */ - -EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) -{ - MprVar *np; - Ejs *ep; - - ep = mprMalloc(sizeof(Ejs)); - if (ep == 0) { - return (EjsId) -1; - } - memset(ep, 0, sizeof(Ejs)); - - ejsLock(); - ep->eid = (EjsId) mprAddToArray(ejsList, ep); - ejsUnlock(); - - /* - * Create array of local variable frames - */ - ep->frames = mprCreateArray(); - if (ep->frames == 0) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - ep->primaryHandle = primaryHandle; - ep->altHandle = altHandle; - - /* - * Create first frame: global variables - */ - ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); - if (ep->global->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->global); - - /* - * Create first local variable frame - */ - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); - if (ep->local->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->local); - - /* - * Clone all master variables into the global frame. This does a - * reference copy. - * - * ejsDefineStandardProperties(ep->global); - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprCreateProperty(ep->global, np->name, np); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - - mprCreateProperty(ep->global, "global", ep->global); - mprCreateProperty(ep->global, "this", ep->global); - mprCreateProperty(ep->local, "local", ep->local); - - return ep->eid; -} - -/******************************************************************************/ -/* - * Close an EJS instance - */ - -void ejsCloseEngine(EjsId eid) -{ - Ejs *ep; - MprVar *vp; - void **handles; - int i; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - - mprFree(ep->error); - mprDestroyVar(&ep->result); - mprDestroyVar(&ep->tokenNumber); - - mprDeleteProperty(ep->local, "local"); - mprDeleteProperty(ep->global, "this"); - mprDeleteProperty(ep->global, "global"); - - handles = ep->frames->handles; - for (i = 0; i < ep->frames->max; i++) { - vp = handles[i]; - if (vp) { -#if BLD_DEBUG - if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { - mprLog(7, "ejsCloseEngine: %s has ref count %d\n", - vp->name, vp->properties->refCount); - } -#endif - mprDestroyVar(vp); - mprFree(vp); - mprRemoveFromArray(ep->frames, i); - } - } - mprDestroyArray(ep->frames); - - ejsLock(); - mprRemoveFromArray(ejsList, (int) ep->eid); - ejsUnlock(); - - mprFree(ep); -} - -/******************************************************************************/ -/* - * Evaluate an EJS script file - */ - -int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) -{ - struct stat sbuf; - Ejs *ep; - char *script; - int rc, fd; - - mprAssert(path && *path); - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - goto error; - } - - if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { - ejsError(ep, "Can't open %s\n", path); - goto error; - } - - if (stat(path, &sbuf) < 0) { - close(fd); - ejsError(ep, "Cant stat %s", path); - goto error; - } - - if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { - close(fd); - ejsError(ep, "Cant malloc %d", (int) sbuf.st_size); - goto error; - } - - if (read(fd, script, sbuf.st_size) != (int) sbuf.st_size) { - close(fd); - mprFree(script); - ejsError(ep, "Error reading %s", path); - goto error; - } - - script[sbuf.st_size] = '\0'; - close(fd); - - rc = ejsEvalBlock(eid, script, result, emsg); - mprFree(script); - - return rc; - -/* - * Error return - */ -error: - *emsg = mprStrdup(ep->error); - return -1; -} - -/******************************************************************************/ -/* - * Create a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsOpenBlock(EjsId eid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); - - mprCreateProperty(ep->local, "local", ep->local); - - return mprAddToArray(ep->frames, ep->local); -} - -/******************************************************************************/ -/* - * Close a variable scope block opened via ejsOpenBlock. Pop back the old - * local variables frame. - */ - -int ejsCloseBlock(EjsId eid, int fid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - /* - * Must remove self-references before destroying "local" - */ - mprDeleteProperty(ep->local, "local"); - - mprDestroyVar(ep->local); - mprFree(ep->local); - - mprRemoveFromArray(ep->frames, fid); - ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; - - return 0; -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All frames - * created during this context will be automatically deleted when complete. - * vp and emsg are optional. i.e. created local variables will be discarded - * when this routine returns. - */ - -int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - int rc, fid; - - mprAssert(script); - - fid = ejsOpenBlock(eid); - rc = ejsEvalScript(eid, script, vp, emsg); - ejsCloseBlock(eid, fid); - - return rc; -} - -/******************************************************************************/ -/* - * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" - * by EJ and the caller must not free it. Returns -1 on errors and zero - * for success. On errors, emsg will be set to the reason. The caller must - * free emsg. - */ - -int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - Ejs *ep; - EjsInput *oldBlock; - int state; - void *endlessLoopTest; - int loopCounter; - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - mprDestroyVar(&ep->result); - - if (script == 0) { - return 0; - } - - /* - * Allocate a new evaluation block, and save the old one - */ - oldBlock = ep->input; - ejsLexOpenScript(ep, script); - - /* - * Do the actual parsing and evaluation - */ - loopCounter = 0; - endlessLoopTest = NULL; - ep->exitStatus = 0; - - do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); - - if (state == EJS_STATE_RET) { - state = EJS_STATE_EOF; - } - /* - * Stuck parser and endless recursion protection. - */ - if (endlessLoopTest == ep->input->scriptServp) { - if (loopCounter++ > 10) { - state = EJS_STATE_ERR; - ejsError(ep, "Syntax error"); - } - } else { - endlessLoopTest = ep->input->scriptServp; - loopCounter = 0; - } - } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); - - ejsLexCloseScript(ep); - - /* - * Return any error string to the user - */ - if (state == EJS_STATE_ERR && emsg) { - *emsg = mprStrdup(ep->error); - } - - /* - * Restore the old evaluation block - */ - ep->input = oldBlock; - - if (state == EJS_STATE_ERR) { - return -1; - } - - if (vp) { - *vp = ep->result; - } - - return ep->exitStatus; -} - -/******************************************************************************/ -/* - * Core error handling - */ - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) - PRINTF_ATTRIBUTE(2, 0); - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) -{ - EjsInput *ip; - char *errbuf, *msgbuf; - - mprAssert(ep); - mprAssert(args); - - msgbuf = NULL; - mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); - - if (ep) { - ip = ep->input; - if (ip) { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, - "%s\nError on line %d. Offending line: %s\n\n", - msgbuf, ip->lineNumber, ip->line); - } else { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); - } - mprFree(ep->error); - ep->error = errbuf; - } - mprFree(msgbuf); -} - -/******************************************************************************/ -/* - * Internal use function to set the error message - */ - -void ejsError(Ejs* ep, const char* fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Public routine to set the error message - */ - -void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) -{ - va_list args; - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejsGetLineNumber(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Return the local object - */ - -MprVar *ejsGetLocalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->local; -} - -/******************************************************************************/ -/* - * Return the global object - */ - -MprVar *ejsGetGlobalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->global; -} - -/******************************************************************************/ -/* - * Copy the value of an object property. Return value is in "value". - * If deepCopy is true, copy all object/strings. Otherwise, object reference - * counts are incremented. Callers must always call mprDestroyVar on the - * return value to prevent leaks. - * - * Returns: -1 on errors or if the variable is not found. - */ - -int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprCopyProperty(value, vp, deepCopy); -} - -/******************************************************************************/ -/* - * Return the value of an object property. Return value is in "value". - * Objects and strings are not copied and reference counts are not modified. - * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the - * variable is not found. - */ - -int ejsReadVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprReadProperty(vp, value); -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { - return -1; - } - mprAssert(vp); - - /* - * Only copy the value. Don't overwrite the object's name - */ - mprWriteProperty(vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) -{ - return ejsWriteVar(eid, var, &value); -} - -/******************************************************************************/ -/* - * Delete a variable - */ - -int ejsDeleteVar(EjsId eid, const char *var) -{ - Ejs *ep; - MprVar *vp; - MprVar *obj; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { - return -1; - } - mprDeleteProperty(obj, vp->name); - return 0; -} - -/******************************************************************************/ -/* - * Set the expression return value - */ - -void ejsSetReturnValue(EjsId eid, MprVar value) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Set the expression return value to a string value - */ - -void ejsSetReturnString(EjsId eid, const char *str) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Get the expression return value - */ - -MprVar *ejsGetReturnValue(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return &ep->result; -} - -/******************************************************************************/ -/* - * Define a C function. If eid < 0, then update the master object with this - * function. NOTE: in this case, functionName must be simple without any "." or - * "[]" elements. If eid >= 0, add to the specified script engine. In this - * case, functionName can be an arbitrary object reference and can contain "." - * or "[]". - */ - -void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, - void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a C function with String arguments - */ - -void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a JavaScript function. Args should be comma separated. - * Body should not contain braces. - */ - -void ejsDefineFunction(EjsId eid, const char *functionName, char *args, - char *body) -{ - MprVar v; - - v = mprCreateFunctionVar(args, body, 0); - if (eid < 0) { - ejsLock(); - mprCreateProperty(&master, functionName, &v); - ejsUnlock(); - } else { - ejsWriteVar(eid, functionName, &v); - } - mprDestroyVar(&v); -} - -/******************************************************************************/ - -void *ejsGetThisPtr(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->thisPtr; -} - -/******************************************************************************/ -/* - * Find a variable given a variable name and return the parent object and - * the variable itself, the variable . This routine supports variable names - * that may be objects or arrays but may NOT have expressions in the array - * indicies. Returns -1 on errors or if the variable is not found. - */ - -int ejsGetVarCore(Ejs *ep, const char *vname, MprVar **obj, - MprVar **varValue, int flags) -{ - MprVar *currentObj; - MprVar *currentVar; - char tokBuf[EJS_MAX_ID]; - char *propertyName, *token, *next, *cp, *varName; - - if (obj) { - *obj = 0; - } - if (varValue) { - *varValue = 0; - } - currentObj = ejsFindObj(ep, 0, vname, flags); - currentVar = 0; - propertyName = 0; - - next = varName = mprStrdup(vname); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - while (currentObj != 0 && token != 0 && *token) { - - if (*token == '[') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - propertyName = token; - if (*propertyName == '\"') { - propertyName++; - if ((cp = strchr(propertyName, '\"')) != 0) { - *cp = '\0'; - } - } else if (*propertyName == '\'') { - propertyName++; - if ((cp = strchr(propertyName, '\'')) != 0) { - *cp = '\0'; - } - } - - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (*token != ']') { - mprFree(varName); - return -1; - } - - } else if (*token == '.') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (!isalpha((int) token[0]) && - token[0] != '_' && token[0] != '$') { - mprFree(varName); - return -1; - } - - propertyName = token; - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - - } else { - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - } - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - } - mprFree(varName); - - if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { - currentVar = mprCreatePropertyValue(currentObj, propertyName, - mprCreateUndefinedVar()); - } - if (obj) { - *obj = currentObj; - } - - /* - * Don't use mprCopyVar as it will copy the data - */ - if (varValue) { - *varValue = currentVar; - } - return currentVar ? 0 : -1; -} - -/******************************************************************************/ -/* - * Get the next token as part of a variable specification. This will return - * a pointer to the next token and will return a pointer to the next token - * (after this one) in "next". The tokBuf holds the parsed token. - */ -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) -{ - char *start, *cp; - int len; - - start = *next; - while (isspace((int) *start) || *start == '\n' || *start == '\r') { - start++; - } - cp = start; - - if (*cp == '.' || *cp == '[' || *cp == ']') { - cp++; - } else { - while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && - !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { - cp++; - } - } - len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); - tokBuf[len] = '\0'; - - *next = cp; - return tokBuf; -} - -/******************************************************************************/ -/* - * Get the EJS structure pointer - */ - -Ejs *ejsPtr(EjsId eid) -{ - Ejs *handle; - int intId; - - intId = (int) eid; - - ejsLock(); - mprAssert(0 <= intId && intId < ejsList->max); - - if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { - mprAssert(0); - ejsUnlock(); - return NULL; - } - handle = ejsList->handles[intId]; - ejsUnlock(); - return handle; -} - -/******************************************************************************/ -/* - * Utility routine to crack JavaScript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { - * mprError("Insufficient args\n"); - * return -1; - * } - */ - -int ejsParseArgs(int argc, char **argv, char *fmt, ...) -{ - va_list vargs; - bool *bp; - char *cp, **sp, *s; - int *ip, argn; - - va_start(vargs, fmt); - - if (argv == 0) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - s = argv[argn]; - switch (*cp) { - case 'b': - bp = va_arg(vargs, bool*); - if (bp) { - if (strcmp(s, "true") == 0 || s[0] == '1') { - *bp = 1; - } else { - *bp = 0; - } - } else { - *bp = 0; - } - break; - - case 'd': - ip = va_arg(vargs, int*); - *ip = atoi(s); - break; - - case 's': - sp = va_arg(vargs, char**); - *sp = s; - break; - - default: - mprAssert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ - -#else -void ejsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejsParser.c b/source4/lib/ejs/ejsParser.c deleted file mode 100644 index 772ed574c5..0000000000 --- a/source4/lib/ejs/ejsParser.c +++ /dev/null @@ -1,2378 +0,0 @@ -/* - * @file ejsParser.c - * @brief EJS Parser and Execution - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static void appendValue(MprVar *v1, MprVar *v2); -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -#if BLD_FEATURE_FLOATING_POINT -static int evalFloatExpr(Ejs *ep, double l, int rel, double r); -#endif -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalFunction(Ejs *ep, MprVar *obj, int flags); -static void freeProc(EjsProc *proc); -static int parseArgs(Ejs *ep, int state, int flags); -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName); -static int parseCond(Ejs *ep, int state, int flags); -static int parseDeclaration(Ejs *ep, int state, int flags); -static int parseExpr(Ejs *ep, int state, int flags); -static int parseFor(Ejs *ep, int state, int flags); -static int parseForIn(Ejs *ep, int state, int flags); -static int parseFunctionDec(Ejs *ep, int state, int flags); -static int parseFunction(Ejs *ep, int state, int flags, char *id); -static int parseId(Ejs *ep, int state, int flags, char **id, - char **fullName, int *fullNameLen, int *done); -static int parseInc(Ejs *ep, int state, int flags); -static int parseIf(Ejs *ep, int state, int flags, int *done); -static int parseStmt(Ejs *ep, int state, int flags); -static void removeNewlines(Ejs *ep, int state); -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); - -/************************************* Code ***********************************/ -/* - * Recursive descent parser for EJS - */ - -int ejsParse(Ejs *ep, int state, int flags) -{ - mprAssert(ep); - - switch (state) { - /* - * Any statement, function arguments or conditional expressions - */ - case EJS_STATE_STMT: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_STMT_DONE && - state != EJS_STATE_EOF && state != EJS_STATE_STMT_BLOCK_DONE && - state != EJS_STATE_RET) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_DEC: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_DEC_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_EXPR: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_EXPR_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - /* - * Variable declaration list - */ - case EJS_STATE_DEC_LIST: - state = parseDeclaration(ep, state, flags); - break; - - /* - * Function argument string - */ - case EJS_STATE_ARG_LIST: - state = parseArgs(ep, state, flags); - break; - - /* - * Logical condition list (relational operations separated by &&, ||) - */ - case EJS_STATE_COND: - state = parseCond(ep, state, flags); - break; - - /* - * Expression list - */ - case EJS_STATE_RELEXP: - state = parseExpr(ep, state, flags); - break; - } - - if (state == EJS_STATE_ERR && ep->error == NULL) { - ejsError(ep, "Syntax error"); - } - return state; -} - -/******************************************************************************/ -/* - * Parse any statement including functions and simple relational operations - */ - -static int parseStmt(Ejs *ep, int state, int flags) -{ - EjsProc *saveProc; - MprVar *vp, *saveObj; - char *id, *fullName, *initToken; - int done, expectSemi, tid, fullNameLen, rel; - int initId; - - mprAssert(ep); - - expectSemi = 0; - saveProc = NULL; - id = 0; - fullName = 0; - fullNameLen = 0; - - ep->currentObj = 0; - ep->currentProperty = 0; - - for (done = 0; !done && state != EJS_STATE_ERR; ) { - tid = ejsLexGetToken(ep, state); - - switch (tid) { - default: - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - done++; - break; - - case EJS_TOK_EXPR: - rel = (int) *ep->token; - if (state == EJS_STATE_EXPR) { - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - } - done++; - break; - - case EJS_TOK_LOGICAL: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_ERR: - state = EJS_STATE_ERR; - done++; - break; - - case EJS_TOK_EOF: - state = EJS_STATE_EOF; - done++; - break; - - case EJS_TOK_NEWLINE: - break; - - case EJS_TOK_SEMI: - /* - * This case is when we discover no statement and just a lone ';' - */ - if (state != EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - } - done++; - break; - - case EJS_TOK_PERIOD: - if (flags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined object \"%s\"\n", id); - goto error; - } - } - ep->currentObj = ep->currentProperty; - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - ejsError(ep, "Bad property after '.': %s\n", ep->token); - goto error; - } - mprFree(id); - id = mprStrdup(ep->token); - - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - updateResult(ep, state, flags, vp); - -#if BLD_DEBUG - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, - 0, ".", 0); -#endif - - ep->currentProperty = vp; - ejsLexPutbackToken(ep, tid, ep->token); - break; - - case EJS_TOK_LBRACKET: - ep->currentObj = ep->currentProperty; - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_RELEXP, flags) != EJS_STATE_RELEXP_DONE){ - goto error; - } - ep->currentObj = saveObj; - - mprFree(id); - mprVarToString(&id, MPR_MAX_STRING, 0, &ep->result); - - if (id[0] == '\0') { - if (flags & EJS_FLAGS_EXE) { - ejsError(ep, - "[] expression evaluates to the empty string\n"); - goto error; - } - } else { - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - ep->currentProperty = vp; - updateResult(ep, state, flags, vp); - } - -#if BLD_DEBUG - if (id[0] && strlen(id) < (MPR_MAX_VAR / 2)) { - /* - * If not executing yet, id may not be known - */ - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, - fullNameLen, 0, "[", id, "]", 0); - } -#endif - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { - ejsError(ep, "Missing ']'\n"); - goto error; - } - break; - - case EJS_TOK_ID: - state = parseId(ep, state, flags, &id, &fullName, &fullNameLen, - &done); - if (done && state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_ASSIGNMENT: - state = parseAssignment(ep, state, flags, id, fullName); - if (state == EJS_STATE_STMT) { - expectSemi++; - done++; - } - break; - - case EJS_TOK_INC_DEC: - state = parseInc(ep, state, flags); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_NEW: - if (ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW) - != EJS_STATE_EXPR_DONE) { - goto error; - } - break; - - case EJS_TOK_DELETE: - if (ejsParse(ep, EJS_STATE_EXPR, - flags | EJS_FLAGS_DELETE) != EJS_STATE_EXPR_DONE) { - goto error; - } - mprDeleteProperty(ep->currentObj, ep->currentProperty->name); - done++; - break; - - case EJS_TOK_FUNCTION: - state = parseFunctionDec(ep, state, flags); - done++; - break; - - case EJS_TOK_LITERAL: - /* - * Set the result to the string literal - */ - mprCopyVarValue(&ep->result, mprCreateStringVar(ep->token, 0), - MPR_SHALLOW_COPY); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_NUMBER: - /* - * Set the result to the parsed number - */ - mprCopyVar(&ep->result, &ep->tokenNumber, 0); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_FUNCTION_NAME: - state = parseFunction(ep, state, flags, id); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - } - done++; - break; - - case EJS_TOK_IF: - state = parseIf(ep, state, flags, &done); - if (state == EJS_STATE_RET) { - goto doneParse; - } - break; - - case EJS_TOK_FOR: - if (state != EJS_STATE_STMT) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - goto error; - } - /* - * Need to peek 2-3 tokens ahead and see if this is a - * for ([var] x in set) - * or - * for (init ; whileCond; incr) - */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - if (initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { - /* Simply eat var tokens */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - } - initToken = mprStrdup(ep->token); - - tid = ejsLexGetToken(ep, EJS_STATE_EXPR); - - ejsLexPutbackToken(ep, tid, ep->token); - ejsLexPutbackToken(ep, initId, initToken); - mprFree(initToken); - - if (tid == EJS_TOK_IN) { - if ((state = parseForIn(ep, state, flags)) < 0) { - goto error; - } - } else { - if ((state = parseFor(ep, state, flags)) < 0) { - goto error; - } - } - done++; - break; - - case EJS_TOK_VAR: - if (ejsParse(ep, EJS_STATE_DEC_LIST, flags) - != EJS_STATE_DEC_LIST_DONE) { - goto error; - } - done++; - break; - - case EJS_TOK_COMMA: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LPAREN: - if (state == EJS_STATE_EXPR) { - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - } - done++; - break; - - case EJS_TOK_RPAREN: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LBRACE: - /* - * This handles any code in braces except "if () {} else {}" - */ - if (state != EJS_STATE_STMT) { - goto error; - } - - /* - * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE - * is seen. - */ - do { - state = ejsParse(ep, EJS_STATE_STMT, flags); - } while (state == EJS_STATE_STMT_DONE); - - if (state != EJS_STATE_RET) { - if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { - goto error; - } - state = EJS_STATE_STMT_DONE; - } - done++; - break; - - case EJS_TOK_RBRACE: - if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_STMT_BLOCK_DONE; - done++; - break; - } - goto error; - - case EJS_TOK_RETURN: - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (flags & EJS_FLAGS_EXE) { - while (ejsLexGetToken(ep, state) != EJS_TOK_EOF) { - ; - } - state = EJS_STATE_RET; - done++; - } - break; - } - } - - if (expectSemi) { - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_SEMI && tid != EJS_TOK_NEWLINE && - tid != EJS_TOK_EOF) { - goto error; - } - - /* - * Skip newline after semi-colon - */ - removeNewlines(ep, state); - } - -/* - * Free resources and return the correct status - */ -doneParse: - mprFree(id); - mprFree(fullName); - - /* - * Advance the state - */ - switch (state) { - case EJS_STATE_STMT: - return EJS_STATE_STMT_DONE; - - case EJS_STATE_DEC: - return EJS_STATE_DEC_DONE; - - case EJS_STATE_EXPR: - return EJS_STATE_EXPR_DONE; - - case EJS_STATE_STMT_DONE: - case EJS_STATE_STMT_BLOCK_DONE: - case EJS_STATE_EOF: - case EJS_STATE_RET: - return state; - - default: - return EJS_STATE_ERR; - } - -/* - * Common error exit - */ -error: - state = EJS_STATE_ERR; - goto doneParse; -} - -/******************************************************************************/ -/* - * Parse function arguments - */ - -static int parseArgs(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - /* - * Peek and see if there are no args - */ - tid = ejsLexGetToken(ep, state); - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RPAREN) { - break; - } - - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state == EJS_STATE_EOF || state == EJS_STATE_ERR) { - return state; - } - if (state == EJS_STATE_RELEXP_DONE) { - if (flags & EJS_FLAGS_EXE) { - mprAssert(ep->proc->args); - mprAddToArray(ep->proc->args, - mprDupVar(&ep->result, MPR_SHALLOW_COPY)); - } - } - /* - * Peek at the next token, continue if more args (ie. comma seen) - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_COMMA) { - ejsLexPutbackToken(ep, tid, ep->token); - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { - return EJS_STATE_ERR; - } - return EJS_STATE_ARG_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse an assignment statement - */ - -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName) -{ - MprVar *vp, *saveProperty, *saveObj; - - if (id == 0) { - return -1; - } - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - if (ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT) - != EJS_STATE_RELEXP_DONE) { - return -1; - } - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty) { - /* - * Update the variable. Update the property name if not - * yet defined. - */ - if (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0') { - mprSetVarName(ep->currentProperty, id); - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0){ - ejsError(ep, "Can't write to variable\n"); - return -1; - } - - } else { - /* - * Create the variable - */ - if (ep->currentObj) { - if (ep->currentObj->type != MPR_TYPE_OBJECT) { - if (strcmp(ep->currentObj->name, "session") == 0) { - ejsError(ep, "Variable \"%s\" is not an array or object." - "If using ESP, you need useSession(); in your page.", - ep->currentObj->name); - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - ep->currentObj->name); - } - return -1; - } - vp = mprCreateProperty(ep->currentObj, id, &ep->result); - - } else { - /* - * Standard says: "var x" means declare locally. - * "x = 2" means declare globally if x is undefined. - */ - if (state == EJS_STATE_DEC) { - vp = mprCreateProperty(ep->local, id, &ep->result); - } else { - vp = mprCreateProperty(ep->global, id, &ep->result); - } - } -#if BLD_DEBUG - mprSetVarFullName(vp, fullName); -#endif - } - return state; -} - -/******************************************************************************/ -/* - * Parse conditional expression (relational ops separated by ||, &&) - */ - -static int parseCond(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int tid, operator; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - operator = 0; - - do { - /* - * Recurse to handle one side of a conditional. Accumulate the - * left hand side and the final result in ep->result. - */ - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - - if (operator > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (evalCond(ep, &lhs, operator, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LOGICAL) { - operator = (int) *ep->token; - - } else if (tid == EJS_TOK_RPAREN || tid == EJS_TOK_SEMI) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_COND_DONE; - break; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - tid = (state == EJS_STATE_RELEXP_DONE); - - } while (state == EJS_STATE_RELEXP_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - return state; -} - -/******************************************************************************/ -/* - * Parse variable declaration list. Declarations can be of the following forms: - * var x; - * var x, y, z; - * var x = 1 + 2 / 3, y = 2 + 4; - * - * We set the variable to NULL if there is no associated assignment. - */ - -static int parseDeclaration(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - return EJS_STATE_ERR; - } - ejsLexPutbackToken(ep, tid, ep->token); - - /* - * Parse the entire assignment or simple identifier declaration - */ - if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { - return EJS_STATE_ERR; - } - - /* - * Peek at the next token, continue if comma seen - */ - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_SEMI) { - return EJS_STATE_DEC_LIST_DONE; - } else if (tid != EJS_TOK_COMMA) { - return EJS_STATE_ERR; - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_SEMI) { - return EJS_STATE_ERR; - } - return EJS_STATE_DEC_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - -static int parseExpr(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int rel, tid; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - rel = 0; - tid = 0; - - do { - /* - * This loop will handle an entire expression list. We call parse - * to evalutate each term which returns the result in ep->result. - */ - if (tid == EJS_TOK_LOGICAL) { - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - } else { - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { - lhs = mprCreateIntegerVar(0); - rel = (int) *ep->token; - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - - state = ejsParse(ep, EJS_STATE_EXPR, flags); - if (state != EJS_STATE_EXPR_DONE) { - state = EJS_STATE_ERR; - break; - } - } - - if (rel > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (tid == EJS_TOK_LOGICAL) { - if (evalCond(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } else { - if (evalExpr(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - if ((tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || - tid == EJS_TOK_INC_DEC || tid == EJS_TOK_LOGICAL) { - rel = (int) *ep->token; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_RELEXP_DONE; - } - - } while (state == EJS_STATE_EXPR_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - - return state; -} - -/******************************************************************************/ -/* - * Parse the "for ... in" statement. Format for the statement is: - * - * for (var in expr) { - * body; - * } - */ - -static int parseForIn(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar *iteratorVar, *setVar, *vp, v; - int forFlags, tid; - - mprAssert(ep); - - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FOREACH | EJS_FLAGS_EXE) - != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0) { - return -1; - } - iteratorVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { - return -1; - } - - /* - * Get the set - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0 && flags & EJS_FLAGS_EXE) { - return -1; - } - setVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * Parse the body and remember the end of the body script - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - ejsInitInputState(&endScript); - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. - */ - if (flags & EJS_FLAGS_EXE) { - if (setVar->type == MPR_TYPE_OBJECT) { - vp = mprGetFirstProperty(setVar, MPR_ENUM_DATA); - while (vp) { - if (strcmp(vp->name, "length") != 0) { - v = mprCreateStringVar(vp->name, 0); - if (mprWriteProperty(iteratorVar, &v) < 0) { - ejsError(ep, "Can't write to variable\n"); - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - return -1; - } - - ejsLexRestoreInputState(ep, &bodyScript); - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - vp = mprGetNextProperty(setVar, vp, MPR_ENUM_DATA); - } - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - setVar->name); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - ejsLexRestoreInputState(ep, &endScript); - - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - - return state; -} - -/******************************************************************************/ -/* - * Parse the for statement. Format for the expression is: - * - * for (initial; condition; incr) { - * body; - * } - */ - -static int parseFor(Ejs *ep, int state, int flags) -{ - EjsInput condScript, endScript, bodyScript, incrScript; - int forFlags, cond; - - ejsInitInputState(&endScript); - ejsInitInputState(&bodyScript); - ejsInitInputState(&incrScript); - ejsInitInputState(&condScript); - - mprAssert(ep); - - /* - * Evaluate the for loop initialization statement - */ - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - return -1; - } - - /* - * The first time through, we save the current input context just prior - * to each step: prior to the conditional, the loop increment and - * the loop body. - */ - ejsLexSaveInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - cond = (ep->result.boolean != 0); - - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - goto error; - } - - /* - * Don't execute the loop increment statement or the body - * first time. - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, forFlags) != EJS_STATE_EXPR_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - - /* - * Parse the body and remember the end of the body script - */ - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - goto error; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. Note loop has been rotated - */ - while (cond && (flags & EJS_FLAGS_EXE)) { - /* - * Evaluate the body - */ - ejsLexRestoreInputState(ep, &bodyScript); - - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - goto error; - } - /* - * Evaluate the increment script - */ - ejsLexRestoreInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE){ - goto error; - } - /* - * Evaluate the condition - */ - ejsLexRestoreInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - mprAssert(ep->result.type == MPR_TYPE_BOOL); - cond = (ep->result.boolean != 0); - } - - ejsLexRestoreInputState(ep, &endScript); - -done: - ejsLexFreeInputState(ep, &condScript); - ejsLexFreeInputState(ep, &incrScript); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return state; - -error: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse a function declaration - */ - -static int parseFunctionDec(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar v, *currentObj, *vp; - char *procName; - int len, tid, bodyFlags; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - /* - * function (arg, arg, arg) { body }; - * function name(arg, arg, arg) { body }; - */ - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_ID) { - procName = mprStrdup(ep->token); - tid = ejsLexGetToken(ep, state); - } else { - procName = 0; - } - if (tid != EJS_TOK_LPAREN) { - mprFree(procName); - return EJS_STATE_ERR; - } - - /* - * Hand craft the function value structure. - */ - v = mprCreateFunctionVar(0, 0, 0); - tid = ejsLexGetToken(ep, state); - while (tid == EJS_TOK_ID) { - mprAddToArray(v.function.args, mprStrdup(ep->token)); - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { - break; - } - tid = ejsLexGetToken(ep, state); - } - if (tid != EJS_TOK_RPAREN) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* Allow new lines before opening brace */ - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - if (tid != EJS_TOK_LBRACE) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* - * Register the function name early to allow for recursive - * function calls (see note in ECMA standard, page 71) - */ - if (!(flags & EJS_FLAGS_ASSIGNMENT)) { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - /* - * Parse the function body. Turn execute off. - */ - bodyFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - - do { - state = ejsParse(ep, EJS_STATE_STMT, bodyFlags); - } while (state == EJS_STATE_STMT_DONE); - - tid = ejsLexGetToken(ep, state); - if (state != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { - mprFree(procName); - mprDestroyVar(&v); - ejsLexFreeInputState(ep, &bodyScript); - return EJS_STATE_ERR; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Save the function body between the starting and ending parse positions. - * Overwrite the trailing '}' with a null. - */ - len = endScript.scriptServp - bodyScript.scriptServp; - v.function.body = mprMalloc(len + 1); - memcpy(v.function.body, bodyScript.scriptServp, len); - - if (len <= 0) { - v.function.body[0] = '\0'; - } else { - v.function.body[len - 1] = '\0'; - } - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - - /* - * If we are in an assignment, don't register the function name, rather - * return the function structure in the parser result. - */ - if (flags & EJS_FLAGS_ASSIGNMENT) { - mprCopyVar(&ep->result, &v, MPR_SHALLOW_COPY); - } else { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - mprFree(procName); - mprDestroyVar(&v); - - return EJS_STATE_STMT; -} - -/******************************************************************************/ -/* - * Parse a function name and invoke the function - */ - -static int parseFunction(Ejs *ep, int state, int flags, char *id) -{ - EjsProc proc, *saveProc; - MprVar *saveObj; - - /* - * Must save any current ep->proc value for the current stack frame - * to allow for recursive function calls. - */ - saveProc = (ep->proc) ? ep->proc: 0; - - memset(&proc, 0, sizeof(EjsProc)); - proc.procName = mprStrdup(id); - proc.fn = ep->currentProperty; - proc.args = mprCreateArray(); - ep->proc = &proc; - - mprDestroyVar(&ep->result); - - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_ARG_LIST, flags) != EJS_STATE_ARG_LIST_DONE) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - ep->currentObj = saveObj; - - /* - * Evaluate the function if required - */ - if (flags & EJS_FLAGS_EXE) { - if (evalFunction(ep, ep->currentObj, flags) < 0) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - } - - freeProc(&proc); - ep->proc = saveProc; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an identifier. This is a segment of a fully qualified variable. - * May come here for an initial identifier or for property names - * after a "." or "[...]". - */ - -static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, - int *fullNameLen, int *done) -{ - int tid; - - mprFree(*id); - *id = mprStrdup(ep->token); -#if BLD_DEBUG - *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, - 0, *id, 0); -#endif - if (ep->currentObj == 0) { - ep->currentObj = ejsFindObj(ep, state, *id, flags); - } - - /* - * Find the referenced variable and store it in currentProperty. - */ - ep->currentProperty = ejsFindProperty(ep, state, ep->currentObj, - *id, flags); - updateResult(ep, state, flags, ep->currentProperty); - -#if BLD_DEBUG - if (ep->currentProperty && (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0')) { - mprSetVarName(ep->currentProperty, *id); - } -#endif - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LPAREN) { - ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); - return state; - } - - if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || - tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { - ejsLexPutbackToken(ep, tid, ep->token); - return state; - } - - /* - * Only come here for variable access and declarations. - * Assignment handled elsewhere. - */ - if (flags & EJS_FLAGS_EXE) { - if (state == EJS_STATE_DEC) { - /* - * Declare a variable. Standard allows: var x ; var x ; - */ -#if DISABLED - if (ep->currentProperty != 0) { - ejsError(ep, "Variable already defined \"%s\"\n", *id); - return -1; - } -#endif - /* - * Create or overwrite if it already exists - */ - mprSetPropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - ep->currentProperty = 0; - mprDestroyVar(&ep->result); - - } else if (flags & EJS_FLAGS_FOREACH) { - if (ep->currentProperty == 0) { - ep->currentProperty = - mprCreatePropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - } - - } else { - if (ep->currentProperty == 0) { - if (ep->currentObj == ep->global || - ep->currentObj == ep->local) { - ejsError(ep, "Undefined variable \"%s\"\n", *id); - return -1; - } - ep->currentProperty = mprCreatePropertyValue(ep->currentObj, - *id, mprCreateUndefinedVar()); - } - } - } - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || - tid == EJS_TOK_IN) { - *done = 1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an "if" statement - */ - -static int parseIf(Ejs *ep, int state, int flags, int *done) -{ - bool ifResult; - int thenFlags, elseFlags, tid; - - if (state != EJS_STATE_STMT) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - return -1; - } - - /* - * Evaluate the entire condition list "(condition)" - */ - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * This is the "then" case. We need to always parse both cases and - * execute only the relevant case. - */ - ifResult = mprVarToBool(&ep->result); - if (ifResult) { - thenFlags = flags; - elseFlags = flags & ~EJS_FLAGS_EXE; - } else { - thenFlags = flags & ~EJS_FLAGS_EXE; - elseFlags = flags; - } - - /* - * Process the "then" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, thenFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - - /* - * Check to see if there is an "else" case - */ - removeNewlines(ep, state); - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ELSE) { - ejsLexPutbackToken(ep, tid, ep->token); - *done = 1; - return state; - } - - /* - * Process the "else" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, elseFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - *done = 1; - return state; -} - -/******************************************************************************/ -/* - * Parse an "++" or "--" statement - */ - -static int parseInc(Ejs *ep, int state, int flags) -{ - MprVar one; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined variable \"%s\"\n", ep->token); - return -1; - } - one = mprCreateIntegerVar(1); - if (evalExpr(ep, ep->currentProperty, (int) *ep->token, - &one) < 0) { - return -1; - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0) { - ejsError(ep, "Can't write to variable\n"); - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result - * in ep->result. Returns -1 on errors, zero if successful. - */ - -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - bool l, r, lval; - - mprAssert(rel > 0); - - l = mprVarToBool(lhs); - r = mprVarToBool(rhs); - - switch (rel) { - case EJS_COND_AND: - lval = l && r; - break; - case EJS_COND_OR: - lval = l || r; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate an operation. Returns with the result in ep->result. Returns -1 - * on errors, otherwise zero is returned. - */ - -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - char *str; - MprNum lval, num; - int rc; - - mprAssert(rel > 0); - str = 0; - lval = 0; - - /* - * Type conversion. This is tricky and must be according to the standard. - * Only numbers (including floats) and strings can be compared. All other - * types are first converted to numbers by preference and if that fails, - * to strings. - * - * First convert objects to comparable types. The "===" operator will - * test the sameness of object references. Here, we coerce to comparable - * types first. - */ - if (lhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, lhs, "toValue", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, lhs, "toString", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - if (rhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, rhs, "toValue", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, rhs, "toString", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - /* - * From here on, lhs and rhs may contain allocated data (strings), so - * we must always destroy before overwriting. - */ - - /* - * Only allow a few bool operations. Otherwise convert to number. - */ - if (lhs->type == MPR_TYPE_BOOL && rhs->type == MPR_TYPE_BOOL && - (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && - rel != EJS_EXPR_BOOL_COMP)) { - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - } - - /* - * Types do not match, so try to coerce the right operand to match the left - * But first, try to convert a left operand that is a numeric stored as a - * string, into a numeric. - */ - if (lhs->type != rhs->type) { - if (lhs->type == MPR_TYPE_STRING) { - if (isdigit((int) lhs->string[0])) { - num = mprVarToNumber(lhs); - lhs->allocatedVar = 0; - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - /* Examine further below */ - - } else { - /* - * Convert the RHS to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, rhs); - rhs->allocatedVar = 0; - mprDestroyVar(rhs); - *rhs = mprCreateStringVar(str, 1); - mprFree(str); - } - -#if BLD_FEATURE_FLOATING_POINT - } else if (lhs->type == MPR_TYPE_FLOAT) { - /* - * Convert rhs to floating - */ - double f = mprVarToFloat(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateFloatVar(f); - -#endif -#if BLD_FEATURE_INT64 - } else if (lhs->type == MPR_TYPE_INT64) { - /* - * Convert the rhs to 64 bit - */ - int64 n = mprVarToInteger64(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateInteger64Var(n); -#endif - } else if (lhs->type == MPR_TYPE_BOOL || lhs->type == MPR_TYPE_INT) { - - if (rhs->type == MPR_TYPE_STRING) { - /* - * Convert to lhs to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, lhs); - mprDestroyVar(lhs); - *lhs = mprCreateStringVar(str, 1); - mprFree(str); - -#if BLD_FEATURE_FLOATING_POINT - } else if (rhs->type == MPR_TYPE_FLOAT) { - /* - * Convert lhs to floating - */ - double f = mprVarToFloat(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateFloatVar(f); -#endif - - } else { - /* - * Convert both operands to numbers - */ - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - - num = mprVarToNumber(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateNumberVar(num); - } - } - } - - /* - * We have failed to coerce the types to be the same. Special case here - * for undefined and null. We need to allow comparisions against these - * special values. - */ - if (lhs->type == MPR_TYPE_UNDEFINED || lhs->type == MPR_TYPE_NULL) { - switch (rel) { - case EJS_EXPR_EQ: - lval = lhs->type == rhs->type; - break; - case EJS_EXPR_NOTEQ: - lval = lhs->type != rhs->type; - break; - default: - lval = 0; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar((bool) lval), 0); - return 0; - } - - /* - * Types are the same here - */ - switch (lhs->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - /* Should be handled above */ - mprAssert(0); - return 0; - - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); - return 0; - - case MPR_TYPE_PTR: - mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0); - return 0; - - case MPR_TYPE_BOOL: - rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); - break; -#endif - - case MPR_TYPE_INT: - rc = evalNumericExpr(ep, (MprNum) lhs->integer, rel, - (MprNum) rhs->integer); - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - rc = evalNumericExpr(ep, (MprNum) lhs->integer64, rel, - (MprNum) rhs->integer64); - break; -#endif - - case MPR_TYPE_STRING: - rc = evalStringExpr(ep, lhs, rel, rhs); - } - return rc; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Expressions with floating operands - */ - -static int evalFloatExpr(Ejs *ep, double l, int rel, double r) -{ - double lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - lval = l / r; - break; - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateFloatVar(lval), 0); - } - return 0; -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ -/* - * Expressions with boolean operands - */ - -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) -{ - bool lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Expressions with numeric operands - */ - -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) -{ - MprNum lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - if (r != 0) { - lval = l / r; - } else { - ejsError(ep, "Divide by zero"); - return -1; - } - break; - case EJS_EXPR_MOD: - if (r != 0) { - lval = l % r; - } else { - ejsError(ep, "Modulo zero"); - return -1; - } - break; - case EJS_EXPR_LSHIFT: - lval = l << r; - break; - case EJS_EXPR_RSHIFT: - lval = l >> r; - break; - - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); - } - return 0; -} - -/******************************************************************************/ -/* - * Expressions with string operands - */ - -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - int lval; - - mprAssert(ep); - mprAssert(lhs); - mprAssert(rhs); - - switch (rel) { - case EJS_EXPR_LESS: - lval = strcmp(lhs->string, rhs->string) < 0; - break; - case EJS_EXPR_LESSEQ: - lval = strcmp(lhs->string, rhs->string) <= 0; - break; - case EJS_EXPR_GREATER: - lval = strcmp(lhs->string, rhs->string) > 0; - break; - case EJS_EXPR_GREATEREQ: - lval = strcmp(lhs->string, rhs->string) >= 0; - break; - case EJS_EXPR_EQ: - lval = strcmp(lhs->string, rhs->string) == 0; - break; - case EJS_EXPR_NOTEQ: - lval = strcmp(lhs->string, rhs->string) != 0; - break; - case EJS_EXPR_PLUS: - /* - * This differs from all the above operations. We append rhs to lhs. - */ - mprDestroyVar(&ep->result); - appendValue(&ep->result, lhs); - appendValue(&ep->result, rhs); - return 0; - - case EJS_EXPR_INC: - case EJS_EXPR_DEC: - case EJS_EXPR_MINUS: - case EJS_EXPR_DIV: - case EJS_EXPR_MOD: - case EJS_EXPR_LSHIFT: - case EJS_EXPR_RSHIFT: - default: - ejsError(ep, "Bad operator"); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a function. obj is set to the current object if a function is being - * run. - */ - -static int evalFunction(Ejs *ep, MprVar *obj, int flags) -{ - EjsProc *proc; - MprVar arguments, callee, thisObject, *prototype, **argValues; - MprArray *formalArgs, *actualArgs; - char buf[16], **argNames, **argBuf; - int i, rc, fid; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - rc = -1; - proc = ep->proc; - prototype = proc->fn; - actualArgs = proc->args; - argValues = (MprVar**) actualArgs->handles; - - if (prototype == NULL) { - ejsError(ep, "Function name not defined '%s'\n", proc->procName); - return -1; - } - - /* - * Create a new variable stack frame. ie. new local variables. - */ - fid = ejsOpenBlock(ep->eid); - - if (flags & EJS_FLAGS_NEW) { - /* - * Create a new bare object and pass it into the constructor as the - * "this" local variable. - */ - thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); - mprCreatePropertyValue(ep->local, "this", thisObject); - - } else if (obj) { - mprCreateProperty(ep->local, "this", obj); - } - - switch (prototype->type) { - default: - mprAssert(0); - break; - - case MPR_TYPE_STRING_CFUNCTION: - if (actualArgs->used > 0) { - argBuf = mprMalloc(actualArgs->used * sizeof(char*)); - for (i = 0; i < actualArgs->used; i++) { - mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); - } - } else { - argBuf = 0; - } - - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) - (ep->eid, ep->altHandle, actualArgs->used, argBuf); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunctionWithStrings.fn)(ep->eid, - actualArgs->used, argBuf); - } else { - rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, - actualArgs->used, argBuf); - } - - if (actualArgs->used > 0) { - for (i = 0; i < actualArgs->used; i++) { - mprFree(argBuf[i]); - } - mprFree(argBuf); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_CFUNCTION: - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunction.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltCFunction) prototype->cFunction.fn) - (ep->eid, ep->altHandle, actualArgs->used, argValues); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, - argValues); - } else { - rc = (prototype->cFunction.fn)(ep->primaryHandle, - actualArgs->used, argValues); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_FUNCTION: - - formalArgs = prototype->function.args; - argNames = (char**) formalArgs->handles; - -#if FUTURE - if (formalArgs->used != actualArgs->used) { - ejsError(ep, "Bad number of args. Should be %d", formalArgs->used); - return -1; - } -#endif - - /* - * Create the arguments and callee variables - */ - arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); - callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); - - /* - * Overwrite the length property - */ - mprCreatePropertyValue(&arguments, "length", - mprCreateIntegerVar(actualArgs->used)); - mprCreatePropertyValue(&callee, "length", - mprCreateIntegerVar(formalArgs->used)); - - /* - * Define all the agruments to be set to the actual parameters - */ - for (i = 0; i < formalArgs->used; i++) { - mprCreateProperty(ep->local, argNames[i], argValues[i]); - } - for (i = 0; i < actualArgs->used; i++) { - mprItoa(i, buf, sizeof(buf)); - mprCreateProperty(&arguments, buf, argValues[i]); - } - - mprCreateProperty(&arguments, "callee", &callee); - mprCreateProperty(ep->local, "arguments", &arguments); - - /* - * Can destroy our variables here as they are now referenced via - * "local" - */ - mprDestroyVar(&callee); - mprDestroyVar(&arguments); - - /* - * Actually run the function - */ - rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); - break; - } - - ejsCloseBlock(ep->eid, fid); - - /* - * New statements return the newly created object as the result of the - * command - */ - if (flags & EJS_FLAGS_NEW) { - mprDestroyVar(&ep->result); - /* - * Don't copy, we want to assign the actual object into result. - * (mprCopyVar would inc the refCount to 2). - */ - ep->result = thisObject; - } - return rc; -} - -/******************************************************************************/ -/* - * Run a function - */ - -int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args) -{ - EjsProc proc, *saveProc; - Ejs *ep; - int rc; - - mprAssert(obj); - mprAssert(functionName && *functionName); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return MPR_ERR_NOT_FOUND; - } - saveProc = ep->proc; - ep->proc = &proc; - - memset(&proc, 0, sizeof(EjsProc)); - mprDestroyVar(&ep->result); - - proc.fn = mprGetProperty(obj, functionName, 0); - if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { - ep->proc = saveProc; - return MPR_ERR_NOT_FOUND; - } - proc.procName = mprStrdup(functionName); - if (args == 0) { - proc.args = mprCreateArray(); - rc = evalFunction(ep, obj, 0); - } else { - proc.args = args; - rc = evalFunction(ep, obj, 0); - proc.args = 0; - } - - freeProc(&proc); - ep->proc = saveProc; - - return rc; -} - -/******************************************************************************/ -/* - * Find which object contains the property given the current context. - * Only used for top level properties. - */ - -MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) -{ - MprVar *vp; - MprVar *obj; - - mprAssert(ep); - mprAssert(property && *property); - - if (flags & EJS_FLAGS_GLOBAL) { - obj = ep->global; - - } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { - obj = ep->local; - - } else { - /* First look local, then look global */ - vp = mprGetProperty(ep->local, property, 0); - if (vp) { - obj = ep->local; - } else if (mprGetProperty(ep->local, property, 0)) { - obj = ep->local; - } else { - obj = ep->global; - } - } - return obj; -} - -/******************************************************************************/ -/* - * Find an object property given a object and a property name. We - * intelligently look in the local and global namespaces depending on - * our state. If not found in local or global, try base classes for function - * names only. Returns the property or NULL. - */ - -MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, - int flags) -{ - MprVar *vp; - - mprAssert(ep); - if (flags & EJS_FLAGS_EXE) { - mprAssert(property && *property); - } - - if (obj != 0) { -#if FUTURE && MB - op = obj; - do { - vp = mprGetProperty(op, property, 0); - if (vp != 0) { - if (op != obj && mprVarIsFunction(vp->type)) { - } - break; - } - op = op->baseObj; - } while (op); -#endif - vp = mprGetProperty(obj, property, 0); - - } else { - if (state == EJS_STATE_DEC) { - vp = mprGetProperty(ep->local, property, 0); - - } else { - /* Look local first, then global */ - vp = mprGetProperty(ep->local, property, 0); - if (vp == NULL) { - vp = mprGetProperty(ep->global, property, 0); - } - } - } - return vp; -} - -/******************************************************************************/ -/* - * Update result - */ - -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp) -{ - if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { - mprDestroyVar(&ep->result); - if (vp) { - mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); - } - } -} - -/******************************************************************************/ -/* - * Append to the pointer value - */ - -static void appendValue(MprVar *dest, MprVar *src) -{ - char *value, *oldBuf, *buf; - int len, oldLen; - - mprAssert(dest); - - mprVarToString(&value, MPR_MAX_STRING, 0, src); - - if (mprVarIsValid(dest)) { - len = strlen(value); - oldBuf = dest->string; - oldLen = strlen(oldBuf); - buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); - dest->string = buf; - strcpy(&buf[oldLen], value); - - } else { - *dest = mprCreateStringVar(value, 1); - } - mprFree(value); -} - -/******************************************************************************/ -/* - * Exit with status - */ - -void ejsSetExitStatus(int eid, int status) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - ep->exitStatus = status; - ep->flags |= EJS_FLAGS_EXIT; -} - -/******************************************************************************/ -/* - * Free an argument list - */ - -static void freeProc(EjsProc *proc) -{ - MprVar **argValues; - int i; - - if (proc->args) { - argValues = (MprVar**) proc->args->handles; - - for (i = 0; i < proc->args->max; i++) { - if (argValues[i]) { - mprDestroyVar(argValues[i]); - mprFree(argValues[i]); - mprRemoveFromArray(proc->args, i); - } - } - - mprDestroyArray(proc->args); - } - - if (proc->procName) { - mprFree(proc->procName); - proc->procName = NULL; - } -} - -/******************************************************************************/ -/* - * This function removes any new lines. Used for else cases, etc. - */ - -static void removeNewlines(Ejs *ep, int state) -{ - int tid; - - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - ejsLexPutbackToken(ep, tid, ep->token); -} - -/******************************************************************************/ - -#else -void ejsParserDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/ejsProcs.c b/source4/lib/ejs/ejsProcs.c deleted file mode 100644 index c01f411161..0000000000 --- a/source4/lib/ejs/ejsProcs.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * @file ejsProc.c - * @brief EJS support functions - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ -/* - * Object constructors - */ -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv); -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv); -static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv); -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv); -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Core functions - */ -static int toStringProc(EjsHandle eid, int argc, MprVar **argv); -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Triggers - */ -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - bool copyRef); - -/******************************************************************************/ -/* - * Routine to create the base common to all object types - */ - -MprVar ejsCreateObj(const char *name, int hashSize) -{ - MprVar o; - - o = mprCreateObjVar(name, hashSize); - if (o.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return o; - } - - mprCreatePropertyValue(&o, "toString", - mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(&o, "valueOf", - mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE)); - return o; -} - -/******************************************************************************/ -/* - * Routine to destroy a variable - */ - -bool ejsDestroyVar(MprVar *obj) -{ - return mprDestroyVar(obj); -} - -/******************************************************************************/ -/* - * Routine to create the base array type - */ - -MprVar ejsCreateArray(const char *name, int size) -{ - MprVar obj, *lp, undef; - char idx[16]; - int i; - - /* Sanity limit for size of hash table */ - - obj = ejsCreateObj(name, max(size, 503)); - if (obj.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return obj; - } - - undef = mprCreateUndefinedVar(); - for (i = 0; i < size; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(&obj, idx, &undef); - } - - lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return obj; -} - -/******************************************************************************/ -/******************************** Constructors ********************************/ -/******************************************************************************/ -/* - * Object constructor. Nothing really done here. For future expansion. - */ - -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv) -{ -#if XX_UNUSED_XX - MprVar *obj; - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); -#endif - return 0; -} - -/******************************************************************************/ -/* - * Array constructor - */ - -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj, *lp, undef; - Ejs *ep; - char idx[16]; - int i, max; - - objectConsProc(eid, argc, argv); - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - - if (argc == 1 && mprVarIsNumber(argv[0]->type)) { - /* - * x = new Array(size); - */ - undef = mprCreateUndefinedVar(); - max = (int) mprVarToInteger(argv[0]); - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, &undef); - } - } else { - /* - * x = new Array(element0, element1, ..., elementN): - */ - max = argc; - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, argv[i]); - } - } - - lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return 0; -} - -/******************************************************************************/ -/* - * Boolean constructor - */ - -static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -#if FUTURE -/* - * Date constructor - */ - -static int dateConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -#endif -/******************************************************************************/ -/* - * Number constructor - */ - -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/* - * String constructor - */ - -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/********************************** Functions *********************************/ -/******************************************************************************/ - -static int toStringProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - char *buf; - int radix; - - if (argc == 0) { - radix = 10; - - } else if (argc == 1) { - radix = (int) mprVarToInteger(argv[0]); - - } else { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - mprVarToString(&buf, MPR_MAX_STRING, 0, obj); - mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY); - mprFree(buf); - - return 0; -} - -/******************************************************************************/ - -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - - if (argc != 0) { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - switch (obj->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_PTR: - mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); - break; - - case MPR_TYPE_STRING: - mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0); - break; - - case MPR_TYPE_BOOL: - case MPR_TYPE_INT: -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: -#endif -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: -#endif - mprCopyVar(&ep->result, obj, 0); - break; - } - return 0; -} - -/******************************************************************************/ -/* - * Var access trigger on the Array.length property. Return the count of - * enumerable properties (don't count functions). - */ - -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - bool copyRef) -{ - switch (op) { - case MPR_VAR_READ: - /* - * Subtract one for the length property - * FUTURE -- need an API to access parentProperties - * FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE. - * API needs finer control. - */ - *newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1); - return MPR_TRIGGER_USE_NEW_VALUE; - - case MPR_VAR_WRITE: - return MPR_TRIGGER_ABORT; - - case MPR_VAR_CREATE_PROPERTY: - case MPR_VAR_DELETE_PROPERTY: - case MPR_VAR_DELETE: - default: - break; - } - return MPR_TRIGGER_PROCEED; -} - -/******************************************************************************/ -/**************************** Extension Functions *****************************/ -/******************************************************************************/ -/* - * Assert - */ - -static int assertProc(EjsHandle eid, int argc, MprVar **argv) -{ - bool b; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: assert(condition)\n"); - return -1; - } - b = mprVarToBool(argv[0]); - if (b == 0) { - ejsSetErrorMsg(eid, "Assertion failure\n"); - return -1; - } - ejsSetReturnValue(eid, mprCreateBoolVar(b)); - return 0; -} - -/******************************************************************************/ -/* - * Exit - */ - -static int exitProc(EjsHandle eid, int argc, MprVar **argv) -{ - int status; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: exit(status)\n"); - return -1; - } - status = (int) mprVarToInteger(argv[0]); - ejsSetExitStatus(eid, status); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ - -static void printVar(MprVar *vp, int recurseCount, int indent) -{ - MprVar *np; - char *buf; - int i; - - if (recurseCount > 5) { - write(1, "Skipping - recursion too deep\n", 29); - return; - } - - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - - if (vp->type == MPR_TYPE_OBJECT) { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": {\n", 4); - np = mprGetFirstProperty(vp, MPR_ENUM_DATA); - while (np) { - if (strcmp(np->name, "local") == 0 || - strcmp(np->name, "global") == 0 || - strcmp(np->name, "this") == 0) { - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - continue; - } - printVar(np, recurseCount + 1, indent + 1); - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - if (np) { - write(1, ",\n", 2); - } - } - write(1, "\n", 1); - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - write(1, "}", 1); - - } else { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": ", 2); - - /* FUTURE -- other types ? */ - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - write(1, buf, strlen(buf)); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - mprFree(buf); - } -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printVarsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - char *buf; - int i; - - for (i = 0; i < argc; i++) { - vp = argv[i]; - switch (vp->type) { - case MPR_TYPE_OBJECT: - printVar(vp, 0, 0); - break; - default: - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - write(1, buf, strlen(buf)); - mprFree(buf); - break; - } - } - write(1, "\n", 1); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printProc(EjsHandle eid, int argc, MprVar **argv) -{ - char *buf; - int i; - - for (i = 0; i < argc; i++) { - mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]); - write(1, buf, strlen(buf)); - mprFree(buf); - } - return 0; -} - -/******************************************************************************/ -/* - * println - */ - -static int printlnProc(EjsHandle eid, int argc, MprVar **argv) -{ - printProc(eid, argc, argv); - write(1, "\n", 1); - return 0; -} - -/******************************************************************************/ -/* - * Trace - */ - -static int traceProc(EjsHandle eid, int argc, char **argv) -{ - if (argc == 1) { - mprLog(0, "%s", argv[0]); - - } else if (argc == 2) { - mprLog(atoi(argv[0]), "%s", argv[1]); - - } else { - ejsSetErrorMsg(eid, "Usage: trace([level], message)"); - return -1; - } - ejsSetReturnString(eid, ""); - return 0; -} - -/******************************************************************************/ -/* - * Return the object reference count - */ - -static int refCountProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - int count; - - vp = argv[0]; - if (vp->type == MPR_TYPE_OBJECT) { - count = mprGetVarRefCount(vp); - ejsSetReturnValue(eid, mprCreateIntegerVar(count)); - } else { - ejsSetReturnValue(eid, mprCreateIntegerVar(0)); - } - - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a sub-script. It is evaluated in the same variable scope as - * the calling script / function. - */ - -static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *arg; - char *emsg; - int i; - - ejsSetReturnValue(eid, mprCreateUndefinedVar()); - - for (i = 0; i < argc; i++) { - arg = argv[i]; - if (arg->type != MPR_TYPE_STRING) { - continue; - } - if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) { - ejsSetErrorMsg(eid, "%s", emsg); - mprFree(emsg); - return -1; - } - } - /* - * Return with the value of the last expression - */ - return 0; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* - * Define the standard properties and functions inherited by all script engines. - */ - -int ejsDefineStandardProperties(MprVar *obj) -{ -#if BLD_FEATURE_FLOATING_POINT - double d = 0.0; - - /* FUTURE - this generates warnings on some systems. This is okay. */ - - mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d)); - d = MAX_FLOAT; - mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d)); -#endif - mprCreatePropertyValue(obj, "null", mprCreateNullVar()); - mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); - mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); - mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); - -#if BLD_FEATURE_LEGACY_API - /* - * DEPRECATED: 2.0. - * So that ESP/ASP can ignore "language=javascript" statements - */ - mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0)); -#endif - - /* - * Extension functions - */ - mprCreatePropertyValue(obj, "assert", - mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "eval", - mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "exit", - mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "refCount", - mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "print", - mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "println", - mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "printVars", - mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "trace", - mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* - * Constructors - */ - mprCreatePropertyValue(obj, "Array", - mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Boolean", - mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Object", - mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Number", - mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "String", - mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* mprCreatePropertyValue(obj, "Date", - * mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - * mprCreatePropertyValue(obj, "Regexp", - * mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - */ - - /* - * Can we use on var x = "string text"; - */ - return 0; -} - -/******************************************************************************/ - -#else -void ejsProcsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/miniMpr.c b/source4/lib/ejs/miniMpr.c deleted file mode 100644 index 8b969289b0..0000000000 --- a/source4/lib/ejs/miniMpr.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * @file miniMpr.cpp - * @brief Mini Mbedthis Portable Runtime (MPR) - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "lib/ejs/miniMpr.h" - -/************************************ Code ************************************/ -#if !BLD_APPWEB -#if !BLD_GOAHEAD_WEBSERVER - -static void *mpr_ctx; - -/* set the memory context to be used for all ejs variables */ -void mprSetCtx(TALLOC_CTX *ctx) -{ - mpr_ctx = ctx; -} - -/* return the memory context being used for all ejs variables */ -void *mprMemCtx(void) -{ - return mpr_ctx; -} - -void mprFree(void *ptr) -{ - talloc_free(ptr); -} - -void *mprMalloc(uint size) -{ - return talloc_size(mpr_ctx, size); -} - -/******************************************************************************/ - -void *mprRealloc(void *ptr, uint size) -{ - return talloc_realloc_size(mpr_ctx, ptr, size); -} - -/******************************************************************************/ - -char *mprStrdup(const char *str) -{ - if (str == 0) { - str = ""; - } - return talloc_strdup(mpr_ctx, str); -} - -/*****************************************************************************/ - -int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) -{ - va_list args; - char *buf; - int count; - - va_start(args, fmt); - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - va_end(args); - return count; -} - -/*****************************************************************************/ - -int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) -{ - char *buf; - int count; - - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - return count; -} - - -/*****************************************************************************/ -/* - * Format a number as a string. FUTURE -- reverse args to be standard. - * ie. mprItoa(char *userBuf, int bufsize, int value); - */ - -char *mprItoa(int value, char *buf, int width) -{ - char numBuf[16]; - char *cp, *dp, *endp; - int negative; - - cp = &numBuf[sizeof(numBuf)]; - *--cp = '\0'; - - if (value < 0) { - negative = 1; - value = -value; - width--; - } else { - negative = 0; - } - - do { - *--cp = '0' + (value % 10); - value /= 10; - } while (value > 0); - - if (negative) { - *--cp = '-'; - } - - dp = buf; - endp = &buf[width]; - while (dp < endp && *cp) { - *dp++ = *cp++; - } - *dp++ = '\0'; - return buf; -} - -/*****************************************************************************/ - -void mprLog(int level, const char *fmt, ...) -{ - va_list args; - char *buf; - - if (DEBUGLVL(level)) { - va_start(args, fmt); - mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); - va_end(args); - DEBUG(level, ("mprLog: %s", buf)); - mprFree(buf); - } -} - -/*****************************************************************************/ - -void mprBreakpoint(const char *file, int line, const char *cond) -{ - char *buf; - mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", - file, line, cond); - ejs_exception(buf); -} - -#endif /* !BLD_GOAHEAD_WEBSERVER */ -/*****************************************************************************/ -/* - * Create a general growable array structure - */ - -MprArray *mprCreateArray() -{ - MprArray *array; - int size; - - array = (MprArray*) mprMalloc(sizeof(MprArray)); - if (array == 0) { - return 0; - } - memset(array, 0, sizeof(MprArray)); - - size = MPR_ARRAY_INCR * sizeof(void*); - array->handles = (void**) mprMalloc(size); - if (array->handles == 0) { - mprFree(array); - return 0; - } - memset(array->handles, 0, size); - array->max = MPR_ARRAY_INCR; - array->used = 0; - return array; -} - -/*****************************************************************************/ -/* - * Dispose of the array. Callers responsibility to dispose of handle entries. - */ - -void mprDestroyArray(MprArray *array) -{ - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - mprFree(array->handles); - mprFree(array); -} - -/*****************************************************************************/ -/* - * Add an item to the array - */ - -int mprAddToArray(MprArray *array, void *item) -{ - int memsize, idx, len; - - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - if (array->used < array->max) { - idx = array->used++; - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - - for (idx = array->used; idx < array->max; idx++) { - if (array->handles[idx] == 0) { - array->used++; - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - } - - len = array->max + MPR_ARRAY_INCR; - memsize = len * sizeof(void*); - array->handles = (void**) mprRealloc((void*) array->handles, memsize); - if (array->handles == NULL) { - return -1; - } - memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); - array->max = len; - array->used++; - - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - - array->handles[idx] = item; - return idx; -} - -/*****************************************************************************/ -/* - * Remove from the array - */ - -int mprRemoveFromArray(MprArray *array, int idx) -{ - mprAssert(array); - mprAssert(array->max > 0); - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] != 0); - mprAssert(array->used > 0); - - array->handles[idx] = 0; - return --array->used; -} - -/*****************************************************************************/ -/* - * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() - */ - -char *mprStrTok(char *str, const char *delim, char **tok) -{ - char *start, *end; - int i; - - start = str ? str : *tok; - - if (start == 0) { - return 0; - } - - i = strspn(start, delim); - start += i; - if (*start == '\0') { - *tok = 0; - return 0; - } - end = strpbrk(start, delim); - if (end) { - *end++ = '\0'; - i = strspn(end, delim); - end += i; - } - *tok = end; - return start; -} - -/*****************************************************************************/ - -static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, - const char *delim, const char *src, va_list args) -{ - va_list ap; - char *dest, *dp; - const char *str; - int sepLen, addBytes, required; - - mprAssert(destp); - mprAssert(destMax > 0); - mprAssert(src); - - dest = *destp; - sepLen = (delim) ? strlen(delim) : 0; - -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - addBytes = 0; - str = src; - while (str) { - addBytes += strlen(str) + sepLen; - str = va_arg(ap, const char*); - } - - if (existingLen > 0) { - addBytes += sepLen; - } - required = existingLen + addBytes + 1; - if (required >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - - if (alloc) { - if (dest == 0) { - dest = (char*) mprMalloc(required); - } else { - dest = (char*) mprRealloc(dest, required); - } - } else { - dest = (char*) *destp; - } - - dp = &dest[existingLen]; - if (delim) { - strcpy(dp, delim); - dp += sepLen; - } - - if (addBytes > 0) { -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - str = src; - while (str) { - strcpy(dp, str); - dp += strlen(str); - str = va_arg(ap, char*); - if (delim && str) { - strcpy(dp, delim); - dp += sepLen; - } - } - } else if (dest == 0) { - dest = (char*) mprMalloc(1); - } - *dp = '\0'; - - *destp = dest; - mprAssert(dp < &dest[required]); - return required - 1; -} - -/*****************************************************************************/ - -int mprReallocStrcat(char **destp, int destMax, int existingLen, - const char *delim, const char *src,...) -{ - va_list ap; - int rc; - - va_start(ap, src); - rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); - va_end(ap); - return rc; -} - -/*****************************************************************************/ -/* - * Return the directory portion of a pathname into the users buffer. - */ - -int mprGetDirName(char *buf, int bufsize, char *path) -{ - char *cp; - int dlen; - - mprAssert(path); - mprAssert(buf); - mprAssert(bufsize > 0); - - cp = strrchr(path, '/'); - if (cp == 0) { -#if WIN - cp = strrchr(path, '\\'); - if (cp == 0) -#endif - { - buf[0] = '\0'; - return 0; - } - } - - if (cp == path && cp[1] == '\0') { - strcpy(buf, "."); - return 0; - } - - dlen = cp - path; - if (dlen < bufsize) { - if (dlen == 0) { - dlen++; - } - mprMemcpy(buf, bufsize, path, dlen); - buf[dlen] = '\0'; - return 0; - } - return MPR_ERR_WONT_FIT; -} - -/*****************************************************************************/ - -int mprStrcpy(char *dest, int destMax, const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax > 0); - mprAssert(src); - - len = strlen(src); - if (len >= destMax && len > 0) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - memcpy(dest, src, len); - dest[len] = '\0'; - } else { - *dest = '\0'; - len = 0; - } - return len; -} - -/*****************************************************************************/ - -int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) -{ - mprAssert(dest); - mprAssert(destMax > nbytes); - mprAssert(src); - mprAssert(nbytes > 0); - - if (nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - memcpy(dest, src, nbytes); - return nbytes; - } else { - return 0; - } -} - -/*****************************************************************************/ -#else -void miniMprDummy() {} -#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/miniMpr.h b/source4/lib/ejs/miniMpr.h deleted file mode 100644 index d431ebdc1b..0000000000 --- a/source4/lib/ejs/miniMpr.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * @file miniMpr.h - * @brief Mini Mbedthis Portable Runtime (MPR) Environment. - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -#ifndef _h_MINI_MPR -#define _h_MINI_MPR 1 - -/********************************** Includes **********************************/ -/* - * Find out about our configuration - */ -#ifndef _INCLUDES_H - #include "includes.h" -#endif - -/* allow this library to use strcpy() */ -#undef strcpy - #include "config.h" - -#if BLD_APPWEB - /* - * If building within AppWeb, use the full MPR - */ - #include "mpr.h" -#else - - #include - #include - #include - #include - #include - #include - #include - -#if !WIN - #include -#endif - -#if CE - #include - #include "CE/wincompat.h" -#endif - -#if LYNX - #include -#endif - -#if QNX4 - #include -#endif - #include - -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#if BLD_FEATURE_SQUEEZE -/* - * Reasonable length of a file path name to use in most cases where you know - * the expected file name and it is certain to be less than this limit. - */ -#define MPR_MAX_FNAME 128 -#define MPR_MAX_STRING 512 -#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (32 * 1024) -#else -#define MPR_MAX_FNAME 256 -#define MPR_MAX_STRING 4096 -#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (64 * 1024) -#endif - -/* - * Useful for debugging - */ -#define MPR_L __FILE__, __LINE__ - -#if BLD_FEATURE_ASSERT -#define mprAssert(C) \ - if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) -#else - #define mprAssert(C) if (1) ; else -#endif - -/* - * Standard MPR return and error codes - */ -#define MPR_ERR_BASE (-200) /* Error code */ -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ -#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ - -/* - * Standard error severity and trace levels. These are ored with the error - * severities below. The MPR_LOG_MASK is used to extract the trace level - * from a flags word. We expect most apps to run with level 2 trace. - */ -#define MPR_FATAL 0 /* Fatal error. Cant continue. */ -#define MPR_ERROR 1 /* Hard error */ -#define MPR_WARN 2 /* Soft warning */ -#define MPR_CONFIG 2 /* Essential configuration settings */ -#define MPR_INFO 3 /* Informational only */ -#define MPR_DEBUG 4 /* Debug information */ -#define MPR_VERBOSE 9 /* Highest level of trace */ -#define MPR_LOG_MASK 0xf /* Level mask */ - -/* - * Error flags. Specify where the error should be sent to. Note that the - * product.xml setting "headless" will modify how errors are reported. - * Assert errors are trapped when in DEV mode. Otherwise ignored. - */ -#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ -#define MPR_LOG 0x20 /* Log the error in the O/S event log */ -#define MPR_USER 0x40 /* Display to the user */ -#define MPR_ALERT 0x80 /* Send a management alert */ -#define MPR_TRACE 0x100 /* Trace */ - -/* - * Error format flags - */ -#define MPR_RAW 0x200 /* Raw trace output */ - -/* - * Error line number information - */ -#define MPR_L __FILE__, __LINE__ - -typedef char* MprStr; - -#ifndef __cplusplus -typedef unsigned char uchar; -typedef int bool; -#endif - -/* - * Porters: put other operating system type defines here - */ -#if WIN - typedef unsigned int uint; - typedef __int64 int64; - typedef unsigned __int64 uint64; -#else -#define O_BINARY 0 -#ifndef uint - #define uint unsigned -#endif - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; -#endif - -/* - * Flexible array data type - */ -typedef struct { - int max; /* Size of the handles array */ - int used; /* Count of used entries in handles */ - void **handles; -} MprArray; - -#if BLD_FEATURE_SQUEEZE -#define MPR_ARRAY_INCR 8 -#else -#define MPR_ARRAY_INCR 16 -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -/********************************* Prototypes *********************************/ -/* - * If running in the GoAhead WebServer, map some MPR routines to WebServer - * equivalents. - */ - -#if BLD_GOAHEAD_WEBSERVER -#include "uemf.h" -#define mprMalloc(size) balloc(B_L, size) -#define mprFree(ptr) bfreeSafe(B_L, ptr) -#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) -#define mprStrdup(ptr) bstrdup(B_L, ptr) -#define mprAllocSprintf fmtAlloc -#define mprAllocVsprintf fmtValloc -#define mprSprintf fmtStatic -#define mprItoa stritoa -#define mprLog trace -#define mprBreakpoint(file, line, cond) \ - error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) - -#else /* !BLD_GOAHEAD_WEBSERVER */ -/* #define mprMalloc malloc */ -#define mprSprintf snprintf -#define mtVsprintf vsnprintf -extern void *mprMalloc(uint size); -extern void *mprRealloc(void *ptr, uint size); -extern void mprFree(void *ptr); -extern char *mprStrdup(const char *str); -extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, - va_list args) PRINTF_ATTRIBUTE(3,0); -extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern char *mprItoa(int num, char *buf, int width); -extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -extern void mprBreakpoint(const char *file, int line, const char *msg); -#endif /* BLD_GOAHEAD_WEBSERVER */ - -extern MprArray *mprCreateArray(void); -extern void mprDestroyArray(MprArray *array); -extern int mprAddToArray(MprArray *array, void *item); -extern int mprRemoveFromArray(MprArray *array, int idx); -extern char *mprStrTok(char *str, const char *delim, char **tok); - -extern int mprGetDirName(char *buf, int bufsize, char *path); -extern int mprReallocStrcat(char **dest, int max, int existingLen, - const char *delim, const char *src, ...); -extern int mprStrcpy(char *dest, int destMax, const char *src); -extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); - -extern void mprSetCtx(void *ctx); -extern void *mprMemCtx(void); - -#ifdef __cplusplus -} -#endif -#endif /* !BLD_APPWEB */ -#endif /* _h_MINI_MPR */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/mprOs.h b/source4/lib/ejs/mprOs.h deleted file mode 100644 index 6a6d0b4205..0000000000 --- a/source4/lib/ejs/mprOs.h +++ /dev/null @@ -1,627 +0,0 @@ -/* - * @file mprOs.h - * @brief Include O/S headers and smooth out per-O/S differences - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - ******************************* Documentation ********************************* - * - * This header is part of the Mbedthis Portable Runtime and aims to include - * all necessary O/S headers and to unify the constants and declarations - * required by Mbedthis products. It can be included by C or C++ programs. - * - ********************************************************************************/ - -#error foo - -blah blah; - -#ifndef _h_MPR_OS_HDRS -#define _h_MPR_OS_HDRS 1 - -#include "lib/ejs/config.h" - -/********************************* CPU Families *********************************/ -/* - * Porters, add your CPU families here and update configure code. - */ -#define MPR_CPU_UNKNOWN 0 -#define MPR_CPU_IX86 1 -#define MPR_CPU_PPC 2 -#define MPR_CPU_SPARC 3 -#define MPR_CPU_XSCALE 4 -#define MPR_CPU_ARM 5 -#define MPR_CPU_MIPS 6 -#define MPR_CPU_68K 7 -#define MPR_CPU_SIMNT 8 /* VxWorks NT simulator */ -#define MPR_CPU_SIMSPARC 9 /* VxWorks sparc simulator */ - -/********************************* O/S Includes *********************************/ - -#if LINUX || SOLARIS - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - -#if LINUX - #include -#endif - -#if SOLARIS - #include -#endif - -#if BLD_FEATURE_FLOATING_POINT - #define __USE_ISOC99 1 - #include - #include -#endif - -#endif /* LINUX || SOLARIS */ - -#if VXWORKS - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #if BLD_FEATURE_FLOATING_POINT - #include - #define __USE_ISOC99 1 - #include - #endif - - #include - #include - #include - #include - #include - #include - #include - #include - -#endif /* VXWORKS */ - -#if MACOSX - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -#endif /* MACOSX */ - -#if WIN - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #define WIN32_LEAN_AND_MEAN - #include - #include - #include - #if BLD_FEATURE_FLOATING_POINT - #include - #endif - #include - #include - #include -#endif /* WIN */ - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************************************************************/ -/******************************* General Defines ********************************/ -/********************************************************************************/ - -#define MAXINT INT_MAX -#define BITS(type) (BITSPERBYTE * (int) sizeof(type)) - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -/* - * Set FD_SETSIZE to the maximum number of files (sockets) that you want to - * support. It is used in select.cpp. - * - * #ifdef FD_SETSIZE - * #undef FD_SETSIZE - * #endif - * #define FD_SETSIZE 128 - */ - -typedef char *MprStr; /* Used for dynamic strings */ - -/********************************************************************************/ -/*******************************/ Linux Defines *********************************/ -/********************************************************************************/ - -#if LINUX - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; - #define INT64(x) (x##LL) -#endif - - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - - #if BLD_FEATURE_MALLOC - /* - * PORTERS: You will need add assembler code for your architecture here - * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - */ - #if UNUSED - #define MPR_GET_RETURN(ip) __builtin_return_address(0) - #else - #if BLD_HOST_CPU_ARCH == MPR_CPU_IX86 - #define MPR_GET_RETURN(ip) \ - asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \ - "=g" (ip) : \ - : "eax") - #endif -#endif /* UNUSED */ -#endif /* BLD_FEATURE_MALLOC */ - -#if FUTURE -/* #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) */ -/* extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); */ - - /* */ - /* Atomic functions */ - /* */ - typedef struct { volatile int counter; } mprAtomic_t; - - #if BLD_FEATURE_MULTITHREAD - #define LOCK "lock ; " - #else - #define LOCK "" - #endif - - static __inline__ void mprAtomicInc(mprAtomic_t* v) { - __asm__ __volatile__( - LOCK "incl %0" - :"=m" (v->counter) - :"m" (v->counter)); - } - - static __inline__ void mprAtomicDec(mprAtomic_t* v) { - __asm__ __volatile__( - LOCK "decl %0" - :"=m" (v->counter) - :"m" (v->counter)); - } -#endif /* FUTURE */ - -#endif /* LINUX */ - -/********************************************************************************/ -/******************************* VxWorks Defines ********************************/ -/********************************************************************************/ - -#if VXWORKS - - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - - #define HAVE_SOCKLEN_T - typedef int socklen_t; - -#if BLD_FEATURE_INT64 - typedef long long int int64; - typedef unsigned long long int uint64; - #define INT64(x) (x##LL) -#endif - - #define closesocket(x) close(x) - #define getpid() taskIdSelf() - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT FLT_MAX -#endif - - #undef R_OK - #define R_OK 4 - #undef W_OK - #define W_OK 2 - #undef X_OK - #define X_OK 1 - #undef F_OK - #define F_OK 0 - - #define MSG_NOSIGNAL 0 - - extern int access(char *path, int mode); - extern int sysClkRateGet(); - - #if BLD_FEATURE_MALLOC - /* - * PORTERS: You will need add assembler code for your architecture here - * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - */ - #if UNUSED - #define MPR_GET_RETURN(ip) __builtin_return_address(0) - #else - #if BLD_HOST_CPU_ARCH == MPR_CPU_IX86 - #define MPR_GET_RETURN(ip) \ - asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \ - "=g" (ip) : \ - : "eax") - #endif -#endif /* UNUSED */ -#endif /* BLD_FEATURE_MALLOC */ -#endif /* VXWORKS */ - -/********************************************************************************/ -/******************************** MacOsx Defines ********************************/ -/********************************************************************************/ -#if MACOSX - typedef unsigned long ulong; - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; - #define INT64(x) (x##LL) -#endif - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".dylib" - #define MSG_NOSIGNAL 0 - #define __WALL 0x40000000 - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - - #if MPR_FEATURE_MALLOC - /* - * PORTERS: You will need add assembler code for your architecture here - * only if you want to use the fast malloc (MPR_FEATURE_MALLOC) - */ - #define MPR_GET_RETURN(ip) __builtin_return_address - #endif - -#if FUTURE -/* #define mprGetHiResTime(x) __asm__ __volatile__ ("rdtsc" : "=A" (x)) */ -/* extern char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen); */ - - /* */ - /* Atomic functions */ - /* */ - typedef struct { volatile int counter; } mprAtomic_t; - - #if MPR_FEATURE_MULTITHREAD - #define LOCK "lock ; " - #else - #define LOCK "" - #endif - - static __inline__ void mprAtomicInc(mprAtomic_t* v) { - __asm__ __volatile__( - LOCK "incl %0" - :"=m" (v->counter) - :"m" (v->counter)); - } - - static __inline__ void mprAtomicDec(mprAtomic_t* v) { - __asm__ __volatile__( - LOCK "decl %0" - :"=m" (v->counter) - :"m" (v->counter)); - } -#endif -#endif /* MACOSX */ - -/********************************************************************************/ -/******************************* Windows Defines ********************************/ -/********************************************************************************/ - -#if WIN - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - typedef unsigned short ushort; - -#if BLD_FEATURE_INT64 - typedef __int64 int64; - typedef unsigned __int64 uint64; - #define INT64(x) (x##i64) -#endif - - typedef int uid_t; - typedef void *handle; - typedef char *caddr_t; - typedef long pid_t; - typedef int gid_t; - typedef ushort mode_t; - typedef void *siginfo_t; - - #define HAVE_SOCKLEN_T - typedef int socklen_t; - - #undef R_OK - #define R_OK 4 - #undef W_OK - #define W_OK 2 - #undef X_OK - #define X_OK 1 - #undef F_OK - #define F_OK 0 - - #ifndef EADDRINUSE - #define EADDRINUSE 46 - #endif - #ifndef EWOULDBLOCK - #define EWOULDBLOCK EAGAIN - #endif - #ifndef ENETDOWN - #define ENETDOWN 43 - #endif - #ifndef ECONNRESET - #define ECONNRESET 44 - #endif - #ifndef ECONNREFUSED - #define ECONNREFUSED 45 - #endif - - #define MSG_NOSIGNAL 0 - #define MPR_BINARY "b" - #define MPR_TEXT "t" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT DBL_MAX -#endif - -#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE -#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 -#endif - - #define access _access - #define close _close - #define fileno _fileno - #define fstat _fstat - #define getpid _getpid - #define open _open - #define putenv _putenv - #define read _read - #define stat _stat - #define umask _umask - #define unlink _unlink - #define write _write - #define strdup _strdup - #define lseek _lseek - - #define mkdir(a,b) _mkdir(a) - #define rmdir(a) _rmdir(a) - - #if BLD_FEATURE_MALLOC - /* - * PORTERS: You will need add assembler code for your architecture here - * only if you want to use the fast malloc (BLD_FEATURE_MALLOC) - */ - #if MPR_CPU_IX86 - #define MPR_GET_RETURN(ip) \ - __asm { mov eax, 4[ebp] } \ - __asm { mov ip, eax } - #endif - #endif - - #define MPR_DLL_EXT ".dll" - - extern void srand48(long); - extern long lrand48(void); - extern long ulimit(int, ...); - extern long nap(long); - extern uint sleep(unsigned int secs); - extern uid_t getuid(void); - extern uid_t geteuid(void); - -#endif /* WIN */ - -/********************************************************************************/ -/*****************************/ Solaris Defines *********************************/ -/********************************************************************************/ - -#if SOLARIS - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - typedef long long int int64; - typedef unsigned long long int uint64; - #define INT64(x) (x##LL) -#endif - - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - #define MSG_NOSIGNAL 0 - #define INADDR_NONE ((in_addr_t) 0xffffffff) - #define __WALL 0 - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - -#endif /* SOLARIS */ - -/********************************************************************************/ -#ifdef __cplusplus -} -#endif - -#endif /* _h_MPR_OS_HDRS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/var.c b/source4/lib/ejs/var.c deleted file mode 100644 index 9d2afe5306..0000000000 --- a/source4/lib/ejs/var.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * @file var.c - * @brief MPR Universal Variable Type - * @overview - * - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This module is NOT multithreaded. - * - * Properties are variables that are stored in an object type variable. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. - */ - -/********************************** Includes **********************************/ - -#include "var.h" - -/*********************************** Locals ***********************************/ -#if VAR_DEBUG - -static MprProperties objectList; /* Dummy head of objects list */ -static int objectCount = -1; /* Count of objects */ - -#endif -/***************************** Forward Declarations ***************************/ - -static int adjustRefCount(MprProperties *pp, int adj); -static int adjustVarRefCount(MprVar *vp, int adj); -static MprVar *allocProperty(const char *propertyName); -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); -static MprProperties - *createProperties(const char *name, int hashSize); -static bool freeVar(MprVar *vp, int force); -static bool freeVarStorage(MprVar *vp, int force); -static MprVar *getObjChain(MprProperties *pp, const char *property); -static int hash(MprProperties *pp, const char *property); -static bool releaseProperties(MprProperties *pp, int force); - -/*********************************** Code *************************************/ -/* - * Destroy a variable and all referenced variables. Release any referenced - * object regardless of whether other users still have references. Be VERY - * careful using this routine. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyAllVars(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all vars. - */ - return freeVar(vp, 1); -} - -/******************************************************************************/ -/* - * Destroy a variable. Release any referenced object (destroy if no other - * users are referencing). - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyVar(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all that have no other - * references. - */ - return freeVar(vp, 0); -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVar(MprVar *vp, int force) -{ - bool freed; - - mprAssert(vp); - - freed = freeVarStorage(vp, force); - - mprFree(vp->name); - mprFree(vp->fullName); - - if (vp->allocatedVar) { - mprFree(vp); - } else { - vp->name = 0; - vp->fullName = 0; - vp->type = MPR_TYPE_UNDEFINED; - } - return freed; -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVarStorage(MprVar *vp, int force) -{ - MprArray *argList; - bool freed; - int i; - - freed = 1; - mprAssert(vp); - - switch (vp->type) { - default: - break; - - case MPR_TYPE_STRING: - if (vp->allocatedData && vp->string != 0) { - mprFree(vp->string); - vp->string = 0; - vp->allocatedData = 0; - } - break; - - case MPR_TYPE_OBJECT: -#if VAR_DEBUG - /* - * Recurse through all properties and release / delete. Release the - * properties hash table. - */ - if (vp->properties->refCount > 1) { - mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } else { - mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } -#endif - if (vp->allocatedData) { - freed = releaseProperties(vp->properties, force); - } - vp->properties = 0; - break; - - case MPR_TYPE_FUNCTION: - if (vp->allocatedData) { - argList = vp->function.args; - for (i = 0; i < argList->max; i++) { - if (argList->handles[i] != 0) { - mprFree(argList->handles[i]); - } - } - mprDestroyArray(argList); - vp->function.args = 0; - mprFree(vp->function.body); - vp->function.body = 0; - } - break; - } - - vp->type = MPR_TYPE_UNDEFINED; - return freed; -} - -/******************************************************************************/ -/* - * Adjust the object reference count and return the currrent count of - * users. - */ - -static int adjustVarRefCount(MprVar *vp, int adj) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, adj); -} - -/******************************************************************************/ -/* - * Get the object reference count - */ - -int mprGetVarRefCount(MprVar *vp) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, 0); -} - -/******************************************************************************/ -/* - * Update the variable's name - */ - -void mprSetVarName(MprVar *vp, char *name) -{ - mprAssert(vp); - - mprFree(vp->name); - vp->name = mprStrdup(name); -} - -/******************************************************************************/ -/* - * Append to the variable's full name - */ - -void mprSetVarFullName(MprVar *vp, char *name) -{ -#if VAR_DEBUG - mprAssert(vp); - - mprFree(vp->fullName); - vp->fullName = mprStrdup(name); - if (vp->type == MPR_TYPE_OBJECT) { - if (strcmp(vp->properties->name, "this") == 0) { - mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); - } - } -#endif -} - -/******************************************************************************/ -/* - * Make a var impervious to recursive forced deletes. - */ - -void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) -{ - mprAssert(vp); - - if (vp->type == MPR_TYPE_OBJECT && vp->properties) { - vp->properties->deleteProtect = deleteProtect; - } -} - -/******************************************************************************/ -/* - * Make a variable readonly. Can still be deleted. - */ - -void mprSetVarReadonly(MprVar *vp, int readonly) -{ - mprAssert(vp); - - vp->readonly = readonly; -} - -/******************************************************************************/ - -MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) -{ - MprVarTrigger oldTrigger; - - mprAssert(vp); - mprAssert(fn); - - oldTrigger = vp->trigger; - vp->trigger = fn; - return oldTrigger; -} - -/******************************************************************************/ - -MprType mprGetVarType(MprVar *vp) -{ - mprAssert(vp); - - return vp->type; -} - -/******************************************************************************/ -/********************************** Properties ********************************/ -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. - */ - -MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, - MprVar *newValue) -{ - MprVar *prop, *last; - int bucketIndex; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - /* - * See if property already exists and locate the bucket to hold the - * property reference. - */ - last = 0; - bucketIndex = hash(obj->properties, propertyName); - prop = obj->properties->buckets[bucketIndex]; - - /* - * Find the property in the hash chain if it exists - */ - for (last = 0; prop; last = prop, prop = prop->forw) { - if (prop->name[0] == propertyName[0] && - strcmp(prop->name, propertyName) == 0) { - break; - } - } - - if (prop) { - /* FUTURE -- remove. Just for debug. */ - mprAssert(prop == 0); - mprLog(0, "Attempting to create property %s in object %s\n", - propertyName, obj->name); - return 0; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, - newValue, 0) == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Create a new property - */ - prop = allocProperty(propertyName); - if (prop == 0) { - mprAssert(prop); - return 0; - } - - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - - prop->bucketIndex = bucketIndex; - if (last) { - last->forw = prop; - } else { - obj->properties->buckets[bucketIndex] = prop; - } - prop->parentProperties = obj->properties; - - /* - * Update the item counts - */ - obj->properties->numItems++; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems++; - } - - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. Same as - * mprCreateProperty except that the new value is passed by value rather than - * by pointer. - */ - -MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprCreateProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Create a new property - */ - -static MprVar *allocProperty(const char *propertyName) -{ - MprVar *prop; - - prop = (MprVar*) mprMalloc(sizeof(MprVar)); - if (prop == 0) { - mprAssert(prop); - return 0; - } - memset(prop, 0, sizeof(MprVar)); - prop->allocatedVar = 1; - prop->name = mprStrdup(propertyName); - prop->forw = (MprVar*) 0; - - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it doesn not already exist. - */ - -MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) -{ - MprVar *prop, triggerValue; - int rc; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(0); - return 0; - } - - prop = mprGetProperty(obj, propertyName, 0); - if (prop == 0) { - return mprCreateProperty(obj, propertyName, newValue); - } - - if (obj->trigger) { - /* - * Call the trigger before the update and pass it the new value. - */ - triggerValue = *newValue; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - /* - * Trigger must copy to triggerValue a variable that is not - * a structure copy of the existing data. - */ - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return prop; - } - } - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it does not already exist. Same as mprSetProperty except that the - * new value is passed by value rather than by pointer. - */ - -MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprSetProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Delete a property from this object - */ - -int mprDeleteProperty(MprVar *obj, const char *property) -{ - MprVar *prop, *last; - char *cp; - int bucketIndex; - - mprAssert(obj); - mprAssert(property && *property); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - last = 0; - bucketIndex = hash(obj->properties, property); - if ((prop = obj->properties->buckets[bucketIndex]) != 0) { - for ( ; prop; prop = prop->forw) { - cp = prop->name; - if (cp[0] == property[0] && strcmp(cp, property) == 0) { - break; - } - last = prop; - } - } - if (prop == (MprVar*) 0) { - mprAssert(prop); - return MPR_ERR_NOT_FOUND; - } - if (prop->readonly) { - mprAssert(! prop->readonly); - return MPR_ERR_READ_ONLY; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) - == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - } - } - - if (last) { - last->forw = prop->forw; - } else { - obj->properties->buckets[bucketIndex] = prop->forw; - } - - obj->properties->numItems--; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems--; - } - - mprDestroyVar(prop); - - return 0; -} - -/******************************************************************************/ -/* - * Find a property in an object and return a pointer to it. If a value arg - * is supplied, then copy the data into the var. - */ - -MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) -{ - MprVar *prop, triggerValue; - int rc; - - if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || - *property == '\0') { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - - for (prop = getObjChain(obj->properties, property); prop; - prop = prop->forw) { - if (prop->name && - prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { - break; - } - } - if (prop == 0) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - if (value) { - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - /* - * Pass the trigger the current read value and may receive - * a new value. - */ - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - } - } - /* - * Clone. No copy. - */ - *value = *prop; - } - return prop; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns the property's value. It does not - * copy object/string data but returns a pointer directly into the variable. - * The caller does not and should not call mprDestroy on the returned value. - * If value is null, just read the property and run triggers. - */ - -int mprReadProperty(MprVar *prop, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - if (value) { - *value = *prop; - - /* - * Just so that if the user calls mprDestroyVar on value, it will do no - * harm. - */ - value->allocatedVar = 0; - value->allocatedData = 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns a copy of the property variable. - * However, if the property is an object or string, it returns a copy of the - * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, - * then the underlying objects and strings data will be copied as well. If - * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If - * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the - * user must call mprDestroyVar to free resources. This routine will run any - * registered triggers which may modify the value the user receives (without - * updating the properties real value). - * - * WARNING: the args are reversed to most other APIs. This conforms to the - * strcpy(dest, src) standard instead. - */ - -int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - mprAssert(dest); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, copyDepth); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - mprCopyVar(dest, prop, copyDepth); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWriteProperty(MprVar *vp, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(vp); - mprAssert(value); - - if (vp->readonly) { - return MPR_ERR_READ_ONLY; - } - - if (vp->trigger) { - triggerValue = *value; - - rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - /* Fall through */ - } - - copyVarCore(vp, value, MPR_SHALLOW_COPY); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWritePropertyValue(MprVar *vp, MprVar value) -{ - mprAssert(vp); - - return mprWriteProperty(vp, &value); -} - -/******************************************************************************/ -/* - * Get the count of properties. - */ - -int mprGetPropertyCount(MprVar *vp, int includeFlags) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - return 0; - } - if (includeFlags == MPR_ENUM_DATA) { - return vp->properties->numDataItems; - } else { - return vp->properties->numItems; - } -} - -/******************************************************************************/ -/* - * Get the first property in an object. Used for walking all properties in an - * object. - */ - -MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) -{ - MprVar *prop; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - for (i = 0; i < (int) obj->properties->hashSize; i++) { - for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { - if (prop) { - if (mprVarIsFunction(prop->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return prop; - } - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Get the next property in sequence. - */ - -MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) -{ - MprProperties *properties; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - properties = obj->properties; - - if (last->forw) { - return last->forw; - } - - for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { - for (last = properties->buckets[i]; last; last = last->forw) { - if (mprVarIsFunction(last->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return last; - } - } - return 0; -} - -/******************************************************************************/ -/************************** Internal Support Routines *************************/ -/******************************************************************************/ -/* - * Create an hash table to hold and index properties. Properties are just - * variables which may contain primitive data types, functions or other - * objects. The hash table is the essence of an object. HashSize specifies - * the size of the hash table to use and should be a prime number. - */ - -static MprProperties *createProperties(const char *name, int hashSize) -{ - MprProperties *pp; - - if (hashSize < 7) { - hashSize = 7; - } - if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { - mprAssert(0); - return 0; - } - mprAssert(pp); - memset(pp, 0, sizeof(MprProperties)); - - pp->numItems = 0; - pp->numDataItems = 0; - pp->hashSize = hashSize; - pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); - mprAssert(pp->buckets); - memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); - pp->refCount = 1; - -#if VAR_DEBUG - if (objectCount == -1) { - objectCount = 0; - objectList.next = objectList.prev = &objectList; - } - - mprStrcpy(pp->name, sizeof(pp->name), name); - pp->next = &objectList; - pp->prev = objectList.prev; - objectList.prev->next = pp; - objectList.prev = pp; - objectCount++; -#endif - return pp; -} - -/******************************************************************************/ -/* - * Release an object's properties hash table. If this is the last person - * using it, free it. Return TRUE if the object is released. - */ - -static bool releaseProperties(MprProperties *obj, int force) -{ - MprProperties *pp; - MprVar *prop, *forw; - int i; - - mprAssert(obj); - mprAssert(obj->refCount > 0); - -#if VAR_DEBUG - /* - * Debug sanity check - */ - mprAssert(obj->refCount < 20); -#endif - - if (--obj->refCount > 0 && !force) { - return 0; - } - -#if VAR_DEBUG - mprAssert(obj->prev); - mprAssert(obj->next); - mprAssert(obj->next->prev); - mprAssert(obj->prev->next); - obj->next->prev = obj->prev; - obj->prev->next = obj->next; - objectCount--; -#endif - - for (i = 0; i < (int) obj->hashSize; i++) { - for (prop = obj->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->type == MPR_TYPE_OBJECT) { - - if (prop->properties == obj) { - /* Self reference */ - continue; - } - pp = prop->properties; - if (pp->visited) { - continue; - } - - pp->visited = 1; - if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { - pp->visited = 0; - } - - } else { - freeVar(prop, force); - } - } - } - - mprFree((void*) obj->buckets); - mprFree((void*) obj); - - return 1; -} - -/******************************************************************************/ -/* - * Adjust the reference count - */ - -static int adjustRefCount(MprProperties *pp, int adj) -{ - mprAssert(pp); - - /* - * Debug sanity check - */ - mprAssert(pp->refCount < 20); - - return pp->refCount += adj; -} - -/******************************************************************************/ -#if VAR_DEBUG -/* - * Print objects held - */ - -void mprPrintObjects(char *msg) -{ - MprProperties *pp, *np; - MprVar *prop, *forw; - char *buf; - int i; - - mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); - pp = objectList.next; - while (pp != &objectList) { - mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", - pp->name, pp, pp->refCount, pp->numItems); - for (i = 0; i < (int) pp->hashSize; i++) { - for (prop = pp->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->properties == pp) { - /* Self reference */ - continue; - } - mprVarToString(&buf, MPR_MAX_STRING, 0, prop); - if (prop->type == MPR_TYPE_OBJECT) { - np = objectList.next; - while (np != &objectList) { - if (prop->properties == np) { - break; - } - np = np->next; - } - if (prop->properties == np) { - mprLog(7, " %s: OBJECT 0x%x, <%s>\n", - prop->name, prop->properties, prop->fullName); - } else { - mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", - prop->name, buf, prop->fullName); - } - } else { - mprLog(7, " %s: <%s> = %s\n", prop->name, - prop->fullName, buf); - } - mprFree(buf); - } - } - pp = pp->next; - } -} - -/******************************************************************************/ - -void mprPrintObjRefCount(MprVar *vp) -{ - mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, - vp->properties->refCount); -} - -#endif -/******************************************************************************/ -/* - * Get the bucket chain containing a property. - */ - -static MprVar *getObjChain(MprProperties *obj, const char *property) -{ - mprAssert(obj); - - return obj->buckets[hash(obj, property)]; -} - -/******************************************************************************/ -/* - * Fast hash. The history of this algorithm is part of lost computer science - * folk lore. - */ - -static int hash(MprProperties *pp, const char *property) -{ - uint sum; - - mprAssert(pp); - mprAssert(property); - - sum = 0; - while (*property) { - sum += (sum * 33) + *property++; - } - - return sum % pp->hashSize; -} - -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -/* - * Initialize an undefined value. - */ - -MprVar mprCreateUndefinedVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_UNDEFINED; - return v; -} - -/******************************************************************************/ -/* - * Initialize an null value. - */ - -MprVar mprCreateNullVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_NULL; - return v; -} - -/******************************************************************************/ - -MprVar mprCreateBoolVar(bool value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_BOOL; - v.boolean = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_CFUNCTION; - v.cFunction.fn = fn; - v.cFunction.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, - int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING_CFUNCTION; - v.cFunctionWithStrings.fn = fn; - v.cFunctionWithStrings.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize an opaque pointer. - */ - -MprVar mprCreatePtrVar(void *ptr) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_PTR; - v.ptr = ptr; - - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Initialize a floating value. - */ - -MprVar mprCreateFloatVar(double value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FLOAT; - v.floating = value; - return v; -} - -#endif -/******************************************************************************/ -/* - * Initialize an integer value. - */ - -MprVar mprCreateIntegerVar(int value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT; - v.integer = value; - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Initialize a 64-bit integer value. - */ - -MprVar mprCreateInteger64Var(int64 value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT64; - v.integer64 = value; - return v; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Initialize an number variable. Type is defined by configure. - */ - -MprVar mprCreateNumberVar(MprNum value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = BLD_FEATURE_NUM_TYPE_ID; -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - v.integer64 = value; -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - v.float = value; -#else - v.integer = value; -#endif - return v; -} - -/******************************************************************************/ -/* - * Initialize a (bare) JavaScript function. args and body can be null. - */ - -MprVar mprCreateFunctionVar(char *args, char *body, int flags) -{ - MprVar v; - char *cp, *arg, *last; - int aid; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FUNCTION; - v.flags = flags; - - v.function.args = mprCreateArray(); - - if (args) { - args = mprStrdup(args); - arg = mprStrTok(args, ",", &last); - while (arg) { - while (isspace((int) *arg)) - arg++; - for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { - if (!isspace((int) *cp)) { - break; - } - } - cp[1] = '\0'; - - aid = mprAddToArray(v.function.args, mprStrdup(arg)); - arg = mprStrTok(0, ",", &last); - } - mprFree(args); - } - - if (body) { - v.function.body = mprStrdup(body); - } - v.allocatedData = 1; - return v; -} - -/******************************************************************************/ -/* - * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the - * memory allocation for the properties table failed. - */ - -MprVar mprCreateObjVar(const char *name, int hashSize) -{ - MprVar v; - - mprAssert(name && *name); - - memset(&v, 0x0, sizeof(MprVar)); - v.type = MPR_TYPE_OBJECT; - if (hashSize <= 0) { - hashSize = MPR_DEFAULT_HASH_SIZE; - } - v.properties = createProperties(name, hashSize); - if (v.properties == 0) { - /* Indicate failed memory allocation */ - v.type = MPR_TYPE_UNDEFINED; - } - v.allocatedData = 1; - v.name = mprStrdup(name); - mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); - return v; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -MprVar mprCreateStringVar(const char *value, bool allocate) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING; - if (value == 0) { - v.string = ""; - } else if (allocate) { - v.string = mprStrdup(value); - v.allocatedData = 1; - } else { - v.string = (char*) value; - } - return v; -} - -/******************************************************************************/ -/* - * Copy an objects core value (only). This preserves the destination object's - * name. This implements copy by reference for objects and copy by value for - * strings and other types. Caller must free dest prior to calling. - */ - -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) -{ - MprVarTrigger saveTrigger; - MprVar *srcProp, *destProp, *last; - char **srcArgs; - int i; - - mprAssert(dest); - mprAssert(src); - - if (dest == src) { - return; - } - - /* - * FUTURE: we should allow read-only triggers where the value is never - * stored in the object. Currently, triggers override the readonly - * status. - */ - - if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { - mprAssert(0); - return; - } - - if (dest->type != MPR_TYPE_UNDEFINED) { - saveTrigger = dest->trigger; - freeVarStorage(dest, 0); - } else { - saveTrigger = 0; - } - - switch (src->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - break; - - case MPR_TYPE_BOOL: - dest->boolean = src->boolean; - break; - - case MPR_TYPE_PTR: - dest->ptr = src->ptr; - break; - - case MPR_TYPE_STRING_CFUNCTION: - dest->cFunctionWithStrings = src->cFunctionWithStrings; - break; - - case MPR_TYPE_CFUNCTION: - dest->cFunction = src->cFunction; - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - dest->floating = src->floating; - break; -#endif - - case MPR_TYPE_INT: - dest->integer = src->integer; - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - dest->integer64 = src->integer64; - break; -#endif - - case MPR_TYPE_OBJECT: - if (copyDepth == MPR_DEEP_COPY) { - - dest->properties = createProperties(src->name, - src->properties->hashSize); - dest->allocatedData = 1; - - for (i = 0; i < (int) src->properties->hashSize; i++) { - last = 0; - for (srcProp = src->properties->buckets[i]; srcProp; - srcProp = srcProp->forw) { - if (srcProp->visited) { - continue; - } - destProp = allocProperty(srcProp->name); - if (destProp == 0) { - mprAssert(destProp); - return; - } - - destProp->bucketIndex = i; - if (last) { - last->forw = destProp; - } else { - dest->properties->buckets[i] = destProp; - } - destProp->parentProperties = dest->properties; - - /* - * Recursively copy the object - */ - srcProp->visited = 1; - copyVarCore(destProp, srcProp, copyDepth); - srcProp->visited = 0; - last = srcProp; - } - } - dest->properties->numItems = src->properties->numItems; - dest->properties->numDataItems = src->properties->numDataItems; - dest->allocatedData = 1; - - } else if (copyDepth == MPR_SHALLOW_COPY) { - dest->properties = src->properties; - adjustVarRefCount(src, 1); - dest->allocatedData = 1; - - } else { - dest->properties = src->properties; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_FUNCTION: - if (copyDepth != MPR_NO_COPY) { - dest->function.args = mprCreateArray(); - srcArgs = (char**) src->function.args->handles; - for (i = 0; i < src->function.args->max; i++) { - if (srcArgs[i]) { - mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); - } - } - dest->function.body = mprStrdup(src->function.body); - dest->allocatedData = 1; - } else { - dest->function.args = src->function.args; - dest->function.body = src->function.body; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_STRING: - if (src->string && copyDepth != MPR_NO_COPY) { - dest->string = mprStrdup(src->string); - dest->allocatedData = 1; - } else { - dest->string = src->string; - dest->allocatedData = 0; - } - break; - } - - dest->type = src->type; - dest->flags = src->flags; - dest->trigger = saveTrigger; - - /* - * Just for safety - */ - dest->spare = 0; -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) -{ - mprAssert(dest); - mprAssert(src); - - copyVarCore(dest, src, copyDepth); - - mprFree(dest->name); - dest->name = mprStrdup(src->name); - -#if VAR_DEBUG - if (src->type == MPR_TYPE_OBJECT) { - - mprFree(dest->fullName); - dest->fullName = mprStrdup(src->fullName); - - mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", - dest->name, dest->fullName, dest->properties, - dest->properties->refCount); - } -#endif -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) -{ - mprAssert(dest); - - mprCopyVar(dest, &src, copyDepth); -} - -/******************************************************************************/ -/* - * Copy an object. This implements copy by reference for objects and copy by - * value for strings and other types. Caller must free dest prior to calling. - */ - -MprVar *mprDupVar(MprVar *src, int copyDepth) -{ - MprVar *dest; - - mprAssert(src); - - dest = (MprVar*) mprMalloc(sizeof(MprVar)); - memset(dest, 0, sizeof(MprVar)); - - mprCopyVar(dest, src, copyDepth); - return dest; -} - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - * FUTURE -- conver this to use the format string in all cases. Allow - * arbitrary format strings. - */ - -void mprVarToString(char** out, int size, char *fmt, MprVar *obj) -{ - char *src; - - mprAssert(out); - - *out = NULL; - - if (obj->trigger) { - mprReadProperty(obj, 0); - } - - switch (obj->type) { - case MPR_TYPE_UNDEFINED: - /* FUTURE -- spec says convert to "undefined" */ - *out = mprStrdup(""); - break; - - case MPR_TYPE_NULL: - *out = mprStrdup("null"); - break; - - case MPR_TYPE_PTR: - mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); - break; - - case MPR_TYPE_BOOL: - if (obj->boolean) { - *out = mprStrdup("true"); - } else { - *out = mprStrdup("false"); - } - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%f", obj->floating); - } else { - mprAllocSprintf(out, size, fmt, obj->floating); - } - break; -#endif - - case MPR_TYPE_INT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%d", obj->integer); - } else { - mprAllocSprintf(out, size, fmt, obj->integer); - } - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - if (fmt == NULL || *fmt == '\0') { -#if BLD_GOAHEAD_WEBSERVER - mprAllocSprintf(out, size, "%d", (int) obj->integer64); -#else - mprAllocSprintf(out, size, "%Ld", obj->integer64); -#endif - } else { - mprAllocSprintf(out, size, fmt, obj->integer64); - } - break; -#endif - - case MPR_TYPE_CFUNCTION: - mprAllocSprintf(out, size, "[C Function]"); - break; - - case MPR_TYPE_STRING_CFUNCTION: - mprAllocSprintf(out, size, "[C StringFunction]"); - break; - - case MPR_TYPE_FUNCTION: - mprAllocSprintf(out, size, "[JavaScript Function]"); - break; - - case MPR_TYPE_OBJECT: - /* FUTURE -- really want: [object class: name] */ - mprAllocSprintf(out, size, "[object %s]", obj->name); - break; - - case MPR_TYPE_STRING: - src = obj->string; - - mprAssert(src); - if (fmt && *fmt) { - mprAllocSprintf(out, size, fmt, src); - - } else if (src == NULL) { - *out = mprStrdup("null"); - - } else { - *out = mprStrdup(src); - } - break; - - default: - mprAssert(0); - } -} - -/******************************************************************************/ -/* - * Parse a string based on formatting instructions and intelligently - * create a variable. - */ - -MprVar mprParseVar(char *buf, MprType preferredType) -{ - MprType type = MPR_TYPE_UNDEFINED; - char *cp; - - mprAssert(buf); - - if (preferredType == MPR_TYPE_UNDEFINED) { - if (*buf == '-') { - type = MPR_NUM_VAR; - - } else if (!isdigit((int) *buf)) { - if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { - type = MPR_TYPE_BOOL; - } else { - type = MPR_TYPE_STRING; - } - - } else if (isdigit((int) *buf)) { - type = MPR_NUM_VAR; - cp = buf; - if (*cp && tolower((unsigned char)cp[1]) == 'x') { - cp = &cp[2]; - } - for (cp = buf; *cp; cp++) { - if (! isdigit((unsigned char) *cp)) { - break; - } - } - - if (*cp != '\0') { -#if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { - type = MPR_TYPE_FLOAT; - } else -#endif - { - type = MPR_NUM_VAR; - } - } - } - } else { - type = preferredType; - } - - switch (type) { - case MPR_TYPE_OBJECT: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_PTR: - default: - break; - - case MPR_TYPE_BOOL: - return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); - - case MPR_TYPE_INT: - return mprCreateIntegerVar(mprParseInteger(buf)); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return mprCreateInteger64Var(mprParseInteger64(buf)); -#endif - - case MPR_TYPE_STRING: - if (strcmp(buf, "null") == 0) { - return mprCreateNullVar(); - } else if (strcmp(buf, "undefined") == 0) { - return mprCreateUndefinedVar(); - } - - return mprCreateStringVar(buf, 1); - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return mprCreateFloatVar(atof(buf)); -#endif - - } - return mprCreateUndefinedVar(); -} - -/******************************************************************************/ -/* - * Convert the variable to a boolean. Only for primitive types. - */ - -bool mprVarToBool(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - return 0; - - case MPR_TYPE_PTR: - return (vp->ptr != NULL); - - case MPR_TYPE_BOOL: - return vp->boolean; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return (vp->floating != 0 && !mprIsNan(vp->floating)); -#endif - - case MPR_TYPE_INT: - return (vp->integer != 0); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (vp->integer64 != 0); -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return (vp->string[0] != '\0'); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the variable to a floating point number. Only for primitive types. - */ - -double mprVarToFloat(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1.0 : 0.0; - - case MPR_TYPE_FLOAT: - return vp->floating; - - case MPR_TYPE_INT: - return (double) vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (double) vp->integer64; -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return atof(vp->string); - } - - /* Not reached */ - return 0; -} - -#endif -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprVarToNumber(const MprVar *vp) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprVarToInteger64(vp); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprVarToFloat(vp); -#else - return mprVarToInteger(vp); -#endif -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprParseNumber(char *s) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprParseInteger64(s); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprParseFloat(s); -#else - return mprParseInteger(s); -#endif -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the variable to an Integer64 type. Only works for primitive types. - */ - -int64 mprVarToInteger64(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int64) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - - case MPR_TYPE_INT64: - return vp->integer64; - - case MPR_TYPE_STRING: - return mprParseInteger64(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer64. - */ - -int64 mprParseInteger64(char *str) -{ - char *cp; - int64 num64; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num64 = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num64 = (*cp - '0') + (num64 * 10); - cp++; - } - } else { - cp++; - if (tolower((unsigned char)*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c)) { - num64 = (c - '0') + (num64 * radix); - } else if (c >= 'a' && c <= 'f') { - num64 = (c - 'a') + (num64 * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c) && c < '8') { - num64 = (c - '0') + (num64 * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num64; - } - return num64; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the variable to an Integer type. Only works for primitive types. - */ - -int mprVarToInteger(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (int) vp->integer64; -#endif - - case MPR_TYPE_STRING: - return mprParseInteger(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer. - */ - -int mprParseInteger(char *str) -{ - char *cp; - int num; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num = (*cp - '0') + (num * 10); - cp++; - } - } else { - cp++; - if (tolower((unsigned char)*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c)) { - num = (c - '0') + (num * radix); - } else if (c >= 'a' && c <= 'f') { - num = (c - 'a') + (num * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c) && c < '8') { - num = (c - '0') + (num * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num; - } - return num; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the string buffer to an Floating. - */ - -double mprParseFloat(char *str) -{ - return atof(str); -} - -/******************************************************************************/ - -bool mprIsNan(double f) -{ -#if WIN - return _isnan(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_NAN); -#endif -} -/******************************************************************************/ - -bool mprIsInfinite(double f) -{ -#if WIN - return !_finite(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_INFINITE); -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/ejs/var.h b/source4/lib/ejs/var.h deleted file mode 100644 index 8ed13a4995..0000000000 --- a/source4/lib/ejs/var.h +++ /dev/null @@ -1,496 +0,0 @@ -/* - * @file var.h - * @brief MPR Universal Variable Type - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ -/* - * Variables can efficiently store primitive types and can hold references to - * objects. Objects can store properties which are themselves variables. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. A variable may store one of - * the following types: - * - * string, integer, integer-64bit, C function, C function with string args, - * Javascript function, Floating point number, boolean value, Undefined - * value and the Null value. - * - * Variables have names while objects may be referenced by multiple variables. - * Objects use reference counting for garbage collection. - * - * This module is not thread safe for performance and compactness. It relies - * on upper modules to provide thread synchronization as required. The API - * provides primitives to get variable/object references or to get copies of - * variables which will help minimize required lock times. - */ - -#ifndef _h_MPR_VAR -#define _h_MPR_VAR 1 - -/********************************* Includes ***********************************/ - -#include "miniMpr.h" - -/********************************** Defines ***********************************/ - -/* - * Define VAR_DEBUG if you want to track objects. However, this code is not - * thread safe and you need to run the server single threaded. - * - * #define VAR_DEBUG 1 - */ - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Forward declare types - */ -struct MprProperties; -struct MprVar; - -/* - * Possible variable types. Don't use enum because we need to be able to - * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. - */ -typedef int MprType; -#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ -#define MPR_TYPE_NULL 1 /* Value defined to be null. */ -#define MPR_TYPE_BOOL 2 /* Boolean type. */ -#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ -#define MPR_TYPE_FLOAT 4 /* Floating point number */ -#define MPR_TYPE_INT 5 /* Integer number */ -#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ -#define MPR_TYPE_OBJECT 7 /* Object reference */ -#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ -#define MPR_TYPE_STRING 9 /* String (immutable) */ -#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ -#define MPR_TYPE_PTR 11 /* Opaque pointer */ - -/* - * Create a type for the default number type - * Config.h will define the default number type. For example: - * - * BLD_FEATURE_NUM_TYPE=int - * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT - */ - -/** - * Set to the type used for MPR numeric variables. Will equate to int, int64 - * or double. - */ -typedef BLD_FEATURE_NUM_TYPE MprNum; - -/** - * Set to the MPR_TYPE used for MPR numeric variables. Will equate to - * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. - */ -#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID -#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID - -/* - * Return TRUE if a variable is a function type - */ -#define mprVarIsFunction(type) \ - (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ - type == MPR_TYPE_CFUNCTION) - -/* - * Return TRUE if a variable is a numeric type - */ -#define mprVarIsNumber(type) \ - (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) - -/* - * Return TRUE if a variable is a boolean - */ -#define mprVarIsBoolean(type) \ - (type == MPR_TYPE_BOOL) -#define mprVarIsString(type) \ - (type == MPR_TYPE_STRING) -#define mprVarIsObject(type) \ - (type == MPR_TYPE_OBJECT) -#define mprVarIsFloating(type) \ - (type == MPR_TYPE_FLOAT) -#define mprVarIsPtr(type) \ - (type == MPR_TYPE_PTR) -#define mprVarIsUndefined(var) \ - ((var)->type == MPR_TYPE_UNDEFINED) -#define mprVarIsNull(var) \ - ((var)->type == MPR_TYPE_NULL) -#define mprVarIsValid(var) \ - (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) - -#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ - -#if BLD_FEATURE_SQUEEZE -#define MPR_MAX_VAR 64 /* Max var full name */ -#else -#define MPR_MAX_VAR 512 -#endif - -#ifndef __NO_PACK -#pragma pack(2) -#endif /* _NO_PACK */ - -/* - * Function signatures - */ -typedef int MprVarHandle; -typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, - struct MprVar **argv); -typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, - char **argv); - -/* - * Triggers - */ -typedef enum { - MPR_VAR_WRITE, /* This property is being updated */ - MPR_VAR_READ, /* This property is being read */ - MPR_VAR_CREATE_PROPERTY, /* A property is being created */ - MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ - MPR_VAR_DELETE /* This object is being deleted */ -} MprVarTriggerOp; - -/* - * Trigger function return codes. - */ -typedef enum { - MPR_TRIGGER_ABORT, /* Abort the current operation */ - MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ - MPR_TRIGGER_PROCEED /* Proceed with the operation */ -} MprVarTriggerStatus; - -/* - * The MprVarTrigger arguments have the following meaning: - * - * op The operation being performed. See MprVarTriggerOp. - * parentProperties Pointer to the MprProperties structure. - * vp Pointer to the property that registered the trigger. - * newValue New value (see below for more details). - * copyDepth Specify what data items to copy. - * - * For VAR_READ, newVar is set to a temporary variable that the trigger - * function may assign a value to be returned instead of the actual - * property value. - * For VAR_WRITE, newValue holds the new value. The old existing value may be - * accessed via vp. - * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. - * For ADD_PROPERTY, vp is set to the property being added and newValue holds - * the new value. - */ -typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, - struct MprProperties *parentProperties, struct MprVar *vp, - struct MprVar *newValue, int copyDepth); - -/* - * mprCreateFunctionVar flags - */ -/** Use the alternate handle on function callbacks */ -#define MPR_VAR_ALT_HANDLE 0x1 - -/** Use the script handle on function callbacks */ -#define MPR_VAR_SCRIPT_HANDLE 0x2 - -/* - * Useful define for the copyDepth argument - */ -/** Don't copy any data. Copy only the variable name */ -#define MPR_NO_COPY 0 - -/** Copy strings. Increment object reference counts. */ -#define MPR_SHALLOW_COPY 1 - -/** Copy strings and do complete object copies. */ -#define MPR_DEEP_COPY 2 - -/* - * GetFirst / GetNext flags - */ -/** Step into data properties. */ -#define MPR_ENUM_DATA 0x1 - -/** Step into functions properties. */ -#define MPR_ENUM_FUNCTIONS 0x2 - -/* - * Collection type to hold properties in an object - */ -typedef struct MprProperties { /* Collection of properties */ -#if VAR_DEBUG - struct MprProperties *next; /* Linked list */ - struct MprProperties *prev; /* Linked list */ - char name[32]; /* Debug name */ -#endif - struct MprVar **buckets; /* Hash chains */ - int numItems; /* Total count of items */ - /* FUTURE - Better way of doing this */ - int numDataItems; /* Enumerable data items */ - uint hashSize : 8; /* Size of the hash table */ - /* FUTURE -- increase size of refCount */ - uint refCount : 8; /* References to this property*/ - /* FUTURE - make these flags */ - uint deleteProtect : 8; /* Don't recursively delete */ - uint visited : 8; /* Node has been processed */ -} MprProperties; - -/* - * Universal Variable Type - */ -typedef struct MprVar { - /* FUTURE - remove name to outside reference */ - MprStr name; /* Property name */ - /* FUTURE - remove */ - MprStr fullName; /* Full object name */ - /* FUTURE - make part of the union */ - MprProperties *properties; /* Pointer to properties */ - - /* - * Packed bit field - */ - MprType type : 8; /* Selector into union */ - uint bucketIndex : 8; /* Copy of bucket index */ - - uint flags : 5; /* Type specific flags */ - uint allocatedData : 1; /* Data needs freeing */ - uint readonly : 1; /* Unmodifiable */ - uint deleteProtect : 1; /* Don't recursively delete */ - - uint visited : 1; /* Node has been processed */ - uint allocatedVar : 1; /* Var needs freeing */ - uint spare : 6; /* Unused */ - - struct MprVar *forw; /* Hash table linkage */ - MprVarTrigger trigger; /* Trigger function */ - -#if UNUSED && KEEP - struct MprVar *baseClass; /* Pointer to class object */ -#endif - MprProperties *parentProperties; /* Pointer to parent object */ - - /* - * Union of primitive types. When debugging on Linux, don't use unions - * as the gdb debugger can't display them. - */ -#if !BLD_DEBUG && !LINUX && !VXWORKS - union { -#endif - int boolean; /* Use int for speed */ -#if BLD_FEATURE_FLOATING_POINT - double floating; -#endif - int integer; -#if BLD_FEATURE_INT64 - int64 integer64; -#endif - struct { /* Javascript functions */ - MprArray *args; /* Null terminated */ - char *body; - } function; - struct { /* Function with MprVar args */ - MprCFunction fn; - void *thisPtr; - } cFunction; - struct { /* Function with string args */ - MprStringCFunction fn; - void *thisPtr; - } cFunctionWithStrings; - MprStr string; /* Allocated string */ - void *ptr; /* Opaque pointer */ -#if !BLD_DEBUG && !LINUX && !VXWORKS - }; -#endif -} MprVar; - -/* - * Define a field macro so code an use numbers in a "generic" fashion. - */ -#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN -/* Default numeric type */ -#define mprNumber integer -#endif -#if MPR_NUM_VAR == MPR_TYPE_INT64 -/* Default numeric type */ -#define mprNumber integer64 -#endif -#if MPR_NUM_VAR == MPR_TYPE_FLOAT -/* Default numeric type */ -#define mprNumber floating -#endif - -typedef BLD_FEATURE_NUM_TYPE MprNumber; - - -#ifndef __NO_PACK -#pragma pack() -#endif /* __NO_PACK */ - -/********************************* Prototypes *********************************/ -/* - * Variable constructors and destructors - */ -extern MprVar mprCreateObjVar(const char *name, int hashSize); -extern MprVar mprCreateBoolVar(bool value); -extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, - int flags); -#if BLD_FEATURE_FLOATING_POINT -extern MprVar mprCreateFloatVar(double value); -#endif -extern MprVar mprCreateIntegerVar(int value); -#if BLD_FEATURE_INT64 -extern MprVar mprCreateInteger64Var(int64 value); -#endif -extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); -extern MprVar mprCreateNullVar(void); -extern MprVar mprCreateNumberVar(MprNumber value); -extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, - void *thisPtr, int flags); -extern MprVar mprCreateStringVar(const char *value, bool allocate); -extern MprVar mprCreateUndefinedVar(void); -extern MprVar mprCreatePtrVar(void *ptr); -extern bool mprDestroyVar(MprVar *vp); -extern bool mprDestroyAllVars(MprVar* vp); -extern MprType mprGetVarType(MprVar *vp); - -/* - * Copy - */ -extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); -extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); -extern MprVar *mprDupVar(MprVar *src, int copyDepth); - -/* - * Manage vars - */ -extern MprVarTrigger - mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); -extern int mprGetVarRefCount(MprVar *vp); -extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); -extern void mprSetVarFullName(MprVar *vp, char *name); -extern void mprSetVarReadonly(MprVar *vp, int readonly); -extern void mprSetVarName(MprVar *vp, char *name); - -/* - * Create properties and return a reference to the property. - */ -extern MprVar *mprCreateProperty(MprVar *obj, const char *property, - MprVar *newValue); -extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, - MprVar newValue); -extern int mprDeleteProperty(MprVar *obj, const char *property); - -/* - * Get/Set properties. Set will update/create. - */ -extern MprVar *mprGetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, - MprVar value); - -/* - * Directly read/write property values (the property must already exist) - * For mprCopyProperty, mprDestroyVar must always called on the var. - */ -extern int mprReadProperty(MprVar *prop, MprVar *value); -extern int mprWriteProperty(MprVar *prop, MprVar *newValue); -extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); - -/* - * Copy a property. NOTE: reverse of most other args: (dest, src) - */ -extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); - -/* - * Enumerate properties - */ -extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); -extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags); - -/* - * Query properties characteristics - */ -extern int mprGetPropertyCount(MprVar *obj, int includeFlags); - -/* - * Conversion routines - */ -extern MprVar mprParseVar(char *str, MprType prefType); -extern MprNum mprVarToNumber(const MprVar *vp); -extern int mprVarToInteger(const MprVar *vp); -#if BLD_FEATURE_INT64 -extern int64 mprVarToInteger64(const MprVar *vp); -#endif -extern bool mprVarToBool(const MprVar *vp); -#if BLD_FEATURE_FLOATING_POINT -extern double mprVarToFloat(const MprVar *vp); -#endif -extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); - -/* - * Parsing and utility routines - */ -extern MprNum mprParseNumber(char *str); -extern int mprParseInteger(char *str); - -#if BLD_FEATURE_INT64 -extern int64 mprParseInteger64(char *str); -#endif - -#if BLD_FEATURE_FLOATING_POINT -extern double mprParseFloat(char *str); -extern bool mprIsInfinite(double f); -extern bool mprIsNan(double f); -#endif - -#if VAR_DEBUG -extern void mprPrintObjects(char *msg); -extern void mprPrintObjRefCount(MprVar *vp); -#endif - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ -#endif /* _h_MPR_VAR */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ -- cgit From a102f52db89f8a31327a3a9fafa1e5a1699ca3cd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 00:12:22 +0000 Subject: r8400: separate out the mpr code, as it is in the upstream appweb sources (This used to be commit 0e30b6e4cc9e70975d3179cfeddc4bfcc8c8fbb7) --- source4/lib/appweb/config.mk | 16 +- source4/lib/appweb/ejs/ejs.h | 4 +- source4/lib/appweb/ejs/miniMpr.c | 512 --------- source4/lib/appweb/ejs/miniMpr.h | 292 ----- source4/lib/appweb/ejs/var.c | 2197 -------------------------------------- source4/lib/appweb/ejs/var.h | 496 --------- source4/lib/appweb/esp/esp.h | 4 +- source4/lib/appweb/mpr/miniMpr.c | 512 +++++++++ source4/lib/appweb/mpr/miniMpr.h | 292 +++++ source4/lib/appweb/mpr/var.c | 2197 ++++++++++++++++++++++++++++++++++++++ source4/lib/appweb/mpr/var.h | 496 +++++++++ 11 files changed, 3514 insertions(+), 3504 deletions(-) delete mode 100644 source4/lib/appweb/ejs/miniMpr.c delete mode 100644 source4/lib/appweb/ejs/miniMpr.h delete mode 100644 source4/lib/appweb/ejs/var.c delete mode 100644 source4/lib/appweb/ejs/var.h create mode 100644 source4/lib/appweb/mpr/miniMpr.c create mode 100644 source4/lib/appweb/mpr/miniMpr.h create mode 100644 source4/lib/appweb/mpr/var.c create mode 100644 source4/lib/appweb/mpr/var.h (limited to 'source4/lib') diff --git a/source4/lib/appweb/config.mk b/source4/lib/appweb/config.mk index 7d1eca3437..1a73d6834a 100644 --- a/source4/lib/appweb/config.mk +++ b/source4/lib/appweb/config.mk @@ -1,3 +1,14 @@ +####################### +# Start SUBSYSTEM MPR +[SUBSYSTEM::MPR] +ADD_OBJ_FILES = \ + lib/appweb/mpr/miniMpr.o \ + lib/appweb/mpr/var.o +NOPROTO=YES +# End SUBSYSTEM MPR +####################### + + ####################### # Start SUBSYSTEM EJS [SUBSYSTEM::EJS] @@ -5,9 +16,8 @@ ADD_OBJ_FILES = \ lib/appweb/ejs/ejsLib.o \ lib/appweb/ejs/ejsLex.o \ lib/appweb/ejs/ejsParser.o \ - lib/appweb/ejs/ejsProcs.o \ - lib/appweb/ejs/miniMpr.o \ - lib/appweb/ejs/var.o + lib/appweb/ejs/ejsProcs.o +REQUIRED_SUBSYSTEMS = MPR NOPROTO=YES # End SUBSYSTEM EJS ####################### diff --git a/source4/lib/appweb/ejs/ejs.h b/source4/lib/appweb/ejs/ejs.h index f1d2bb4c6e..5efdb47192 100644 --- a/source4/lib/appweb/ejs/ejs.h +++ b/source4/lib/appweb/ejs/ejs.h @@ -44,8 +44,8 @@ #ifndef _h_EJS #define _h_EJS 1 -#include "miniMpr.h" -#include "var.h" +#include "lib/appweb/mpr/miniMpr.h" +#include "lib/appweb/mpr/var.h" #ifdef __cplusplus extern "C" { diff --git a/source4/lib/appweb/ejs/miniMpr.c b/source4/lib/appweb/ejs/miniMpr.c deleted file mode 100644 index 7dda4e7bd7..0000000000 --- a/source4/lib/appweb/ejs/miniMpr.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * @file miniMpr.cpp - * @brief Mini Mbedthis Portable Runtime (MPR) - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "lib/appweb/ejs/miniMpr.h" - -/************************************ Code ************************************/ -#if !BLD_APPWEB -#if !BLD_GOAHEAD_WEBSERVER - -static void *mpr_ctx; - -/* set the memory context to be used for all ejs variables */ -void mprSetCtx(TALLOC_CTX *ctx) -{ - mpr_ctx = ctx; -} - -/* return the memory context being used for all ejs variables */ -void *mprMemCtx(void) -{ - return mpr_ctx; -} - -void mprFree(void *ptr) -{ - talloc_free(ptr); -} - -void *mprMalloc(uint size) -{ - return talloc_size(mpr_ctx, size); -} - -/******************************************************************************/ - -void *mprRealloc(void *ptr, uint size) -{ - return talloc_realloc_size(mpr_ctx, ptr, size); -} - -/******************************************************************************/ - -char *mprStrdup(const char *str) -{ - if (str == 0) { - str = ""; - } - return talloc_strdup(mpr_ctx, str); -} - -/*****************************************************************************/ - -int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) -{ - va_list args; - char *buf; - int count; - - va_start(args, fmt); - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - va_end(args); - return count; -} - -/*****************************************************************************/ - -int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) -{ - char *buf; - int count; - - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - return count; -} - - -/*****************************************************************************/ -/* - * Format a number as a string. FUTURE -- reverse args to be standard. - * ie. mprItoa(char *userBuf, int bufsize, int value); - */ - -char *mprItoa(int value, char *buf, int width) -{ - char numBuf[16]; - char *cp, *dp, *endp; - int negative; - - cp = &numBuf[sizeof(numBuf)]; - *--cp = '\0'; - - if (value < 0) { - negative = 1; - value = -value; - width--; - } else { - negative = 0; - } - - do { - *--cp = '0' + (value % 10); - value /= 10; - } while (value > 0); - - if (negative) { - *--cp = '-'; - } - - dp = buf; - endp = &buf[width]; - while (dp < endp && *cp) { - *dp++ = *cp++; - } - *dp++ = '\0'; - return buf; -} - -/*****************************************************************************/ - -void mprLog(int level, const char *fmt, ...) -{ - va_list args; - char *buf; - - if (DEBUGLVL(level)) { - va_start(args, fmt); - mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); - va_end(args); - DEBUG(level, ("mprLog: %s", buf)); - mprFree(buf); - } -} - -/*****************************************************************************/ - -void mprBreakpoint(const char *file, int line, const char *cond) -{ - char *buf; - mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", - file, line, cond); - ejs_exception(buf); -} - -#endif /* !BLD_GOAHEAD_WEBSERVER */ -/*****************************************************************************/ -/* - * Create a general growable array structure - */ - -MprArray *mprCreateArray() -{ - MprArray *array; - int size; - - array = (MprArray*) mprMalloc(sizeof(MprArray)); - if (array == 0) { - return 0; - } - memset(array, 0, sizeof(MprArray)); - - size = MPR_ARRAY_INCR * sizeof(void*); - array->handles = (void**) mprMalloc(size); - if (array->handles == 0) { - mprFree(array); - return 0; - } - memset(array->handles, 0, size); - array->max = MPR_ARRAY_INCR; - array->used = 0; - return array; -} - -/*****************************************************************************/ -/* - * Dispose of the array. Callers responsibility to dispose of handle entries. - */ - -void mprDestroyArray(MprArray *array) -{ - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - mprFree(array->handles); - mprFree(array); -} - -/*****************************************************************************/ -/* - * Add an item to the array - */ - -int mprAddToArray(MprArray *array, void *item) -{ - int memsize, idx, len; - - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - if (array->used < array->max) { - idx = array->used++; - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - - for (idx = array->used; idx < array->max; idx++) { - if (array->handles[idx] == 0) { - array->used++; - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - } - - len = array->max + MPR_ARRAY_INCR; - memsize = len * sizeof(void*); - array->handles = (void**) mprRealloc((void*) array->handles, memsize); - if (array->handles == NULL) { - return -1; - } - memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); - array->max = len; - array->used++; - - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - - array->handles[idx] = item; - return idx; -} - -/*****************************************************************************/ -/* - * Remove from the array - */ - -int mprRemoveFromArray(MprArray *array, int idx) -{ - mprAssert(array); - mprAssert(array->max > 0); - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] != 0); - mprAssert(array->used > 0); - - array->handles[idx] = 0; - return --array->used; -} - -/*****************************************************************************/ -/* - * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() - */ - -char *mprStrTok(char *str, const char *delim, char **tok) -{ - char *start, *end; - int i; - - start = str ? str : *tok; - - if (start == 0) { - return 0; - } - - i = strspn(start, delim); - start += i; - if (*start == '\0') { - *tok = 0; - return 0; - } - end = strpbrk(start, delim); - if (end) { - *end++ = '\0'; - i = strspn(end, delim); - end += i; - } - *tok = end; - return start; -} - -/*****************************************************************************/ - -static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, - const char *delim, const char *src, va_list args) -{ - va_list ap; - char *dest, *dp; - const char *str; - int sepLen, addBytes, required; - - mprAssert(destp); - mprAssert(destMax > 0); - mprAssert(src); - - dest = *destp; - sepLen = (delim) ? strlen(delim) : 0; - -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - addBytes = 0; - str = src; - while (str) { - addBytes += strlen(str) + sepLen; - str = va_arg(ap, const char*); - } - - if (existingLen > 0) { - addBytes += sepLen; - } - required = existingLen + addBytes + 1; - if (required >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - - if (alloc) { - if (dest == 0) { - dest = (char*) mprMalloc(required); - } else { - dest = (char*) mprRealloc(dest, required); - } - } else { - dest = (char*) *destp; - } - - dp = &dest[existingLen]; - if (delim) { - strcpy(dp, delim); - dp += sepLen; - } - - if (addBytes > 0) { -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - str = src; - while (str) { - strcpy(dp, str); - dp += strlen(str); - str = va_arg(ap, char*); - if (delim && str) { - strcpy(dp, delim); - dp += sepLen; - } - } - } else if (dest == 0) { - dest = (char*) mprMalloc(1); - } - *dp = '\0'; - - *destp = dest; - mprAssert(dp < &dest[required]); - return required - 1; -} - -/*****************************************************************************/ - -int mprReallocStrcat(char **destp, int destMax, int existingLen, - const char *delim, const char *src,...) -{ - va_list ap; - int rc; - - va_start(ap, src); - rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); - va_end(ap); - return rc; -} - -/*****************************************************************************/ -/* - * Return the directory portion of a pathname into the users buffer. - */ - -int mprGetDirName(char *buf, int bufsize, char *path) -{ - char *cp; - int dlen; - - mprAssert(path); - mprAssert(buf); - mprAssert(bufsize > 0); - - cp = strrchr(path, '/'); - if (cp == 0) { -#if WIN - cp = strrchr(path, '\\'); - if (cp == 0) -#endif - { - buf[0] = '\0'; - return 0; - } - } - - if (cp == path && cp[1] == '\0') { - strcpy(buf, "."); - return 0; - } - - dlen = cp - path; - if (dlen < bufsize) { - if (dlen == 0) { - dlen++; - } - mprMemcpy(buf, bufsize, path, dlen); - buf[dlen] = '\0'; - return 0; - } - return MPR_ERR_WONT_FIT; -} - -/*****************************************************************************/ - -int mprStrcpy(char *dest, int destMax, const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax > 0); - mprAssert(src); - - len = strlen(src); - if (len >= destMax && len > 0) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - memcpy(dest, src, len); - dest[len] = '\0'; - } else { - *dest = '\0'; - len = 0; - } - return len; -} - -/*****************************************************************************/ - -int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) -{ - mprAssert(dest); - mprAssert(destMax > nbytes); - mprAssert(src); - mprAssert(nbytes > 0); - - if (nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - memcpy(dest, src, nbytes); - return nbytes; - } else { - return 0; - } -} - -/*****************************************************************************/ -#else -void miniMprDummy() {} -#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/miniMpr.h b/source4/lib/appweb/ejs/miniMpr.h deleted file mode 100644 index d431ebdc1b..0000000000 --- a/source4/lib/appweb/ejs/miniMpr.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * @file miniMpr.h - * @brief Mini Mbedthis Portable Runtime (MPR) Environment. - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -#ifndef _h_MINI_MPR -#define _h_MINI_MPR 1 - -/********************************** Includes **********************************/ -/* - * Find out about our configuration - */ -#ifndef _INCLUDES_H - #include "includes.h" -#endif - -/* allow this library to use strcpy() */ -#undef strcpy - #include "config.h" - -#if BLD_APPWEB - /* - * If building within AppWeb, use the full MPR - */ - #include "mpr.h" -#else - - #include - #include - #include - #include - #include - #include - #include - -#if !WIN - #include -#endif - -#if CE - #include - #include "CE/wincompat.h" -#endif - -#if LYNX - #include -#endif - -#if QNX4 - #include -#endif - #include - -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#if BLD_FEATURE_SQUEEZE -/* - * Reasonable length of a file path name to use in most cases where you know - * the expected file name and it is certain to be less than this limit. - */ -#define MPR_MAX_FNAME 128 -#define MPR_MAX_STRING 512 -#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (32 * 1024) -#else -#define MPR_MAX_FNAME 256 -#define MPR_MAX_STRING 4096 -#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (64 * 1024) -#endif - -/* - * Useful for debugging - */ -#define MPR_L __FILE__, __LINE__ - -#if BLD_FEATURE_ASSERT -#define mprAssert(C) \ - if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) -#else - #define mprAssert(C) if (1) ; else -#endif - -/* - * Standard MPR return and error codes - */ -#define MPR_ERR_BASE (-200) /* Error code */ -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ -#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ - -/* - * Standard error severity and trace levels. These are ored with the error - * severities below. The MPR_LOG_MASK is used to extract the trace level - * from a flags word. We expect most apps to run with level 2 trace. - */ -#define MPR_FATAL 0 /* Fatal error. Cant continue. */ -#define MPR_ERROR 1 /* Hard error */ -#define MPR_WARN 2 /* Soft warning */ -#define MPR_CONFIG 2 /* Essential configuration settings */ -#define MPR_INFO 3 /* Informational only */ -#define MPR_DEBUG 4 /* Debug information */ -#define MPR_VERBOSE 9 /* Highest level of trace */ -#define MPR_LOG_MASK 0xf /* Level mask */ - -/* - * Error flags. Specify where the error should be sent to. Note that the - * product.xml setting "headless" will modify how errors are reported. - * Assert errors are trapped when in DEV mode. Otherwise ignored. - */ -#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ -#define MPR_LOG 0x20 /* Log the error in the O/S event log */ -#define MPR_USER 0x40 /* Display to the user */ -#define MPR_ALERT 0x80 /* Send a management alert */ -#define MPR_TRACE 0x100 /* Trace */ - -/* - * Error format flags - */ -#define MPR_RAW 0x200 /* Raw trace output */ - -/* - * Error line number information - */ -#define MPR_L __FILE__, __LINE__ - -typedef char* MprStr; - -#ifndef __cplusplus -typedef unsigned char uchar; -typedef int bool; -#endif - -/* - * Porters: put other operating system type defines here - */ -#if WIN - typedef unsigned int uint; - typedef __int64 int64; - typedef unsigned __int64 uint64; -#else -#define O_BINARY 0 -#ifndef uint - #define uint unsigned -#endif - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; -#endif - -/* - * Flexible array data type - */ -typedef struct { - int max; /* Size of the handles array */ - int used; /* Count of used entries in handles */ - void **handles; -} MprArray; - -#if BLD_FEATURE_SQUEEZE -#define MPR_ARRAY_INCR 8 -#else -#define MPR_ARRAY_INCR 16 -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -/********************************* Prototypes *********************************/ -/* - * If running in the GoAhead WebServer, map some MPR routines to WebServer - * equivalents. - */ - -#if BLD_GOAHEAD_WEBSERVER -#include "uemf.h" -#define mprMalloc(size) balloc(B_L, size) -#define mprFree(ptr) bfreeSafe(B_L, ptr) -#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) -#define mprStrdup(ptr) bstrdup(B_L, ptr) -#define mprAllocSprintf fmtAlloc -#define mprAllocVsprintf fmtValloc -#define mprSprintf fmtStatic -#define mprItoa stritoa -#define mprLog trace -#define mprBreakpoint(file, line, cond) \ - error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) - -#else /* !BLD_GOAHEAD_WEBSERVER */ -/* #define mprMalloc malloc */ -#define mprSprintf snprintf -#define mtVsprintf vsnprintf -extern void *mprMalloc(uint size); -extern void *mprRealloc(void *ptr, uint size); -extern void mprFree(void *ptr); -extern char *mprStrdup(const char *str); -extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, - va_list args) PRINTF_ATTRIBUTE(3,0); -extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern char *mprItoa(int num, char *buf, int width); -extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -extern void mprBreakpoint(const char *file, int line, const char *msg); -#endif /* BLD_GOAHEAD_WEBSERVER */ - -extern MprArray *mprCreateArray(void); -extern void mprDestroyArray(MprArray *array); -extern int mprAddToArray(MprArray *array, void *item); -extern int mprRemoveFromArray(MprArray *array, int idx); -extern char *mprStrTok(char *str, const char *delim, char **tok); - -extern int mprGetDirName(char *buf, int bufsize, char *path); -extern int mprReallocStrcat(char **dest, int max, int existingLen, - const char *delim, const char *src, ...); -extern int mprStrcpy(char *dest, int destMax, const char *src); -extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); - -extern void mprSetCtx(void *ctx); -extern void *mprMemCtx(void); - -#ifdef __cplusplus -} -#endif -#endif /* !BLD_APPWEB */ -#endif /* _h_MINI_MPR */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/var.c b/source4/lib/appweb/ejs/var.c deleted file mode 100644 index 9d2afe5306..0000000000 --- a/source4/lib/appweb/ejs/var.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * @file var.c - * @brief MPR Universal Variable Type - * @overview - * - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This module is NOT multithreaded. - * - * Properties are variables that are stored in an object type variable. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. - */ - -/********************************** Includes **********************************/ - -#include "var.h" - -/*********************************** Locals ***********************************/ -#if VAR_DEBUG - -static MprProperties objectList; /* Dummy head of objects list */ -static int objectCount = -1; /* Count of objects */ - -#endif -/***************************** Forward Declarations ***************************/ - -static int adjustRefCount(MprProperties *pp, int adj); -static int adjustVarRefCount(MprVar *vp, int adj); -static MprVar *allocProperty(const char *propertyName); -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); -static MprProperties - *createProperties(const char *name, int hashSize); -static bool freeVar(MprVar *vp, int force); -static bool freeVarStorage(MprVar *vp, int force); -static MprVar *getObjChain(MprProperties *pp, const char *property); -static int hash(MprProperties *pp, const char *property); -static bool releaseProperties(MprProperties *pp, int force); - -/*********************************** Code *************************************/ -/* - * Destroy a variable and all referenced variables. Release any referenced - * object regardless of whether other users still have references. Be VERY - * careful using this routine. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyAllVars(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all vars. - */ - return freeVar(vp, 1); -} - -/******************************************************************************/ -/* - * Destroy a variable. Release any referenced object (destroy if no other - * users are referencing). - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyVar(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all that have no other - * references. - */ - return freeVar(vp, 0); -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVar(MprVar *vp, int force) -{ - bool freed; - - mprAssert(vp); - - freed = freeVarStorage(vp, force); - - mprFree(vp->name); - mprFree(vp->fullName); - - if (vp->allocatedVar) { - mprFree(vp); - } else { - vp->name = 0; - vp->fullName = 0; - vp->type = MPR_TYPE_UNDEFINED; - } - return freed; -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVarStorage(MprVar *vp, int force) -{ - MprArray *argList; - bool freed; - int i; - - freed = 1; - mprAssert(vp); - - switch (vp->type) { - default: - break; - - case MPR_TYPE_STRING: - if (vp->allocatedData && vp->string != 0) { - mprFree(vp->string); - vp->string = 0; - vp->allocatedData = 0; - } - break; - - case MPR_TYPE_OBJECT: -#if VAR_DEBUG - /* - * Recurse through all properties and release / delete. Release the - * properties hash table. - */ - if (vp->properties->refCount > 1) { - mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } else { - mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } -#endif - if (vp->allocatedData) { - freed = releaseProperties(vp->properties, force); - } - vp->properties = 0; - break; - - case MPR_TYPE_FUNCTION: - if (vp->allocatedData) { - argList = vp->function.args; - for (i = 0; i < argList->max; i++) { - if (argList->handles[i] != 0) { - mprFree(argList->handles[i]); - } - } - mprDestroyArray(argList); - vp->function.args = 0; - mprFree(vp->function.body); - vp->function.body = 0; - } - break; - } - - vp->type = MPR_TYPE_UNDEFINED; - return freed; -} - -/******************************************************************************/ -/* - * Adjust the object reference count and return the currrent count of - * users. - */ - -static int adjustVarRefCount(MprVar *vp, int adj) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, adj); -} - -/******************************************************************************/ -/* - * Get the object reference count - */ - -int mprGetVarRefCount(MprVar *vp) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, 0); -} - -/******************************************************************************/ -/* - * Update the variable's name - */ - -void mprSetVarName(MprVar *vp, char *name) -{ - mprAssert(vp); - - mprFree(vp->name); - vp->name = mprStrdup(name); -} - -/******************************************************************************/ -/* - * Append to the variable's full name - */ - -void mprSetVarFullName(MprVar *vp, char *name) -{ -#if VAR_DEBUG - mprAssert(vp); - - mprFree(vp->fullName); - vp->fullName = mprStrdup(name); - if (vp->type == MPR_TYPE_OBJECT) { - if (strcmp(vp->properties->name, "this") == 0) { - mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); - } - } -#endif -} - -/******************************************************************************/ -/* - * Make a var impervious to recursive forced deletes. - */ - -void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) -{ - mprAssert(vp); - - if (vp->type == MPR_TYPE_OBJECT && vp->properties) { - vp->properties->deleteProtect = deleteProtect; - } -} - -/******************************************************************************/ -/* - * Make a variable readonly. Can still be deleted. - */ - -void mprSetVarReadonly(MprVar *vp, int readonly) -{ - mprAssert(vp); - - vp->readonly = readonly; -} - -/******************************************************************************/ - -MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) -{ - MprVarTrigger oldTrigger; - - mprAssert(vp); - mprAssert(fn); - - oldTrigger = vp->trigger; - vp->trigger = fn; - return oldTrigger; -} - -/******************************************************************************/ - -MprType mprGetVarType(MprVar *vp) -{ - mprAssert(vp); - - return vp->type; -} - -/******************************************************************************/ -/********************************** Properties ********************************/ -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. - */ - -MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, - MprVar *newValue) -{ - MprVar *prop, *last; - int bucketIndex; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - /* - * See if property already exists and locate the bucket to hold the - * property reference. - */ - last = 0; - bucketIndex = hash(obj->properties, propertyName); - prop = obj->properties->buckets[bucketIndex]; - - /* - * Find the property in the hash chain if it exists - */ - for (last = 0; prop; last = prop, prop = prop->forw) { - if (prop->name[0] == propertyName[0] && - strcmp(prop->name, propertyName) == 0) { - break; - } - } - - if (prop) { - /* FUTURE -- remove. Just for debug. */ - mprAssert(prop == 0); - mprLog(0, "Attempting to create property %s in object %s\n", - propertyName, obj->name); - return 0; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, - newValue, 0) == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Create a new property - */ - prop = allocProperty(propertyName); - if (prop == 0) { - mprAssert(prop); - return 0; - } - - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - - prop->bucketIndex = bucketIndex; - if (last) { - last->forw = prop; - } else { - obj->properties->buckets[bucketIndex] = prop; - } - prop->parentProperties = obj->properties; - - /* - * Update the item counts - */ - obj->properties->numItems++; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems++; - } - - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. Same as - * mprCreateProperty except that the new value is passed by value rather than - * by pointer. - */ - -MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprCreateProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Create a new property - */ - -static MprVar *allocProperty(const char *propertyName) -{ - MprVar *prop; - - prop = (MprVar*) mprMalloc(sizeof(MprVar)); - if (prop == 0) { - mprAssert(prop); - return 0; - } - memset(prop, 0, sizeof(MprVar)); - prop->allocatedVar = 1; - prop->name = mprStrdup(propertyName); - prop->forw = (MprVar*) 0; - - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it doesn not already exist. - */ - -MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) -{ - MprVar *prop, triggerValue; - int rc; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(0); - return 0; - } - - prop = mprGetProperty(obj, propertyName, 0); - if (prop == 0) { - return mprCreateProperty(obj, propertyName, newValue); - } - - if (obj->trigger) { - /* - * Call the trigger before the update and pass it the new value. - */ - triggerValue = *newValue; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - /* - * Trigger must copy to triggerValue a variable that is not - * a structure copy of the existing data. - */ - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return prop; - } - } - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it does not already exist. Same as mprSetProperty except that the - * new value is passed by value rather than by pointer. - */ - -MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprSetProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Delete a property from this object - */ - -int mprDeleteProperty(MprVar *obj, const char *property) -{ - MprVar *prop, *last; - char *cp; - int bucketIndex; - - mprAssert(obj); - mprAssert(property && *property); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - last = 0; - bucketIndex = hash(obj->properties, property); - if ((prop = obj->properties->buckets[bucketIndex]) != 0) { - for ( ; prop; prop = prop->forw) { - cp = prop->name; - if (cp[0] == property[0] && strcmp(cp, property) == 0) { - break; - } - last = prop; - } - } - if (prop == (MprVar*) 0) { - mprAssert(prop); - return MPR_ERR_NOT_FOUND; - } - if (prop->readonly) { - mprAssert(! prop->readonly); - return MPR_ERR_READ_ONLY; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) - == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - } - } - - if (last) { - last->forw = prop->forw; - } else { - obj->properties->buckets[bucketIndex] = prop->forw; - } - - obj->properties->numItems--; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems--; - } - - mprDestroyVar(prop); - - return 0; -} - -/******************************************************************************/ -/* - * Find a property in an object and return a pointer to it. If a value arg - * is supplied, then copy the data into the var. - */ - -MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) -{ - MprVar *prop, triggerValue; - int rc; - - if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || - *property == '\0') { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - - for (prop = getObjChain(obj->properties, property); prop; - prop = prop->forw) { - if (prop->name && - prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { - break; - } - } - if (prop == 0) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - if (value) { - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - /* - * Pass the trigger the current read value and may receive - * a new value. - */ - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - } - } - /* - * Clone. No copy. - */ - *value = *prop; - } - return prop; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns the property's value. It does not - * copy object/string data but returns a pointer directly into the variable. - * The caller does not and should not call mprDestroy on the returned value. - * If value is null, just read the property and run triggers. - */ - -int mprReadProperty(MprVar *prop, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - if (value) { - *value = *prop; - - /* - * Just so that if the user calls mprDestroyVar on value, it will do no - * harm. - */ - value->allocatedVar = 0; - value->allocatedData = 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns a copy of the property variable. - * However, if the property is an object or string, it returns a copy of the - * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, - * then the underlying objects and strings data will be copied as well. If - * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If - * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the - * user must call mprDestroyVar to free resources. This routine will run any - * registered triggers which may modify the value the user receives (without - * updating the properties real value). - * - * WARNING: the args are reversed to most other APIs. This conforms to the - * strcpy(dest, src) standard instead. - */ - -int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - mprAssert(dest); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, copyDepth); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - mprCopyVar(dest, prop, copyDepth); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWriteProperty(MprVar *vp, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(vp); - mprAssert(value); - - if (vp->readonly) { - return MPR_ERR_READ_ONLY; - } - - if (vp->trigger) { - triggerValue = *value; - - rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - /* Fall through */ - } - - copyVarCore(vp, value, MPR_SHALLOW_COPY); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWritePropertyValue(MprVar *vp, MprVar value) -{ - mprAssert(vp); - - return mprWriteProperty(vp, &value); -} - -/******************************************************************************/ -/* - * Get the count of properties. - */ - -int mprGetPropertyCount(MprVar *vp, int includeFlags) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - return 0; - } - if (includeFlags == MPR_ENUM_DATA) { - return vp->properties->numDataItems; - } else { - return vp->properties->numItems; - } -} - -/******************************************************************************/ -/* - * Get the first property in an object. Used for walking all properties in an - * object. - */ - -MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) -{ - MprVar *prop; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - for (i = 0; i < (int) obj->properties->hashSize; i++) { - for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { - if (prop) { - if (mprVarIsFunction(prop->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return prop; - } - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Get the next property in sequence. - */ - -MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) -{ - MprProperties *properties; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - properties = obj->properties; - - if (last->forw) { - return last->forw; - } - - for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { - for (last = properties->buckets[i]; last; last = last->forw) { - if (mprVarIsFunction(last->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return last; - } - } - return 0; -} - -/******************************************************************************/ -/************************** Internal Support Routines *************************/ -/******************************************************************************/ -/* - * Create an hash table to hold and index properties. Properties are just - * variables which may contain primitive data types, functions or other - * objects. The hash table is the essence of an object. HashSize specifies - * the size of the hash table to use and should be a prime number. - */ - -static MprProperties *createProperties(const char *name, int hashSize) -{ - MprProperties *pp; - - if (hashSize < 7) { - hashSize = 7; - } - if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { - mprAssert(0); - return 0; - } - mprAssert(pp); - memset(pp, 0, sizeof(MprProperties)); - - pp->numItems = 0; - pp->numDataItems = 0; - pp->hashSize = hashSize; - pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); - mprAssert(pp->buckets); - memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); - pp->refCount = 1; - -#if VAR_DEBUG - if (objectCount == -1) { - objectCount = 0; - objectList.next = objectList.prev = &objectList; - } - - mprStrcpy(pp->name, sizeof(pp->name), name); - pp->next = &objectList; - pp->prev = objectList.prev; - objectList.prev->next = pp; - objectList.prev = pp; - objectCount++; -#endif - return pp; -} - -/******************************************************************************/ -/* - * Release an object's properties hash table. If this is the last person - * using it, free it. Return TRUE if the object is released. - */ - -static bool releaseProperties(MprProperties *obj, int force) -{ - MprProperties *pp; - MprVar *prop, *forw; - int i; - - mprAssert(obj); - mprAssert(obj->refCount > 0); - -#if VAR_DEBUG - /* - * Debug sanity check - */ - mprAssert(obj->refCount < 20); -#endif - - if (--obj->refCount > 0 && !force) { - return 0; - } - -#if VAR_DEBUG - mprAssert(obj->prev); - mprAssert(obj->next); - mprAssert(obj->next->prev); - mprAssert(obj->prev->next); - obj->next->prev = obj->prev; - obj->prev->next = obj->next; - objectCount--; -#endif - - for (i = 0; i < (int) obj->hashSize; i++) { - for (prop = obj->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->type == MPR_TYPE_OBJECT) { - - if (prop->properties == obj) { - /* Self reference */ - continue; - } - pp = prop->properties; - if (pp->visited) { - continue; - } - - pp->visited = 1; - if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { - pp->visited = 0; - } - - } else { - freeVar(prop, force); - } - } - } - - mprFree((void*) obj->buckets); - mprFree((void*) obj); - - return 1; -} - -/******************************************************************************/ -/* - * Adjust the reference count - */ - -static int adjustRefCount(MprProperties *pp, int adj) -{ - mprAssert(pp); - - /* - * Debug sanity check - */ - mprAssert(pp->refCount < 20); - - return pp->refCount += adj; -} - -/******************************************************************************/ -#if VAR_DEBUG -/* - * Print objects held - */ - -void mprPrintObjects(char *msg) -{ - MprProperties *pp, *np; - MprVar *prop, *forw; - char *buf; - int i; - - mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); - pp = objectList.next; - while (pp != &objectList) { - mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", - pp->name, pp, pp->refCount, pp->numItems); - for (i = 0; i < (int) pp->hashSize; i++) { - for (prop = pp->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->properties == pp) { - /* Self reference */ - continue; - } - mprVarToString(&buf, MPR_MAX_STRING, 0, prop); - if (prop->type == MPR_TYPE_OBJECT) { - np = objectList.next; - while (np != &objectList) { - if (prop->properties == np) { - break; - } - np = np->next; - } - if (prop->properties == np) { - mprLog(7, " %s: OBJECT 0x%x, <%s>\n", - prop->name, prop->properties, prop->fullName); - } else { - mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", - prop->name, buf, prop->fullName); - } - } else { - mprLog(7, " %s: <%s> = %s\n", prop->name, - prop->fullName, buf); - } - mprFree(buf); - } - } - pp = pp->next; - } -} - -/******************************************************************************/ - -void mprPrintObjRefCount(MprVar *vp) -{ - mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, - vp->properties->refCount); -} - -#endif -/******************************************************************************/ -/* - * Get the bucket chain containing a property. - */ - -static MprVar *getObjChain(MprProperties *obj, const char *property) -{ - mprAssert(obj); - - return obj->buckets[hash(obj, property)]; -} - -/******************************************************************************/ -/* - * Fast hash. The history of this algorithm is part of lost computer science - * folk lore. - */ - -static int hash(MprProperties *pp, const char *property) -{ - uint sum; - - mprAssert(pp); - mprAssert(property); - - sum = 0; - while (*property) { - sum += (sum * 33) + *property++; - } - - return sum % pp->hashSize; -} - -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -/* - * Initialize an undefined value. - */ - -MprVar mprCreateUndefinedVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_UNDEFINED; - return v; -} - -/******************************************************************************/ -/* - * Initialize an null value. - */ - -MprVar mprCreateNullVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_NULL; - return v; -} - -/******************************************************************************/ - -MprVar mprCreateBoolVar(bool value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_BOOL; - v.boolean = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_CFUNCTION; - v.cFunction.fn = fn; - v.cFunction.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, - int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING_CFUNCTION; - v.cFunctionWithStrings.fn = fn; - v.cFunctionWithStrings.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize an opaque pointer. - */ - -MprVar mprCreatePtrVar(void *ptr) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_PTR; - v.ptr = ptr; - - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Initialize a floating value. - */ - -MprVar mprCreateFloatVar(double value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FLOAT; - v.floating = value; - return v; -} - -#endif -/******************************************************************************/ -/* - * Initialize an integer value. - */ - -MprVar mprCreateIntegerVar(int value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT; - v.integer = value; - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Initialize a 64-bit integer value. - */ - -MprVar mprCreateInteger64Var(int64 value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT64; - v.integer64 = value; - return v; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Initialize an number variable. Type is defined by configure. - */ - -MprVar mprCreateNumberVar(MprNum value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = BLD_FEATURE_NUM_TYPE_ID; -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - v.integer64 = value; -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - v.float = value; -#else - v.integer = value; -#endif - return v; -} - -/******************************************************************************/ -/* - * Initialize a (bare) JavaScript function. args and body can be null. - */ - -MprVar mprCreateFunctionVar(char *args, char *body, int flags) -{ - MprVar v; - char *cp, *arg, *last; - int aid; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FUNCTION; - v.flags = flags; - - v.function.args = mprCreateArray(); - - if (args) { - args = mprStrdup(args); - arg = mprStrTok(args, ",", &last); - while (arg) { - while (isspace((int) *arg)) - arg++; - for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { - if (!isspace((int) *cp)) { - break; - } - } - cp[1] = '\0'; - - aid = mprAddToArray(v.function.args, mprStrdup(arg)); - arg = mprStrTok(0, ",", &last); - } - mprFree(args); - } - - if (body) { - v.function.body = mprStrdup(body); - } - v.allocatedData = 1; - return v; -} - -/******************************************************************************/ -/* - * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the - * memory allocation for the properties table failed. - */ - -MprVar mprCreateObjVar(const char *name, int hashSize) -{ - MprVar v; - - mprAssert(name && *name); - - memset(&v, 0x0, sizeof(MprVar)); - v.type = MPR_TYPE_OBJECT; - if (hashSize <= 0) { - hashSize = MPR_DEFAULT_HASH_SIZE; - } - v.properties = createProperties(name, hashSize); - if (v.properties == 0) { - /* Indicate failed memory allocation */ - v.type = MPR_TYPE_UNDEFINED; - } - v.allocatedData = 1; - v.name = mprStrdup(name); - mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); - return v; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -MprVar mprCreateStringVar(const char *value, bool allocate) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING; - if (value == 0) { - v.string = ""; - } else if (allocate) { - v.string = mprStrdup(value); - v.allocatedData = 1; - } else { - v.string = (char*) value; - } - return v; -} - -/******************************************************************************/ -/* - * Copy an objects core value (only). This preserves the destination object's - * name. This implements copy by reference for objects and copy by value for - * strings and other types. Caller must free dest prior to calling. - */ - -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) -{ - MprVarTrigger saveTrigger; - MprVar *srcProp, *destProp, *last; - char **srcArgs; - int i; - - mprAssert(dest); - mprAssert(src); - - if (dest == src) { - return; - } - - /* - * FUTURE: we should allow read-only triggers where the value is never - * stored in the object. Currently, triggers override the readonly - * status. - */ - - if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { - mprAssert(0); - return; - } - - if (dest->type != MPR_TYPE_UNDEFINED) { - saveTrigger = dest->trigger; - freeVarStorage(dest, 0); - } else { - saveTrigger = 0; - } - - switch (src->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - break; - - case MPR_TYPE_BOOL: - dest->boolean = src->boolean; - break; - - case MPR_TYPE_PTR: - dest->ptr = src->ptr; - break; - - case MPR_TYPE_STRING_CFUNCTION: - dest->cFunctionWithStrings = src->cFunctionWithStrings; - break; - - case MPR_TYPE_CFUNCTION: - dest->cFunction = src->cFunction; - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - dest->floating = src->floating; - break; -#endif - - case MPR_TYPE_INT: - dest->integer = src->integer; - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - dest->integer64 = src->integer64; - break; -#endif - - case MPR_TYPE_OBJECT: - if (copyDepth == MPR_DEEP_COPY) { - - dest->properties = createProperties(src->name, - src->properties->hashSize); - dest->allocatedData = 1; - - for (i = 0; i < (int) src->properties->hashSize; i++) { - last = 0; - for (srcProp = src->properties->buckets[i]; srcProp; - srcProp = srcProp->forw) { - if (srcProp->visited) { - continue; - } - destProp = allocProperty(srcProp->name); - if (destProp == 0) { - mprAssert(destProp); - return; - } - - destProp->bucketIndex = i; - if (last) { - last->forw = destProp; - } else { - dest->properties->buckets[i] = destProp; - } - destProp->parentProperties = dest->properties; - - /* - * Recursively copy the object - */ - srcProp->visited = 1; - copyVarCore(destProp, srcProp, copyDepth); - srcProp->visited = 0; - last = srcProp; - } - } - dest->properties->numItems = src->properties->numItems; - dest->properties->numDataItems = src->properties->numDataItems; - dest->allocatedData = 1; - - } else if (copyDepth == MPR_SHALLOW_COPY) { - dest->properties = src->properties; - adjustVarRefCount(src, 1); - dest->allocatedData = 1; - - } else { - dest->properties = src->properties; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_FUNCTION: - if (copyDepth != MPR_NO_COPY) { - dest->function.args = mprCreateArray(); - srcArgs = (char**) src->function.args->handles; - for (i = 0; i < src->function.args->max; i++) { - if (srcArgs[i]) { - mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); - } - } - dest->function.body = mprStrdup(src->function.body); - dest->allocatedData = 1; - } else { - dest->function.args = src->function.args; - dest->function.body = src->function.body; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_STRING: - if (src->string && copyDepth != MPR_NO_COPY) { - dest->string = mprStrdup(src->string); - dest->allocatedData = 1; - } else { - dest->string = src->string; - dest->allocatedData = 0; - } - break; - } - - dest->type = src->type; - dest->flags = src->flags; - dest->trigger = saveTrigger; - - /* - * Just for safety - */ - dest->spare = 0; -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) -{ - mprAssert(dest); - mprAssert(src); - - copyVarCore(dest, src, copyDepth); - - mprFree(dest->name); - dest->name = mprStrdup(src->name); - -#if VAR_DEBUG - if (src->type == MPR_TYPE_OBJECT) { - - mprFree(dest->fullName); - dest->fullName = mprStrdup(src->fullName); - - mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", - dest->name, dest->fullName, dest->properties, - dest->properties->refCount); - } -#endif -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) -{ - mprAssert(dest); - - mprCopyVar(dest, &src, copyDepth); -} - -/******************************************************************************/ -/* - * Copy an object. This implements copy by reference for objects and copy by - * value for strings and other types. Caller must free dest prior to calling. - */ - -MprVar *mprDupVar(MprVar *src, int copyDepth) -{ - MprVar *dest; - - mprAssert(src); - - dest = (MprVar*) mprMalloc(sizeof(MprVar)); - memset(dest, 0, sizeof(MprVar)); - - mprCopyVar(dest, src, copyDepth); - return dest; -} - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - * FUTURE -- conver this to use the format string in all cases. Allow - * arbitrary format strings. - */ - -void mprVarToString(char** out, int size, char *fmt, MprVar *obj) -{ - char *src; - - mprAssert(out); - - *out = NULL; - - if (obj->trigger) { - mprReadProperty(obj, 0); - } - - switch (obj->type) { - case MPR_TYPE_UNDEFINED: - /* FUTURE -- spec says convert to "undefined" */ - *out = mprStrdup(""); - break; - - case MPR_TYPE_NULL: - *out = mprStrdup("null"); - break; - - case MPR_TYPE_PTR: - mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); - break; - - case MPR_TYPE_BOOL: - if (obj->boolean) { - *out = mprStrdup("true"); - } else { - *out = mprStrdup("false"); - } - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%f", obj->floating); - } else { - mprAllocSprintf(out, size, fmt, obj->floating); - } - break; -#endif - - case MPR_TYPE_INT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%d", obj->integer); - } else { - mprAllocSprintf(out, size, fmt, obj->integer); - } - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - if (fmt == NULL || *fmt == '\0') { -#if BLD_GOAHEAD_WEBSERVER - mprAllocSprintf(out, size, "%d", (int) obj->integer64); -#else - mprAllocSprintf(out, size, "%Ld", obj->integer64); -#endif - } else { - mprAllocSprintf(out, size, fmt, obj->integer64); - } - break; -#endif - - case MPR_TYPE_CFUNCTION: - mprAllocSprintf(out, size, "[C Function]"); - break; - - case MPR_TYPE_STRING_CFUNCTION: - mprAllocSprintf(out, size, "[C StringFunction]"); - break; - - case MPR_TYPE_FUNCTION: - mprAllocSprintf(out, size, "[JavaScript Function]"); - break; - - case MPR_TYPE_OBJECT: - /* FUTURE -- really want: [object class: name] */ - mprAllocSprintf(out, size, "[object %s]", obj->name); - break; - - case MPR_TYPE_STRING: - src = obj->string; - - mprAssert(src); - if (fmt && *fmt) { - mprAllocSprintf(out, size, fmt, src); - - } else if (src == NULL) { - *out = mprStrdup("null"); - - } else { - *out = mprStrdup(src); - } - break; - - default: - mprAssert(0); - } -} - -/******************************************************************************/ -/* - * Parse a string based on formatting instructions and intelligently - * create a variable. - */ - -MprVar mprParseVar(char *buf, MprType preferredType) -{ - MprType type = MPR_TYPE_UNDEFINED; - char *cp; - - mprAssert(buf); - - if (preferredType == MPR_TYPE_UNDEFINED) { - if (*buf == '-') { - type = MPR_NUM_VAR; - - } else if (!isdigit((int) *buf)) { - if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { - type = MPR_TYPE_BOOL; - } else { - type = MPR_TYPE_STRING; - } - - } else if (isdigit((int) *buf)) { - type = MPR_NUM_VAR; - cp = buf; - if (*cp && tolower((unsigned char)cp[1]) == 'x') { - cp = &cp[2]; - } - for (cp = buf; *cp; cp++) { - if (! isdigit((unsigned char) *cp)) { - break; - } - } - - if (*cp != '\0') { -#if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { - type = MPR_TYPE_FLOAT; - } else -#endif - { - type = MPR_NUM_VAR; - } - } - } - } else { - type = preferredType; - } - - switch (type) { - case MPR_TYPE_OBJECT: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_PTR: - default: - break; - - case MPR_TYPE_BOOL: - return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); - - case MPR_TYPE_INT: - return mprCreateIntegerVar(mprParseInteger(buf)); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return mprCreateInteger64Var(mprParseInteger64(buf)); -#endif - - case MPR_TYPE_STRING: - if (strcmp(buf, "null") == 0) { - return mprCreateNullVar(); - } else if (strcmp(buf, "undefined") == 0) { - return mprCreateUndefinedVar(); - } - - return mprCreateStringVar(buf, 1); - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return mprCreateFloatVar(atof(buf)); -#endif - - } - return mprCreateUndefinedVar(); -} - -/******************************************************************************/ -/* - * Convert the variable to a boolean. Only for primitive types. - */ - -bool mprVarToBool(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - return 0; - - case MPR_TYPE_PTR: - return (vp->ptr != NULL); - - case MPR_TYPE_BOOL: - return vp->boolean; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return (vp->floating != 0 && !mprIsNan(vp->floating)); -#endif - - case MPR_TYPE_INT: - return (vp->integer != 0); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (vp->integer64 != 0); -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return (vp->string[0] != '\0'); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the variable to a floating point number. Only for primitive types. - */ - -double mprVarToFloat(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1.0 : 0.0; - - case MPR_TYPE_FLOAT: - return vp->floating; - - case MPR_TYPE_INT: - return (double) vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (double) vp->integer64; -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return atof(vp->string); - } - - /* Not reached */ - return 0; -} - -#endif -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprVarToNumber(const MprVar *vp) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprVarToInteger64(vp); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprVarToFloat(vp); -#else - return mprVarToInteger(vp); -#endif -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprParseNumber(char *s) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprParseInteger64(s); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprParseFloat(s); -#else - return mprParseInteger(s); -#endif -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the variable to an Integer64 type. Only works for primitive types. - */ - -int64 mprVarToInteger64(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int64) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - - case MPR_TYPE_INT64: - return vp->integer64; - - case MPR_TYPE_STRING: - return mprParseInteger64(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer64. - */ - -int64 mprParseInteger64(char *str) -{ - char *cp; - int64 num64; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num64 = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num64 = (*cp - '0') + (num64 * 10); - cp++; - } - } else { - cp++; - if (tolower((unsigned char)*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c)) { - num64 = (c - '0') + (num64 * radix); - } else if (c >= 'a' && c <= 'f') { - num64 = (c - 'a') + (num64 * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c) && c < '8') { - num64 = (c - '0') + (num64 * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num64; - } - return num64; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the variable to an Integer type. Only works for primitive types. - */ - -int mprVarToInteger(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (int) vp->integer64; -#endif - - case MPR_TYPE_STRING: - return mprParseInteger(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer. - */ - -int mprParseInteger(char *str) -{ - char *cp; - int num; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num = (*cp - '0') + (num * 10); - cp++; - } - } else { - cp++; - if (tolower((unsigned char)*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c)) { - num = (c - '0') + (num * radix); - } else if (c >= 'a' && c <= 'f') { - num = (c - 'a') + (num * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower((unsigned char)*cp); - if (isdigit(c) && c < '8') { - num = (c - '0') + (num * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num; - } - return num; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the string buffer to an Floating. - */ - -double mprParseFloat(char *str) -{ - return atof(str); -} - -/******************************************************************************/ - -bool mprIsNan(double f) -{ -#if WIN - return _isnan(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_NAN); -#endif -} -/******************************************************************************/ - -bool mprIsInfinite(double f) -{ -#if WIN - return !_finite(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_INFINITE); -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/var.h b/source4/lib/appweb/ejs/var.h deleted file mode 100644 index 8ed13a4995..0000000000 --- a/source4/lib/appweb/ejs/var.h +++ /dev/null @@ -1,496 +0,0 @@ -/* - * @file var.h - * @brief MPR Universal Variable Type - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; 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 (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ -/* - * Variables can efficiently store primitive types and can hold references to - * objects. Objects can store properties which are themselves variables. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. A variable may store one of - * the following types: - * - * string, integer, integer-64bit, C function, C function with string args, - * Javascript function, Floating point number, boolean value, Undefined - * value and the Null value. - * - * Variables have names while objects may be referenced by multiple variables. - * Objects use reference counting for garbage collection. - * - * This module is not thread safe for performance and compactness. It relies - * on upper modules to provide thread synchronization as required. The API - * provides primitives to get variable/object references or to get copies of - * variables which will help minimize required lock times. - */ - -#ifndef _h_MPR_VAR -#define _h_MPR_VAR 1 - -/********************************* Includes ***********************************/ - -#include "miniMpr.h" - -/********************************** Defines ***********************************/ - -/* - * Define VAR_DEBUG if you want to track objects. However, this code is not - * thread safe and you need to run the server single threaded. - * - * #define VAR_DEBUG 1 - */ - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Forward declare types - */ -struct MprProperties; -struct MprVar; - -/* - * Possible variable types. Don't use enum because we need to be able to - * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. - */ -typedef int MprType; -#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ -#define MPR_TYPE_NULL 1 /* Value defined to be null. */ -#define MPR_TYPE_BOOL 2 /* Boolean type. */ -#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ -#define MPR_TYPE_FLOAT 4 /* Floating point number */ -#define MPR_TYPE_INT 5 /* Integer number */ -#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ -#define MPR_TYPE_OBJECT 7 /* Object reference */ -#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ -#define MPR_TYPE_STRING 9 /* String (immutable) */ -#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ -#define MPR_TYPE_PTR 11 /* Opaque pointer */ - -/* - * Create a type for the default number type - * Config.h will define the default number type. For example: - * - * BLD_FEATURE_NUM_TYPE=int - * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT - */ - -/** - * Set to the type used for MPR numeric variables. Will equate to int, int64 - * or double. - */ -typedef BLD_FEATURE_NUM_TYPE MprNum; - -/** - * Set to the MPR_TYPE used for MPR numeric variables. Will equate to - * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. - */ -#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID -#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID - -/* - * Return TRUE if a variable is a function type - */ -#define mprVarIsFunction(type) \ - (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ - type == MPR_TYPE_CFUNCTION) - -/* - * Return TRUE if a variable is a numeric type - */ -#define mprVarIsNumber(type) \ - (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) - -/* - * Return TRUE if a variable is a boolean - */ -#define mprVarIsBoolean(type) \ - (type == MPR_TYPE_BOOL) -#define mprVarIsString(type) \ - (type == MPR_TYPE_STRING) -#define mprVarIsObject(type) \ - (type == MPR_TYPE_OBJECT) -#define mprVarIsFloating(type) \ - (type == MPR_TYPE_FLOAT) -#define mprVarIsPtr(type) \ - (type == MPR_TYPE_PTR) -#define mprVarIsUndefined(var) \ - ((var)->type == MPR_TYPE_UNDEFINED) -#define mprVarIsNull(var) \ - ((var)->type == MPR_TYPE_NULL) -#define mprVarIsValid(var) \ - (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) - -#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ - -#if BLD_FEATURE_SQUEEZE -#define MPR_MAX_VAR 64 /* Max var full name */ -#else -#define MPR_MAX_VAR 512 -#endif - -#ifndef __NO_PACK -#pragma pack(2) -#endif /* _NO_PACK */ - -/* - * Function signatures - */ -typedef int MprVarHandle; -typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, - struct MprVar **argv); -typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, - char **argv); - -/* - * Triggers - */ -typedef enum { - MPR_VAR_WRITE, /* This property is being updated */ - MPR_VAR_READ, /* This property is being read */ - MPR_VAR_CREATE_PROPERTY, /* A property is being created */ - MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ - MPR_VAR_DELETE /* This object is being deleted */ -} MprVarTriggerOp; - -/* - * Trigger function return codes. - */ -typedef enum { - MPR_TRIGGER_ABORT, /* Abort the current operation */ - MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ - MPR_TRIGGER_PROCEED /* Proceed with the operation */ -} MprVarTriggerStatus; - -/* - * The MprVarTrigger arguments have the following meaning: - * - * op The operation being performed. See MprVarTriggerOp. - * parentProperties Pointer to the MprProperties structure. - * vp Pointer to the property that registered the trigger. - * newValue New value (see below for more details). - * copyDepth Specify what data items to copy. - * - * For VAR_READ, newVar is set to a temporary variable that the trigger - * function may assign a value to be returned instead of the actual - * property value. - * For VAR_WRITE, newValue holds the new value. The old existing value may be - * accessed via vp. - * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. - * For ADD_PROPERTY, vp is set to the property being added and newValue holds - * the new value. - */ -typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, - struct MprProperties *parentProperties, struct MprVar *vp, - struct MprVar *newValue, int copyDepth); - -/* - * mprCreateFunctionVar flags - */ -/** Use the alternate handle on function callbacks */ -#define MPR_VAR_ALT_HANDLE 0x1 - -/** Use the script handle on function callbacks */ -#define MPR_VAR_SCRIPT_HANDLE 0x2 - -/* - * Useful define for the copyDepth argument - */ -/** Don't copy any data. Copy only the variable name */ -#define MPR_NO_COPY 0 - -/** Copy strings. Increment object reference counts. */ -#define MPR_SHALLOW_COPY 1 - -/** Copy strings and do complete object copies. */ -#define MPR_DEEP_COPY 2 - -/* - * GetFirst / GetNext flags - */ -/** Step into data properties. */ -#define MPR_ENUM_DATA 0x1 - -/** Step into functions properties. */ -#define MPR_ENUM_FUNCTIONS 0x2 - -/* - * Collection type to hold properties in an object - */ -typedef struct MprProperties { /* Collection of properties */ -#if VAR_DEBUG - struct MprProperties *next; /* Linked list */ - struct MprProperties *prev; /* Linked list */ - char name[32]; /* Debug name */ -#endif - struct MprVar **buckets; /* Hash chains */ - int numItems; /* Total count of items */ - /* FUTURE - Better way of doing this */ - int numDataItems; /* Enumerable data items */ - uint hashSize : 8; /* Size of the hash table */ - /* FUTURE -- increase size of refCount */ - uint refCount : 8; /* References to this property*/ - /* FUTURE - make these flags */ - uint deleteProtect : 8; /* Don't recursively delete */ - uint visited : 8; /* Node has been processed */ -} MprProperties; - -/* - * Universal Variable Type - */ -typedef struct MprVar { - /* FUTURE - remove name to outside reference */ - MprStr name; /* Property name */ - /* FUTURE - remove */ - MprStr fullName; /* Full object name */ - /* FUTURE - make part of the union */ - MprProperties *properties; /* Pointer to properties */ - - /* - * Packed bit field - */ - MprType type : 8; /* Selector into union */ - uint bucketIndex : 8; /* Copy of bucket index */ - - uint flags : 5; /* Type specific flags */ - uint allocatedData : 1; /* Data needs freeing */ - uint readonly : 1; /* Unmodifiable */ - uint deleteProtect : 1; /* Don't recursively delete */ - - uint visited : 1; /* Node has been processed */ - uint allocatedVar : 1; /* Var needs freeing */ - uint spare : 6; /* Unused */ - - struct MprVar *forw; /* Hash table linkage */ - MprVarTrigger trigger; /* Trigger function */ - -#if UNUSED && KEEP - struct MprVar *baseClass; /* Pointer to class object */ -#endif - MprProperties *parentProperties; /* Pointer to parent object */ - - /* - * Union of primitive types. When debugging on Linux, don't use unions - * as the gdb debugger can't display them. - */ -#if !BLD_DEBUG && !LINUX && !VXWORKS - union { -#endif - int boolean; /* Use int for speed */ -#if BLD_FEATURE_FLOATING_POINT - double floating; -#endif - int integer; -#if BLD_FEATURE_INT64 - int64 integer64; -#endif - struct { /* Javascript functions */ - MprArray *args; /* Null terminated */ - char *body; - } function; - struct { /* Function with MprVar args */ - MprCFunction fn; - void *thisPtr; - } cFunction; - struct { /* Function with string args */ - MprStringCFunction fn; - void *thisPtr; - } cFunctionWithStrings; - MprStr string; /* Allocated string */ - void *ptr; /* Opaque pointer */ -#if !BLD_DEBUG && !LINUX && !VXWORKS - }; -#endif -} MprVar; - -/* - * Define a field macro so code an use numbers in a "generic" fashion. - */ -#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN -/* Default numeric type */ -#define mprNumber integer -#endif -#if MPR_NUM_VAR == MPR_TYPE_INT64 -/* Default numeric type */ -#define mprNumber integer64 -#endif -#if MPR_NUM_VAR == MPR_TYPE_FLOAT -/* Default numeric type */ -#define mprNumber floating -#endif - -typedef BLD_FEATURE_NUM_TYPE MprNumber; - - -#ifndef __NO_PACK -#pragma pack() -#endif /* __NO_PACK */ - -/********************************* Prototypes *********************************/ -/* - * Variable constructors and destructors - */ -extern MprVar mprCreateObjVar(const char *name, int hashSize); -extern MprVar mprCreateBoolVar(bool value); -extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, - int flags); -#if BLD_FEATURE_FLOATING_POINT -extern MprVar mprCreateFloatVar(double value); -#endif -extern MprVar mprCreateIntegerVar(int value); -#if BLD_FEATURE_INT64 -extern MprVar mprCreateInteger64Var(int64 value); -#endif -extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); -extern MprVar mprCreateNullVar(void); -extern MprVar mprCreateNumberVar(MprNumber value); -extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, - void *thisPtr, int flags); -extern MprVar mprCreateStringVar(const char *value, bool allocate); -extern MprVar mprCreateUndefinedVar(void); -extern MprVar mprCreatePtrVar(void *ptr); -extern bool mprDestroyVar(MprVar *vp); -extern bool mprDestroyAllVars(MprVar* vp); -extern MprType mprGetVarType(MprVar *vp); - -/* - * Copy - */ -extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); -extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); -extern MprVar *mprDupVar(MprVar *src, int copyDepth); - -/* - * Manage vars - */ -extern MprVarTrigger - mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); -extern int mprGetVarRefCount(MprVar *vp); -extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); -extern void mprSetVarFullName(MprVar *vp, char *name); -extern void mprSetVarReadonly(MprVar *vp, int readonly); -extern void mprSetVarName(MprVar *vp, char *name); - -/* - * Create properties and return a reference to the property. - */ -extern MprVar *mprCreateProperty(MprVar *obj, const char *property, - MprVar *newValue); -extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, - MprVar newValue); -extern int mprDeleteProperty(MprVar *obj, const char *property); - -/* - * Get/Set properties. Set will update/create. - */ -extern MprVar *mprGetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, - MprVar value); - -/* - * Directly read/write property values (the property must already exist) - * For mprCopyProperty, mprDestroyVar must always called on the var. - */ -extern int mprReadProperty(MprVar *prop, MprVar *value); -extern int mprWriteProperty(MprVar *prop, MprVar *newValue); -extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); - -/* - * Copy a property. NOTE: reverse of most other args: (dest, src) - */ -extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); - -/* - * Enumerate properties - */ -extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); -extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags); - -/* - * Query properties characteristics - */ -extern int mprGetPropertyCount(MprVar *obj, int includeFlags); - -/* - * Conversion routines - */ -extern MprVar mprParseVar(char *str, MprType prefType); -extern MprNum mprVarToNumber(const MprVar *vp); -extern int mprVarToInteger(const MprVar *vp); -#if BLD_FEATURE_INT64 -extern int64 mprVarToInteger64(const MprVar *vp); -#endif -extern bool mprVarToBool(const MprVar *vp); -#if BLD_FEATURE_FLOATING_POINT -extern double mprVarToFloat(const MprVar *vp); -#endif -extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); - -/* - * Parsing and utility routines - */ -extern MprNum mprParseNumber(char *str); -extern int mprParseInteger(char *str); - -#if BLD_FEATURE_INT64 -extern int64 mprParseInteger64(char *str); -#endif - -#if BLD_FEATURE_FLOATING_POINT -extern double mprParseFloat(char *str); -extern bool mprIsInfinite(double f); -extern bool mprIsNan(double f); -#endif - -#if VAR_DEBUG -extern void mprPrintObjects(char *msg); -extern void mprPrintObjRefCount(MprVar *vp); -#endif - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ -#endif /* _h_MPR_VAR */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h index ee86e8d345..e15daf0b4e 100644 --- a/source4/lib/appweb/esp/esp.h +++ b/source4/lib/appweb/esp/esp.h @@ -38,8 +38,8 @@ #include "lib/appweb/ejs/ejs.h" #include "lib/appweb/esp/espEnv.h" -#include "lib/appweb/ejs/var.h" -#include "lib/appweb/ejs/miniMpr.h" +#include "lib/appweb/mpr/var.h" +#include "lib/appweb/mpr/miniMpr.h" /*********************************** Defines **********************************/ diff --git a/source4/lib/appweb/mpr/miniMpr.c b/source4/lib/appweb/mpr/miniMpr.c new file mode 100644 index 0000000000..abeefe1ec8 --- /dev/null +++ b/source4/lib/appweb/mpr/miniMpr.c @@ -0,0 +1,512 @@ +/* + * @file miniMpr.cpp + * @brief Mini Mbedthis Portable Runtime (MPR) + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +#include "miniMpr.h" + +/************************************ Code ************************************/ +#if !BLD_APPWEB +#if !BLD_GOAHEAD_WEBSERVER + +static void *mpr_ctx; + +/* set the memory context to be used for all ejs variables */ +void mprSetCtx(TALLOC_CTX *ctx) +{ + mpr_ctx = ctx; +} + +/* return the memory context being used for all ejs variables */ +void *mprMemCtx(void) +{ + return mpr_ctx; +} + +void mprFree(void *ptr) +{ + talloc_free(ptr); +} + +void *mprMalloc(uint size) +{ + return talloc_size(mpr_ctx, size); +} + +/******************************************************************************/ + +void *mprRealloc(void *ptr, uint size) +{ + return talloc_realloc_size(mpr_ctx, ptr, size); +} + +/******************************************************************************/ + +char *mprStrdup(const char *str) +{ + if (str == 0) { + str = ""; + } + return talloc_strdup(mpr_ctx, str); +} + +/*****************************************************************************/ + +int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) +{ + va_list args; + char *buf; + int count; + + va_start(args, fmt); + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + va_end(args); + return count; +} + +/*****************************************************************************/ + +int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) +{ + char *buf; + int count; + + buf = mprMalloc(maxSize + 1); + count = mtVsprintf(buf, maxSize, fmt, args); + *msgbuf = buf; + return count; +} + + +/*****************************************************************************/ +/* + * Format a number as a string. FUTURE -- reverse args to be standard. + * ie. mprItoa(char *userBuf, int bufsize, int value); + */ + +char *mprItoa(int value, char *buf, int width) +{ + char numBuf[16]; + char *cp, *dp, *endp; + int negative; + + cp = &numBuf[sizeof(numBuf)]; + *--cp = '\0'; + + if (value < 0) { + negative = 1; + value = -value; + width--; + } else { + negative = 0; + } + + do { + *--cp = '0' + (value % 10); + value /= 10; + } while (value > 0); + + if (negative) { + *--cp = '-'; + } + + dp = buf; + endp = &buf[width]; + while (dp < endp && *cp) { + *dp++ = *cp++; + } + *dp++ = '\0'; + return buf; +} + +/*****************************************************************************/ + +void mprLog(int level, const char *fmt, ...) +{ + va_list args; + char *buf; + + if (DEBUGLVL(level)) { + va_start(args, fmt); + mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); + va_end(args); + DEBUG(level, ("mprLog: %s", buf)); + mprFree(buf); + } +} + +/*****************************************************************************/ + +void mprBreakpoint(const char *file, int line, const char *cond) +{ + char *buf; + mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", + file, line, cond); + ejs_exception(buf); +} + +#endif /* !BLD_GOAHEAD_WEBSERVER */ +/*****************************************************************************/ +/* + * Create a general growable array structure + */ + +MprArray *mprCreateArray() +{ + MprArray *array; + int size; + + array = (MprArray*) mprMalloc(sizeof(MprArray)); + if (array == 0) { + return 0; + } + memset(array, 0, sizeof(MprArray)); + + size = MPR_ARRAY_INCR * sizeof(void*); + array->handles = (void**) mprMalloc(size); + if (array->handles == 0) { + mprFree(array); + return 0; + } + memset(array->handles, 0, size); + array->max = MPR_ARRAY_INCR; + array->used = 0; + return array; +} + +/*****************************************************************************/ +/* + * Dispose of the array. Callers responsibility to dispose of handle entries. + */ + +void mprDestroyArray(MprArray *array) +{ + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + mprFree(array->handles); + mprFree(array); +} + +/*****************************************************************************/ +/* + * Add an item to the array + */ + +int mprAddToArray(MprArray *array, void *item) +{ + int memsize, idx, len; + + mprAssert(array); + mprAssert(array->max >= 0); + mprAssert(array->used >= 0); + + if (array->used < array->max) { + idx = array->used++; + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + + for (idx = array->used; idx < array->max; idx++) { + if (array->handles[idx] == 0) { + array->used++; + mprAssert(array->handles[idx] == 0); + array->handles[idx] = item; + return idx; + } + } + + len = array->max + MPR_ARRAY_INCR; + memsize = len * sizeof(void*); + array->handles = (void**) mprRealloc((void*) array->handles, memsize); + if (array->handles == NULL) { + return -1; + } + memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); + array->max = len; + array->used++; + + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] == 0); + + array->handles[idx] = item; + return idx; +} + +/*****************************************************************************/ +/* + * Remove from the array + */ + +int mprRemoveFromArray(MprArray *array, int idx) +{ + mprAssert(array); + mprAssert(array->max > 0); + mprAssert(idx >= 0 && idx < array->max); + mprAssert(array->handles[idx] != 0); + mprAssert(array->used > 0); + + array->handles[idx] = 0; + return --array->used; +} + +/*****************************************************************************/ +/* + * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() + */ + +char *mprStrTok(char *str, const char *delim, char **tok) +{ + char *start, *end; + int i; + + start = str ? str : *tok; + + if (start == 0) { + return 0; + } + + i = strspn(start, delim); + start += i; + if (*start == '\0') { + *tok = 0; + return 0; + } + end = strpbrk(start, delim); + if (end) { + *end++ = '\0'; + i = strspn(end, delim); + end += i; + } + *tok = end; + return start; +} + +/*****************************************************************************/ + +static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, + const char *delim, const char *src, va_list args) +{ + va_list ap; + char *dest, *dp; + const char *str; + int sepLen, addBytes, required; + + mprAssert(destp); + mprAssert(destMax > 0); + mprAssert(src); + + dest = *destp; + sepLen = (delim) ? strlen(delim) : 0; + +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + addBytes = 0; + str = src; + while (str) { + addBytes += strlen(str) + sepLen; + str = va_arg(ap, const char*); + } + + if (existingLen > 0) { + addBytes += sepLen; + } + required = existingLen + addBytes + 1; + if (required >= destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + + if (alloc) { + if (dest == 0) { + dest = (char*) mprMalloc(required); + } else { + dest = (char*) mprRealloc(dest, required); + } + } else { + dest = (char*) *destp; + } + + dp = &dest[existingLen]; + if (delim) { + strcpy(dp, delim); + dp += sepLen; + } + + if (addBytes > 0) { +#ifdef __va_copy + __va_copy(ap, args); +#else + ap = args; +#endif + str = src; + while (str) { + strcpy(dp, str); + dp += strlen(str); + str = va_arg(ap, char*); + if (delim && str) { + strcpy(dp, delim); + dp += sepLen; + } + } + } else if (dest == 0) { + dest = (char*) mprMalloc(1); + } + *dp = '\0'; + + *destp = dest; + mprAssert(dp < &dest[required]); + return required - 1; +} + +/*****************************************************************************/ + +int mprReallocStrcat(char **destp, int destMax, int existingLen, + const char *delim, const char *src,...) +{ + va_list ap; + int rc; + + va_start(ap, src); + rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); + va_end(ap); + return rc; +} + +/*****************************************************************************/ +/* + * Return the directory portion of a pathname into the users buffer. + */ + +int mprGetDirName(char *buf, int bufsize, char *path) +{ + char *cp; + int dlen; + + mprAssert(path); + mprAssert(buf); + mprAssert(bufsize > 0); + + cp = strrchr(path, '/'); + if (cp == 0) { +#if WIN + cp = strrchr(path, '\\'); + if (cp == 0) +#endif + { + buf[0] = '\0'; + return 0; + } + } + + if (cp == path && cp[1] == '\0') { + strcpy(buf, "."); + return 0; + } + + dlen = cp - path; + if (dlen < bufsize) { + if (dlen == 0) { + dlen++; + } + mprMemcpy(buf, bufsize, path, dlen); + buf[dlen] = '\0'; + return 0; + } + return MPR_ERR_WONT_FIT; +} + +/*****************************************************************************/ + +int mprStrcpy(char *dest, int destMax, const char *src) +{ + int len; + + mprAssert(dest); + mprAssert(destMax > 0); + mprAssert(src); + + len = strlen(src); + if (len >= destMax && len > 0) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (len > 0) { + memcpy(dest, src, len); + dest[len] = '\0'; + } else { + *dest = '\0'; + len = 0; + } + return len; +} + +/*****************************************************************************/ + +int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) +{ + mprAssert(dest); + mprAssert(destMax > nbytes); + mprAssert(src); + mprAssert(nbytes > 0); + + if (nbytes > destMax) { + mprAssert(0); + return MPR_ERR_WONT_FIT; + } + if (nbytes > 0) { + memcpy(dest, src, nbytes); + return nbytes; + } else { + return 0; + } +} + +/*****************************************************************************/ +#else +void miniMprDummy() {} +#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h new file mode 100644 index 0000000000..a0030b25b5 --- /dev/null +++ b/source4/lib/appweb/mpr/miniMpr.h @@ -0,0 +1,292 @@ +/* + * @file miniMpr.h + * @brief Mini Mbedthis Portable Runtime (MPR) Environment. + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ +#ifndef _h_MINI_MPR +#define _h_MINI_MPR 1 + +/********************************** Includes **********************************/ +/* + * Find out about our configuration + */ +#ifndef _INCLUDES_H + #include "includes.h" +#endif + +/* allow this library to use strcpy() */ +#undef strcpy + #include "lib/appweb/ejs/config.h" + +#if BLD_APPWEB + /* + * If building within AppWeb, use the full MPR + */ + #include "mpr.h" +#else + + #include + #include + #include + #include + #include + #include + #include + +#if !WIN + #include +#endif + +#if CE + #include + #include "CE/wincompat.h" +#endif + +#if LYNX + #include +#endif + +#if QNX4 + #include +#endif + #include + +/********************************** Defines ***********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if BLD_FEATURE_SQUEEZE +/* + * Reasonable length of a file path name to use in most cases where you know + * the expected file name and it is certain to be less than this limit. + */ +#define MPR_MAX_FNAME 128 +#define MPR_MAX_STRING 512 +#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ +#define MPR_MAX_HEAP_SIZE (32 * 1024) +#else +#define MPR_MAX_FNAME 256 +#define MPR_MAX_STRING 4096 +#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ +#define MPR_MAX_HEAP_SIZE (64 * 1024) +#endif + +/* + * Useful for debugging + */ +#define MPR_L __FILE__, __LINE__ + +#if BLD_FEATURE_ASSERT +#define mprAssert(C) \ + if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) +#else + #define mprAssert(C) if (1) ; else +#endif + +/* + * Standard MPR return and error codes + */ +#define MPR_ERR_BASE (-200) /* Error code */ +#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ +#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ +#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ +#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ +#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ +#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ +#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ +#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ +#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ +#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ +#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ +#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ +#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ +#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ +#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ +#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ +#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ +#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ +#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ +#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ +#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ +#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ +#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ +#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ +#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ +#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ +#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ +#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ +#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ +#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ + +/* + * Standard error severity and trace levels. These are ored with the error + * severities below. The MPR_LOG_MASK is used to extract the trace level + * from a flags word. We expect most apps to run with level 2 trace. + */ +#define MPR_FATAL 0 /* Fatal error. Cant continue. */ +#define MPR_ERROR 1 /* Hard error */ +#define MPR_WARN 2 /* Soft warning */ +#define MPR_CONFIG 2 /* Essential configuration settings */ +#define MPR_INFO 3 /* Informational only */ +#define MPR_DEBUG 4 /* Debug information */ +#define MPR_VERBOSE 9 /* Highest level of trace */ +#define MPR_LOG_MASK 0xf /* Level mask */ + +/* + * Error flags. Specify where the error should be sent to. Note that the + * product.xml setting "headless" will modify how errors are reported. + * Assert errors are trapped when in DEV mode. Otherwise ignored. + */ +#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ +#define MPR_LOG 0x20 /* Log the error in the O/S event log */ +#define MPR_USER 0x40 /* Display to the user */ +#define MPR_ALERT 0x80 /* Send a management alert */ +#define MPR_TRACE 0x100 /* Trace */ + +/* + * Error format flags + */ +#define MPR_RAW 0x200 /* Raw trace output */ + +/* + * Error line number information + */ +#define MPR_L __FILE__, __LINE__ + +typedef char* MprStr; + +#ifndef __cplusplus +typedef unsigned char uchar; +typedef int bool; +#endif + +/* + * Porters: put other operating system type defines here + */ +#if WIN + typedef unsigned int uint; + typedef __int64 int64; + typedef unsigned __int64 uint64; +#else +#define O_BINARY 0 +#ifndef uint + #define uint unsigned +#endif + __extension__ typedef long long int int64; + __extension__ typedef unsigned long long int uint64; +#endif + +/* + * Flexible array data type + */ +typedef struct { + int max; /* Size of the handles array */ + int used; /* Count of used entries in handles */ + void **handles; +} MprArray; + +#if BLD_FEATURE_SQUEEZE +#define MPR_ARRAY_INCR 8 +#else +#define MPR_ARRAY_INCR 16 +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/********************************* Prototypes *********************************/ +/* + * If running in the GoAhead WebServer, map some MPR routines to WebServer + * equivalents. + */ + +#if BLD_GOAHEAD_WEBSERVER +#include "uemf.h" +#define mprMalloc(size) balloc(B_L, size) +#define mprFree(ptr) bfreeSafe(B_L, ptr) +#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) +#define mprStrdup(ptr) bstrdup(B_L, ptr) +#define mprAllocSprintf fmtAlloc +#define mprAllocVsprintf fmtValloc +#define mprSprintf fmtStatic +#define mprItoa stritoa +#define mprLog trace +#define mprBreakpoint(file, line, cond) \ + error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) + +#else /* !BLD_GOAHEAD_WEBSERVER */ +/* #define mprMalloc malloc */ +#define mprSprintf snprintf +#define mtVsprintf vsnprintf +extern void *mprMalloc(uint size); +extern void *mprRealloc(void *ptr, uint size); +extern void mprFree(void *ptr); +extern char *mprStrdup(const char *str); +extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, + va_list args) PRINTF_ATTRIBUTE(3,0); +extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +extern char *mprItoa(int num, char *buf, int width); +extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +extern void mprBreakpoint(const char *file, int line, const char *msg); +#endif /* BLD_GOAHEAD_WEBSERVER */ + +extern MprArray *mprCreateArray(void); +extern void mprDestroyArray(MprArray *array); +extern int mprAddToArray(MprArray *array, void *item); +extern int mprRemoveFromArray(MprArray *array, int idx); +extern char *mprStrTok(char *str, const char *delim, char **tok); + +extern int mprGetDirName(char *buf, int bufsize, char *path); +extern int mprReallocStrcat(char **dest, int max, int existingLen, + const char *delim, const char *src, ...); +extern int mprStrcpy(char *dest, int destMax, const char *src); +extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); + +extern void mprSetCtx(void *ctx); +extern void *mprMemCtx(void); + +#ifdef __cplusplus +} +#endif +#endif /* !BLD_APPWEB */ +#endif /* _h_MINI_MPR */ + +/*****************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c new file mode 100644 index 0000000000..9d2afe5306 --- /dev/null +++ b/source4/lib/appweb/mpr/var.c @@ -0,0 +1,2197 @@ +/* + * @file var.c + * @brief MPR Universal Variable Type + * @overview + * + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ + +/* + * This module is NOT multithreaded. + * + * Properties are variables that are stored in an object type variable. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. + */ + +/********************************** Includes **********************************/ + +#include "var.h" + +/*********************************** Locals ***********************************/ +#if VAR_DEBUG + +static MprProperties objectList; /* Dummy head of objects list */ +static int objectCount = -1; /* Count of objects */ + +#endif +/***************************** Forward Declarations ***************************/ + +static int adjustRefCount(MprProperties *pp, int adj); +static int adjustVarRefCount(MprVar *vp, int adj); +static MprVar *allocProperty(const char *propertyName); +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); +static MprProperties + *createProperties(const char *name, int hashSize); +static bool freeVar(MprVar *vp, int force); +static bool freeVarStorage(MprVar *vp, int force); +static MprVar *getObjChain(MprProperties *pp, const char *property); +static int hash(MprProperties *pp, const char *property); +static bool releaseProperties(MprProperties *pp, int force); + +/*********************************** Code *************************************/ +/* + * Destroy a variable and all referenced variables. Release any referenced + * object regardless of whether other users still have references. Be VERY + * careful using this routine. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyAllVars(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all vars. + */ + return freeVar(vp, 1); +} + +/******************************************************************************/ +/* + * Destroy a variable. Release any referenced object (destroy if no other + * users are referencing). + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +bool mprDestroyVar(MprVar *vp) +{ + mprAssert(vp); + + if (vp->trigger) { + if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) + == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Free the actual value. If this var refers to an object, we will + * recurse through all the properties freeing all that have no other + * references. + */ + return freeVar(vp, 0); +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVar(MprVar *vp, int force) +{ + bool freed; + + mprAssert(vp); + + freed = freeVarStorage(vp, force); + + mprFree(vp->name); + mprFree(vp->fullName); + + if (vp->allocatedVar) { + mprFree(vp); + } else { + vp->name = 0; + vp->fullName = 0; + vp->type = MPR_TYPE_UNDEFINED; + } + return freed; +} + +/******************************************************************************/ +/* + * Free the value in a variable for primitive types. Release objects. + * + * Return TRUE if the underlying data is freed. Objects may not be freed if + * there are other users of the object. + */ + +static bool freeVarStorage(MprVar *vp, int force) +{ + MprArray *argList; + bool freed; + int i; + + freed = 1; + mprAssert(vp); + + switch (vp->type) { + default: + break; + + case MPR_TYPE_STRING: + if (vp->allocatedData && vp->string != 0) { + mprFree(vp->string); + vp->string = 0; + vp->allocatedData = 0; + } + break; + + case MPR_TYPE_OBJECT: +#if VAR_DEBUG + /* + * Recurse through all properties and release / delete. Release the + * properties hash table. + */ + if (vp->properties->refCount > 1) { + mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } else { + mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", + vp->name, vp->properties, vp->properties->refCount, force); + } +#endif + if (vp->allocatedData) { + freed = releaseProperties(vp->properties, force); + } + vp->properties = 0; + break; + + case MPR_TYPE_FUNCTION: + if (vp->allocatedData) { + argList = vp->function.args; + for (i = 0; i < argList->max; i++) { + if (argList->handles[i] != 0) { + mprFree(argList->handles[i]); + } + } + mprDestroyArray(argList); + vp->function.args = 0; + mprFree(vp->function.body); + vp->function.body = 0; + } + break; + } + + vp->type = MPR_TYPE_UNDEFINED; + return freed; +} + +/******************************************************************************/ +/* + * Adjust the object reference count and return the currrent count of + * users. + */ + +static int adjustVarRefCount(MprVar *vp, int adj) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, adj); +} + +/******************************************************************************/ +/* + * Get the object reference count + */ + +int mprGetVarRefCount(MprVar *vp) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + mprAssert(vp->type == MPR_TYPE_OBJECT); + return 0; + } + return adjustRefCount(vp->properties, 0); +} + +/******************************************************************************/ +/* + * Update the variable's name + */ + +void mprSetVarName(MprVar *vp, char *name) +{ + mprAssert(vp); + + mprFree(vp->name); + vp->name = mprStrdup(name); +} + +/******************************************************************************/ +/* + * Append to the variable's full name + */ + +void mprSetVarFullName(MprVar *vp, char *name) +{ +#if VAR_DEBUG + mprAssert(vp); + + mprFree(vp->fullName); + vp->fullName = mprStrdup(name); + if (vp->type == MPR_TYPE_OBJECT) { + if (strcmp(vp->properties->name, "this") == 0) { + mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); + } + } +#endif +} + +/******************************************************************************/ +/* + * Make a var impervious to recursive forced deletes. + */ + +void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) +{ + mprAssert(vp); + + if (vp->type == MPR_TYPE_OBJECT && vp->properties) { + vp->properties->deleteProtect = deleteProtect; + } +} + +/******************************************************************************/ +/* + * Make a variable readonly. Can still be deleted. + */ + +void mprSetVarReadonly(MprVar *vp, int readonly) +{ + mprAssert(vp); + + vp->readonly = readonly; +} + +/******************************************************************************/ + +MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) +{ + MprVarTrigger oldTrigger; + + mprAssert(vp); + mprAssert(fn); + + oldTrigger = vp->trigger; + vp->trigger = fn; + return oldTrigger; +} + +/******************************************************************************/ + +MprType mprGetVarType(MprVar *vp) +{ + mprAssert(vp); + + return vp->type; +} + +/******************************************************************************/ +/********************************** Properties ********************************/ +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. + */ + +MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, + MprVar *newValue) +{ + MprVar *prop, *last; + int bucketIndex; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + /* + * See if property already exists and locate the bucket to hold the + * property reference. + */ + last = 0; + bucketIndex = hash(obj->properties, propertyName); + prop = obj->properties->buckets[bucketIndex]; + + /* + * Find the property in the hash chain if it exists + */ + for (last = 0; prop; last = prop, prop = prop->forw) { + if (prop->name[0] == propertyName[0] && + strcmp(prop->name, propertyName) == 0) { + break; + } + } + + if (prop) { + /* FUTURE -- remove. Just for debug. */ + mprAssert(prop == 0); + mprLog(0, "Attempting to create property %s in object %s\n", + propertyName, obj->name); + return 0; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, + newValue, 0) == MPR_TRIGGER_ABORT) { + return 0; + } + } + + /* + * Create a new property + */ + prop = allocProperty(propertyName); + if (prop == 0) { + mprAssert(prop); + return 0; + } + + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + + prop->bucketIndex = bucketIndex; + if (last) { + last->forw = prop; + } else { + obj->properties->buckets[bucketIndex] = prop; + } + prop->parentProperties = obj->properties; + + /* + * Update the item counts + */ + obj->properties->numItems++; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems++; + } + + return prop; +} + +/******************************************************************************/ +/* + * Create a property in an object with a defined value. If the property + * already exists in the object, then just write its value. Same as + * mprCreateProperty except that the new value is passed by value rather than + * by pointer. + */ + +MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) +{ + return mprCreateProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Create a new property + */ + +static MprVar *allocProperty(const char *propertyName) +{ + MprVar *prop; + + prop = (MprVar*) mprMalloc(sizeof(MprVar)); + if (prop == 0) { + mprAssert(prop); + return 0; + } + memset(prop, 0, sizeof(MprVar)); + prop->allocatedVar = 1; + prop->name = mprStrdup(propertyName); + prop->forw = (MprVar*) 0; + + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it doesn not already exist. + */ + +MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) +{ + MprVar *prop, triggerValue; + int rc; + + mprAssert(obj); + mprAssert(propertyName && *propertyName); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(0); + return 0; + } + + prop = mprGetProperty(obj, propertyName, 0); + if (prop == 0) { + return mprCreateProperty(obj, propertyName, newValue); + } + + if (obj->trigger) { + /* + * Call the trigger before the update and pass it the new value. + */ + triggerValue = *newValue; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + /* + * Trigger must copy to triggerValue a variable that is not + * a structure copy of the existing data. + */ + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return prop; + } + } + copyVarCore(prop, newValue, MPR_SHALLOW_COPY); + return prop; +} + +/******************************************************************************/ +/* + * Update a property in an object with a defined value. Create the property + * if it does not already exist. Same as mprSetProperty except that the + * new value is passed by value rather than by pointer. + */ + +MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, + MprVar newValue) +{ + return mprSetProperty(obj, propertyName, &newValue); +} + +/******************************************************************************/ +/* + * Delete a property from this object + */ + +int mprDeleteProperty(MprVar *obj, const char *property) +{ + MprVar *prop, *last; + char *cp; + int bucketIndex; + + mprAssert(obj); + mprAssert(property && *property); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + last = 0; + bucketIndex = hash(obj->properties, property); + if ((prop = obj->properties->buckets[bucketIndex]) != 0) { + for ( ; prop; prop = prop->forw) { + cp = prop->name; + if (cp[0] == property[0] && strcmp(cp, property) == 0) { + break; + } + last = prop; + } + } + if (prop == (MprVar*) 0) { + mprAssert(prop); + return MPR_ERR_NOT_FOUND; + } + if (prop->readonly) { + mprAssert(! prop->readonly); + return MPR_ERR_READ_ONLY; + } + + if (obj->trigger) { + if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) + == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + } + } + + if (last) { + last->forw = prop->forw; + } else { + obj->properties->buckets[bucketIndex] = prop->forw; + } + + obj->properties->numItems--; + if (! mprVarIsFunction(prop->type)) { + obj->properties->numDataItems--; + } + + mprDestroyVar(prop); + + return 0; +} + +/******************************************************************************/ +/* + * Find a property in an object and return a pointer to it. If a value arg + * is supplied, then copy the data into the var. + */ + +MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) +{ + MprVar *prop, triggerValue; + int rc; + + if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || + *property == '\0') { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + + for (prop = getObjChain(obj->properties, property); prop; + prop = prop->forw) { + if (prop->name && + prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { + break; + } + } + if (prop == 0) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + } + if (value) { + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + /* + * Pass the trigger the current read value and may receive + * a new value. + */ + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + if (rc == MPR_TRIGGER_ABORT) { + if (value) { + value->type = MPR_TYPE_UNDEFINED; + } + return 0; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + } + } + /* + * Clone. No copy. + */ + *value = *prop; + } + return prop; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns the property's value. It does not + * copy object/string data but returns a pointer directly into the variable. + * The caller does not and should not call mprDestroy on the returned value. + * If value is null, just read the property and run triggers. + */ + +int mprReadProperty(MprVar *prop, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + if (value) { + *value = *prop; + + /* + * Just so that if the user calls mprDestroyVar on value, it will do no + * harm. + */ + value->allocatedVar = 0; + value->allocatedData = 0; + } + return 0; +} + +/******************************************************************************/ +/* + * Read a properties value. This returns a copy of the property variable. + * However, if the property is an object or string, it returns a copy of the + * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, + * then the underlying objects and strings data will be copied as well. If + * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If + * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the + * user must call mprDestroyVar to free resources. This routine will run any + * registered triggers which may modify the value the user receives (without + * updating the properties real value). + * + * WARNING: the args are reversed to most other APIs. This conforms to the + * strcpy(dest, src) standard instead. + */ + +int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) +{ + MprVar triggerValue; + int rc; + + mprAssert(prop); + mprAssert(dest); + + if (prop->trigger) { + triggerValue = *prop; + triggerValue.allocatedVar = 0; + triggerValue.allocatedData = 0; + rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, + &triggerValue, copyDepth); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + } + mprCopyVar(dest, prop, copyDepth); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWriteProperty(MprVar *vp, MprVar *value) +{ + MprVar triggerValue; + int rc; + + mprAssert(vp); + mprAssert(value); + + if (vp->readonly) { + return MPR_ERR_READ_ONLY; + } + + if (vp->trigger) { + triggerValue = *value; + + rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, + &triggerValue, 0); + + if (rc == MPR_TRIGGER_ABORT) { + return MPR_ERR_ABORTED; + + } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { + copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); + mprDestroyVar(&triggerValue); + return 0; + } + /* Fall through */ + } + + copyVarCore(vp, value, MPR_SHALLOW_COPY); + return 0; +} + +/******************************************************************************/ +/* + * Write a new value into an existing property in an object. + */ + +int mprWritePropertyValue(MprVar *vp, MprVar value) +{ + mprAssert(vp); + + return mprWriteProperty(vp, &value); +} + +/******************************************************************************/ +/* + * Get the count of properties. + */ + +int mprGetPropertyCount(MprVar *vp, int includeFlags) +{ + mprAssert(vp); + + if (vp->type != MPR_TYPE_OBJECT) { + return 0; + } + if (includeFlags == MPR_ENUM_DATA) { + return vp->properties->numDataItems; + } else { + return vp->properties->numItems; + } +} + +/******************************************************************************/ +/* + * Get the first property in an object. Used for walking all properties in an + * object. + */ + +MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) +{ + MprVar *prop; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + + for (i = 0; i < (int) obj->properties->hashSize; i++) { + for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { + if (prop) { + if (mprVarIsFunction(prop->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return prop; + } + break; + } + } + return 0; +} + +/******************************************************************************/ +/* + * Get the next property in sequence. + */ + +MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) +{ + MprProperties *properties; + int i; + + mprAssert(obj); + mprAssert(obj->type == MPR_TYPE_OBJECT); + + if (obj->type != MPR_TYPE_OBJECT) { + mprAssert(obj->type == MPR_TYPE_OBJECT); + return 0; + } + properties = obj->properties; + + if (last->forw) { + return last->forw; + } + + for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { + for (last = properties->buckets[i]; last; last = last->forw) { + if (mprVarIsFunction(last->type)) { + if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { + continue; + } + } else { + if (!(includeFlags & MPR_ENUM_DATA)) { + continue; + } + } + return last; + } + } + return 0; +} + +/******************************************************************************/ +/************************** Internal Support Routines *************************/ +/******************************************************************************/ +/* + * Create an hash table to hold and index properties. Properties are just + * variables which may contain primitive data types, functions or other + * objects. The hash table is the essence of an object. HashSize specifies + * the size of the hash table to use and should be a prime number. + */ + +static MprProperties *createProperties(const char *name, int hashSize) +{ + MprProperties *pp; + + if (hashSize < 7) { + hashSize = 7; + } + if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { + mprAssert(0); + return 0; + } + mprAssert(pp); + memset(pp, 0, sizeof(MprProperties)); + + pp->numItems = 0; + pp->numDataItems = 0; + pp->hashSize = hashSize; + pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); + mprAssert(pp->buckets); + memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); + pp->refCount = 1; + +#if VAR_DEBUG + if (objectCount == -1) { + objectCount = 0; + objectList.next = objectList.prev = &objectList; + } + + mprStrcpy(pp->name, sizeof(pp->name), name); + pp->next = &objectList; + pp->prev = objectList.prev; + objectList.prev->next = pp; + objectList.prev = pp; + objectCount++; +#endif + return pp; +} + +/******************************************************************************/ +/* + * Release an object's properties hash table. If this is the last person + * using it, free it. Return TRUE if the object is released. + */ + +static bool releaseProperties(MprProperties *obj, int force) +{ + MprProperties *pp; + MprVar *prop, *forw; + int i; + + mprAssert(obj); + mprAssert(obj->refCount > 0); + +#if VAR_DEBUG + /* + * Debug sanity check + */ + mprAssert(obj->refCount < 20); +#endif + + if (--obj->refCount > 0 && !force) { + return 0; + } + +#if VAR_DEBUG + mprAssert(obj->prev); + mprAssert(obj->next); + mprAssert(obj->next->prev); + mprAssert(obj->prev->next); + obj->next->prev = obj->prev; + obj->prev->next = obj->next; + objectCount--; +#endif + + for (i = 0; i < (int) obj->hashSize; i++) { + for (prop = obj->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->type == MPR_TYPE_OBJECT) { + + if (prop->properties == obj) { + /* Self reference */ + continue; + } + pp = prop->properties; + if (pp->visited) { + continue; + } + + pp->visited = 1; + if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { + pp->visited = 0; + } + + } else { + freeVar(prop, force); + } + } + } + + mprFree((void*) obj->buckets); + mprFree((void*) obj); + + return 1; +} + +/******************************************************************************/ +/* + * Adjust the reference count + */ + +static int adjustRefCount(MprProperties *pp, int adj) +{ + mprAssert(pp); + + /* + * Debug sanity check + */ + mprAssert(pp->refCount < 20); + + return pp->refCount += adj; +} + +/******************************************************************************/ +#if VAR_DEBUG +/* + * Print objects held + */ + +void mprPrintObjects(char *msg) +{ + MprProperties *pp, *np; + MprVar *prop, *forw; + char *buf; + int i; + + mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); + pp = objectList.next; + while (pp != &objectList) { + mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", + pp->name, pp, pp->refCount, pp->numItems); + for (i = 0; i < (int) pp->hashSize; i++) { + for (prop = pp->buckets[i]; prop; prop = forw) { + forw = prop->forw; + if (prop->properties == pp) { + /* Self reference */ + continue; + } + mprVarToString(&buf, MPR_MAX_STRING, 0, prop); + if (prop->type == MPR_TYPE_OBJECT) { + np = objectList.next; + while (np != &objectList) { + if (prop->properties == np) { + break; + } + np = np->next; + } + if (prop->properties == np) { + mprLog(7, " %s: OBJECT 0x%x, <%s>\n", + prop->name, prop->properties, prop->fullName); + } else { + mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", + prop->name, buf, prop->fullName); + } + } else { + mprLog(7, " %s: <%s> = %s\n", prop->name, + prop->fullName, buf); + } + mprFree(buf); + } + } + pp = pp->next; + } +} + +/******************************************************************************/ + +void mprPrintObjRefCount(MprVar *vp) +{ + mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, + vp->properties->refCount); +} + +#endif +/******************************************************************************/ +/* + * Get the bucket chain containing a property. + */ + +static MprVar *getObjChain(MprProperties *obj, const char *property) +{ + mprAssert(obj); + + return obj->buckets[hash(obj, property)]; +} + +/******************************************************************************/ +/* + * Fast hash. The history of this algorithm is part of lost computer science + * folk lore. + */ + +static int hash(MprProperties *pp, const char *property) +{ + uint sum; + + mprAssert(pp); + mprAssert(property); + + sum = 0; + while (*property) { + sum += (sum * 33) + *property++; + } + + return sum % pp->hashSize; +} + +/******************************************************************************/ +/*********************************** Constructors *****************************/ +/******************************************************************************/ +/* + * Initialize an undefined value. + */ + +MprVar mprCreateUndefinedVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_UNDEFINED; + return v; +} + +/******************************************************************************/ +/* + * Initialize an null value. + */ + +MprVar mprCreateNullVar() +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_NULL; + return v; +} + +/******************************************************************************/ + +MprVar mprCreateBoolVar(bool value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_BOOL; + v.boolean = value; + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_CFUNCTION; + v.cFunction.fn = fn; + v.cFunction.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +/* + * Initialize a C function. + */ + +MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, + int flags) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING_CFUNCTION; + v.cFunctionWithStrings.fn = fn; + v.cFunctionWithStrings.thisPtr = thisPtr; + v.flags = flags; + + return v; +} + +/******************************************************************************/ +/* + * Initialize an opaque pointer. + */ + +MprVar mprCreatePtrVar(void *ptr) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_PTR; + v.ptr = ptr; + + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Initialize a floating value. + */ + +MprVar mprCreateFloatVar(double value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FLOAT; + v.floating = value; + return v; +} + +#endif +/******************************************************************************/ +/* + * Initialize an integer value. + */ + +MprVar mprCreateIntegerVar(int value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT; + v.integer = value; + return v; +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Initialize a 64-bit integer value. + */ + +MprVar mprCreateInteger64Var(int64 value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_INT64; + v.integer64 = value; + return v; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Initialize an number variable. Type is defined by configure. + */ + +MprVar mprCreateNumberVar(MprNum value) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = BLD_FEATURE_NUM_TYPE_ID; +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + v.integer64 = value; +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + v.float = value; +#else + v.integer = value; +#endif + return v; +} + +/******************************************************************************/ +/* + * Initialize a (bare) JavaScript function. args and body can be null. + */ + +MprVar mprCreateFunctionVar(char *args, char *body, int flags) +{ + MprVar v; + char *cp, *arg, *last; + int aid; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_FUNCTION; + v.flags = flags; + + v.function.args = mprCreateArray(); + + if (args) { + args = mprStrdup(args); + arg = mprStrTok(args, ",", &last); + while (arg) { + while (isspace((int) *arg)) + arg++; + for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { + if (!isspace((int) *cp)) { + break; + } + } + cp[1] = '\0'; + + aid = mprAddToArray(v.function.args, mprStrdup(arg)); + arg = mprStrTok(0, ",", &last); + } + mprFree(args); + } + + if (body) { + v.function.body = mprStrdup(body); + } + v.allocatedData = 1; + return v; +} + +/******************************************************************************/ +/* + * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the + * memory allocation for the properties table failed. + */ + +MprVar mprCreateObjVar(const char *name, int hashSize) +{ + MprVar v; + + mprAssert(name && *name); + + memset(&v, 0x0, sizeof(MprVar)); + v.type = MPR_TYPE_OBJECT; + if (hashSize <= 0) { + hashSize = MPR_DEFAULT_HASH_SIZE; + } + v.properties = createProperties(name, hashSize); + if (v.properties == 0) { + /* Indicate failed memory allocation */ + v.type = MPR_TYPE_UNDEFINED; + } + v.allocatedData = 1; + v.name = mprStrdup(name); + mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); + return v; +} + +/******************************************************************************/ +/* + * Initialize a string value. + */ + +MprVar mprCreateStringVar(const char *value, bool allocate) +{ + MprVar v; + + memset(&v, 0x0, sizeof(v)); + v.type = MPR_TYPE_STRING; + if (value == 0) { + v.string = ""; + } else if (allocate) { + v.string = mprStrdup(value); + v.allocatedData = 1; + } else { + v.string = (char*) value; + } + return v; +} + +/******************************************************************************/ +/* + * Copy an objects core value (only). This preserves the destination object's + * name. This implements copy by reference for objects and copy by value for + * strings and other types. Caller must free dest prior to calling. + */ + +static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) +{ + MprVarTrigger saveTrigger; + MprVar *srcProp, *destProp, *last; + char **srcArgs; + int i; + + mprAssert(dest); + mprAssert(src); + + if (dest == src) { + return; + } + + /* + * FUTURE: we should allow read-only triggers where the value is never + * stored in the object. Currently, triggers override the readonly + * status. + */ + + if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { + mprAssert(0); + return; + } + + if (dest->type != MPR_TYPE_UNDEFINED) { + saveTrigger = dest->trigger; + freeVarStorage(dest, 0); + } else { + saveTrigger = 0; + } + + switch (src->type) { + default: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + break; + + case MPR_TYPE_BOOL: + dest->boolean = src->boolean; + break; + + case MPR_TYPE_PTR: + dest->ptr = src->ptr; + break; + + case MPR_TYPE_STRING_CFUNCTION: + dest->cFunctionWithStrings = src->cFunctionWithStrings; + break; + + case MPR_TYPE_CFUNCTION: + dest->cFunction = src->cFunction; + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + dest->floating = src->floating; + break; +#endif + + case MPR_TYPE_INT: + dest->integer = src->integer; + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + dest->integer64 = src->integer64; + break; +#endif + + case MPR_TYPE_OBJECT: + if (copyDepth == MPR_DEEP_COPY) { + + dest->properties = createProperties(src->name, + src->properties->hashSize); + dest->allocatedData = 1; + + for (i = 0; i < (int) src->properties->hashSize; i++) { + last = 0; + for (srcProp = src->properties->buckets[i]; srcProp; + srcProp = srcProp->forw) { + if (srcProp->visited) { + continue; + } + destProp = allocProperty(srcProp->name); + if (destProp == 0) { + mprAssert(destProp); + return; + } + + destProp->bucketIndex = i; + if (last) { + last->forw = destProp; + } else { + dest->properties->buckets[i] = destProp; + } + destProp->parentProperties = dest->properties; + + /* + * Recursively copy the object + */ + srcProp->visited = 1; + copyVarCore(destProp, srcProp, copyDepth); + srcProp->visited = 0; + last = srcProp; + } + } + dest->properties->numItems = src->properties->numItems; + dest->properties->numDataItems = src->properties->numDataItems; + dest->allocatedData = 1; + + } else if (copyDepth == MPR_SHALLOW_COPY) { + dest->properties = src->properties; + adjustVarRefCount(src, 1); + dest->allocatedData = 1; + + } else { + dest->properties = src->properties; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_FUNCTION: + if (copyDepth != MPR_NO_COPY) { + dest->function.args = mprCreateArray(); + srcArgs = (char**) src->function.args->handles; + for (i = 0; i < src->function.args->max; i++) { + if (srcArgs[i]) { + mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); + } + } + dest->function.body = mprStrdup(src->function.body); + dest->allocatedData = 1; + } else { + dest->function.args = src->function.args; + dest->function.body = src->function.body; + dest->allocatedData = 0; + } + break; + + case MPR_TYPE_STRING: + if (src->string && copyDepth != MPR_NO_COPY) { + dest->string = mprStrdup(src->string); + dest->allocatedData = 1; + } else { + dest->string = src->string; + dest->allocatedData = 0; + } + break; + } + + dest->type = src->type; + dest->flags = src->flags; + dest->trigger = saveTrigger; + + /* + * Just for safety + */ + dest->spare = 0; +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) +{ + mprAssert(dest); + mprAssert(src); + + copyVarCore(dest, src, copyDepth); + + mprFree(dest->name); + dest->name = mprStrdup(src->name); + +#if VAR_DEBUG + if (src->type == MPR_TYPE_OBJECT) { + + mprFree(dest->fullName); + dest->fullName = mprStrdup(src->fullName); + + mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", + dest->name, dest->fullName, dest->properties, + dest->properties->refCount); + } +#endif +} + +/******************************************************************************/ +/* + * Copy an entire object including name. + */ + +void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) +{ + mprAssert(dest); + + mprCopyVar(dest, &src, copyDepth); +} + +/******************************************************************************/ +/* + * Copy an object. This implements copy by reference for objects and copy by + * value for strings and other types. Caller must free dest prior to calling. + */ + +MprVar *mprDupVar(MprVar *src, int copyDepth) +{ + MprVar *dest; + + mprAssert(src); + + dest = (MprVar*) mprMalloc(sizeof(MprVar)); + memset(dest, 0, sizeof(MprVar)); + + mprCopyVar(dest, src, copyDepth); + return dest; +} + +/******************************************************************************/ +/* + * Convert a value to a text based representation of its value + * FUTURE -- conver this to use the format string in all cases. Allow + * arbitrary format strings. + */ + +void mprVarToString(char** out, int size, char *fmt, MprVar *obj) +{ + char *src; + + mprAssert(out); + + *out = NULL; + + if (obj->trigger) { + mprReadProperty(obj, 0); + } + + switch (obj->type) { + case MPR_TYPE_UNDEFINED: + /* FUTURE -- spec says convert to "undefined" */ + *out = mprStrdup(""); + break; + + case MPR_TYPE_NULL: + *out = mprStrdup("null"); + break; + + case MPR_TYPE_PTR: + mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); + break; + + case MPR_TYPE_BOOL: + if (obj->boolean) { + *out = mprStrdup("true"); + } else { + *out = mprStrdup("false"); + } + break; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%f", obj->floating); + } else { + mprAllocSprintf(out, size, fmt, obj->floating); + } + break; +#endif + + case MPR_TYPE_INT: + if (fmt == NULL || *fmt == '\0') { + mprAllocSprintf(out, size, "%d", obj->integer); + } else { + mprAllocSprintf(out, size, fmt, obj->integer); + } + break; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + if (fmt == NULL || *fmt == '\0') { +#if BLD_GOAHEAD_WEBSERVER + mprAllocSprintf(out, size, "%d", (int) obj->integer64); +#else + mprAllocSprintf(out, size, "%Ld", obj->integer64); +#endif + } else { + mprAllocSprintf(out, size, fmt, obj->integer64); + } + break; +#endif + + case MPR_TYPE_CFUNCTION: + mprAllocSprintf(out, size, "[C Function]"); + break; + + case MPR_TYPE_STRING_CFUNCTION: + mprAllocSprintf(out, size, "[C StringFunction]"); + break; + + case MPR_TYPE_FUNCTION: + mprAllocSprintf(out, size, "[JavaScript Function]"); + break; + + case MPR_TYPE_OBJECT: + /* FUTURE -- really want: [object class: name] */ + mprAllocSprintf(out, size, "[object %s]", obj->name); + break; + + case MPR_TYPE_STRING: + src = obj->string; + + mprAssert(src); + if (fmt && *fmt) { + mprAllocSprintf(out, size, fmt, src); + + } else if (src == NULL) { + *out = mprStrdup("null"); + + } else { + *out = mprStrdup(src); + } + break; + + default: + mprAssert(0); + } +} + +/******************************************************************************/ +/* + * Parse a string based on formatting instructions and intelligently + * create a variable. + */ + +MprVar mprParseVar(char *buf, MprType preferredType) +{ + MprType type = MPR_TYPE_UNDEFINED; + char *cp; + + mprAssert(buf); + + if (preferredType == MPR_TYPE_UNDEFINED) { + if (*buf == '-') { + type = MPR_NUM_VAR; + + } else if (!isdigit((int) *buf)) { + if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { + type = MPR_TYPE_BOOL; + } else { + type = MPR_TYPE_STRING; + } + + } else if (isdigit((int) *buf)) { + type = MPR_NUM_VAR; + cp = buf; + if (*cp && tolower((unsigned char)cp[1]) == 'x') { + cp = &cp[2]; + } + for (cp = buf; *cp; cp++) { + if (! isdigit((unsigned char) *cp)) { + break; + } + } + + if (*cp != '\0') { +#if BLD_FEATURE_FLOATING_POINT + if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { + type = MPR_TYPE_FLOAT; + } else +#endif + { + type = MPR_NUM_VAR; + } + } + } + } else { + type = preferredType; + } + + switch (type) { + case MPR_TYPE_OBJECT: + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_PTR: + default: + break; + + case MPR_TYPE_BOOL: + return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); + + case MPR_TYPE_INT: + return mprCreateIntegerVar(mprParseInteger(buf)); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return mprCreateInteger64Var(mprParseInteger64(buf)); +#endif + + case MPR_TYPE_STRING: + if (strcmp(buf, "null") == 0) { + return mprCreateNullVar(); + } else if (strcmp(buf, "undefined") == 0) { + return mprCreateUndefinedVar(); + } + + return mprCreateStringVar(buf, 1); + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return mprCreateFloatVar(atof(buf)); +#endif + + } + return mprCreateUndefinedVar(); +} + +/******************************************************************************/ +/* + * Convert the variable to a boolean. Only for primitive types. + */ + +bool mprVarToBool(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + return 0; + + case MPR_TYPE_PTR: + return (vp->ptr != NULL); + + case MPR_TYPE_BOOL: + return vp->boolean; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + return (vp->floating != 0 && !mprIsNan(vp->floating)); +#endif + + case MPR_TYPE_INT: + return (vp->integer != 0); + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (vp->integer64 != 0); +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return (vp->string[0] != '\0'); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the variable to a floating point number. Only for primitive types. + */ + +double mprVarToFloat(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1.0 : 0.0; + + case MPR_TYPE_FLOAT: + return vp->floating; + + case MPR_TYPE_INT: + return (double) vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (double) vp->integer64; +#endif + + case MPR_TYPE_STRING: + mprAssert(vp->string); + return atof(vp->string); + } + + /* Not reached */ + return 0; +} + +#endif +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprVarToNumber(const MprVar *vp) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprVarToInteger64(vp); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprVarToFloat(vp); +#else + return mprVarToInteger(vp); +#endif +} + +/******************************************************************************/ +/* + * Convert the variable to a number type. Only works for primitive types. + */ + +MprNum mprParseNumber(char *s) +{ +#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 + return mprParseInteger64(s); +#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT + return mprParseFloat(s); +#else + return mprParseInteger(s); +#endif +} + +/******************************************************************************/ +#if BLD_FEATURE_INT64 +/* + * Convert the variable to an Integer64 type. Only works for primitive types. + */ + +int64 mprVarToInteger64(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int64) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + + case MPR_TYPE_INT64: + return vp->integer64; + + case MPR_TYPE_STRING: + return mprParseInteger64(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer64. + */ + +int64 mprParseInteger64(char *str) +{ + char *cp; + int64 num64; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num64 = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num64 = (*cp - '0') + (num64 * 10); + cp++; + } + } else { + cp++; + if (tolower((unsigned char)*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c)) { + num64 = (c - '0') + (num64 * radix); + } else if (c >= 'a' && c <= 'f') { + num64 = (c - 'a') + (num64 * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c) && c < '8') { + num64 = (c - '0') + (num64 * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num64; + } + return num64; +} + +#endif /* BLD_FEATURE_INT64 */ +/******************************************************************************/ +/* + * Convert the variable to an Integer type. Only works for primitive types. + */ + +int mprVarToInteger(const MprVar *vp) +{ + mprAssert(vp); + + switch (vp->type) { + case MPR_TYPE_UNDEFINED: + case MPR_TYPE_NULL: + case MPR_TYPE_STRING_CFUNCTION: + case MPR_TYPE_CFUNCTION: + case MPR_TYPE_FUNCTION: + case MPR_TYPE_OBJECT: + case MPR_TYPE_PTR: + return 0; + + case MPR_TYPE_BOOL: + return (vp->boolean) ? 1 : 0; + +#if BLD_FEATURE_FLOATING_POINT + case MPR_TYPE_FLOAT: + if (mprIsNan(vp->floating)) { + return 0; + } + return (int) vp->floating; +#endif + + case MPR_TYPE_INT: + return vp->integer; + +#if BLD_FEATURE_INT64 + case MPR_TYPE_INT64: + return (int) vp->integer64; +#endif + + case MPR_TYPE_STRING: + return mprParseInteger(vp->string); + } + + /* Not reached */ + return 0; +} + +/******************************************************************************/ +/* + * Convert the string buffer to an Integer. + */ + +int mprParseInteger(char *str) +{ + char *cp; + int num; + int radix, c, negative; + + mprAssert(str); + + cp = str; + num = 0; + negative = 0; + + if (*cp == '-') { + cp++; + negative = 1; + } + + /* + * Parse a number. Observe hex and octal prefixes (0x, 0) + */ + if (*cp != '0') { + /* + * Normal numbers (Radix 10) + */ + while (isdigit((int) *cp)) { + num = (*cp - '0') + (num * 10); + cp++; + } + } else { + cp++; + if (tolower((unsigned char)*cp) == 'x') { + cp++; + radix = 16; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c)) { + num = (c - '0') + (num * radix); + } else if (c >= 'a' && c <= 'f') { + num = (c - 'a') + (num * radix); + } else { + break; + } + cp++; + } + + } else{ + radix = 8; + while (*cp) { + c = tolower((unsigned char)*cp); + if (isdigit(c) && c < '8') { + num = (c - '0') + (num * radix); + } else { + break; + } + cp++; + } + } + } + + if (negative) { + return 0 - num; + } + return num; +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Convert the string buffer to an Floating. + */ + +double mprParseFloat(char *str) +{ + return atof(str); +} + +/******************************************************************************/ + +bool mprIsNan(double f) +{ +#if WIN + return _isnan(f); +#elif VXWORKS + /* FUTURE */ + return (0); +#else + return (f == FP_NAN); +#endif +} +/******************************************************************************/ + +bool mprIsInfinite(double f) +{ +#if WIN + return !_finite(f); +#elif VXWORKS + /* FUTURE */ + return (0); +#else + return (f == FP_INFINITE); +#endif +} + +#endif /* BLD_FEATURE_FLOATING_POINT */ +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/source4/lib/appweb/mpr/var.h b/source4/lib/appweb/mpr/var.h new file mode 100644 index 0000000000..8ed13a4995 --- /dev/null +++ b/source4/lib/appweb/mpr/var.h @@ -0,0 +1,496 @@ +/* + * @file var.h + * @brief MPR Universal Variable Type + * @copy default.m + * + * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. + * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; 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 (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/******************************* Documentation ********************************/ +/* + * Variables can efficiently store primitive types and can hold references to + * objects. Objects can store properties which are themselves variables. + * Properties can be primitive data types, other objects or functions. + * Properties are indexed by a character name. A variable may store one of + * the following types: + * + * string, integer, integer-64bit, C function, C function with string args, + * Javascript function, Floating point number, boolean value, Undefined + * value and the Null value. + * + * Variables have names while objects may be referenced by multiple variables. + * Objects use reference counting for garbage collection. + * + * This module is not thread safe for performance and compactness. It relies + * on upper modules to provide thread synchronization as required. The API + * provides primitives to get variable/object references or to get copies of + * variables which will help minimize required lock times. + */ + +#ifndef _h_MPR_VAR +#define _h_MPR_VAR 1 + +/********************************* Includes ***********************************/ + +#include "miniMpr.h" + +/********************************** Defines ***********************************/ + +/* + * Define VAR_DEBUG if you want to track objects. However, this code is not + * thread safe and you need to run the server single threaded. + * + * #define VAR_DEBUG 1 + */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Forward declare types + */ +struct MprProperties; +struct MprVar; + +/* + * Possible variable types. Don't use enum because we need to be able to + * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. + */ +typedef int MprType; +#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ +#define MPR_TYPE_NULL 1 /* Value defined to be null. */ +#define MPR_TYPE_BOOL 2 /* Boolean type. */ +#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ +#define MPR_TYPE_FLOAT 4 /* Floating point number */ +#define MPR_TYPE_INT 5 /* Integer number */ +#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ +#define MPR_TYPE_OBJECT 7 /* Object reference */ +#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ +#define MPR_TYPE_STRING 9 /* String (immutable) */ +#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ +#define MPR_TYPE_PTR 11 /* Opaque pointer */ + +/* + * Create a type for the default number type + * Config.h will define the default number type. For example: + * + * BLD_FEATURE_NUM_TYPE=int + * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT + */ + +/** + * Set to the type used for MPR numeric variables. Will equate to int, int64 + * or double. + */ +typedef BLD_FEATURE_NUM_TYPE MprNum; + +/** + * Set to the MPR_TYPE used for MPR numeric variables. Will equate to + * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. + */ +#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID +#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID + +/* + * Return TRUE if a variable is a function type + */ +#define mprVarIsFunction(type) \ + (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ + type == MPR_TYPE_CFUNCTION) + +/* + * Return TRUE if a variable is a numeric type + */ +#define mprVarIsNumber(type) \ + (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) + +/* + * Return TRUE if a variable is a boolean + */ +#define mprVarIsBoolean(type) \ + (type == MPR_TYPE_BOOL) +#define mprVarIsString(type) \ + (type == MPR_TYPE_STRING) +#define mprVarIsObject(type) \ + (type == MPR_TYPE_OBJECT) +#define mprVarIsFloating(type) \ + (type == MPR_TYPE_FLOAT) +#define mprVarIsPtr(type) \ + (type == MPR_TYPE_PTR) +#define mprVarIsUndefined(var) \ + ((var)->type == MPR_TYPE_UNDEFINED) +#define mprVarIsNull(var) \ + ((var)->type == MPR_TYPE_NULL) +#define mprVarIsValid(var) \ + (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) + +#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ + +#if BLD_FEATURE_SQUEEZE +#define MPR_MAX_VAR 64 /* Max var full name */ +#else +#define MPR_MAX_VAR 512 +#endif + +#ifndef __NO_PACK +#pragma pack(2) +#endif /* _NO_PACK */ + +/* + * Function signatures + */ +typedef int MprVarHandle; +typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, + struct MprVar **argv); +typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, + char **argv); + +/* + * Triggers + */ +typedef enum { + MPR_VAR_WRITE, /* This property is being updated */ + MPR_VAR_READ, /* This property is being read */ + MPR_VAR_CREATE_PROPERTY, /* A property is being created */ + MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ + MPR_VAR_DELETE /* This object is being deleted */ +} MprVarTriggerOp; + +/* + * Trigger function return codes. + */ +typedef enum { + MPR_TRIGGER_ABORT, /* Abort the current operation */ + MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ + MPR_TRIGGER_PROCEED /* Proceed with the operation */ +} MprVarTriggerStatus; + +/* + * The MprVarTrigger arguments have the following meaning: + * + * op The operation being performed. See MprVarTriggerOp. + * parentProperties Pointer to the MprProperties structure. + * vp Pointer to the property that registered the trigger. + * newValue New value (see below for more details). + * copyDepth Specify what data items to copy. + * + * For VAR_READ, newVar is set to a temporary variable that the trigger + * function may assign a value to be returned instead of the actual + * property value. + * For VAR_WRITE, newValue holds the new value. The old existing value may be + * accessed via vp. + * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. + * For ADD_PROPERTY, vp is set to the property being added and newValue holds + * the new value. + */ +typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, + struct MprProperties *parentProperties, struct MprVar *vp, + struct MprVar *newValue, int copyDepth); + +/* + * mprCreateFunctionVar flags + */ +/** Use the alternate handle on function callbacks */ +#define MPR_VAR_ALT_HANDLE 0x1 + +/** Use the script handle on function callbacks */ +#define MPR_VAR_SCRIPT_HANDLE 0x2 + +/* + * Useful define for the copyDepth argument + */ +/** Don't copy any data. Copy only the variable name */ +#define MPR_NO_COPY 0 + +/** Copy strings. Increment object reference counts. */ +#define MPR_SHALLOW_COPY 1 + +/** Copy strings and do complete object copies. */ +#define MPR_DEEP_COPY 2 + +/* + * GetFirst / GetNext flags + */ +/** Step into data properties. */ +#define MPR_ENUM_DATA 0x1 + +/** Step into functions properties. */ +#define MPR_ENUM_FUNCTIONS 0x2 + +/* + * Collection type to hold properties in an object + */ +typedef struct MprProperties { /* Collection of properties */ +#if VAR_DEBUG + struct MprProperties *next; /* Linked list */ + struct MprProperties *prev; /* Linked list */ + char name[32]; /* Debug name */ +#endif + struct MprVar **buckets; /* Hash chains */ + int numItems; /* Total count of items */ + /* FUTURE - Better way of doing this */ + int numDataItems; /* Enumerable data items */ + uint hashSize : 8; /* Size of the hash table */ + /* FUTURE -- increase size of refCount */ + uint refCount : 8; /* References to this property*/ + /* FUTURE - make these flags */ + uint deleteProtect : 8; /* Don't recursively delete */ + uint visited : 8; /* Node has been processed */ +} MprProperties; + +/* + * Universal Variable Type + */ +typedef struct MprVar { + /* FUTURE - remove name to outside reference */ + MprStr name; /* Property name */ + /* FUTURE - remove */ + MprStr fullName; /* Full object name */ + /* FUTURE - make part of the union */ + MprProperties *properties; /* Pointer to properties */ + + /* + * Packed bit field + */ + MprType type : 8; /* Selector into union */ + uint bucketIndex : 8; /* Copy of bucket index */ + + uint flags : 5; /* Type specific flags */ + uint allocatedData : 1; /* Data needs freeing */ + uint readonly : 1; /* Unmodifiable */ + uint deleteProtect : 1; /* Don't recursively delete */ + + uint visited : 1; /* Node has been processed */ + uint allocatedVar : 1; /* Var needs freeing */ + uint spare : 6; /* Unused */ + + struct MprVar *forw; /* Hash table linkage */ + MprVarTrigger trigger; /* Trigger function */ + +#if UNUSED && KEEP + struct MprVar *baseClass; /* Pointer to class object */ +#endif + MprProperties *parentProperties; /* Pointer to parent object */ + + /* + * Union of primitive types. When debugging on Linux, don't use unions + * as the gdb debugger can't display them. + */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + union { +#endif + int boolean; /* Use int for speed */ +#if BLD_FEATURE_FLOATING_POINT + double floating; +#endif + int integer; +#if BLD_FEATURE_INT64 + int64 integer64; +#endif + struct { /* Javascript functions */ + MprArray *args; /* Null terminated */ + char *body; + } function; + struct { /* Function with MprVar args */ + MprCFunction fn; + void *thisPtr; + } cFunction; + struct { /* Function with string args */ + MprStringCFunction fn; + void *thisPtr; + } cFunctionWithStrings; + MprStr string; /* Allocated string */ + void *ptr; /* Opaque pointer */ +#if !BLD_DEBUG && !LINUX && !VXWORKS + }; +#endif +} MprVar; + +/* + * Define a field macro so code an use numbers in a "generic" fashion. + */ +#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN +/* Default numeric type */ +#define mprNumber integer +#endif +#if MPR_NUM_VAR == MPR_TYPE_INT64 +/* Default numeric type */ +#define mprNumber integer64 +#endif +#if MPR_NUM_VAR == MPR_TYPE_FLOAT +/* Default numeric type */ +#define mprNumber floating +#endif + +typedef BLD_FEATURE_NUM_TYPE MprNumber; + + +#ifndef __NO_PACK +#pragma pack() +#endif /* __NO_PACK */ + +/********************************* Prototypes *********************************/ +/* + * Variable constructors and destructors + */ +extern MprVar mprCreateObjVar(const char *name, int hashSize); +extern MprVar mprCreateBoolVar(bool value); +extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, + int flags); +#if BLD_FEATURE_FLOATING_POINT +extern MprVar mprCreateFloatVar(double value); +#endif +extern MprVar mprCreateIntegerVar(int value); +#if BLD_FEATURE_INT64 +extern MprVar mprCreateInteger64Var(int64 value); +#endif +extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); +extern MprVar mprCreateNullVar(void); +extern MprVar mprCreateNumberVar(MprNumber value); +extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, + void *thisPtr, int flags); +extern MprVar mprCreateStringVar(const char *value, bool allocate); +extern MprVar mprCreateUndefinedVar(void); +extern MprVar mprCreatePtrVar(void *ptr); +extern bool mprDestroyVar(MprVar *vp); +extern bool mprDestroyAllVars(MprVar* vp); +extern MprType mprGetVarType(MprVar *vp); + +/* + * Copy + */ +extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); +extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); +extern MprVar *mprDupVar(MprVar *src, int copyDepth); + +/* + * Manage vars + */ +extern MprVarTrigger + mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); +extern int mprGetVarRefCount(MprVar *vp); +extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); +extern void mprSetVarFullName(MprVar *vp, char *name); +extern void mprSetVarReadonly(MprVar *vp, int readonly); +extern void mprSetVarName(MprVar *vp, char *name); + +/* + * Create properties and return a reference to the property. + */ +extern MprVar *mprCreateProperty(MprVar *obj, const char *property, + MprVar *newValue); +extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, + MprVar newValue); +extern int mprDeleteProperty(MprVar *obj, const char *property); + +/* + * Get/Set properties. Set will update/create. + */ +extern MprVar *mprGetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetProperty(MprVar *obj, const char *property, + MprVar *value); +extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, + MprVar value); + +/* + * Directly read/write property values (the property must already exist) + * For mprCopyProperty, mprDestroyVar must always called on the var. + */ +extern int mprReadProperty(MprVar *prop, MprVar *value); +extern int mprWriteProperty(MprVar *prop, MprVar *newValue); +extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); + +/* + * Copy a property. NOTE: reverse of most other args: (dest, src) + */ +extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); + +/* + * Enumerate properties + */ +extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); +extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, + int includeFlags); + +/* + * Query properties characteristics + */ +extern int mprGetPropertyCount(MprVar *obj, int includeFlags); + +/* + * Conversion routines + */ +extern MprVar mprParseVar(char *str, MprType prefType); +extern MprNum mprVarToNumber(const MprVar *vp); +extern int mprVarToInteger(const MprVar *vp); +#if BLD_FEATURE_INT64 +extern int64 mprVarToInteger64(const MprVar *vp); +#endif +extern bool mprVarToBool(const MprVar *vp); +#if BLD_FEATURE_FLOATING_POINT +extern double mprVarToFloat(const MprVar *vp); +#endif +extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); + +/* + * Parsing and utility routines + */ +extern MprNum mprParseNumber(char *str); +extern int mprParseInteger(char *str); + +#if BLD_FEATURE_INT64 +extern int64 mprParseInteger64(char *str); +#endif + +#if BLD_FEATURE_FLOATING_POINT +extern double mprParseFloat(char *str); +extern bool mprIsInfinite(double f); +extern bool mprIsNan(double f); +#endif + +#if VAR_DEBUG +extern void mprPrintObjects(char *msg); +extern void mprPrintObjRefCount(MprVar *vp); +#endif + +#ifdef __cplusplus +} +#endif + +/*****************************************************************************/ +#endif /* _h_MPR_VAR */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ -- cgit From 54433c747ad771340cd4ac2cf22bbfba69c9ab02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 00:17:02 +0000 Subject: r8401: add a readme pointing to the upstream sources (This used to be commit 2dcae5c98ca66a26fd6ae6d27cf7eb31cf16fee3) --- source4/lib/appweb/README | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 source4/lib/appweb/README (limited to 'source4/lib') diff --git a/source4/lib/appweb/README b/source4/lib/appweb/README new file mode 100644 index 0000000000..bdc943446b --- /dev/null +++ b/source4/lib/appweb/README @@ -0,0 +1,6 @@ +The lib/appweb directory is a partial import of the appweb ejs and esp +code from http://www.appwebserver.org/ + +Many thanks to the mbedthis people, and especially Michael O'Brien for +his assistance in getting this code integrated into Samba4. + -- cgit From 8fc8fa2ad4e38751205afc089c957d38e5fc9384 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 00:43:16 +0000 Subject: r8404: small upstream merges of appweb code (This used to be commit 205ff9a82bd51eae3c1400ea0a24fcf2a662e96f) --- source4/lib/appweb/esp/esp.c | 12 ++++++------ source4/lib/appweb/esp/espProcs.c | 7 +++++-- source4/lib/appweb/mpr/miniMpr.h | 2 ++ source4/lib/appweb/mpr/var.h | 9 --------- 4 files changed, 13 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/esp/esp.c b/source4/lib/appweb/esp/esp.c index ef20557f93..0be7af6c1b 100644 --- a/source4/lib/appweb/esp/esp.c +++ b/source4/lib/appweb/esp/esp.c @@ -1,7 +1,7 @@ /* * @file esp.c * @brief Embedded Server Pages (ESP) core processing. - * @overview The ESP handler provides an efficient way to generate + * @overview Embedded Server Pages provides an efficient way to generate * dynamic pages using server-side Javascript. This code provides * core processing, and should be called by an associated web * server URL handler. @@ -166,7 +166,7 @@ EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri, * Define variables as globals. headers[] are prefixed with "HTTP_". * NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar * does if legacy_api is defined. So variables pre-defined by MaRequest - * must be copied here into globals[]. + * must be copied here into globals[]. * * NOTE: if a variable is in session[] and in form[], the form[] will * override being later in the variables[] list. Use mprSetProperty @@ -301,7 +301,7 @@ int espGetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar *value) */ int espProcessRequest(EspRequest *ep, const char *docPath, char *docBuf, - char **errMsg) + char **errMsg) { char *jsBuf; @@ -549,7 +549,7 @@ static int getEspToken(int state, EspParse *parse) if (parse->token == 0) { return ESP_TOK_ERR; } - parse->token[parse->tokLen] = '\0'; + parse->token[parse->tokLen] = '\0'; parse->tokp = &parse->token[parse->tokLen - 1]; parse->tokLen += ESP_TOK_INCR; parse->endp = &parse->token[parse->tokLen - 1]; @@ -774,7 +774,7 @@ static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) mprStrcpy(incPath, sizeof(incPath), parse.token); } else { mprGetDirName(dir, sizeof(dir), ep->uri); - mprSprintf(incPath, sizeof(incPath), "%s/%s", + mprSprintf(incPath, sizeof(incPath), "%s/%s", dir, parse.token); } if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), @@ -812,7 +812,7 @@ static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) } mprFree(parse.token); if (len < 0) { - mprAllocSprintf(errMsg, MPR_MAX_STRING, + mprAllocSprintf(errMsg, MPR_MAX_STRING, "Script token is too big in %s.\nConfigured maximum is %d.", path, maxScriptSize); return MPR_ERR_WONT_FIT; diff --git a/source4/lib/appweb/esp/espProcs.c b/source4/lib/appweb/esp/espProcs.c index 28b69a8a6f..7b5dfe680e 100644 --- a/source4/lib/appweb/esp/espProcs.c +++ b/source4/lib/appweb/esp/espProcs.c @@ -93,8 +93,11 @@ static int includeProc(EspRequest *ep, int argc, char **argv) buf[size] = '\0'; extension = strrchr(argv[i], '.'); - /* this makes handling include files in esp scripts much more convenient */ - if (extension && strcasecmp(extension, ".esp") == 0) { + + /* + * Allow nested inclusion of ESP requests + */ + if (extension && mprStrCmpAnyCase(extension, ".esp") == 0) { if (espProcessRequest(ep, path, buf, &emsg) != 0) { espError(ep, "Cant evaluate script - %s", emsg?emsg:""); mprFree(buf); diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h index a0030b25b5..8b28472826 100644 --- a/source4/lib/appweb/mpr/miniMpr.h +++ b/source4/lib/appweb/mpr/miniMpr.h @@ -273,6 +273,8 @@ extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); extern void mprSetCtx(void *ctx); extern void *mprMemCtx(void); +#define mprStrCmpAnyCase(s1, s2) StrCaseCmp(s1, s2) + #ifdef __cplusplus } #endif diff --git a/source4/lib/appweb/mpr/var.h b/source4/lib/appweb/mpr/var.h index 8ed13a4995..ef9217b9cf 100644 --- a/source4/lib/appweb/mpr/var.h +++ b/source4/lib/appweb/mpr/var.h @@ -156,10 +156,6 @@ typedef BLD_FEATURE_NUM_TYPE MprNum; #define MPR_MAX_VAR 512 #endif -#ifndef __NO_PACK -#pragma pack(2) -#endif /* _NO_PACK */ - /* * Function signatures */ @@ -348,11 +344,6 @@ typedef struct MprVar { typedef BLD_FEATURE_NUM_TYPE MprNumber; - -#ifndef __NO_PACK -#pragma pack() -#endif /* __NO_PACK */ - /********************************* Prototypes *********************************/ /* * Variable constructors and destructors -- cgit From 74727243cd10e5cdf02fb133dbbbe7c213cfda63 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 00:47:54 +0000 Subject: r8405: update var.c from upstream (This used to be commit 288c178d5fef80947590fd58e3c9b1fbcdddcdf6) --- source4/lib/appweb/mpr/var.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c index 9d2afe5306..533248dd06 100644 --- a/source4/lib/appweb/mpr/var.c +++ b/source4/lib/appweb/mpr/var.c @@ -1711,11 +1711,13 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) MprVar mprParseVar(char *buf, MprType preferredType) { - MprType type = MPR_TYPE_UNDEFINED; + MprType type; char *cp; mprAssert(buf); + type = preferredType; + if (preferredType == MPR_TYPE_UNDEFINED) { if (*buf == '-') { type = MPR_NUM_VAR; @@ -1730,18 +1732,18 @@ MprVar mprParseVar(char *buf, MprType preferredType) } else if (isdigit((int) *buf)) { type = MPR_NUM_VAR; cp = buf; - if (*cp && tolower((unsigned char)cp[1]) == 'x') { + if (*cp && tolower(cp[1]) == 'x') { cp = &cp[2]; } for (cp = buf; *cp; cp++) { - if (! isdigit((unsigned char) *cp)) { + if (! isdigit((int) *cp)) { break; } } if (*cp != '\0') { #if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower((unsigned char)*cp) == 'e') { + if (*cp == '.' || tolower(*cp) == 'e') { type = MPR_TYPE_FLOAT; } else #endif @@ -1750,8 +1752,6 @@ MprVar mprParseVar(char *buf, MprType preferredType) } } } - } else { - type = preferredType; } switch (type) { @@ -1993,11 +1993,11 @@ int64 mprParseInteger64(char *str) } } else { cp++; - if (tolower((unsigned char)*cp) == 'x') { + if (tolower(*cp) == 'x') { cp++; radix = 16; while (*cp) { - c = tolower((unsigned char)*cp); + c = tolower(*cp); if (isdigit(c)) { num64 = (c - '0') + (num64 * radix); } else if (c >= 'a' && c <= 'f') { @@ -2011,7 +2011,7 @@ int64 mprParseInteger64(char *str) } else{ radix = 8; while (*cp) { - c = tolower((unsigned char)*cp); + c = tolower(*cp); if (isdigit(c) && c < '8') { num64 = (c - '0') + (num64 * radix); } else { @@ -2110,11 +2110,11 @@ int mprParseInteger(char *str) } } else { cp++; - if (tolower((unsigned char)*cp) == 'x') { + if (tolower(*cp) == 'x') { cp++; radix = 16; while (*cp) { - c = tolower((unsigned char)*cp); + c = tolower(*cp); if (isdigit(c)) { num = (c - '0') + (num * radix); } else if (c >= 'a' && c <= 'f') { @@ -2128,7 +2128,7 @@ int mprParseInteger(char *str) } else{ radix = 8; while (*cp) { - c = tolower((unsigned char)*cp); + c = tolower(*cp); if (isdigit(c) && c < '8') { num = (c - '0') + (num * radix); } else { -- cgit From d1291dacbd8c5e736e7d8288fb00b5368288b711 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 03:25:36 +0000 Subject: r8408: its quite common in our code to free up a connection when we get an error, but sometimes a socket option may then happen on the NULL socket. This has been handled by the individual libraries up to now, but its cleaner to centralise it here (This used to be commit d9864e1f9aac1fb19f054c2da996a5099e90941e) --- source4/lib/socket/socket.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index 9d5b67a966..db249522a2 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -98,6 +98,9 @@ NTSTATUS socket_connect(struct socket_context *sock, const char *server_address, int server_port, uint32_t flags) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->state != SOCKET_STATE_UNDEFINED) { return NT_STATUS_INVALID_PARAMETER; } @@ -119,6 +122,9 @@ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags) NTSTATUS socket_listen(struct socket_context *sock, const char *my_address, int port, int queue_size, uint32_t flags) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->state != SOCKET_STATE_UNDEFINED) { return NT_STATUS_INVALID_PARAMETER; } @@ -134,6 +140,9 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ { NTSTATUS status; + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->type != SOCKET_TYPE_STREAM) { return NT_STATUS_INVALID_PARAMETER; } @@ -158,6 +167,9 @@ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED && sock->type != SOCKET_TYPE_DGRAM) { @@ -183,6 +195,9 @@ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread, uint32_t flags, const char **src_addr, int *src_port) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->type != SOCKET_TYPE_DGRAM) { return NT_STATUS_INVALID_PARAMETER; } @@ -198,6 +213,9 @@ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, NTSTATUS socket_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->state != SOCKET_STATE_CLIENT_CONNECTED && sock->state != SOCKET_STATE_SERVER_CONNECTED) { return NT_STATUS_INVALID_PARAMETER; @@ -225,6 +243,9 @@ NTSTATUS socket_sendto(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, uint32_t flags, const char *dest_addr, int dest_port) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (sock->type != SOCKET_TYPE_DGRAM) { return NT_STATUS_INVALID_PARAMETER; } @@ -247,6 +268,9 @@ NTSTATUS socket_sendto(struct socket_context *sock, */ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (!sock->ops->fn_pending) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -256,6 +280,9 @@ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending) NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val) { + if (sock == NULL) { + return NT_STATUS_CONNECTION_DISCONNECTED; + } if (!sock->ops->fn_set_option) { return NT_STATUS_NOT_IMPLEMENTED; } -- cgit From b433d615370dfad05befb1ca524c2cbc0d4e64bc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 03:55:22 +0000 Subject: r8409: fixed another error found on netbsd. some of our torture code does its own timeout processing, which means there is no event timer in the event context. To fix this gererically I have added a 30 second timout to all select/epoll calls so the callers timeout loop is guaranteed to run eventually (This used to be commit 01e5aa146439f2dbf6c4133a0b5d910383a6576b) --- source4/lib/events/events_standard.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index a867f86801..5a64a42b28 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -335,6 +335,10 @@ static void std_event_loop_timer(struct event_context *ev) struct timeval t = timeval_current(); struct timed_event *te = std_ev->timed_events; + if (te == NULL) { + return; + } + te->next_event = timeval_zero(); te->handler(ev, te, t, te->private_data); @@ -479,31 +483,32 @@ static int std_event_loop_once(struct event_context *ev) { struct std_event_context *std_ev = talloc_get_type(ev->additional_data, struct std_event_context); - struct timeval tval, *tvalp; - - tvalp = NULL; + struct timeval tval; /* work out the right timeout for all timed events */ if (std_ev->timed_events) { struct timeval t = timeval_current(); - tval = timeval_diff(&std_ev->timed_events->next_event, &t); - tvalp = &tval; - if (timeval_is_zero(tvalp)) { + if (timeval_is_zero(&tval)) { std_event_loop_timer(ev); return 0; } + } else { + /* have a default tick time of 30 seconds. This guarantees + that code that uses its own timeout checking will be + able to proceeed eventually */ + tval = timeval_set(30, 0); } #if WITH_EPOLL if (std_ev->epoll_fd != -1) { - if (std_event_loop_epoll(ev, tvalp) == 0) { + if (std_event_loop_epoll(ev, &tval) == 0) { return 0; } } #endif - return std_event_loop_select(ev, tvalp); + return std_event_loop_select(ev, &tval); } /* -- cgit From 52bef30fd48393fa7b24ade7622c758373bd6dbe Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 13 Jul 2005 05:55:28 +0000 Subject: r8414: Some C++ friendlyness fixes - 'not' is apparently a keyword in C++. (This used to be commit bcfb3a45e4a5962fe763f8071d4458f4bd11605b) --- source4/lib/ldb/common/ldb_match.c | 2 +- source4/lib/ldb/common/ldb_parse.c | 6 +++--- source4/lib/ldb/include/ldb.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index b32a933df3..f437f31eac 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -369,7 +369,7 @@ static int ldb_match_message(struct ldb_context *ldb, return ldb_match_extended(ldb, msg, tree, base, scope); case LDB_OP_NOT: - return ! ldb_match_message(ldb, msg, tree->u.not.child, base, scope); + return ! ldb_match_message(ldb, msg, tree->u.isnot.child, base, scope); case LDB_OP_AND: for (i=0;iu.list.num_elements;i++) { diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index ad3cbd883d..933ff18f2b 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -459,8 +459,8 @@ static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) } ret->operation = LDB_OP_NOT; - ret->u.not.child = ldb_parse_filter(ret, &s); - if (!ret->u.not.child) { + ret->u.isnot.child = ldb_parse_filter(ret, &s); + if (!ret->u.isnot.child) { talloc_free(ret); return NULL; } @@ -629,7 +629,7 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) } return s; case LDB_OP_NOT: - s = ldb_filter_from_tree(mem_ctx, tree->u.not.child); + s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child); if (s == NULL) return NULL; ret = talloc_asprintf(mem_ctx, "(!%s)", s); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 8233e78f0e..c2d7b0d614 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -186,7 +186,7 @@ struct ldb_parse_tree { } list; struct { struct ldb_parse_tree *child; - } not; + } isnot; } u; }; -- cgit From 72fbfff1a7c11ac96ef3e7f80691f51856a87478 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 10:22:13 +0000 Subject: r8417: fixed handling of PRINTF_ATTRIBUTE for heimdal portion of build (This used to be commit 117d2fa31d3a7e0b37c09979aa41243c564c0385) --- source4/lib/replace/replace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index c7c343ef38..b67e629aa0 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -112,7 +112,7 @@ typedef int (*comparison_fn_t)(const void *, const void *); #endif #ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) +#if !defined(NO_PRINTF_ATTRIBUTE) && (__GNUC__ >= 3) /** Use gcc attribute to check printf fns. a1 is the 1-based index of * the parameter containing the format, and a2 the index of the first * argument. Note that some gcc 2.x versions don't handle this -- cgit From 12ed349f9025a4ca27f7399bb352c674af284ac4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 10:58:43 +0000 Subject: r8418: PRINTF_ATTRIBUTE declaration has to come before it is used :-) (This used to be commit a1ca8352f48cf1942e5a060c79ae1cc78b8a3668) --- source4/lib/replace/replace.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index b67e629aa0..8062c4c683 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -75,6 +75,18 @@ int vasprintf(char **ptr, const char *format, va_list ap); #define bzero(a,b) memset((a),'\0',(b)) #endif +#ifndef PRINTF_ATTRIBUTE +#if !defined(NO_PRINTF_ATTRIBUTE) && (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + /* add varargs prototypes with printf checking */ #ifndef HAVE_SNPRINTF_DECL int snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); @@ -111,16 +123,4 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); typedef int (*comparison_fn_t)(const void *, const void *); #endif -#ifndef PRINTF_ATTRIBUTE -#if !defined(NO_PRINTF_ATTRIBUTE) && (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - #endif -- cgit From 2ea372afd98b133144ad897250bd89d2c2855b16 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Jul 2005 11:17:32 +0000 Subject: r8420: slowly getting my way through some more heimdal portability fixes (This used to be commit 59c3de6ca8b8e153e5cfd67da5f2afc2e23d36db) --- source4/lib/replace/replace.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 8062c4c683..89225d3d65 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -109,10 +109,6 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); #define VA_COPY(dest, src) (dest) = (src) #endif -#ifndef UINT16_MAX -#define UINT16_MAX 65535 -#endif - #if defined(HAVE_VOLATILE) #define VOLATILE volatile #else -- cgit From 84db0662071a6ab61ae21a5da35317d8aed55d75 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 13 Jul 2005 20:44:46 +0000 Subject: r8434: Win32 portability updates from Steven Edwards : - undefine anything in the win32 api or PSDK headers that Samba already defines - map BSD error codes to Winsock Error codes (This used to be commit d2ea6191259a28a32a1f4ffdff067b1a80e8dcc9) --- source4/lib/replace/win32.m4 | 20 ----- source4/lib/replace/win32/config.m4 | 20 +++++ source4/lib/replace/win32/replace.h | 143 ++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 20 deletions(-) delete mode 100644 source4/lib/replace/win32.m4 create mode 100644 source4/lib/replace/win32/config.m4 create mode 100644 source4/lib/replace/win32/replace.h (limited to 'source4/lib') diff --git a/source4/lib/replace/win32.m4 b/source4/lib/replace/win32.m4 deleted file mode 100644 index 9ac84cdf2a..0000000000 --- a/source4/lib/replace/win32.m4 +++ /dev/null @@ -1,20 +0,0 @@ -AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) - -####################################### -# Check for mkdir mode -AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, - AC_TRY_COMPILE([ - #include - #ifdef HAVE_DIRECT_H - #include - #endif],[ - mkdir("foo",0777); - return 0; - ], - ac_mkdir_has_mode="yes", - ac_mkdir_has_mode="no") ) - -if test "$ac_mkdir_has_mode" = "yes" -then - AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) -fi diff --git a/source4/lib/replace/win32/config.m4 b/source4/lib/replace/win32/config.m4 new file mode 100644 index 0000000000..9ac84cdf2a --- /dev/null +++ b/source4/lib/replace/win32/config.m4 @@ -0,0 +1,20 @@ +AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) + +####################################### +# Check for mkdir mode +AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, + AC_TRY_COMPILE([ + #include + #ifdef HAVE_DIRECT_H + #include + #endif],[ + mkdir("foo",0777); + return 0; + ], + ac_mkdir_has_mode="yes", + ac_mkdir_has_mode="no") ) + +if test "$ac_mkdir_has_mode" = "yes" +then + AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) +fi diff --git a/source4/lib/replace/win32/replace.h b/source4/lib/replace/win32/replace.h new file mode 100644 index 0000000000..94fa140681 --- /dev/null +++ b/source4/lib/replace/win32/replace.h @@ -0,0 +1,143 @@ +#ifndef _WIN32_REPLACE_H +#define _WIN32_REPLACE_H + +/* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */ + +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define ECONNREFUSED WSAECONNREFUSED +#define EINPROGRESS WSAEINPROGRESS +#define EMSGSIZE WSAEMSGSIZE +#define ENOBUFS WSAENOBUFS +#define ENOTSOCK WSAENOTSOCK +#define ENETUNREACH WSAENETUNREACH +#define ENOPROTOOPT WSAENOPROTOOPT +#define ENOTCONN WSAENOTCONN +#define ENOTSUP 134 + +/* We undefine the following constants due to conflicts with the w32api headers + * and the Windows Platform SDK/DDK. + */ + +#undef interface + +#undef ERROR_INVALID_PARAMETER +#undef ERROR_INSUFFICIENT_BUFFER +#undef ERROR_INVALID_DATATYPE + +#undef FILE_GENERIC_READ +#undef FILE_GENERIC_WRITE +#undef FILE_GENERIC_EXECUTE +#undef FILE_ATTRIBUTE_READONLY +#undef FILE_ATTRIBUTE_HIDDEN +#undef FILE_ATTRIBUTE_SYSTEM +#undef FILE_ATTRIBUTE_DIRECTORY +#undef FILE_ATTRIBUTE_ARCHIVE +#undef FILE_ATTRIBUTE_DEVICE +#undef FILE_ATTRIBUTE_NORMAL +#undef FILE_ATTRIBUTE_TEMPORARY +#undef FILE_ATTRIBUTE_REPARSE_POINT +#undef FILE_ATTRIBUTE_COMPRESSED +#undef FILE_ATTRIBUTE_OFFLINE +#undef FILE_ATTRIBUTE_ENCRYPTED +#undef FILE_FLAG_WRITE_THROUGH +#undef FILE_FLAG_NO_BUFFERING +#undef FILE_FLAG_RANDOM_ACCESS +#undef FILE_FLAG_SEQUENTIAL_SCAN +#undef FILE_FLAG_DELETE_ON_CLOSE +#undef FILE_FLAG_BACKUP_SEMANTICS +#undef FILE_FLAG_POSIX_SEMANTICS +#undef FILE_TYPE_DISK +#undef FILE_TYPE_UNKNOWN +#undef FILE_CASE_SENSITIVE_SEARCH +#undef FILE_CASE_PRESERVED_NAMES +#undef FILE_UNICODE_ON_DISK +#undef FILE_PERSISTENT_ACLS +#undef FILE_FILE_COMPRESSION +#undef FILE_VOLUME_QUOTAS +#undef FILE_VOLUME_IS_COMPRESSED +#undef FILE_NOTIFY_CHANGE_DIR_NAME +#undef FILE_NOTIFY_CHANGE_ATTRIBUTES +#undef FILE_NOTIFY_CHANGE_SIZE +#undef FILE_NOTIFY_CHANGE_LAST_WRITE +#undef FILE_NOTIFY_CHANGE_LAST_ACCESS +#undef FILE_NOTIFY_CHANGE_CREATION +#undef FILE_NOTIFY_CHANGE_EA +#undef FILE_NOTIFY_CHANGE_SECURITY +#undef FILE_NOTIFY_CHANGE_FILE_NAME + +#undef PRINTER_ATTRIBUTE_QUEUED +#undef PRINTER_ATTRIBUTE_DIRECT +#undef PRINTER_ATTRIBUTE_DEFAULT +#undef PRINTER_ATTRIBUTE_SHARED +#undef PRINTER_ATTRIBUTE_NETWORK +#undef PRINTER_ATTRIBUTE_HIDDEN +#undef PRINTER_ATTRIBUTE_LOCAL +#undef PRINTER_ATTRIBUTE_ENABLE_DEVQ +#undef PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS +#undef PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST +#undef PRINTER_ATTRIBUTE_WORK_OFFLINE +#undef PRINTER_ATTRIBUTE_ENABLE_BIDI +#undef PRINTER_ATTRIBUTE_RAW_ONLY +#undef PRINTER_ATTRIBUTE_PUBLISHED +#undef PRINTER_ENUM_DEFAULT +#undef PRINTER_ENUM_LOCAL +#undef PRINTER_ENUM_CONNECTIONS +#undef PRINTER_ENUM_FAVORITE +#undef PRINTER_ENUM_NAME +#undef PRINTER_ENUM_REMOTE +#undef PRINTER_ENUM_SHARED +#undef PRINTER_ENUM_NETWORK +#undef PRINTER_ENUM_EXPAND +#undef PRINTER_ENUM_CONTAINER +#undef PRINTER_ENUM_ICON1 +#undef PRINTER_ENUM_ICON2 +#undef PRINTER_ENUM_ICON3 +#undef PRINTER_ENUM_ICON4 +#undef PRINTER_ENUM_ICON5 +#undef PRINTER_ENUM_ICON6 +#undef PRINTER_ENUM_ICON7 +#undef PRINTER_ENUM_ICON8 +#undef PRINTER_STATUS_PAUSED +#undef PRINTER_STATUS_ERROR +#undef PRINTER_STATUS_PENDING_DELETION +#undef PRINTER_STATUS_PAPER_JAM +#undef PRINTER_STATUS_PAPER_OUT +#undef PRINTER_STATUS_MANUAL_FEED +#undef PRINTER_STATUS_PAPER_PROBLEM +#undef PRINTER_STATUS_OFFLINE +#undef PRINTER_STATUS_IO_ACTIVE +#undef PRINTER_STATUS_BUSY +#undef PRINTER_STATUS_PRINTING +#undef PRINTER_STATUS_OUTPUT_BIN_FULL +#undef PRINTER_STATUS_NOT_AVAILABLE +#undef PRINTER_STATUS_WAITING +#undef PRINTER_STATUS_PROCESSING +#undef PRINTER_STATUS_INITIALIZING +#undef PRINTER_STATUS_WARMING_UP +#undef PRINTER_STATUS_TONER_LOW +#undef PRINTER_STATUS_NO_TONER +#undef PRINTER_STATUS_PAGE_PUNT +#undef PRINTER_STATUS_USER_INTERVENTION +#undef PRINTER_STATUS_OUT_OF_MEMORY +#undef PRINTER_STATUS_DOOR_OPEN +#undef PRINTER_STATUS_SERVER_UNKNOWN +#undef PRINTER_STATUS_POWER_SAVE + +#undef DWORD +#undef HKEY_CLASSES_ROOT +#undef HKEY_CURRENT_USER +#undef HKEY_LOCAL_MACHINE +#undef HKEY_USERS +#undef HKEY_PERFORMANCE_DATA +#undef HKEY_CURRENT_CONFIG +#undef HKEY_DYN_DATA +#undef REG_DWORD +#undef REG_QWORD + +#undef SERVICE_STATE_ALL + +#undef SE_GROUP_MANDATORY +#undef SE_GROUP_ENABLED_BY_DEFAULT +#undef SE_GROUP_ENABLED + +#endif /* _WIN32_REPLACE_H */ -- cgit From e1512846939abceae37f62b755aaf7006b64b0c7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 13 Jul 2005 21:54:34 +0000 Subject: r8437: Win32 doesn't have u_int*_t (This used to be commit 5b007037dfacc5e13141ca41241543ac11a567b6) --- source4/lib/replace/win32/replace.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/win32/replace.h b/source4/lib/replace/win32/replace.h index 94fa140681..2c6d0e1a3f 100644 --- a/source4/lib/replace/win32/replace.h +++ b/source4/lib/replace/win32/replace.h @@ -140,4 +140,7 @@ #undef SE_GROUP_ENABLED_BY_DEFAULT #undef SE_GROUP_ENABLED +typedef uint32_t u_int32_t; +typedef uint16_t u_int16_t; + #endif /* _WIN32_REPLACE_H */ -- cgit From 2dabfc1cde31932b8dfdaef2f4aacd56864c9fc3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 02:35:51 +0000 Subject: r8441: don't build tdbtest by default as there are too many systems that don't have libgdbm, and the configure test for gdbm is broken (This used to be commit 5c4c3e9a8d9d853028271f228ad36388f4cb2012) --- source4/lib/tdb/Makefile.in | 2 +- source4/lib/tdb/config.m4 | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index f9912cd6b1..c06e7a8dc7 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -10,7 +10,7 @@ bindir = @bindir@ includedir = @includedir@ libdir = @libdir@ -PROGS = bin/tdbtest bin/tdbtool bin/tdbtorture +PROGS = bin/tdbtool bin/tdbtorture TDB_OBJ = common/tdb.o common/spinlock.o all: $(PROGS) diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 414ccfdfed..cea67fe6e7 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -3,19 +3,3 @@ if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtdb,YES) fi -############################### -# start SMB_EXT_LIB_GDBM -# check for gdbm.h and -lgdbm -AC_CHECK_HEADERS(gdbm.h) -AC_CHECK_LIB_EXT(gdbm, GDBM_LIBS, gdbm_open) -if test x"$ac_cv_header_gdbm_h" = x"yes" -a x"$ac_cv_lib_ext_gdbm_gdbm_open" = x"yes";then - SMB_EXT_LIB_ENABLE(GDBM,YES) -fi -SMB_EXT_LIB(GDBM, $GDBM_LIBS) -# end SMB_EXT_LIB_GDBM -############################### - -SMB_BINARY_ENABLE(tdbtest, NO) -if test x"$SMB_EXT_LIB_ENABLE_GDBM" = x"YES"; then - SMB_BINARY_ENABLE(tdbtest, YES) -fi -- cgit From c9e5d3b53e55b6bf6a3328f47888a23b03b3b044 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 02:37:01 +0000 Subject: r8442: remove tdbtest from our build. If you want it, then do 'make bin/tdbtest' manually in the tdb tree (This used to be commit 28dd79587df523c5622d09bd6d59305ae79af479) --- source4/lib/tdb/config.mk | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 2b2a595fca..221c5284f7 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -25,16 +25,6 @@ REQUIRED_SUBSYSTEMS = \ # End LIBRARY LIBLDB ################################################ -################################################ -# Start BINARY tdbtest -[BINARY::tdbtest] -OBJ_FILES= \ - lib/tdb/tools/tdbtest.o -REQUIRED_SUBSYSTEMS = \ - LIBTDB EXT_LIB_GDBM -# End BINARY tdbtest -################################################ - ################################################ # Start BINARY tdbtool [BINARY::tdbtool] -- cgit From ef300e66861fd4bab000c1dd3ef9ecc0484a4a77 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 02:44:30 +0000 Subject: r8443: added talloc.3 to the tree to try to allow talloc to build on systems without xsltproc (This used to be commit 0e5b89b1e8871a76c2f9c94d7d7552498d16f350) --- source4/lib/talloc/talloc.3 | 489 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 source4/lib/talloc/talloc.3 (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.3 b/source4/lib/talloc/talloc.3 new file mode 100644 index 0000000000..bf10943227 --- /dev/null +++ b/source4/lib/talloc/talloc.3 @@ -0,0 +1,489 @@ +.\"Generated by db2man.xsl. Don't modify this, modify the source. +.de Sh \" Subsection +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Ip \" List item +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.TH "TALLOC" 3 "" "" "" +.SH NAME +talloc \- hierarchical reference counted memory pool system with destructors +.SH "SYNOPSIS" + +.nf +#include +.fi + +.SH "DESCRIPTION" + +.PP +If you are used to talloc from Samba3 then please read this carefully, as talloc has changed a lot\&. + +.PP +The new talloc is a hierarchical, reference counted memory pool system with destructors\&. Quite a mouthful really, but not too bad once you get used to it\&. + +.PP +Perhaps the biggest change from Samba3 is that there is no distinction between a "talloc context" and a "talloc pointer"\&. Any pointer returned from talloc() is itself a valid talloc context\&. This means you can do this: + +.nf + + struct foo *X = talloc(mem_ctx, struct foo); + X\->name = talloc_strdup(X, "foo"); + +.fi + +.PP +and the pointer X\->name would be a "child" of the talloc context X which is itself a child of mem_ctx\&. So if you do talloc_free(mem_ctx) then it is all destroyed, whereas if you do talloc_free(X) then just X and X\->name are destroyed, and if you do talloc_free(X\->name) then just the name element of X is destroyed\&. + +.PP +If you think about this, then what this effectively gives you is an n\-ary tree, where you can free any part of the tree with talloc_free()\&. + +.PP +If you find this confusing, then I suggest you run the testsuite program to watch talloc in action\&. You may also like to add your own tests to testsuite\&.c to clarify how some particular situation is handled\&. + +.SH "TALLOC API" + +.PP +The following is a complete guide to the talloc API\&. Read it all at least twice\&. + +.SS "(type *)talloc(const void *ctx, type);" + +.PP +The talloc() macro is the core of the talloc library\&. It takes a memory \fIctx\fR and a \fItype\fR, and returns a pointer to a new area of memory of the given \fItype\fR\&. + +.PP +The returned pointer is itself a talloc context, so you can use it as the \fIctx\fR argument to more calls to talloc() if you wish\&. + +.PP +The returned pointer is a "child" of the supplied context\&. This means that if you talloc_free() the \fIctx\fR then the new child disappears as well\&. Alternatively you can free just the child\&. + +.PP +The \fIctx\fR argument to talloc() can be NULL, in which case a new top level context is created\&. + +.SS "void *talloc_size(const void *ctx, size_t size);" + +.PP +The function talloc_size() should be used when you don't have a convenient type to pass to talloc()\&. Unlike talloc(), it is not type safe (as it returns a void *), so you are on your own for type checking\&. + +.SS "int talloc_free(void *ptr);" + +.PP +The talloc_free() function frees a piece of talloc memory, and all its children\&. You can call talloc_free() on any pointer returned by talloc()\&. + +.PP +The return value of talloc_free() indicates success or failure, with 0 returned for success and \-1 for failure\&. The only possible failure condition is if \fIptr\fR had a destructor attached to it and the destructor returned \-1\&. See ``talloc_set_destructor()'' for details on destructors\&. + +.PP +If this pointer has an additional parent when talloc_free() is called then the memory is not actually released, but instead the most recently established parent is destroyed\&. See ``talloc_reference()'' for details on establishing additional parents\&. + +.PP +For more control on which parent is removed, see ``talloc_unlink()''\&. + +.PP +talloc_free() operates recursively on its children\&. + +.SS "void *talloc_reference(const void *ctx, const void *ptr);" + +.PP +The talloc_reference() function makes \fIctx\fR an additional parent of \fIptr\fR\&. + +.PP +The return value of talloc_reference() is always the original pointer \fIptr\fR, unless talloc ran out of memory in creating the reference in which case it will return NULL (each additional reference consumes around 48 bytes of memory on intel x86 platforms)\&. + +.PP +If \fIptr\fR is NULL, then the function is a no\-op, and simply returns NULL\&. + +.PP +After creating a reference you can free it in one of the following ways: + +.PP + + +.TP 3 +\(bu +you can talloc_free() any parent of the original pointer\&. That will reduce the number of parents of this pointer by 1, and will cause this pointer to be freed if it runs out of parents\&. +.TP +\(bu +you can talloc_free() the pointer itself\&. That will destroy the most recently established parent to the pointer and leave the pointer as a child of its current parent\&. +.LP + + +.PP +For more control on which parent to remove, see ``talloc_unlink()''\&. + +.SS "int talloc_unlink(const void *ctx, const void *ptr);" + +.PP +The talloc_unlink() function removes a specific parent from \fIptr\fR\&. The \fIctx\fR passed must either be a context used in talloc_reference() with this pointer, or must be a direct parent of ptr\&. + +.PP +Note that if the parent has already been removed using talloc_free() then this function will fail and will return \-1\&. Likewise, if \fIptr\fR is NULL, then the function will make no modifications and return \-1\&. + +.PP +Usually you can just use talloc_free() instead of talloc_unlink(), but sometimes it is useful to have the additional control on which parent is removed\&. + +.SS "void talloc_set_destructor(const void *ptr, int (*destructor)(void *));" + +.PP +The function talloc_set_destructor() sets the \fIdestructor\fR for the pointer \fIptr\fR\&. A \fIdestructor\fR is a function that is called when the memory used by a pointer is about to be released\&. The destructor receives \fIptr\fR as an argument, and should return 0 for success and \-1 for failure\&. + +.PP +The \fIdestructor\fR can do anything it wants to, including freeing other pieces of memory\&. A common use for destructors is to clean up operating system resources (such as open file descriptors) contained in the structure the destructor is placed on\&. + +.PP +You can only place one destructor on a pointer\&. If you need more than one destructor then you can create a zero\-length child of the pointer and place an additional destructor on that\&. + +.PP +To remove a destructor call talloc_set_destructor() with NULL for the destructor\&. + +.PP +If your destructor attempts to talloc_free() the pointer that it is the destructor for then talloc_free() will return \-1 and the free will be ignored\&. This would be a pointless operation anyway, as the destructor is only called when the memory is just about to go away\&. + +.SS "void talloc_increase_ref_count(const void *ptr);" + +.PP +The talloc_increase_ref_count(\fIptr\fR) function is exactly equivalent to: + +.nf +talloc_reference(NULL, ptr); +.fi + +.PP +You can use either syntax, depending on which you think is clearer in your code\&. + +.SS "void talloc_set_name(const void *ptr, const char *fmt, ...);" + +.PP +Each talloc pointer has a "name"\&. The name is used principally for debugging purposes, although it is also possible to set and get the name on a pointer in as a way of "marking" pointers in your code\&. + +.PP +The main use for names on pointer is for "talloc reports"\&. See ``talloc_report()'' and ``talloc_report_full()'' for details\&. Also see ``talloc_enable_leak_report()'' and ``talloc_enable_leak_report_full()''\&. + +.PP +The talloc_set_name() function allocates memory as a child of the pointer\&. It is logically equivalent to: + +.nf +talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, \&.\&.\&.)); +.fi + +.PP +Note that multiple calls to talloc_set_name() will allocate more memory without releasing the name\&. All of the memory is released when the ptr is freed using talloc_free()\&. + +.SS "void talloc_set_name_const(const void *ptr, const char *name);" + +.PP +The function talloc_set_name_const() is just like talloc_set_name(), but it takes a string constant, and is much faster\&. It is extensively used by the "auto naming" macros, such as talloc_p()\&. + +.PP +This function does not allocate any memory\&. It just copies the supplied pointer into the internal representation of the talloc ptr\&. This means you must not pass a \fIname\fR pointer to memory that will disappear before \fIptr\fR is freed with talloc_free()\&. + +.SS "void *talloc_named(const void *ctx, size_t size, const char *fmt, ...);" + +.PP +The talloc_named() function creates a named talloc pointer\&. It is equivalent to: + +.nf +ptr = talloc_size(ctx, size); +talloc_set_name(ptr, fmt, \&.\&.\&.\&.); +.fi + +.SS "void *talloc_named_const(const void *ctx, size_t size, const char *name);" + +.PP +This is equivalent to: + +.nf +ptr = talloc_size(ctx, size); +talloc_set_name_const(ptr, name); +.fi + +.SS "const char *talloc_get_name(const void *ptr);" + +.PP +This returns the current name for the given talloc pointer, \fIptr\fR\&. See ``talloc_set_name()'' for details\&. + +.SS "void *talloc_init(const char *fmt, ...);" + +.PP +This function creates a zero length named talloc context as a top level context\&. It is equivalent to: + +.nf +talloc_named(NULL, 0, fmt, \&.\&.\&.); +.fi + +.SS "void *talloc_new(void *ctx);" + +.PP +This is a utility macro that creates a new memory context hanging off an exiting context, automatically naming it "talloc_new: __location__" where __location__ is the source line it is called from\&. It is particularly useful for creating a new temporary working context\&. + +.SS "(type *)talloc_realloc(const void *ctx, void *ptr, type, count);" + +.PP +The talloc_realloc() macro changes the size of a talloc pointer\&. It has the following equivalences: + +.nf +talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); +talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); +.fi + +.PP +The \fIctx\fR argument is only used if \fIptr\fR is not NULL, otherwise it is ignored\&. + +.PP +talloc_realloc() returns the new pointer, or NULL on failure\&. The call will fail either due to a lack of memory, or because the pointer has more than one parent (see ``talloc_reference()'')\&. + +.SS "void *talloc_realloc_size(const void *ctx, void *ptr, size_t size);" + +.PP +the talloc_realloc_size() function is useful when the type is not known so the type\-safe talloc_realloc() cannot be used\&. + +.SS "void *talloc_steal(const void *new_ctx, const void *ptr);" + +.PP +The talloc_steal() function changes the parent context of a talloc pointer\&. It is typically used when the context that the pointer is currently a child of is going to be freed and you wish to keep the memory for a longer time\&. + +.PP +The talloc_steal() function returns the pointer that you pass it\&. It does not have any failure modes\&. + +.PP +NOTE: It is possible to produce loops in the parent/child relationship if you are not careful with talloc_steal()\&. No guarantees are provided as to your sanity or the safety of your data if you do this\&. + +.SS "off_t talloc_total_size(const void *ptr);" + +.PP +The talloc_total_size() function returns the total size in bytes used by this pointer and all child pointers\&. Mostly useful for debugging\&. + +.PP +Passing NULL is allowed, but it will only give a meaningful result if talloc_enable_leak_report() or talloc_enable_leak_report_full() has been called\&. + +.SS "off_t talloc_total_blocks(const void *ptr);" + +.PP +The talloc_total_blocks() function returns the total memory block count used by this pointer and all child pointers\&. Mostly useful for debugging\&. + +.PP +Passing NULL is allowed, but it will only give a meaningful result if talloc_enable_leak_report() or talloc_enable_leak_report_full() has been called\&. + +.SS "void talloc_report(const void *ptr, FILE *f);" + +.PP +The talloc_report() function prints a summary report of all memory used by \fIptr\fR\&. One line of report is printed for each immediate child of ptr, showing the total memory and number of blocks used by that child\&. + +.PP +You can pass NULL for the pointer, in which case a report is printed for the top level memory context, but only if talloc_enable_leak_report() or talloc_enable_leak_report_full() has been called\&. + +.SS "void talloc_report_full(const void *ptr, FILE *f);" + +.PP +This provides a more detailed report than talloc_report()\&. It will recursively print the entire tree of memory referenced by the pointer\&. References in the tree are shown by giving the name of the pointer that is referenced\&. + +.PP +You can pass NULL for the pointer, in which case a report is printed for the top level memory context, but only if talloc_enable_leak_report() or talloc_enable_leak_report_full() has been called\&. + +.SS "void talloc_enable_leak_report(void);" + +.PP +This enables calling of talloc_report(NULL, stderr) when the program exits\&. In Samba4 this is enabled by using the \-\-leak\-report command line option\&. + +.PP +For it to be useful, this function must be called before any other talloc function as it establishes a "null context" that acts as the top of the tree\&. If you don't call this function first then passing NULL to talloc_report() or talloc_report_full() won't give you the full tree printout\&. + +.PP +Here is a typical talloc report: + +.IP +talloc report on 'null_context' (total 267 bytes in 15 blocks) +libcli/auth/spnego_parse\&.c:55 contains 31 bytes in 2 blocks +libcli/auth/spnego_parse\&.c:55 contains 31 bytes in 2 blocks +iconv(UTF8,CP850) contains 42 bytes in 2 blocks +libcli/auth/spnego_parse\&.c:55 contains 31 bytes in 2 blocks +iconv(CP850,UTF8) contains 42 bytes in 2 blocks +iconv(UTF8,UTF\-16LE) contains 45 bytes in 2 blocks +iconv(UTF\-16LE,UTF8) contains 45 bytes in 2 blocks + +.SS "void talloc_enable_leak_report_full(void);" + +.PP +This enables calling of talloc_report_full(NULL, stderr) when the program exits\&. In Samba4 this is enabled by using the \-\-leak\-report\-full command line option\&. + +.PP +For it to be useful, this function must be called before any other talloc function as it establishes a "null context" that acts as the top of the tree\&. If you don't call this function first then passing NULL to talloc_report() or talloc_report_full() won't give you the full tree printout\&. + +.PP +Here is a typical full report: + +.IP +full talloc report on 'root' (total 18 bytes in 8 blocks) +p1 contains 18 bytes in 7 blocks (ref 0) + r1 contains 13 bytes in 2 blocks (ref 0) + reference to: p2 + p2 contains 1 bytes in 1 blocks (ref 1) + x3 contains 1 bytes in 1 blocks (ref 0) + x2 contains 1 bytes in 1 blocks (ref 0) + x1 contains 1 bytes in 1 blocks (ref 0) + +.SS "(type *)talloc_zero(const void *ctx, type);" + +.PP +The talloc_zero() macro is equivalent to: + +.nf +ptr = talloc(ctx, type); +if (ptr) memset(ptr, 0, sizeof(type)); +.fi + +.SS "void *talloc_zero_size(const void *ctx, size_t size)" + +.PP +The talloc_zero_size() function is useful when you don't have a known type\&. + +.SS "void *talloc_memdup(const void *ctx, const void *p, size_t size);" + +.PP +The talloc_memdup() function is equivalent to: + +.nf +ptr = talloc_size(ctx, size); +if (ptr) memcpy(ptr, p, size); +.fi + +.SS "char *talloc_strdup(const void *ctx, const char *p);" + +.PP +The talloc_strdup() function is equivalent to: + +.nf +ptr = talloc_size(ctx, strlen(p)+1); +if (ptr) memcpy(ptr, p, strlen(p)+1); +.fi + +.PP +This function sets the name of the new pointer to the passed string\&. This is equivalent to: + +.nf +talloc_set_name_const(ptr, ptr) +.fi + +.SS "char *talloc_strndup(const void *t, const char *p, size_t n);" + +.PP +The talloc_strndup() function is the talloc equivalent of the C library function strndup(3)\&. + +.PP +This function sets the name of the new pointer to the passed string\&. This is equivalent to: + +.nf +talloc_set_name_const(ptr, ptr) +.fi + +.SS "char *talloc_vasprintf(const void *t, const char *fmt, va_list ap);" + +.PP +The talloc_vasprintf() function is the talloc equivalent of the C library function vasprintf(3)\&. + +.SS "char *talloc_asprintf(const void *t, const char *fmt, ...);" + +.PP +The talloc_asprintf() function is the talloc equivalent of the C library function asprintf(3)\&. + +.PP +This function sets the name of the new pointer to the passed string\&. This is equivalent to: + +.nf +talloc_set_name_const(ptr, ptr) +.fi + +.SS "char *talloc_asprintf_append(char *s, const char *fmt, ...);" + +.PP +The talloc_asprintf_append() function appends the given formatted string to the given string\&. + +.SS "(type *)talloc_array(const void *ctx, type, uint_t count);" + +.PP +The talloc_array() macro is equivalent to: + +.nf +(type *)talloc_size(ctx, sizeof(type) * count); +.fi + +.PP +except that it provides integer overflow protection for the multiply, returning NULL if the multiply overflows\&. + +.SS "void *talloc_array_size(const void *ctx, size_t size, uint_t count);" + +.PP +The talloc_array_size() function is useful when the type is not known\&. It operates in the same way as talloc_array(), but takes a size instead of a type\&. + +.SS "void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size)" + +.PP +This is a non\-macro version of talloc_realloc(), which is useful as libraries sometimes want a realloc function pointer\&. A realloc(3) implementation encapsulates the functionality of malloc(3), free(3) and realloc(3) in one call, which is why it is useful to be able to pass around a single function pointer\&. + +.SS "void *talloc_autofree_context(void);" + +.PP +This is a handy utility function that returns a talloc context which will be automatically freed on program exit\&. This can be used to reduce the noise in memory leak reports\&. + +.SS "void *talloc_check_name(const void *ptr, const char *name);" + +.PP +This function checks if a pointer has the specified \fIname\fR\&. If it does then the pointer is returned\&. It it doesn't then NULL is returned\&. + +.SS "(type *)talloc_get_type(const void *ptr, type);" + +.PP +This macro allows you to do type checking on talloc pointers\&. It is particularly useful for void* private pointers\&. It is equivalent to this: + +.nf +(type *)talloc_check_name(ptr, #type) +.fi + +.SS "talloc_set_type(const void *ptr, type);" + +.PP +This macro allows you to force the name of a pointer to be a particular \fItype\fR\&. This can be used in conjunction with talloc_get_type() to do type checking on void* pointers\&. + +.PP +It is equivalent to this: + +.nf +talloc_set_name_const(ptr, #type) +.fi + +.SH "PERFORMANCE" + +.PP +All the additional features of talloc(3) over malloc(3) do come at a price\&. We have a simple performance test in Samba4 that measures talloc() versus malloc() performance, and it seems that talloc() is about 10% slower than malloc() on my x86 Debian Linux box\&. For Samba, the great reduction in code complexity that we get by using talloc makes this worthwhile, especially as the total overhead of talloc/malloc in Samba is already quite small\&. + +.SH "SEE ALSO" + +.PP +malloc(3), strndup(3), vasprintf(3), asprintf(3), \fIhttp://talloc.samba.org/\fR + +.SH "COPYRIGHT/LICENSE" + +.PP +Copyright (C) Andrew Tridgell 2004 + +.PP +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 (at your option) any later version\&. + +.PP +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\&. + +.PP +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc\&., 675 Mass Ave, Cambridge, MA 02139, USA\&. + -- cgit From a411d4f4d5801a2ceae7eb7c88f5b6f7bc3bdcc3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 04:00:38 +0000 Subject: r8447: fixed make install in the farm (This used to be commit 4a61a5c70efdf3842e19ae74a2b56c4b10e8e294) --- source4/lib/tdb/Makefile.in | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index c06e7a8dc7..8e9a359514 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -16,6 +16,9 @@ TDB_OBJ = common/tdb.o common/spinlock.o all: $(PROGS) install: all + mkdir -p $(bindir) + mkdir -p $(includedir) + mkdir -p $(libdir) cp $(PROGS) $(bindir) cp include/tdb.h $(includedir) cp tdb.pc $(libdir)/pkgconfig -- cgit From 606beece8ed995f457b012a8010aa0e8ed1f5b07 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 04:27:55 +0000 Subject: r8448: - added a test target for tdb - reduced the torture size so it doesn't kill the build farm hosts (This used to be commit 7a88a9f06cbe5c125edad0da7908b94bcedfe4fc) --- source4/lib/tdb/Makefile.in | 5 +++++ source4/lib/tdb/tools/tdbtorture.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index 8e9a359514..ea96dddffc 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -40,3 +40,8 @@ bin/tdbbackup: tools/tdbbackup.o $(TDB_OBJ) clean: rm -f $(PROGS) common/*.o tools/*.o *~ *.bak */*~ */*.bak *% core test.db test.tdb test.gdbm + +installcheck: install + $(bindir)/tdbtorture + +test: installcheck diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 7e8e77952c..687d304b70 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -182,11 +182,11 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, } #ifndef NPROC -#define NPROC 6 +#define NPROC 2 #endif #ifndef NLOOPS -#define NLOOPS 200000 +#define NLOOPS 5000 #endif int main(int argc, const char *argv[]) @@ -197,6 +197,8 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, pids[0] = getpid(); + unlink("torture.tdb"); + for (i=0;i Date: Thu, 14 Jul 2005 06:36:19 +0000 Subject: r8450: more configure tests for solaris. It now builds some binaries, but fails in the ejs floating point code. (This used to be commit 30e1b6140e9f6246cb66eef7cf108d1ccf62bd40) --- source4/lib/replace/replace.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 89225d3d65..48e46ba18e 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -119,4 +119,16 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); typedef int (*comparison_fn_t)(const void *, const void *); #endif +#ifndef HAVE_U_INT32_T +typedef unsigned u_int32_t; +#endif + +#ifndef HAVE_U_INT16_T +typedef unsigned short u_int16_t; +#endif + +#ifndef HAVE_U_INT8_T +typedef unsigned char u_int8_t; +#endif + #endif -- cgit From fa2b97a20a518708e4534e8aa2cce12024228488 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 07:04:21 +0000 Subject: r8451: samba4 finally builds on solaris 8 sparc with heimdal and ejs its been a long haul ... (This used to be commit 3c4291e49abed14973b4a4fa1a9277918b896cac) --- source4/lib/appweb/mpr/var.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c index 533248dd06..d3d21f7eee 100644 --- a/source4/lib/appweb/mpr/var.c +++ b/source4/lib/appweb/mpr/var.c @@ -2165,8 +2165,10 @@ bool mprIsNan(double f) #elif VXWORKS /* FUTURE */ return (0); -#else +#elif defined(FP_NAN) return (f == FP_NAN); +#else + return 0; #endif } /******************************************************************************/ @@ -2178,8 +2180,10 @@ bool mprIsInfinite(double f) #elif VXWORKS /* FUTURE */ return (0); -#else +#elif defined(FP_INFINITE) return (f == FP_INFINITE); +#else + return 0; #endif } -- cgit From 598aafe9b3d6302e15a6a990e911c0fd3c23f634 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 07:35:48 +0000 Subject: r8453: my solaris10 box doesn't have math.h maybe sun isn't very good at maths? (This used to be commit ab67c8b2b7847ecad803dfc04a66007b8f6b4abe) --- source4/lib/appweb/mpr/miniMpr.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h index 8b28472826..6fc4d50c31 100644 --- a/source4/lib/appweb/mpr/miniMpr.h +++ b/source4/lib/appweb/mpr/miniMpr.h @@ -74,8 +74,9 @@ #if QNX4 #include #endif +#ifdef HAVE_MATH_H #include - +#endif /********************************** Defines ***********************************/ #ifdef __cplusplus -- cgit From c4173f67255f1c620d944bf68d34d577ab433ef1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 09:23:52 +0000 Subject: r8458: next target is irix - this gets the socket wrapper code building (This used to be commit 3d4a2221c3e032bbb6c23d132e00588f44f5e2ed) --- source4/lib/replace/replace.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 48e46ba18e..13cbc9dfe4 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -131,4 +131,8 @@ typedef unsigned short u_int16_t; typedef unsigned char u_int8_t; #endif +#ifndef HAVE_SOCKLEN_T +#define socklen_t int +#endif + #endif -- cgit From 978bbb4f4da3078c0c562cfccc18b76f518eccea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 12:00:31 +0000 Subject: r8461: fixed integer64 handling on bit endian platforms. The ejs code used %Ld, which is an invalid format code. This will probably cause problems on systems that don't have %lld, but do have a working snprintf otherwise. We will need to expand the snprintf configure test to make sure we replace snprintf on those platforms (This used to be commit ccc87eb8aaf571d91170555a732d287746b3430f) --- source4/lib/appweb/mpr/var.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c index d3d21f7eee..9b02c0f8b0 100644 --- a/source4/lib/appweb/mpr/var.c +++ b/source4/lib/appweb/mpr/var.c @@ -1658,7 +1658,7 @@ void mprVarToString(char** out, int size, char *fmt, MprVar *obj) #if BLD_GOAHEAD_WEBSERVER mprAllocSprintf(out, size, "%d", (int) obj->integer64); #else - mprAllocSprintf(out, size, "%Ld", obj->integer64); + mprAllocSprintf(out, size, "%lld", obj->integer64); #endif } else { mprAllocSprintf(out, size, fmt, obj->integer64); -- cgit From 5c453f5698add13c859ff0e4cd3e1865a8f08c39 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 13:14:47 +0000 Subject: r8465: once we define socklen_t, then tell other include files we have it. This prevents roken trying to redefine it (This used to be commit aa9491c0cb00f5cab9e00983bf2a0c266011904a) --- source4/lib/replace/replace.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 13cbc9dfe4..f85c8de634 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -133,6 +133,7 @@ typedef unsigned char u_int8_t; #ifndef HAVE_SOCKLEN_T #define socklen_t int +#define HAVE_SOCKLEN_T 1 #endif #endif -- cgit From 61b16caed8b0ae4ffbbbabfc007a6e3c19b39227 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 13:17:14 +0000 Subject: r8466: it is not portable to assert() a va_list (it breaks on alpha for example) (This used to be commit 2a64ee4227840de4aebe2ebe1887dfd167831738) --- source4/lib/appweb/ejs/ejsLib.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c index caae5b6495..b3e61ec375 100644 --- a/source4/lib/appweb/ejs/ejsLib.c +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -477,7 +477,6 @@ static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) char *errbuf, *msgbuf; mprAssert(ep); - mprAssert(args); msgbuf = NULL; mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); -- cgit From 1329c2eb1fd9d6c8180e694f039f07fcab59f9b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 13:21:27 +0000 Subject: r8467: using both math.h and float.h breaks popt on freebsd 5.4 (This used to be commit a1acb3300eec7717df24ecdf7205fb4e395d8c16) --- source4/lib/popt/popt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c index eb81c720f5..253fe9c424 100644 --- a/source4/lib/popt/popt.c +++ b/source4/lib/popt/popt.c @@ -10,10 +10,11 @@ #include "system.h" -#if HAVE_FLOAT_H +#if HAVE_MATH_H +#include +#elif HAVE_FLOAT_H #include #endif -#include #include "findme.h" #include "poptint.h" -- cgit From f48a20b249bdc3db549e2295404db697c92a9798 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Jul 2005 13:33:17 +0000 Subject: r8470: looks like popt portability is going to be a bit of a fight :( (This used to be commit d3872a6e4ce0227fa3c84173562551d0270918b6) --- source4/lib/popt/popt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/popt.c b/source4/lib/popt/popt.c index 253fe9c424..f25b9279a4 100644 --- a/source4/lib/popt/popt.c +++ b/source4/lib/popt/popt.c @@ -12,7 +12,8 @@ #if HAVE_MATH_H #include -#elif HAVE_FLOAT_H +#endif +#if HAVE_FLOAT_H #include #endif -- cgit From 7b8332369f3664af13bd7760561765a35c312b9e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Jul 2005 07:00:12 +0000 Subject: r8482: gnutls_x509_crt_set_subject_key_id is not available in some versions of gnutls. Thanks to ab for spotting this. (This used to be commit 437c4057ae4e89725ddbdd026977510beb33c009) --- source4/lib/tls/config.m4 | 16 ++++++++++++++++ source4/lib/tls/tlscert.c | 4 ++++ 2 files changed, 20 insertions(+) create mode 100644 source4/lib/tls/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/tls/config.m4 b/source4/lib/tls/config.m4 new file mode 100644 index 0000000000..6ad618632e --- /dev/null +++ b/source4/lib/tls/config.m4 @@ -0,0 +1,16 @@ +############################### +# start SMB_EXT_LIB_GNUTLS +# check for gnutls/gnutls.h and -lgnutls +AC_CHECK_HEADERS(gnutls/gnutls.h) +AC_CHECK_LIB_EXT(gnutls, GNUTLS_LIBS, gnutls_global_init) +if test x"$ac_cv_header_gnutls_gnutls_h" = x"yes" -a x"$ac_cv_lib_ext_gnutls_gnutls_global_init" = x"yes";then + SMB_EXT_LIB_ENABLE(GNUTLS,YES) + AC_CHECK_DECL(gnutls_x509_crt_set_subject_key_id, + [AC_DEFINE(HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID,1,gnutls subject_key)], [], [ +#include +#include +]) +fi +SMB_EXT_LIB(GNUTLS, $GNUTLS_LIBS) +# end SMB_EXT_LIB_GNUTLS +############################### diff --git a/source4/lib/tls/tlscert.c b/source4/lib/tls/tlscert.c index 2cd46ff432..d119922602 100644 --- a/source4/lib/tls/tlscert.c +++ b/source4/lib/tls/tlscert.c @@ -94,7 +94,9 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx, #endif TLSCHECK(gnutls_x509_crt_set_version(cacrt, 3)); TLSCHECK(gnutls_x509_crt_get_key_id(cacrt, 0, keyid, &keyidsize)); +#if HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID TLSCHECK(gnutls_x509_crt_set_subject_key_id(cacrt, keyid, keyidsize)); +#endif TLSCHECK(gnutls_x509_crt_sign(cacrt, cacrt, cakey)); DEBUG(3,("Generating TLS certificate\n")); @@ -118,7 +120,9 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx, #endif TLSCHECK(gnutls_x509_crt_set_version(crt, 3)); TLSCHECK(gnutls_x509_crt_get_key_id(crt, 0, keyid, &keyidsize)); +#if HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID TLSCHECK(gnutls_x509_crt_set_subject_key_id(crt, keyid, keyidsize)); +#endif TLSCHECK(gnutls_x509_crt_sign(crt, crt, key)); DEBUG(3,("Exporting TLS keys\n")); -- cgit From a0bc4da1a307753e3b28a11863f50d66b0894190 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Jul 2005 07:18:23 +0000 Subject: r8483: switched our generated ejs rpc code over to the new OO interface. This means we don't pollute the name space, and also makes for faster startup times as we only create variables for the pipes that we use, not all pipes (This used to be commit 57d7a585e8162d21c7152952aa0cc7471968784f) --- source4/lib/appweb/ejs/ejsProcs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsProcs.c b/source4/lib/appweb/ejs/ejsProcs.c index c01f411161..adef6e898a 100644 --- a/source4/lib/appweb/ejs/ejsProcs.c +++ b/source4/lib/appweb/ejs/ejsProcs.c @@ -629,6 +629,7 @@ int ejsDefineStandardProperties(MprVar *obj) mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); + mprCreatePropertyValue(obj, "NULL", mprCreatePtrVar(NULL)); #if BLD_FEATURE_LEGACY_API /* -- cgit From 32b06d5882a6fc93692815392e0a94d0709bc273 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Jul 2005 08:10:34 +0000 Subject: r8485: - be friendly to shells other than bash - don't use /tmp in test paths, as that opens us to symlink attacks (This used to be commit 9f29cccbc1fb44cb0317911601456c190883f066) --- source4/lib/ldb/tests/test-schema.sh | 3 ++- source4/lib/ldb/tests/test-sqlite3.sh | 3 ++- source4/lib/ldb/tests/test-tdb.sh | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-schema.sh b/source4/lib/ldb/tests/test-schema.sh index a8af8a38e2..2f10fb45e2 100755 --- a/source4/lib/ldb/tests/test-schema.sh +++ b/source4/lib/ldb/tests/test-schema.sh @@ -1,6 +1,7 @@ #!/bin/sh -export LDB_URL="tdb://schema.ldb" +LDB_URL="tdb://schema.ldb" +export LDB_URL rm -f schema.ldb diff --git a/source4/lib/ldb/tests/test-sqlite3.sh b/source4/lib/ldb/tests/test-sqlite3.sh index 7e0c96feaf..18e72024f3 100755 --- a/source4/lib/ldb/tests/test-sqlite3.sh +++ b/source4/lib/ldb/tests/test-sqlite3.sh @@ -1,7 +1,8 @@ #!/bin/sh -export LDB_URL="sqlite:///var/tmp/test.ldb" +LDB_URL="sqlite://test.ldb" +export LDB_URL rm -f sqltest.ldb diff --git a/source4/lib/ldb/tests/test-tdb.sh b/source4/lib/ldb/tests/test-tdb.sh index 936c448757..6899d98677 100755 --- a/source4/lib/ldb/tests/test-tdb.sh +++ b/source4/lib/ldb/tests/test-tdb.sh @@ -1,7 +1,8 @@ #!/bin/sh -export LDB_URL="tdbtest.ldb" +LDB_URL="tdbtest.ldb" +export LDB_URL PATH=bin:$PATH export PATH -- cgit From 4df9b5a6e3498743475d2309f75eb42db347f7eb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Jul 2005 11:27:32 +0000 Subject: r8490: make the ldb tests more portable (This used to be commit 6b20bcbeeb33a2cf6abc7bb251830ad6def9a79e) --- source4/lib/ldb/tests/test-extended.sh | 2 +- source4/lib/ldb/tests/test-generic.sh | 2 +- source4/lib/ldb/tests/test-tdb-features.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-extended.sh b/source4/lib/ldb/tests/test-extended.sh index c3958cf01c..a84e3b78a3 100755 --- a/source4/lib/ldb/tests/test-extended.sh +++ b/source4/lib/ldb/tests/test-extended.sh @@ -38,7 +38,7 @@ EOF checkcount() { count=$1 expression="$2" - n=`bin/ldbsearch "$expression" | grep ^dn | wc -l` + n=`bin/ldbsearch "$expression" | grep '^dn' | wc -l` if [ $n != $count ]; then echo "Got $n but expected $count for $expression" bin/ldbsearch "$expression" diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 3ad17fe9d3..cc9f41954f 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -58,7 +58,7 @@ echo "Starting ldbtest indexed" time $VALGRIND ldbtest --num-records 100 --num-searches 500 || exit 1 echo "Testing one level search" -count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep ^dn | wc -l` +count=`$VALGRIND ldbsearch -b 'ou=Groups,o=University of Michigan,c=TEST' -s one 'objectclass=*' none |grep '^dn' | wc -l` if [ $count != 3 ]; then echo returned $count records - expected 3 exit 1 diff --git a/source4/lib/ldb/tests/test-tdb-features.sh b/source4/lib/ldb/tests/test-tdb-features.sh index fb68733802..6f1afdcf33 100644 --- a/source4/lib/ldb/tests/test-tdb-features.sh +++ b/source4/lib/ldb/tests/test-tdb-features.sh @@ -7,7 +7,7 @@ mv $LDB_URL $LDB_URL.2 checkcount() { count=$1 expression="$2" - n=`bin/ldbsearch "$expression" | grep ^dn | wc -l` + n=`bin/ldbsearch "$expression" | grep '^dn' | wc -l` if [ $n != $count ]; then echo "Got $n but expected $count for $expression" $VALGRIND bin/ldbsearch "$expression" -- cgit From cb2c43f7b032c26adf82f3ba7d6e3dc855f89fa4 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 16 Jul 2005 18:16:32 +0000 Subject: r8515: ldb_dn_cmp now uses ldb_dn_compare so that the DNs are compared on a content level not ona form level, his means that the 2 DNs: a) cn= user, dc=this, dc = is,dc=test b) cn=user,dc=this,dc=is,dc=test are now identical even if the string form differ (spaces) (This used to be commit 76d496c30867ae80434483a34b0d842523aed762) --- source4/lib/ldb/common/ldb_dn.c | 23 +++++++++++++++++++++++ source4/lib/ldb/common/ldb_utf8.c | 9 --------- source4/lib/ldb/include/ldb.h | 2 +- source4/lib/ldb/tools/ldbedit.c | 10 ++++++---- source4/lib/ldb/tools/ldbsearch.c | 7 +++++-- 5 files changed, 35 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 32b575dd36..3cdc7ba85f 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -450,6 +450,29 @@ int ldb_dn_compare(struct ldb_context *ldb, return ldb_dn_compare_base(ldb, edn0, edn1); } +int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1) +{ + struct ldb_dn *edn0; + struct ldb_dn *edn1; + int ret; + + edn0 = ldb_dn_explode_casefold(ldb, dn0); + if (edn0 == NULL) return 0; + + edn1 = ldb_dn_explode_casefold(ldb, dn1); + if (edn1 == NULL) { + talloc_free(edn0); + return 0; + } + + ret = ldb_dn_compare(ldb, edn0, edn1); + + talloc_free(edn0); + talloc_free(edn1); + + return ret; +} + /* casefold a dn. We need to casefold the attribute names, and canonicalize attribute values of case insensitive attributes. diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 5df5a6bba7..cd68180f77 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -72,15 +72,6 @@ int ldb_caseless_cmp(const char *s1, const char *s2) return s2[i]; } -/* - compare two basedn fields - return 0 for match -*/ -int ldb_dn_cmp(const char *dn1, const char *dn2) -{ - return ldb_caseless_cmp(dn1, dn2); -} - /* compare two attributes return 0 for match diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index c2d7b0d614..485e2bc730 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -335,7 +335,7 @@ int ldb_attrib_add_handlers(struct ldb_context *ldb, /* useful functions for ldb_message structure manipulation */ -int ldb_dn_cmp(const char *dn1, const char *dn2); +int ldb_dn_cmp(struct ldb_context *ldb, const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); /* case-fold a DN */ diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 12bf12bfff..1613f4ddc5 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -93,12 +93,14 @@ static int modify_record(struct ldb_context *ldb, /* find dn in msgs[] */ -static struct ldb_message *msg_find(struct ldb_message **msgs, int count, +static struct ldb_message *msg_find(struct ldb_context *ldb, + struct ldb_message **msgs, + int count, const char *dn) { int i; for (i=0;idn) == 0) { + if (ldb_dn_cmp(ldb, dn, msgs[i]->dn) == 0) { return msgs[i]; } } @@ -119,7 +121,7 @@ static int merge_edits(struct ldb_context *ldb, /* do the adds and modifies */ for (i=0;idn); + msg = msg_find(ldb, msgs1, count1, msgs2[i]->dn); if (!msg) { if (options->verbose > 0) { ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); @@ -139,7 +141,7 @@ static int merge_edits(struct ldb_context *ldb, /* do the deletes */ for (i=0;idn); + msg = msg_find(ldb, msgs2, count2, msgs1[i]->dn); if (!msg) { if (options->verbose > 0) { ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 396bb7797a..5604436980 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -55,10 +55,12 @@ static void usage(void) exit(1); } +struct ldb_context *ldbsearch_ldb; + static int do_compare_msg(struct ldb_message **el1, - struct ldb_message **el2) + struct ldb_message **el2) { - return ldb_dn_cmp((*el1)->dn, (*el2)->dn); + return ldb_dn_cmp(ldbsearch_ldb, (*el1)->dn, (*el2)->dn); } static int do_search(struct ldb_context *ldb, @@ -79,6 +81,7 @@ static int do_search(struct ldb_context *ldb, printf("# returned %d records\n", ret); + ldbsearch_ldb = ldb; if (sort_attribs) { qsort(msgs, ret, sizeof(struct ldb_message *), (comparison_fn_t)do_compare_msg); -- cgit From 6e4bcaffa051f69f4e6595cf7d659ec22a22ef21 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Jul 2005 09:06:58 +0000 Subject: r8517: fixed a crash bug in ldb_dn_compare_base() (This used to be commit 19d789e82526eff236aeed77ddc8d2606c5118b6) --- source4/lib/ldb/common/ldb_dn.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 3cdc7ba85f..edb5124d99 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -412,13 +412,13 @@ int ldb_dn_compare_base(struct ldb_context *ldb, const struct ldb_dn *base, const struct ldb_dn *dn) { - int i, ret; + int ret; int n0, n1; /* if the number of components doesn't match they differ */ n0 = base->comp_num - 1; n1 = dn->comp_num - 1; - for (i = 0; i < base->comp_num; i++, n0--, n1--) { + while (n0 >= 0 && n1 >= 0) { const struct ldb_attrib_handler *h; /* compare names (attribute names are guaranteed to be ASCII only) */ @@ -435,6 +435,8 @@ int ldb_dn_compare_base(struct ldb_context *ldb, if (ret) { return ret; } + n1--; + n0--; } return 0; -- cgit From e835621799647ee70630b389fb53d15b15d68355 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Jul 2005 09:20:52 +0000 Subject: r8520: fixed a pile of warnings from the build farm gcc -Wall output on S390. This is an attempt to avoid the panic we're seeing in the automatic builds. The main fixes are: - assumptions that sizeof(size_t) == sizeof(int), mostly in printf formats - use of NULL format statements to perform dn searches. - assumption that sizeof() returns an int (This used to be commit a58ea6b3854973b694d2b1e22323ed7eb00e3a3f) --- source4/lib/charcnv.c | 5 +++-- source4/lib/gendb.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/messaging/messaging.c | 7 ++++--- source4/lib/registry/reg_backend_nt4.c | 2 +- source4/lib/util_file.c | 2 +- source4/lib/util_str.c | 6 +++--- 7 files changed, 14 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c index ea0fcd8d32..e632790155 100644 --- a/source4/lib/charcnv.c +++ b/source4/lib/charcnv.c @@ -175,11 +175,12 @@ ssize_t convert_string(charset_t from, charset_t to, if (from == CH_UNIX) { DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n", charset_name(from), charset_name(to), - srclen, destlen, (const char *)src)); + (int)srclen, (int)destlen, + (const char *)src)); } else { DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n", charset_name(from), charset_name(to), - srclen, destlen)); + (int)srclen, (int)destlen)); } break; case EILSEQ: diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index 92bbd8155c..4bf76a7f64 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -89,7 +89,7 @@ int gendb_search_dn(struct ldb_context *ldb, struct ldb_message ***res, const char * const *attrs) { - return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); + return gendb_search(ldb, mem_ctx, dn, res, attrs, "dn=%s", dn); } /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 03ad0612d4..87b52ac366 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -131,7 +131,7 @@ static char *ldb_dn_key(struct ldb_context *ldb, } ret = talloc_asprintf(ldb, "%s:%s:%.*s", - LTDB_INDEX, attr_folded, v.length, (char *)v.data); + LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data); if (v.data != value->data) { talloc_free(v.data); diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index a29f14f065..4f1589a9ba 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -93,7 +93,8 @@ static void ping_message(struct messaging_context *msg, void *private, uint32_t msg_type, uint32_t src, DATA_BLOB *data) { DEBUG(1,("INFO: Received PING message from server %u [%.*s]\n", - (uint_t)src, data->length, data->data?(const char *)data->data:"")); + (uint_t)src, (int)data->length, + data->data?(const char *)data->data:"")); messaging_send(msg, src, MSG_PONG, data); } @@ -198,7 +199,7 @@ static void messaging_recv_handler(struct messaging_context *msg) } if (msize < sizeof(*rec->header)) { - DEBUG(0,("messaging: bad message of size %d\n", msize)); + DEBUG(0,("messaging: bad message of size %d\n", (int)msize)); data_blob_free(&packet); return; } @@ -216,7 +217,7 @@ static void messaging_recv_handler(struct messaging_context *msg) if (msize != sizeof(*rec->header) + rec->header->length) { DEBUG(0,("messaging: bad message header size %d should be %d\n", - rec->header->length, msize - sizeof(*rec->header))); + rec->header->length, (int)(msize - sizeof(*rec->header)))); talloc_free(rec); return; } diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 6072222a87..e07534884c 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -1051,7 +1051,7 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk if (-size < (sizeof(NK_HDR) - 1 + namlen)) { DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", - sizeof(NK_HDR), namlen, clsname_len)); + (int)sizeof(NK_HDR), namlen, clsname_len)); return WERR_GENERAL_FAILURE; } diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index a7d29d1a1d..fdf06c47c5 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -258,7 +258,7 @@ void *map_file(char *fname, size_t size) if (!p) return NULL; if (s2 != size) { DEBUG(1,("incorrect size for %s - got %d expected %d\n", - fname, s2, size)); + fname, (int)s2, (int)size)); talloc_free(p); return NULL; } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 592c38e53c..a0e9da4160 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -274,7 +274,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength) if (len > maxlength) { DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", - (uint_t)(len-maxlength), len, maxlength, src)); + (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src)); len = maxlength; } @@ -760,7 +760,7 @@ void strlower_m(char *s) c_size2 = push_codepoint(d, tolower_w(c)); if (c_size2 > c_size) { DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n", - c, tolower_w(c), c_size, c_size2)); + c, tolower_w(c), (int)c_size, (int)c_size2)); smb_panic("codepoint expansion in strlower_m\n"); } s += c_size; @@ -796,7 +796,7 @@ void strupper_m(char *s) c_size2 = push_codepoint(d, toupper_w(c)); if (c_size2 > c_size) { DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n", - c, toupper_w(c), c_size, c_size2)); + c, toupper_w(c), (int)c_size, (int)c_size2)); smb_panic("codepoint expansion in strupper_m\n"); } s += c_size; -- cgit From 7bcccfc000a22c1f686341678f171bcfaed19763 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 17 Jul 2005 14:15:45 +0000 Subject: r8529: Matching against the wrong union (This used to be commit 24a65b5ba6e31655bdf49be8076d758206694ac3) --- source4/lib/ldb/common/ldb_match.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index f437f31eac..3664855ddd 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -2,6 +2,7 @@ ldb database library Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Simo Sorce 2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -101,11 +102,11 @@ static int ldb_match_present(struct ldb_context *ldb, enum ldb_scope scope) { - if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { + if (ldb_attr_cmp(tree->u.present.attr, "dn") == 0) { return 1; } - if (ldb_msg_find_element(msg, tree->u.simple.attr)) { + if (ldb_msg_find_element(msg, tree->u.present.attr)) { return 1; } -- cgit From d1f9224f5824856339d80cf93f1bf4fcee57ce8f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Jul 2005 09:46:52 +0000 Subject: r8540: fixed network interface detection on several hosts (This used to be commit 777ac8496b400b0ed348995feed83c22c5b344b3) --- source4/lib/netif/netif.c | 8 +++++--- source4/lib/netif/netif.h | 4 ---- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/netif.c b/source4/lib/netif/netif.c index 2a87a7a610..b197178880 100644 --- a/source4/lib/netif/netif.c +++ b/source4/lib/netif/netif.c @@ -35,15 +35,15 @@ #include #include #include -#include -#include #include #include #include #include +#include +#include +#include #ifndef AUTOCONF_TEST -#include "lib/netif/netif.h" #include "config.h" #endif @@ -77,6 +77,8 @@ #define QSORT_CAST (int (*)(const void *, const void *)) #endif +#include "netif.h" + #if HAVE_IFACE_IFCONF /* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 diff --git a/source4/lib/netif/netif.h b/source4/lib/netif/netif.h index d25294f8c2..7efe5a9b19 100644 --- a/source4/lib/netif/netif.h +++ b/source4/lib/netif/netif.h @@ -20,10 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include - struct iface_struct { char name[16]; struct in_addr ip; -- cgit From 7ef904e9e1de31129f12cb4c8dee0a06a93b9dc4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Jul 2005 10:01:58 +0000 Subject: r8541: this might take a few tries ... (This used to be commit cc61a0ba33d5a9d4d0b98736109220c58342358a) --- source4/lib/netif/netif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/netif/netif.c b/source4/lib/netif/netif.c index b197178880..8256615ef2 100644 --- a/source4/lib/netif/netif.c +++ b/source4/lib/netif/netif.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -77,6 +76,7 @@ #define QSORT_CAST (int (*)(const void *, const void *)) #endif +#include #include "netif.h" #if HAVE_IFACE_IFCONF -- cgit From 2d92eca39316a9edb17a1ffee0087f7365453471 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 00:40:52 +0000 Subject: r8562: small merge with upstream (This used to be commit 6c9bf162afddda4747ef08b56598aaf0747a4d27) --- source4/lib/appweb/ejs/ejsParser.c | 15 +++++---------- source4/lib/appweb/esp/esp.h | 2 -- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index 772ed574c5..452e7fde8f 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -1280,6 +1280,10 @@ static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, tid = ejsLexGetToken(ep, state); if (tid == EJS_TOK_LPAREN) { + if (ep->currentProperty == 0 && (flags & EJS_FLAGS_EXE)) { + ejsError(ep, "Function name not defined \"%s\"\n", *id); + return -1; + } ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); return state; } @@ -1975,11 +1979,6 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) actualArgs = proc->args; argValues = (MprVar**) actualArgs->handles; - if (prototype == NULL) { - ejsError(ep, "Function name not defined '%s'\n", proc->procName); - return -1; - } - /* * Create a new variable stack frame. ie. new local variables. */ @@ -2179,7 +2178,6 @@ int ejsRunFunction(int eid, MprVar *obj, const char *functionName, MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) { - MprVar *vp; MprVar *obj; mprAssert(ep); @@ -2193,10 +2191,7 @@ MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) } else { /* First look local, then look global */ - vp = mprGetProperty(ep->local, property, 0); - if (vp) { - obj = ep->local; - } else if (mprGetProperty(ep->local, property, 0)) { + if (mprGetProperty(ep->local, property, 0)) { obj = ep->local; } else { obj = ep->global; diff --git a/source4/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h index e15daf0b4e..39dc5310c2 100644 --- a/source4/lib/appweb/esp/esp.h +++ b/source4/lib/appweb/esp/esp.h @@ -43,8 +43,6 @@ /*********************************** Defines **********************************/ -#define ESP_STRING_ARGS MPR_TYPE_STRING_ARGS - #if BLD_FEATURE_SQUEEZE #define ESP_TOK_INCR 1024 #define ESP_MAX_HEADER 1024 -- cgit From d2d5d71f34800fa74132a4f013b80eae3c9d6124 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 01:33:38 +0000 Subject: r8567: fixed the build after the com idl changes Jelmer, can you please check that I got this right? (This used to be commit bec135446af741200743cdc4ecb4c5ce68ed34a6) --- source4/lib/com/dcom/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c index bc47cb7c68..1c54f17113 100644 --- a/source4/lib/com/dcom/main.c +++ b/source4/lib/com/dcom/main.c @@ -164,7 +164,7 @@ WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const cha r.in.protseq = protseq; r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; - r.out.ifaces = talloc_array(ctx, struct pMInterfacePointer, num_ifaces); + r.out.ifaces = talloc_array(ctx, struct MInterfacePointer *, num_ifaces); r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); @@ -186,7 +186,7 @@ WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const cha results[i] = r.out.results[i]; (*ip)[i] = NULL; if (W_ERROR_IS_OK(results[i])) { - status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].ip->obj); + status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i]->obj); if (!NT_STATUS_IS_OK(status)) { results[i] = ntstatus_to_werror(status); } @@ -208,7 +208,7 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const struct DUALSTRINGARRAY dualstring; NTSTATUS status; struct MInterfacePointer pm; - struct pMInterfacePointer ifaces[1]; + struct MInterfacePointer *ifaces[1]; uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; if (!server) { @@ -233,7 +233,7 @@ WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; r.out.ifaces = ifaces; - ifaces[0].ip = ± + ifaces[0] = ± r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); -- cgit From 9a4bc49fee7666427c35db287948d5acc47990e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 05:09:36 +0000 Subject: r8579: recognise the name 'localhost' as 127.0.0.1. This solves a problem with some hosts that are missing localhost from /etc/hosts (This used to be commit f9866258e099001390aa61dcc12055fe1374db60) --- source4/lib/util.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 308d1b6f45..03ae86422f 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -339,6 +339,11 @@ uint32_t interpret_addr(const char *str) if (strcmp(str,"255.255.255.255") == 0) { return 0xFFFFFFFF; } + /* recognise 'localhost' as a special name. This fixes problems with + some hosts that don't have localhost in /etc/hosts */ + if (strcmp(str,"localhost") == 0) { + str = "127.0.0.1"; + } /* if it's in the form of an IP address then get the lib to interpret it */ if (is_ipaddress(str)) { -- cgit From b48422173005c83034b474db47f956476e862bba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 05:35:19 +0000 Subject: r8580: try to fix the build on stratus (This used to be commit 58d7a1e6a311c98c9b4dfc9e280b328406165997) --- source4/lib/replace/replace.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index 89612912b7..79b452d69c 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -191,16 +191,12 @@ Corrections by richard.kettlewell@kewill.com /**************************************************************************** some systems don't have an initgroups call ****************************************************************************/ - int initgroups(char *name,gid_t id) + int initgroups(char *name, gid_t id) { #ifndef HAVE_SETGROUPS - static int done; - if (!done) { - DEBUG(1,("WARNING: running without setgroups\n")); - done=1; - } /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ - return(0); + errno = ENOSYS; + return -1; #else /* HAVE_SETGROUPS */ gid_t *grouplst = NULL; int max_gr = groups_max(); @@ -209,8 +205,8 @@ Corrections by richard.kettlewell@kewill.com struct group *g; char *gr; - if((grouplst = malloc_array_p(gid_t, max_gr)) == NULL) { - DEBUG(0,("initgroups: malloc fail !\n")); + if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) { + errno = ENOMEM; return -1; } @@ -232,8 +228,8 @@ Corrections by richard.kettlewell@kewill.com } } endgrent(); - ret = sys_setgroups(i,grouplst); - SAFE_FREE(grouplst); + ret = setgroups(i, grouplst); + free(grouplst); return ret; #endif /* HAVE_SETGROUPS */ } @@ -429,7 +425,7 @@ duplicate a string if (!msg) return; syslog(facility_priority, "%s", msg); - SAFE_FREE(msg); + free(msg); } #endif /* HAVE_SYSLOG */ #endif /* HAVE_VSYSLOG */ -- cgit From bfb11862698743ee36bc6050269378321e6e577c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Jul 2005 09:09:00 +0000 Subject: r8585: add to ldb and ldap comparison functionality better pares filters Approx is currently only a stub need to dig more info to understand what it really means and how it works exactly (This used to be commit a9e8cd0bad27ed2b3c6a12302e787ba3c9a70a3c) --- source4/lib/ldb/common/ldb_match.c | 99 +++++-- source4/lib/ldb/common/ldb_parse.c | 493 ++++++++++++++++++++-------------- source4/lib/ldb/include/ldb.h | 25 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 47 ++-- source4/lib/ldb/tests/test-generic.sh | 13 + 5 files changed, 420 insertions(+), 257 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 3664855ddd..97e0a60ace 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -113,14 +113,53 @@ static int ldb_match_present(struct ldb_context *ldb, return 0; } +static int ldb_match_comparison(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope, + enum ldb_parse_op comp_op) +{ + unsigned int i; + struct ldb_message_element *el; + const struct ldb_attrib_handler *h; + int ret; + + /* FIXME: APPROX comparison not handled yet */ + if (comp_op == LDB_OP_APPROX) return 0; + + el = ldb_msg_find_element(msg, tree->u.comparison.attr); + if (el == NULL) { + return 0; + } + + h = ldb_attrib_handler(ldb, el->name); + + for (i = 0; i < el->num_values; i++) { + ret = h->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value); + + if (ret == 0) { + return 1; + } + if (ret > 0 && comp_op == LDB_OP_GREATER) { + return 1; + } + if (ret < 0 && comp_op == LDB_OP_LESS) { + return 1; + } + } + + return 0; +} + /* match a simple leaf node */ -static int ldb_match_simple(struct ldb_context *ldb, - struct ldb_message *msg, - struct ldb_parse_tree *tree, - const char *base, - enum ldb_scope scope) +static int ldb_match_equality(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_parse_tree *tree, + const char *base, + enum ldb_scope scope) { unsigned int i; struct ldb_message_element *el; @@ -128,12 +167,12 @@ static int ldb_match_simple(struct ldb_context *ldb, struct ldb_dn *msgdn, *valuedn; int ret; - if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) { + if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { msgdn = ldb_dn_explode_casefold(ldb, msg->dn); if (msgdn == NULL) return 0; - valuedn = ldb_dn_explode_casefold(ldb, tree->u.simple.value.data); + valuedn = ldb_dn_explode_casefold(ldb, tree->u.equality.value.data); if (valuedn == NULL) { talloc_free(msgdn); return 0; @@ -148,7 +187,7 @@ static int ldb_match_simple(struct ldb_context *ldb, return 0; } - el = ldb_msg_find_element(msg, tree->u.simple.attr); + el = ldb_msg_find_element(msg, tree->u.equality.attr); if (el == NULL) { return 0; } @@ -156,7 +195,7 @@ static int ldb_match_simple(struct ldb_context *ldb, h = ldb_attrib_handler(ldb, el->name); for (i=0;inum_values;i++) { - if (h->comparison_fn(ldb, ldb, &tree->u.simple.value, + if (h->comparison_fn(ldb, ldb, &tree->u.equality.value, &el->values[i]) == 0) { return 1; } @@ -242,7 +281,7 @@ static int ldb_match_substring(struct ldb_context *ldb, unsigned int i; struct ldb_message_element *el; - el = ldb_msg_find_element(msg, tree->u.simple.attr); + el = ldb_msg_find_element(msg, tree->u.substring.attr); if (el == NULL) { return 0; } @@ -357,21 +396,6 @@ static int ldb_match_message(struct ldb_context *ldb, int v; switch (tree->operation) { - case LDB_OP_SIMPLE: - return ldb_match_simple(ldb, msg, tree, base, scope); - - case LDB_OP_PRESENT: - return ldb_match_present(ldb, msg, tree, base, scope); - - case LDB_OP_SUBSTRING: - return ldb_match_substring(ldb, msg, tree, base, scope); - - case LDB_OP_EXTENDED: - return ldb_match_extended(ldb, msg, tree, base, scope); - - case LDB_OP_NOT: - return ! ldb_match_message(ldb, msg, tree->u.isnot.child, base, scope); - case LDB_OP_AND: for (i=0;iu.list.num_elements;i++) { v = ldb_match_message(ldb, msg, tree->u.list.elements[i], @@ -387,6 +411,31 @@ static int ldb_match_message(struct ldb_context *ldb, if (v) return 1; } return 0; + + case LDB_OP_NOT: + return ! ldb_match_message(ldb, msg, tree->u.isnot.child, base, scope); + + case LDB_OP_EQUALITY: + return ldb_match_equality(ldb, msg, tree, base, scope); + + case LDB_OP_SUBSTRING: + return ldb_match_substring(ldb, msg, tree, base, scope); + + case LDB_OP_GREATER: + return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_GREATER); + + case LDB_OP_LESS: + return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_LESS); + + case LDB_OP_PRESENT: + return ldb_match_present(ldb, msg, tree, base, scope); + + case LDB_OP_APPROX: + return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_APPROX); + + case LDB_OP_EXTENDED: + return ldb_match_extended(ldb, msg, tree, base, scope); + } return 0; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 933ff18f2b..83fcc73941 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -58,73 +58,6 @@ a filter is defined by: ::= '=' | '~=' | '<=' | '>=' */ -#define LDB_ALL_SEP "()&|=!" - -/* - return next token element. Caller frees -*/ -static char *ldb_parse_lex(void *ctx, const char **s, const char *sep) -{ - const char *p = *s; - char *ret; - - while (isspace((unsigned char)*p)) { - p++; - } - *s = p; - - if (*p == 0) { - return NULL; - } - - if (strchr(sep, *p)) { - (*s) = p+1; - ret = talloc_strndup(ctx, p, 1); - if (!ret) { - errno = ENOMEM; - } - return ret; - } - - while (*p && (isalnum((unsigned char)*p) || !strchr(sep, *p))) { - p++; - } - - if (p == *s) { - return NULL; - } - - ret = talloc_strndup(ctx, *s, p - *s); - if (!ret) { - errno = ENOMEM; - } - - *s = p; - - return ret; -} - -/* - find a matching close brace in a string -*/ -static const char *match_brace(const char *s) -{ - unsigned int count = 0; - while (*s && (count != 0 || *s != ')')) { - if (*s == '(') { - count++; - } - if (*s == ')') { - count--; - } - s++; - } - if (! *s) { - return NULL; - } - return s; -} - /* decode a RFC2254 binary string representation of a buffer. Used in LDAP filters. @@ -273,7 +206,7 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s); static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, char *attr, char *value) { - char *p1, *p2, *p3; + char *p1, *p2; ret->operation = LDB_OP_EXTENDED; ret->u.extended.value = ldb_binary_decode(ret, value); @@ -282,18 +215,14 @@ static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, p1 = strchr(attr, ':'); if (p1 == NULL) goto failed; p2 = strchr(p1+1, ':'); - if (p2 == NULL) goto failed; - p3 = strchr(p2+1, ':'); *p1 = 0; - *p2 = 0; - if (p3) *p3 = 0; + if (p2) *p2 = 0; - ret->u.extended.attr = talloc_strdup(ret, attr); - if (ret->u.extended.attr == NULL) goto failed; + ret->u.extended.attr = attr; if (strcmp(p1+1, "dn") == 0) { ret->u.extended.dnAttributes = 1; - if (p3) { + if (p2) { ret->u.extended.rule_id = talloc_strdup(ret, p2+1); if (ret->u.extended.rule_id == NULL) goto failed; } else { @@ -312,14 +241,104 @@ failed: return NULL; } +static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char **value, const char **s) +{ + enum ldb_parse_op filter = 0; + char *name, *val, *k; + const char *p = *s; + const char *t, *t1; + + /* retrieve attributetype name */ + t = p; + + while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */ + p++; + } + + if (*p == ':') { /* but extended searches have : and . chars too */ + p = strstr(p, ":="); + if (p == NULL) { /* malformed attribute name */ + return 0; + } + } + + t1 = p; + + while (isspace((unsigned char)*p)) p++; + + if (!strchr("=<>~:", *p)) { + return 0; + } + + /* save name */ + name = talloc_memdup(mem_ctx, t, t1 - t + 1); + if (name == NULL) return 0; + name[t1 - t] = '\0'; + + /* retrieve filtertype */ + + if (*p == '=') { + filter = LDB_OP_EQUALITY; + } else if (*(p + 1) == '=') { + switch (*p) { + case '<': + filter = LDB_OP_LESS; + p++; + break; + case '>': + filter = LDB_OP_GREATER; + p++; + break; + case '~': + filter = LDB_OP_APPROX; + p++; + break; + case ':': + filter = LDB_OP_EXTENDED; + p++; + break; + } + } + if (!filter) { + talloc_free(name); + return filter; + } + p++; + + while (isspace((unsigned char)*p)) p++; + + /* retieve value */ + t = p; + + while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++; + + val = talloc_memdup(mem_ctx, t, p - t + 1); + if (val == NULL) { + talloc_free(name); + return 0; + } + val[p - t] = '\0'; + + k = &(val[p - t]); + + /* remove trailing spaces from value */ + while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--; + *k = '\0'; + + *type = name; + *value = val; + *s = p; + return filter; +} /* ::= */ -static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char **s) { - char *eq, *val, *l; + char *attr, *value; struct ldb_parse_tree *ret; + enum ldb_parse_op filtertype; ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { @@ -327,64 +346,92 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) return NULL; } - l = ldb_parse_lex(ret, &s, LDB_ALL_SEP); - if (!l) { + filtertype = ldb_parse_filtertype(ret, &attr, &value, s); + if (!filtertype) { talloc_free(ret); return NULL; } - if (strchr("()&|=", *l)) { - talloc_free(ret); - return NULL; - } + switch (filtertype) { - eq = ldb_parse_lex(ret, &s, LDB_ALL_SEP); - if (!eq || strcmp(eq, "=") != 0) { - talloc_free(ret); - return NULL; - } - talloc_free(eq); + case LDB_OP_EQUALITY: - val = ldb_parse_lex(ret, &s, ")"); - if (val && strchr("()&|", *val)) { - talloc_free(ret); - return NULL; - } + if (strcmp(value, "*") == 0) { + ret->operation = LDB_OP_PRESENT; + ret->u.present.attr = attr; + break; + } - if (l[strlen(l)-1] == ':') { - /* its an extended match */ - return ldb_parse_extended(ret, l, val); - } + if (ldb_parse_find_wildcard(value) != NULL) { + ret->operation = LDB_OP_SUBSTRING; + ret->u.substring.attr = attr; + ret->u.substring.start_with_wildcard = 0; + ret->u.substring.end_with_wildcard = 0; + ret->u.substring.chunks = ldb_wildcard_decode(ret, value); + if (ret->u.substring.chunks == NULL){ + talloc_free(ret); + return NULL; + } + if (value[0] == '*') + ret->u.substring.start_with_wildcard = 1; + if (value[strlen(value) - 1] == '*') + ret->u.substring.end_with_wildcard = 1; + talloc_free(value); + + break; + } + + ret->operation = LDB_OP_EQUALITY; + ret->u.equality.attr = attr; + ret->u.equality.value = ldb_binary_decode(ret, value); + if (ret->u.equality.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_GREATER: + ret->operation = LDB_OP_GREATER; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_LESS: + ret->operation = LDB_OP_LESS; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; + + case LDB_OP_APPROX: + ret->operation = LDB_OP_APPROX; + ret->u.comparison.attr = attr; + ret->u.comparison.value = ldb_binary_decode(ret, value); + if (ret->u.comparison.value.data == NULL) { + talloc_free(ret); + return NULL; + } + talloc_free(value); + break; - if (val && strcmp(val, "*") == 0) { - ret->operation = LDB_OP_PRESENT; - ret->u.present.attr = l; + case LDB_OP_EXTENDED: - return ret; - } + ret = ldb_parse_extended(ret, attr, value); + break; - if (val && ldb_parse_find_wildcard(val) != NULL) { - ret->operation = LDB_OP_SUBSTRING; - ret->u.substring.attr = l; - ret->u.substring.start_with_wildcard = 0; - ret->u.substring.end_with_wildcard = 0; - ret->u.substring.chunks = ldb_wildcard_decode(ret, val); - if (ret->u.substring.chunks == NULL){ + default: talloc_free(ret); return NULL; - } - if (val[0] == '*') ret->u.substring.start_with_wildcard = 1; - if (val[strlen(val) - 1] == '*') ret->u.substring.end_with_wildcard = 1; - - return ret; - } - - ret->operation = LDB_OP_SIMPLE; - ret->u.simple.attr = l; - ret->u.simple.value = ldb_binary_decode(ret, val); - if (ret->u.simple.value.data == NULL) { - talloc_free(ret); - return NULL; } return ret; @@ -397,10 +444,25 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char *s) ::= '|' ::= | */ -static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, - enum ldb_parse_op op, const char *s) +static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, const char **s) { struct ldb_parse_tree *ret, *next; + enum ldb_parse_op op; + const char *p = *s; + + switch (*p) { + case '&': + op = LDB_OP_AND; + break; + case '|': + op = LDB_OP_OR; + break; + default: + return NULL; + } + p++; + + while (isspace((unsigned char)*p)) p++; ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { @@ -417,19 +479,19 @@ static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, return NULL; } - ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &s); + ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &p); if (!ret->u.list.elements[0]) { talloc_free(ret); return NULL; } - while (isspace((unsigned char)*s)) s++; + while (isspace((unsigned char)*p)) p++; - while (*s && (next = ldb_parse_filter(ret->u.list.elements, &s))) { + while (*p && (next = ldb_parse_filter(ret->u.list.elements, &p))) { struct ldb_parse_tree **e; e = talloc_realloc(ret, ret->u.list.elements, struct ldb_parse_tree *, - ret->u.list.num_elements+1); + ret->u.list.num_elements + 1); if (!e) { errno = ENOMEM; talloc_free(ret); @@ -438,9 +500,11 @@ static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, ret->u.list.elements = e; ret->u.list.elements[ret->u.list.num_elements] = next; ret->u.list.num_elements++; - while (isspace((unsigned char)*s)) s++; + while (isspace((unsigned char)*p)) p++; } + *s = p; + return ret; } @@ -448,9 +512,15 @@ static struct ldb_parse_tree *ldb_parse_filterlist(void *mem_ctx, /* ::= '!' */ -static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char **s) { struct ldb_parse_tree *ret; + const char *p = *s; + + if (*p != '!') { + return NULL; + } + p++; ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { @@ -459,12 +529,14 @@ static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) } ret->operation = LDB_OP_NOT; - ret->u.isnot.child = ldb_parse_filter(ret, &s); + ret->u.isnot.child = ldb_parse_filter(ret, &p); if (!ret->u.isnot.child) { talloc_free(ret); return NULL; } + *s = p; + return ret; } @@ -472,26 +544,37 @@ static struct ldb_parse_tree *ldb_parse_not(void *mem_ctx, const char *s) parse a filtercomp ::= | | | */ -static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char *s) +static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char **s) { - while (isspace((unsigned char)*s)) s++; + struct ldb_parse_tree *ret; + const char *p = *s; - switch (*s) { + while (isspace((unsigned char)*p)) p++; + + switch (*p) { case '&': - return ldb_parse_filterlist(mem_ctx, LDB_OP_AND, s+1); + ret = ldb_parse_filterlist(mem_ctx, &p); + break; case '|': - return ldb_parse_filterlist(mem_ctx, LDB_OP_OR, s+1); + ret = ldb_parse_filterlist(mem_ctx, &p); + break; case '!': - return ldb_parse_not(mem_ctx, s+1); + ret = ldb_parse_not(mem_ctx, &p); + break; case '(': case ')': return NULL; + + default: + ret = ldb_parse_simple(mem_ctx, &p); + } - return ldb_parse_simple(mem_ctx, s); + *s = p; + return ret; } @@ -500,37 +583,26 @@ static struct ldb_parse_tree *ldb_parse_filtercomp(void *mem_ctx, const char *s) */ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) { - char *l, *s2; - const char *p, *p2; struct ldb_parse_tree *ret; + const char *p = *s; - l = ldb_parse_lex(mem_ctx, s, LDB_ALL_SEP); - if (!l) { + if (*p != '(') { return NULL; } + p++; - if (strcmp(l, "(") != 0) { - talloc_free(l); - return NULL; - } - talloc_free(l); + ret = ldb_parse_filtercomp(mem_ctx, &p); - p = match_brace(*s); - if (!p) { + if (*p != ')') { return NULL; } - p2 = p + 1; + p++; - s2 = talloc_strndup(mem_ctx, *s, p - *s); - if (!s2) { - errno = ENOMEM; - return NULL; + while (isspace((unsigned char)*p)) { + p++; } - ret = ldb_parse_filtercomp(mem_ctx, s2); - talloc_free(s2); - - *s = p2; + *s = p; return ret; } @@ -549,7 +621,7 @@ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) return ldb_parse_filter(mem_ctx, &s); } - return ldb_parse_simple(mem_ctx, s); + return ldb_parse_simple(mem_ctx, &s); } @@ -562,22 +634,42 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) int i; switch (tree->operation) { - case LDB_OP_SIMPLE: - s = ldb_binary_encode(mem_ctx, tree->u.simple.value); + case LDB_OP_AND: + case LDB_OP_OR: + ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); + if (ret == NULL) return NULL; + for (i=0;iu.list.num_elements;i++) { + s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + s2 = talloc_asprintf_append(ret, "%s", s); + talloc_free(s); + if (s2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = s2; + } + s = talloc_asprintf_append(ret, ")"); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + return s; + case LDB_OP_NOT: + s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child); if (s == NULL) return NULL; - ret = talloc_asprintf(mem_ctx, "(%s=%s)", - tree->u.simple.attr, s); + + ret = talloc_asprintf(mem_ctx, "(!%s)", s); talloc_free(s); return ret; - case LDB_OP_EXTENDED: - s = ldb_binary_encode(mem_ctx, tree->u.extended.value); + case LDB_OP_EQUALITY: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); if (s == NULL) return NULL; - ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", - tree->u.extended.attr?tree->u.extended.attr:"", - tree->u.extended.dnAttributes?":dn":"", - tree->u.extended.rule_id?":":"", - tree->u.extended.rule_id?tree->u.extended.rule_id:"", - s); + ret = talloc_asprintf(mem_ctx, "(%s=%s)", + tree->u.equality.attr, s); talloc_free(s); return ret; case LDB_OP_SUBSTRING: @@ -600,39 +692,40 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) ret[strlen(ret) - 1] = '\0'; /* remove last wildcard */ } return ret; + case LDB_OP_GREATER: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s>=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_LESS: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s<=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; case LDB_OP_PRESENT: ret = talloc_strdup(mem_ctx, "*"); if (ret == NULL) return NULL; return ret; - case LDB_OP_AND: - case LDB_OP_OR: - ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); - if (ret == NULL) return NULL; - for (i=0;iu.list.num_elements;i++) { - s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]); - if (s == NULL) { - talloc_free(ret); - return NULL; - } - s2 = talloc_asprintf_append(ret, "%s", s); - talloc_free(s); - if (s2 == NULL) { - talloc_free(ret); - return NULL; - } - ret = s2; - } - s = talloc_asprintf_append(ret, ")"); - if (s == NULL) { - talloc_free(ret); - return NULL; - } - return s; - case LDB_OP_NOT: - s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child); + case LDB_OP_APPROX: + s = ldb_binary_encode(mem_ctx, tree->u.equality.value); if (s == NULL) return NULL; - - ret = talloc_asprintf(mem_ctx, "(!%s)", s); + ret = talloc_asprintf(mem_ctx, "(%s~=%s)", + tree->u.equality.attr, s); + talloc_free(s); + return ret; + case LDB_OP_EXTENDED: + s = ldb_binary_encode(mem_ctx, tree->u.extended.value); + if (s == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", + tree->u.extended.attr?tree->u.extended.attr:"", + tree->u.extended.dnAttributes?":dn":"", + tree->u.extended.rule_id?":":"", + tree->u.extended.rule_id?tree->u.extended.rule_id:"", + s); talloc_free(s); return ret; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 485e2bc730..6670089902 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -154,26 +154,34 @@ struct ldb_debug_ops { /* structues for ldb_parse_tree handling code */ -enum ldb_parse_op {LDB_OP_SIMPLE=1, LDB_OP_EXTENDED=2, - LDB_OP_SUBSTRING=3, LDB_OP_PRESENT=4, - LDB_OP_AND='&', LDB_OP_OR='|', LDB_OP_NOT='!'}; +enum ldb_parse_op { LDB_OP_AND=1, LDB_OP_OR=2, LDB_OP_NOT=3, + LDB_OP_EQUALITY=4, LDB_OP_SUBSTRING=5, + LDB_OP_GREATER=6, LDB_OP_LESS=7, LDB_OP_PRESENT=8, + LDB_OP_APPROX=9, LDB_OP_EXTENDED=10 }; struct ldb_parse_tree { enum ldb_parse_op operation; union { struct { - char *attr; - struct ldb_val value; - } simple; + struct ldb_parse_tree *child; + } isnot; struct { char *attr; - } present; + struct ldb_val value; + } equality; struct { char *attr; int start_with_wildcard; int end_with_wildcard; struct ldb_val **chunks; } substring; + struct { + char *attr; + } present; + struct { + char *attr; + struct ldb_val value; + } comparison; struct { char *attr; int dnAttributes; @@ -184,9 +192,6 @@ struct ldb_parse_tree { unsigned int num_elements; struct ldb_parse_tree **elements; } list; - struct { - struct ldb_parse_tree *child; - } isnot; } u; }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 87b52ac366..1cfebe6864 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -190,13 +190,13 @@ static int ltdb_index_dn_simple(struct ldb_module *module, /* if the attribute isn't in the list of indexed attributes then this node needs a full search */ - if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL, LTDB_IDXATTR) == -1) { + if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) { return -1; } /* the attribute is indexed. Pull the list of DNs that match the search criterion */ - dn = ldb_dn_key(ldb, tree->u.simple.attr, &tree->u.simple.value); + dn = ldb_dn_key(ldb, tree->u.equality.attr, &tree->u.equality.value); if (!dn) return -1; msg = talloc(list, struct ldb_message); @@ -256,7 +256,7 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, struct ldb_context *ldb = module->ldb; unsigned int i; int ret; - const char *target = tree->u.simple.value.data; + const char *target = tree->u.equality.value.data; const char **subclasses; list->count = 0; @@ -273,16 +273,16 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, for (i=0;subclasses[i];i++) { struct ldb_parse_tree tree2; struct dn_list *list2; - tree2.operation = LDB_OP_SIMPLE; - tree2.u.simple.attr = talloc_strdup(list, LTDB_OBJECTCLASS); - if (!tree2.u.simple.attr) { + tree2.operation = LDB_OP_EQUALITY; + tree2.u.equality.attr = talloc_strdup(list, LTDB_OBJECTCLASS); + if (!tree2.u.equality.attr) { return -1; } - tree2.u.simple.value.data = talloc_strdup(tree2.u.simple.attr, subclasses[i]); - if (tree2.u.simple.value.data == NULL) { + tree2.u.equality.value.data = talloc_strdup(tree2.u.equality.attr, subclasses[i]); + if (tree2.u.equality.value.data == NULL) { return -1; } - tree2.u.simple.value.length = strlen(subclasses[i]); + tree2.u.equality.value.length = strlen(subclasses[i]); list2 = talloc(list, struct dn_list); if (list2 == NULL) { return -1; @@ -297,7 +297,7 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, talloc_free(list2); } } - talloc_free(tree2.u.simple.attr); + talloc_free(tree2.u.equality.attr); } return ret; @@ -311,7 +311,7 @@ static int ltdb_index_dn_leaf(struct ldb_module *module, const struct ldb_message *index_list, struct dn_list *list) { - if (ldb_attr_cmp(tree->u.simple.attr, LTDB_OBJECTCLASS) == 0) { + if (ldb_attr_cmp(tree->u.equality.attr, LTDB_OBJECTCLASS) == 0) { return ltdb_index_dn_objectclass(module, tree, index_list, list); } return ltdb_index_dn_simple(module, tree, index_list, list); @@ -570,17 +570,6 @@ static int ltdb_index_dn(struct ldb_module *module, int ret = -1; switch (tree->operation) { - case LDB_OP_SIMPLE: - ret = ltdb_index_dn_leaf(module, tree, index_list, list); - break; - - case LDB_OP_PRESENT: - case LDB_OP_SUBSTRING: - case LDB_OP_EXTENDED: - /* we can't index with fancy bitops yet */ - ret = -1; - break; - case LDB_OP_AND: ret = ltdb_index_dn_and(module, tree, index_list, list); break; @@ -592,6 +581,20 @@ static int ltdb_index_dn(struct ldb_module *module, case LDB_OP_NOT: ret = ltdb_index_dn_not(module, tree, index_list, list); break; + + case LDB_OP_EQUALITY: + ret = ltdb_index_dn_leaf(module, tree, index_list, list); + break; + + case LDB_OP_SUBSTRING: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_PRESENT: + case LDB_OP_APPROX: + case LDB_OP_EXTENDED: + /* we can't index with fancy bitops yet */ + ret = -1; + break; } return ret; diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index cc9f41954f..0e2cb187a1 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -64,5 +64,18 @@ if [ $count != 3 ]; then exit 1 fi +echo "Testing compare" +count=`$VALGRIND ldbsearch '(cn>=U)' cn | grep '^dn' | wc -l` +if [ $count != 2 ]; then + echo returned $count records - expected 2 + exit 1 +fi + +count=`$VALGRIND ldbsearch '(cn<=U)' cn | grep '^dn' | wc -l` +if [ $count != 13 ]; then + echo returned $count records - expected 13 + exit 1 +fi + echo "Testing binary file attribute value" $VALGRIND ldbmodify $LDBDIR/tests/photo.ldif || exit 1 -- cgit From 7ee2babcfe2ffb956a9013a2364c038021b77ae3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 09:28:13 +0000 Subject: r8587: - fixed ref allocation in irpc replies - make every irpc server support the irpc_uptime() call (This used to be commit eee90448268b9f673cc43076ad87529aa80d17ae) --- source4/lib/messaging/messaging.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 4f1589a9ba..1a2485d700 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -47,6 +47,7 @@ struct messaging_context { struct irpc_list *irpc; struct idr_context *idr; const char **names; + struct timeval start_time; struct { struct event_context *ev; @@ -98,6 +99,17 @@ static void ping_message(struct messaging_context *msg, void *private, messaging_send(msg, src, MSG_PONG, data); } +/* + return uptime of messaging server via irpc +*/ +static NTSTATUS irpc_uptime(struct irpc_message *msg, + struct irpc_uptime *r) +{ + struct messaging_context *ctx = talloc_get_type(msg->private, struct messaging_context); + *r->out.start_time = timeval_to_nttime(&ctx->start_time); + return NT_STATUS_OK; +} + /* return the path to a messaging socket */ @@ -385,14 +397,15 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id mkdir(path, 0700); talloc_free(path); - msg->base_path = smbd_tmp_path(msg, "messaging"); - msg->path = messaging_path(msg, server_id); - msg->server_id = server_id; - msg->dispatch = NULL; - msg->pending = NULL; - msg->idr = idr_init(msg); - msg->irpc = NULL; - msg->names = NULL; + msg->base_path = smbd_tmp_path(msg, "messaging"); + msg->path = messaging_path(msg, server_id); + msg->server_id = server_id; + msg->dispatch = NULL; + msg->pending = NULL; + msg->idr = idr_init(msg); + msg->irpc = NULL; + msg->names = NULL; + msg->start_time = timeval_current(); status = socket_create("unix", SOCKET_TYPE_DGRAM, &msg->sock, 0); if (!NT_STATUS_IS_OK(status)) { @@ -422,6 +435,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id messaging_register(msg, NULL, MSG_PING, ping_message); messaging_register(msg, NULL, MSG_IRPC, irpc_handler); + IRPC_REGISTER(msg, irpc, IRPC_UPTIME, irpc_uptime, msg); return msg; } @@ -571,6 +585,8 @@ static void irpc_handler(struct messaging_context *msg_ctx, void *private, ndr = ndr_pull_init_blob(packet, msg_ctx); if (ndr == NULL) goto failed; + ndr->flags |= LIBNDR_FLAG_REF_ALLOC; + status = ndr_pull_irpc_header(ndr, NDR_BUFFERS|NDR_SCALARS, &header); if (!NT_STATUS_IS_OK(status)) goto failed; -- cgit From cd65f29fc68eb51d0ca7e3c598f875d2c9eafc35 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 11:52:50 +0000 Subject: r8599: null terminate the argv list in string C functions (This used to be commit cabf638a31ab5f9b0e62e085d844d615c597bc2f) --- source4/lib/appweb/ejs/ejsParser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index 452e7fde8f..e7c44f4d6c 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -2003,10 +2003,11 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) case MPR_TYPE_STRING_CFUNCTION: if (actualArgs->used > 0) { - argBuf = mprMalloc(actualArgs->used * sizeof(char*)); + argBuf = mprMalloc((1+actualArgs->used) * sizeof(char*)); for (i = 0; i < actualArgs->used; i++) { mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); } + argBuf[i] = NULL; } else { argBuf = 0; } -- cgit From 3c5675af9340cb66f9d9337d3dc7f82e6ff13e1b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 11:53:25 +0000 Subject: r8600: fixed null termination on some error messages in ldb (This used to be commit 326f0ad6fba8d78f104b93b49995e6c24f9493ef) --- source4/lib/ldb/common/ldb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index aa5b58c252..3a2eb13297 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -88,17 +88,17 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co } #endif else { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'", url); + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'\n", url); return -1; } if (ret != 0) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'", url); + ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url); return ret; } if (ldb_load_modules(ldb, options) != 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'", url); + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url); return -1; } -- cgit From c1a4f0c769479f0a5a262db6f9d82814bf81d1d3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Jul 2005 11:54:00 +0000 Subject: r8601: fixed null termination in ltdb connect error (This used to be commit 64b6586b57de0bf22f8779447d217a918b7024a0) --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index df94b0691d..0c8d2cea3e 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -861,7 +861,7 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, /* note that we use quite a large default hash size */ tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); if (!tdb) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'", path); + ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path); return -1; } -- cgit From f650ea10120d41ceff8ea04975fea7637cb45a0a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 00:09:23 +0000 Subject: r8624: removed valgrind comment on tdb that no longer applies (This used to be commit 8f222c8c7a750c739d3288da0b1edb1efc3b1ffc) --- source4/lib/tdb/common/tdb.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 44533aad27..4c2d9a1add 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -27,25 +27,6 @@ */ -/* NOTE: If you use tdbs under valgrind, and in particular if you run - * tdbtorture, you may get spurious "uninitialized value" warnings. I - * think this is because valgrind doesn't understand that the mmap'd - * area may be written to by other processes. Memory can, from the - * point of view of the grinded process, spontaneously become - * initialized. - * - * I can think of a few solutions. [mbp 20030311] - * - * 1 - Write suppressions for Valgrind so that it doesn't complain - * about this. Probably the most reasonable but people need to - * remember to use them. - * - * 2 - Use IO not mmap when running under valgrind. Not so nice. - * - * 3 - Use the special valgrind macros to mark memory as valid at the - * right time. Probably too hard -- the process just doesn't know. - */ - #ifndef _SAMBA_BUILD_ #if HAVE_CONFIG_H #include -- cgit From 338c3f8523d5db2cba1b79f94ff0cecabcd9e9cd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 00:59:38 +0000 Subject: r8625: move the ldb_wrap logic into the ldb code. This logic is meant to avoid the horrors of posix locking, but it was preventing us having an ldb open twice with different options. Now each ldb open of the same file shares the same underlying tdb, but uses a different ldb structure (This used to be commit 4e090c66dfa1d2764e4693578d3845be3b8893f6) --- source4/lib/db_wrap.c | 37 +---------- source4/lib/ldb/Makefile.in | 2 +- source4/lib/ldb/config.mk | 3 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 30 +++------ source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 ++ source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c | 115 +++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 60 deletions(-) create mode 100644 source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 57055462ff..8698e9affd 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -33,14 +33,6 @@ #include "lib/ldb/include/ldb.h" #include "db_wrap.h" -struct ldb_wrap { - struct ldb_context *ldb; - - const char *url; - struct ldb_wrap *next, *prev; -}; - -static struct ldb_wrap *ldb_list; static struct tdb_wrap *tdb_list; /* @@ -62,14 +54,6 @@ static void ldb_wrap_debug(void *context, enum ldb_debug_level level, free(s); } -/* destroy the last connection to a ldb */ -static int ldb_wrap_destructor(void *ctx) -{ - struct ldb_wrap *w = ctx; - DLIST_REMOVE(ldb_list, w); - return 0; -} - /* wrapped connection to a ldb database to close just talloc_free() the returned ldb_context @@ -80,18 +64,11 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, const char *options[]) { struct ldb_context *ldb; - struct ldb_wrap *w; int ret; struct event_context *ev; char *real_url = NULL; - for (w = ldb_list; w; w = w->next) { - if (strcmp(url, w->url) == 0) { - return talloc_reference(mem_ctx, w->ldb); - } - } - - ldb = ldb_init(talloc_autofree_context()); + ldb = ldb_init(mem_ctx); if (ldb == NULL) { return NULL; } @@ -126,20 +103,8 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, talloc_free(real_url); - w = talloc(ldb, struct ldb_wrap); - if (w == NULL) { - talloc_free(ldb); - return NULL; - } - - w->ldb = ldb; - w->url = talloc_strdup(w, url); - - talloc_set_destructor(w, ldb_wrap_destructor); ldb_set_debug(ldb, ldb_wrap_debug, NULL); - DLIST_ADD(ldb_list, w); - return ldb; } diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 2f82f63714..81e2b147d5 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -46,7 +46,7 @@ TALLOC_OBJ=$(TALLOCDIR)/talloc.o LDB_TDB_OBJ=ldb_tdb/ldb_tdb.o \ ldb_tdb/ldb_pack.o ldb_tdb/ldb_search.o ldb_tdb/ldb_index.o \ - ldb_tdb/ldb_cache.o + ldb_tdb/ldb_cache.o ldb_tdb/ldb_tdb_wrap.o COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 83de5730d4..0844fd056e 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -50,7 +50,8 @@ ADD_OBJ_FILES = \ lib/ldb/ldb_tdb/ldb_search.o \ lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ - lib/ldb/ldb_tdb/ldb_cache.o + lib/ldb/ldb_tdb/ldb_cache.o \ + lib/ldb/ldb_tdb/ldb_tdb_wrap.o REQUIRED_SUBSYSTEMS = \ LIBTDB NOPROTO = YES diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 0c8d2cea3e..40cfe97c29 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -818,16 +818,6 @@ static const struct ldb_module_ops ltdb_ops = { }; -/* - destroy the ltdb context -*/ -static int ltdb_destructor(void *p) -{ - struct ltdb_private *ltdb = p; - tdb_close(ltdb->tdb); - return 0; -} - /* connect to the database */ @@ -837,7 +827,6 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, const char *path; int tdb_flags, open_flags; struct ltdb_private *ltdb; - TDB_CONTEXT *tdb; /* parse the url */ if (strchr(url, ':')) { @@ -858,24 +847,21 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, open_flags = O_CREAT | O_RDWR; } - /* note that we use quite a large default hash size */ - tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666); - if (!tdb) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path); - return -1; - } - ltdb = talloc_zero(ldb, struct ltdb_private); if (!ltdb) { - tdb_close(tdb); ldb_oom(ldb); return -1; } - ltdb->tdb = tdb; - ltdb->sequence_number = 0; + /* note that we use quite a large default hash size */ + ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666); + if (!ltdb->tdb) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path); + talloc_free(ltdb); + return -1; + } - talloc_set_destructor(ltdb, ltdb_destructor); + ltdb->sequence_number = 0; ldb->modules = talloc(ldb, struct ldb_module); if (!ldb->modules) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 46c5843d60..9ee3bfb70f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -105,3 +105,7 @@ int ltdb_unlock_read(struct ldb_module *module); int ltdb_index_del_value(struct ldb_module *module, const char *dn, struct ldb_message_element *el, int v_idx); +struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *path, int hash_size, int tdb_flags, + int open_flags, mode_t mode); + diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c b/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c new file mode 100644 index 0000000000..f58ec7f7ff --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c @@ -0,0 +1,115 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/ldb_tdb/ldb_tdb.h" + +/* + the purpose of this code is to work around the braindead posix locking + rules, to allow us to have a ldb open more than once while allowing + locking to work +*/ + +struct ltdb_wrap { + struct ltdb_wrap *next, *prev; + struct tdb_context *tdb; + dev_t device; + ino_t inode; +}; + +static struct ltdb_wrap *tdb_list; + +/* destroy the last connection to a tdb */ +static int ltdb_wrap_destructor(void *ctx) +{ + struct ltdb_wrap *w = talloc_get_type(ctx, struct ltdb_wrap); + tdb_close(w->tdb); + if (w->next) { + w->next->prev = w->prev; + } + if (w->prev) { + w->prev->next = w->next; + } + if (w == tdb_list) { + tdb_list = w->next; + } + return 0; +} + +/* + wrapped connection to a tdb database. The caller should _not_ free + this as it is not a talloc structure (as tdb does not use talloc + yet). It will auto-close when the caller frees the mem_ctx that is + passed to this call + */ +struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, + const char *path, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + struct ltdb_wrap *w; + struct stat st; + + if (stat(path, &st) == 0) { + for (w=tdb_list;w;w=w->next) { + if (st.st_dev == w->device && st.st_ino == w->inode) { + talloc_reference(mem_ctx, w); + return w->tdb; + } + } + } + + w = talloc(mem_ctx, struct ltdb_wrap); + if (w == NULL) { + return NULL; + } + + w->tdb = tdb_open(path, hash_size, tdb_flags, open_flags, mode); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + if (fstat(w->tdb->fd, &st) != 0) { + tdb_close(w->tdb); + talloc_free(w); + return NULL; + } + + w->device = st.st_dev; + w->inode = st.st_ino; + + talloc_set_destructor(w, ltdb_wrap_destructor); + + w->next = tdb_list; + w->prev = NULL; + if (tdb_list) { + tdb_list->prev = w; + } + tdb_list = w; + + return w->tdb; +} + -- cgit From 6f48b3a5cbe0235e60834f0b96a34290797d3bf4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 05:13:01 +0000 Subject: r8630: give a much nicer backtrace on assert() failures in ejs I will submit this upstream (This used to be commit a2266f6927d953459bd4b02fbca0a9c95c18494e) --- source4/lib/appweb/ejs/ejsInternal.h | 2 ++ source4/lib/appweb/ejs/ejsLex.c | 7 +++++-- source4/lib/appweb/ejs/ejsLib.c | 36 ++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsInternal.h b/source4/lib/appweb/ejs/ejsInternal.h index 3bf99d88b9..8b66dafdca 100644 --- a/source4/lib/appweb/ejs/ejsInternal.h +++ b/source4/lib/appweb/ejs/ejsInternal.h @@ -192,6 +192,8 @@ typedef struct ejEval { char *tokEndp; /* Pointer past end of token */ char *tokServp; /* Pointer to next token char */ int tokSize; /* Size of token buffer */ + struct ejEval *next; /* used for backtraces */ + const char *procName; /* gives name in backtrace */ } EjsInput; /* diff --git a/source4/lib/appweb/ejs/ejsLex.c b/source4/lib/appweb/ejs/ejsLex.c index a5f15c2979..b4617a638e 100644 --- a/source4/lib/appweb/ejs/ejsLex.c +++ b/source4/lib/appweb/ejs/ejsLex.c @@ -60,11 +60,13 @@ int ejsLexOpenScript(Ejs *ep, char *script) mprAssert(ep); mprAssert(script); - if ((ep->input = mprMalloc(sizeof(EjsInput))) == NULL) { + if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) { return -1; } - ip = ep->input; memset(ip, 0, sizeof(*ip)); + ip->next = ep->input; + ep->input = ip; + ip->procName = ep->proc?ep->proc->procName:NULL; /* * Create the parse token buffer and script buffer @@ -102,6 +104,7 @@ void ejsLexCloseScript(Ejs *ep) ip = ep->input; mprAssert(ip); + ep->input = ip->next; for (i = 0; i < EJS_TOKEN_STACK; i++) { mprFree(ip->putBack[i].token); diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c index b3e61ec375..eed6d67fb4 100644 --- a/source4/lib/appweb/ejs/ejsLib.c +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -385,7 +385,6 @@ int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) { Ejs *ep; - EjsInput *oldBlock; int state; void *endlessLoopTest; int loopCounter; @@ -408,7 +407,6 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) /* * Allocate a new evaluation block, and save the old one */ - oldBlock = ep->input; ejsLexOpenScript(ep, script); /* @@ -447,11 +445,6 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) *emsg = mprStrdup(ep->error); } - /* - * Restore the old evaluation block - */ - ep->input = oldBlock; - if (state == EJS_STATE_ERR) { return -1; } @@ -475,24 +468,31 @@ static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) { EjsInput *ip; char *errbuf, *msgbuf; + int frame = 0; mprAssert(ep); msgbuf = NULL; mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); - if (ep) { - ip = ep->input; - if (ip) { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, - "%s\nError on line %d. Offending line: %s\n\n", - msgbuf, ip->lineNumber, ip->line); - } else { - mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf); - } - mprFree(ep->error); - ep->error = errbuf; + ip = ep->input; + mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\nBacktrace:\n", msgbuf); + + /* form a backtrace */ + while (ip) { + char *msg2, *ebuf2; + mprAllocSprintf(&msg2, MPR_MAX_STRING, + "\t[%2d] %20s:%-4d -> %s\n", + frame++, ip->procName?ip->procName:"", ip->lineNumber, ip->line); + ebuf2 = mprRealloc(errbuf, strlen(errbuf) + strlen(msg2) + 1); + if (ebuf2 == NULL) break; + errbuf = ebuf2; + memcpy(errbuf+strlen(errbuf), msg2, strlen(msg2)+1); + mprFree(msg2); + ip = ip->next; } + mprFree(ep->error); + ep->error = errbuf; mprFree(msgbuf); } -- cgit From 3473f6b74b4545d09234d198468b0229c621b1cb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 05:40:24 +0000 Subject: r8631: give an error on incorrect argument count (This used to be commit ed09e19794d9625553bc48892a2e08b84d7bdcf4) --- source4/lib/appweb/ejs/ejsParser.c | 7 +++---- source4/lib/appweb/esp/esp.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index e7c44f4d6c..1f110e7ac4 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -2059,12 +2059,11 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags) formalArgs = prototype->function.args; argNames = (char**) formalArgs->handles; -#if FUTURE - if (formalArgs->used != actualArgs->used) { - ejsError(ep, "Bad number of args. Should be %d", formalArgs->used); + if (formalArgs->used > actualArgs->used) { + ejsError(ep, "Bad number of args. Should be %d", + formalArgs->used); return -1; } -#endif /* * Create the arguments and callee variables diff --git a/source4/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h index 39dc5310c2..3d9b7bf8dc 100644 --- a/source4/lib/appweb/esp/esp.h +++ b/source4/lib/appweb/esp/esp.h @@ -103,7 +103,7 @@ typedef struct Esp { int lifetime, const char *path, bool secure); void (*setHeader)(EspHandle handle, const char *value, bool allowMultiple); void (*setResponseCode)(EspHandle handle, int code); - int (*writeBlock)(EspHandle handle, char *buf, int size); + int (*writeBlock)(EspHandle handle, const char *buf, int size); int (*writeFmt)(EspHandle handle, char *fmt, ...); #if BLD_FEATURE_MULTITHREAD void (*lock)(void *lockData); -- cgit From 2f5f01567b4c30cd764843a1ca0c7ab6d9bc0882 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 10:07:48 +0000 Subject: r8643: - make lp_configfile() work again - get rid of redundeny dyn_CONFIGFILE argument to lp_load() - fixed provisioning to work with completely pristine install, creating an initial smb.conf is none is present - added lp.set() and lp.reload() to loadparm ejs object interface (This used to be commit c2691ef7126ddcee5f95970b78759b40a049d0a7) --- source4/lib/cmdline/popt_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index b7b7bdc286..e39c8e964d 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -52,7 +52,7 @@ static void popt_common_callback(poptContext con, if (reason == POPT_CALLBACK_REASON_POST) { /* Hook any 'every Samba program must do this, after * the smb.conf is setup' functions here */ - lp_load(dyn_CONFIGFILE); + lp_load(); load_interfaces(); return; } @@ -92,7 +92,7 @@ static void popt_common_callback(poptContext con, case 's': if (arg) { - pstrcpy(dyn_CONFIGFILE, arg); + lp_set_cmdline("config file", arg); } break; -- cgit From 24d2107324982d8ad69fb89d13037ba591f49534 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 20 Jul 2005 11:43:23 +0000 Subject: r8650: Use the timestamps and a new objectguid module rather than placing boilerplate attributes in every entry in provision.ldif. The next step will be to use templates. Andrew Bartlett (This used to be commit 940ed9827f5ab83b668a60a2b0110567dd54c3e2) --- source4/lib/ldb/common/ldb_modules.c | 10 ++ source4/lib/ldb/config.mk | 9 ++ source4/lib/ldb/modules/objectguid.c | 220 +++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 source4/lib/ldb/modules/objectguid.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index d4f35c0e56..dc1a90ebc2 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -189,6 +189,16 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } + if (strcmp(modules[i], "objectguid") == 0) { + current = objectguid_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } + #ifdef _SAMBA_BUILD_ if (strcmp(modules[i], "samldb") == 0) { current = samldb_module_init(ldb, options); diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 0844fd056e..39bf004e5d 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -7,6 +7,15 @@ INIT_OBJ_FILES = \ # End MODULE libldb_timestamps ################################################ +################################################ +# Start MODULE libldb_objectguid +[MODULE::libldb_objectguid] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/modules/objectguid.o +# End MODULE libldb_objectguid +################################################ + ################################################ # Start MODULE libldb_schema [MODULE::libldb_schema] diff --git a/source4/lib/ldb/modules/objectguid.c b/source4/lib/ldb/modules/objectguid.c new file mode 100644 index 0000000000..0e789c2bda --- /dev/null +++ b/source4/lib/ldb/modules/objectguid.c @@ -0,0 +1,220 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb objectguid module + * + * Description: add a unique objectGUID onto every new record + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +struct private_data { + const char *error_string; +}; + +static int objectguid_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int objectguid_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + +static struct ldb_message_element *objectguid_find_attribute(const struct ldb_message *msg, const char *name) +{ + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { + return &msg->elements[i]; + } + } + + return NULL; +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int objectguid_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct GUID guid; + char *guidstr; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_add_record\n"); + + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } + + if ((attribute = objectguid_find_attribute(msg, "objectGUID")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + /* a new GUID */ + guid = GUID_random(); + guidstr = GUID_string(msg2, &guid); + if (!guidstr) { + return -1; + } + + if (ldb_msg_add_string(module->ldb, msg2, "objectGUID", guidstr) != 0) { + return -1; + } + + ret = ldb_next_add_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int objectguid_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_modify_record\n"); + return ldb_next_modify_record(module, msg); +} + +static int objectguid_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int objectguid_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +static int objectguid_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int objectguid_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + +/* return extended error information */ +static const char *objectguid_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_errstring\n"); + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static int objectguid_destructor(void *module_ctx) +{ + /* struct ldb_module *ctx = module_ctx; */ + /* put your clean-up functions here */ + return 0; +} + +static const struct ldb_module_ops objectguid_ops = { + .name = "objectguid", + .search = objectguid_search, + .search_bytree = objectguid_search_bytree, + .add_record = objectguid_add_record, + .modify_record = objectguid_modify_record, + .delete_record = objectguid_delete_record, + .rename_record = objectguid_rename_record, + .named_lock = objectguid_lock, + .named_unlock = objectguid_unlock, + .errstring = objectguid_errstring +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *objectguid_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &objectguid_ops; + + talloc_set_destructor (ctx, objectguid_destructor); + + return ctx; +} -- cgit From 5e9988708f30ce093ab0f48ebb02787c9e418331 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jul 2005 11:55:20 +0000 Subject: r8651: fixed a boolean expression bug (submitted upstream) (This used to be commit bd4c388cd2653823e012f1cd8c14832ee032eb11) --- source4/lib/appweb/ejs/ejsParser.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index 1f110e7ac4..dadd3eac11 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -1641,6 +1641,9 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) case EJS_EXPR_NOTEQ: lval = lhs->type != rhs->type; break; + case EJS_EXPR_BOOL_COMP: + lval = ! mprVarToBool(rhs); + break; default: lval = 0; } -- cgit From 7a8ac7588720ebd1ea61a539ca4040d322c4fcf2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 01:56:22 +0000 Subject: r8659: return ldif formatted attributes in the ejs ldb search call, so sids show up as strings not binary blobs (This used to be commit d2c29a5a51f68cabb9ef587376bf0a6b936cdd76) --- source4/lib/ldb/include/ldb.h | 3 +++ source4/lib/ldb/include/ldb_private.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 6670089902..7399b8ffe7 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -440,4 +440,7 @@ int ldb_set_debug_stderr(struct ldb_context *ldb); int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value); void *ldb_get_opaque(struct ldb_context *ldb, const char *name); +const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, + const char *attrib); + #endif diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index da813eb588..0abf056db4 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -172,9 +172,6 @@ int lsqlite3_connect(struct ldb_context *ldb, struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); -const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, - const char *attrib); - int ldb_match_msg(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, -- cgit From 2a0cf520e3255d8e1bdec1bedd710489619de614 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Jul 2005 07:59:01 +0000 Subject: r8667: Further simply the provision script, by removing the 'name' attribute. This is now calculated on the fly for every add and modify. Andrew Bartlett (This used to be commit ed1f2e029c840d2b3ecb49dbe6e8cd67588eeeed) --- source4/lib/ldb/common/ldb_modules.c | 10 ++ source4/lib/ldb/config.mk | 9 ++ source4/lib/ldb/modules/rdn_name.c | 276 +++++++++++++++++++++++++++++++++++ source4/lib/ldb/modules/timestamps.c | 37 ++--- 4 files changed, 311 insertions(+), 21 deletions(-) create mode 100644 source4/lib/ldb/modules/rdn_name.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index dc1a90ebc2..d6213be79a 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -199,6 +199,16 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } + if (strcmp(modules[i], "rdn_name") == 0) { + current = rdn_name_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } + #ifdef _SAMBA_BUILD_ if (strcmp(modules[i], "samldb") == 0) { current = samldb_module_init(ldb, options); diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 39bf004e5d..fe339f9e17 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -16,6 +16,15 @@ INIT_OBJ_FILES = \ # End MODULE libldb_objectguid ################################################ +################################################ +# Start MODULE libldb_rdn_name +[MODULE::libldb_rdn_name] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/modules/rdn_name.o +# End MODULE libldb_rdn_name +################################################ + ################################################ # Start MODULE libldb_schema [MODULE::libldb_schema] diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c new file mode 100644 index 0000000000..6a11ab87fe --- /dev/null +++ b/source4/lib/ldb/modules/rdn_name.c @@ -0,0 +1,276 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb objectguid module + * + * Description: add a unique objectGUID onto every new record + * + * Author: Simo Sorce + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +struct private_data { + const char *error_string; +}; + +static int rdn_name_search(struct ldb_module *module, const char *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); + return ldb_next_search(module, base, scope, expression, attrs, res); +} + +static int rdn_name_search_bytree(struct ldb_module *module, const char *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); + return ldb_next_search_bytree(module, base, scope, tree, attrs, res); +} + +static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name) +{ + int i; + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { + return &msg->elements[i]; + } + } + + return NULL; +} + +static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) +{ + struct ldb_dn *dn_exploded = ldb_dn_explode(mem_ctx, dn); + + if (!dn_exploded) { + return NULL; + } + + if (dn_exploded->comp_num < 1) { + return NULL; + } + + return &dn_exploded->components[0]; +} + +/* add_record: add crateTimestamp/modifyTimestamp attributes */ +static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct ldb_dn_component *rdn; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); + + if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + return ldb_next_add_record(module, msg); + } + + /* Perhaps someone above us knows better */ + if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + rdn = get_rdn(msg2, msg2->dn); + if (!rdn) { + return -1; + } + + if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + return -1; + } + + ret = ldb_next_add_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +/* modify_record: change modifyTimestamp as well */ +static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *msg2; + struct ldb_message_element *attribute; + struct ldb_dn_component *rdn; + int ret, i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n"); + + /* Perhaps someone above us knows better */ + if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { + return ldb_next_add_record(module, msg); + } + + msg2 = talloc(module, struct ldb_message); + if (!msg2) { + return -1; + } + + msg2->dn = msg->dn; + msg2->num_elements = msg->num_elements; + msg2->private_data = msg->private_data; + msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); + for (i = 0; i < msg2->num_elements; i++) { + msg2->elements[i] = msg->elements[i]; + } + + rdn = get_rdn(msg2, msg2->dn); + if (!rdn) { + return -1; + } + + if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + return -1; + } + + attribute = rdn_name_find_attribute(msg2, "name"); + if (!attribute) { + return -1; + } + + attribute->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_next_modify_record(module, msg2); + talloc_free(msg2); + + return ret; +} + +static int rdn_name_delete_record(struct ldb_module *module, const char *dn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); + return ldb_next_delete_record(module, dn); +} + +static int rdn_name_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); + return ldb_next_rename_record(module, olddn, newdn); +} + +static int rdn_name_lock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_lock\n"); + return ldb_next_named_lock(module, lockname); +} + +static int rdn_name_unlock(struct ldb_module *module, const char *lockname) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_unlock\n"); + return ldb_next_named_unlock(module, lockname); +} + +/* return extended error information */ +static const char *rdn_name_errstring(struct ldb_module *module) +{ + struct private_data *data = (struct private_data *)module->private_data; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_errstring\n"); + if (data->error_string) { + const char *error; + + error = data->error_string; + data->error_string = NULL; + return error; + } + + return ldb_next_errstring(module); +} + +static int rdn_name_destructor(void *module_ctx) +{ + /* struct ldb_module *ctx = module_ctx; */ + /* put your clean-up functions here */ + return 0; +} + +static const struct ldb_module_ops rdn_name_ops = { + .name = "rdn_name", + .search = rdn_name_search, + .search_bytree = rdn_name_search_bytree, + .add_record = rdn_name_add_record, + .modify_record = rdn_name_modify_record, + .delete_record = rdn_name_delete_record, + .rename_record = rdn_name_rename_record, + .named_lock = rdn_name_lock, + .named_unlock = rdn_name_unlock, + .errstring = rdn_name_errstring +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + struct private_data *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct private_data); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->error_string = NULL; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &rdn_name_ops; + + talloc_set_destructor (ctx, rdn_name_destructor); + + return ctx; +} diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index c1db85a284..b067d8e8d6 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -60,8 +60,8 @@ static int timestamps_search_bytree(struct ldb_module *module, const char *base, static int add_time_element(struct ldb_module *module, struct ldb_message *msg, const char *attr_name, const char *time_string, unsigned int flags) { - struct ldb_val *values; - char *name, *timestr; + struct ldb_message_element *attribute = NULL; + int i; for (i = 0; i < msg->num_elements; i++) { @@ -70,23 +70,22 @@ static int add_time_element(struct ldb_module *module, struct ldb_message *msg, } } - msg->elements = talloc_realloc(msg, msg->elements, - struct ldb_message_element, msg->num_elements + 1); - name = talloc_strdup(msg->elements, attr_name); - timestr = talloc_strdup(msg->elements, time_string); - values = talloc(msg->elements, struct ldb_val); - if (!msg->elements || !name || !timestr || !values) { + if (ldb_msg_add_string(module->ldb, msg, attr_name, time_string) != 0) { return -1; } - msg->elements[msg->num_elements].name = name; - msg->elements[msg->num_elements].flags = flags; - msg->elements[msg->num_elements].num_values = 1; - msg->elements[msg->num_elements].values = values; - msg->elements[msg->num_elements].values[0].data = timestr; - msg->elements[msg->num_elements].values[0].length = strlen(timestr); + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(attr_name, msg->elements[i].name) == 0) { + attribute = &msg->elements[i]; + break; + } + } - msg->num_elements += 1; + if (!attribute) { + return -1; + } + + attribute->flags = flags; return 0; } @@ -196,12 +195,8 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ add_time_element(module, msg2, "modifyTimestamp", timestr, LDB_FLAG_MOD_REPLACE); add_time_element(module, msg2, "whenChanged", timestr, LDB_FLAG_MOD_REPLACE); - if (msg2) { - ret = ldb_next_modify_record(module, msg2); - talloc_free(msg2); - } else { - ret = ldb_next_modify_record(module, msg); - } + ret = ldb_next_modify_record(module, msg2); + talloc_free(msg2); return ret; } -- cgit From eb08c1fc8f877bffeaf63acfbc97ae00a4370a15 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 08:06:39 +0000 Subject: r8668: fixed a segv during upgrade of a very old ldb. Thanks to volker for finding this one too. Keep them coming! (This used to be commit 756796ad2ea86a9471d1b09e66b1a74c4523f6f4) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 1cfebe6864..2fb6c34227 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -1001,6 +1001,11 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * /* check if the DN key has changed, perhaps due to the case insensitivity of an element changing */ key2 = ltdb_key(module, msg->dn); + if (key2.dptr == NULL) { + /* probably a corrupt record ... darn */ + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n", msg->dn); + return 0; + } if (strcmp(key2.dptr, key.dptr) != 0) { tdb_delete(tdb, key); tdb_store(tdb, key2, data, 0); -- cgit From 4396d0d1482d4033a469f7a3e3835a6f3b145046 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 21 Jul 2005 08:32:07 +0000 Subject: r8669: The objectguid module belongs in Samba's ldb module collection, not in ldb, as it can't build without the NDR and GUID code. Also make it properly use the NDR encoding for the GUID (I forgot last time, and used a string), as well as set the dependencies on the module correctly. Andrew Bartlett (This used to be commit 8054abc76e5e3588cebc7fc01062a1223b7f140b) --- source4/lib/ldb/common/ldb_modules.c | 10 +- source4/lib/ldb/config.mk | 9 -- source4/lib/ldb/modules/objectguid.c | 220 ----------------------------------- 3 files changed, 5 insertions(+), 234 deletions(-) delete mode 100644 source4/lib/ldb/modules/objectguid.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index d6213be79a..dcc384ffad 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -189,8 +189,8 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } - if (strcmp(modules[i], "objectguid") == 0) { - current = objectguid_module_init(ldb, options); + if (strcmp(modules[i], "rdn_name") == 0) { + current = rdn_name_module_init(ldb, options); if (!current) { ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); return -1; @@ -199,8 +199,9 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } - if (strcmp(modules[i], "rdn_name") == 0) { - current = rdn_name_module_init(ldb, options); +#ifdef _SAMBA_BUILD_ + if (strcmp(modules[i], "objectguid") == 0) { + current = objectguid_module_init(ldb, options); if (!current) { ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); return -1; @@ -209,7 +210,6 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) continue; } -#ifdef _SAMBA_BUILD_ if (strcmp(modules[i], "samldb") == 0) { current = samldb_module_init(ldb, options); if (!current) { diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index fe339f9e17..87e15f1375 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -7,15 +7,6 @@ INIT_OBJ_FILES = \ # End MODULE libldb_timestamps ################################################ -################################################ -# Start MODULE libldb_objectguid -[MODULE::libldb_objectguid] -SUBSYSTEM = LIBLDB -INIT_OBJ_FILES = \ - lib/ldb/modules/objectguid.o -# End MODULE libldb_objectguid -################################################ - ################################################ # Start MODULE libldb_rdn_name [MODULE::libldb_rdn_name] diff --git a/source4/lib/ldb/modules/objectguid.c b/source4/lib/ldb/modules/objectguid.c deleted file mode 100644 index 0e789c2bda..0000000000 --- a/source4/lib/ldb/modules/objectguid.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2004 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Name: ldb - * - * Component: ldb objectguid module - * - * Description: add a unique objectGUID onto every new record - * - * Author: Simo Sorce - */ - -#include "includes.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" -#include - -struct private_data { - const char *error_string; -}; - -static int objectguid_search(struct ldb_module *module, const char *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - -static int objectguid_search_bytree(struct ldb_module *module, const char *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_search\n"); - return ldb_next_search_bytree(module, base, scope, tree, attrs, res); -} - -static struct ldb_message_element *objectguid_find_attribute(const struct ldb_message *msg, const char *name) -{ - int i; - - for (i = 0; i < msg->num_elements; i++) { - if (ldb_attr_cmp(name, msg->elements[i].name) == 0) { - return &msg->elements[i]; - } - } - - return NULL; -} - -/* add_record: add crateTimestamp/modifyTimestamp attributes */ -static int objectguid_add_record(struct ldb_module *module, const struct ldb_message *msg) -{ - struct ldb_message *msg2; - struct ldb_message_element *attribute; - struct GUID guid; - char *guidstr; - int ret, i; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_add_record\n"); - - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ - return ldb_next_add_record(module, msg); - } - - if ((attribute = objectguid_find_attribute(msg, "objectGUID")) != NULL ) { - return ldb_next_add_record(module, msg); - } - - msg2 = talloc(module, struct ldb_message); - if (!msg2) { - return -1; - } - - msg2->dn = msg->dn; - msg2->num_elements = msg->num_elements; - msg2->private_data = msg->private_data; - msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements); - for (i = 0; i < msg2->num_elements; i++) { - msg2->elements[i] = msg->elements[i]; - } - - /* a new GUID */ - guid = GUID_random(); - guidstr = GUID_string(msg2, &guid); - if (!guidstr) { - return -1; - } - - if (ldb_msg_add_string(module->ldb, msg2, "objectGUID", guidstr) != 0) { - return -1; - } - - ret = ldb_next_add_record(module, msg2); - talloc_free(msg2); - - return ret; -} - -/* modify_record: change modifyTimestamp as well */ -static int objectguid_modify_record(struct ldb_module *module, const struct ldb_message *msg) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_modify_record\n"); - return ldb_next_modify_record(module, msg); -} - -static int objectguid_delete_record(struct ldb_module *module, const char *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - -static int objectguid_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_rename_record\n"); - return ldb_next_rename_record(module, olddn, newdn); -} - -static int objectguid_lock(struct ldb_module *module, const char *lockname) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_lock\n"); - return ldb_next_named_lock(module, lockname); -} - -static int objectguid_unlock(struct ldb_module *module, const char *lockname) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_unlock\n"); - return ldb_next_named_unlock(module, lockname); -} - -/* return extended error information */ -static const char *objectguid_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectguid_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - -static int objectguid_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - -static const struct ldb_module_ops objectguid_ops = { - .name = "objectguid", - .search = objectguid_search, - .search_bytree = objectguid_search_bytree, - .add_record = objectguid_add_record, - .modify_record = objectguid_modify_record, - .delete_record = objectguid_delete_record, - .rename_record = objectguid_rename_record, - .named_lock = objectguid_lock, - .named_unlock = objectguid_unlock, - .errstring = objectguid_errstring -}; - - -/* the init function */ -#ifdef HAVE_DLOPEN_DISABLED - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) -#else -struct ldb_module *objectguid_module_init(struct ldb_context *ldb, const char *options[]) -#endif -{ - struct ldb_module *ctx; - struct private_data *data; - - ctx = talloc(ldb, struct ldb_module); - if (!ctx) - return NULL; - - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; - ctx->ldb = ldb; - ctx->prev = ctx->next = NULL; - ctx->ops = &objectguid_ops; - - talloc_set_destructor (ctx, objectguid_destructor); - - return ctx; -} -- cgit From a78558321a994dd02713c04ed3626b6d20d57cc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 08:42:17 +0000 Subject: r8671: use much shorter names for the selftest directory and socket wrapper code. I'm afraid this is needed by irix 6.4 which silently truncates names in unix domain sockets in recvfrom() to 16 chars. My apologies for having to move to such short names :-( (This used to be commit f9693e313da67e1347a607db5d3ebbf36e02a77a) --- source4/lib/socket_wrapper/socket_wrapper.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index 940883a45f..d0d08d22b9 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -57,6 +57,14 @@ #define real_close close #endif +/* we need to use a very terse format here as IRIX 6.4 silently + truncates names to 16 chars, so if we use a longer name then we + can't tell which port a packet came from with recvfrom() + + with this format we have 8 chars left for the directory name +*/ +#define SOCKET_FORMAT "%u_%u" + static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) { struct sockaddr *ret = (struct sockaddr *)malloc(len); @@ -102,7 +110,7 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s p = strrchr(un->sun_path, '/'); if (p) p++; else p = un->sun_path; - if (sscanf(p, "sock_ip_%d_%u", &type, &prt) == 2) { + if (sscanf(p, SOCKET_FORMAT, &type, &prt) == 2) { in->sin_port = htons(prt); } in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -119,12 +127,12 @@ static int convert_in_un(struct socket_info *si, const struct sockaddr_in *in, s /* handle auto-allocation of ephemeral ports */ prt = 5000; do { - snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", + snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, getenv("SOCKET_WRAPPER_DIR"), type, ++prt); } while (stat(un->sun_path, &st) == 0 && prt < 10000); ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); } - snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", + snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, getenv("SOCKET_WRAPPER_DIR"), type, prt); return 0; } @@ -230,6 +238,8 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) return real_accept(s, addr, addrlen); } + memset(&un_addr, 0, sizeof(un_addr)); + ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); if (ret == -1) return ret; @@ -270,7 +280,7 @@ static int swrap_auto_bind(struct socket_info *si) for (i=0;i<1000;i++) { snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), - "%s/sock_ip_%u_%u", getenv("SOCKET_WRAPPER_DIR"), + "%s/"SOCKET_FORMAT, getenv("SOCKET_WRAPPER_DIR"), SOCK_DGRAM, i + 10000); if (bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)) == 0) { @@ -458,6 +468,8 @@ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr return real_recvfrom(s, buf, len, flags, from, fromlen); } + /* irix 6.4 forgets to null terminate the sun_path string :-( */ + memset(&un_addr, 0, sizeof(un_addr)); ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); if (ret == -1) return ret; -- cgit From a369f0ecaf35fb49652873c4c1ddcaf28629c26e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 12:11:52 +0000 Subject: r8678: setup for gdb backtrace in 'make test' (This used to be commit acf8c8fd4995acef47390df5a7d4e611c597367d) --- source4/lib/cmdline/popt_common.c | 3 +++ source4/lib/fault.c | 35 +++++++++++++++-------------------- 2 files changed, 18 insertions(+), 20 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index e39c8e964d..53bb7b5a8c 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -48,6 +48,9 @@ static void popt_common_callback(poptContext con, const char *arg, const void *data) { const char *pname; + + /* setup for panics */ + fault_setup(poptGetInvocationName(con)); if (reason == POPT_CALLBACK_REASON_POST) { /* Hook any 'every Samba program must do this, after diff --git a/source4/lib/fault.c b/source4/lib/fault.c index f3a9e78f39..22efb4825d 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -23,14 +23,13 @@ #include "system/wait.h" #include "system/filesys.h" -static void (*cont_fn)(void *); - /* the registered fault handler */ static struct { const char *name; void (*fault_handler)(int sig); } fault_handlers; +static const char *progname; #ifdef HAVE_BACKTRACE #include @@ -111,8 +110,16 @@ void smb_panic(const char *why) int result; if (cmd && *cmd) { - DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd)); - result = system(cmd); + char pidstr[20]; + char cmdstring[200]; + safe_strcpy(cmdstring, cmd, sizeof(cmdstring)); + snprintf(pidstr, sizeof(pidstr), "%u", getpid()); + all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring)); + if (progname) { + all_string_sub(cmdstring, "%PROG%", progname, sizeof(cmdstring)); + } + DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring)); + result = system(cmdstring); if (result == -1) DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", @@ -147,19 +154,6 @@ static void fault_report(int sig) smb_panic("internal error"); - if (cont_fn) { - cont_fn(NULL); -#ifdef SIGSEGV - CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL); -#endif -#ifdef SIGBUS - CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); -#endif -#ifdef SIGABRT - CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); -#endif - return; /* this should cause a core dump */ - } exit(1); } @@ -179,10 +173,11 @@ static void sig_fault(int sig) /******************************************************************* setup our fault handlers ********************************************************************/ -void fault_setup(void (*fn)(void *)) +void fault_setup(const char *pname) { - cont_fn = fn; - + if (progname == NULL) { + progname = pname; + } #ifdef SIGSEGV CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); #endif -- cgit From 87e2396be99a1560d3f083e77e5fc6c583d3b9c1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 12:20:18 +0000 Subject: r8679: only call fault setup once (thanks to andrew for pointing this out) (This used to be commit f8a2b032a70dd63f4454b982d00168dcf6793202) --- source4/lib/cmdline/popt_common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 53bb7b5a8c..4e808652f7 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -49,9 +49,6 @@ static void popt_common_callback(poptContext con, { const char *pname; - /* setup for panics */ - fault_setup(poptGetInvocationName(con)); - if (reason == POPT_CALLBACK_REASON_POST) { /* Hook any 'every Samba program must do this, after * the smb.conf is setup' functions here */ @@ -69,6 +66,10 @@ static void popt_common_callback(poptContext con, pname++; if (reason == POPT_CALLBACK_REASON_PRE) { + /* setup for panics */ + fault_setup(poptGetInvocationName(con)); + + /* and logging */ setup_logging(pname, DEBUG_STDOUT); return; } -- cgit From 5086945689f10db74fbb2a4340c7e22469f9e8d8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 13:45:07 +0000 Subject: r8681: if SOCKET_WRAPPER_DIR starts with ./ then strip it internally. This saves us 2 more chars in the name, which is enough to get IRIX 6.4 working (This used to be commit e6d9cde482ad9f3fa91d9ce3638e2ec6530b3a9c) --- source4/lib/socket_wrapper/socket_wrapper.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket_wrapper/socket_wrapper.c b/source4/lib/socket_wrapper/socket_wrapper.c index d0d08d22b9..1c3d5c3bfc 100644 --- a/source4/lib/socket_wrapper/socket_wrapper.c +++ b/source4/lib/socket_wrapper/socket_wrapper.c @@ -95,6 +95,19 @@ struct socket_info static struct socket_info *sockets = NULL; + +static const char *socket_wrapper_dir(void) +{ + const char *s = getenv("SOCKET_WRAPPER_DIR"); + if (s == NULL) { + return NULL; + } + if (strncmp(s, "./", 2) == 0) { + s += 2; + } + return s; +} + static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len) { unsigned int prt; @@ -128,12 +141,12 @@ static int convert_in_un(struct socket_info *si, const struct sockaddr_in *in, s prt = 5000; do { snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, - getenv("SOCKET_WRAPPER_DIR"), type, ++prt); + socket_wrapper_dir(), type, ++prt); } while (stat(un->sun_path, &st) == 0 && prt < 10000); ((struct sockaddr_in *)si->myname)->sin_port = htons(prt); } snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, - getenv("SOCKET_WRAPPER_DIR"), type, prt); + socket_wrapper_dir(), type, prt); return 0; } @@ -205,7 +218,7 @@ int swrap_socket(int domain, int type, int protocol) struct socket_info *si; int fd; - if (!getenv("SOCKET_WRAPPER_DIR")) { + if (!socket_wrapper_dir()) { return real_socket(domain, type, protocol); } @@ -280,7 +293,7 @@ static int swrap_auto_bind(struct socket_info *si) for (i=0;i<1000;i++) { snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), - "%s/"SOCKET_FORMAT, getenv("SOCKET_WRAPPER_DIR"), + "%s/"SOCKET_FORMAT, socket_wrapper_dir(), SOCK_DGRAM, i + 10000); if (bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)) == 0) { -- cgit From 04598d3832ef26c40c6b320e5e806f4e92947572 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 14:00:51 +0000 Subject: r8684: this should fix the panic on x86_64, and possibly alpha (This used to be commit c2f5884e2f8a033446467384b6c058567b2fb9ce) --- source4/lib/appweb/mpr/miniMpr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/miniMpr.c b/source4/lib/appweb/mpr/miniMpr.c index abeefe1ec8..615b46bf09 100644 --- a/source4/lib/appweb/mpr/miniMpr.c +++ b/source4/lib/appweb/mpr/miniMpr.c @@ -330,7 +330,9 @@ static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, dest = *destp; sepLen = (delim) ? strlen(delim) : 0; -#ifdef __va_copy +#ifdef HAVE_VA_COPY + va_copy(ap, args); +#elif HAVE___VA_COPY __va_copy(ap, args); #else ap = args; @@ -368,7 +370,9 @@ static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, } if (addBytes > 0) { -#ifdef __va_copy +#ifdef HAVE_VA_COPY + va_copy(ap, args); +#elif HAVE___VA_COPY __va_copy(ap, args); #else ap = args; -- cgit From 2a65d17e06da3b1f1f78d9586fd82a79ba2f73a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 Jul 2005 14:04:13 +0000 Subject: r8685: an alpha in the build farm is dying with a floating point exception. Catch these in out fault handler, so we get a backtrace (This used to be commit 802724cf69e65a07202f3399a4321a35c2f3c018) --- source4/lib/fault.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/fault.c b/source4/lib/fault.c index 22efb4825d..3670575dcc 100644 --- a/source4/lib/fault.c +++ b/source4/lib/fault.c @@ -187,6 +187,9 @@ void fault_setup(const char *pname) #ifdef SIGABRT CatchSignal(SIGABRT,SIGNAL_CAST sig_fault); #endif +#ifdef SIGFPE + CatchSignal(SIGFPE,SIGNAL_CAST sig_fault); +#endif } /* -- cgit From d55b75d8336326a2f8aaad2144e53d8b821a3b21 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jul 2005 01:56:51 +0000 Subject: r8696: fixed ejs to more strictly follow the va_list rules. Might fix that pesky panic on x86_64 (This used to be commit 80177b29f4b32996d41a87df041c4c1bfb6876c2) --- source4/lib/appweb/ejs/ejsParser.c | 6 +++--- source4/lib/appweb/mpr/miniMpr.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index dadd3eac11..5b8b84f7b3 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -230,7 +230,7 @@ static int parseStmt(Ejs *ep, int state, int flags) #if BLD_DEBUG fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, - 0, ".", 0); + 0, ".", NULL); #endif ep->currentProperty = vp; @@ -266,7 +266,7 @@ static int parseStmt(Ejs *ep, int state, int flags) * If not executing yet, id may not be known */ fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, - fullNameLen, 0, "[", id, "]", 0); + fullNameLen, 0, "[", id, "]", NULL); } #endif @@ -1258,7 +1258,7 @@ static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, *id = mprStrdup(ep->token); #if BLD_DEBUG *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, - 0, *id, 0); + 0, *id, NULL); #endif if (ep->currentObj == 0) { ep->currentObj = ejsFindObj(ep, state, *id, flags); diff --git a/source4/lib/appweb/mpr/miniMpr.c b/source4/lib/appweb/mpr/miniMpr.c index 615b46bf09..f4c219fe4c 100644 --- a/source4/lib/appweb/mpr/miniMpr.c +++ b/source4/lib/appweb/mpr/miniMpr.c @@ -343,6 +343,7 @@ static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, addBytes += strlen(str) + sepLen; str = va_arg(ap, const char*); } + va_end(ap); if (existingLen > 0) { addBytes += sepLen; @@ -387,6 +388,7 @@ static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, dp += sepLen; } } + va_end(ap); } else if (dest == 0) { dest = (char*) mprMalloc(1); } -- cgit From fe6eeeb60177c0b55366bcfb69be3acf8a95fb3b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jul 2005 03:46:57 +0000 Subject: r8698: attempt to cope with lack of strtoull() on HPUX (This used to be commit c84c516b179fcbbcdb36c0c0aa4ffb4ff12f2c35) --- source4/lib/replace/replace.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index 79b452d69c..20a420084a 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -512,7 +512,15 @@ int get_time_zone(time_t t) #ifdef HAVE_STRTOUQ return strtouq(str, endptr, base); #else -#error "system must support 64 bit integer read from strings" + unsigned long long int v; + if (sscanf(str, "%lli", &v) != 1) { + smb_panic("system does not support %lli in sscanf"); + } + if (endptr) { + /* try to get endptr right - uggh */ + strtoul(str, endptr, base); + } + return v; #endif } #endif -- cgit From 355c1699891ac7fd2a5c018c8176ed2472a5161d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jul 2005 04:32:59 +0000 Subject: r8703: cope with null string in interpret_addr() (This used to be commit ff156f7aae29045edd898635d16d141b3e848f3f) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 03ae86422f..173d755bec 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -332,7 +332,7 @@ uint32_t interpret_addr(const char *str) struct hostent *hp; uint32_t res; - if (str == NULL || + if (str == NULL || *str == 0 || strcmp(str,"0.0.0.0") == 0) { return 0; } -- cgit From 0edd0f43c0d25c31e893a4200aa583d83f81ba9c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Jul 2005 10:01:26 +0000 Subject: r8710: another attempt at fixing HPUX (This used to be commit eb3b3c8b407b2208291385539c3379f0420a448e) --- source4/lib/replace/replace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index 20a420084a..9ef3999769 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -514,7 +514,8 @@ int get_time_zone(time_t t) #else unsigned long long int v; if (sscanf(str, "%lli", &v) != 1) { - smb_panic("system does not support %lli in sscanf"); + errno = EINVAL; + return 0; } if (endptr) { /* try to get endptr right - uggh */ -- cgit From 79cac4b6e2f1b4e808930cb584c20c11b5df903f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Jul 2005 12:38:42 +0000 Subject: r8736: this fixes the ldb speed (raises BENCH-WINS from 15 ops/sec to over 4000) simo, we need to be careful to cope with this sort of direct dn query efficiently (This used to be commit 7b37923b726752101062fa8a92d3f96e41d55602) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 3ecb2d9b39..8e84cfa681 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -461,6 +461,13 @@ int ltdb_search_bytree(struct ldb_module *module, const char *base, struct ltdb_private *ltdb = module->private_data; int ret; + /* it is important that we handle dn queries this way, and not + via a full db search, otherwise ldb is horribly slow */ + if (tree->operation == LDB_OP_EQUALITY && + ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { + return ltdb_search_dn(module, tree->u.equality.value.data, attrs, res); + } + if (ltdb_lock_read(module) != 0) { return -1; } -- cgit From a7f9d9c5b8e77e0530ace68bd2ed4a7c374bf0fa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Jul 2005 01:17:09 +0000 Subject: r8740: Extend the rdn_name module to handle adding the rdn as an attribute. ie: dn: cn=foo,ou=bar objectClass: person implies dn: cn=foo,ou=bar objectClass: person cn: foo (as well as a pile more default attributes) We also correct the case in the attirbute to match that in the DN (win2k3 behaviour) and I have a testsuite (in ejs) to prove it. This module also found a bug in our provision.ldif, so and reduces code complexity in the samdb module. Andrew Bartlett (This used to be commit 0cc58f5c3cce12341ad0f7a90cdd85a3fab786b3) --- source4/lib/ldb/modules/rdn_name.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 6a11ab87fe..89cc49eb3e 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -88,10 +88,12 @@ static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { + struct private_data *data = (struct private_data *)module->private_data; + struct ldb_message *msg2; struct ldb_message_element *attribute; struct ldb_dn_component *rdn; - int ret, i; + int i, ret; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); @@ -126,6 +128,29 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa return -1; } + attribute = rdn_name_find_attribute(msg2, rdn->name); + + if (!attribute) { + if (ldb_msg_add_value(module->ldb, msg2, rdn->name, &rdn->value) != 0) { + return -1; + } + } else { + const struct ldb_attrib_handler *handler + = ldb_attrib_handler(module->ldb, rdn->name); + for (i=0; i < attribute->num_values; i++) { + if (handler->comparison_fn(module->ldb, msg2, &rdn->value, &attribute->values[i]) == 0) { + /* overwrite so it matches in case */ + attribute->values[i] = rdn->value; + break; + } + } + if (i == attribute->num_values) { + data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", msg2->dn, rdn->name); + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + return -1; + } + } + ret = ldb_next_add_record(module, msg2); talloc_free(msg2); -- cgit From f92c000fc903803e1c2817dd407974ec44390593 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jul 2005 04:03:01 +0000 Subject: r8746: replace opendir/readdir/telldir/seekdir/closedir on systems where they are broken (apparently all BSD systems). This breakage leads to unlink on files in an open directory causing a later seekdir to miss files. The bug happens due to a block boundary bug in the BSD libc implementation of these calls. This replacement code also fixes a severe memory usage problem with telldir that can cause closedir() to take an arbitrary amount of time. I have reported the bug in readdir to Greg Lehey (a FreeBSD maintainer) (This used to be commit e1bf7c4279fbc03a52497d24cea375e75059cba1) --- source4/lib/replace/config.mk | 12 ++- source4/lib/replace/repdir/config.m4 | 17 +++++ source4/lib/replace/repdir/repdir.c | 138 +++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 source4/lib/replace/repdir/config.m4 create mode 100644 source4/lib/replace/repdir/repdir.c (limited to 'source4/lib') diff --git a/source4/lib/replace/config.mk b/source4/lib/replace/config.mk index bd60402ba3..16952ea32d 100644 --- a/source4/lib/replace/config.mk +++ b/source4/lib/replace/config.mk @@ -1,9 +1,19 @@ +############################## +# Start SUBSYSTEM REPLACE_READDIR +[SUBSYSTEM::REPLACE_READDIR] +ADD_OBJ_FILES = \ + lib/replace/repdir/repdir.o +NOPROTO = YES +# End SUBSYSTEM REPLACE_READDIR +############################## + + ############################## # Start SUBSYSTEM LIBREPLACE [SUBSYSTEM::LIBREPLACE] INIT_OBJ_FILES = lib/replace/replace.o ADD_OBJ_FILES = \ lib/replace/snprintf.o +REQUIRED_SUBSYSTEMS = REPLACE_READDIR # End SUBSYSTEM LIBREPLACE ############################## - diff --git a/source4/lib/replace/repdir/config.m4 b/source4/lib/replace/repdir/config.m4 new file mode 100644 index 0000000000..0ef40ad8cb --- /dev/null +++ b/source4/lib/replace/repdir/config.m4 @@ -0,0 +1,17 @@ +AC_CACHE_CHECK([for broken readdir],samba_cv_HAVE_BROKEN_READDIR,[ + AC_TRY_RUN([#include "${srcdir-.}/build/tests/os2_delete.c"], + samba_cv_HAVE_BROKEN_READDIR=no,samba_cv_HAVE_BROKEN_READDIR=yes)]) + +if test x"$samba_cv_HAVE_BROKEN_READDIR" = x"yes"; then +AC_CACHE_CHECK([for replacing readdir],samba_cv_REPLACE_READDIR,[ + AC_TRY_RUN([ +#include "${srcdir-.}/lib/replace/repdir/repdir.c" +#include "${srcdir-.}/build/tests/os2_delete.c"], + samba_cv_REPLACE_READDIR=yes,samba_cv_REPLACE_READDIR=no)]) +fi + +SMB_SUBSYSTEM_ENABLE(REPLACE_READDIR, NO) +if test x"$samba_cv_REPLACE_READDIR" = x"yes"; then + AC_DEFINE(REPLACE_READDIR,1,[replace readdir]) + SMB_SUBSYSTEM_ENABLE(REPLACE_READDIR, YES) +fi diff --git a/source4/lib/replace/repdir/repdir.c b/source4/lib/replace/repdir/repdir.c new file mode 100644 index 0000000000..9c81355c68 --- /dev/null +++ b/source4/lib/replace/repdir/repdir.c @@ -0,0 +1,138 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a replacement for opendir/readdir/telldir/seekdir/closedir for BSD systems + + This is needed because the existing directory handling in FreeBSD + and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() + on files in a directory where telldir() has been used. On a block + boundary it will occasionally miss a file when seekdir() is used to + return to a position previously recorded with telldir(). + + This also fixes a severe performance and memory usage problem with + telldir() on BSD systems. Each call to telldir() in BSD adds an + entry to a linked list, and those entries are cleaned up on + closedir(). This means with a large directory closedir() can take an + arbitrary amount of time, causing network timeouts as millions of + telldir() entries are freed + + Note! This replacement code is not portable. It relies on getdents() + always leaving the file descriptor at a seek offset that is a + multiple of DIR_BUF_SIZE. If the code detects that this doesn't + happen then it will abort(). It also does not handle directories + with offsets larger than can be stored in a long, + + This code is available under other free software licenses as + well. Contact the author. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define DIR_BUF_BITS 9 +#define DIR_BUF_SIZE (1<fd = open(dname, O_RDONLY); + if (d->fd == -1) { + free(d); + return NULL; + } + d->ofs = 0; + d->seekpos = 0; + d->nbytes = 0; + return (DIR *)d; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + struct dirent *de; + + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + } + if (d->ofs >= d->nbytes) { + return NULL; + } + de = (struct dirent *)&d->buf[d->ofs]; + d->ofs += de->d_reclen; + return de; +} + +long telldir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->ofs = 0; + d->nbytes = 0; + } + /* this relies on seekpos always being a multiple of + DIR_BUF_SIZE. Is that always true on BSD systems? */ + if (d->seekpos & (DIR_BUF_SIZE-1)) { + abort(); + } + return d->seekpos + d->ofs; +} + +void seekdir(DIR *dir, long ofs) +{ + struct dir_buf *d = (struct dir_buf *)dir; + d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { + if (readdir(dir) == NULL) break; + } +} + +int closedir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + int r = close(d->fd); + if (r != 0) { + return r; + } + free(d); + return 0; +} + -- cgit From 616ea8deb42979593911a04cf7c56909fbaee7b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jul 2005 04:03:22 +0000 Subject: r8747: remove unused code (This used to be commit 60a07da59dfe6dd89f01c6fb494debeda1a1984d) --- source4/lib/ldap_escape.c | 90 ----------------------------------------------- 1 file changed, 90 deletions(-) delete mode 100644 source4/lib/ldap_escape.c (limited to 'source4/lib') diff --git a/source4/lib/ldap_escape.c b/source4/lib/ldap_escape.c deleted file mode 100644 index 9e88b4999c..0000000000 --- a/source4/lib/ldap_escape.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Unix SMB/CIFS implementation. - ldap filter argument escaping - - Copyright (C) 1998, 1999, 2000 Luke Howard , - Copyright (C) 2003 Andrew Bartlett - - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/** - * Escape a parameter to an LDAP filter string, so they cannot contain - * embeded ( ) * or \ chars which may cause it not to parse correctly. - * - * @param s The input string - * - * @return A string allocated with malloc(), containing the escaped string, - * and to be free()ed by the caller. - **/ - -char *escape_ldap_string_alloc(const char *s) -{ - size_t len = strlen(s)+1; - char *output = malloc(len); - char *output_tmp; - const char *sub; - int i = 0; - char *p = output; - - while (*s) - { - switch (*s) - { - case '*': - sub = "\\2a"; - break; - case '(': - sub = "\\28"; - break; - case ')': - sub = "\\29"; - break; - case '\\': - sub = "\\5c"; - break; - default: - sub = NULL; - break; - } - - if (sub) { - len = len + 3; - output_tmp = realloc(output, len); - if (!output_tmp) { - SAFE_FREE(output); - return NULL; - } - output = output_tmp; - - p = &output[i]; - strncpy (p, sub, 3); - p += 3; - i += 3; - - } else { - *p = *s; - p++; - i++; - } - s++; - } - - *p = '\0'; - return output; -} -- cgit From ecc691041c0650973830c4c566b362b19967f80c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jul 2005 04:34:14 +0000 Subject: r8749: for completeness, add rewinddir() and dirfd() (This used to be commit ce022e40908dabad41de276941d2ee7a5739aea4) --- source4/lib/replace/repdir/repdir.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/repdir/repdir.c b/source4/lib/replace/repdir/repdir.c index 9c81355c68..a4317aa11c 100644 --- a/source4/lib/replace/repdir/repdir.c +++ b/source4/lib/replace/repdir/repdir.c @@ -125,6 +125,11 @@ void seekdir(DIR *dir, long ofs) } } +void rewinddir(DIR *dir) +{ + seekdir(dir, 0); +} + int closedir(DIR *dir) { struct dir_buf *d = (struct dir_buf *)dir; @@ -136,3 +141,8 @@ int closedir(DIR *dir) return 0; } +int dirfd(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + return d->fd; +} -- cgit From dc4af82432c43920eeafbcdbbe2a6576a6d8d80e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Jul 2005 04:39:20 +0000 Subject: r8750: drat, on some systems dirfd() is a macro (This used to be commit d974bf3589e1b0cd1d5661a21571b81e99350709) --- source4/lib/replace/repdir/repdir.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/repdir/repdir.c b/source4/lib/replace/repdir/repdir.c index a4317aa11c..b536ed6587 100644 --- a/source4/lib/replace/repdir/repdir.c +++ b/source4/lib/replace/repdir/repdir.c @@ -141,8 +141,11 @@ int closedir(DIR *dir) return 0; } +#ifndef dirfd +/* darn, this is a macro on some systems. */ int dirfd(DIR *dir) { struct dir_buf *d = (struct dir_buf *)dir; return d->fd; } +#endif -- cgit From 768585b1dd3fcc2f2180528bd94e1fef4a6ead7b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 26 Jul 2005 09:17:46 +0000 Subject: r8779: Add rdn module to makefile and headers Search by distinguishedName as if searching by dn (This used to be commit 1d4046136255aead319ab08da229146dbd285b38) --- source4/lib/ldb/Makefile.in | 2 +- source4/lib/ldb/include/ldb_private.h | 2 ++ source4/lib/ldb/ldb_tdb/ldb_search.c | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 81e2b147d5..bbd2602ef7 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -55,7 +55,7 @@ COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ common/ldb_dn.o common/ldb_match.o common/ldb_attributes.o \ common/attrib_handlers.o -MODULES_OBJ=modules/timestamps.o modules/schema.o +MODULES_OBJ=modules/timestamps.o modules/schema.o modules/rdn_name.o OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) $(LDB_SQLITE3_OBJ) diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 0abf056db4..43e6a3ecba 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -171,6 +171,8 @@ int lsqlite3_connect(struct ldb_context *ldb, const char *options[]); struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *options[]); struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *options[]); +struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[]); + int ldb_match_msg(struct ldb_context *ldb, struct ldb_message *msg, diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 8e84cfa681..922d24b6eb 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -464,7 +464,8 @@ int ltdb_search_bytree(struct ldb_module *module, const char *base, /* it is important that we handle dn queries this way, and not via a full db search, otherwise ldb is horribly slow */ if (tree->operation == LDB_OP_EQUALITY && - ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { + (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0 || + ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0)) { return ltdb_search_dn(module, tree->u.equality.value.data, attrs, res); } -- cgit From ebb76f84ad372a24c8ed21feb2b21da45be19f24 Mon Sep 17 00:00:00 2001 From: Rafal Szczesniak Date: Wed, 27 Jul 2005 22:14:55 +0000 Subject: r8810: Fix missing headers. Still doesn't fix the build but getting closer there. rafal (This used to be commit bc638cc3d66525cf91ef76eb0c486542fff2b929) --- source4/lib/ldb/samba/ldif_handlers.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/samba/ldif_handlers.c b/source4/lib/ldb/samba/ldif_handlers.c index 6cd4b7e849..659fbc013d 100644 --- a/source4/lib/ldb/samba/ldif_handlers.c +++ b/source4/lib/ldb/samba/ldif_handlers.c @@ -26,6 +26,7 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/ndr_security.h" +#include "librpc/gen_ndr/ndr_misc.h" /* convert a ldif formatted objectSid to a NDR formatted blob -- cgit From ba759b4c86efbf386bc20c1a10ff1996715af132 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Jul 2005 04:09:11 +0000 Subject: r8819: fixed a memory leak in irpc_call() (This used to be commit 25b7524ce5029eadd48c3046297ca6bd3260b013) --- source4/lib/messaging/messaging.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 1a2485d700..911d439de1 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -717,7 +717,9 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, { struct irpc_request *irpc = irpc_call_send(msg_ctx, server_id, table, callnum, r); - return irpc_call_recv(irpc); + NTSTATUS status = irpc_call_recv(irpc); + talloc_free(irpc); + return status; } /* -- cgit From 930e624d816a175d5ca4448e6ed40bc7dd8ec5b7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 28 Jul 2005 11:51:37 +0000 Subject: r8826: Make configure generate config.mk files (with the external libraries that were found) and a config.pm file (with all substitution variables) (This used to be commit 52bb1374bbcfc9b9a6d098687bafe9021a1ee858) --- source4/lib/cmdline/config.m4 | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index 45c3a70f9f..4f6606b8db 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -76,7 +76,6 @@ SMB_EXT_LIB(READLINE, [${TMP_LIBCMDLINE_LIBS}]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], - [], [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS LIBCMDLINE_CREDENTIALS]) AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ -- cgit From 5bddfe7a1a094d86dffaa0f8a52c2e35d6453b2d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Aug 2005 00:34:39 +0000 Subject: r8875: Rename timeval_diff to timeval_until and revert the arguments. timeval_diff is not strictly a subtraction function, there can't be negative timevals. Volker (This used to be commit 525d75dd24f6a8810f1ed2043d170c70b060f1f0) --- source4/lib/events/events_standard.c | 2 +- source4/lib/time.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 5a64a42b28..16c9464fd0 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -488,7 +488,7 @@ static int std_event_loop_once(struct event_context *ev) /* work out the right timeout for all timed events */ if (std_ev->timed_events) { struct timeval t = timeval_current(); - tval = timeval_diff(&std_ev->timed_events->next_event, &t); + tval = timeval_until(&t, &std_ev->timed_events->next_event); if (timeval_is_zero(&tval)) { std_event_loop_timer(ev); return 0; diff --git a/source4/lib/time.c b/source4/lib/time.c index 7b371f58dd..1fce5af06d 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -561,21 +561,21 @@ struct timeval timeval_max(struct timeval *tv1, struct timeval *tv2) /* return the difference between two timevals as a timeval - if tv2 comes after tv1, then return a zero timeval - (this is *tv1 - *tv2) + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) */ -struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2) +struct timeval timeval_until(struct timeval *tv1, struct timeval *tv2) { struct timeval t; - if (timeval_compare(tv1, tv2) >= 0) { + if (timeval_compare(tv2, tv1) >= 0) { return timeval_zero(); } - t.tv_sec = tv1->tv_sec - tv2->tv_sec; - if (tv2->tv_usec > tv1->tv_usec) { + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { t.tv_sec--; - t.tv_usec = 1000000 - (tv2->tv_usec - tv1->tv_usec); + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); } else { - t.tv_usec = tv1->tv_usec - tv2->tv_usec; + t.tv_usec = tv2->tv_usec - tv1->tv_usec; } return t; } -- cgit From 66c270ba525e96d1cb7c3ab75c7137d3f62ddffb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Aug 2005 16:12:19 +0000 Subject: r8883: Apply some const. Volker (This used to be commit ccbb64e2670eab921bc50b8f2dbf0b274c0b8750) --- source4/lib/time.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/time.c b/source4/lib/time.c index 1fce5af06d..3bc97dddc9 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -435,7 +435,7 @@ struct timeval timeval_zero(void) /* return True if a timeval is zero */ -BOOL timeval_is_zero(struct timeval *tv) +BOOL timeval_is_zero(const struct timeval *tv) { return tv->tv_sec == 0 && tv->tv_usec == 0; } @@ -465,7 +465,8 @@ struct timeval timeval_set(uint32_t secs, uint32_t usecs) /* return a timeval ofs microseconds after tv */ -struct timeval timeval_add(struct timeval *tv, uint32_t secs, uint32_t usecs) +struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs) { struct timeval tv2 = *tv; const uint_t million = 1000000; @@ -479,7 +480,8 @@ struct timeval timeval_add(struct timeval *tv, uint32_t secs, uint32_t usecs) /* return the sum of two timeval structures */ -struct timeval timeval_sum(struct timeval *tv1, struct timeval *tv2) +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2) { return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); } @@ -499,7 +501,7 @@ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) Return 0 if tv2 == tv1 Return -1 if tv2 < tv1 */ -int timeval_compare(struct timeval *tv1, struct timeval *tv2) +int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) { if (tv2->tv_sec > tv1->tv_sec) return 1; if (tv2->tv_sec < tv1->tv_sec) return -1; @@ -511,7 +513,7 @@ int timeval_compare(struct timeval *tv1, struct timeval *tv2) /* return True if a timer is in the past */ -BOOL timeval_expired(struct timeval *tv) +BOOL timeval_expired(const struct timeval *tv) { struct timeval tv2 = timeval_current(); if (tv2.tv_sec > tv->tv_sec) return True; @@ -522,7 +524,7 @@ BOOL timeval_expired(struct timeval *tv) /* return the number of seconds elapsed between two times */ -double timeval_elapsed2(struct timeval *tv1, struct timeval *tv2) +double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) { return (tv2->tv_sec - tv1->tv_sec) + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; @@ -531,7 +533,7 @@ double timeval_elapsed2(struct timeval *tv1, struct timeval *tv2) /* return the number of seconds elapsed since a given time */ -double timeval_elapsed(struct timeval *tv) +double timeval_elapsed(const struct timeval *tv) { struct timeval tv2 = timeval_current(); return timeval_elapsed2(tv, &tv2); @@ -540,7 +542,8 @@ double timeval_elapsed(struct timeval *tv) /* return the lesser of two timevals */ -struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2) +struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2) { if (tv1->tv_sec < tv2->tv_sec) return *tv1; if (tv1->tv_sec > tv2->tv_sec) return *tv2; @@ -551,7 +554,8 @@ struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2) /* return the greater of two timevals */ -struct timeval timeval_max(struct timeval *tv1, struct timeval *tv2) +struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2) { if (tv1->tv_sec > tv2->tv_sec) return *tv1; if (tv1->tv_sec < tv2->tv_sec) return *tv2; @@ -564,7 +568,8 @@ struct timeval timeval_max(struct timeval *tv1, struct timeval *tv2) if tv1 comes after tv2, then return a zero timeval (this is *tv2 - *tv1) */ -struct timeval timeval_until(struct timeval *tv1, struct timeval *tv2) +struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2) { struct timeval t; if (timeval_compare(tv2, tv1) >= 0) { @@ -584,7 +589,7 @@ struct timeval timeval_until(struct timeval *tv1, struct timeval *tv2) /* convert a timeval to a NTTIME */ -NTTIME timeval_to_nttime(struct timeval *tv) +NTTIME timeval_to_nttime(const struct timeval *tv) { return 10*(tv->tv_usec + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); -- cgit From 6f0e5b59538b99decc186e899bef65d4c02e41bb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Aug 2005 17:31:40 +0000 Subject: r8886: Exchange the arguments of timeval_compare, this makes it behave like strcmp. Volker (This used to be commit 6f5bd7602155413029de32295d2639c4073ad4d8) --- source4/lib/events/events_standard.c | 3 ++- source4/lib/time.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 16c9464fd0..810e8bbca3 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -311,7 +311,8 @@ static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_ for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) { /* if the new event comes before the current one break */ if (!timeval_is_zero(&cur_te->next_event) && - timeval_compare(&cur_te->next_event, &te->next_event) < 0) { + timeval_compare(&te->next_event, + &cur_te->next_event) < 0) { break; } diff --git a/source4/lib/time.c b/source4/lib/time.c index 3bc97dddc9..61e92b8c00 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -497,16 +497,16 @@ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) /* compare two timeval structures. - Return 1 if tv2 > tv1 - Return 0 if tv2 == tv1 - Return -1 if tv2 < tv1 + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 */ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) { - if (tv2->tv_sec > tv1->tv_sec) return 1; - if (tv2->tv_sec < tv1->tv_sec) return -1; - if (tv2->tv_usec > tv1->tv_usec) return 1; - if (tv2->tv_usec < tv1->tv_usec) return -1; + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; return 0; } @@ -572,7 +572,7 @@ struct timeval timeval_until(const struct timeval *tv1, const struct timeval *tv2) { struct timeval t; - if (timeval_compare(tv2, tv1) >= 0) { + if (timeval_compare(tv1, tv2) >= 0) { return timeval_zero(); } t.tv_sec = tv2->tv_sec - tv1->tv_sec; -- cgit From fc585709402e6840a5dd16c9a3fb22792ddacf3e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Aug 2005 17:33:43 +0000 Subject: r8887: fixed the irpc error that caused ia64 to fail the LOCAL-IRPC test (This used to be commit ce9a262d379b946717d0d4be4731c837e6f7373d) --- source4/lib/messaging/irpc.h | 15 ++++++++------- source4/lib/messaging/messaging.c | 12 ++++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 4fb1acfedb..7398453612 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -29,7 +29,7 @@ struct irpc_message { }; /* don't allow calls to take too long */ -#define IRPC_CALL_TIMEOUT 10 +#define IRPC_CALL_TIMEOUT 1000 /* the server function type */ @@ -42,11 +42,11 @@ typedef NTSTATUS (*irpc_function_t)(struct irpc_message *, void *r); (irpc_function_t)function, private) /* make a irpc call */ -#define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr) \ - irpc_call(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr) +#define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr, ctx) \ + irpc_call(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr, ctx) -#define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr) \ - irpc_call_send(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr) +#define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr, ctx) \ + irpc_call_send(msg_ctx, server_id, &dcerpc_table_ ## pipename, DCERPC_ ## funcname, ptr, ctx) /* @@ -60,6 +60,7 @@ struct irpc_request { void *r; NTSTATUS status; BOOL done; + TALLOC_CTX *mem_ctx; struct { void (*fn)(struct irpc_request *); void *private; @@ -89,12 +90,12 @@ NTSTATUS irpc_register(struct messaging_context *msg_ctx, struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, - int callnum, void *r); + int callnum, void *r, TALLOC_CTX *ctx); NTSTATUS irpc_call_recv(struct irpc_request *irpc); NTSTATUS irpc_call(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, - int callnum, void *r); + int callnum, void *r, TALLOC_CTX *ctx); NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *name); diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 911d439de1..6cabb4c63b 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -500,9 +500,11 @@ static void irpc_handler_reply(struct messaging_context *msg_ctx, irpc->status = irpc->table->calls[irpc->callnum].ndr_pull(ndr, NDR_OUT, irpc->r); if (NT_STATUS_IS_OK(irpc->status)) { irpc->status = header->status; + talloc_steal(irpc->mem_ctx, ndr); + } else { + talloc_steal(irpc, ndr); } irpc->done = True; - talloc_steal(irpc, ndr); if (irpc->async.fn) { irpc->async.fn(irpc); } @@ -634,7 +636,7 @@ static void irpc_timeout(struct event_context *ev, struct timed_event *te, struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, - int callnum, void *r) + int callnum, void *r, TALLOC_CTX *ctx) { struct irpc_header header; struct ndr_push *ndr; @@ -653,6 +655,7 @@ struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, irpc->r = r; irpc->done = False; irpc->async.fn = NULL; + irpc->mem_ctx = ctx; talloc_set_destructor(irpc, irpc_destructor); @@ -713,10 +716,11 @@ NTSTATUS irpc_call_recv(struct irpc_request *irpc) NTSTATUS irpc_call(struct messaging_context *msg_ctx, uint32_t server_id, const struct dcerpc_interface_table *table, - int callnum, void *r) + int callnum, void *r, + TALLOC_CTX *mem_ctx) { struct irpc_request *irpc = irpc_call_send(msg_ctx, server_id, - table, callnum, r); + table, callnum, r, mem_ctx); NTSTATUS status = irpc_call_recv(irpc); talloc_free(irpc); return status; -- cgit From 6e64a8b40fe0857cc5565ff855387c2ef97374dc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Aug 2005 01:22:38 +0000 Subject: r8905: don't try to do DNS lookups on interface names with wildcards (This used to be commit bbdd446254a0e66af3326e2e66d568eeee0922c0) --- source4/lib/netif/interface.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index 670913ab6f..17a10c6799 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -136,6 +136,10 @@ static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token) /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (!p) { + /* don't try to do dns lookups on wildcard names */ + if (strpbrk(token, "*?") != NULL) { + return; + } ip.s_addr = interpret_addr2(token).addr; for (i=0;i Date: Tue, 2 Aug 2005 14:04:22 +0000 Subject: r8917: Better support for extended ldap search operations Try to follow the RFC where possible and adapt to openLdap and AD way of handling this structure (This used to be commit d844d45d87b4114bc1b9af2e40f8c27ba3e219de) --- source4/lib/ldb/common/ldb_match.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 97e0a60ace..7ff84f70c3 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -187,6 +187,8 @@ static int ldb_match_equality(struct ldb_context *ldb, return 0; } + /* TODO: handle the "*" case derived from an extended search + operation without the attibute type defined */ el = ldb_msg_find_element(msg, tree->u.equality.attr); if (el == NULL) { return 0; -- cgit From 08b2b7e3e1557ec7b0ddca09695844b7839a7ddf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Aug 2005 16:58:52 +0000 Subject: r8923: put the IRPC default timeout back to 10s (I didn't mean to commit this, it was changed just for deugging) (This used to be commit a7c260e61feec210bcb5cad0f8f759544dc9dd1e) --- source4/lib/messaging/irpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index 7398453612..f015215940 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -29,7 +29,7 @@ struct irpc_message { }; /* don't allow calls to take too long */ -#define IRPC_CALL_TIMEOUT 1000 +#define IRPC_CALL_TIMEOUT 10 /* the server function type */ -- cgit From f30eba52225df456e341beac380ab05469bde76b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 2 Aug 2005 20:12:31 +0000 Subject: r8940: Add TDR (Trivial Data Representation). The aim is to use this later for NBT/WINS/etc rather then having to depend on NDR. (This used to be commit 5ee7af26dd220de06f1764cd1683abedeeda5131) --- source4/lib/basic.mk | 3 + source4/lib/tdr/tdr.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++ source4/lib/tdr/tdr.h | 52 ++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 source4/lib/tdr/tdr.c create mode 100644 source4/lib/tdr/tdr.h (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 58cbca0198..3953d702bc 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -10,6 +10,9 @@ ADD_OBJ_FILES = \ # End SUBSYSTEM LIBNETIF ############################## +[SUBSYSTEM::TDR] +INIT_OBJ_FILES = lib/tdr/tdr.o + ############################## # Start SUBSYSTEM LIBCRYPTO [SUBSYSTEM::LIBCRYPTO] diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c new file mode 100644 index 0000000000..c9aa289f00 --- /dev/null +++ b/source4/lib/tdr/tdr.c @@ -0,0 +1,229 @@ +/* + Unix SMB/CIFS implementation. + + TDR (Trivial Data Representation) helper functions + Based loosely on ndr.c by Andrew Tridgell. + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/network.h" + +#define TDR_BASE_MARSHALL_SIZE 1024 + +#define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->offset+(n))) + +#define TDR_PULL_NEED_BYTES(tdr, n) do { \ + if ((n) > tdr->length || tdr->offset + (n) > tdr->length) { \ + return NT_STATUS_BUFFER_TOO_SMALL; \ + } \ +} while(0) + +#define TDR_BE(tdr) ((tdr)->flags & TDR_FLAG_BIGENDIAN) + +#define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data,ofs):SVAL(tdr->data,ofs)) +#define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data,ofs):IVAL(tdr->data,ofs)) +#define TDR_IVALS(tdr, ofs) (TDR_BE(tdr)?RIVALS(tdr->data,ofs):IVALS(tdr->data,ofs)) +#define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSSVAL(tdr->data,ofs,v); } else SSVAL(tdr->data,ofs,v); } while (0) +#define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data,ofs,v); } else SIVAL(tdr->data,ofs,v); } while (0) +#define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVALS(tdr->data,ofs,v); } else SIVALS(tdr->data,ofs,v); } while (0) + +struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + struct tdr_pull *tdr = talloc(mem_ctx, struct tdr_pull); + tdr->data = blob->data; + tdr->length = blob->length; + tdr->offset = 0; + tdr->flags = 0; + return tdr; +} + +struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct tdr_push); +} + +struct tdr_print *tdr_print_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct tdr_print); +} + +/* + expand the available space in the buffer to 'size' +*/ +NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) +{ + if (tdr->alloc_size >= size) { + return NT_STATUS_OK; + } + + tdr->alloc_size += TDR_BASE_MARSHALL_SIZE; + if (size > tdr->alloc_size) { + tdr->length = size; + } + tdr->data = talloc_realloc(tdr, tdr->data, uint8_t, tdr->alloc_size); + return NT_STATUS_NO_MEMORY; +} + + +NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) +{ + TDR_PULL_NEED_BYTES(tdr, 1); + SCVAL(tdr->data, tdr->offset, *v); + tdr->offset += 1; + return NT_STATUS_OK; +} + +NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v) +{ + TDR_PUSH_NEED_BYTES(tdr, 1); + SCVAL(tdr->data, tdr->offset, *v); + tdr->offset += 1; + return NT_STATUS_OK; +} + +NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v) +{ + tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); + return NT_STATUS_OK; +} + +NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, uint16_t *v) +{ + TDR_PULL_NEED_BYTES(tdr, 2); + *v = TDR_SVAL(tdr, tdr->offset); + tdr->offset += 2; + return NT_STATUS_OK; +} + +NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v) +{ + TDR_PUSH_NEED_BYTES(tdr, 2); + TDR_SSVAL(tdr, tdr->offset, *v); + tdr->offset += 2; + return NT_STATUS_OK; +} + +NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v) +{ + tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); + return NT_STATUS_OK; +} + +NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint16_t *v) +{ + TDR_PULL_NEED_BYTES(tdr, 4); + *v = TDR_IVAL(tdr, tdr->offset); + tdr->offset += 4; + return NT_STATUS_OK; +} + +NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint16_t *v) +{ + TDR_PUSH_NEED_BYTES(tdr, 4); + TDR_SIVAL(tdr, tdr->offset, *v); + tdr->offset += 4; + return NT_STATUS_OK; +} + +NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v) +{ + tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); + return NT_STATUS_OK; +} + +NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, char **v, uint32_t length, uint32_t el_size, int chset) +{ + int ret; + if (length == -1) { + switch (chset) { + case CH_DOS: + length = ascii_len_n((const char*)tdr->data+tdr->offset, tdr->length-tdr->offset); + break; + case CH_UTF16: + length = utf16_len_n(tdr->data+tdr->offset, tdr->length-tdr->offset); + default: + return NT_STATUS_INVALID_PARAMETER; + } + } + + TDR_PULL_NEED_BYTES(tdr, el_size*length); + + ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, (void **)v); + + if (ret == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + + return NT_STATUS_OK; +} + +NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, int chset) +{ + int ret; + TDR_PUSH_NEED_BYTES(tdr, el_size*length); + + ret = convert_string(CH_UNIX, chset, *v, length, tdr->data+tdr->offset, el_size*length); + + if (ret == -1) { + return NT_STATUS_INVALID_PARAMETER; + } + + tdr->offset += ret; + + return NT_STATUS_OK; +} + +NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, int chset) +{ + tdr->print(tdr, "%-25s: %s", name, *v); + return NT_STATUS_OK; +} + +/* + pull a ipv4address +*/ +NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, const char **address) +{ + struct ipv4_addr in; + TDR_CHECK(tdr_pull_uint32(tdr, &in.addr)); + in.addr = htonl(in.addr); + *address = talloc_strdup(tdr, sys_inet_ntoa(in)); + NT_STATUS_HAVE_NO_MEMORY(*address); + return NT_STATUS_OK; +} + +/* + push a ipv4address +*/ +NTSTATUS tdr_push_ipv4address(struct tdr_push *tdr, const char **address) +{ + uint32_t addr = htonl(interpret_addr(*address)); + TDR_CHECK(tdr_push_uint32(tdr, &addr)); + return NT_STATUS_OK; +} + +/* + print a ipv4address +*/ +NTSTATUS tdr_print_ipv4address(struct tdr_print *tdr, const char *name, + const char **address) +{ + tdr->print(tdr, "%-25s: %s", name, *address); + return NT_STATUS_OK; +} diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h new file mode 100644 index 0000000000..604f9d549a --- /dev/null +++ b/source4/lib/tdr/tdr.h @@ -0,0 +1,52 @@ +/* + Unix SMB/CIFS implementation. + TDR definitions + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define TDR_FLAG_BIGENDIAN 1 + +struct tdr_pull { + uint8_t *data; + uint32_t offset; + uint32_t length; + int flags; +}; + +struct tdr_push { + uint8_t *data; + uint32_t alloc_size; + uint32_t offset; + uint32_t length; + int flags; +}; + +struct tdr_print { + int level; + void (*print)(struct tdr_print *, const char *, ...); +}; + +#define TDR_CHECK(call) do { NTSTATUS _status; \ + _status = call; \ + if (!NT_STATUS_IS_OK(_status)) \ + return _status; \ + } while (0) + +#define TDR_ALLOC(tdr, s, n) do { \ + (s) = talloc_array_size(tdr, sizeof(*(s)), n); \ + if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ + } while (0) -- cgit From 9f611ffddeced5661b81fbe6264502a0d59f187b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Aug 2005 00:08:28 +0000 Subject: r8966: Simplify the makefile generation system a bit. Autogenerate list of binaries (rather then having them hardcoded in build/smb_build/makefile.pm) Add INSTALLDIR keyword to .mk files (This used to be commit ce0935112b846486cf705ec69f12350be9c4c89d) --- source4/lib/ldb/config.mk | 7 +++++++ source4/lib/registry/config.mk | 4 ++++ source4/lib/tdb/config.mk | 4 ++++ 3 files changed, 15 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 87e15f1375..f2c10638b0 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -123,6 +123,7 @@ REQUIRED_SUBSYSTEMS = LIBLDB LIBCMDLINE LIBBASIC ################################################ # Start BINARY ldbadd [BINARY::ldbadd] +INSTALLDIR = BINDIR OBJ_FILES = \ lib/ldb/tools/ldbadd.o REQUIRED_SUBSYSTEMS = \ @@ -134,6 +135,7 @@ MANPAGE = lib/ldb/man/ldbadd.1 ################################################ # Start BINARY ldbdel [BINARY::ldbdel] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbdel.o REQUIRED_SUBSYSTEMS = \ @@ -145,6 +147,7 @@ MANPAGE = lib/ldb/man/ldbdel.1 ################################################ # Start BINARY ldbmodify [BINARY::ldbmodify] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbmodify.o REQUIRED_SUBSYSTEMS = \ @@ -156,6 +159,7 @@ MANPAGE = lib/ldb/man/ldbmodify.1 ################################################ # Start BINARY ldbsearch [BINARY::ldbsearch] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbsearch.o REQUIRED_SUBSYSTEMS = \ @@ -167,6 +171,7 @@ MANPAGE = lib/ldb/man/ldbsearch.1 ################################################ # Start BINARY ldbedit [BINARY::ldbedit] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbedit.o REQUIRED_SUBSYSTEMS = \ @@ -178,6 +183,7 @@ MANPAGE = lib/ldb/man/ldbedit.1 ################################################ # Start BINARY ldbrename [BINARY::ldbrename] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbrename.o REQUIRED_SUBSYSTEMS = \ @@ -189,6 +195,7 @@ MANPAGE = lib/ldb/man/ldbrename.1 ################################################ # Start BINARY ldbtest [BINARY::ldbtest] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/ldb/tools/ldbtest.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index ab699a8ac0..c533e17ea9 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -94,6 +94,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY regdiff [BINARY::regdiff] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/registry/tools/regdiff.o REQUIRED_SUBSYSTEMS = \ @@ -105,6 +106,7 @@ MANPAGE = lib/registry/man/regdiff.1 ################################################ # Start BINARY regpatch [BINARY::regpatch] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/registry/tools/regpatch.o REQUIRED_SUBSYSTEMS = \ @@ -116,6 +118,7 @@ MANPAGE = lib/registry/man/regpatch.1 ################################################ # Start BINARY regshell [BINARY::regshell] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/registry/tools/regshell.o REQUIRED_SUBSYSTEMS = \ @@ -127,6 +130,7 @@ MANPAGE = lib/registry/man/regshell.1 ################################################ # Start BINARY regtree [BINARY::regtree] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/registry/tools/regtree.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 221c5284f7..60c41f8bb2 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -28,6 +28,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbtool [BINARY::tdbtool] +INSTALLDIR = BINDIR ENABLE = NO OBJ_FILES= \ lib/tdb/tools/tdbtool.o @@ -39,6 +40,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbtorture [BINARY::tdbtorture] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/tdb/tools/tdbtorture.o REQUIRED_SUBSYSTEMS = \ @@ -49,6 +51,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbdump [BINARY::tdbdump] +INSTALLDIR = BINDIR OBJ_FILES= \ lib/tdb/tools/tdbdump.o REQUIRED_SUBSYSTEMS = \ @@ -59,6 +62,7 @@ REQUIRED_SUBSYSTEMS = \ ################################################ # Start BINARY tdbbackup [BINARY::tdbbackup] +INSTALLDIR = BINDIR ENABLE = NO OBJ_FILES= \ lib/tdb/tools/tdbbackup.o -- cgit From 88632d832f0becc9aadfefc6d49a2c3593f58a2c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Aug 2005 01:46:33 +0000 Subject: r8972: More simplifications... (This used to be commit d89caeb8004c5cfabc934c8efa899a6d1839d250) --- source4/lib/cmdline/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/config.m4 b/source4/lib/cmdline/config.m4 index 4f6606b8db..e43f7cf390 100644 --- a/source4/lib/cmdline/config.m4 +++ b/source4/lib/cmdline/config.m4 @@ -76,7 +76,7 @@ SMB_EXT_LIB(READLINE, [${TMP_LIBCMDLINE_LIBS}]) SMB_SUBSYSTEM(LIBCMDLINE,[], [${TMP_LIBCMDLINE_OBJS}], - [LIBPOPT EXT_LIB_READLINE EXT_LIB_ALLLIBS LIBCMDLINE_CREDENTIALS]) + [LIBPOPT EXT_LIB_READLINE LIBCMDLINE_CREDENTIALS]) AC_CACHE_CHECK([whether getpass should be replaced],samba_cv_REPLACE_GETPASS,[ SAVE_CPPFLAGS="$CPPFLAGS" -- cgit From 7facdcc161b75c7a3a85a0f6380f5b83394183c4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 3 Aug 2005 05:28:08 +0000 Subject: r8985: Automatically generate make dependency rules for the asn1 and error table files. This removes the need for HEIMDAL_EXTERNAL (This used to be commit 2f481ac93c0151b82dab737d49ae8d0d3cbbbbbe) --- source4/lib/talloc/config.mk | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/config.mk b/source4/lib/talloc/config.mk index a1032a6e41..7b47eacaf6 100644 --- a/source4/lib/talloc/config.mk +++ b/source4/lib/talloc/config.mk @@ -1,13 +1,10 @@ ################################################ # Start SUBSYSTEM LIBTALLOC [SUBSYSTEM::LIBTALLOC] -INIT_OBJ_FILES = \ - lib/talloc/talloc.o -REQUIRED_SUBSYSTEMS = \ - LIBREPLACE +INIT_OBJ_FILES = lib/talloc/talloc.o +REQUIRED_SUBSYSTEMS = LIBREPLACE NOPROTO = YES MANPAGE = lib/talloc/talloc.3 -# # End SUBSYSTEM LIBTALLOC ################################################ @@ -17,8 +14,7 @@ MANPAGE = lib/talloc/talloc.3 MAJOR_VERSION = 0 MINOR_VERSION = 0 RELEASE_VERSION = 1 -REQUIRED_SUBSYSTEMS = \ - LIBTALLOC +REQUIRED_SUBSYSTEMS = LIBTALLOC # # End LIBRARY LIBTALLOC ################################################ -- cgit From 56c112bbbc028bf7b74b47b22d41b74c7a3f9855 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Aug 2005 16:49:17 +0000 Subject: r9063: - don't pollute the global $LIBS variable with -ldl - -lresolve seems to not being needed any more (it's actually not used, and the build farm seem to happy with it) - move socket and netif configure test to seperate files - don't pollute the global $LIBS variable with -lsocket ... - actually make use of the -lsocket when needed (should fix the solaris build) metze (This used to be commit adebd56be6f62323d56b6666ca0e02f85a33438e) --- source4/lib/netif/config.m4 | 42 ++++++++++++++++++++ source4/lib/replace/config.m4 | 16 ++++++++ source4/lib/socket/config.m4 | 90 ++++++++++++++++++++++++++++++++++++++++++- source4/lib/socket/config.mk | 3 ++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 source4/lib/netif/config.m4 create mode 100644 source4/lib/replace/config.m4 (limited to 'source4/lib') diff --git a/source4/lib/netif/config.m4 b/source4/lib/netif/config.m4 new file mode 100644 index 0000000000..76d1bfa9d5 --- /dev/null +++ b/source4/lib/netif/config.m4 @@ -0,0 +1,42 @@ +AC_CHECK_HEADERS(arpa/inet.h net/if.h netdb.h netinet/in.h) +AC_CHECK_HEADERS(netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h) + +################## +# look for a method of finding the list of network interfaces +iface=no; +AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[ +AC_TRY_RUN([ +#define HAVE_IFACE_AIX 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/netif/netif.c"], + samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)]) +if test x"$samba_cv_HAVE_IFACE_AIX" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available]) +fi + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifconf],samba_cv_HAVE_IFACE_IFCONF,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFCONF 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/netif/netif.c"], + samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)]) +if test x"$samba_cv_HAVE_IFACE_IFCONF" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available]) +fi +fi + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifreq],samba_cv_HAVE_IFACE_IFREQ,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFREQ 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/netif/netif.c"], + samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)]) +if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available]) +fi +fi diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 new file mode 100644 index 0000000000..8c85663d3b --- /dev/null +++ b/source4/lib/replace/config.m4 @@ -0,0 +1,16 @@ +AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ +AC_TRY_RUN([ +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +main() { struct in_addr ip; ip.s_addr = 0x12345678; +if (strcmp(inet_ntoa(ip),"18.52.86.120") && + strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } +exit(1);}], + samba_cv_REPLACE_INET_NTOA=yes,samba_cv_REPLACE_INET_NTOA=no,samba_cv_REPLACE_INET_NTOA=cross)]) +if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then + AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) +fi diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index b301c6060c..786d6c72bc 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,3 +1,92 @@ +AC_CHECK_HEADERS(sys/socket.h sys/sockio.h sys/un.h) + +AC_CACHE_CHECK([for socklen_t type],samba_cv_socklen_t, [ + AC_TRY_COMPILE([ +#include +#if STDC_HEADERS +#include +#include +#endif +#include ],[socklen_t i = 0], + samba_cv_socklen_t=yes,samba_cv_socklen_t=no)]) +if test x"$samba_cv_socklen_t" = x"yes"; then + AC_DEFINE(HAVE_SOCKLEN_T_TYPE,1,[Whether we have the variable type socklen_t]) +fi + +AC_CACHE_CHECK([for sin_len in sock],samba_cv_HAVE_SOCK_SIN_LEN,[ +AC_TRY_COMPILE([#include +#include +#include ], +[struct sockaddr_in sock; sock.sin_len = sizeof(sock);], +samba_cv_HAVE_SOCK_SIN_LEN=yes,samba_cv_HAVE_SOCK_SIN_LEN=no)]) +if test x"$samba_cv_HAVE_SOCK_SIN_LEN" = x"yes"; then + AC_DEFINE(HAVE_SOCK_SIN_LEN,1,[Whether the sockaddr_in struct has a sin_len property]) +fi + +# The following test taken from the cvs sources +# If we can't find connect, try looking in -lsocket, -lnsl, and -linet. +# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has +# libsocket.so which has a bad implementation of gethostbyname (it +# only looks in /etc/hosts), so we only look for -lsocket if we need +# it. +AC_CHECK_FUNCS(connect) +if test x"$ac_cv_func_connect" = x"no"; then + case "$LIBS $SOCKET_LIBS" in + *-lnsl*) ;; + *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, printf) ;; + esac + case "$LIBS $SOCKET_LIBS" in + *-lnsl*) ;; + *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, printf) ;; + esac + case "$LIBS $SOCKET_LIBS" in + *-lsocket*) ;; + *) AC_CHECK_LIB_EXT(socket, SOCKET_LIBS, connect) ;; + esac + case "$LIBS $SOCKET_LIBS" in + *-linet*) ;; + *) AC_CHECK_LIB_EXT(inet, SOCKET_LIBS, connect) ;; + esac + dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value + dnl has been cached. + if test x"$ac_cv_lib_ext_socket_connect" = x"yes" || + test x"$ac_cv_lib_ext_inet_connect" = x"yes"; then + # ac_cv_func_connect=yes + # don't! it would cause AC_CHECK_FUNC to succeed next time configure is run + AC_DEFINE(HAVE_CONNECT,1,[Whether the system has connect()]) + fi +fi +SMB_EXT_LIB(SOCKET,[${SOCKET_LIBS}],[${SOCKET_CFLAGS}],[${SOCKET_CPPFLAGS}],[${SOCKET_LDFLAGS}]) + +############################################ +# check for unix domain sockets +AC_CACHE_CHECK([for unix domain sockets],samba_cv_unixsocket, [ + AC_TRY_COMPILE([ +#include +#include +#include +#include +#include ], +[ + struct sockaddr_un sunaddr; + sunaddr.sun_family = AF_UNIX; +], + samba_cv_unixsocket=yes,samba_cv_unixsocket=no)]) +SMB_MODULE_DEFAULT(socket_unix, NOT) +if test x"$samba_cv_unixsocket" = x"yes"; then + SMB_MODULE_DEFAULT(socket_unix, STATIC) + AC_DEFINE(HAVE_UNIXSOCKET,1,[If we need to build with unixscoket support]) +fi + +AC_CACHE_CHECK([for AF_LOCAL socket support], samba_cv_HAVE_WORKING_AF_LOCAL, [ +AC_TRY_RUN([#include "${srcdir-.}/build/tests/unixsock.c"], + samba_cv_HAVE_WORKING_AF_LOCAL=yes, + samba_cv_HAVE_WORKING_AF_LOCAL=no, + samba_cv_HAVE_WORKING_AF_LOCAL=cross)]) +if test x"$samba_cv_HAVE_WORKING_AF_LOCAL" != xno +then + AC_DEFINE(HAVE_WORKING_AF_LOCAL, 1, [Define if you have working AF_LOCAL sockets]) +fi dnl test for ipv6 using the gethostbyname2() function. That should be sufficient dnl for now @@ -7,6 +96,5 @@ if $have_ipv6 = true; then SMB_MODULE_DEFAULT(socket_ipv6, STATIC) AC_DEFINE(HAVE_SOCKET_IPV6,1,[Whether the system has ipv6 support]) fi - dnl don't build ipv6 by default, unless the above test enables it, or dnl the configure uses --with-static-modules=socket_ipv6 diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index 13fe584373..e007b01725 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -6,6 +6,7 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv4.o NOPROTO=YES +REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_ipv4 ################################################ @@ -16,6 +17,7 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv6.o NOPROTO=YES +REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_ipv6 ################################################ @@ -26,6 +28,7 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_unix.o NOPROTO=YES +REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_unix ################################################ -- cgit From 6243e2a30414ef059fe2fd3636563269f4b12d06 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Aug 2005 23:56:18 +0000 Subject: r9078: - move charset stuff to lib/charset - don't use the global $LIBS variable for -liconv as $LIBS is not used anymore should fix the build on solaris 10 metze (This used to be commit 69ade058fde8e4cc62e4830c0b080e720d8e581d) --- source4/lib/charcnv.c | 723 ------------------------------------------ source4/lib/charset/charcnv.c | 723 ++++++++++++++++++++++++++++++++++++++++++ source4/lib/charset/config.m4 | 65 ++++ source4/lib/charset/config.mk | 10 + source4/lib/charset/iconv.c | 693 ++++++++++++++++++++++++++++++++++++++++ source4/lib/iconv.c | 693 ---------------------------------------- source4/lib/iconv.m4 | 66 ---- 7 files changed, 1491 insertions(+), 1482 deletions(-) delete mode 100644 source4/lib/charcnv.c create mode 100644 source4/lib/charset/charcnv.c create mode 100644 source4/lib/charset/config.m4 create mode 100644 source4/lib/charset/config.mk create mode 100644 source4/lib/charset/iconv.c delete mode 100644 source4/lib/iconv.c delete mode 100644 source4/lib/iconv.m4 (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c deleted file mode 100644 index e632790155..0000000000 --- a/source4/lib/charcnv.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Character set conversion Extensions - Copyright (C) Igor Vergeichik 2001 - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Simo Sorce 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#include "includes.h" -#include "system/iconv.h" -#include "pstring.h" - -/** - * @file - * - * @brief Character-set conversion routines built on our iconv. - * - * @note Samba's internal character set (at least in the 3.0 series) - * is always the same as the one for the Unix filesystem. It is - * not necessarily UTF-8 and may be different on machines that - * need i18n filenames to be compatible with Unix software. It does - * have to be a superset of ASCII. All multibyte sequences must start - * with a byte with the high bit set. - * - * @sa lib/iconv.c - */ - -/** - * Return the name of a charset to give to iconv(). - **/ -static const char *charset_name(charset_t ch) -{ - const char *ret = NULL; - - if (ch == CH_UTF16) ret = "UTF-16LE"; - else if (ch == CH_UNIX) ret = lp_unix_charset(); - else if (ch == CH_DOS) ret = lp_dos_charset(); - else if (ch == CH_DISPLAY) ret = lp_display_charset(); - else if (ch == CH_UTF8) ret = "UTF8"; - else if (ch == CH_UTF16BE) ret = "UTF-16BE"; - - if (!ret || !*ret) ret = "ASCII"; - return ret; -} - -static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - -/** - re-initialize iconv conversion descriptors -**/ -void init_iconv(void) -{ - charset_t c1, c2; - for (c1=0;c1 - *
STR_TERMINATE
means include the null termination
- *
STR_UPPER
means uppercase in the destination
- * - * - * @param dest_len the maximum length in bytes allowed in the - * destination. If @p dest_len is -1 then no maximum is used. - **/ -ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) -{ - size_t src_len; - ssize_t ret; - - if (flags & STR_UPPER) { - char *tmpbuf = strupper_talloc(NULL, src); - if (tmpbuf == NULL) { - return -1; - } - ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER); - talloc_free(tmpbuf); - return ret; - } - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - src_len = strlen(src); - - if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) - src_len++; - - return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); -} - -/** - * Copy a string from a unix char* src to an ASCII destination, - * allocating a buffer using talloc(). - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - * or -1 in case of error. - **/ -ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); -} - - -/** - * Copy a string from a dos codepage source to a unix char* destination. - * - * The resulting string in "dest" is always null terminated. - * - * @param flags can have: - *
- *
STR_TERMINATE
- *
STR_TERMINATE means the string in @p src - * is null terminated, and src_len is ignored.
- *
- * - * @param src_len is the length of the source area in bytes. - * @returns the number of bytes occupied by the string in @p src. - **/ -ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - size_t ret; - - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { - if (src_len == (size_t)-1) { - src_len = strlen(src) + 1; - } else { - size_t len = strnlen(src, src_len); - if (len < src_len) - len++; - src_len = len; - } - } - - ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); - - if (dest_len) - dest[MIN(ret, dest_len-1)] = 0; - - return src_len; -} - -/** - * Copy a string from a char* src to a unicode destination. - * - * @returns the number of bytes occupied by the string in the destination. - * - * @param flags can have: - * - *
- *
STR_TERMINATE
means include the null termination. - *
STR_UPPER
means uppercase in the destination. - *
STR_NOALIGN
means don't do alignment. - *
- * - * @param dest_len is the maximum length allowed in the - * destination. If dest_len is -1 then no maxiumum is used. - **/ -ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) -{ - size_t len=0; - size_t src_len = strlen(src); - size_t ret; - - if (flags & STR_UPPER) { - char *tmpbuf = strupper_talloc(NULL, src); - if (tmpbuf == NULL) { - return -1; - } - ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); - talloc_free(tmpbuf); - return ret; - } - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & STR_TERMINATE) - src_len++; - - if (ucs2_align(NULL, dest, flags)) { - *(char *)dest = 0; - dest = (void *)((char *)dest + 1); - if (dest_len) dest_len--; - len++; - } - - /* ucs2 is always a multiple of 2 bytes */ - dest_len &= ~1; - - ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); - if (ret == (size_t)-1) { - return 0; - } - - len += ret; - - return len; -} - - -/** - * Copy a string from a unix char* src to a UCS2 destination, - * allocating a buffer using talloc(). - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - * or -1 in case of error. - **/ -ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); -} - - -/** - * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); -} - -/** - Copy a string from a ucs2 source to a unix char* destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - STR_NOALIGN means don't try to align. - if STR_TERMINATE is set then src_len is ignored if it is -1. - src_len is the length of the source area in bytes - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - size_t ret; - - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (ucs2_align(NULL, src, flags)) { - src = (const void *)((const char *)src + 1); - if (src_len > 0) - src_len--; - } - - if (flags & STR_TERMINATE) { - if (src_len == (size_t)-1) { - src_len = utf16_len(src); - } else { - src_len = utf16_len_n(src, src_len); - } - } - - /* ucs2 is always a multiple of 2 bytes */ - if (src_len != (size_t)-1) - src_len &= ~1; - - ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len); - if (dest_len) - dest[MIN(ret, dest_len-1)] = 0; - - return src_len; -} - -/** - * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) -{ - size_t src_len = utf16_len(src); - *dest = NULL; - return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); -} - -/** - * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); -} - -/** - Copy a string from a char* src to a unicode or ascii - dos codepage destination choosing unicode or ascii based on the - flags in the SMB buffer starting at base_ptr. - Return the number of bytes occupied by the string in the destination. - flags can have: - STR_TERMINATE means include the null termination. - STR_UPPER means uppercase in the destination. - STR_ASCII use ascii even with unicode packet. - STR_NOALIGN means don't do alignment. - dest_len is the maximum length allowed in the destination. If dest_len - is -1 then no maxiumum is used. -**/ - -ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) -{ - if (flags & STR_ASCII) { - return push_ascii(dest, src, dest_len, flags); - } else if (flags & STR_UNICODE) { - return push_ucs2(dest, src, dest_len, flags); - } else { - smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); - return -1; - } -} - - -/** - Copy a string from a unicode or ascii source (depending on - the packet flags) to a char* destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - STR_UNICODE means to force as unicode. - STR_ASCII use ascii even with unicode packet. - STR_NOALIGN means don't do alignment. - if STR_TERMINATE is set then src_len is ignored is it is -1 - src_len is the length of the source area in bytes. - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - if (flags & STR_ASCII) { - return pull_ascii(dest, src, dest_len, src_len, flags); - } else if (flags & STR_UNICODE) { - return pull_ucs2(dest, src, dest_len, src_len, flags); - } else { - smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); - return -1; - } -} - - -/* - return the unicode codepoint for the next multi-byte CH_UNIX character - in the string - - also return the number of bytes consumed (which tells the caller - how many bytes to skip to get to the next CH_UNIX character) - - return INVALID_CODEPOINT if the next character cannot be converted -*/ -codepoint_t next_codepoint(const char *str, size_t *size) -{ - /* it cannot occupy more than 4 bytes in UTF16 format */ - uint8_t buf[4]; - smb_iconv_t descriptor; - size_t ilen_orig; - size_t ilen; - size_t olen; - char *outbuf; - - if ((str[0] & 0x80) == 0) { - *size = 1; - return (codepoint_t)str[0]; - } - - /* we assume that no multi-byte character can take - more than 5 bytes. This is OK as we only - support codepoints up to 1M */ - ilen_orig = strnlen(str, 5); - ilen = ilen_orig; - - descriptor = get_conv_handle(CH_UNIX, CH_UTF16); - if (descriptor == (smb_iconv_t)-1) { - *size = 1; - return INVALID_CODEPOINT; - } - - /* this looks a little strange, but it is needed to cope - with codepoints above 64k */ - olen = 2; - outbuf = buf; - smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); - if (olen == 2) { - olen = 4; - outbuf = buf; - smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); - if (olen == 4) { - /* we didn't convert any bytes */ - *size = 1; - return INVALID_CODEPOINT; - } - olen = 4 - olen; - } else { - olen = 2 - olen; - } - - *size = ilen_orig - ilen; - - if (olen == 2) { - return (codepoint_t)SVAL(buf, 0); - } - if (olen == 4) { - /* decode a 4 byte UTF16 character manually */ - return (codepoint_t)0x10000 + - (buf[2] | ((buf[3] & 0x3)<<8) | - (buf[0]<<10) | ((buf[1] & 0x3)<<18)); - } - - /* no other length is valid */ - return INVALID_CODEPOINT; -} - -/* - push a single codepoint into a CH_UNIX string the target string must - be able to hold the full character, which is guaranteed if it is at - least 5 bytes in size. The caller may pass less than 5 bytes if they - are sure the character will fit (for example, you can assume that - uppercase/lowercase of a character will not add more than 1 byte) - - return the number of bytes occupied by the CH_UNIX character, or - -1 on failure -*/ -ssize_t push_codepoint(char *str, codepoint_t c) -{ - smb_iconv_t descriptor; - uint8_t buf[4]; - size_t ilen, olen; - const char *inbuf; - - if (c < 128) { - *str = c; - return 1; - } - - descriptor = get_conv_handle(CH_UTF16, CH_UNIX); - if (descriptor == (smb_iconv_t)-1) { - return -1; - } - - if (c < 0x10000) { - ilen = 2; - olen = 5; - inbuf = buf; - SSVAL(buf, 0, c); - smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); - if (ilen != 0) { - return -1; - } - return 5 - olen; - } - - c -= 0x10000; - - buf[0] = (c>>10) & 0xFF; - buf[1] = (c>>18) | 0xd8; - buf[2] = c & 0xFF; - buf[3] = ((c>>8) & 0x3) | 0xdc; - - ilen = 4; - olen = 5; - inbuf = buf; - - smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); - if (ilen != 0) { - return -1; - } - return 5 - olen; -} diff --git a/source4/lib/charset/charcnv.c b/source4/lib/charset/charcnv.c new file mode 100644 index 0000000000..e632790155 --- /dev/null +++ b/source4/lib/charset/charcnv.c @@ -0,0 +1,723 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include "includes.h" +#include "system/iconv.h" +#include "pstring.h" + +/** + * @file + * + * @brief Character-set conversion routines built on our iconv. + * + * @note Samba's internal character set (at least in the 3.0 series) + * is always the same as the one for the Unix filesystem. It is + * not necessarily UTF-8 and may be different on machines that + * need i18n filenames to be compatible with Unix software. It does + * have to be a superset of ASCII. All multibyte sequences must start + * with a byte with the high bit set. + * + * @sa lib/iconv.c + */ + +/** + * Return the name of a charset to give to iconv(). + **/ +static const char *charset_name(charset_t ch) +{ + const char *ret = NULL; + + if (ch == CH_UTF16) ret = "UTF-16LE"; + else if (ch == CH_UNIX) ret = lp_unix_charset(); + else if (ch == CH_DOS) ret = lp_dos_charset(); + else if (ch == CH_DISPLAY) ret = lp_display_charset(); + else if (ch == CH_UTF8) ret = "UTF8"; + else if (ch == CH_UTF16BE) ret = "UTF-16BE"; + + if (!ret || !*ret) ret = "ASCII"; + return ret; +} + +static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; + +/** + re-initialize iconv conversion descriptors +**/ +void init_iconv(void) +{ + charset_t c1, c2; + for (c1=0;c1 + *
STR_TERMINATE
means include the null termination
+ *
STR_UPPER
means uppercase in the destination
+ * + * + * @param dest_len the maximum length in bytes allowed in the + * destination. If @p dest_len is -1 then no maximum is used. + **/ +ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t src_len; + ssize_t ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return -1; + } + ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; + } + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + src_len = strlen(src); + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) + src_len++; + + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); +} + +/** + * Copy a string from a unix char* src to an ASCII destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); +} + + +/** + * Copy a string from a dos codepage source to a unix char* destination. + * + * The resulting string in "dest" is always null terminated. + * + * @param flags can have: + *
+ *
STR_TERMINATE
+ *
STR_TERMINATE means the string in @p src + * is null terminated, and src_len is ignored.
+ *
+ * + * @param src_len is the length of the source area in bytes. + * @returns the number of bytes occupied by the string in @p src. + **/ +ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { + if (src_len == (size_t)-1) { + src_len = strlen(src) + 1; + } else { + size_t len = strnlen(src, src_len); + if (len < src_len) + len++; + src_len = len; + } + } + + ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); + + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +/** + * Copy a string from a char* src to a unicode destination. + * + * @returns the number of bytes occupied by the string in the destination. + * + * @param flags can have: + * + *
+ *
STR_TERMINATE
means include the null termination. + *
STR_UPPER
means uppercase in the destination. + *
STR_NOALIGN
means don't do alignment. + *
+ * + * @param dest_len is the maximum length allowed in the + * destination. If dest_len is -1 then no maxiumum is used. + **/ +ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t len=0; + size_t src_len = strlen(src); + size_t ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return -1; + } + ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; + } + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_TERMINATE) + src_len++; + + if (ucs2_align(NULL, dest, flags)) { + *(char *)dest = 0; + dest = (void *)((char *)dest + 1); + if (dest_len) dest_len--; + len++; + } + + /* ucs2 is always a multiple of 2 bytes */ + dest_len &= ~1; + + ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); + if (ret == (size_t)-1) { + return 0; + } + + len += ret; + + return len; +} + + +/** + * Copy a string from a unix char* src to a UCS2 destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); +} + + +/** + * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); +} + +/** + Copy a string from a ucs2 source to a unix char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_NOALIGN means don't try to align. + if STR_TERMINATE is set then src_len is ignored if it is -1. + src_len is the length of the source area in bytes + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (ucs2_align(NULL, src, flags)) { + src = (const void *)((const char *)src + 1); + if (src_len > 0) + src_len--; + } + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = utf16_len(src); + } else { + src_len = utf16_len_n(src, src_len); + } + } + + /* ucs2 is always a multiple of 2 bytes */ + if (src_len != (size_t)-1) + src_len &= ~1; + + ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len); + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +/** + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) +{ + size_t src_len = utf16_len(src); + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); +} + +/** + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); +} + +/** + Copy a string from a char* src to a unicode or ascii + dos codepage destination choosing unicode or ascii based on the + flags in the SMB buffer starting at base_ptr. + Return the number of bytes occupied by the string in the destination. + flags can have: + STR_TERMINATE means include the null termination. + STR_UPPER means uppercase in the destination. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maxiumum is used. +**/ + +ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) +{ + if (flags & STR_ASCII) { + return push_ascii(dest, src, dest_len, flags); + } else if (flags & STR_UNICODE) { + return push_ucs2(dest, src, dest_len, flags); + } else { + smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} + + +/** + Copy a string from a unicode or ascii source (depending on + the packet flags) to a char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_UNICODE means to force as unicode. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + if STR_TERMINATE is set then src_len is ignored is it is -1 + src_len is the length of the source area in bytes. + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + if (flags & STR_ASCII) { + return pull_ascii(dest, src, dest_len, src_len, flags); + } else if (flags & STR_UNICODE) { + return pull_ucs2(dest, src, dest_len, src_len, flags); + } else { + smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} + + +/* + return the unicode codepoint for the next multi-byte CH_UNIX character + in the string + + also return the number of bytes consumed (which tells the caller + how many bytes to skip to get to the next CH_UNIX character) + + return INVALID_CODEPOINT if the next character cannot be converted +*/ +codepoint_t next_codepoint(const char *str, size_t *size) +{ + /* it cannot occupy more than 4 bytes in UTF16 format */ + uint8_t buf[4]; + smb_iconv_t descriptor; + size_t ilen_orig; + size_t ilen; + size_t olen; + char *outbuf; + + if ((str[0] & 0x80) == 0) { + *size = 1; + return (codepoint_t)str[0]; + } + + /* we assume that no multi-byte character can take + more than 5 bytes. This is OK as we only + support codepoints up to 1M */ + ilen_orig = strnlen(str, 5); + ilen = ilen_orig; + + descriptor = get_conv_handle(CH_UNIX, CH_UTF16); + if (descriptor == (smb_iconv_t)-1) { + *size = 1; + return INVALID_CODEPOINT; + } + + /* this looks a little strange, but it is needed to cope + with codepoints above 64k */ + olen = 2; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 2) { + olen = 4; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 4) { + /* we didn't convert any bytes */ + *size = 1; + return INVALID_CODEPOINT; + } + olen = 4 - olen; + } else { + olen = 2 - olen; + } + + *size = ilen_orig - ilen; + + if (olen == 2) { + return (codepoint_t)SVAL(buf, 0); + } + if (olen == 4) { + /* decode a 4 byte UTF16 character manually */ + return (codepoint_t)0x10000 + + (buf[2] | ((buf[3] & 0x3)<<8) | + (buf[0]<<10) | ((buf[1] & 0x3)<<18)); + } + + /* no other length is valid */ + return INVALID_CODEPOINT; +} + +/* + push a single codepoint into a CH_UNIX string the target string must + be able to hold the full character, which is guaranteed if it is at + least 5 bytes in size. The caller may pass less than 5 bytes if they + are sure the character will fit (for example, you can assume that + uppercase/lowercase of a character will not add more than 1 byte) + + return the number of bytes occupied by the CH_UNIX character, or + -1 on failure +*/ +ssize_t push_codepoint(char *str, codepoint_t c) +{ + smb_iconv_t descriptor; + uint8_t buf[4]; + size_t ilen, olen; + const char *inbuf; + + if (c < 128) { + *str = c; + return 1; + } + + descriptor = get_conv_handle(CH_UTF16, CH_UNIX); + if (descriptor == (smb_iconv_t)-1) { + return -1; + } + + if (c < 0x10000) { + ilen = 2; + olen = 5; + inbuf = buf; + SSVAL(buf, 0, c); + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; + } + + c -= 0x10000; + + buf[0] = (c>>10) & 0xFF; + buf[1] = (c>>18) | 0xd8; + buf[2] = c & 0xFF; + buf[3] = ((c>>8) & 0x3) | 0xdc; + + ilen = 4; + olen = 5; + inbuf = buf; + + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; +} diff --git a/source4/lib/charset/config.m4 b/source4/lib/charset/config.m4 new file mode 100644 index 0000000000..9812c356ff --- /dev/null +++ b/source4/lib/charset/config.m4 @@ -0,0 +1,65 @@ +dnl # ICONV/CHARSET subsystem + +ICONV_LOCATION=standard +LOOK_DIRS="/usr /usr/local /sw" +AC_ARG_WITH(libiconv, +[ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], +[ + if test "$withval" = "no" ; then + AC_MSG_ERROR(I won't take no for an answer) + else + if test "$withval" != "yes" ; then + LOOK_DIRS="$withval $LOOK_DIRS" + fi + fi +]) + +ICONV_FOUND="no" +for i in $LOOK_DIRS ; do + save_LIBS=$LIBS + save_LDFLAGS=$LDFLAGS + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="-I$i/include" + LDFLAGS="-L$i/lib" + LIBS= + export LDFLAGS LIBS CPPFLAGS +dnl Try to find iconv(3) + jm_ICONV($i) + + TMP_ICONV_LIBS="$LIBS" + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + export LDFLAGS LIBS CPPFLAGS + + if test -n "$ICONV_FOUND" ; then + LIB_ADD_DIR(ICONV_LDFLAGS, $i/lib) + CFLAGS_ADD_DIR(ICONV_CPPFLAGS, $i/include) + ICONV_LIBS="$TMP_ICONV_LIBS" + break + fi +done + +############ +# check for iconv in libc +AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ +AC_TRY_RUN([ +#include +main() { + iconv_t cd = iconv_open("ASCII", "UCS-2LE"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} +], +samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) +if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then + AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) +fi + +if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then + AC_MSG_WARN([Sufficient support for iconv function was not found. + Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) +fi + +SMB_EXT_LIB(ICONV,[${ICONV_LIBS}],[${ICONV_CFLAGS}],[${ICONV_CPPFLAGS}],[${ICONV_LDFLAGS}]) diff --git a/source4/lib/charset/config.mk b/source4/lib/charset/config.mk new file mode 100644 index 0000000000..6b0fe02b72 --- /dev/null +++ b/source4/lib/charset/config.mk @@ -0,0 +1,10 @@ +################################################ +# Start SUBSYSTEM CHARSET +[SUBSYSTEM::CHARSET] +INIT_OBJ_FILES = \ + lib/charset/iconv.o +ADD_OBJ_FILES = \ + lib/charset/charcnv.o +REQUIRED_SUBSYSTEMS = EXT_LIB_ICONV +# End SUBSYSTEM CHARSET +################################################ diff --git a/source4/lib/charset/iconv.c b/source4/lib/charset/iconv.c new file mode 100644 index 0000000000..df590444e5 --- /dev/null +++ b/source4/lib/charset/iconv.c @@ -0,0 +1,693 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "system/iconv.h" +#include "system/filesys.h" + + +/** + * @file + * + * @brief Samba wrapper/stub for iconv character set conversion. + * + * iconv is the XPG2 interface for converting between character + * encodings. This file provides a Samba wrapper around it, and also + * a simple reimplementation that is used if the system does not + * implement iconv. + * + * Samba only works with encodings that are supersets of ASCII: ascii + * characters like whitespace can be tested for directly, multibyte + * sequences start with a byte with the high bit set, and strings are + * terminated by a nul byte. + * + * Note that the only function provided by iconv is conversion between + * characters. It doesn't directly support operations like + * uppercasing or comparison. We have to convert to UTF-16LE and + * compare there. + * + * @sa Samba Developers Guide + **/ + +static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); +static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); +static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); +static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); +static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); + +static const struct charset_functions builtin_functions[] = { + /* windows is closest to UTF-16 */ + {"UCS-2LE", iconv_copy, iconv_copy}, + {"UTF-16LE", iconv_copy, iconv_copy}, + {"UCS-2BE", iconv_swab, iconv_swab}, + {"UTF-16BE", iconv_swab, iconv_swab}, + + /* we include the UTF-8 alias to cope with differing locale settings */ + {"UTF8", utf8_pull, utf8_push}, + {"UTF-8", utf8_pull, utf8_push}, + {"ASCII", ascii_pull, ascii_push}, + {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} +}; + +static struct charset_functions *charsets = NULL; + +NTSTATUS charset_register_backend(const void *_funcs) +{ + struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); + struct charset_functions *c = charsets; + + /* Check whether we already have this charset... */ + while(c) { + if(!strcasecmp(c->name, funcs->name)){ + DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + c = c->next; + } + + funcs->next = funcs->prev = NULL; + DLIST_ADD(charsets, funcs); + return NT_STATUS_OK; +} + +#ifdef HAVE_NATIVE_ICONV +/* if there was an error then reset the internal state, + this ensures that we don't have a shift state remaining for + character sets like SJIS */ +static size_t sys_iconv(void *cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t ret = iconv((iconv_t)cd, + discard_const_p(char *, inbuf), inbytesleft, + outbuf, outbytesleft); + if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); + return ret; +} +#endif + +/** + * This is a simple portable iconv() implementaion. + * + * It only knows about a very small number of character sets - just + * enough that Samba works on systems that don't have iconv. + **/ +size_t smb_iconv(smb_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + char cvtbuf[2048]; + size_t bufsize; + + /* in many cases we can go direct */ + if (cd->direct) { + return cd->direct(cd->cd_direct, + inbuf, inbytesleft, outbuf, outbytesleft); + } + + + /* otherwise we have to do it chunks at a time */ + while (*inbytesleft > 0) { + char *bufp1 = cvtbuf; + const char *bufp2 = cvtbuf; + + bufsize = sizeof(cvtbuf); + + if (cd->pull(cd->cd_pull, + inbuf, inbytesleft, &bufp1, &bufsize) == -1 + && errno != E2BIG) return -1; + + bufsize = sizeof(cvtbuf) - bufsize; + + if (cd->push(cd->cd_push, + &bufp2, &bufsize, + outbuf, outbytesleft) == -1) return -1; + } + + return 0; +} + +static BOOL is_utf16(const char *name) +{ + return strcasecmp(name, "UCS-2LE") == 0 || + strcasecmp(name, "UTF-16LE") == 0; +} + +/* + simple iconv_open() wrapper + */ +smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) +{ + smb_iconv_t ret; + const struct charset_functions *from=NULL, *to=NULL; + int i; + + ret = (smb_iconv_t)talloc_named(NULL, sizeof(*ret), + "iconv(%s,%s)", tocode, fromcode); + if (!ret) { + errno = ENOMEM; + return (smb_iconv_t)-1; + } + memset(ret, 0, sizeof(*ret)); + + /* check for the simplest null conversion */ + if (strcmp(fromcode, tocode) == 0) { + ret->direct = iconv_copy; + return ret; + } + + for (i=0;inext) { + if (strcasecmp(from->name, fromcode) == 0) break; + } + } + + if (to == NULL) { + for (to=charsets; to; to=to->next) { + if (strcasecmp(to->name, tocode) == 0) break; + } + } + +#ifdef HAVE_NATIVE_ICONV + if (!from) { + ret->pull = sys_iconv; + ret->cd_pull = iconv_open("UTF-16LE", fromcode); + if (ret->cd_pull == (iconv_t)-1) + ret->cd_pull = iconv_open("UCS-2LE", fromcode); + if (ret->cd_pull == (iconv_t)-1) goto failed; + } + + if (!to) { + ret->push = sys_iconv; + ret->cd_push = iconv_open(tocode, "UTF-16LE"); + if (ret->cd_push == (iconv_t)-1) + ret->cd_push = iconv_open(tocode, "UCS-2LE"); + if (ret->cd_push == (iconv_t)-1) goto failed; + } +#else + if (!from || !to) { + goto failed; + } +#endif + + /* check for conversion to/from ucs2 */ + if (is_utf16(fromcode) && to) { + ret->direct = to->push; + return ret; + } + if (is_utf16(tocode) && from) { + ret->direct = from->pull; + return ret; + } + +#ifdef HAVE_NATIVE_ICONV + if (is_utf16(fromcode)) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_push; + ret->cd_push = NULL; + return ret; + } + if (is_utf16(tocode)) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_pull; + ret->cd_pull = NULL; + return ret; + } +#endif + + /* the general case has to go via a buffer */ + if (!ret->pull) ret->pull = from->pull; + if (!ret->push) ret->push = to->push; + return ret; + +failed: + talloc_free(ret); + errno = EINVAL; + return (smb_iconv_t)-1; +} + +/* + simple iconv_close() wrapper +*/ +int smb_iconv_close(smb_iconv_t cd) +{ +#ifdef HAVE_NATIVE_ICONV + if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); + if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull); + if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); +#endif + + talloc_free(cd); + return 0; +} + + +/********************************************************************** + the following functions implement the builtin character sets in Samba + and also the "test" character sets that are designed to test + multi-byte character set support for english users +***********************************************************************/ +static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + (*outbuf)[0] = (*inbuf)[0] & 0x7F; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + + +static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + uint_t v; + + if ((*inbuf)[0] != '@') { + /* seven bit ascii case */ + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + continue; + } + /* it's a hex character */ + if (*inbytesleft < 5) { + errno = EINVAL; + return -1; + } + + if (sscanf(&(*inbuf)[1], "%04x", &v) != 1) { + errno = EILSEQ; + return -1; + } + + (*outbuf)[0] = v&0xff; + (*outbuf)[1] = v>>8; + (*inbytesleft) -= 5; + (*outbytesleft) -= 2; + (*inbuf) += 5; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + char buf[6]; + + if ((*inbuf)[1] == 0 && + ((*inbuf)[0] & 0x80) == 0 && + (*inbuf)[0] != '@') { + (*outbuf)[0] = (*inbuf)[0]; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + continue; + } + if (*outbytesleft < 5) { + errno = E2BIG; + return -1; + } + snprintf(buf, 6, "@%04x", SVAL(*inbuf, 0)); + memcpy(*outbuf, buf, 5); + (*inbytesleft) -= 2; + (*outbytesleft) -= 5; + (*inbuf) += 2; + (*outbuf) += 5; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + swab(*inbuf, *outbuf, (n&~1)); + if (n&1) { + (*outbuf)[n-1] = 0; + } + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + + +static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + memmove(*outbuf, *inbuf, n); + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t in_left=*inbytesleft, out_left=*outbytesleft; + const uint8_t *c = (const uint8_t *)*inbuf; + uint8_t *uc = (uint8_t *)*outbuf; + + while (in_left >= 1 && out_left >= 2) { + if ((c[0] & 0x80) == 0) { + uc[0] = c[0]; + uc[1] = 0; + c += 1; + in_left -= 1; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xe0) == 0xc0) { + if (in_left < 2 || + (c[1] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + uc[1] = (c[0]>>2) & 0x7; + uc[0] = (c[0]<<6) | (c[1]&0x3f); + c += 2; + in_left -= 2; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf0) == 0xe0) { + if (in_left < 3 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); + uc[0] = (c[1]<<6) | (c[2]&0x3f); + c += 3; + in_left -= 3; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf8) == 0xf0) { + unsigned int codepoint; + if (in_left < 4 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80 || + (c[3] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + codepoint = + (c[3]&0x3f) | + ((c[2]&0x3f)<<6) | + ((c[1]&0x3f)<<12) | + ((c[0]&0x7)<<18); + if (codepoint < 0x10000) { + /* accept UTF-8 characters that are not + minimally packed, but pack the result */ + uc[0] = (codepoint & 0xFF); + uc[1] = (codepoint >> 8); + c += 4; + in_left -= 4; + out_left -= 2; + uc += 2; + continue; + } + + codepoint -= 0x10000; + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + + uc[0] = (codepoint>>10) & 0xFF; + uc[1] = (codepoint>>18) | 0xd8; + uc[2] = codepoint & 0xFF; + uc[3] = ((codepoint>>8) & 0x3) | 0xdc; + c += 4; + in_left -= 4; + out_left -= 4; + uc += 4; + continue; + } + + /* we don't handle 5 byte sequences */ + errno = EINVAL; + goto error; + } + + if (in_left > 0) { + errno = E2BIG; + goto error; + } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = c; + *outbuf = uc; + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = c; + *outbuf = uc; + return -1; +} + +static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t in_left=*inbytesleft, out_left=*outbytesleft; + uint8_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*inbuf; + + while (in_left >= 2 && out_left >= 1) { + unsigned int codepoint; + + if (uc[1] == 0 && !(uc[0] & 0x80)) { + /* simplest case */ + c[0] = uc[0]; + in_left -= 2; + out_left -= 1; + uc += 2; + c += 1; + continue; + } + + if ((uc[1]&0xf8) == 0) { + /* next simplest case */ + if (out_left < 2) { + errno = E2BIG; + goto error; + } + c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2); + c[1] = 0x80 | (uc[0] & 0x3f); + in_left -= 2; + out_left -= 2; + uc += 2; + c += 2; + continue; + } + + if ((uc[1] & 0xfc) == 0xdc) { + /* its the second part of a 4 byte sequence. Illegal */ + if (in_left < 4) { + errno = EINVAL; + } else { + errno = EILSEQ; + } + goto error; + } + + if ((uc[1] & 0xfc) != 0xd8) { + codepoint = uc[0] | (uc[1]<<8); + if (out_left < 3) { + errno = E2BIG; + goto error; + } + c[0] = 0xe0 | (codepoint >> 12); + c[1] = 0x80 | ((codepoint >> 6) & 0x3f); + c[2] = 0x80 | (codepoint & 0x3f); + + in_left -= 2; + out_left -= 3; + uc += 2; + c += 3; + continue; + } + + /* its the first part of a 4 byte sequence */ + if (in_left < 4) { + errno = EINVAL; + goto error; + } + if ((uc[3] & 0xfc) != 0xdc) { + errno = EILSEQ; + goto error; + } + codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) | + (uc[0]<<10) | ((uc[1] & 0x3)<<18)); + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + c[0] = 0xf0 | (codepoint >> 18); + c[1] = 0x80 | ((codepoint >> 12) & 0x3f); + c[2] = 0x80 | ((codepoint >> 6) & 0x3f); + c[3] = 0x80 | (codepoint & 0x3f); + + in_left -= 4; + out_left -= 4; + uc += 4; + c += 4; + } + + if (in_left == 1) { + errno = EINVAL; + goto error; + } + + if (in_left > 1) { + errno = E2BIG; + goto error; + } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = uc; + *outbuf = c; + + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = uc; + *outbuf = c; + return -1; +} + + + diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c deleted file mode 100644 index df590444e5..0000000000 --- a/source4/lib/iconv.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - Unix SMB/CIFS implementation. - minimal iconv implementation - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jelmer Vernooij 2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "dlinklist.h" -#include "system/iconv.h" -#include "system/filesys.h" - - -/** - * @file - * - * @brief Samba wrapper/stub for iconv character set conversion. - * - * iconv is the XPG2 interface for converting between character - * encodings. This file provides a Samba wrapper around it, and also - * a simple reimplementation that is used if the system does not - * implement iconv. - * - * Samba only works with encodings that are supersets of ASCII: ascii - * characters like whitespace can be tested for directly, multibyte - * sequences start with a byte with the high bit set, and strings are - * terminated by a nul byte. - * - * Note that the only function provided by iconv is conversion between - * characters. It doesn't directly support operations like - * uppercasing or comparison. We have to convert to UTF-16LE and - * compare there. - * - * @sa Samba Developers Guide - **/ - -static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); -static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); -static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); -static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); -static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); -static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); -static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); -static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); - -static const struct charset_functions builtin_functions[] = { - /* windows is closest to UTF-16 */ - {"UCS-2LE", iconv_copy, iconv_copy}, - {"UTF-16LE", iconv_copy, iconv_copy}, - {"UCS-2BE", iconv_swab, iconv_swab}, - {"UTF-16BE", iconv_swab, iconv_swab}, - - /* we include the UTF-8 alias to cope with differing locale settings */ - {"UTF8", utf8_pull, utf8_push}, - {"UTF-8", utf8_pull, utf8_push}, - {"ASCII", ascii_pull, ascii_push}, - {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} -}; - -static struct charset_functions *charsets = NULL; - -NTSTATUS charset_register_backend(const void *_funcs) -{ - struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); - struct charset_functions *c = charsets; - - /* Check whether we already have this charset... */ - while(c) { - if(!strcasecmp(c->name, funcs->name)){ - DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - c = c->next; - } - - funcs->next = funcs->prev = NULL; - DLIST_ADD(charsets, funcs); - return NT_STATUS_OK; -} - -#ifdef HAVE_NATIVE_ICONV -/* if there was an error then reset the internal state, - this ensures that we don't have a shift state remaining for - character sets like SJIS */ -static size_t sys_iconv(void *cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t ret = iconv((iconv_t)cd, - discard_const_p(char *, inbuf), inbytesleft, - outbuf, outbytesleft); - if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); - return ret; -} -#endif - -/** - * This is a simple portable iconv() implementaion. - * - * It only knows about a very small number of character sets - just - * enough that Samba works on systems that don't have iconv. - **/ -size_t smb_iconv(smb_iconv_t cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - char cvtbuf[2048]; - size_t bufsize; - - /* in many cases we can go direct */ - if (cd->direct) { - return cd->direct(cd->cd_direct, - inbuf, inbytesleft, outbuf, outbytesleft); - } - - - /* otherwise we have to do it chunks at a time */ - while (*inbytesleft > 0) { - char *bufp1 = cvtbuf; - const char *bufp2 = cvtbuf; - - bufsize = sizeof(cvtbuf); - - if (cd->pull(cd->cd_pull, - inbuf, inbytesleft, &bufp1, &bufsize) == -1 - && errno != E2BIG) return -1; - - bufsize = sizeof(cvtbuf) - bufsize; - - if (cd->push(cd->cd_push, - &bufp2, &bufsize, - outbuf, outbytesleft) == -1) return -1; - } - - return 0; -} - -static BOOL is_utf16(const char *name) -{ - return strcasecmp(name, "UCS-2LE") == 0 || - strcasecmp(name, "UTF-16LE") == 0; -} - -/* - simple iconv_open() wrapper - */ -smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) -{ - smb_iconv_t ret; - const struct charset_functions *from=NULL, *to=NULL; - int i; - - ret = (smb_iconv_t)talloc_named(NULL, sizeof(*ret), - "iconv(%s,%s)", tocode, fromcode); - if (!ret) { - errno = ENOMEM; - return (smb_iconv_t)-1; - } - memset(ret, 0, sizeof(*ret)); - - /* check for the simplest null conversion */ - if (strcmp(fromcode, tocode) == 0) { - ret->direct = iconv_copy; - return ret; - } - - for (i=0;inext) { - if (strcasecmp(from->name, fromcode) == 0) break; - } - } - - if (to == NULL) { - for (to=charsets; to; to=to->next) { - if (strcasecmp(to->name, tocode) == 0) break; - } - } - -#ifdef HAVE_NATIVE_ICONV - if (!from) { - ret->pull = sys_iconv; - ret->cd_pull = iconv_open("UTF-16LE", fromcode); - if (ret->cd_pull == (iconv_t)-1) - ret->cd_pull = iconv_open("UCS-2LE", fromcode); - if (ret->cd_pull == (iconv_t)-1) goto failed; - } - - if (!to) { - ret->push = sys_iconv; - ret->cd_push = iconv_open(tocode, "UTF-16LE"); - if (ret->cd_push == (iconv_t)-1) - ret->cd_push = iconv_open(tocode, "UCS-2LE"); - if (ret->cd_push == (iconv_t)-1) goto failed; - } -#else - if (!from || !to) { - goto failed; - } -#endif - - /* check for conversion to/from ucs2 */ - if (is_utf16(fromcode) && to) { - ret->direct = to->push; - return ret; - } - if (is_utf16(tocode) && from) { - ret->direct = from->pull; - return ret; - } - -#ifdef HAVE_NATIVE_ICONV - if (is_utf16(fromcode)) { - ret->direct = sys_iconv; - ret->cd_direct = ret->cd_push; - ret->cd_push = NULL; - return ret; - } - if (is_utf16(tocode)) { - ret->direct = sys_iconv; - ret->cd_direct = ret->cd_pull; - ret->cd_pull = NULL; - return ret; - } -#endif - - /* the general case has to go via a buffer */ - if (!ret->pull) ret->pull = from->pull; - if (!ret->push) ret->push = to->push; - return ret; - -failed: - talloc_free(ret); - errno = EINVAL; - return (smb_iconv_t)-1; -} - -/* - simple iconv_close() wrapper -*/ -int smb_iconv_close(smb_iconv_t cd) -{ -#ifdef HAVE_NATIVE_ICONV - if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); - if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull); - if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); -#endif - - talloc_free(cd); - return 0; -} - - -/********************************************************************** - the following functions implement the builtin character sets in Samba - and also the "test" character sets that are designed to test - multi-byte character set support for english users -***********************************************************************/ -static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - (*outbuf)[0] = (*inbuf)[0]; - (*outbuf)[1] = 0; - (*inbytesleft) -= 1; - (*outbytesleft) -= 2; - (*inbuf) += 1; - (*outbuf) += 2; - } - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int ir_count=0; - - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - (*outbuf)[0] = (*inbuf)[0] & 0x7F; - if ((*inbuf)[1]) ir_count++; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return ir_count; -} - - -static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - uint_t v; - - if ((*inbuf)[0] != '@') { - /* seven bit ascii case */ - (*outbuf)[0] = (*inbuf)[0]; - (*outbuf)[1] = 0; - (*inbytesleft) -= 1; - (*outbytesleft) -= 2; - (*inbuf) += 1; - (*outbuf) += 2; - continue; - } - /* it's a hex character */ - if (*inbytesleft < 5) { - errno = EINVAL; - return -1; - } - - if (sscanf(&(*inbuf)[1], "%04x", &v) != 1) { - errno = EILSEQ; - return -1; - } - - (*outbuf)[0] = v&0xff; - (*outbuf)[1] = v>>8; - (*inbytesleft) -= 5; - (*outbytesleft) -= 2; - (*inbuf) += 5; - (*outbuf) += 2; - } - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - char buf[6]; - - if ((*inbuf)[1] == 0 && - ((*inbuf)[0] & 0x80) == 0 && - (*inbuf)[0] != '@') { - (*outbuf)[0] = (*inbuf)[0]; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - continue; - } - if (*outbytesleft < 5) { - errno = E2BIG; - return -1; - } - snprintf(buf, 6, "@%04x", SVAL(*inbuf, 0)); - memcpy(*outbuf, buf, 5); - (*inbytesleft) -= 2; - (*outbytesleft) -= 5; - (*inbuf) += 2; - (*outbuf) += 5; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int n; - - n = MIN(*inbytesleft, *outbytesleft); - - swab(*inbuf, *outbuf, (n&~1)); - if (n&1) { - (*outbuf)[n-1] = 0; - } - - (*inbytesleft) -= n; - (*outbytesleft) -= n; - (*inbuf) += n; - (*outbuf) += n; - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - - -static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int n; - - n = MIN(*inbytesleft, *outbytesleft); - - memmove(*outbuf, *inbuf, n); - - (*inbytesleft) -= n; - (*outbytesleft) -= n; - (*inbuf) += n; - (*outbuf) += n; - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t in_left=*inbytesleft, out_left=*outbytesleft; - const uint8_t *c = (const uint8_t *)*inbuf; - uint8_t *uc = (uint8_t *)*outbuf; - - while (in_left >= 1 && out_left >= 2) { - if ((c[0] & 0x80) == 0) { - uc[0] = c[0]; - uc[1] = 0; - c += 1; - in_left -= 1; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xe0) == 0xc0) { - if (in_left < 2 || - (c[1] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - uc[1] = (c[0]>>2) & 0x7; - uc[0] = (c[0]<<6) | (c[1]&0x3f); - c += 2; - in_left -= 2; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xf0) == 0xe0) { - if (in_left < 3 || - (c[1] & 0xc0) != 0x80 || - (c[2] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); - uc[0] = (c[1]<<6) | (c[2]&0x3f); - c += 3; - in_left -= 3; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xf8) == 0xf0) { - unsigned int codepoint; - if (in_left < 4 || - (c[1] & 0xc0) != 0x80 || - (c[2] & 0xc0) != 0x80 || - (c[3] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - codepoint = - (c[3]&0x3f) | - ((c[2]&0x3f)<<6) | - ((c[1]&0x3f)<<12) | - ((c[0]&0x7)<<18); - if (codepoint < 0x10000) { - /* accept UTF-8 characters that are not - minimally packed, but pack the result */ - uc[0] = (codepoint & 0xFF); - uc[1] = (codepoint >> 8); - c += 4; - in_left -= 4; - out_left -= 2; - uc += 2; - continue; - } - - codepoint -= 0x10000; - - if (out_left < 4) { - errno = E2BIG; - goto error; - } - - uc[0] = (codepoint>>10) & 0xFF; - uc[1] = (codepoint>>18) | 0xd8; - uc[2] = codepoint & 0xFF; - uc[3] = ((codepoint>>8) & 0x3) | 0xdc; - c += 4; - in_left -= 4; - out_left -= 4; - uc += 4; - continue; - } - - /* we don't handle 5 byte sequences */ - errno = EINVAL; - goto error; - } - - if (in_left > 0) { - errno = E2BIG; - goto error; - } - - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = c; - *outbuf = uc; - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = c; - *outbuf = uc; - return -1; -} - -static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t in_left=*inbytesleft, out_left=*outbytesleft; - uint8_t *c = (uint8_t *)*outbuf; - const uint8_t *uc = (const uint8_t *)*inbuf; - - while (in_left >= 2 && out_left >= 1) { - unsigned int codepoint; - - if (uc[1] == 0 && !(uc[0] & 0x80)) { - /* simplest case */ - c[0] = uc[0]; - in_left -= 2; - out_left -= 1; - uc += 2; - c += 1; - continue; - } - - if ((uc[1]&0xf8) == 0) { - /* next simplest case */ - if (out_left < 2) { - errno = E2BIG; - goto error; - } - c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2); - c[1] = 0x80 | (uc[0] & 0x3f); - in_left -= 2; - out_left -= 2; - uc += 2; - c += 2; - continue; - } - - if ((uc[1] & 0xfc) == 0xdc) { - /* its the second part of a 4 byte sequence. Illegal */ - if (in_left < 4) { - errno = EINVAL; - } else { - errno = EILSEQ; - } - goto error; - } - - if ((uc[1] & 0xfc) != 0xd8) { - codepoint = uc[0] | (uc[1]<<8); - if (out_left < 3) { - errno = E2BIG; - goto error; - } - c[0] = 0xe0 | (codepoint >> 12); - c[1] = 0x80 | ((codepoint >> 6) & 0x3f); - c[2] = 0x80 | (codepoint & 0x3f); - - in_left -= 2; - out_left -= 3; - uc += 2; - c += 3; - continue; - } - - /* its the first part of a 4 byte sequence */ - if (in_left < 4) { - errno = EINVAL; - goto error; - } - if ((uc[3] & 0xfc) != 0xdc) { - errno = EILSEQ; - goto error; - } - codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) | - (uc[0]<<10) | ((uc[1] & 0x3)<<18)); - - if (out_left < 4) { - errno = E2BIG; - goto error; - } - c[0] = 0xf0 | (codepoint >> 18); - c[1] = 0x80 | ((codepoint >> 12) & 0x3f); - c[2] = 0x80 | ((codepoint >> 6) & 0x3f); - c[3] = 0x80 | (codepoint & 0x3f); - - in_left -= 4; - out_left -= 4; - uc += 4; - c += 4; - } - - if (in_left == 1) { - errno = EINVAL; - goto error; - } - - if (in_left > 1) { - errno = E2BIG; - goto error; - } - - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = uc; - *outbuf = c; - - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = uc; - *outbuf = c; - return -1; -} - - - diff --git a/source4/lib/iconv.m4 b/source4/lib/iconv.m4 deleted file mode 100644 index 282fa69b2d..0000000000 --- a/source4/lib/iconv.m4 +++ /dev/null @@ -1,66 +0,0 @@ -dnl # ICONV/CHARSET subsystem - -ICONV_LOCATION=standard -LOOK_DIRS="/usr /usr/local /sw" -AC_ARG_WITH(libiconv, -[ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], -[ - if test "$withval" = "no" ; then - AC_MSG_ERROR(I won't take no for an answer) - else - if test "$withval" != "yes" ; then - LOOK_DIRS="$withval $LOOK_DIRS" - fi - fi -]) - -ICONV_FOUND="no" -for i in $LOOK_DIRS ; do - save_LIBS=$LIBS - save_LDFLAGS=$LDFLAGS - save_CPPFLAGS=$CPPFLAGS - CPPFLAGS="-I$i/include" - LDFLAGS="-L$i/lib" - LIBS= - export LDFLAGS LIBS CPPFLAGS -dnl Try to find iconv(3) - jm_ICONV($i) - - CPPFLAGS=$save_CPPFLAGS - if test -n "$ICONV_FOUND" ; then - LDFLAGS=$save_LDFLAGS - LIB_ADD_DIR(LDFLAGS, "$i/lib") - CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") - LIBS="$save_LIBS $LIBS" - ICONV_LOCATION=$i - export LDFLAGS LIBS CPPFLAGS - break - else - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - export LDFLAGS LIBS CPPFLAGS - fi -done - -############ -# check for iconv in libc -AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ -AC_TRY_RUN([ -#include -main() { - iconv_t cd = iconv_open("ASCII", "UCS-2LE"); - if (cd == 0 || cd == (iconv_t)-1) return -1; - return 0; -} -], -samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) -if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then - AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) -fi - -if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then - AC_MSG_WARN([Sufficient support for iconv function was not found. - Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) -fi - -SMB_SUBSYSTEM(CHARSET,lib/iconv.o,lib/charcnv.o,[${TMP_CHARSET_LIBS}]) -- cgit From 224a2a62b5f9e23f3edd3e9fcafa52829c322ba1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 5 Aug 2005 10:11:22 +0000 Subject: r9106: look for something more usefull in the -lnsl (this is for solaris) metze (This used to be commit f37bb2a838b83e70d50a0ed036e641ced16d8a7b) --- source4/lib/socket/config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 786d6c72bc..5c87678bd6 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -33,11 +33,11 @@ AC_CHECK_FUNCS(connect) if test x"$ac_cv_func_connect" = x"no"; then case "$LIBS $SOCKET_LIBS" in *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, printf) ;; + *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, inet_aton) ;; esac case "$LIBS $SOCKET_LIBS" in *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, printf) ;; + *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, inet_aton) ;; esac case "$LIBS $SOCKET_LIBS" in *-lsocket*) ;; -- cgit From 0bbe88c8598505f2166cfa8869117e9d02ebfa85 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 5 Aug 2005 11:34:36 +0000 Subject: r9110: use printf again metyze (This used to be commit 99537d35cb7c2561a7ce47ac7ad602496afe3475) --- source4/lib/socket/config.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 5c87678bd6..786d6c72bc 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -33,11 +33,11 @@ AC_CHECK_FUNCS(connect) if test x"$ac_cv_func_connect" = x"no"; then case "$LIBS $SOCKET_LIBS" in *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, inet_aton) ;; + *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, printf) ;; esac case "$LIBS $SOCKET_LIBS" in *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, inet_aton) ;; + *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, printf) ;; esac case "$LIBS $SOCKET_LIBS" in *-lsocket*) ;; -- cgit From f9e0b8aca502357d64f4816204ddcb2c7e876c8d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 7 Aug 2005 06:16:10 +0000 Subject: r9172: - fixed a nasty bug in the 'deep copy' mpr code that caused variables called 'credentials' to not copy correctly (the bug was in handling of chaining in the copy code - ensure that C pointer variables are copied via a talloc reference so that we can persist rpc pipes and credentials between sessions (This used to be commit ca6f049693f8bfe69d5c7533b2cc92221d0cf6d4) --- source4/lib/appweb/mpr/var.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c index 9b02c0f8b0..77f4cbc55a 100644 --- a/source4/lib/appweb/mpr/var.c +++ b/source4/lib/appweb/mpr/var.c @@ -1416,7 +1416,9 @@ static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) break; case MPR_TYPE_PTR: - dest->ptr = src->ptr; + /* we have to reference here so talloc structures survive a + copy */ + dest->ptr = talloc_reference(dest, src->ptr); break; case MPR_TYPE_STRING_CFUNCTION: @@ -1477,7 +1479,7 @@ static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) srcProp->visited = 1; copyVarCore(destProp, srcProp, copyDepth); srcProp->visited = 0; - last = srcProp; + last = destProp; } } dest->properties->numItems = src->properties->numItems; -- cgit From f13fbd7e6fcdf8fe6de2d9be2fd453fe22fc5e16 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 7 Aug 2005 06:16:32 +0000 Subject: r9173: catch ep->local being NULL (This used to be commit 9f75bc3ca061abbfeb6ac9fc60834b8c1f6e2c4d) --- source4/lib/appweb/ejs/ejsLib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c index eed6d67fb4..b24b2b013c 100644 --- a/source4/lib/appweb/ejs/ejsLib.c +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -211,7 +211,9 @@ void ejsCloseEngine(EjsId eid) mprDestroyVar(&ep->result); mprDestroyVar(&ep->tokenNumber); - mprDeleteProperty(ep->local, "local"); + if (ep->local) { + mprDeleteProperty(ep->local, "local"); + } mprDeleteProperty(ep->global, "this"); mprDeleteProperty(ep->global, "global"); -- cgit From a663d2110678b6c059737eecf7929cd5e5d46160 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 7 Aug 2005 15:45:59 +0000 Subject: r9183: more workarounds for the global variables in ejs. I will discuss getting rid of these with the mbedthis people. (This used to be commit a5b9e74a5c23e724ae4ee222e6f128133b175494) --- source4/lib/appweb/ejs/ejs.h | 3 +++ source4/lib/appweb/ejs/ejsLib.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejs.h b/source4/lib/appweb/ejs/ejs.h index 5efdb47192..c7b0c54d8e 100644 --- a/source4/lib/appweb/ejs/ejs.h +++ b/source4/lib/appweb/ejs/ejs.h @@ -71,6 +71,9 @@ extern void ejsClose(void); extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); extern void ejsCloseEngine(EjsId eid); +void *ejs_save_state(void); +void ejs_restore_state(void *ptr); + /* * Evaluation functions */ diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c index b24b2b013c..f6c004592b 100644 --- a/source4/lib/appweb/ejs/ejsLib.c +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -58,6 +58,33 @@ static void *lockData; #define ejsUnlock() #endif + +/* + save/restore global ejs state - used to cope with simultaneous ejs requests + this is a workaround for the use of global variables in ejs +*/ +struct ejs_state_ctx { + struct MprVar master; + struct MprArray *ejsList; +}; + +void *ejs_save_state(void) +{ + struct ejs_state_ctx *ctx = talloc(talloc_autofree_context(), struct ejs_state_ctx); + ctx->master = master; + ctx->ejsList = ejsList; + return ctx; +} + +void ejs_restore_state(void *ptr) +{ + struct ejs_state_ctx *ctx = talloc_get_type(ptr, struct ejs_state_ctx); + master = ctx->master; + ejsList = ctx->ejsList; + talloc_free(ctx); +} + + /****************************** Forward Declarations **************************/ static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); -- cgit From a689b968b6c1b47b0425f753472f1e221d2dea67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 8 Aug 2005 03:19:28 +0000 Subject: r9209: - fixed the ldb registry backend to work with the new provision ldif - default to ldb backend if none specified (This used to be commit 8c3f57f7917efceb11b3b6a2ac76ec44968fbfb6) --- source4/lib/registry/reg_backend_ldb.c | 2 +- source4/lib/registry/reg_samba.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 5f4e296edf..8a5eac59c5 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -250,7 +250,7 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) talloc_set_destructor (hive, ldb_free_hive); (*k)->name = talloc_strdup(*k, ""); (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data); - kd->dn = talloc_strdup(*k, "hive="); + kd->dn = talloc_strdup(*k, "hive=NONE"); return WERR_OK; diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c index 7188109daa..3c9ae3f415 100644 --- a/source4/lib/registry/reg_samba.c +++ b/source4/lib/registry/reg_samba.c @@ -27,7 +27,8 @@ static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, { WERROR error; const char *conf; - char *backend, *location; + char *backend; + const char *location; const char *hivename = reg_get_predef_name(hkey); *k = NULL; @@ -38,12 +39,13 @@ static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, return WERR_NOT_SUPPORTED; } - backend = talloc_strdup(NULL, conf); - location = strchr(backend, ':'); - + location = strchr(conf, ':'); if (location) { - *location = '\0'; + backend = talloc_strndup(ctx, conf, (int)(location - conf)); location++; + } else { + backend = talloc_strdup(ctx, "ldb"); + location = conf; } /* FIXME: Different hive backend for HKEY_CLASSES_ROOT: merged view of HKEY_LOCAL_MACHINE\Software\Classes -- cgit From 1774019fc27869f01808ad8b0f8f85d03492d4b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 13 Aug 2005 03:16:03 +0000 Subject: r9299: fixed the evaluation of pointer expressions that evaluate to boolean (This used to be commit 17679676d4629ac81116ae1b102f1a311b5d4eed) --- source4/lib/appweb/ejs/ejsParser.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index 5b8b84f7b3..871907dd10 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -48,6 +48,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); static int evalFloatExpr(Ejs *ep, double l, int rel, double r); #endif static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); +static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r); static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); static int evalFunction(Ejs *ep, MprVar *obj, int flags); @@ -1670,8 +1671,8 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) return 0; case MPR_TYPE_PTR: - mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0); - return 0; + rc = evalPtrExpr(ep, lhs->ptr, rel, rhs->ptr); + break; case MPR_TYPE_BOOL: rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); @@ -1806,6 +1807,28 @@ static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) return 0; } +static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r) +{ + bool lval; + + switch (rel) { + case EJS_EXPR_EQ: + lval = l == r; + break; + case EJS_EXPR_NOTEQ: + lval = l != r; + break; + case EJS_EXPR_BOOL_COMP: + lval = (r == NULL) ? 1 : 0; + break; + default: + ejsError(ep, "Bad operator %d", rel); + return -1; + } + mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); + return 0; +} + /******************************************************************************/ /* * Expressions with numeric operands -- cgit From 56aadf82af5e3c5feeeb0dc5a5c14fc6967b4336 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 16 Aug 2005 00:01:25 +0000 Subject: r9311: Missing null pointer check in ejsLib Found by coverity (This used to be commit ae7b073af3d690275dbfa11c8406963702c57d3b) --- source4/lib/appweb/ejs/ejsLib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c index f6c004592b..af5ce52731 100644 --- a/source4/lib/appweb/ejs/ejsLib.c +++ b/source4/lib/appweb/ejs/ejsLib.c @@ -327,7 +327,8 @@ int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) * Error return */ error: - *emsg = mprStrdup(ep->error); + if(emsg) + *emsg = mprStrdup(ep->error); return -1; } -- cgit From 8609e7993237e5ffe54830299212c128e082d9b9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Aug 2005 06:55:40 +0000 Subject: r9318: fix searches with scope ONE and SUB, the problem was that ldb_dn_compare_base() just looked at if both dn's mtach some how, and the following happens: basedn: CN=bar,DC=foo,DC=com dn: DC=foo,DC=com and dn: DC=foo,DC=com was return as result of a sub and base search and also the ONE search with basedn: DC=foo,DC=com returned this dn: CN=bla,CN=bar,DC=foo,DC=com metze (This used to be commit 2a107472c373e425013050e28b944c830f653a87) --- source4/lib/ldb/common/ldb_dn.c | 4 ++++ source4/lib/ldb/common/ldb_match.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index edb5124d99..5dcb540fa1 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -415,6 +415,10 @@ int ldb_dn_compare_base(struct ldb_context *ldb, int ret; int n0, n1; + if (base->comp_num > dn->comp_num) { + return (dn->comp_num - base->comp_num); + } + /* if the number of components doesn't match they differ */ n0 = base->comp_num - 1; n1 = dn->comp_num - 1; diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 7ff84f70c3..b6f5f5a18d 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -71,7 +71,7 @@ static int ldb_match_scope(struct ldb_context *ldb, break; case LDB_SCOPE_ONELEVEL: - if (dn->comp_num != base->comp_num) { + if (dn->comp_num == (base->comp_num + 1)) { if (ldb_dn_compare_base(ldb, base, dn) == 0) { ret = 1; } -- cgit From 9fffd12799239219a276b1ca83319d1340d97232 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Aug 2005 01:25:58 +0000 Subject: r9338: fixed the winreg IDL to be correct for the EnumKey and EnumValue calls. The previous IDL was just a workaround for the limitations of our older rpc infrastructure. Now that Jelmer has added much improved string support using the charset keyword we can correctly implemenent the unusual winreg string buffers. Jelmer, note the little comment I put on winreg_StringBuf() about why I couldn't use [value()] for the length field. This also fixes EnumKey() and EnumValue() to use NTTIME fields for the last_changed_time. I don't know why we were using a pair of uint32's, as it is just a NTTIME. (This used to be commit 8354b016122cc4f3cff042b3ada1de07e1614eb7) --- source4/lib/registry/reg_backend_rpc.c | 49 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 73d2d54687..5734b96770 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -177,8 +177,8 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p struct winreg_EnumValue r; uint32_t type, len1, zero = 0; NTSTATUS status; - uint8_t buf8; - uint16_t buf16; + struct winreg_StringBuf name; + uint8_t u8; if(mykeydata->num_values == -1) { error = rpc_query_key(parent); @@ -187,17 +187,18 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p len1 = mykeydata->max_valdatalen; + name.length = 0; + name.size = mykeydata->max_valnamelen * 2; + name.name = ""; + r.in.handle = &mykeydata->pol; r.in.enum_index = n; - r.in.name_in.length = 0; - r.in.name_in.size = mykeydata->max_valnamelen * 2; - r.in.name_in.name = &buf16; + r.in.name = &name; r.in.type = &type; - r.in.value = &buf8; + r.in.value = &u8; r.in.length = &zero; r.in.size = &len1; - r.out.type = &type; - + r.out.name = &name; status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -208,7 +209,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result) && r.out.length) { *value = talloc(mem_ctx, struct registry_value); - (*value)->name = talloc_strdup(mem_ctx, r.out.name_out.name); + (*value)->name = talloc_strdup(mem_ctx, r.out.name->name); (*value)->data_type = type; (*value)->data_len = *r.out.length; (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value, *r.out.length); @@ -221,27 +222,29 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) { struct winreg_EnumKey r; - struct winreg_EnumKeyNameRequest keyname; - struct winreg_String classname; - struct winreg_Time tm; struct rpc_key_data *mykeydata = parent->backend_data; NTSTATUS status; + struct winreg_StringBuf namebuf, classbuf; + NTTIME change_time = 0; - r.in.handle = &mykeydata->pol; - keyname.unknown = 0x0000020a; - init_winreg_String(&keyname.key_name, NULL); - init_winreg_String(&classname, NULL); - r.in.in_name = &keyname; - r.in.class = &classname; - tm.low = tm.high = 0x7fffffff; - r.in.last_changed_time = &tm; + namebuf.length = 0; + namebuf.size = 1024; + namebuf.name = NULL; + classbuf.length = 0; + classbuf.size = 0; + classbuf.name = NULL; + r.in.handle = &mykeydata->pol; r.in.enum_index = n; - r.in.unknown = r.out.unknown = 0x0414; - r.in.key_name_len = r.out.key_name_len = 0; + r.in.name = &namebuf; + r.in.class = &classbuf; + r.in.last_changed_time = &change_time; + r.out.name = &namebuf; + status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - return rpc_open_key(mem_ctx, parent, talloc_strdup(mem_ctx, r.out.out_name->name), subkey); + char *name = talloc_strdup(mem_ctx, r.out.name->name); + return rpc_open_key(mem_ctx, parent, name, subkey); } return r.out.result; -- cgit From 878e139f09e6e2f87de35341f4340119959469e5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 17 Aug 2005 12:51:07 +0000 Subject: r9357: Remove DBGC_CLASS cruft copied over from Samba 3. I would like to replace this with something funkier. (This used to be commit 8d376d56c78894b9bbd27ed7fa70da415c0cd038) --- source4/lib/gencache.c | 3 --- source4/lib/registry/common/reg_interface.c | 3 --- source4/lib/registry/common/reg_util.c | 3 --- source4/lib/registry/reg_samba.c | 3 --- 4 files changed, 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 2db66b7564..de8c47ada5 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -27,9 +27,6 @@ #include "system/filesys.h" #include "db_wrap.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_TDB - #define TIMEOUT_LEN 12 #define CACHE_DATA_FMT "%12u/%s" diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 76de2f041f..2abe90f2d1 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -22,9 +22,6 @@ #include "dlinklist.h" #include "registry.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_REGISTRY - /* List of available backends */ static struct reg_init_function_entry *backends = NULL; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index e12cff186a..2d933f2e6b 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -21,9 +21,6 @@ #include "includes.h" #include "registry.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_REGISTRY - static const struct { uint32_t id; const char *name; diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c index 3c9ae3f415..6341a1c4ee 100644 --- a/source4/lib/registry/reg_samba.c +++ b/source4/lib/registry/reg_samba.c @@ -20,9 +20,6 @@ #include "includes.h" #include "registry.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_REGISTRY - static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, struct registry_key **k) { WERROR error; -- cgit From 5d899b8a35c9ef1e3688fc56495be1c37477e726 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 00:20:40 +0000 Subject: r9369: an attempt to fix the build on HPUX. This is based on work by Don McCall, but takes a slightly different approach that I hope will be more generic (This used to be commit e8260a81cf99be2ccae64135ca0572c8a6ae62ad) --- source4/lib/replace/config.m4 | 2 + source4/lib/replace/replace.c | 106 +++++++++++------------------------------- 2 files changed, 29 insertions(+), 79 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 8c85663d3b..33dc33a50b 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -14,3 +14,5 @@ exit(1);}], if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) fi + +AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq seteuid) diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index 9ef3999769..ae70634215 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -340,75 +340,6 @@ duplicate a string #endif /* REPLACE_INET_NTOA */ #endif -#ifndef HAVE_STRTOUL -#ifndef ULONG_MAX -#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ -#endif - -/* - * Convert a string to an unsigned long integer. - * Taken from libg++ - libiberty code. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ - unsigned long strtoul(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') { - neg = 1; - c = *s++; - } else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base); - for (acc = 0, any = 0;; c = *s++) { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *) (any ? s - 1 : nptr); - return (acc); -} -#endif /* HAVE_STRTOUL */ - #ifndef HAVE_SETLINEBUF int setlinebuf(FILE *stream) { @@ -511,17 +442,23 @@ int get_time_zone(time_t t) { #ifdef HAVE_STRTOUQ return strtouq(str, endptr, base); +#elif defined(HAVE___STRTOULL) + return __strtoull(str, endptr, base); #else - unsigned long long int v; - if (sscanf(str, "%lli", &v) != 1) { - errno = EINVAL; - return 0; - } - if (endptr) { - /* try to get endptr right - uggh */ - strtoul(str, endptr, base); - } - return v; +# error "You need a strtoull function" +#endif +} +#endif + +#ifndef HAVE_STRTOLL + long long int strtoll(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOQ + return strtoq(str, endptr, base); +#elif defined(HAVE___STRTOLL) + return __strtoll(str, endptr, base); +#else +# error "You need a strtoll function" #endif } #endif @@ -567,3 +504,14 @@ int sys_waitpid(pid_t pid,int *status,int options) return wait4(pid, status, options, NULL); #endif /* USE_WAITPID */ } + +#ifndef HAVE_SETEUID + int seteuid(uid_t euid) +{ +#ifdef HAVE_SETRESUID + return setresuid(-1, euid, -1); +#else +# error "You need a seteuid function" +#endif +} +#endif -- cgit From 4e21575ed2144c0ca330439989278906c273270d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 00:31:40 +0000 Subject: r9370: need a configure test for setresuid() (This used to be commit 5a38b9a10b3c5363cddc7acaaea2e1e9aceb254c) --- source4/lib/replace/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 33dc33a50b..a912675d0f 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -15,4 +15,4 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) fi -AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq seteuid) +AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq seteuid setresuid) -- cgit From 3f260e2efe416a05571c29d8edb81ae0385a00c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 01:57:43 +0000 Subject: r9374: HPUX is also missing setegid() (This used to be commit 57e6bd61395e82064c72510dcc326b11b7bdf7fd) --- source4/lib/replace/config.m4 | 3 ++- source4/lib/replace/replace.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index a912675d0f..4dfeb5647a 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -15,4 +15,5 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) fi -AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq seteuid setresuid) +AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) +AC_CHECK_FUNCS(seteuid setresuid setegid setresgid) diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index ae70634215..ef8e053257 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -515,3 +515,14 @@ int sys_waitpid(pid_t pid,int *status,int options) #endif } #endif + +#ifndef HAVE_SETEGID + int setegid(gid_t egid) +{ +#ifdef HAVE_SETRESGID + return setresgid(-1, egid, -1); +#else +# error "You need a setegid function" +#endif +} +#endif -- cgit From 20b6f0a11b7827f327de05b68370759129db1fe2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 06:14:10 +0000 Subject: r9378: initialise the last_mod attribute in the ldb backend. Better to return 0 than an uninitialised value, but we should put proper last_modified time support into the ldb winreg backend in the future (This used to be commit 899bf07908d4a04cb3d1cd4034dca0c91e6a912b) --- source4/lib/registry/reg_backend_ldb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 8a5eac59c5..19d982c109 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -170,6 +170,8 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, talloc_set_destructor(*subkey, reg_close_ldb_key); (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data); + (*subkey)->last_mod = 0; /* TODO: we need to add this to the + ldb backend properly */ newkd->dn = talloc_strdup(mem_ctx, kd->subkeys[idx]->dn); return WERR_OK; -- cgit From 09085941d130542cf4609ec4cb5b743ba1c25f42 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 18 Aug 2005 07:00:37 +0000 Subject: r9381: Line wrapping. (This used to be commit 2cebdd59387786c8aeee4c6757e38ed5303f7315) --- source4/lib/registry/README | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/README b/source4/lib/registry/README index c91d361acd..db1fb7a678 100644 --- a/source4/lib/registry/README +++ b/source4/lib/registry/README @@ -1,22 +1,23 @@ -This is the registry library. The registry is basically a bunch of hives -that can be loaded from different places. +This is the registry library. The registry is basically a bunch of +hives that can be loaded from different places. + +The various registry backends provide support for loading/saving +specific types of hives: -The various registry backends provide support for loading/saving specific types -of hives: - ldb - w95 (USER.DAT-style files) - nt4 (NTUSER.DAT-style files) - gconf (GNOME configuration) - rpc (Remote individual hives) -Instead of opening individual hives, one can also open a 'complete' registry by -using one of these three functions: +Instead of opening individual hives, one can also open a 'complete' +registry by using one of these three functions: - reg_open_local() - load local registry, see below - reg_open_remote() - connect to remote registry over RPC - reg_open_wine() (not working yet) -reg_open_local() loads a set of hives based on smb.conf settings. +reg_open_local() loads a set of hives based on smb.conf settings. Lines in smb.conf should have the following syntax: registry: = : @@ -38,4 +39,3 @@ HKEY_LOCAL_MACHINE\Software: %SystemRoot%\System32\Config\Software HKEY_LOCAL_MACHINE\System: %SystemRoot%\System32\Config\System HKEY_USERS\.DEFAULT: %SystemRoot%\System32\Config\Default HKEY_LOCAL_MACHINE\HARDWARE: is autogenerated - -- cgit From 6c1dde71f4ace7901fa13347ef9ced0ac8b16233 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 10:58:05 +0000 Subject: r9386: OpenKey with a bad name must return WERR_BADFILE (w2k3 regedit relies on this) (This used to be commit ae42976590b3c532790d854be45fff49074aef68) --- source4/lib/registry/reg_backend_ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 19d982c109..784d8ac6fa 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -214,7 +214,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); if(ret == 0) { - return WERR_NO_MORE_ITEMS; + return WERR_BADFILE; } else if(ret < 0) { DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c))); return WERR_FOOBAR; -- cgit From 6195932b4241d94453438a857179debc08495ece Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 11:15:15 +0000 Subject: r9387: regedit uses "New Key #nn" for newly created keys, which conflicts with the stricter DN rules in ldb. Escape the DN components to cope. Simo, sorry for making a change in ldb_dn.c while you have changes pending. Please feel free to revert these and switch reg_backend_ldb.c to use the new dn construction code. (This used to be commit 136ecf5cb23758558b4119b08047fc273be8b0f8) --- source4/lib/ldb/common/ldb_dn.c | 2 +- source4/lib/ldb/include/ldb.h | 1 + source4/lib/registry/reg_backend_ldb.c | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 5dcb540fa1..d13238cc17 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -56,7 +56,7 @@ static int ldb_dn_is_valid_attribute_name(const char *name) return 1; } -static char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value) +char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value) { const char *p, *s, *src; char *d, *dst; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 7399b8ffe7..fdf5dc8d91 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -342,6 +342,7 @@ int ldb_attrib_add_handlers(struct ldb_context *ldb, int ldb_dn_cmp(struct ldb_context *ldb, const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); +char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value); /* case-fold a DN */ char *ldb_dn_fold(void * mem_ctx, diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 784d8ac6fa..114614597f 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -126,12 +126,24 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, con while(mypath) { char *keyname; begin = strrchr(mypath, '\\'); + struct ldb_val val; + char *key; - if(begin) keyname = begin + 1; + if (begin) keyname = begin + 1; else keyname = mypath; - if(strlen(keyname)) - ret = talloc_asprintf_append(ret, "key=%s,", keyname); + val.data = keyname; + val.length = strlen(keyname); + + key = ldb_dn_escape_value(mem_ctx, val); + if (key == NULL) { + return NULL; + } + + if (strlen(key)) + ret = talloc_asprintf_append(ret, "key=%s,", key); + + talloc_free(key); if(begin) { *begin = '\0'; -- cgit From a8d51f87620a688a286603766cbb7edb2b7c6e60 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Aug 2005 12:21:42 +0000 Subject: r9390: fixed mixing of code and data (This used to be commit ae2122e76a7e50435dafcc412ee425b522c0c766) --- source4/lib/registry/reg_backend_ldb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 114614597f..3c50258d02 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -125,10 +125,11 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, con while(mypath) { char *keyname; - begin = strrchr(mypath, '\\'); struct ldb_val val; char *key; + begin = strrchr(mypath, '\\'); + if (begin) keyname = begin + 1; else keyname = mypath; -- cgit From 3e4c4cff2177af33efdb15f03a1bbcb639505cee Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Aug 2005 15:02:01 +0000 Subject: r9391: Convert all the code to use struct ldb_dn to ohandle ldap like distinguished names Provide more functions to handle DNs in this form (This used to be commit 692e35b7797e39533dd2a1c4b63d9da30f1eb5ba) --- source4/lib/gendb.c | 11 +- source4/lib/ldb/common/ldb.c | 8 +- source4/lib/ldb/common/ldb_dn.c | 308 ++++++++++++++++++++++++++++++++- source4/lib/ldb/common/ldb_ldif.c | 4 +- source4/lib/ldb/common/ldb_match.c | 60 ++----- source4/lib/ldb/common/ldb_modules.c | 17 +- source4/lib/ldb/common/ldb_msg.c | 19 +- source4/lib/ldb/include/ldb.h | 57 ++++-- source4/lib/ldb/include/ldb_private.h | 39 ++--- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 111 ++++++++---- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 94 +++++++--- source4/lib/ldb/ldb_tdb/ldb_cache.c | 50 +++++- source4/lib/ldb/ldb_tdb/ldb_index.c | 133 +++++++++----- source4/lib/ldb/ldb_tdb/ldb_pack.c | 21 ++- source4/lib/ldb/ldb_tdb/ldb_search.c | 37 ++-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 113 +++++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 12 +- source4/lib/ldb/modules/rdn_name.c | 44 +++-- source4/lib/ldb/modules/schema.c | 87 ++++------ source4/lib/ldb/modules/skel.c | 6 +- source4/lib/ldb/modules/timestamps.c | 16 +- source4/lib/ldb/tools/cmdline.c | 22 ++- source4/lib/ldb/tools/cmdline.h | 2 + source4/lib/ldb/tools/ldbadd.c | 2 +- source4/lib/ldb/tools/ldbdel.c | 14 +- source4/lib/ldb/tools/ldbedit.c | 23 ++- source4/lib/ldb/tools/ldbmodify.c | 2 +- source4/lib/ldb/tools/ldbrename.c | 8 +- source4/lib/ldb/tools/ldbsearch.c | 17 +- source4/lib/ldb/tools/ldbtest.c | 55 +++--- source4/lib/registry/reg_backend_ldb.c | 61 ++++--- 31 files changed, 994 insertions(+), 459 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index 4bf76a7f64..a5fe7c3bce 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -29,7 +29,7 @@ */ int gendb_search_v(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - const char *basedn, + const struct ldb_dn *basedn, struct ldb_message ***res, const char * const *attrs, const char *format, @@ -55,7 +55,8 @@ int gendb_search_v(struct ldb_context *ldb, if (*res) talloc_steal(mem_ctx, *res); DEBUG(4,("gendb_search_v: %s %s -> %d (%s)\n", - basedn?basedn:"NULL", expr?expr:"NULL", count, + basedn?ldb_dn_linearize(mem_ctx,basedn):"NULL", + expr?expr:"NULL", count, count==-1?ldb_errstring(ldb):"OK")); free(expr); @@ -68,7 +69,7 @@ int gendb_search_v(struct ldb_context *ldb, */ int gendb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - const char *basedn, + const struct ldb_dn *basedn, struct ldb_message ***res, const char * const *attrs, const char *format, ...) _PRINTF_ATTRIBUTE(6,7) @@ -85,11 +86,11 @@ int gendb_search(struct ldb_context *ldb, int gendb_search_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - const char *dn, + const struct ldb_dn *dn, struct ldb_message ***res, const char * const *attrs) { - return gendb_search(ldb, mem_ctx, dn, res, attrs, "dn=%s", dn); + return gendb_search(ldb, mem_ctx, dn, res, attrs, "dn=%s", ldb_dn_linearize(mem_ctx, dn)); } /* diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 3a2eb13297..25e7bee66b 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -114,7 +114,7 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co */ int ldb_search(struct ldb_context *ldb, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -131,7 +131,7 @@ int ldb_search(struct ldb_context *ldb, */ int ldb_search_bytree(struct ldb_context *ldb, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -162,7 +162,7 @@ int ldb_modify(struct ldb_context *ldb, /* delete a record from the database */ -int ldb_delete(struct ldb_context *ldb, const char *dn) +int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) { return ldb->modules->ops->delete_record(ldb->modules, dn); } @@ -170,7 +170,7 @@ int ldb_delete(struct ldb_context *ldb, const char *dn) /* rename a record in the database */ -int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn) +int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); } diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index d13238cc17..dae79fd9e1 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -41,8 +41,26 @@ #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed +#define LDB_SPECIAL "@SPECIAL" + +BOOL ldb_dn_is_special(const struct ldb_dn *dn) +{ + if (dn == NULL || dn->comp_num != 1) return 0; + + return ! strcmp(dn->components[0].name, LDB_SPECIAL); +} + +BOOL ldb_dn_check_special(const struct ldb_dn *dn, const char *check) +{ + if (dn == NULL || dn->comp_num != 1) return 0; + + return ! strcmp(dn->components[0].value.data, check); +} + static int ldb_dn_is_valid_attribute_name(const char *name) { + if (name == NULL) return 0; + while (*name) { if (! isascii(*name)) { return 0; @@ -165,6 +183,8 @@ static int get_quotes_position(const char *source, int *quote_start, int *quote_ { const char *p; + if (source == NULL || quote_start == NULL || quote_end == NULL) return -1; + p = source; /* check if there are quotes surrounding the value */ @@ -197,6 +217,8 @@ static char *seek_to_separator(char *string, const char *separators) char *p; int ret, qs, qe; + if (string == NULL || separators == NULL) return NULL; + p = strchr(string, '='); LDB_DN_NULL_FAILED(p); @@ -254,6 +276,11 @@ static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw char *p; int ret, qs, qe; + if (raw_component == NULL) { + dc.name = NULL; + return dc; + } + /* find attribute type/value separator */ p = strchr(raw_component, '='); LDB_DN_NULL_FAILED(p); @@ -300,14 +327,10 @@ failed: return dc; } -struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) +struct ldb_dn *ldb_dn_new(void *mem_ctx) { - struct ldb_dn *edn; /* the exploded dn */ - char *pdn, *p; + struct ldb_dn *edn; - pdn = NULL; - - /* Allocate a structure to hold the exploded DN */ edn = talloc(mem_ctx, struct ldb_dn); LDB_DN_NULL_FAILED(edn); @@ -315,12 +338,33 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) edn->comp_num = 0; edn->components = NULL; + return edn; + +failed: + return NULL; +} + +struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) +{ + struct ldb_dn *edn; /* the exploded dn */ + char *pdn, *p; + + if (dn == NULL) return NULL; + + /* Allocate a structure to hold the exploded DN */ + edn = ldb_dn_new(mem_ctx); + + /* Empty DNs */ + if (dn[0] == '\0') { + return edn; + } + /* Special DNs case */ if (dn[0] == '@') { edn->comp_num = 1; edn->components = talloc(edn, struct ldb_dn_component); if (edn->components == NULL) goto failed; - edn->components[0].name = talloc_strdup(edn->components, "@SPECIAL"); + edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL); if (edn->components[0].name == NULL) goto failed; edn->components[0].value.data = talloc_strdup(edn->components, dn); if (edn->components[0].value.data== NULL) goto failed; @@ -376,8 +420,10 @@ char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) char *dn, *value; int i; + if (edn == NULL) return NULL; + /* Special DNs */ - if ((edn->comp_num == 1) && strcmp("@SPECIAL", edn->components[0].name) == 0) { + if (ldb_dn_is_special(edn)) { dn = talloc_strdup(mem_ctx, edn->components[0].value.data); return dn; } @@ -419,6 +465,10 @@ int ldb_dn_compare_base(struct ldb_context *ldb, return (dn->comp_num - base->comp_num); } + if (base == NULL || base->comp_num == 0) return 0; + if (dn == NULL || dn->comp_num == 0) return -1; + if (base->comp_num > dn->comp_num) return -1; + /* if the number of components doesn't match they differ */ n0 = base->comp_num - 1; n1 = dn->comp_num - 1; @@ -450,6 +500,8 @@ int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1) { + if (edn0 == NULL || edn1 == NULL) return edn1 - edn0; + if (edn0->comp_num != edn1->comp_num) return (edn1->comp_num - edn0->comp_num); @@ -462,6 +514,8 @@ int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1) struct ldb_dn *edn1; int ret; + if (dn0 == NULL || dn1 == NULL) return dn1 - dn0; + edn0 = ldb_dn_explode_casefold(ldb, dn0); if (edn0 == NULL) return 0; @@ -488,7 +542,9 @@ struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn struct ldb_dn *cedn; int i; - cedn = talloc(ldb, struct ldb_dn); + if (edn == NULL) return NULL; + + cedn = ldb_dn_new(ldb); LDB_DN_NULL_FAILED(cedn); cedn->comp_num = edn->comp_num; @@ -521,6 +577,8 @@ struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn) { struct ldb_dn *edn, *cdn; + if (dn == NULL) return NULL; + edn = ldb_dn_explode(ldb, dn); if (edn == NULL) return NULL; @@ -529,3 +587,235 @@ struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn) talloc_free(edn); return cdn; } + +char *ldb_dn_linearize_casefold(struct ldb_context *ldb, const struct ldb_dn *edn) +{ + struct ldb_dn *cdn; + char *dn; + + if (edn == NULL) return NULL; + + /* Special DNs */ + if (ldb_dn_is_special(edn)) { + dn = talloc_strdup(ldb, edn->components[0].value.data); + return dn; + } + + cdn = ldb_dn_casefold(ldb, edn); + if (cdn == NULL) return NULL; + + dn = ldb_dn_linearize(ldb, cdn); + if (dn == NULL) { + talloc_free(cdn); + return NULL; + } + + talloc_free(cdn); + return dn; +} + +static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src) +{ + struct ldb_dn_component dst; + + dst.name = NULL; + + if (src == NULL) { + return dst; + } + + dst.value = ldb_val_dup(mem_ctx, &(src->value)); + if (dst.value.data == NULL) { + return dst; + } + + dst.name = talloc_strdup(mem_ctx, src->name); + if (dst.name == NULL) { + talloc_free(dst.value.data); + } + + return dst; +} + +/* copy specified number of elements of a dn into a new one + element are copied from top level up to the unique rdn + num_el may be greater then dn->comp_num (see ldb_dn_make_child) +*/ +struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el) +{ + struct ldb_dn *new; + int i, n, e; + + if (dn == NULL) return NULL; + if (num_el <= 0) return NULL; + + new = ldb_dn_new(mem_ctx); + LDB_DN_NULL_FAILED(new); + + new->comp_num = num_el; + n = new->comp_num - 1; + new->components = talloc_array(new, struct ldb_dn_component, new->comp_num); + + if (dn->comp_num == 0) return new; + e = dn->comp_num - 1; + + for (i = 0; i < new->comp_num; i++) { + new->components[n - i] = ldb_dn_copy_component(new->components, + &(dn->components[e - i])); + if ((e - i) == 0) { + return new; + } + } + + return new; + +failed: + talloc_free(new); + return NULL; +} + +struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn) +{ + if (dn == NULL) return NULL; + return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num); +} + +struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn) +{ + if (dn == NULL) return NULL; + return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1); +} + +struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr, + const char *val) +{ + struct ldb_dn_component *dc; + + if (attr == NULL || val == NULL) return NULL; + + dc = talloc(mem_ctx, struct ldb_dn_component); + if (dc == NULL) return NULL; + + dc->name = talloc_strdup(dc, attr); + if (dc->name == NULL) { + talloc_free(dc); + return NULL; + } + + dc->value.data = talloc_strdup(dc, val); + if (dc->value.data == NULL) { + talloc_free(dc); + return NULL; + } + + dc->value.length = strlen(val); + + return dc; +} + +struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr, + const char * value, + const struct ldb_dn *base) +{ + struct ldb_dn *new; + if (! ldb_dn_is_valid_attribute_name(attr)) return NULL; + if (value == NULL || value == '\0') return NULL; + + if (base != NULL) { + new = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1); + LDB_DN_NULL_FAILED(new); + } else { + new = ldb_dn_new(mem_ctx); + LDB_DN_NULL_FAILED(new); + + new->comp_num = 1; + new->components = talloc_array(new, struct ldb_dn_component, new->comp_num); + } + + new->components[0].name = talloc_strdup(new->components, attr); + LDB_DN_NULL_FAILED(new->components[0].name); + + new->components[0].value.data = talloc_strdup(new->components, value); + LDB_DN_NULL_FAILED(new->components[0].value.data); + new->components[0].value.length = strlen(new->components[0].value.data); + + return new; + +failed: + talloc_free(new); + return NULL; + +} + +struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component, + const struct ldb_dn *base) +{ + if (component == NULL) return NULL; + + return ldb_dn_build_child(mem_ctx, component->name, component->value.data, base); +} + +struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2) +{ + int i; + struct ldb_dn *new; + + if (dn2 == NULL && dn1 == NULL) { + return NULL; + } + + if (dn2 == NULL) { + new = ldb_dn_new(mem_ctx); + LDB_DN_NULL_FAILED(new); + + new->comp_num = dn1->comp_num; + new->components = talloc_array(new, struct ldb_dn_component, new->comp_num); + } else { + new = ldb_dn_copy_partial(mem_ctx, dn2, dn2->comp_num + dn1?dn1->comp_num:0); + } + + if (dn1 == NULL) { + return new; + } + + for (i = 0; i < dn1->comp_num; i++) { + new->components[i] = ldb_dn_copy_component(new->components, + &(dn1->components[i])); + } + + return new; + +failed: + talloc_free(new); + return NULL; +} + +struct ldb_dn *ldb_dn_compose_string_dn(void *mem_ctx, const char *dn1, const struct ldb_dn *dn2) +{ + if (dn1 == NULL) return NULL; + + return ldb_dn_compose(mem_ctx, ldb_dn_explode(mem_ctx, dn1), dn2); +} + +struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn) +{ + struct ldb_dn_component *rdn; + + if (dn == NULL) return NULL; + + if (dn->comp_num < 1) { + return NULL; + } + + rdn = talloc(mem_ctx, struct ldb_dn_component); + if (rdn == NULL) return NULL; + + *rdn = ldb_dn_copy_component(mem_ctx, &dn->components[0]); + if (rdn->name == NULL) { + talloc_free(rdn); + return NULL; + } + + return rdn; +} + diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 463bae483b..6359c9a014 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -275,7 +275,7 @@ int ldb_ldif_write(struct ldb_context *ldb, msg = ldif->msg; - ret = fprintf_fn(private_data, "dn: %s\n", msg->dn); + ret = fprintf_fn(private_data, "dn: %s\n", ldb_dn_linearize(msg->dn, msg->dn)); CHECK_RET; if (ldif->changetype != LDB_CHANGETYPE_NONE) { @@ -587,7 +587,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, goto failed; } - msg->dn = value.data; + msg->dn = ldb_dn_explode(msg, value.data); while (next_attr(ldif, &s, &attr, &value) == 0) { const struct ldb_attrib_handler *h; diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index b6f5f5a18d..1269d99a0f 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -42,27 +42,16 @@ check if the scope matches in a search result */ static int ldb_match_scope(struct ldb_context *ldb, - const char *base_str, - const char *dn_str, + const struct ldb_dn *base, + const struct ldb_dn *dn, enum ldb_scope scope) { - struct ldb_dn *base; - struct ldb_dn *dn; int ret = 0; - if (base_str == NULL) { + if (base == NULL || dn == NULL) { return 1; } - base = ldb_dn_explode_casefold(ldb, base_str); - if (base == NULL) return 0; - - dn = ldb_dn_explode_casefold(ldb, dn_str); - if (dn == NULL) { - talloc_free(base); - return 0; - } - switch (scope) { case LDB_SCOPE_BASE: if (ldb_dn_compare(ldb, base, dn) == 0) { @@ -86,8 +75,6 @@ static int ldb_match_scope(struct ldb_context *ldb, break; } - talloc_free(base); - talloc_free(dn); return ret; } @@ -98,7 +85,6 @@ static int ldb_match_scope(struct ldb_context *ldb, static int ldb_match_present(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope) { @@ -116,7 +102,6 @@ static int ldb_match_present(struct ldb_context *ldb, static int ldb_match_comparison(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope, enum ldb_parse_op comp_op) { @@ -158,29 +143,23 @@ static int ldb_match_comparison(struct ldb_context *ldb, static int ldb_match_equality(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope) { unsigned int i; struct ldb_message_element *el; const struct ldb_attrib_handler *h; - struct ldb_dn *msgdn, *valuedn; + struct ldb_dn *valuedn; int ret; if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { - msgdn = ldb_dn_explode_casefold(ldb, msg->dn); - if (msgdn == NULL) return 0; - valuedn = ldb_dn_explode_casefold(ldb, tree->u.equality.value.data); if (valuedn == NULL) { - talloc_free(msgdn); return 0; } - ret = ldb_dn_compare(ldb, msgdn, valuedn); + ret = ldb_dn_compare(ldb, msg->dn, valuedn); - talloc_free(msgdn); talloc_free(valuedn); if (ret == 0) return 1; @@ -277,7 +256,6 @@ failed: static int ldb_match_substring(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope) { unsigned int i; @@ -327,7 +305,6 @@ static int ldb_comparator_or(struct ldb_val *v1, struct ldb_val *v2) static int ldb_match_extended(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope) { int i; @@ -391,7 +368,6 @@ static int ldb_match_extended(struct ldb_context *ldb, static int ldb_match_message(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, enum ldb_scope scope) { unsigned int i; @@ -400,43 +376,41 @@ static int ldb_match_message(struct ldb_context *ldb, switch (tree->operation) { case LDB_OP_AND: for (i=0;iu.list.num_elements;i++) { - v = ldb_match_message(ldb, msg, tree->u.list.elements[i], - base, scope); + v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope); if (!v) return 0; } return 1; case LDB_OP_OR: for (i=0;iu.list.num_elements;i++) { - v = ldb_match_message(ldb, msg, tree->u.list.elements[i], - base, scope); + v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope); if (v) return 1; } return 0; case LDB_OP_NOT: - return ! ldb_match_message(ldb, msg, tree->u.isnot.child, base, scope); + return ! ldb_match_message(ldb, msg, tree->u.isnot.child, scope); case LDB_OP_EQUALITY: - return ldb_match_equality(ldb, msg, tree, base, scope); + return ldb_match_equality(ldb, msg, tree, scope); case LDB_OP_SUBSTRING: - return ldb_match_substring(ldb, msg, tree, base, scope); + return ldb_match_substring(ldb, msg, tree, scope); case LDB_OP_GREATER: - return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_GREATER); + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER); case LDB_OP_LESS: - return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_LESS); + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS); case LDB_OP_PRESENT: - return ldb_match_present(ldb, msg, tree, base, scope); + return ldb_match_present(ldb, msg, tree, scope); case LDB_OP_APPROX: - return ldb_match_comparison(ldb, msg, tree, base, scope, LDB_OP_APPROX); + return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX); case LDB_OP_EXTENDED: - return ldb_match_extended(ldb, msg, tree, base, scope); + return ldb_match_extended(ldb, msg, tree, scope); } @@ -446,12 +420,12 @@ static int ldb_match_message(struct ldb_context *ldb, int ldb_match_msg(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope) { if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { return 0; } - return ldb_match_message(ldb, msg, tree, base, scope); + return ldb_match_message(ldb, msg, tree, scope); } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index dcc384ffad..ab743d1b49 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -139,8 +139,15 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) int ret; const char * const attrs[] = { "@LIST" , NULL}; struct ldb_message **msg = NULL; + struct ldb_dn *mods; - ret = ldb_search(ldb, "@MODULES", LDB_SCOPE_BASE, "", attrs, &msg); + mods = ldb_dn_explode(ldb, "@MODULES"); + if (mods == NULL) { + return -1; + } + + ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg); + talloc_free(mods); if (ret == 0 || (ret == 1 && msg[0]->num_elements == 0)) { ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n"); } else { @@ -233,7 +240,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) */ int ldb_next_search(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -245,7 +252,7 @@ int ldb_next_search(struct ldb_module *module, } int ldb_next_search_bytree(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -272,7 +279,7 @@ int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message * return module->next->ops->modify_record(module->next, message); } -int ldb_next_delete_record(struct ldb_module *module, const char *dn) +int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { if (!module->next) { return -1; @@ -280,7 +287,7 @@ int ldb_next_delete_record(struct ldb_module *module, const char *dn) return module->next->ops->delete_record(module->next, dn); } -int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { if (!module->next) { return -1; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 295c74c90d..197c42ddb5 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -344,7 +344,6 @@ const char *ldb_msg_find_string(const struct ldb_message *msg, return v->data; } - /* sort the elements of a message by name */ @@ -354,32 +353,23 @@ void ldb_msg_sort_elements(struct ldb_message *msg) (comparison_fn_t)ldb_msg_element_compare_name); } - -/* - free a message created using ldb_msg_copy -*/ -void ldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg) -{ - talloc_free(msg); -} - /* copy a message, allocating new memory for all parts */ -struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, +struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, const struct ldb_message *msg) { struct ldb_message *msg2; int i, j; - msg2 = talloc(ldb, struct ldb_message); + msg2 = talloc(mem_ctx, struct ldb_message); if (msg2 == NULL) return NULL; msg2->elements = NULL; msg2->num_elements = 0; msg2->private_data = NULL; - msg2->dn = talloc_strdup(msg2, msg->dn); + msg2->dn = ldb_dn_copy(msg2, msg->dn); if (msg2->dn == NULL) goto failed; msg2->elements = talloc_array(msg2, struct ldb_message_element, msg->num_elements); @@ -396,12 +386,11 @@ struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, if (el2->name == NULL) goto failed; el2->values = talloc_array(msg2->elements, struct ldb_val, el1->num_values); for (j=0;jnum_values;j++) { - el2->values[j] = ldb_val_dup(ldb, &el1->values[j]); + el2->values[j] = ldb_val_dup(el2->values, &el1->values[j]); if (el2->values[j].data == NULL && el1->values[j].length != 0) { goto failed; } - el2->values[j].data = talloc_steal(el2->values, el2->values[j].data); el2->num_values++; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index fdf5dc8d91..13c9b72e6d 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -64,6 +64,16 @@ struct ldb_val { }; #endif +/* internal ldb exploded dn structures */ +struct ldb_dn_component { + char *name; + struct ldb_val value; +}; +struct ldb_dn { + int comp_num; + struct ldb_dn_component *components; +}; + /* these flags are used in ldd_message_element.flags fields. The LDA_FLAGS_MOD_* flags are used in ldap_modify() calls to specify whether attributes are being added, deleted or modified */ @@ -95,7 +105,7 @@ struct ldb_message_element { number of elements. */ struct ldb_message { - char *dn; + struct ldb_dn *dn; unsigned int num_elements; struct ldb_message_element *elements; void *private_data; /* private to the backend */ @@ -259,7 +269,7 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co use talloc_free to free the ldb_message returned */ int ldb_search(struct ldb_context *ldb, - const char *base, + const const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res); @@ -268,7 +278,7 @@ int ldb_search(struct ldb_context *ldb, like ldb_search() but takes a parse tree */ int ldb_search_bytree(struct ldb_context *ldb, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res); @@ -289,7 +299,7 @@ int ldb_modify(struct ldb_context *ldb, /* rename a record in the database */ -int ldb_rename(struct ldb_context *ldb, const char *olddn, const char *newdn); +int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn); /* create a named lock @@ -304,7 +314,7 @@ int ldb_unlock(struct ldb_context *ldb, const char *lockname); /* delete a record from the database */ -int ldb_delete(struct ldb_context *ldb, const char *dn); +int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn); /* @@ -337,19 +347,38 @@ int ldb_attrib_add_handlers(struct ldb_context *ldb, const struct ldb_attrib_handler *handlers, unsigned num_handlers); +/* The following definitions come from lib/ldb/common/ldb_dn.c */ +BOOL ldb_dn_is_special(const struct ldb_dn *dn); +BOOL ldb_dn_check_special(const struct ldb_dn *dn, const char *check); +char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value); +struct ldb_dn *ldb_dn_new(void *mem_ctx); +struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); +char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn); +char *ldb_dn_linearize_casefold(struct ldb_context *ldb, const struct ldb_dn *edn); +int ldb_dn_compare_base(struct ldb_context *ldb, const struct ldb_dn *base, const struct ldb_dn *dn); +int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1); +struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn); +struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn); +struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el); +struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn); +struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn); +struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr, + const char *val); +struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr, + const char * value, + const struct ldb_dn *base); +struct ldb_dn *ldb_dn_make_child(void *mem_ctx, + const struct ldb_dn_component *component, + const struct ldb_dn *base); +struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2); +struct ldb_dn *ldb_dn_compose_string_dn(void *mem_ctx, const char *dn1, const struct ldb_dn *dn2); +struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn); /* useful functions for ldb_message structure manipulation */ - int ldb_dn_cmp(struct ldb_context *ldb, const char *dn1, const char *dn2); int ldb_attr_cmp(const char *dn1, const char *dn2); char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value); -/* case-fold a DN */ -char *ldb_dn_fold(void * mem_ctx, - const char * dn, - void * user_data, - int (* case_fold_attr_fn)(void * user_data, char * attr)); - /* create an empty message */ struct ldb_message *ldb_msg_new(void *mem_ctx); @@ -411,9 +440,7 @@ const char *ldb_msg_find_string(const struct ldb_message *msg, void ldb_msg_sort_elements(struct ldb_message *msg); -void ldb_msg_free(struct ldb_context *ldb, struct ldb_message *msg); - -struct ldb_message *ldb_msg_copy(struct ldb_context *ldb, +struct ldb_message *ldb_msg_copy(void *mem_ctx, const struct ldb_message *msg); struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 43e6a3ecba..f5b50f5fc0 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -56,14 +56,14 @@ struct ldb_module { */ struct ldb_module_ops { const char *name; - int (*search)(struct ldb_module *, const char *, enum ldb_scope, + int (*search)(struct ldb_module *, const struct ldb_dn *, enum ldb_scope, const char *, const char * const [], struct ldb_message ***); - int (*search_bytree)(struct ldb_module *, const char *, enum ldb_scope, + int (*search_bytree)(struct ldb_module *, const struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const [], struct ldb_message ***); int (*add_record)(struct ldb_module *, const struct ldb_message *); int (*modify_record)(struct ldb_module *, const struct ldb_message *); - int (*delete_record)(struct ldb_module *, const char *); - int (*rename_record)(struct ldb_module *, const char *, const char *); + int (*delete_record)(struct ldb_module *, const struct ldb_dn *); + int (*rename_record)(struct ldb_module *, const struct ldb_dn *, const struct ldb_dn *); int (*named_lock)(struct ldb_module *, const char *); int (*named_unlock)(struct ldb_module *, const char *); const char * (*errstring)(struct ldb_module *); @@ -106,16 +106,6 @@ struct ldb_context { struct ldb_schema schema; }; -/* internal ldb exploded dn structures */ -struct ldb_dn_component { - char *name; - struct ldb_val value; -}; -struct ldb_dn { - int comp_num; - struct ldb_dn_component *components; -}; - /* the modules init function */ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, const char *options[]); @@ -132,19 +122,19 @@ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, int ldb_load_modules(struct ldb_context *ldb, const char *options[]); int ldb_next_search(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res); int ldb_next_search_bytree(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res); int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); -int ldb_next_delete_record(struct ldb_module *module, const char *dn); -int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn); +int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn); +int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn); int ldb_next_named_lock(struct ldb_module *module, const char *lockname); int ldb_next_named_unlock(struct ldb_module *module, const char *lockname); const char *ldb_next_errstring(struct ldb_module *module); @@ -174,10 +164,10 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[]); -int ldb_match_msg(struct ldb_context *ldb, +int ldb_match_msg(struct ldb_context *ldb, struct ldb_message *msg, struct ldb_parse_tree *tree, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope); void ldb_remove_attrib_handler(struct ldb_context *ldb, const char *attrib); @@ -188,15 +178,6 @@ int ldb_set_attrib_handlers(struct ldb_context *ldb, unsigned num_handlers); int ldb_setup_wellknown_attributes(struct ldb_context *ldb); - -/* The following definitions come from lib/ldb/common/ldb_dn.c */ -struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); -char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn); -int ldb_dn_compare_base(struct ldb_context *ldb, const struct ldb_dn *base, const struct ldb_dn *dn); -int ldb_dn_compare(struct ldb_context *ldb, const struct ldb_dn *edn0, const struct ldb_dn *edn1); -struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn); -struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn); - /* The following definitions come from lib/ldb/common/ldb_attributes.c */ const char **ldb_subclass_list(struct ldb_context *ldb, const char *class); void ldb_subclass_remove(struct ldb_context *ldb, const char *class); diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index b51139aa6f..bb89fc910e 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -45,57 +45,77 @@ struct ildb_private { /* rename a record */ -static int ildb_rename(struct ldb_module *module, const char *olddn, const char *newdn) +static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { + TALLOC_CTX *local_ctx; struct ildb_private *ildb = module->private_data; int ret = 0; - char *newrdn, *p; - const char *parentdn = ""; + char *old_dn; + char *newrdn, *parentdn; /* ignore ltdb specials */ - if (olddn[0] == '@' ||newdn[0] == '@') { + if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) { return 0; } - newrdn = talloc_strdup(ildb, newdn); - if (!newrdn) { + local_ctx = talloc_named(ildb, 0, "ildb_rename local context"); + if (local_ctx == NULL) { return -1; } - p = strchr(newrdn, ','); - if (p) { - *p++ = '\0'; - parentdn = p; + old_dn = ldb_dn_linearize(local_ctx, olddn); + if (old_dn == NULL) { + goto failed; + } + + newrdn = talloc_asprintf(local_ctx, "%s=%s", + newdn->components[0].name, + ldb_dn_escape_value(ildb, newdn->components[0].value)); + if (newrdn == NULL) { + goto failed; + } + + parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn)); + if (parentdn == NULL) { + goto failed; } - ildb->last_rc = ildap_rename(ildb->ldap, olddn, newrdn, parentdn, True); + ildb->last_rc = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True); if (!NT_STATUS_IS_OK(ildb->last_rc)) { ret = -1; } - talloc_free(newrdn); - + talloc_free(local_ctx); return ret; + +failed: + talloc_free(local_ctx); + return -1; } /* delete a record */ -static int ildb_delete(struct ldb_module *module, const char *dn) +static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ildb_private *ildb = module->private_data; + char *del_dn; int ret = 0; /* ignore ltdb specials */ - if (dn[0] == '@') { + if (ldb_dn_is_special(dn)) { return 0; } - ildb->last_rc = ildap_delete(ildb->ldap, dn); + del_dn = ldb_dn_linearize(ildb, dn); + + ildb->last_rc = ildap_delete(ildb->ldap, del_dn); if (!NT_STATUS_IS_OK(ildb->last_rc)) { ret = -1; } + talloc_free(del_dn); + return ret; } @@ -105,13 +125,14 @@ static void ildb_rootdse(struct ldb_module *module); /* search for matching records */ -static int ildb_search(struct ldb_module *module, const char *base, +static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { struct ildb_private *ildb = module->private_data; int count, i; struct ldap_message **ldapres, *msg; + char *search_base; if (scope == LDB_SCOPE_DEFAULT) { scope = LDB_SCOPE_SUBTREE; @@ -122,19 +143,26 @@ static int ildb_search(struct ldb_module *module, const char *base, ildb_rootdse(module); } if (ildb->rootDSE != NULL) { - base = ldb_msg_find_string(ildb->rootDSE, - "defaultNamingContext", ""); + search_base = talloc_strdup(ildb, + ldb_msg_find_string(ildb->rootDSE, + "defaultNamingContext", "")); } else { - base = ""; + search_base = talloc_strdup(ildb, ""); } + } else { + search_base = ldb_dn_linearize(ildb, base); + } + if (search_base == NULL) { + return -1; } if (expression == NULL || expression[0] == '\0') { expression = "objectClass=*"; } - ildb->last_rc = ildap_search(ildb->ldap, base, scope, expression, attrs, + ildb->last_rc = ildap_search(ildb->ldap, search_base, scope, expression, attrs, 0, &ldapres); + talloc_free(search_base); if (!NT_STATUS_IS_OK(ildb->last_rc)) { return -1; } @@ -166,7 +194,10 @@ static int ildb_search(struct ldb_module *module, const char *base, } (*res)[i+1] = NULL; - (*res)[i]->dn = talloc_steal((*res)[i], search->dn); + (*res)[i]->dn = ldb_dn_explode((*res)[i], search->dn); + if ((*res)[i]->dn == NULL) { + goto failed; + } (*res)[i]->num_elements = search->num_attributes; (*res)[i]->elements = talloc_steal((*res)[i], search->attributes); (*res)[i]->private_data = NULL; @@ -185,7 +216,7 @@ failed: /* search for matching records using a ldb_parse_tree */ -static int ildb_search_bytree(struct ldb_module *module, const char *base, +static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -264,16 +295,26 @@ static int ildb_add(struct ldb_module *module, const struct ldb_message *msg) struct ldb_context *ldb = module->ldb; struct ildb_private *ildb = module->private_data; struct ldap_mod **mods; + char *dn; int ret = 0; /* ignore ltdb specials */ - if (msg->dn[0] == '@') { + if (ldb_dn_is_special(msg->dn)) { return 0; } mods = ildb_msg_to_mods(ldb, msg, 0); + if (mods == NULL) { + return -1; + } - ildb->last_rc = ildap_add(ildb->ldap, msg->dn, mods); + dn = ldb_dn_linearize(mods, msg->dn); + if (dn == NULL) { + talloc_free(mods); + return -1; + } + + ildb->last_rc = ildap_add(ildb->ldap, dn, mods); if (!NT_STATUS_IS_OK(ildb->last_rc)) { ret = -1; } @@ -292,16 +333,26 @@ static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg) struct ldb_context *ldb = module->ldb; struct ildb_private *ildb = module->private_data; struct ldap_mod **mods; + char *dn; int ret = 0; /* ignore ltdb specials */ - if (msg->dn[0] == '@') { + if (ldb_dn_is_special(msg->dn)) { return 0; } mods = ildb_msg_to_mods(ldb, msg, 1); + if (mods == NULL) { + return -1; + } + + dn = ldb_dn_linearize(mods, msg->dn); + if (dn == NULL) { + talloc_free(mods); + return -1; + } - ildb->last_rc = ildap_modify(ildb->ldap, msg->dn, mods); + ildb->last_rc = ildap_modify(ildb->ldap, dn, mods); if (!NT_STATUS_IS_OK(ildb->last_rc)) { ret = -1; } @@ -372,12 +423,14 @@ static void ildb_rootdse(struct ldb_module *module) { struct ildb_private *ildb = module->private_data; struct ldb_message **res = NULL; + struct ldb_dn *empty_dn = ldb_dn_new(ildb); int ret; - ret = ildb_search(module, "", LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res); + ret = ildb_search(module, empty_dn, LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res); if (ret == 1) { ildb->rootDSE = talloc_steal(ildb, res[0]); } - talloc_free(res); + if (ret != -1) talloc_free(res); + talloc_free(empty_dn); } diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index d7f589e2e5..2da4f1af8e 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -40,57 +40,77 @@ /* rename a record */ -static int lldb_rename(struct ldb_module *module, const char *olddn, const char *newdn) +static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { + TALLOC_CTX *local_ctx; struct lldb_private *lldb = module->private_data; int ret = 0; - char *newrdn, *p; + char *old_dn; + char *newrdn; const char *parentdn = ""; /* ignore ltdb specials */ - if (olddn[0] == '@' ||newdn[0] == '@') { + if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) { return 0; } - newrdn = talloc_strdup(lldb, newdn); - if (!newrdn) { + local_ctx = talloc_named(lldb, 0, "lldb_rename local context"); + if (local_ctx == NULL) { return -1; } - p = strchr(newrdn, ','); - if (p) { - *p++ = '\0'; - parentdn = p; + old_dn = ldb_dn_linearize(local_ctx, olddn); + if (old_dn == NULL) { + goto failed; + } + + newrdn = talloc_asprintf(lldb, "%s=%s", + newdn->components[0].name, + ldb_dn_escape_value(lldb, newdn->components[0].value)); + if (!newrdn) { + goto failed; + } + + parentdn = ldb_dn_linearize(lldb, ldb_dn_get_parent(lldb, newdn)); + if (!parentdn) { + goto failed; } - lldb->last_rc = ldap_rename_s(lldb->ldap, olddn, newrdn, parentdn, 1, NULL, NULL); + lldb->last_rc = ldap_rename_s(lldb->ldap, old_dn, newrdn, parentdn, 1, NULL, NULL); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } - talloc_free(newrdn); - + talloc_free(local_ctx); return ret; + +failed: + talloc_free(local_ctx); + return -1; } /* delete a record */ -static int lldb_delete(struct ldb_module *module, const char *dn) +static int lldb_delete(struct ldb_module *module, const struct ldb_dn *edn) { struct lldb_private *lldb = module->private_data; + char *dn; int ret = 0; /* ignore ltdb specials */ - if (dn[0] == '@') { + if (ldb_dn_is_special(edn)) { return 0; } - + + dn = ldb_dn_linearize(lldb, edn); + lldb->last_rc = ldap_delete_s(lldb->ldap, dn); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } + talloc_free(dn); return ret; } @@ -152,27 +172,33 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, /* search for matching records */ -static int lldb_search(struct ldb_module *module, const char *base, +static int lldb_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; struct lldb_private *lldb = module->private_data; int count, msg_count; + char *search_base; LDAPMessage *ldapres, *msg; + search_base = ldb_dn_linearize(ldb, base); if (base == NULL) { - base = ""; + search_base = talloc_strdup(ldb, ""); + } + if (search_base == NULL) { + return -1; } if (expression == NULL || expression[0] == '\0') { expression = "objectClass=*"; } - lldb->last_rc = ldap_search_s(lldb->ldap, base, (int)scope, + lldb->last_rc = ldap_search_s(lldb->ldap, search_base, (int)scope, expression, discard_const_p(char *, attrs), 0, &ldapres); + talloc_free(search_base); if (lldb->last_rc != LDAP_SUCCESS) { return -1; } @@ -218,7 +244,7 @@ static int lldb_search(struct ldb_module *module, const char *base, goto failed; } - (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn); + (*res)[msg_count]->dn = ldb_dn_explode((*res)[msg_count], dn); ldap_memfree(dn); if (!(*res)[msg_count]->dn) { goto failed; @@ -261,7 +287,7 @@ failed: /* search for matching records using a ldb_parse_tree */ -static int lldb_search_bytree(struct ldb_module *module, const char *base, +static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -357,16 +383,26 @@ static int lldb_add(struct ldb_module *module, const struct ldb_message *msg) struct ldb_context *ldb = module->ldb; struct lldb_private *lldb = module->private_data; LDAPMod **mods; + char *dn; int ret = 0; /* ignore ltdb specials */ - if (msg->dn[0] == '@') { + if (ldb_dn_is_special(msg->dn)) { return 0; } mods = lldb_msg_to_mods(ldb, msg, 0); + if (mods == NULL) { + return -1; + } - lldb->last_rc = ldap_add_s(lldb->ldap, msg->dn, mods); + dn = ldb_dn_linearize(mods, msg->dn); + if (dn == NULL) { + talloc_free(mods); + return -1; + } + + lldb->last_rc = ldap_add_s(lldb->ldap, dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } @@ -385,16 +421,26 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) struct ldb_context *ldb = module->ldb; struct lldb_private *lldb = module->private_data; LDAPMod **mods; + char *dn; int ret = 0; /* ignore ltdb specials */ - if (msg->dn[0] == '@') { + if (ldb_dn_is_special(msg->dn)) { return 0; } mods = lldb_msg_to_mods(ldb, msg, 1); + if (mods == NULL) { + return -1; + } + + dn = ldb_dn_linearize(mods, msg->dn); + if (dn == NULL) { + talloc_free(mods); + return -1; + } - lldb->last_rc = ldap_modify_s(lldb->ldap, msg->dn, mods); + lldb->last_rc = ldap_modify_s(lldb->ldap, dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { ret = -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index be76f7085b..5e40b8fd3f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -115,11 +115,17 @@ static int ltdb_attributes_load(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; struct ldb_message *msg = ltdb->cache->attributes; + struct ldb_dn *dn; int i; - if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, msg) == -1) { + dn = ldb_dn_explode(module->ldb, LTDB_ATTRIBUTES); + if (dn == NULL) goto failed; + + if (ltdb_search_dn1(module, dn, msg) == -1) { + talloc_free(dn); goto failed; } + talloc_free(dn); /* mapping these flags onto ldap 'syntaxes' isn't strictly correct, but its close enough for now */ for (i=0;inum_elements;i++) { @@ -176,11 +182,17 @@ static int ltdb_subclasses_load(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; struct ldb_message *msg = ltdb->cache->subclasses; + struct ldb_dn *dn; int i, j; - if (ltdb_search_dn1(module, LTDB_SUBCLASSES, msg) == -1) { + dn = ldb_dn_explode(module->ldb, LTDB_SUBCLASSES); + if (dn == NULL) goto failed; + + if (ltdb_search_dn1(module, dn, msg) == -1) { + talloc_free(dn); goto failed; } + talloc_free(dn); for (i=0;inum_elements;i++) { struct ldb_message_element *el = &msg->elements[i]; @@ -245,7 +257,7 @@ static int ltdb_baseinfo_init(struct ldb_module *module) msg->num_elements = 1; msg->elements = ⪙ - msg->dn = talloc_strdup(msg, LTDB_BASEINFO); + msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO); if (!msg->dn) { goto failed; } @@ -303,6 +315,8 @@ int ltdb_cache_reload(struct ldb_module *module) int ltdb_cache_load(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; + struct ldb_dn *baseinfo_dn = NULL; + struct ldb_dn *indexlist_dn = NULL; double seq; if (ltdb->cache == NULL) { @@ -321,8 +335,11 @@ int ltdb_cache_load(struct ldb_module *module) talloc_free(ltdb->cache->baseinfo); ltdb->cache->baseinfo = talloc(ltdb->cache, struct ldb_message); if (ltdb->cache->baseinfo == NULL) goto failed; - - if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) == -1) { + + baseinfo_dn = ldb_dn_explode(module->ldb, LTDB_BASEINFO); + if (baseinfo_dn == NULL) goto failed; + + if (ltdb_search_dn1(module, baseinfo_dn, ltdb->cache->baseinfo) == -1) { goto failed; } @@ -331,7 +348,7 @@ int ltdb_cache_load(struct ldb_module *module) if (ltdb_baseinfo_init(module) != 0) { goto failed; } - if (ltdb_search_dn1(module, LTDB_BASEINFO, ltdb->cache->baseinfo) != 1) { + if (ltdb_search_dn1(module, baseinfo_dn, ltdb->cache->baseinfo) != 1) { goto failed; } } @@ -362,7 +379,10 @@ int ltdb_cache_load(struct ldb_module *module) goto failed; } - if (ltdb_search_dn1(module, LTDB_INDEXLIST, ltdb->cache->indexlist) == -1) { + indexlist_dn = ldb_dn_explode(module->ldb, LTDB_INDEXLIST); + if (indexlist_dn == NULL) goto failed; + + if (ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist) == -1) { goto failed; } @@ -374,9 +394,13 @@ int ltdb_cache_load(struct ldb_module *module) } done: + talloc_free(baseinfo_dn); + talloc_free(indexlist_dn); return 0; failed: + talloc_free(baseinfo_dn); + talloc_free(indexlist_dn); return -1; } @@ -407,8 +431,18 @@ int ltdb_increase_sequence_number(struct ldb_module *module) msg->num_elements = 1; msg->elements = ⪙ - msg->dn = talloc_strdup(msg, LTDB_BASEINFO); + msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO); + if (msg->dn == NULL) { + talloc_free(msg); + errno = ENOMEM; + return -1; + } el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER); + if (el.name == NULL) { + talloc_free(msg); + errno = ENOMEM; + return -1; + } el.values = &val; el.num_values = 1; el.flags = LDB_FLAG_MOD_REPLACE; diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 2fb6c34227..f78d840206 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -97,10 +97,11 @@ struct dn_list { return the dn key to be used for an index caller frees */ -static char *ldb_dn_key(struct ldb_context *ldb, +static struct ldb_dn *ldb_dn_key(struct ldb_context *ldb, const char *attr, const struct ldb_val *value) { - char *ret = NULL; + struct ldb_dn *ret; + char *dn; struct ldb_val v; const struct ldb_attrib_handler *h; char *attr_folded; @@ -121,16 +122,17 @@ static char *ldb_dn_key(struct ldb_context *ldb, if (ldb_should_b64_encode(&v)) { char *vstr = ldb_base64_encode(ldb, v.data, v.length); if (!vstr) return NULL; - ret = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); + dn = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); talloc_free(vstr); if (v.data != value->data) { talloc_free(v.data); } talloc_free(attr_folded); - return ret; + if (dn == NULL) return NULL; + goto done; } - ret = talloc_asprintf(ldb, "%s:%s:%.*s", + dn = talloc_asprintf(ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data); if (v.data != value->data) { @@ -138,6 +140,9 @@ static char *ldb_dn_key(struct ldb_context *ldb, } talloc_free(attr_folded); +done: + ret = ldb_dn_explode(ldb, dn); + talloc_free(dn); return ret; } @@ -180,7 +185,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module, struct dn_list *list) { struct ldb_context *ldb = module->ldb; - char *dn = NULL; + struct ldb_dn *dn; int ret; unsigned int i, j; struct ldb_message *msg; @@ -605,7 +610,7 @@ static int ltdb_index_dn(struct ldb_module *module, extracting just the given attributes */ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tree, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, const struct dn_list *dn_list, const char * const attrs[], struct ldb_message ***res) @@ -613,8 +618,9 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr unsigned int i; int count = 0; - for (i=0;icount;i++) { + for (i = 0; i < dn_list->count; i++) { struct ldb_message *msg; + struct ldb_dn *dn; int ret; msg = talloc(module, struct ldb_message); @@ -622,7 +628,14 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr return -1; } - ret = ltdb_search_dn1(module, dn_list->dn[i], msg); + dn = ldb_dn_explode(msg, dn_list->dn[i]); + if (dn == NULL) { + talloc_free(msg); + return -1; + } + + ret = ltdb_search_dn1(module, dn, msg); + talloc_free(dn); if (ret == 0) { /* the record has disappeared? yes, this can happen */ talloc_free(msg); @@ -654,7 +667,7 @@ static int ldb_index_filter(struct ldb_module *module, struct ldb_parse_tree *tr case the caller should call ltdb_search_full() */ int ltdb_search_indexed(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) @@ -766,33 +779,32 @@ static int ltdb_index_add1(struct ldb_module *module, char *dn, { struct ldb_context *ldb = module->ldb; struct ldb_message *msg; - char *dn_key; + struct ldb_dn *dn_key; int ret; unsigned int i; - dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); - if (!dn_key) { + msg = talloc(module, struct ldb_message); + if (msg == NULL) { + errno = ENOMEM; return -1; } - msg = talloc(dn_key, struct ldb_message); - if (msg == NULL) { + dn_key = ldb_dn_key(ldb, el->name, &el->values[v_idx]); + if (!dn_key) { + talloc_free(msg); + errno = ENOMEM; return -1; } + talloc_steal(msg, dn_key); ret = ltdb_search_dn1(module, dn_key, msg); if (ret == -1) { - talloc_free(dn_key); + talloc_free(msg); return -1; } if (ret == 0) { - msg->dn = talloc_strdup(msg, dn_key); - if (!msg->dn) { - talloc_free(dn_key); - errno = ENOMEM; - return -1; - } + msg->dn = dn_key; msg->num_elements = 0; msg->elements = NULL; } @@ -813,22 +825,19 @@ static int ltdb_index_add1(struct ldb_module *module, char *dn, ret = ltdb_store(module, msg, TDB_REPLACE); } - talloc_free(dn_key); + talloc_free(msg); return ret; } -/* - add the index entries for a new record - return -1 on failure -*/ -int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) +static int ltdb_index_add0(struct ldb_module *module, char *dn, + struct ldb_message_element *elements, int num_el) { struct ltdb_private *ltdb = module->private_data; int ret; unsigned int i, j; - if (msg->dn[0] == '@') { + if (dn[0] == '@') { return 0; } @@ -837,15 +846,16 @@ int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) return 0; } - for (i=0;inum_elements;i++) { - ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name, + for (i = 0; i < num_el; i++) { + ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name, NULL, LTDB_IDXATTR); if (ret == -1) { continue; } - for (j=0;jelements[i].num_values;j++) { - ret = ltdb_index_add1(module, msg->dn, &msg->elements[i], j); + for (j = 0; j < elements[i].num_values; j++) { + ret = ltdb_index_add1(module, dn, &elements[i], j); if (ret == -1) { + talloc_free(dn); return -1; } } @@ -854,6 +864,28 @@ int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) return 0; } +/* + add the index entries for a new record + return -1 on failure +*/ +int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ltdb_private *ltdb = module->private_data; + char *dn; + int ret; + + dn = ldb_dn_linearize(ltdb, msg->dn); + if (dn == NULL) { + return -1; + } + + ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements); + + talloc_free(dn); + + return ret; +} + /* delete an index entry for one message element @@ -863,7 +895,7 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, { struct ldb_context *ldb = module->ldb; struct ldb_message *msg; - char *dn_key; + struct ldb_dn *dn_key; int ret, i; unsigned int j; @@ -897,7 +929,9 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX); if (i == -1) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "ERROR: dn %s not found in %s\n", dn, dn_key); + ldb_debug(ldb, LDB_DEBUG_ERROR, + "ERROR: dn %s not found in %s\n", dn, + ldb_dn_linearize(dn_key, dn_key)); /* it ain't there. hmmm */ talloc_free(dn_key); return 0; @@ -930,32 +964,40 @@ int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) { struct ltdb_private *ltdb = module->private_data; int ret; + char *dn; unsigned int i, j; - if (msg->dn[0] == '@') { + if (ldb_dn_is_special(msg->dn)) { return 0; } + dn = ldb_dn_linearize(ltdb, msg->dn); + if (dn == NULL) { + return -1; + } + /* find the list of indexed fields */ if (ltdb->cache->indexlist->num_elements == 0) { /* no indexed fields */ return 0; } - for (i=0;inum_elements;i++) { + for (i = 0; i < msg->num_elements; i++) { ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name, NULL, LTDB_IDXATTR); if (ret == -1) { continue; } - for (j=0;jelements[i].num_values;j++) { - ret = ltdb_index_del_value(module, msg->dn, &msg->elements[i], j); + for (j = 0; j < msg->elements[i].num_values; j++) { + ret = ltdb_index_del_value(module, dn, &msg->elements[i], j); if (ret == -1) { + talloc_free(dn); return -1; } } } + talloc_free(dn); return 0; } @@ -979,6 +1021,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * { struct ldb_module *module = state; struct ldb_message *msg; + char *dn = NULL; int ret; TDB_DATA key2; @@ -1003,7 +1046,9 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * key2 = ltdb_key(module, msg->dn); if (key2.dptr == NULL) { /* probably a corrupt record ... darn */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n", msg->dn); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n", + ldb_dn_linearize(msg, msg->dn)); + talloc_free(msg); return 0; } if (strcmp(key2.dptr, key.dptr) != 0) { @@ -1012,11 +1057,13 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * } talloc_free(key2.dptr); - if (!msg->dn) { - msg->dn = key.dptr+3; + if (msg->dn == NULL) { + dn = key.dptr + 3; + } else { + dn = ldb_dn_linearize(msg->dn, msg->dn); } - ret = ltdb_index_add(module, msg); + ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements); talloc_free(msg); diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 4433e16cb2..332dbf03df 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -74,9 +74,16 @@ int ltdb_pack_data(struct ldb_module *module, struct ldb_context *ldb = module->ldb; unsigned int i, j, real_elements=0; size_t size; + char *dn; char *p; size_t len; + dn = ldb_dn_linearize(ldb, message->dn); + if (dn == NULL) { + errno = ENOMEM; + return -1; + } + for (i=0;inum_elements;i++) { if (message->elements[i].num_values != 0) { real_elements++; @@ -86,7 +93,7 @@ int ltdb_pack_data(struct ldb_module *module, /* work out how big it needs to be */ size = 8; - size += 1 + strlen(message->dn); + size += 1 + strlen(dn); for (i=0;inum_elements;i++) { if (message->elements[i].num_values == 0) { @@ -101,6 +108,7 @@ int ltdb_pack_data(struct ldb_module *module, /* allocate it */ data->dptr = talloc_array(ldb, char, size); if (!data->dptr) { + talloc_free(dn); errno = ENOMEM; return -1; } @@ -113,8 +121,8 @@ int ltdb_pack_data(struct ldb_module *module, /* the dn needs to be packed so we can be case preserving while hashing on a case folded dn */ - len = strlen(message->dn); - memcpy(p, message->dn, len+1); + len = strlen(dn); + memcpy(p, dn, len+1); p += len + 1; for (i=0;inum_elements;i++) { @@ -135,6 +143,7 @@ int ltdb_pack_data(struct ldb_module *module, } } + talloc_free(dn); return 0; } @@ -179,7 +188,11 @@ int ltdb_unpack_data(struct ldb_module *module, errno = EIO; goto failed; } - message->dn = p; + message->dn = ldb_dn_explode(message, p); + if (message->dn == NULL) { + errno = ENOMEM; + goto failed; + } remaining -= len + 1; p += len + 1; break; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 922d24b6eb..160affd4e7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -94,7 +94,7 @@ static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *r for (i=0;inum_elements;i++) { const struct ldb_attrib_handler *h; h = ldb_attrib_handler(ldb, msg->elements[i].name); - if ((msg->dn[0] != '@') && (h->flags & LDB_ATTR_FLAG_HIDDEN)) { + if (ldb_dn_is_special(msg->dn) && (h->flags & LDB_ATTR_FLAG_HIDDEN)) { continue; } if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { @@ -122,7 +122,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, return NULL; } - ret->dn = talloc_strdup(ret, msg->dn); + ret->dn = ldb_dn_copy(ret, msg->dn); if (!ret->dn) { talloc_free(ret); return NULL; @@ -163,8 +163,8 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, } el2.num_values = 1; el2.values = &val; - val.data = ret->dn; - val.length = strlen(ret->dn); + val.data = ldb_dn_linearize(ret, ret->dn); + val.length = strlen(val.data); if (msg_add_element(ldb, ret, &el2) != 0) { talloc_free(ret); @@ -194,7 +194,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, return 1 on success, 0 on record-not-found and -1 on error */ -int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg) +int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg) { struct ltdb_private *ltdb = module->private_data; int ret; @@ -231,7 +231,7 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag } if (!msg->dn) { - msg->dn = talloc_strdup(tdb_data2.dptr, dn); + msg->dn = ldb_dn_copy(tdb_data2.dptr, dn); } if (!msg->dn) { talloc_free(tdb_data2.dptr); @@ -245,7 +245,7 @@ int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_messag /* search the database for a single simple dn */ -static int ltdb_search_dn(struct ldb_module *module, const char *dn, +static int ltdb_search_dn(struct ldb_module *module, const struct ldb_dn *dn, const char * const attrs[], struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; @@ -347,7 +347,7 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, struct ltdb_search_info { struct ldb_module *module; struct ldb_parse_tree *tree; - const char *base; + const struct ldb_dn *base; enum ldb_scope scope; const char * const *attrs; struct ldb_message **msgs; @@ -384,7 +384,11 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } if (!msg->dn) { - msg->dn = key.dptr + 3; + msg->dn = ldb_dn_explode(msg, key.dptr + 3); + if (msg->dn == NULL) { + talloc_free(msg); + return -1; + } } /* see if it matches the given expression */ @@ -411,7 +415,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi this is the "full search" non-indexed variant */ static int ltdb_search_full(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) @@ -454,7 +458,7 @@ static int ltdb_search_full(struct ldb_module *module, search the database with a LDAP-like expression. choses a search method */ -int ltdb_search_bytree(struct ldb_module *module, const char *base, +int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) { @@ -466,7 +470,14 @@ int ltdb_search_bytree(struct ldb_module *module, const char *base, if (tree->operation == LDB_OP_EQUALITY && (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0 || ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0)) { - return ltdb_search_dn(module, tree->u.equality.value.data, attrs, res); + struct ldb_dn *dn; + dn = ldb_dn_explode(module->ldb, tree->u.equality.value.data); + if (dn == NULL) { + return -1; + } + ret = ltdb_search_dn(module, dn, attrs, res); + talloc_free(dn); + return ret; } if (ltdb_lock_read(module) != 0) { @@ -497,7 +508,7 @@ int ltdb_search_bytree(struct ldb_module *module, const char *base, search the database with a LDAP-like expression. choses a search method */ -int ltdb_search(struct ldb_module *module, const char *base, +int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const attrs[], struct ldb_message ***res) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 40cfe97c29..61d0f9b64a 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -50,14 +50,12 @@ note that the key for a record can depend on whether the dn refers to a case sensitive index record or not */ -struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) +struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn) { struct ldb_context *ldb = module->ldb; TDB_DATA key; char *key_str = NULL; char *dn_folded = NULL; - struct ldb_dn *edn = NULL; - struct ldb_dn *cedn = NULL; /* most DNs are case insensitive. The exception is index DNs for @@ -70,26 +68,14 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) 2) if the dn starts with @ then leave it alone - the indexing code handles the rest */ - if (*dn == '@') { - dn_folded = talloc_strdup(ldb, dn); - } else { - edn = ldb_dn_explode(ldb, dn); - if (!edn) - goto failed; - - cedn = ldb_dn_casefold(ldb, edn); - if (!cedn) - goto failed; - - dn_folded = ldb_dn_linearize(ldb, cedn); - if (!dn_folded) - goto failed; - talloc_free(edn); - talloc_free(cedn); + dn_folded = ldb_dn_linearize_casefold(ldb, dn); + if (!dn_folded) { + goto failed; } key_str = talloc_asprintf(ldb, "DN=%s", dn_folded); + talloc_free(dn_folded); if (!key_str) { @@ -102,8 +88,6 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) return key; failed: - talloc_free(edn); - talloc_free(cedn); errno = ENOMEM; key.dptr = NULL; key.dsize = 0; @@ -116,7 +100,8 @@ failed: static int ltdb_lock(struct ldb_module *module, const char *lockname) { struct ltdb_private *ltdb = module->private_data; - char *lock_dn; + struct ldb_dn *lock_dn; + char *ldn; TDB_DATA key; int ret; @@ -124,10 +109,17 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) return -1; } - lock_dn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + ldn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + if (ldn == NULL) { + return -1; + } + + lock_dn = ldb_dn_explode(module->ldb, ldn); if (lock_dn == NULL) { + talloc_free(ldn); return -1; } + talloc_free(ldn); key = ltdb_key(module, lock_dn); if (!key.dptr) { @@ -149,17 +141,25 @@ static int ltdb_lock(struct ldb_module *module, const char *lockname) static int ltdb_unlock(struct ldb_module *module, const char *lockname) { struct ltdb_private *ltdb = module->private_data; - char *lock_dn; + struct ldb_dn *lock_dn; + char *ldn; TDB_DATA key; if (lockname == NULL) { return -1; } - lock_dn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + ldn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); + if (ldn == NULL) { + return -1; + } + + lock_dn = ldb_dn_explode(module->ldb, ldn); if (lock_dn == NULL) { + talloc_free(ldn); return -1; } + talloc_free(ldn); key = ltdb_key(module, lock_dn); if (!key.dptr) { @@ -183,11 +183,21 @@ int ltdb_lock_read(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; TDB_DATA key; + struct ldb_dn *lock_dn; int ret; - key = ltdb_key(module, LDBLOCK); + + lock_dn = ldb_dn_explode(module, LDBLOCK); + if (lock_dn == NULL) { + return -1; + } + + key = ltdb_key(module, lock_dn); if (!key.dptr) { + talloc_free(lock_dn); return -1; } + talloc_free(lock_dn); + ret = tdb_chainlock_read(ltdb->tdb, key); talloc_free(key.dptr); return ret; @@ -199,11 +209,21 @@ int ltdb_lock_read(struct ldb_module *module) int ltdb_unlock_read(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; + struct ldb_dn *lock_dn; TDB_DATA key; - key = ltdb_key(module, LDBLOCK); + + lock_dn = ldb_dn_explode(module, LDBLOCK); + if (lock_dn == NULL) { + return -1; + } + + key = ltdb_key(module, lock_dn); if (!key.dptr) { + talloc_free(lock_dn); return -1; } + talloc_free(lock_dn); + tdb_chainunlock_read(ltdb->tdb, key); talloc_free(key.dptr); return 0; @@ -217,8 +237,9 @@ int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *m { struct ltdb_private *ltdb = module->private_data; int i, j; - - if (strcmp(msg->dn, LTDB_ATTRIBUTES) != 0) { + + if (! ldb_dn_is_special(msg->dn) || + ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) { return 0; } @@ -241,17 +262,19 @@ int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *m we've made a modification to a dn - possibly reindex and update sequence number */ -static int ltdb_modified(struct ldb_module *module, const char *dn) +static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn) { int ret = 0; - if (strcmp(dn, LTDB_INDEXLIST) == 0 || - strcmp(dn, LTDB_ATTRIBUTES) == 0) { + if (ldb_dn_is_special(dn) && + (ldb_dn_check_special(dn, LTDB_INDEXLIST) || + ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) { ret = ltdb_reindex(module); } if (ret == 0 && - strcmp(dn, LTDB_BASEINFO) != 0) { + !(ldb_dn_is_special(dn) && + ldb_dn_check_special(dn, LTDB_BASEINFO)) ) { ret = ltdb_increase_sequence_number(module); } @@ -335,7 +358,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) delete a record from the database, not updating indexes (used for deleting index records) */ -int ltdb_delete_noindex(struct ldb_module *module, const char *dn) +int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn) { struct ltdb_private *ltdb = module->private_data; TDB_DATA tdb_key; @@ -355,7 +378,7 @@ int ltdb_delete_noindex(struct ldb_module *module, const char *dn) /* delete a record from the database */ -static int ltdb_delete(struct ldb_module *module, const char *dn) +static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ltdb_private *ltdb = module->private_data; int ret; @@ -477,12 +500,18 @@ static int msg_delete_attribute(struct ldb_module *module, struct ldb_context *ldb, struct ldb_message *msg, const char *name) { + char *dn; unsigned int i, j; + dn = ldb_dn_linearize(ldb, msg->dn); + if (dn == NULL) { + return -1; + } + for (i=0;inum_elements;i++) { if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { for (j=0;jelements[i].num_values;j++) { - ltdb_index_del_value(module, msg->dn, &msg->elements[i], j); + ltdb_index_del_value(module, dn, &msg->elements[i], j); } talloc_free(msg->elements[i].values); if (msg->num_elements > (i+1)) { @@ -499,6 +528,7 @@ static int msg_delete_attribute(struct ldb_module *module, } } + talloc_free(dn); return 0; } @@ -593,6 +623,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms struct ldb_message_element *el = &msg->elements[i]; struct ldb_message_element *el2; struct ldb_val *vals; + char *dn; switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { @@ -650,6 +681,10 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms break; case LDB_FLAG_MOD_DELETE: + + dn = ldb_dn_linearize(msg2, msg->dn); + if (dn == NULL) goto failed; + /* we could be being asked to delete all values or just some values */ if (msg->elements[i].num_values == 0) { @@ -668,7 +703,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms ltdb->last_err_string = "No such attribute"; goto failed; } - if (ltdb_index_del_value(module, msg->dn, &msg->elements[i], j) != 0) { + if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) { goto failed; } } @@ -730,7 +765,7 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) /* rename a record */ -static int ltdb_rename(struct ldb_module *module, const char *olddn, const char *newdn) +static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { struct ltdb_private *ltdb = module->private_data; int ret; @@ -761,7 +796,7 @@ static int ltdb_rename(struct ldb_module *module, const char *olddn, const char goto failed; } - msg->dn = talloc_strdup(msg, newdn); + msg->dn = ldb_dn_copy(msg, newdn); if (!msg->dn) { goto failed; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 9ee3bfb70f..f08601832c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -57,7 +57,7 @@ int ltdb_check_at_attributes_values(const struct ldb_val *value); struct ldb_parse_tree; int ltdb_search_indexed(struct ldb_module *module, - const char *base, + const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res); @@ -81,23 +81,23 @@ int ltdb_unpack_data(struct ldb_module *module, int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val); void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg); -int ltdb_search_dn1(struct ldb_module *module, const char *dn, struct ldb_message *msg); +int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg); int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], int *count, struct ldb_message ***res); -int ltdb_search(struct ldb_module *module, const char *base, +int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const attrs[], struct ldb_message ***res); -int ltdb_search_bytree(struct ldb_module *module, const char *base, +int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res); /* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */ -struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn); +struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn); int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); -int ltdb_delete_noindex(struct ldb_module *module, const char *dn); +int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn); int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); int ltdb_lock_read(struct ldb_module *module); int ltdb_unlock_read(struct ldb_module *module); diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 89cc49eb3e..d59205c6e4 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -41,7 +41,7 @@ struct private_data { const char *error_string; }; -static int rdn_name_search(struct ldb_module *module, const char *base, +static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -49,7 +49,7 @@ static int rdn_name_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int rdn_name_search_bytree(struct ldb_module *module, const char *base, +static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -70,21 +70,6 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess return NULL; } -static struct ldb_dn_component *get_rdn(void *mem_ctx, const char *dn) -{ - struct ldb_dn *dn_exploded = ldb_dn_explode(mem_ctx, dn); - - if (!dn_exploded) { - return NULL; - } - - if (dn_exploded->comp_num < 1) { - return NULL; - } - - return &dn_exploded->components[0]; -} - /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { @@ -97,7 +82,8 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } @@ -119,12 +105,14 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa msg2->elements[i] = msg->elements[i]; } - rdn = get_rdn(msg2, msg2->dn); + rdn = ldb_dn_get_rdn(msg2, msg2->dn); if (!rdn) { + talloc_free(msg2); return -1; } if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + talloc_free(msg2); return -1; } @@ -132,6 +120,7 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa if (!attribute) { if (ldb_msg_add_value(module->ldb, msg2, rdn->name, &rdn->value) != 0) { + talloc_free(msg2); return -1; } } else { @@ -145,8 +134,9 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa } } if (i == attribute->num_values) { - data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", msg2->dn, rdn->name); + data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + talloc_free(msg2); return -1; } } @@ -167,6 +157,11 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n"); + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); + } + /* Perhaps someone above us knows better */ if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { return ldb_next_add_record(module, msg); @@ -185,17 +180,20 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me msg2->elements[i] = msg->elements[i]; } - rdn = get_rdn(msg2, msg2->dn); + rdn = ldb_dn_get_rdn(msg2, msg2->dn); if (!rdn) { + talloc_free(msg2); return -1; } if (ldb_msg_add_value(module->ldb, msg2, "name", &rdn->value) != 0) { + talloc_free(msg2); return -1; } attribute = rdn_name_find_attribute(msg2, "name"); if (!attribute) { + talloc_free(msg2); return -1; } @@ -207,13 +205,13 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me return ret; } -static int rdn_name_delete_record(struct ldb_module *module, const char *dn) +static int rdn_name_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); return ldb_next_delete_record(module, dn); } -static int rdn_name_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index e11c8b4e4e..baf038de0c 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -1,7 +1,7 @@ /* ldb database library - Copyright (C) Simo Sorce 2004 + Copyright (C) Simo Sorce 2004-2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -72,28 +72,6 @@ struct schema_structures { struct schema_attribute_list optional_attrs; }; -/* This function embedds the knowledge of aliased names. - Currently it handles only dn vs distinguishedNAme as a special case as AD - only have this special alias case, in future we should read the schema - to find out which names have an alias and check for them */ -static int schema_attr_cmp(const char *attr1, const char *attr2) -{ - int ret; - - ret = ldb_attr_cmp(attr1, attr2); - if (ret != 0) { - if ((ldb_attr_cmp("dn", attr1) == 0) && - (ldb_attr_cmp("distinguishedName", attr2) == 0)) { - return 0; - } - if ((ldb_attr_cmp("dn", attr2) == 0) && - (ldb_attr_cmp("distinguishedName", attr1) == 0)) { - return 0; - } - } - return ret; -} - static struct schema_attribute *schema_find_attribute(struct schema_attribute_list *list, const char *attr_name) { unsigned int i; @@ -110,7 +88,7 @@ static struct schema_attribute *schema_find_attribute(struct schema_attribute_li objectclasses go in the objectclasses structure */ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_message *msg, int flag_mask) { - int i, j, k, l; + int i, j, anum, cnum; ss->entry_attrs.attr = talloc_realloc(ss, ss->entry_attrs.attr, struct schema_attribute, @@ -119,9 +97,9 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes return -1; } - for (i = 0, j = ss->entry_attrs.num; i < msg->num_elements; i++) { + for (i = 0, anum = ss->entry_attrs.num; i < msg->num_elements; i++) { - if (schema_attr_cmp(msg->elements[i].name, "objectclass") == 0) { + if (ldb_attr_cmp(msg->elements[i].name, "objectclass") == 0) { ss->objectclasses.attr = talloc_realloc(ss, ss->objectclasses.attr, struct schema_attribute, @@ -130,34 +108,33 @@ static int get_msg_attributes(struct schema_structures *ss, const struct ldb_mes return -1; } - for (k = 0, l = ss->objectclasses.num; k < msg->elements[i].num_values; k++) { - ss->objectclasses.attr[l].name = msg->elements[i].values[k].data; - ss->objectclasses.attr[l].flags = msg->elements[i].flags & flag_mask; - l++; + for (j = 0, cnum = ss->objectclasses.num; j < msg->elements[i].num_values; j++) { + ss->objectclasses.attr[cnum+j].name = msg->elements[i].values[j].data; + ss->objectclasses.attr[cnum+j].flags = msg->elements[i].flags & flag_mask; } ss->objectclasses.num += msg->elements[i].num_values; } - ss->entry_attrs.attr[j].flags = msg->elements[i].flags & flag_mask; - ss->entry_attrs.attr[j].name = talloc_reference(ss->entry_attrs.attr, + /* TODO: Check for proper attribute Syntax ! */ + + ss->entry_attrs.attr[anum+i].flags = msg->elements[i].flags & flag_mask; + ss->entry_attrs.attr[anum+i].name = talloc_reference(ss->entry_attrs.attr, msg->elements[i].name); - if (ss->entry_attrs.attr[j].name == NULL) { + if (ss->entry_attrs.attr[anum+i].name == NULL) { return -1; } - j++; } ss->entry_attrs.num += msg->num_elements; return 0; } -static int get_entry_attributes(struct ldb_context *ldb, const char *dn, struct schema_structures *ss) +static int get_entry_attributes(struct ldb_context *ldb, const struct ldb_dn *dn, struct schema_structures *ss) { - char *filter = talloc_asprintf(ss, "dn=%s", dn); struct ldb_message **srch; int ret; - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &srch); + ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &srch); if (ret != 1) { return ret; } @@ -190,7 +167,7 @@ static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, for (c = 0; c < list->num; c++) { len = strlen(list->attr[c].name); if (len == el->values[i].length) { - if (schema_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { + if (ldb_attr_cmp(list->attr[c].name, el->values[i].data) == 0) { found = 1; break; } @@ -254,11 +231,15 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru is_aux = 0; is_class = 0; - if (schema_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "systemAuxiliaryclass") == 0) { is_aux = SCHEMA_FLAG_AUXILIARY; is_class = 1; } - if (schema_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "auxiliaryClass") == 0) { + is_aux = SCHEMA_FLAG_AUXILIARY; + is_class = 1; + } + if (ldb_attr_cmp((*srch)->elements[j].name, "subClassOf") == 0) { is_class = 1; } @@ -271,8 +252,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } } else { - if (schema_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || - schema_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mustContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMustContain") == 0) { if (add_attribute_uniq(schema_struct, &schema_struct->required_attrs, SCHEMA_FLAG_RESET, @@ -281,8 +262,8 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } } - if (schema_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || - schema_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { + if (ldb_attr_cmp((*srch)->elements[j].name, "mayContain") == 0 || + ldb_attr_cmp((*srch)->elements[j].name, "SystemMayContain") == 0) { if (add_attribute_uniq(schema_struct, &schema_struct->optional_attrs, @@ -299,14 +280,14 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } /* search */ -static int schema_search(struct ldb_module *module, const char *base, +static int schema_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { return ldb_next_search(module, base, scope, expression, attrs, res); } -static int schema_search_bytree(struct ldb_module *module, const char *base, +static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -329,10 +310,13 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message Free all structures and commit the change */ - if (msg->dn[0] == '@') { /* do not check on our control entries */ + /* do not check on our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } + /* TODO: check parent exists */ + entry_structs = talloc_zero(module, struct schema_structures); if (!entry_structs) { return -1; @@ -414,8 +398,9 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess Free all structures and commit the change. */ - if (msg->dn[0] == '@') { /* do not check on our control entries */ - return ldb_next_modify_record(module, msg); + /* do not check on our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); } /* allocate object structs */ @@ -504,14 +489,14 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess } /* delete_record */ -static int schema_delete_record(struct ldb_module *module, const char *dn) +static int schema_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { /* struct private_data *data = (struct private_data *)module->private_data; */ return ldb_next_delete_record(module, dn); } /* rename_record */ -static int schema_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int schema_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { return ldb_next_rename_record(module, olddn, newdn); } diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 1221ac70f1..57c89a6a65 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -42,7 +42,7 @@ struct private_data { }; /* search */ -static int skel_search(struct ldb_module *module, const char *base, +static int skel_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -62,13 +62,13 @@ static int skel_modify_record(struct ldb_module *module, const struct ldb_messag } /* delete_record */ -static int skel_delete_record(struct ldb_module *module, const char *dn) +static int skel_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { return ldb_next_delete_record(module, dn); } /* rename_record */ -static int skel_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int skel_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { return ldb_next_rename_record(module, olddn, newdn); } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index b067d8e8d6..4819e0466b 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -41,7 +41,7 @@ struct private_data { const char *error_string; }; -static int timestamps_search(struct ldb_module *module, const char *base, +static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { @@ -49,7 +49,7 @@ static int timestamps_search(struct ldb_module *module, const char *base, return ldb_next_search(module, base, scope, expression, attrs, res); } -static int timestamps_search_bytree(struct ldb_module *module, const char *base, +static int timestamps_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -101,7 +101,8 @@ static int timestamps_add_record(struct ldb_module *module, const struct ldb_mes ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_add_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { return ldb_next_add_record(module, msg); } @@ -159,8 +160,9 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_modify_record\n"); - if (msg->dn[0] == '@') { /* do not manipulate our control entries */ - return ldb_next_modify_record(module, msg); + /* do not manipulate our control entries */ + if (ldb_dn_is_special(msg->dn)) { + return ldb_next_add_record(module, msg); } timeval = time(NULL); @@ -201,13 +203,13 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return ret; } -static int timestamps_delete_record(struct ldb_module *module, const char *dn) +static int timestamps_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); return ldb_next_delete_record(module, dn); } -static int timestamps_rename_record(struct ldb_module *module, const char *olddn, const char *newdn) +static int timestamps_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 48dc8ddd47..7657301f35 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -57,6 +57,8 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "dn=*", NULL }, { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, { "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" }, + { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" }, + { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" }, { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, #ifdef _SAMBA_BUILD_ POPT_COMMON_SAMBA @@ -149,16 +151,18 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const *ret = options; /* all utils need some option */ - if (ret->url == NULL) { - fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); - if (usage) usage(); - goto failed; - } + if (ldb) { + if (ret->url == NULL) { + fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); + if (usage) usage(); + goto failed; + } - if (ldb_connect(ldb, ret->url, 0, ret->options) != 0) { - fprintf(stderr, "Failed to connect to %s - %s\n", - ret->url, ldb_errstring(ldb)); - goto failed; + if (ldb_connect(ldb, ret->url, 0, ret->options) != 0) { + fprintf(stderr, "Failed to connect to %s - %s\n", + ret->url, ldb_errstring(ldb)); + goto failed; + } } return ret; diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h index 8e479c5538..daf9c06f42 100644 --- a/source4/lib/ldb/tools/cmdline.h +++ b/source4/lib/ldb/tools/cmdline.h @@ -40,6 +40,8 @@ struct ldb_cmdline { int num_records; int num_searches; const char *sasl_mechanism; + const char *input; + const char *output; }; struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 5be3b7fc75..de6da0eb5b 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -76,7 +76,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) ret = ldb_add(ldb, ldif->msg); if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", - ldb_errstring(ldb), ldif->msg->dn); + ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); failures++; } else { count++; diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index fdb1f7ef3b..6082931e22 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -41,7 +41,7 @@ #include "system/filesys.h" #endif -static int ldb_delete_recursive(struct ldb_context *ldb, const char *dn) +static int ldb_delete_recursive(struct ldb_context *ldb, const struct ldb_dn *dn) { int ret, i, total=0; const char *attrs[] = { "dn", NULL }; @@ -94,7 +94,13 @@ static void usage(void) } for (i=0;iargc;i++) { - const char *dn = options->argv[i]; + const struct ldb_dn *dn; + + dn = ldb_dn_explode(ldb, options->argv[i]); + if (dn == NULL) { + printf("Invalid DN format\n"); + exit(1); + } if (options->recursive) { ret = ldb_delete_recursive(ldb, dn); } else { @@ -104,7 +110,9 @@ static void usage(void) } } if (ret != 0) { - printf("delete of '%s' failed - %s\n", dn, ldb_errstring(ldb)); + printf("delete of '%s' failed - %s\n", + ldb_dn_linearize(ldb, dn), + ldb_errstring(ldb)); } } diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index 1613f4ddc5..a850562a7d 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -83,7 +83,7 @@ static int modify_record(struct ldb_context *ldb, if (ldb_modify(ldb, mod) != 0) { fprintf(stderr, "failed to modify %s - %s\n", - msg1->dn, ldb_errstring(ldb)); + ldb_dn_linearize(ldb, msg1->dn), ldb_errstring(ldb)); return -1; } @@ -96,11 +96,11 @@ static int modify_record(struct ldb_context *ldb, static struct ldb_message *msg_find(struct ldb_context *ldb, struct ldb_message **msgs, int count, - const char *dn) + const struct ldb_dn *dn) { int i; for (i=0;idn) == 0) { + if (ldb_dn_compare(ldb, dn, msgs[i]->dn) == 0) { return msgs[i]; } } @@ -128,7 +128,8 @@ static int merge_edits(struct ldb_context *ldb, } if (ldb_add(ldb, msgs2[i]) != 0) { fprintf(stderr, "failed to add %s - %s\n", - msgs2[i]->dn, ldb_errstring(ldb)); + ldb_dn_linearize(ldb, msgs2[i]->dn), + ldb_errstring(ldb)); return -1; } adds++; @@ -148,7 +149,8 @@ static int merge_edits(struct ldb_context *ldb, } if (ldb_delete(ldb, msgs1[i]->dn) != 0) { fprintf(stderr, "failed to delete %s - %s\n", - msgs1[i]->dn, ldb_errstring(ldb)); + ldb_dn_linearize(ldb, msgs1[i]->dn), + ldb_errstring(ldb)); return -1; } deletes++; @@ -279,6 +281,7 @@ static void usage(void) { struct ldb_context *ldb; struct ldb_message **msgs; + struct ldb_dn *basedn = NULL; int ret; const char *expression = "(|(objectclass=*)(dn=*))"; const char * const * attrs = NULL; @@ -299,7 +302,15 @@ static void usage(void) attrs = (const char * const *)(options->argv); } - ret = ldb_search(ldb, options->basedn, options->scope, expression, attrs, &msgs); + if (options->basedn != NULL) { + basedn = ldb_dn_explode(ldb, options->basedn); + if (basedn == NULL) { + printf("Invalid Base DN format\n"); + exit(1); + } + } + + ret = ldb_search(ldb, basedn, options->scope, expression, attrs, &msgs); if (ret == -1) { printf("search failed - %s\n", ldb_errstring(ldb)); exit(1); diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 901a4c9628..4c78e485b5 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -78,7 +78,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) } if (ret != 0) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", - ldb_errstring(ldb), ldif->msg->dn); + ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); failures++; } else { count++; diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c index c74516869e..4b3b27c130 100644 --- a/source4/lib/ldb/tools/ldbrename.c +++ b/source4/lib/ldb/tools/ldbrename.c @@ -61,7 +61,7 @@ static void usage(void) struct ldb_context *ldb; int ret; struct ldb_cmdline *options; - const char *dn1, *dn2; + const struct ldb_dn *dn1, *dn2; ldb = ldb_init(NULL); @@ -71,15 +71,15 @@ static void usage(void) usage(); } - dn1 = options->argv[0]; - dn2 = options->argv[1]; + dn1 = ldb_dn_explode(ldb, options->argv[0]); + dn2 = ldb_dn_explode(ldb, options->argv[1]); ret = ldb_rename(ldb, dn1, dn2); if (ret == 0) { printf("Renamed 1 record\n"); } else { printf("rename of '%s' to '%s' failed - %s\n", - dn1, dn2, ldb_errstring(ldb)); + options->argv[0], options->argv[1], ldb_errstring(ldb)); } talloc_free(ldb); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 5604436980..4499bc9359 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -60,11 +60,11 @@ struct ldb_context *ldbsearch_ldb; static int do_compare_msg(struct ldb_message **el1, struct ldb_message **el2) { - return ldb_dn_cmp(ldbsearch_ldb, (*el1)->dn, (*el2)->dn); + return ldb_dn_compare(ldbsearch_ldb, (*el1)->dn, (*el2)->dn); } static int do_search(struct ldb_context *ldb, - const char *basedn, + const struct ldb_dn *basedn, int scope, int sort_attribs, const char *expression, @@ -120,6 +120,7 @@ static int do_search(struct ldb_context *ldb, int main(int argc, const char **argv) { struct ldb_context *ldb; + struct ldb_dn *basedn = NULL; const char * const * attrs = NULL; struct ldb_cmdline *options; int ret = -1; @@ -142,16 +143,24 @@ static int do_search(struct ldb_context *ldb, attrs = (const char * const *)(options->argv); } + if (options->basedn != NULL) { + basedn = ldb_dn_explode(ldb, options->basedn); + if (basedn == NULL) { + fprintf(stderr, "Invalid Base DN format\n"); + exit(1); + } + } + if (options->interactive) { char line[1024]; while (fgets(line, sizeof(line), stdin)) { - if (do_search(ldb, options->basedn, + if (do_search(ldb, basedn, options->scope, options->sorted, line, attrs) == -1) { ret = -1; } } } else { - ret = do_search(ldb, options->basedn, options->scope, options->sorted, + ret = do_search(ldb, basedn, options->scope, options->sorted, expression, attrs); } diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index aff1eaadda..a2e824dcdb 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -58,7 +58,7 @@ static double _end_timer(void) } static void add_records(struct ldb_context *ldb, - const char *basedn, + const struct ldb_dn *basedn, int count) { struct ldb_message msg; @@ -77,7 +77,7 @@ static void add_records(struct ldb_context *ldb, asprintf(&name, "Test%d", i); - msg.dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, basedn); + msg.dn = ldb_dn_build_child(tmp_ctx, "cn", name, basedn); msg.num_elements = 6; msg.elements = el; @@ -145,7 +145,7 @@ static void add_records(struct ldb_context *ldb, } static void modify_records(struct ldb_context *ldb, - const char *basedn, + const struct ldb_dn *basedn, int count) { struct ldb_message msg; @@ -158,7 +158,7 @@ static void modify_records(struct ldb_context *ldb, TALLOC_CTX *tmp_ctx = talloc_new(ldb); name = talloc_asprintf(tmp_ctx, "Test%d", i); - msg.dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, basedn); + msg.dn = ldb_dn_build_child(tmp_ctx, "cn", name, basedn); msg.num_elements = 3; msg.elements = el; @@ -197,29 +197,30 @@ static void modify_records(struct ldb_context *ldb, static void delete_records(struct ldb_context *ldb, - const char *basedn, + const struct ldb_dn *basedn, int count) { int i; for (i=0;ibasedn, LDB_SCOPE_SUBTREE, expr, NULL, &res); + ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, NULL, &res); if (uid < nrecords && ret != 1) { printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb)); @@ -257,19 +258,23 @@ static void search_uid(struct ldb_context *ldb, int nrecords, int nsearches) static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) { + struct ldb_dn *basedn; + + basedn = ldb_dn_explode(ldb, options->basedn); + printf("Adding %d records\n", nrecords); - add_records(ldb, options->basedn, nrecords); + add_records(ldb, basedn, nrecords); printf("Starting search on uid\n"); _start_timer(); - search_uid(ldb, nrecords, nsearches); + search_uid(ldb, basedn, nrecords, nsearches); printf("uid search took %.2f seconds\n", _end_timer()); printf("Modifying records\n"); - modify_records(ldb, options->basedn, nrecords); + modify_records(ldb, basedn, nrecords); printf("Deleting records\n"); - delete_records(ldb, options->basedn, nrecords); + delete_records(ldb, basedn, nrecords); } @@ -290,31 +295,37 @@ static void start_test_index(struct ldb_context **ldb) { struct ldb_message *msg; struct ldb_message **res; + struct ldb_dn *indexlist; + struct ldb_dn *basedn; int ret; printf("Starting index test\n"); - ldb_delete(*ldb, "@INDEXLIST"); + indexlist = ldb_dn_explode(NULL, "@INDEXLIST"); + + ldb_delete(*ldb, indexlist); msg = ldb_msg_new(NULL); - msg->dn = strdup("@INDEXLIST"); + msg->dn = indexlist; ldb_msg_add_string(*ldb, msg, "@IDXATTR", strdup("uid")); if (ldb_add(*ldb, msg) != 0) { - printf("Add of %s failed - %s\n", msg->dn, ldb_errstring(*ldb)); + printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb, msg->dn), ldb_errstring(*ldb)); exit(1); } + basedn = ldb_dn_explode(NULL, options->basedn); + memset(msg, 0, sizeof(*msg)); - asprintf(&msg->dn, "cn=%s,%s", "test", options->basedn); + msg->dn = ldb_dn_build_child(msg, "cn", "test", basedn); ldb_msg_add_string(*ldb, msg, "cn", strdup("test")); ldb_msg_add_string(*ldb, msg, "sn", strdup("test")); ldb_msg_add_string(*ldb, msg, "uid", strdup("test")); ldb_msg_add_string(*ldb, msg, "objectClass", strdup("OpenLDAPperson")); if (ldb_add(*ldb, msg) != 0) { - printf("Add of %s failed - %s\n", msg->dn, ldb_errstring(*ldb)); + printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb, msg->dn), ldb_errstring(*ldb)); exit(1); } @@ -331,14 +342,14 @@ static void start_test_index(struct ldb_context **ldb) exit(1); } - ret = ldb_search(*ldb, options->basedn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); + ret = ldb_search(*ldb, basedn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res); if (ret != 1) { printf("Should have found 1 record - found %d\n", ret); exit(1); } if (ldb_delete(*ldb, msg->dn) != 0 || - ldb_delete(*ldb, "@INDEXLIST") != 0) { + ldb_delete(*ldb, indexlist) != 0) { printf("cleanup failed - %s\n", ldb_errstring(*ldb)); exit(1); } diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 3c50258d02..404dab4dc1 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -25,7 +25,7 @@ struct ldb_key_data { - const char *dn; + const struct ldb_dn *dn; struct ldb_message **subkeys, **values; int subkey_count, value_count; }; @@ -113,39 +113,34 @@ static int reg_close_ldb_key (void *data) return 0; } -static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, const char *path, const char *add) +static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, const char *path, const char *add) { - char *ret = talloc_strdup(mem_ctx, ""); + TALLOC_CTX *local_ctx; + struct ldb_dn *ret = ldb_dn_new(mem_ctx); char *mypath = talloc_strdup(mem_ctx, path); char *begin; struct ldb_key_data *kd = from->backend_data; - if(add) - ret = talloc_asprintf_append(ret, "%s", add); + local_ctx = talloc_named(mem_ctx, 0, "reg_path_to_ldb context"); + + if (add) + ret = ldb_dn_compose(local_ctx, ret, ldb_dn_explode(mem_ctx, add)); while(mypath) { char *keyname; - struct ldb_val val; - char *key; begin = strrchr(mypath, '\\'); if (begin) keyname = begin + 1; else keyname = mypath; - val.data = keyname; - val.length = strlen(keyname); - - key = ldb_dn_escape_value(mem_ctx, val); - if (key == NULL) { - return NULL; - } + if(strlen(keyname)) { + struct ldb_dn *base; - if (strlen(key)) - ret = talloc_asprintf_append(ret, "key=%s,", key); + base = ldb_dn_build_child(local_ctx, "key", keyname, NULL); + ret = ldb_dn_compose(local_ctx, ret, base); + } - talloc_free(key); - if(begin) { *begin = '\0'; } else { @@ -153,7 +148,7 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, con } } - ret = talloc_asprintf_append(ret, "%s", kd->dn); + ret = ldb_dn_compose(local_ctx, ret, kd->dn); return ret; } @@ -170,7 +165,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &kd->subkeys); if(kd->subkey_count < 0) { - DEBUG(0, ("Error getting subkeys for '%s': %s\n", kd->dn, ldb_errstring(c))); + DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c))); return WERR_FOOBAR; } } @@ -185,7 +180,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data); (*subkey)->last_mod = 0; /* TODO: we need to add this to the ldb backend properly */ - newkd->dn = talloc_strdup(mem_ctx, kd->subkeys[idx]->dn); + newkd->dn = ldb_dn_copy(mem_ctx, kd->subkeys[idx]->dn); return WERR_OK; } @@ -200,7 +195,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i kd->value_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&kd->values); if(kd->value_count < 0) { - DEBUG(0, ("Error getting values for '%s': %s\n", kd->dn, ldb_errstring(c))); + DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c))); return WERR_FOOBAR; } } @@ -218,18 +213,18 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch { struct ldb_context *c = h->hive->backend_data; struct ldb_message **msg; - char *ldap_path; + struct ldb_dn *ldap_path; int ret; struct ldb_key_data *newkd; ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL); - ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg); + ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &msg); if(ret == 0) { return WERR_BADFILE; } else if(ret < 0) { - DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c))); + DEBUG(0, ("Error opening key '%s': %s\n", ldb_dn_linearize(ldap_path, ldap_path), ldb_errstring(c))); return WERR_FOOBAR; } @@ -237,7 +232,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch talloc_set_destructor(*key, reg_close_ldb_key); (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name); (*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data); - newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); + newkd->dn = ldb_dn_copy(mem_ctx, msg[0]->dn); talloc_free(msg); @@ -265,7 +260,7 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) talloc_set_destructor (hive, ldb_free_hive); (*k)->name = talloc_strdup(*k, ""); (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data); - kd->dn = talloc_strdup(*k, "hive=NONE"); + kd->dn = ldb_dn_explode(*k, "hive=NONE"); return WERR_OK; @@ -303,11 +298,12 @@ static WERROR ldb_del_key (struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; - char *childdn = talloc_asprintf(NULL, "key=%s,%s", child, kd->dn); + TALLOC_CTX *local_ctx = talloc_named(NULL, 0, "ldb_del_key mem ctx"); + struct ldb_dn *childdn = ldb_dn_build_child(local_ctx, "key", child, kd->dn); ret = ldb_delete(key->hive->backend_data, childdn); - talloc_free(childdn); + talloc_free(local_ctx); if (ret < 0) { DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); @@ -321,11 +317,12 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; - char *childdn = talloc_asprintf(NULL, "value=%s,%s", child, kd->dn); + TALLOC_CTX *local_ctx = talloc_named(NULL, 0, "ldb_del_value mem ctx"); + struct ldb_dn *childdn = ldb_dn_build_child(local_ctx, "value", child, kd->dn); ret = ldb_delete(key->hive->backend_data, childdn); - talloc_free(childdn); + talloc_free(local_ctx); if (ret < 0) { DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data))); @@ -345,7 +342,7 @@ static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data, len); - msg->dn = talloc_asprintf(mem_ctx, "value=%s,%s", name, kd->dn); + msg->dn = ldb_dn_build_child(msg, "value", name, kd->dn); ret = ldb_add(ctx, msg); if (ret < 0) { -- cgit From ac90ddfdb28050912ecab0e998089b93216c5c35 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Aug 2005 16:18:48 +0000 Subject: r9392: Fix ldb_dn_compose to make build farm happy Add ldb_dn_string_compose so that you can build a dn starting from a struct ldb_dn base and a set of parameters to be composed in a format string with the same syntax of printf (This used to be commit 31c69d0655752cc8ea3bc5b7ea87792291302091) --- source4/lib/ldb/common/ldb_dn.c | 25 +++++++++++++++++++++---- source4/lib/ldb/include/ldb.h | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index dae79fd9e1..df95e37dac 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -771,7 +771,9 @@ struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const str new->comp_num = dn1->comp_num; new->components = talloc_array(new, struct ldb_dn_component, new->comp_num); } else { - new = ldb_dn_copy_partial(mem_ctx, dn2, dn2->comp_num + dn1?dn1->comp_num:0); + int comp_num = dn2->comp_num; + if (dn1 != NULL) comp_num += dn1->comp_num; + new = ldb_dn_copy_partial(mem_ctx, dn2, comp_num); } if (dn1 == NULL) { @@ -790,11 +792,26 @@ failed: return NULL; } -struct ldb_dn *ldb_dn_compose_string_dn(void *mem_ctx, const char *dn1, const struct ldb_dn *dn2) +struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...) { - if (dn1 == NULL) return NULL; + struct ldb_dn *dn; + char *child_str; + va_list ap; + int ret; + + if (child_fmt == NULL) return NULL; + + va_start(ap, child_fmt); + ret = vasprintf(&child_str, child_fmt, ap); + va_end(ap); + + if (ret <= 0) return NULL; - return ldb_dn_compose(mem_ctx, ldb_dn_explode(mem_ctx, dn1), dn2); + dn = ldb_dn_compose(mem_ctx, ldb_dn_explode(mem_ctx, child_str), base); + + free(child_str); + + return dn; } struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn) diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 13c9b72e6d..e7862522e4 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -371,7 +371,7 @@ struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component, const struct ldb_dn *base); struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2); -struct ldb_dn *ldb_dn_compose_string_dn(void *mem_ctx, const char *dn1, const struct ldb_dn *dn2); +struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...); struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn); /* useful functions for ldb_message structure manipulation */ -- cgit From 7c7b93f6497737a09d3e76a626ee4f20284effde Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Aug 2005 16:27:09 +0000 Subject: r9393: Fix ldb standalone build (This used to be commit 796d0ea2fcf5132b157a397cc1a54aa26c042691) --- source4/lib/ldb/common/ldb_dn.c | 1 + source4/lib/ldb/include/ldb.h | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index df95e37dac..12078231b8 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -353,6 +353,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) /* Allocate a structure to hold the exploded DN */ edn = ldb_dn_new(mem_ctx); + pdn = NULL; /* Empty DNs */ if (dn[0] == '\0') { diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index e7862522e4..fc447102d6 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -348,6 +348,11 @@ int ldb_attrib_add_handlers(struct ldb_context *ldb, unsigned num_handlers); /* The following definitions come from lib/ldb/common/ldb_dn.c */ + +#ifndef BOOL +typedef int BOOL; +#endif + BOOL ldb_dn_is_special(const struct ldb_dn *dn); BOOL ldb_dn_check_special(const struct ldb_dn *dn, const char *check); char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value); -- cgit From f2ac4b8d6b24bec9aecfe00daf8c0b4ccf3964a6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Aug 2005 16:41:27 +0000 Subject: r9394: avoid to use BOOL in ldb (This used to be commit d2055849fba56e8620403621f3fb9684f24e853f) --- source4/lib/ldb/common/ldb_dn.c | 4 ++-- source4/lib/ldb/include/ldb.h | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 12078231b8..20cef9dd81 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -43,14 +43,14 @@ #define LDB_SPECIAL "@SPECIAL" -BOOL ldb_dn_is_special(const struct ldb_dn *dn) +int ldb_dn_is_special(const struct ldb_dn *dn) { if (dn == NULL || dn->comp_num != 1) return 0; return ! strcmp(dn->components[0].name, LDB_SPECIAL); } -BOOL ldb_dn_check_special(const struct ldb_dn *dn, const char *check) +int ldb_dn_check_special(const struct ldb_dn *dn, const char *check) { if (dn == NULL || dn->comp_num != 1) return 0; diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index fc447102d6..89e88fd4e9 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -349,12 +349,8 @@ int ldb_attrib_add_handlers(struct ldb_context *ldb, /* The following definitions come from lib/ldb/common/ldb_dn.c */ -#ifndef BOOL -typedef int BOOL; -#endif - -BOOL ldb_dn_is_special(const struct ldb_dn *dn); -BOOL ldb_dn_check_special(const struct ldb_dn *dn, const char *check); +int ldb_dn_is_special(const struct ldb_dn *dn); +int ldb_dn_check_special(const struct ldb_dn *dn, const char *check); char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value); struct ldb_dn *ldb_dn_new(void *mem_ctx); struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); -- cgit From 479be53c0a894df441db9a02d0b75b222b374ae9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 20 Aug 2005 06:01:49 +0000 Subject: r9414: Fix failure to find own domain info due to recent ldb_dn upgrade - we don't use a simple char* here any more. Andrew Bartlett (This used to be commit f21c31c7e151e23caa2699b1727d1ae310fbed4e) --- source4/lib/credentials.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 58a1b8c0e3..aae55be800 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -496,7 +496,6 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) struct ldb_context *ldb; int ldb_ret; struct ldb_message **msgs; - const char *base_dn = SECRETS_PRIMARY_DOMAIN_DN; const char *attrs[] = { "secret", "samAccountName", @@ -527,7 +526,8 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) /* search for the secret record */ ldb_ret = gendb_search(ldb, - mem_ctx, base_dn, &msgs, attrs, + mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), + &msgs, attrs, SECRETS_PRIMARY_DOMAIN_FILTER, cli_credentials_get_domain(cred)); if (ldb_ret == 0) { -- cgit From 684c824e9ac51ee2d6b748973757697a8ead2634 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 20 Aug 2005 07:59:00 +0000 Subject: r9421: Move arcfour code into it's own file, in lib/crypto. Andrew Bartlett (This used to be commit ca6cf462708810637544d4b4bef0f404fb89a002) --- source4/lib/basic.mk | 3 +- source4/lib/crypto/arcfour.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ source4/lib/crypto/crypto.h | 6 +++ source4/lib/crypto/hmacmd5.h | 2 +- 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 source4/lib/crypto/arcfour.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 3953d702bc..4dd6a05d54 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -22,7 +22,8 @@ INIT_OBJ_FILES = \ ADD_OBJ_FILES = \ lib/crypto/md5.o \ lib/crypto/hmacmd5.o \ - lib/crypto/md4.o + lib/crypto/md4.o \ + lib/crypto/arcfour.o # End SUBSYSTEM LIBCRYPTO ############################## diff --git a/source4/lib/crypto/arcfour.c b/source4/lib/crypto/arcfour.c new file mode 100644 index 0000000000..cc5d2df567 --- /dev/null +++ b/source4/lib/crypto/arcfour.c @@ -0,0 +1,92 @@ +/* + Unix SMB/CIFS implementation. + + An implementation of the arcfour algorithm + + Copyright (C) Andrew Tridgell 1998 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/crypto/crypto.h" + +/* initialise the arcfour sbox with key */ +void arcfour_init(struct arcfour_state *state, const DATA_BLOB *key) +{ + int ind; + uint8_t j = 0; + for (ind = 0; ind < sizeof(state->sbox); ind++) { + state->sbox[ind] = (uint8_t)ind; + } + + for (ind = 0; ind < sizeof(state->sbox); ind++) { + uint8_t tc; + + j += (state->sbox[ind] + key->data[ind%key->length]); + + tc = state->sbox[ind]; + state->sbox[ind] = state->sbox[j]; + state->sbox[j] = tc; + } + state->index_i = 0; + state->index_j = 0; +} + +/* crypt the data with arcfour */ +void arcfour_crypt_sbox(struct arcfour_state *state, uint8_t *data, int len) +{ + int ind; + + for (ind = 0; ind < len; ind++) { + uint8_t tc; + uint8_t t; + + state->index_i++; + state->index_j += state->sbox[state->index_i]; + + tc = state->sbox[state->index_i]; + state->sbox[state->index_i] = state->sbox[state->index_j]; + state->sbox[state->index_j] = tc; + + t = state->sbox[state->index_i] + state->sbox[state->index_j]; + data[ind] = data[ind] ^ state->sbox[t]; + } +} + +/* + arcfour encryption with a blob key +*/ +void arcfour_crypt_blob(uint8_t *data, int len, const DATA_BLOB *key) +{ + struct arcfour_state state; + arcfour_init(&state, key); + arcfour_crypt_sbox(&state, data, len); +} + +/* + a variant that assumes a 16 byte key. This should be removed + when the last user is gone +*/ +void arcfour_crypt(uint8_t *data, const uint8_t keystr[16], int len) +{ + DATA_BLOB key = data_blob(keystr, 16); + + arcfour_crypt_blob(data, len, &key); + + data_blob_free(&key); +} + + diff --git a/source4/lib/crypto/crypto.h b/source4/lib/crypto/crypto.h index 8cf4b21aae..19457f60dc 100644 --- a/source4/lib/crypto/crypto.h +++ b/source4/lib/crypto/crypto.h @@ -28,3 +28,9 @@ struct arcfour_state { uint8_t index_i; uint8_t index_j; }; + +void arcfour_init(struct arcfour_state *state, const DATA_BLOB *key); +void arcfour_crypt_sbox(struct arcfour_state *state, uint8_t *data, int len); +void arcfour_crypt_blob(uint8_t *data, int len, const DATA_BLOB *key); +void arcfour_crypt(uint8_t *data, const uint8_t keystr[16], int len); + diff --git a/source4/lib/crypto/hmacmd5.h b/source4/lib/crypto/hmacmd5.h index fb6692a05f..6ee195875e 100644 --- a/source4/lib/crypto/hmacmd5.h +++ b/source4/lib/crypto/hmacmd5.h @@ -1,6 +1,6 @@ /* Unix SMB/CIFS implementation. - Interface header: Scheduler service + Interface header: HMAC MD5 code Copyright (C) Luke Kenneth Casson Leighton 1996-1999 Copyright (C) Andrew Tridgell 1992-1999 -- cgit From 85a12fe9af036577064bee17fee9f4987e6a62ed Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 20 Aug 2005 23:28:14 +0000 Subject: r9437: Update PLAN and README for Samba3 compatibility layer Add support for reading tdbsam files (This used to be commit 75ac972909ac601fb876e208a992eeebafaf6417) --- source4/lib/samba3/PLAN | 34 ++++-- source4/lib/samba3/README | 2 +- source4/lib/samba3/config.mk | 10 ++ source4/lib/samba3/sam.h | 52 +++++++++ source4/lib/samba3/tdbsam.c | 266 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 354 insertions(+), 10 deletions(-) create mode 100644 source4/lib/samba3/config.mk create mode 100644 source4/lib/samba3/sam.h create mode 100644 source4/lib/samba3/tdbsam.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index a75c60018c..6e83e8fc33 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,9 +1,25 @@ -- Each of the various password database backends(tdb,ldap,smbpaswd) available in Samba3 need to be accessible and converted to the SAM database in Samba4. -- Printer database needs to be read from the Samba3 TDB and added to the apprioprate LDAP subtree. -- The WINS database needs to be converted from both plain text file and TDB file to LDAP/LDB. -- The account policy database needs to be read in from a TDB and applied to the data in LDAP/LDB. -- The privilege database needs to be read from a TDB and added to the SAM database in LDB. -- Group mappings need to be read from the TDB and added to the SAM database. -- The share info database and the configuration file from Samba3 need to be read and converted to either xattrs or a TDB in Samba4 -- Secrets.tdb, containing the domain formation, needs to be merged into the SAM database. -- Last, but not least, a Samba3 configuration file should be parsable in Samba4. This file can be used for producing a Samba4 smb.conf file as well as for updating the various databases mentioned above. +Three possible viable approaches: + 1) TDB conversion approach. Read in TDB dump out LDIF (one-way) + - samr.ldb: from tdbsam/smbpasswd, account_policy.tdb, secrets.tdb, group_mapping.tdb, idmap.tdb, privilege.tdb + - registry.ldb: from registry.tdb + - wins.ldif: from wins.tdb/wins.dat + - smb.conf/ea's: generated from the old smb.conf + share_info.tdb + + (one-way upgrades can be done by using ldbsearch -a on these dynamically + generated ldb's) + + 2) samr "mapping" backend (alternative for samr.ldb) (two-way) + + 3) The vampire way of doing things (one-way) + - samba3 pidl backend + - Samba4 vampire + server side samsync support in Samba3 + - unixinfo (\unixinfo) + - in Samba4 (client side) + - in Samba3 (server side) + - winsrepl (thru seperate pipe?) + - enum/add shares (\srvsvc) + - enum/add registry (\winreg) + - enum/add printers (\winreg, perhaps also \spoolss(?)) + - convert smb.conf (using Jerry's registry hack) + +(going with a combination of 1 and 2) diff --git a/source4/lib/samba3/README b/source4/lib/samba3/README index cf55be047a..3f6553f7e8 100644 --- a/source4/lib/samba3/README +++ b/source4/lib/samba3/README @@ -1,5 +1,5 @@ This directory contains various files and functions for the purpose of -Samba3 import, migration and compatability. +Samba3 import, migration and compatibility. For example, the first file in this directory (smbpasswd.c) handles portions of the smbpasswd file format. diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk new file mode 100644 index 0000000000..43608577c5 --- /dev/null +++ b/source4/lib/samba3/config.mk @@ -0,0 +1,10 @@ +################################################ +# Start SUBSYSTEM LIBSAMBA3 +[SUBSYSTEM::LIBSAMBA3] +INIT_OBJ_FILES = \ + lib/samba3/smbpasswd.o \ + lib/samba3/tdbsam.o +# End SUBSYSTEM LIBSAMBA3 +################################################ + + diff --git a/source4/lib/samba3/sam.h b/source4/lib/samba3/sam.h new file mode 100644 index 0000000000..11a9f42ec7 --- /dev/null +++ b/source4/lib/samba3/sam.h @@ -0,0 +1,52 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SAMBA3_SAM_H /* _SAMBA3_SAM_H */ +#define _SAMBA3_SAM_H + +struct samba3_samaccount { + uint32_t logon_time, + logoff_time, + kickoff_time, + bad_password_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time; + char *username; + char *domain; + char *nt_username; + char *dir_drive; + char *unknown_str; + char *munged_dial; + char *fullname; + char *homedir; + char *logon_script; + char *profile_path; + char *acct_desc; + char *workstations; + uint32_t user_rid, group_rid, hours_len, unknown_6; + uint16_t acct_ctrl, logon_divs; + uint16_t bad_password_count, logon_count; + uint8_t *lm_pw_ptr, *nt_pw_ptr; + uint8_t *nt_pw_hist_ptr; + uint8_t *hours; +}; + +#endif /* _SAMBA3_SAM_H */ diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c new file mode 100644 index 0000000000..0b2f975441 --- /dev/null +++ b/source4/lib/samba3/tdbsam.c @@ -0,0 +1,266 @@ +/* + Unix SMB/CIFS implementation. + tdb passdb backend format routines + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Simo Sorce 2000-2003 + Copyright (C) Gerald Carter 2000 + Copyright (C) Jeremy Allison 2001 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/iconv.h" +#include "lib/tdb/include/tdbutil.h" +#include "lib/samba3/sam.h" + +#define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" +#define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" +#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" +#define TDBSAM_VERSION_STRING "INFO/version" + +/** + * Open the TDB passwd database, check version and convert it if needed. + * @param name filename of the tdbsam file. + * @param open_flags file access mode. + * @return a TDB_CONTEXT handle on the tdbsam file. + **/ + +static TDB_CONTEXT * tdbsam_open (const char *name, int open_flags, int32_t *version) +{ + TDB_CONTEXT *pdb_tdb; + + /* Try to open tdb passwd */ + if (!(pdb_tdb = tdb_open(name, 0, TDB_DEFAULT, + open_flags, 0600))) { + DEBUG(0, ("Unable to open/create TDB passwd\n")); + return NULL; + } + + /* Check the version */ + *version = tdb_fetch_int32(pdb_tdb, + TDBSAM_VERSION_STRING); + if (*version == -1) + *version = 0; /* Version not found, assume version 0 */ + + /* Compare the version */ + if (*version > 2) { + /* Version more recent than the latest known */ + DEBUG(0, ("TDBSAM version unknown: %d\n", *version)); + tdb_close(pdb_tdb); + pdb_tdb = NULL; + } + + return pdb_tdb; +} + +static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +{ + uint32_t username_len, domain_len, nt_username_len, + dir_drive_len, unknown_str_len, munged_dial_len, + fullname_len, homedir_len, logon_script_len, + profile_path_len, acct_desc_len, workstations_len; + + uint32_t remove_me; + uint32_t len = 0; + uint32_t lm_pw_len, nt_pw_len, hourslen; + + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n")); + return False; + } + + /* unpack the buffer into variables */ + len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V0, + &sampass->logon_time, /* d */ + &sampass->logoff_time, /* d */ + &sampass->kickoff_time, /* d */ + &sampass->pass_last_set_time, /* d */ + &sampass->pass_can_change_time, /* d */ + &sampass->pass_must_change_time, /* d */ + &username_len, &sampass->username, /* B */ + &domain_len, &sampass->domain, /* B */ + &nt_username_len, &sampass->nt_username, /* B */ + &fullname_len, &sampass->fullname, /* B */ + &homedir_len, &sampass->homedir, /* B */ + &dir_drive_len, &sampass->dir_drive, /* B */ + &logon_script_len, &sampass->logon_script, /* B */ + &profile_path_len, &sampass->profile_path, /* B */ + &acct_desc_len, &sampass->acct_desc, /* B */ + &workstations_len, &sampass->workstations, /* B */ + &unknown_str_len, &sampass->unknown_str, /* B */ + &munged_dial_len, &sampass->munged_dial, /* B */ + &sampass->user_rid, /* d */ + &sampass->group_rid, /* d */ + &lm_pw_len, &sampass->lm_pw_ptr, /* B */ + &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &sampass->acct_ctrl, /* w */ + &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ + &sampass->logon_divs, /* w */ + &sampass->hours_len, /* d */ + &hourslen, &sampass->hours, /* B */ + &sampass->bad_password_count, /* w */ + &sampass->logon_count, /* w */ + &sampass->unknown_6); /* d */ + + if (len == (uint32_t) -1) { + return False; + } + + if (lm_pw_len != 16) { + sampass->lm_pw_ptr = NULL; + } + + if (nt_pw_len != 16) { + sampass->nt_pw_ptr = NULL; + } + + return True; +} + +static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +{ + uint32_t username_len, domain_len, nt_username_len, + dir_drive_len, unknown_str_len, munged_dial_len, + fullname_len, homedir_len, logon_script_len, + profile_path_len, acct_desc_len, workstations_len; + + uint32_t remove_me; + uint32_t len = 0; + uint32_t lm_pw_len, nt_pw_len, hourslen; + + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n")); + return False; + } + + /* unpack the buffer into variables */ + len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V1, + &sampass->logon_time, /* d */ + &sampass->logoff_time, /* d */ + &sampass->kickoff_time, /* d */ + /* Change from V0 is addition of bad_password_time field. */ + &sampass->bad_password_time, /* d */ + &sampass->pass_last_set_time, /* d */ + &sampass->pass_can_change_time, /* d */ + &sampass->pass_must_change_time, /* d */ + &username_len, &sampass->username, /* B */ + &domain_len, &sampass->domain, /* B */ + &nt_username_len, &sampass->nt_username, /* B */ + &fullname_len, &sampass->fullname, /* B */ + &homedir_len, &sampass->homedir, /* B */ + &dir_drive_len, &sampass->dir_drive, /* B */ + &logon_script_len, &sampass->logon_script, /* B */ + &profile_path_len, &sampass->profile_path, /* B */ + &acct_desc_len, &sampass->acct_desc, /* B */ + &workstations_len, &sampass->workstations, /* B */ + &unknown_str_len, &sampass->unknown_str, /* B */ + &munged_dial_len, &sampass->munged_dial, /* B */ + &sampass->user_rid, /* d */ + &sampass->group_rid, /* d */ + &lm_pw_len, &sampass->lm_pw_ptr, /* B */ + &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &sampass->acct_ctrl, /* w */ + &remove_me, /* d */ + &sampass->logon_divs, /* w */ + &sampass->hours_len, /* d */ + &hourslen, &sampass->hours, /* B */ + &sampass->bad_password_count, /* w */ + &sampass->logon_count, /* w */ + &sampass->unknown_6); /* d */ + + if (len == (uint32_t) -1) { + return False; + } + + if (sampass->lm_pw_ptr && lm_pw_len != 16) { + sampass->lm_pw_ptr = NULL; + } + + if (sampass->nt_pw_ptr && nt_pw_len != 16) { + sampass->nt_pw_ptr = NULL; + } + + return True; +} + +static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +{ + uint32_t username_len, domain_len, nt_username_len, + dir_drive_len, unknown_str_len, munged_dial_len, + fullname_len, homedir_len, logon_script_len, + profile_path_len, acct_desc_len, workstations_len; + + uint32_t len = 0; + uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen; + + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n")); + return False; + } + + /* unpack the buffer into variables */ + len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V2, + &sampass->logon_time, /* d */ + &sampass->logoff_time, /* d */ + &sampass->kickoff_time, /* d */ + &sampass->bad_password_time, /* d */ + &sampass->pass_last_set_time, /* d */ + &sampass->pass_can_change_time, /* d */ + &sampass->pass_must_change_time, /* d */ + &username_len, &sampass->username, /* B */ + &domain_len, &sampass->domain, /* B */ + &nt_username_len, &sampass->nt_username, /* B */ + &fullname_len, &sampass->fullname, /* B */ + &homedir_len, &sampass->homedir, /* B */ + &dir_drive_len, &sampass->dir_drive, /* B */ + &logon_script_len, &sampass->logon_script, /* B */ + &profile_path_len, &sampass->profile_path, /* B */ + &acct_desc_len, &sampass->acct_desc, /* B */ + &workstations_len, &sampass->workstations, /* B */ + &unknown_str_len, &sampass->unknown_str, /* B */ + &munged_dial_len, &sampass->munged_dial, /* B */ + &sampass->user_rid, /* d */ + &sampass->group_rid, /* d */ + &lm_pw_len, &sampass->lm_pw_ptr, /* B */ + &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + /* Change from V1 is addition of password history field. */ + &nt_pw_hist_len, &sampass->nt_pw_hist_ptr, /* B */ + &sampass->acct_ctrl, /* w */ + /* Also "remove_me" field was removed. */ + &sampass->logon_divs, /* w */ + &sampass->hours_len, /* d */ + &hourslen, &sampass->hours, /* B */ + &sampass->bad_password_count, /* w */ + &sampass->logon_count, /* w */ + &sampass->unknown_6); /* d */ + + if (len == (uint32_t) -1) { + return False; + } + + if (sampass->lm_pw_ptr && lm_pw_len != 16) { + sampass->lm_pw_ptr = NULL; + } + + if (sampass->nt_pw_ptr && nt_pw_len != 16) { + sampass->nt_pw_ptr = NULL; + } + + return True; +} -- cgit From 3c4cc87bf8b7e24664d8402ab09b0f666f7b270f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 20 Aug 2005 23:30:10 +0000 Subject: r9438: Add initial files for ldb_map (This used to be commit a66eeadecdcc5f67dd34c4ae82f5ae9191163499) --- source4/lib/ldb/ldb_map/README | 29 +++++++++++++++++++++++++++++ source4/lib/ldb/ldb_map/ldb_map.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 source4/lib/ldb/ldb_map/README create mode 100644 source4/lib/ldb/ldb_map/ldb_map.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/README b/source4/lib/ldb/ldb_map/README new file mode 100644 index 0000000000..3c7e30a331 --- /dev/null +++ b/source4/lib/ldb/ldb_map/README @@ -0,0 +1,29 @@ +This directory contains a skeleton backend for ldb backends that allow +using an LDAP server while mapping the attributes in that schema to +another schema. This backend will never be used itself but instead have +other backends based on it (e.g. ldb_samba3 for a Samba3-LDAP-to-samdb +backend) + +Each backend that uses this skeleton has to specify an array of +struct objectclass_mapping's (see ldb_map.h). + +If no mappings are defined for an objectclass, it will be kept as is. + +Special mapping routine for dn's (calls rdn mapping routine) +Special mapping routine for rdn's + +Keep cache of mapped dn's so we don't have to traverse the tree each time + +search + Simply uses search_bytree + +search_bytree + Map all attributes in parse_tree + +add +modify + Map ldb_message to LDAPMod + +rename +delete + Simply map dn diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h new file mode 100644 index 0000000000..6d6e47873c --- /dev/null +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -0,0 +1,29 @@ +struct objectclass_mapping { + char *local_name; + char *remote_name; + + char *key; /* Name of attribute used in rdn */ + + /* For mapping attributes used in searches */ + struct local_attribute_mapping { + char *local_name; + + /* Attributes to request from the server for this attribute, + * needed by generate */ + char *required_attributes[]; + + /* If not set, the value for the first element of + * required_attributes will simply be used here */ + struct ldb_message_element *(*generate) (LDAPMessage *msg); + } *local_attribute_mappings; + + /* Generate LDAPMod for adds and modifies */ + LDAPMod *(*generate_mod)(struct ldb_message *); +} + +struct ldb_map_backend { + struct objectclass_mapping *objectclass_mappings; +}; + +const char *ldb_map_dn(const char *old); +const char *ldb_map_rdn(const char *old); -- cgit From f0b06b36f9d98e67de1b20dc840d317720ba4ab7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 02:12:25 +0000 Subject: r9442: Support some more primitive types. Fix charset support. (This used to be commit eeced29eb3dd2cbc4540555bdb642b2685eb9c5c) --- source4/lib/tdr/tdr.c | 105 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index c9aa289f00..8cfbe3695b 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -125,7 +125,7 @@ NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint16_t *v) +NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint32_t *v) { TDR_PULL_NEED_BYTES(tdr, 4); *v = TDR_IVAL(tdr, tdr->offset); @@ -133,7 +133,7 @@ NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint16_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint16_t *v) +NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v) { TDR_PUSH_NEED_BYTES(tdr, 4); TDR_SIVAL(tdr, tdr->offset, *v); @@ -147,21 +147,24 @@ NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, char **v, uint32_t length, uint32_t el_size, int chset) +NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, uint32_t el_size, int chset) { int ret; + if (length == -1) { switch (chset) { - case CH_DOS: - length = ascii_len_n((const char*)tdr->data+tdr->offset, tdr->length-tdr->offset); - break; - case CH_UTF16: - length = utf16_len_n(tdr->data+tdr->offset, tdr->length-tdr->offset); - default: - return NT_STATUS_INVALID_PARAMETER; + case CH_DOS: + length = ascii_len_n((const char*)tdr->data+tdr->offset, tdr->length-tdr->offset); + break; + case CH_UTF16: + length = utf16_len_n(tdr->data+tdr->offset, tdr->length-tdr->offset); + break; + + default: + return NT_STATUS_INVALID_PARAMETER; } } - + TDR_PULL_NEED_BYTES(tdr, el_size*length); ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, (void **)v); @@ -175,16 +178,23 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, char **v, uint32_t length, uint3 NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, int chset) { - int ret; - TDR_PUSH_NEED_BYTES(tdr, el_size*length); + ssize_t ret, required; + + required = el_size * length; + TDR_PUSH_NEED_BYTES(tdr, required); - ret = convert_string(CH_UNIX, chset, *v, length, tdr->data+tdr->offset, el_size*length); + ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data+tdr->offset, required); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; } + + /* Make sure the remaining part of the string is filled with zeroes */ + if (ret < required) { + memset(tdr->data+tdr->offset+ret, 0, required-ret); + } - tdr->offset += ret; + tdr->offset += required; return NT_STATUS_OK; } @@ -227,3 +237,68 @@ NTSTATUS tdr_print_ipv4address(struct tdr_print *tdr, const char *name, tdr->print(tdr, "%-25s: %s", name, *address); return NT_STATUS_OK; } + +/* + parse a hyper +*/ +NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, uint64_t *v) +{ + TDR_PULL_NEED_BYTES(tdr, 8); + *v = TDR_IVAL(tdr, tdr->offset); + *v |= (uint64_t)(TDR_IVAL(tdr, tdr->offset+4)) << 32; + tdr->offset += 8; + return NT_STATUS_OK; +} + +/* + push a hyper +*/ +NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v) +{ + TDR_PUSH_NEED_BYTES(tdr, 8); + TDR_SIVAL(tdr, tdr->offset, ((*v) & 0xFFFFFFFF)); + TDR_SIVAL(tdr, tdr->offset+4, ((*v)>>32)); + tdr->offset += 8; + return NT_STATUS_OK; +} + + + +/* + push a NTTIME +*/ +NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t) +{ + TDR_CHECK(tdr_push_hyper(tdr, t)); + return NT_STATUS_OK; +} + +/* + pull a NTTIME +*/ +NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, NTTIME *t) +{ + TDR_CHECK(tdr_pull_hyper(tdr, t)); + return NT_STATUS_OK; +} + +/* + push a time_t +*/ +NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t) +{ + return tdr_push_uint32(tdr, (uint32_t *)t); +} + +/* + pull a time_t +*/ +NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, time_t *t) +{ + uint32_t tt; + TDR_CHECK(tdr_pull_uint32(tdr, &tt)); + *t = tt; + return NT_STATUS_OK; +} + + -- cgit From 9796ba264ca1ad8a7ec178ecfec6331d4cac4349 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 13:19:36 +0000 Subject: r9445: Support flags, add DATA_BLOB support (This used to be commit cb5b23f0382ea7e242248cdfbbed82bc4eedfe42) --- source4/lib/tdr/tdr.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--- source4/lib/tdr/tdr.h | 7 ++++- 2 files changed, 86 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index 8cfbe3695b..1c84d2229f 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -34,7 +34,7 @@ } \ } while(0) -#define TDR_BE(tdr) ((tdr)->flags & TDR_FLAG_BIGENDIAN) +#define TDR_BE(tdr) ((tdr)->flags & TDR_BIG_ENDIAN) #define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data,ofs):SVAL(tdr->data,ofs)) #define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data,ofs):IVAL(tdr->data,ofs)) @@ -45,11 +45,9 @@ struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) { - struct tdr_pull *tdr = talloc(mem_ctx, struct tdr_pull); + struct tdr_pull *tdr = talloc_zero(mem_ctx, struct tdr_pull); tdr->data = blob->data; tdr->length = blob->length; - tdr->offset = 0; - tdr->flags = 0; return tdr; } @@ -167,7 +165,7 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, TDR_PULL_NEED_BYTES(tdr, el_size*length); - ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, (void **)v); + ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, discard_const_p(void *, v)); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; @@ -301,4 +299,81 @@ NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, time_t *t) return NT_STATUS_OK; } +NTSTATUS tdr_print_time_t(struct tdr_print *tdr, const char *name, time_t *t) +{ + if (*t == (time_t)-1 || *t == 0) { + tdr->print(tdr, "%-25s: (time_t)%d", name, (int)*t); + } else { + tdr->print(tdr, "%-25s: %s", name, timestring(tdr, *t)); + } + + return NT_STATUS_OK; +} + +NTSTATUS tdr_print_NTTIME(struct tdr_print *tdr, const char *name, NTTIME *t) +{ + tdr->print(tdr, "%-25s: %s", name, nt_time_string(tdr, *t)); + + return NT_STATUS_OK; +} +NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB *r) +{ + tdr->print(tdr, "%-25s: DATA_BLOB length=%u", name, r->length); + if (r->length) { + dump_data(10, r->data, r->length); + } + + return NT_STATUS_OK; +} + +#define TDR_ALIGN(tdr,n) (((tdr)->offset & ((n)-1)) == 0?0:((n)-((tdr)->offset&((n)-1)))) + +/* + push a DATA_BLOB onto the wire. +*/ +NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob) +{ + if (tdr->flags & TDR_ALIGN2) { + blob->length = TDR_ALIGN(tdr, 2); + } else if (tdr->flags & TDR_ALIGN4) { + blob->length = TDR_ALIGN(tdr, 4); + } else if (tdr->flags & TDR_ALIGN8) { + blob->length = TDR_ALIGN(tdr, 8); + } + + TDR_PUSH_NEED_BYTES(tdr, blob->length); + + memcpy(tdr->data+tdr->offset, blob->data, blob->length); + return NT_STATUS_OK; +} + +/* + pull a DATA_BLOB from the wire. +*/ +NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob) +{ + uint32_t length; + + if (tdr->flags & TDR_ALIGN2) { + length = TDR_ALIGN(tdr, 2); + } else if (tdr->flags & TDR_ALIGN4) { + length = TDR_ALIGN(tdr, 4); + } else if (tdr->flags & TDR_ALIGN8) { + length = TDR_ALIGN(tdr, 8); + } else if (tdr->flags & TDR_REMAINING) { + length = tdr->length - tdr->offset; + } else { + return NT_STATUS_INVALID_PARAMETER; + } + + if (tdr->length - tdr->offset < length) { + length = tdr->length - tdr->offset; + } + + TDR_PULL_NEED_BYTES(tdr, length); + + *blob = data_blob_talloc(tdr, tdr->data+tdr->offset, length); + tdr->offset += length; + return NT_STATUS_OK; +} diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index 604f9d549a..b6a1177c0d 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -18,7 +18,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define TDR_FLAG_BIGENDIAN 1 +#define TDR_BIG_ENDIAN 0x01 +#define TDR_ALIGN2 0x02 +#define TDR_ALIGN4 0x04 +#define TDR_ALIGN8 0x08 +#define TDR_REMAINING 0x10 struct tdr_pull { uint8_t *data; @@ -38,6 +42,7 @@ struct tdr_push { struct tdr_print { int level; void (*print)(struct tdr_print *, const char *, ...); + int flags; }; #define TDR_CHECK(call) do { NTSTATUS _status; \ -- cgit From f975eb06f0ddd13fe20dd336bb134e6d32be9067 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 Aug 2005 14:23:45 +0000 Subject: r9446: clean up old test file (This used to be commit 10e4ebcc4233de7c89eb25b679db69b41b3d8273) --- source4/lib/ldb/tests/schema-tests/schema.ldif | 596 ++----------------------- 1 file changed, 37 insertions(+), 559 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/schema-tests/schema.ldif b/source4/lib/ldb/tests/schema-tests/schema.ldif index d1ad50f2cc..3be31282fa 100644 --- a/source4/lib/ldb/tests/schema-tests/schema.ldif +++ b/source4/lib/ldb/tests/schema-tests/schema.ldif @@ -7,6 +7,7 @@ dn: @INDEXLIST @IDXATTR: unixID @IDXATTR: unixName @IDXATTR: privilege +@IDXATTR: lDAPDisplayName dn: @ATTRIBUTES realm: CASE_INSENSITIVE @@ -39,595 +40,72 @@ template: groupTemplate dn: @MODULES @LIST: timestamps,schema -# Top, Schema, Configuration, schema, test dn: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test objectClass: top objectClass: classSchema +lDAPDisplayName: top cn: Top -distinguishedName: CN=Top,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175509.0Z -whenChanged: 20050116175509.0Z -uSNCreated: 1437 +uSNCreated: 1 +uSNChanged: 1 subClassOf: top -governsID: 2.5.6.0 -mayContain: msDS-ObjectReferenceBL -rDNAttID: cn -uSNChanged: 1437 -showInAdvancedViewOnly: TRUE -adminDisplayName: Top -adminDescription: Top -objectClassCategory: 2 -lDAPDisplayName: top -name: Top -objectGUID: 8b12f9c3-008f-2b4f-b32b-dddd2e396ea8 -schemaIDGUID: dafbc8ff-64e9-d2cb-4569-4ba91d60aa83 -systemOnly: TRUE -systemPossSuperiors: lostAndFound -systemMayContain: url -systemMayContain: wWWHomePage +systemMustContain: objectClass +systemMayContain: structuralObjectClass +systemMayContain: createTimeStamp +systemMayContain: modifyTimeStamp +systemMayContain: creatorsName +systemMayContain: modifiersName +systemMayContain: hasSubordinates +systemMayContain: subschemaSubentry +systemMayContain: collectiveSubentry +systemMayContain: entryUUID +systemMayContain: entryCSN +systemMayContain: namingCSN +systemMayContain: superiorUUID +systemMayContain: contextCSN systemMayContain: whenCreated systemMayContain: whenChanged -systemMayContain: wellKnownObjects -systemMayContain: wbemPath -systemMayContain: uSNSource -systemMayContain: uSNLastObjRem -systemMayContain: USNIntersite -systemMayContain: uSNDSALastObjRemoved systemMayContain: uSNCreated systemMayContain: uSNChanged -systemMayContain: systemFlags -systemMayContain: subSchemaSubEntry -systemMayContain: subRefs -systemMayContain: structuralObjectClass -systemMayContain: siteObjectBL -systemMayContain: serverReferenceBL -systemMayContain: sDRightsEffective -systemMayContain: revision -systemMayContain: repsTo -systemMayContain: repsFrom -systemMayContain: directReports -systemMayContain: replUpToDateVector -systemMayContain: replPropertyMetaData -systemMayContain: name -systemMayContain: queryPolicyBL -systemMayContain: proxyAddresses -systemMayContain: proxiedObjectName -systemMayContain: possibleInferiors -systemMayContain: partialAttributeSet -systemMayContain: partialAttributeDeletionList -systemMayContain: otherWellKnownObjects -systemMayContain: objectVersion -systemMayContain: objectGUID systemMayContain: distinguishedName -systemMayContain: nonSecurityMemberBL -systemMayContain: netbootSCPBL -systemMayContain: ownerBL -systemMayContain: msDS-ReplValueMetaData -systemMayContain: msDS-ReplAttributeMetaData -systemMayContain: msDS-NonMembersBL -systemMayContain: msDS-NCReplOutboundNeighbors -systemMayContain: msDS-NCReplInboundNeighbors -systemMayContain: msDS-NCReplCursors -systemMayContain: msDS-TasksForAzRoleBL -systemMayContain: msDS-TasksForAzTaskBL -systemMayContain: msDS-OperationsForAzRoleBL -systemMayContain: msDS-OperationsForAzTaskBL -systemMayContain: msDS-MembersForAzRoleBL -systemMayContain: msDs-masteredBy -systemMayContain: mS-DS-ConsistencyGuid -systemMayContain: mS-DS-ConsistencyChildCount -systemMayContain: msDS-Approx-Immed-Subordinates -systemMayContain: msCOM-PartitionSetLink -systemMayContain: msCOM-UserLink -systemMayContain: modifyTimeStamp -systemMayContain: masteredBy -systemMayContain: managedObjects -systemMayContain: lastKnownParent -systemMayContain: isPrivilegeHolder -systemMayContain: memberOf -systemMayContain: isDeleted -systemMayContain: isCriticalSystemObject -systemMayContain: showInAdvancedViewOnly -systemMayContain: fSMORoleOwner -systemMayContain: fRSMemberReferenceBL -systemMayContain: frsComputerReferenceBL -systemMayContain: fromEntry -systemMayContain: flags -systemMayContain: extensionName -systemMayContain: dSASignature -systemMayContain: dSCorePropagationData -systemMayContain: displayNamePrintable -systemMayContain: displayName -systemMayContain: description -systemMayContain: createTimeStamp +systemMayContain: name systemMayContain: cn -systemMayContain: canonicalName -systemMayContain: bridgeheadServerListBL -systemMayContain: allowedChildClassesEffective -systemMayContain: allowedChildClasses -systemMayContain: allowedAttributesEffective -systemMayContain: allowedAttributes -systemMayContain: adminDisplayName -systemMayContain: adminDescription -systemMustContain: objectClass -systemMustContain: objectCategory -systemMustContain: nTSecurityDescriptor -systemMustContain: instanceType -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,${BASEDN} -defaultObjectCategory: CN=Top,CN=Schema,CN=Configuration,${BASEDN} - -# Container, Schema, Configuration, schema, test -dn: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Container -distinguishedName: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1113 -subClassOf: top -governsID: 1.2.840.113556.1.3.23 -mayContain: msDS-ObjectReference -rDNAttID: cn -uSNChanged: 1114 -showInAdvancedViewOnly: TRUE -adminDisplayName: Container -adminDescription: Container -objectClassCategory: 1 -lDAPDisplayName: container -name: Container -objectGUID: 48a16bf7-0128-6605-ad1a-9f5ab97b0b62 -schemaIDGUID: 3f619f8c-f7d6-6b1b-8674-b4f91b0e3755 -systemOnly: FALSE -systemPossSuperiors: msDS-AzScope -systemPossSuperiors: msDS-AzApplication -systemPossSuperiors: msDS-AzAdminManager -systemPossSuperiors: subnet -systemPossSuperiors: server -systemPossSuperiors: nTDSService -systemPossSuperiors: domainDNS -systemPossSuperiors: organization -systemPossSuperiors: configuration -systemPossSuperiors: container -systemPossSuperiors: organizationalUnit -systemMayContain: schemaVersion -systemMayContain: defaultClassStore -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Container,CN=Schema,CN=Configuration,DC=schema,DC=test +systemMayContain: userPassword +systemMayContain: labeledURI -# Class-Schema, Schema, Configuration, schema, test dn: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test objectClass: top objectClass: classSchema +lDAPDisplayName: classSchema cn: Class-Schema -distinguishedName: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175530.0Z -whenChanged: 20050116175530.0Z -uSNCreated: 673 -subClassOf: top -governsID: 1.2.840.113556.1.3.13 -rDNAttID: cn -uSNChanged: 674 -showInAdvancedViewOnly: TRUE -adminDisplayName: Class-Schema -adminDescription: Class-Schema -objectClassCategory: 1 +uSNCreated: 2 +uSNChanged: 2 lDAPDisplayName: classSchema -name: Class-Schema -objectGUID: 63151723-143e-98ab-2e14-f6df3e9c8458 -schemaIDGUID: 44cd522f-747f-e071-ff4b-b8beddfaae75 -systemOnly: FALSE -systemPossSuperiors: dMD +subClassOf: top +systemMustContain: cn +systemMustContain: subClassOf systemMayContain: systemPossSuperiors systemMayContain: systemOnly systemMayContain: systemMustContain systemMayContain: systemMayContain systemMayContain: systemAuxiliaryClass -systemMayContain: schemaFlagsEx -systemMayContain: rDNAttID systemMayContain: possSuperiors systemMayContain: mustContain -systemMayContain: msDs-Schema-Extensions -systemMayContain: msDS-IntId systemMayContain: mayContain systemMayContain: lDAPDisplayName -systemMayContain: isDefunct -systemMayContain: defaultSecurityDescriptor -systemMayContain: defaultHidingValue -systemMayContain: classDisplayName systemMayContain: auxiliaryClass -systemMustContain: subClassOf -systemMustContain: schemaIDGUID -systemMustContain: objectClassCategory -systemMustContain: governsID -systemMustContain: defaultObjectCategory -systemMustContain: cn -defaultSecurityDescriptor: D:S: -systemFlags: 134217744 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Person, Schema, Configuration, schema, test -dn: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Person -distinguishedName: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1093 -subClassOf: top -governsID: 2.5.6.6 -mayContain: attributeCertificateAttribute -rDNAttID: cn -uSNChanged: 1094 -showInAdvancedViewOnly: TRUE -adminDisplayName: Person -adminDescription: Person -objectClassCategory: 0 -lDAPDisplayName: person -name: Person -objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 -schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: container -systemMayContain: userPassword -systemMayContain: telephoneNumber -systemMayContain: sn -systemMayContain: serialNumber -systemMayContain: seeAlso -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Organizational-Person, Schema, Configuration, schema, test -dn: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Organizational-Person -distinguishedName: CN=Organizational-Person,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175533.0Z -whenChanged: 20050116175533.0Z -uSNCreated: 795 -subClassOf: person -governsID: 2.5.6.7 -mayContain: houseIdentifier -mayContain: msExchHouseIdentifier -mayContain: homePostalAddress -rDNAttID: cn -uSNChanged: 796 -showInAdvancedViewOnly: TRUE -adminDisplayName: Organizational-Person -adminDescription: Organizational-Person -objectClassCategory: 0 -lDAPDisplayName: organizationalPerson -name: Organizational-Person -objectGUID: 91aaede0-136e-c1a0-9ac0-5ddd606a0cfc -schemaIDGUID: 6f71a564-de69-3971-c169-528d111a9f27 -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: organization -systemPossSuperiors: container -systemMayContain: x121Address -systemMayContain: comment -systemMayContain: title -systemMayContain: co -systemMayContain: primaryTelexNumber -systemMayContain: telexNumber -systemMayContain: teletexTerminalIdentifier -systemMayContain: street -systemMayContain: st -systemMayContain: registeredAddress -systemMayContain: preferredDeliveryMethod -systemMayContain: postalCode -systemMayContain: postalAddress -systemMayContain: postOfficeBox -systemMayContain: thumbnailPhoto -systemMayContain: physicalDeliveryOfficeName -systemMayContain: pager -systemMayContain: otherPager -systemMayContain: otherTelephone -systemMayContain: mobile -systemMayContain: otherMobile -systemMayContain: primaryInternationalISDNNumber -systemMayContain: ipPhone -systemMayContain: otherIpPhone -systemMayContain: otherHomePhone -systemMayContain: homePhone -systemMayContain: otherFacsimileTelephoneNumber -systemMayContain: personalTitle -systemMayContain: middleName -systemMayContain: otherMailbox -systemMayContain: ou -systemMayContain: o -systemMayContain: mhsORAddress -systemMayContain: msDS-AllowedToDelegateTo -systemMayContain: manager -systemMayContain: thumbnailLogo -systemMayContain: l -systemMayContain: internationalISDNNumber -systemMayContain: initials -systemMayContain: givenName -systemMayContain: generationQualifier -systemMayContain: facsimileTelephoneNumber -systemMayContain: employeeID -systemMayContain: mail -systemMayContain: division -systemMayContain: destinationIndicator -systemMayContain: department -systemMayContain: c -systemMayContain: countryCode -systemMayContain: company -systemMayContain: assistant -systemMayContain: streetAddress -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# User, Schema, Configuration, schema, test -dn: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: User -distinguishedName: CN=User,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175549.0Z -whenChanged: 20050116175549.0Z -uSNCreated: 1442 -subClassOf: organizationalPerson -governsID: 1.2.840.113556.1.5.9 -mayContain: x500uniqueIdentifier -mayContain: userSMIMECertificate -mayContain: userPKCS12 -mayContain: uid -mayContain: secretary -mayContain: roomNumber -mayContain: preferredLanguage -mayContain: photo -mayContain: labeledURI -mayContain: jpegPhoto -mayContain: homePostalAddress -mayContain: givenName -mayContain: employeeType -mayContain: employeeNumber -mayContain: displayName -mayContain: departmentNumber -mayContain: carLicense -mayContain: audio -rDNAttID: cn -uSNChanged: 1442 -showInAdvancedViewOnly: TRUE -adminDisplayName: User -adminDescription: User -objectClassCategory: 1 -lDAPDisplayName: user -name: User -objectGUID: 2cc46512-6733-eb01-ce05-213403264ea4 -schemaIDGUID: e8a42693-9d99-2091-5554-eef0548c0b65 -systemOnly: FALSE -systemPossSuperiors: builtinDomain -systemPossSuperiors: organizationalUnit -systemPossSuperiors: domainDNS -systemMayContain: pager -systemMayContain: o -systemMayContain: mobile -systemMayContain: manager -systemMayContain: mail -systemMayContain: initials -systemMayContain: homePhone -systemMayContain: businessCategory -systemMayContain: userCertificate -systemMayContain: userWorkstations -systemMayContain: userSharedFolderOther -systemMayContain: userSharedFolder -systemMayContain: userPrincipalName -systemMayContain: userParameters -systemMayContain: userAccountControl -systemMayContain: unicodePwd -systemMayContain: terminalServer -systemMayContain: servicePrincipalName -systemMayContain: scriptPath -systemMayContain: pwdLastSet -systemMayContain: profilePath -systemMayContain: primaryGroupID -systemMayContain: preferredOU -systemMayContain: otherLoginWorkstations -systemMayContain: operatorCount -systemMayContain: ntPwdHistory -systemMayContain: networkAddress -systemMayContain: msRASSavedFramedRoute -systemMayContain: msRASSavedFramedIPAddress -systemMayContain: msRASSavedCallbackNumber -systemMayContain: msRADIUSServiceType -systemMayContain: msRADIUSFramedRoute -systemMayContain: msRADIUSFramedIPAddress -systemMayContain: msRADIUSCallbackNumber -systemMayContain: msNPSavedCallingStationID -systemMayContain: msNPCallingStationID -systemMayContain: msNPAllowDialin -systemMayContain: mSMQSignCertificatesMig -systemMayContain: mSMQSignCertificates -systemMayContain: mSMQDigestsMig -systemMayContain: mSMQDigests -systemMayContain: msIIS-FTPRoot -systemMayContain: msIIS-FTPDir -systemMayContain: msDS-User-Account-Control-Computed -systemMayContain: msDS-Site-Affinity -systemMayContain: mS-DS-CreatorSID -systemMayContain: msDS-Cached-Membership-Time-Stamp -systemMayContain: msDS-Cached-Membership -systemMayContain: msDRM-IdentityCertificate -systemMayContain: msCOM-UserPartitionSetLink -systemMayContain: maxStorage -systemMayContain: logonWorkstation -systemMayContain: logonHours -systemMayContain: logonCount -systemMayContain: lockoutTime -systemMayContain: localeID -systemMayContain: lmPwdHistory -systemMayContain: lastLogonTimestamp -systemMayContain: lastLogon -systemMayContain: lastLogoff -systemMayContain: homeDrive -systemMayContain: homeDirectory -systemMayContain: groupsToIgnore -systemMayContain: groupPriority -systemMayContain: groupMembershipSAM -systemMayContain: dynamicLDAPServer -systemMayContain: desktopProfile -systemMayContain: defaultClassStore -systemMayContain: dBCSPwd -systemMayContain: controlAccessRights -systemMayContain: codePage -systemMayContain: badPwdCount -systemMayContain: badPasswordTime -systemMayContain: adminCount -systemMayContain: aCSPolicyName -systemMayContain: accountExpires -systemAuxiliaryClass: securityPrincipal -systemAuxiliaryClass: mailRecipient -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;AO)(A;;RPLCLORC;;;PS)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a54-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;CR;ab721a56-1e2f-11d0-9819-00aa0040529b;;PS)(OA;;RPWP;77B5B886-944A-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B2-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RPWP;E45795B3-9455-11d1-AEBD-0000F80367C1;;PS)(OA;;RP;037088f8-0ae1-11d2-b422-00a0c968f939;;RS)(OA;;RP;4c164200-20c0-11d0-a768-00aa006e0529;;RS)(OA;;RP;bc0ac240-79a9-11d0-9020-00c04fc2d4cf;;RS)(A;;RC;;;AU)(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;;AU)(OA;;RP;77B5B886-944A-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;E45795B3-9455-11d1-AEBD-0000F80367C1;;AU)(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;AU)(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)(OA;;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;;RS)(OA;;RPWP;bf967a7f-0de6-11d0-a285-00aa003049e2;;CA)(OA;;RP;46a9b11d-60ae-405a-b7e8-ff8a58d456d2;;S-1-5-32-560)(OA;;WPRP;6db69a1c-9422-11d1-aebd-0000f80367c1;;S-1-5-32-561) -systemFlags: 16 -defaultHidingValue: FALSE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Security-Principal, Schema, Configuration, schema, test -dn: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Security-Principal -distinguishedName: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175546.0Z -whenChanged: 20050116175546.0Z -uSNCreated: 1406 -subClassOf: top -governsID: 1.2.840.113556.1.5.6 -rDNAttID: cn -uSNChanged: 1406 -showInAdvancedViewOnly: TRUE -adminDisplayName: Security-Principal -adminDescription: Security-Principal -objectClassCategory: 3 -lDAPDisplayName: securityPrincipal -name: Security-Principal -objectGUID: d1a6ae33-f6d5-197f-93d6-923d07d64c1a -schemaIDGUID: eb3adbfa-fb52-71a6-054f-b077e32c73f1 -systemOnly: FALSE -systemMayContain: supplementalCredentials -systemMayContain: sIDHistory -systemMayContain: securityIdentifier -systemMayContain: sAMAccountType -systemMayContain: rid -systemMayContain: tokenGroupsNoGCAcceptable -systemMayContain: tokenGroupsGlobalAndUniversal -systemMayContain: tokenGroups -systemMayContain: nTSecurityDescriptor -systemMayContain: msDS-KeyVersionNumber -systemMayContain: altSecurityIdentities -systemMayContain: accountNameHistory -systemMustContain: sAMAccountName -systemMustContain: objectSid -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Security-Principal,CN=Schema,CN=Configuration,DC=schema,DC=test - -# Mail-Recipient, Schema, Configuration, schema, test -dn: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test -objectClass: top -objectClass: classSchema -cn: Mail-Recipient -distinguishedName: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175550.0Z -whenChanged: 20050116175550.0Z -uSNCreated: 1222 -subClassOf: top -governsID: 1.2.840.113556.1.3.46 -mayContain: userSMIMECertificate -mayContain: secretary -mayContain: msExchLabeledURI -mayContain: msExchAssistantName -mayContain: labeledURI -rDNAttID: cn -uSNChanged: 1222 -showInAdvancedViewOnly: TRUE -adminDisplayName: Mail-Recipient -adminDescription: Mail-Recipient -objectClassCategory: 3 -lDAPDisplayName: mailRecipient -name: Mail-Recipient -objectGUID: 79f6fa6e-c08d-5c1f-47ff-6b33be595f50 -schemaIDGUID: bcdded89-7f72-0166-da62-08647c98fcf9 -systemOnly: FALSE -systemPossSuperiors: container -systemMayContain: userCertificate -systemMayContain: userCert -systemMayContain: textEncodedORAddress -systemMayContain: telephoneNumber -systemMayContain: showInAddressBook -systemMayContain: legacyExchangeDN -systemMayContain: garbageCollPeriod -systemMayContain: info -systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Mail-Recipient,CN=Schema,CN=Configuration,DC=schema,DC=test -# Test, Schema, Configuration, schema, test -dn: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test +dn: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test objectClass: top objectClass: classSchema -cn: Test -distinguishedName: CN=Test,CN=Schema,CN=Configuration,DC=schema,DC=test -instanceType: 4 -whenCreated: 20050116175540.0Z -whenChanged: 20050116175540.0Z -uSNCreated: 1093 +cn: Attribute-Schema +uSNCreated: 3 +uSNChanged: 3 +lDAPDisplayName: attributeSchema subClassOf: top -governsID: 2.5.6.6 -mayContain: test -rDNAttID: cn -uSNChanged: 1094 -showInAdvancedViewOnly: TRUE -adminDisplayName: Test -adminDescription: Test -objectClassCategory: 0 -lDAPDisplayName: test -name: Test -objectGUID: 7f021dc1-d7cb-e61f-1e11-53978e425b25 -schemaIDGUID: db7414bc-d145-b482-bf4a-6d0db78a483a -systemOnly: FALSE -systemPossSuperiors: organizationalUnit -systemPossSuperiors: container -systemMayContain: description +systemMustContain: oMSyntax +systemMustContain: lDAPDisplayName +systemMustContain: isSingleValued systemMustContain: cn -defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) -systemFlags: 16 -defaultHidingValue: TRUE -objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=schema,DC=test -defaultObjectCategory: CN=Person,CN=Schema,CN=Configuration,DC=schema,DC=test +systemMustContain: attributeSyntax +systemMustContain: attributeID -- cgit From 5c16371daa9d496fe109ea30bd6cfa3fd863a219 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 Aug 2005 14:26:03 +0000 Subject: r9447: Add a new tool to convert openLdap schema files into an ldif My first test with nis.schema seem to confirm it works properly Use a command line like: oLschema2ldif -I tests/schema/nis.schema -O nis_schema.ldif -b "dc=sambadom,dc=samba,dc=org" to see how it works. SSS (This used to be commit fc373fd4631420c9d8d4087a2c698b08e18372d7) --- source4/lib/ldb/Makefile.in | 5 +- source4/lib/ldb/config.mk | 11 + source4/lib/ldb/tools/cmdline.c | 12 +- source4/lib/ldb/tools/oLschema2ldif.c | 583 ++++++++++++++++++++++++++++++++++ 4 files changed, 604 insertions(+), 7 deletions(-) create mode 100644 source4/lib/ldb/tools/oLschema2ldif.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index bbd2602ef7..0b7c8c2c14 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -61,7 +61,7 @@ OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(L LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest bin/oLschema2ldif LIBS = $(LDB_LIB)($(OBJS)) @@ -102,6 +102,9 @@ bin/ldbrename: tools/ldbrename.o tools/cmdline.o $(LIBS) bin/ldbtest: tools/ldbtest.o tools/cmdline.o $(LIBS) $(CC) -o bin/ldbtest tools/ldbtest.o tools/cmdline.o $(LIB_FLAGS) +bin/oLschema2ldif: tools/oLschema2ldif.o tools/cmdline.o $(LIBS) + $(CC) -o bin/oLschema2ldif tools/oLschema2ldif.o tools/cmdline.o $(LIB_FLAGS) + .SUFFIXES: .1 .2 .3 .yo %.3: %.3.xml diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index f2c10638b0..d3f60b74ca 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -202,3 +202,14 @@ REQUIRED_SUBSYSTEMS = \ LIBLDB_CMDLINE # End BINARY ldbtest ################################################ + +################################################ +# Start BINARY oLschema2ldif +[BINARY::oLschema2ldif] +INSTALLDIR = BINDIR +OBJ_FILES= \ + lib/ldb/tools/oLschema2ldif.o +REQUIRED_SUBSYSTEMS = \ + LIBLDB_CMDLINE +# End BINARY oLschema2ldif +################################################ diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 7657301f35..cde357a088 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -151,13 +151,13 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const *ret = options; /* all utils need some option */ - if (ldb) { - if (ret->url == NULL) { - fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); - if (usage) usage(); - goto failed; - } + if (ret->url == NULL) { + fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); + if (usage) usage(); + goto failed; + } + if (strcmp(ret->url, "NONE") != 0) { if (ldb_connect(ldb, ret->url, 0, ret->options) != 0) { fprintf(stderr, "Failed to connect to %s - %s\n", ret->url, ldb_errstring(ldb)); diff --git a/source4/lib/ldb/tools/oLschema2ldif.c b/source4/lib/ldb/tools/oLschema2ldif.c new file mode 100644 index 0000000000..c24d160c3a --- /dev/null +++ b/source4/lib/ldb/tools/oLschema2ldif.c @@ -0,0 +1,583 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbdel + * + * Description: utility to delete records - modelled on ldapdelete + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/tools/cmdline.h" + +#include + +#ifdef _SAMBA_BUILD_ +#include "system/filesys.h" +#endif + +#define SCHEMA_UNKNOWN 0 +#define SCHEMA_NAME 1 +#define SCHEMA_SUP 2 +#define SCHEMA_STRUCTURAL 3 +#define SCHEMA_ABSTRACT 4 +#define SCHEMA_AUXILIARY 5 +#define SCHEMA_MUST 6 +#define SCHEMA_MAY 7 +#define SCHEMA_SINGLE_VALUE 8 +#define SCHEMA_EQUALITY 9 +#define SCHEMA_SUBSTR 10 +#define SCHEMA_SYNTAX 11 +#define SCHEMA_DESC 12 + + +struct schema_conv { + int count; + int failures; +}; + +struct token { + int type; + char *value; +}; + +struct ldb_context *ldb_ctx; +struct ldb_dn *basedn; + +static int check_braces(const char *string) +{ + int b; + char *c; + + b = 0; + if ((c = strchr(string, '(')) == NULL) { + return -1; + } + b++; + c++; + while (b) { + c = strpbrk(c, "()"); + if (c == NULL) return 1; + if (*c == '(') b++; + if (*c == ')') b--; + c++; + } + return 0; +} + +static char *skip_spaces(char *string) { + return (string + strspn(string, " \t\n")); +} + +static int add_multi_string(struct ldb_context *ldb, struct ldb_message *msg, const char *attr, char *values) +{ + char *c; + char *s; + int n; + + c = skip_spaces(values); + while (*c) { + n = strcspn(c, " \t$"); + s = talloc_strndup(msg, c, n); + if (ldb_msg_add_string(ldb, msg, attr, s) != 0) { + return -1; + } + c += n; + c += strspn(c, " \t$"); + } + + return 0; +} + +#define MSG_ADD_STRING(a, v) do { if (ldb_msg_add_string(ldb_ctx, msg, a, v) != 0) goto failed; } while(0) +#define MSG_ADD_M_STRING(a, v) do { if (add_multi_string(ldb_ctx, msg, a, v) != 0) goto failed; } while(0) + +static char *get_def_value(TALLOC_CTX *ctx, char **string) +{ + char *c = *string; + char *value; + int n; + + if (*c == '\'') { + c++; + n = strcspn(c, "\'"); + value = talloc_strndup(ctx, c, n); + c += n; + c++; /* skip closing \' */ + } else { + n = strcspn(c, " \t\n"); + value = talloc_strndup(ctx, c, n); + c += n; + } + *string = c; + + return value; +} + +static struct token *get_next_schema_token(TALLOC_CTX *ctx, char **string) +{ + char *c = skip_spaces(*string); + char *type; + struct token *token; + int n; + + token = talloc(ctx, struct token); + + n = strcspn(c, " \t\n"); + type = talloc_strndup(token, c, n); + c += n; + c = skip_spaces(c); + + if (strcasecmp("NAME", type) == 0) { + talloc_free(type); + token->type = SCHEMA_NAME; + /* we do not support aliases so we get only the first name given and skip others */ + if (*c == '(') { + char *s = strchr(c, ')'); + if (s == NULL) return NULL; + s = skip_spaces(s); + *string = s; + + c++; + c = skip_spaces(c); + } + + token->value = get_def_value(ctx, &c); + + if (*string < c) { /* single name */ + c = skip_spaces(c); + *string = c; + } + return token; + } + if (strcasecmp("SUP", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SUP; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("STRUCTURAL", type) == 0) { + talloc_free(type); + token->type = SCHEMA_STRUCTURAL; + *string = c; + return token; + } + + if (strcasecmp("ABSTRACT", type) == 0) { + talloc_free(type); + token->type = SCHEMA_ABSTRACT; + *string = c; + return token; + } + + if (strcasecmp("AUXILIARY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_AUXILIARY; + *string = c; + return token; + } + + if (strcasecmp("MUST", type) == 0) { + talloc_free(type); + token->type = SCHEMA_MUST; + + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("MAY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_MAY; + + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SINGLE-VALUE", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SINGLE_VALUE; + *string = c; + return token; + } + + if (strcasecmp("EQUALITY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_EQUALITY; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SUBSTR", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SUBSTR; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SYNTAX", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SYNTAX; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("DESC", type) == 0) { + talloc_free(type); + token->type = SCHEMA_DESC; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + token->type = SCHEMA_UNKNOWN; + token->value = type; + if (*c == ')') { + *string = c; + return token; + } + if (*c == '\'') { + c = strchr(++c, '\''); + c++; + } else { + c += strcspn(c, " \t\n"); + } + c = skip_spaces(c); + *string = c; + + return token; +} + +static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry) +{ + TALLOC_CTX *ctx; + struct ldb_message *msg; + struct token *token; + char *c, *s; + int n; + + ctx = talloc_new(mem_ctx); + msg = ldb_msg_new(ctx); + + ldb_msg_add_string(ldb_ctx, msg, "objectClass", "top"); + + c = talloc_strdup(ctx, entry); + if (!c) return NULL; + + c = skip_spaces(c); + + switch (*c) { + case 'a': + if (strncmp(c, "attributetype", 13) == 0) { + c += 13; + MSG_ADD_STRING("objectClass", "attributeSchema"); + break; + } + goto failed; + case 'o': + if (strncmp(c, "objectclass", 11) == 0) { + c += 11; + MSG_ADD_STRING("objectClass", "classSchema"); + break; + } + goto failed; + default: + goto failed; + } + + c = strchr(c, '('); + if (c == NULL) goto failed; + c++; + + c = skip_spaces(c); + + /* get attributeID */ + n = strcspn(c, " \t"); + s = talloc_strndup(msg, c, n); + MSG_ADD_STRING("attributeID", s); + c += n; + c = skip_spaces(c); + + while (*c != ')') { + token = get_next_schema_token(msg, &c); + if (!token) goto failed; + + switch (token->type) { + case SCHEMA_NAME: + MSG_ADD_STRING("cn", token->value); + MSG_ADD_STRING("name", token->value); + MSG_ADD_STRING("lDAPDisplayName", token->value); + msg->dn = ldb_dn_string_compose(msg, basedn, + "CN=%s,CN=Schema,CN=Configuration", + token->value); + break; + + case SCHEMA_SUP: + MSG_ADD_STRING("subClassOf", token->value); + break; + + case SCHEMA_STRUCTURAL: + MSG_ADD_STRING("objectClassCategory", "1"); + break; + + case SCHEMA_ABSTRACT: + MSG_ADD_STRING("objectClassCategory", "2"); + break; + + case SCHEMA_AUXILIARY: + MSG_ADD_STRING("objectClassCategory", "3"); + break; + + case SCHEMA_MUST: + MSG_ADD_M_STRING("mustContain", token->value); + break; + + case SCHEMA_MAY: + MSG_ADD_M_STRING("mayContain", token->value); + break; + + case SCHEMA_SINGLE_VALUE: + MSG_ADD_STRING("isSingleValued", "TRUE"); + break; + + case SCHEMA_EQUALITY: + /* TODO */ + break; + + case SCHEMA_SUBSTR: + /* TODO */ + break; + + case SCHEMA_SYNTAX: + MSG_ADD_STRING("attributeSyntax", token->value); + break; + + case SCHEMA_DESC: + MSG_ADD_STRING("description", token->value); + break; + + default: + fprintf(stderr, "Unknown Definition: %s\n", token->value); + } + } + + talloc_steal(mem_ctx, msg); + talloc_free(ctx); + return msg; + +failed: + talloc_free(ctx); + return NULL; +} + +static const struct schema_conv process_file(FILE *in, FILE *out) +{ + TALLOC_CTX *ctx; + struct schema_conv ret; + char *entry; + int c, t, line; + struct ldb_ldif ldif; + + ldif.changetype = LDB_CHANGETYPE_NONE; + + ctx = talloc_new(NULL); + + ret.count = 0; + ret.failures = 0; + line = 0; + + while ((c = fgetc(in)) != EOF) { + line++; + /* fprintf(stderr, "Parsing line %d\n", line); */ + if (c == '#') { + do { + c = fgetc(in); + } while (c != EOF && c != '\n'); + continue; + } + if (c == '\n') { + continue; + } + + t = 0; + entry = talloc_array(ctx, char, 1024); + if (entry == NULL) exit(-1); + + do { + if (c == '\n') { + entry[t] = '\0'; + if (check_braces(entry) == 0) { + ret.count++; + ldif.msg = process_entry(ctx, entry); + if (ldif.msg == NULL) { + ret.failures++; + fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line); + break; + } + ldb_ldif_write_file(ldb_ctx, out, &ldif); + break; + } + line++; + } else { + entry[t] = c; + t++; + } + if ((t % 1023) == 0) { + entry = talloc_realloc(ctx, entry, char, t + 1024); + if (entry == NULL) exit(-1); + } + } while ((c = fgetc(in)) != EOF); + + if (c != '\n') { + entry[t] = '\0'; + if (check_braces(entry) == 0) { + ret.count++; + ldif.msg = process_entry(ctx, entry); + if (ldif.msg == NULL) { + ret.failures++; + fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line); + break; + } + ldb_ldif_write_file(ldb_ctx, out, &ldif); + } else { + fprintf(stderr, "malformed entry on line %d\n", line); + ret.failures++; + } + } + + if (c == EOF) break; + } + + return ret; +} + +static void usage(void) +{ + printf("Usage: oLschema2ldif \n"); + printf("Options:\n"); + printf(" -I inputfile inputfile otherwise STDIN\n"); + printf(" -O outputfile outputfile otherwise STDOUT\n"); + printf(" -o options pass options like modules to activate\n"); + printf(" e.g: -o modules:timestamps\n"); + printf("\n"); + printf("Converts records from an openLdap formatted schema to an ldif schema\n\n"); + exit(1); +} + + int main(int argc, const char **argv) +{ + TALLOC_CTX *ctx; + struct schema_conv ret; + struct ldb_cmdline *options; + FILE *in = stdin; + FILE *out = stdout; + + ctx = talloc_new(NULL); + ldb_ctx = ldb_init(ctx); + + setenv("LDB_URL", "NONE", 1); + options = ldb_cmdline_process(ldb_ctx, argc, argv, usage); + + if (options->basedn == NULL) { + perror("Base DN not specified"); + exit(1); + } else { + basedn = ldb_dn_explode(ctx, options->basedn); + if (basedn == NULL) { + perror("Malformed Base DN"); + exit(1); + } + } + + if (options->input) { + in = fopen(options->input, "r"); + if (!in) { + perror(options->input); + exit(1); + } + } + if (options->output) { + out = fopen(options->output, "w"); + if (!out) { + perror(options->output); + exit(1); + } + } + + ret = process_file(in, out); + + fclose(in); + fclose(out); + + printf("Converted %d records with %d failures\n", ret.count, ret.failures); + + return 0; +} -- cgit From 7de12a8d50ebb5ead2c44b9d726bb134dc8919b6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 15:45:16 +0000 Subject: r9448: Work on reading the secrets tdb. Build tdbsam support by default. (This used to be commit 9ea601c0a675767f8ea5f316c9355572dffbc4c0) --- source4/lib/basic.mk | 9 - source4/lib/samba3/secrets.c | 542 ++++++++++++++++++++++++++++++++++++++ source4/lib/tdb/include/tdbutil.h | 2 + 3 files changed, 544 insertions(+), 9 deletions(-) create mode 100644 source4/lib/samba3/secrets.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 4dd6a05d54..7b95632c70 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -35,15 +35,6 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBCOMPRESION ################################################ - -################################################ -# Start SUBSYSTEM LIBSAMBA3 -[SUBSYSTEM::LIBSAMBA3] -INIT_OBJ_FILES = \ - lib/samba3/smbpasswd.o -# End SUBSYSTEM LIBSAMBA3 -################################################ - [SUBSYSTEM::PAM_ERRORS] OBJ_FILES = lib/pam_errors.o diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c new file mode 100644 index 0000000000..ccd53c0398 --- /dev/null +++ b/source4/lib/samba3/secrets.c @@ -0,0 +1,542 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Tim Potter 2001 + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* the Samba secrets database stores any generated, private information + such as the local SID and machine trust password */ + +#define SECRETS_DOMAIN_SID "SECRETS/SID" +#define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID" +#define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW" +#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC" +#define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC" +#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD" +#define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME" +#define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE" +#define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE" +#define SECRETS_AUTH_USER "SECRETS/AUTH_USER" +#define SECRETS_AUTH_DOMAIN "SECRETS/AUTH_DOMAIN" +#define SECRETS_AUTH_PASSWORD "SECRETS/AUTH_PASSWORD" + + +#include "includes.h" +#include "tdb.h" +#include "system/filesys.h" +#include "librpc/gen_ndr/ndr_security.h" + +/* structure for storing machine account password + (ie. when samba server is member of a domain */ +struct machine_acct_pass { + uint8_t hash[16]; + time_t mod_time; +}; + +#define SECRETS_AFS_MAXKEYS 8 + +struct afs_key { + uint32_t kvno; + char key[8]; +}; + +static TDB_CONTEXT *secrets_open(const char *fname) +{ + TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600); + + if (!tdb) { + DEBUG(0,("Failed to open %s\n", fname)); + return NULL; + } + + return tdb; +} + +/* read a entry from the secrets database - the caller must free the result + if size is non-null then the size of the entry is put in there + */ +static void *secrets_fetch(TDB_CONTEXT *tdb, const char *key, size_t *size) +{ + TDB_DATA kbuf, dbuf; + + kbuf.dptr = strdup(key); + kbuf.dsize = strlen(key); + dbuf = tdb_fetch(tdb, kbuf); + if (size) + *size = dbuf.dsize; + free(kbuf.dptr); + return dbuf.dptr; +} + +static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid) +{ + struct dom_sid *dyn_sid; + char *key; + size_t size; + + asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain); + strupper_m(key); + dyn_sid = (struct dom_sid *)secrets_fetch(tdb, key, &size); + SAFE_FREE(key); + + if (dyn_sid == NULL) + return False; + + if (size != sizeof(struct dom_sid)) + { + SAFE_FREE(dyn_sid); + return False; + } + + *sid = *dyn_sid; + SAFE_FREE(dyn_sid); + return True; +} + +static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, struct GUID *guid) +{ + struct GUID *dyn_guid; + char *key; + size_t size; + + asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain); + strupper_m(key); + dyn_guid = (struct GUID *)secrets_fetch(tdb, key, &size); + + if (!dyn_guid) { + return False; + } + + if (size != sizeof(struct GUID)) + { + DEBUG(1,("GUID size %d is wrong!\n", (int)size)); + SAFE_FREE(dyn_guid); + return False; + } + + *guid = *dyn_guid; + SAFE_FREE(dyn_guid); + return True; +} + +/** + * Form a key for fetching the machine trust account password + * + * @param domain domain name + * + * @return stored password's key + **/ +static char *trust_keystr(const char *domain) +{ + char *keystr; + + asprintf(&keystr, "%s/%s", SECRETS_MACHINE_ACCT_PASS, domain); + strupper_m(keystr); + + return keystr; +} + +/** + * Form a key for fetching a trusted domain password + * + * @param domain trusted domain name + * + * @return stored password's key + **/ +static char *trustdom_keystr(const char *domain) +{ + char *keystr; + + asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); + strupper_m(keystr); + + return keystr; +} + +/************************************************************************ + Routine to get the trust account password for a domain. + The user of this function must have locked the trust password file using + the above secrets_lock_trust_account_password(). +************************************************************************/ + +static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, + const char *domain, uint8_t ret_pwd[16], + time_t *pass_last_set_time, + uint32_t *channel) +{ + struct machine_acct_pass *pass; + char *plaintext; + size_t size; + + plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, + channel); + if (plaintext) { + DEBUG(4,("Using cleartext machine password\n")); + E_md4hash(plaintext, ret_pwd); + SAFE_FREE(plaintext); + return True; + } + + if (!(pass = secrets_fetch(tdb, trust_keystr(domain), &size))) { + DEBUG(5, ("secrets_fetch failed!\n")); + return False; + } + + if (size != sizeof(*pass)) { + DEBUG(0, ("secrets were of incorrect size!\n")); + return False; + } + + if (pass_last_set_time) *pass_last_set_time = pass->mod_time; + memcpy(ret_pwd, pass->hash, 16); + SAFE_FREE(pass); + + if (channel) + *channel = get_default_sec_channel(); + + return True; +} + +/************************************************************************ + Routine to get account password to trusted domain +************************************************************************/ + +static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time) +{ + struct trusted_dom_pass pass; + size_t size; + + /* unpacking structures */ + char* pass_buf; + int pass_len = 0; + + ZERO_STRUCT(pass); + + /* fetching trusted domain password structure */ + if (!(pass_buf = secrets_fetch(tdb, trustdom_keystr(domain), &size))) { + DEBUG(5, ("secrets_fetch failed!\n")); + return False; + } + + /* unpack trusted domain password */ + pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass); + SAFE_FREE(pass_buf); + + if (pass_len != size) { + DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n")); + return False; + } + + /* the trust's password */ + if (pwd) { + *pwd = strdup(pass.pass); + if (!*pwd) { + return False; + } + } + + /* last change time */ + if (pass_last_set_time) *pass_last_set_time = pass.mod_time; + + /* domain sid */ + + *sid = dom_sid_dup(tdb, &pass.domain_sid); + + return True; +} + +/************************************************************************ + Routine to fetch the plaintext machine account password for a realm +the password is assumed to be a null terminated ascii string +************************************************************************/ +static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain, + time_t *pass_last_set_time, + uint32_t *channel) +{ + char *key = NULL; + char *ret; + asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); + strupper_m(key); + ret = (char *)secrets_fetch(tdb, key, NULL); + SAFE_FREE(key); + + if (pass_last_set_time) { + size_t size; + uint32_t *last_set_time; + asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); + strupper_m(key); + last_set_time = secrets_fetch(tdb, key, &size); + if (last_set_time) { + *pass_last_set_time = IVAL(last_set_time,0); + SAFE_FREE(last_set_time); + } else { + *pass_last_set_time = 0; + } + SAFE_FREE(key); + } + + if (channel) { + size_t size; + uint32_t *channel_type; + asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); + strupper_m(key); + channel_type = secrets_fetch(tdb, key, &size); + if (channel_type) { + *channel = IVAL(channel_type,0); + SAFE_FREE(channel_type); + } else { + *channel = get_default_sec_channel(); + } + SAFE_FREE(key); + } + + return ret; +} + +/******************************************************************* + find the ldap password +******************************************************************/ +static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw) +{ + char *key = NULL; + size_t size; + + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) { + DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); + } + + *pw=secrets_fetch(tdb, key, &size); + SAFE_FREE(key); + + if (!size) { + return False; + } + + return True; +} + + +/** + * Get trusted domains info from secrets.tdb. + * + * The linked list is allocated on the supplied talloc context, caller gets to destroy + * when done. + * + * @param ctx Allocation context + * @param enum_ctx Starting index, eg. we can start fetching at third + * or sixth trusted domain entry. Zero is the first index. + * Value it is set to is the enum context for the next enumeration. + * @param num_domains Number of domain entries to fetch at one call + * @param domains Pointer to array of trusted domain structs to be filled up + * + * @return nt status code of rpc response + **/ + +static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains, + int *num_domains, struct samba3_trustdom ***domains) +{ + TDB_LIST_NODE *keys, *k; + struct samba3_trustdom *dom = NULL; + char *pattern; + unsigned int start_idx; + uint32_t idx = 0; + size_t size, packed_size = 0; + fstring dom_name; + char *packed_pass; + struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass); + NTSTATUS status; + + if (!secrets_init()) return NT_STATUS_ACCESS_DENIED; + + if (!pass) { + DEBUG(0, ("talloc_zero failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + *num_domains = 0; + start_idx = *enum_ctx; + + /* generate searching pattern */ + if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) { + DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", + max_num_domains, *enum_ctx)); + + *domains = talloc_zero_array(ctx, struct samba3_trustdom *, max_num_domains); + + /* fetching trusted domains' data and collecting them in a list */ + keys = tdb_search_keys(tdb, pattern); + + /* + * if there's no keys returned ie. no trusted domain, + * return "no more entries" code + */ + status = NT_STATUS_NO_MORE_ENTRIES; + + /* searching for keys in secrets db -- way to go ... */ + for (k = keys; k; k = k->next) { + char *secrets_key; + + /* important: ensure null-termination of the key string */ + secrets_key = strndup(k->node_key.dptr, k->node_key.dsize); + if (!secrets_key) { + DEBUG(0, ("strndup failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + packed_pass = secrets_fetch(tdb, secrets_key, &size); + packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass); + /* packed representation isn't needed anymore */ + SAFE_FREE(packed_pass); + + if (size != packed_size) { + DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key)); + continue; + } + + pull_ucs2_fstring(dom_name, pass->uni_name); + DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n", + idx, dom_name, sid_string_static(&pass->domain_sid))); + + SAFE_FREE(secrets_key); + + if (idx >= start_idx && idx < start_idx + max_num_domains) { + dom = talloc(ctx, struct samba3_trustdom); + if (!dom) { + /* free returned tdb record */ + return NT_STATUS_NO_MEMORY; + } + + /* copy domain sid */ + SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid)); + memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid)); + + /* copy unicode domain name */ + dom->name = talloc_memdup(ctx, pass->uni_name, + (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t)); + + (*domains)[idx - start_idx] = dom; + + DEBUG(18, ("Secret record is in required range.\n \ + start_idx = %d, max_num_domains = %d. Added to returned array.\n", + start_idx, max_num_domains)); + + *enum_ctx = idx + 1; + (*num_domains)++; + + /* set proper status code to return */ + if (k->next) { + /* there are yet some entries to enumerate */ + status = STATUS_MORE_ENTRIES; + } else { + /* this is the last entry in the whole enumeration */ + status = NT_STATUS_OK; + } + } else { + DEBUG(18, ("Secret is outside the required range.\n \ + start_idx = %d, max_num_domains = %d. Not added to returned array\n", + start_idx, max_num_domains)); + } + + idx++; + } + + DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains)); + + /* free the results of searching the keys */ + tdb_search_list_free(keys); + + return status; +} + +/******************************************************************************* + Fetch the current (highest) AFS key from secrets.tdb +*******************************************************************************/ +static BOOL secrets_fetch_afs_key(TDB_CONTEXT *tdb, const char *cell, struct afs_key *result) +{ + fstring key; + struct afs_keyfile *keyfile; + size_t size; + uint32_t i; + + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell); + + keyfile = (struct afs_keyfile *)secrets_fetch(tdb, key, &size); + + if (keyfile == NULL) + return False; + + if (size != sizeof(struct afs_keyfile)) { + SAFE_FREE(keyfile); + return False; + } + + i = ntohl(keyfile->nkeys); + + if (i > SECRETS_AFS_MAXKEYS) { + SAFE_FREE(keyfile); + return False; + } + + *result = keyfile->entry[i-1]; + + result->kvno = ntohl(result->kvno); + + return True; +} + +/****************************************************************************** + When kerberos is not available, choose between anonymous or + authenticated connections. + + We need to use an authenticated connection if DCs have the + RestrictAnonymous registry entry set > 0, or the "Additional + restrictions for anonymous connections" set in the win2k Local + Security Policy. + + Caller to free() result in domain, username, password +*******************************************************************************/ +static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char **domain, char **password) +{ + *username = secrets_fetch(tdb, SECRETS_AUTH_USER, NULL); + *domain = secrets_fetch(tdb, SECRETS_AUTH_DOMAIN, NULL); + *password = secrets_fetch(tdb, SECRETS_AUTH_PASSWORD, NULL); + + if (*username && **username) { + + if (!*domain || !**domain) + *domain = smb_xstrdup(lp_workgroup()); + + if (!*password || !**password) + *password = smb_xstrdup(""); + + DEBUG(3, ("IPC$ connections done by user %s\\%s\n", + *domain, *username)); + + } else { + DEBUG(3, ("IPC$ connections done anonymously\n")); + *username = smb_xstrdup(""); + *domain = smb_xstrdup(""); + *password = smb_xstrdup(""); + } +} diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index fb9e5cf48f..0d86ddc993 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -43,5 +43,7 @@ int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags); TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr); +int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...); +size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...); #endif /* __TDBUTIL_H__ */ -- cgit From 0b3f8c443d5094ac813ab83fa50f1555480f70af Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 17:18:35 +0000 Subject: r9449: Add simple utility for dumping Samba3 domain information. Currently only prints rids and usernames of users in passdb database. Update plan (This used to be commit 651d06728fb21393c15268ea47689c738c2c6b86) --- source4/lib/samba3/PLAN | 3 ++ source4/lib/samba3/config.mk | 10 +++++- source4/lib/samba3/sam.h | 26 ++++++++++++++ source4/lib/samba3/samba3dump.c | 75 +++++++++++++++++++++++++++++++++++++++++ source4/lib/samba3/tdbsam.c | 67 +++++++++++++++++++++++++++++------- 5 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 source4/lib/samba3/samba3dump.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 6e83e8fc33..6076141ac0 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -7,8 +7,11 @@ Three possible viable approaches: (one-way upgrades can be done by using ldbsearch -a on these dynamically generated ldb's) + Since TDB's are local, there isn't much point in writing back backwards + compatible data. 2) samr "mapping" backend (alternative for samr.ldb) (two-way) + This would allow users to keep mixed domains containing Samba3 and Samba4. 3) The vampire way of doing things (one-way) - samba3 pidl backend diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 43608577c5..5045901b3b 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -7,4 +7,12 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBSAMBA3 ################################################ - +################################################ +# Start BINARY samba3dump +[BINARY::samba3dump] +INSTALLDIR = BINDIR +INIT_OBJ_FILES = \ + lib/samba3/samba3dump.o +REQUIRED_SUBSYSTEMS = LIBBASIC LIBCMDLINE LIBSAMBA3 +# End BINARY samba3dump +################################################ diff --git a/source4/lib/samba3/sam.h b/source4/lib/samba3/sam.h index 11a9f42ec7..bc13b28e2a 100644 --- a/source4/lib/samba3/sam.h +++ b/source4/lib/samba3/sam.h @@ -21,6 +21,8 @@ #ifndef _SAMBA3_SAM_H /* _SAMBA3_SAM_H */ #define _SAMBA3_SAM_H +#include "librpc/gen_ndr/security.h" + struct samba3_samaccount { uint32_t logon_time, logoff_time, @@ -49,4 +51,28 @@ struct samba3_samaccount { uint8_t *hours; }; +/* SID Types */ +enum SID_NAME_USE +{ + SID_NAME_USE_NONE = 0, + SID_NAME_USER = 1, /* user */ + SID_NAME_DOM_GRP, /* domain group */ + SID_NAME_DOMAIN, /* domain sid */ + SID_NAME_ALIAS, /* local group */ + SID_NAME_WKN_GRP, /* well-known group */ + SID_NAME_DELETED, /* deleted account: needed for c2 rating */ + SID_NAME_INVALID, /* invalid account */ + SID_NAME_UNKNOWN, /* unknown sid type */ + SID_NAME_COMPUTER /* sid for a computer */ +}; + +struct samba3_groupmapping { + struct pdb_methods *methods; + gid_t gid; + struct dom_sid *sid; + enum SID_NAME_USE sid_name_use; + const char *nt_name; + const char *comment; +}; + #endif /* _SAMBA3_SAM_H */ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c new file mode 100644 index 0000000000..4071ba1bf9 --- /dev/null +++ b/source4/lib/samba3/samba3dump.c @@ -0,0 +1,75 @@ +/* + Unix SMB/CIFS implementation. + Samba3 database dump utility + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/samba3/sam.h" +#include "lib/cmdline/popt_common.h" + +static const char *libdir = "/var/lib/samba"; + +static NTSTATUS print_sam(void) +{ + struct samba3_samaccount *accounts; + uint32_t count, i; + char *tdbsam_file; + NTSTATUS status; + + asprintf(&tdbsam_file, "%s/passdb.tdb", libdir); + + printf("Opening TDB sam %s\n", tdbsam_file); + + status = samba3_read_tdbsam(NULL, tdbsam_file, &accounts, &count); + if (NT_STATUS_IS_ERR(status)) { + fprintf(stderr, "Error reading tdbsam database %s\n", tdbsam_file); + return status; + } + + for (i = 0; i < count; i++) { + printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); + } + + return NT_STATUS_OK; +} + +int main(int argc, char **argv) +{ + int opt; + poptContext pc; + struct poptOption long_options[] = { + POPT_AUTOHELP + { "libdir", 0, POPT_ARG_STRING, &libdir, 'l', "Set libdir [/var/lib/samba]", "LIBDIR" }, + POPT_COMMON_SAMBA + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + poptSetOtherOptionHelp(pc, ""); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + print_sam(); + + poptFreeContext(pc); + + return 0; +} diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index 0b2f975441..a16c07d2d1 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -26,6 +26,7 @@ #include "includes.h" #include "system/iconv.h" +#include "system/filesys.h" #include "lib/tdb/include/tdbutil.h" #include "lib/samba3/sam.h" @@ -37,18 +38,18 @@ /** * Open the TDB passwd database, check version and convert it if needed. * @param name filename of the tdbsam file. - * @param open_flags file access mode. + * @param version version of the tdbsam database * @return a TDB_CONTEXT handle on the tdbsam file. **/ -static TDB_CONTEXT * tdbsam_open (const char *name, int open_flags, int32_t *version) +static TDB_CONTEXT *tdbsam_open (const char *name, int32_t *version) { TDB_CONTEXT *pdb_tdb; /* Try to open tdb passwd */ if (!(pdb_tdb = tdb_open(name, 0, TDB_DEFAULT, - open_flags, 0600))) { - DEBUG(0, ("Unable to open/create TDB passwd\n")); + O_RDONLY, 0600))) { + DEBUG(0, ("Unable to open TDB passwd\n")); return NULL; } @@ -69,7 +70,7 @@ static TDB_CONTEXT * tdbsam_open (const char *name, int open_flags, int32_t *ver return pdb_tdb; } -static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf) { uint32_t username_len, domain_len, nt_username_len, dir_drive_len, unknown_str_len, munged_dial_len, @@ -80,13 +81,13 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * uint32_t len = 0; uint32_t lm_pw_len, nt_pw_len, hourslen; - if(sampass == NULL || buf == NULL) { + if(sampass == NULL || buf.dptr == NULL) { DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n")); return False; } /* unpack the buffer into variables */ - len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V0, + len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V0, &sampass->logon_time, /* d */ &sampass->logoff_time, /* d */ &sampass->kickoff_time, /* d */ @@ -133,7 +134,7 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * return True; } -static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf) { uint32_t username_len, domain_len, nt_username_len, dir_drive_len, unknown_str_len, munged_dial_len, @@ -144,13 +145,13 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * uint32_t len = 0; uint32_t lm_pw_len, nt_pw_len, hourslen; - if(sampass == NULL || buf == NULL) { + if(sampass == NULL || buf.dptr == NULL) { DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n")); return False; } /* unpack the buffer into variables */ - len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V1, + len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V1, &sampass->logon_time, /* d */ &sampass->logoff_time, /* d */ &sampass->kickoff_time, /* d */ @@ -199,7 +200,7 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * return True; } -static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, uint8_t *buf, uint32_t buflen) +static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf) { uint32_t username_len, domain_len, nt_username_len, dir_drive_len, unknown_str_len, munged_dial_len, @@ -209,13 +210,13 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * uint32_t len = 0; uint32_t lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen; - if(sampass == NULL || buf == NULL) { + if(sampass == NULL || buf.dptr == NULL) { DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n")); return False; } /* unpack the buffer into variables */ - len = tdb_unpack (tdb, (char *)buf, buflen, TDB_FORMAT_STRING_V2, + len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V2, &sampass->logon_time, /* d */ &sampass->logoff_time, /* d */ &sampass->kickoff_time, /* d */ @@ -264,3 +265,43 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * return True; } + +NTSTATUS samba3_read_tdbsam(TALLOC_CTX *ctx, const char *filename, struct samba3_samaccount **accounts, uint32_t *count) +{ + int32_t version; + TDB_CONTEXT *tdb = tdbsam_open(filename, &version); + TDB_DATA key, val; + + if (tdb == NULL) + return NT_STATUS_UNSUCCESSFUL; + + if (version < 0 || version > 2) { + return NT_STATUS_NOT_SUPPORTED; + } + + *accounts = NULL; + *count = 0; + + for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) + { + if (strncmp(key.dptr, "RID/", 4) == 0) continue; + + val = tdb_fetch(tdb, key); + + *accounts = talloc_realloc(ctx, *accounts, struct samba3_samaccount, (*count)+1); + + switch (version) + { + case 0: init_sam_from_buffer_v0(tdb, &(*accounts)[*count], val); break; + case 1: init_sam_from_buffer_v1(tdb, &(*accounts)[*count], val); break; + case 2: init_sam_from_buffer_v2(tdb, &(*accounts)[*count], val); break; + + } + + (*count)++; + } + + tdb_close(tdb); + + return NT_STATUS_OK; +} -- cgit From 70ca8615387835f60e9533dd397f10369087157f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 17:19:14 +0000 Subject: r9450: Initial work on reading group mapping database. (This used to be commit 788fd262fc736a1bdb0fe6f266b31b2268f9d8d8) --- source4/lib/samba3/group.c | 483 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 source4/lib/samba3/group.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c new file mode 100644 index 0000000000..b8cc0d6819 --- /dev/null +++ b/source4/lib/samba3/group.c @@ -0,0 +1,483 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Jean François Micouleau 1998-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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "system/iconv.h" +#include "lib/samba3/sam.h" +#include "lib/tdb/include/tdbutil.h" +#include "system/filesys.h" + +#define DATABASE_VERSION_V1 1 /* native byte format. */ +#define DATABASE_VERSION_V2 2 /* le format. */ + +#define GROUP_PREFIX "UNIXGROUP/" + +/* Alias memberships are stored reverse, as memberships. The performance + * critical operation is to determine the aliases a SID is member of, not + * listing alias members. So we store a list of alias SIDs a SID is member of + * hanging of the member as key. + */ +#define MEMBEROF_PREFIX "MEMBEROF/" + +#define ENUM_ONLY_MAPPED True +#define ENUM_ALL_MAPPED False + + +/**************************************************************************** +dump the mapping group mapping to a text file +****************************************************************************/ +static const char *decode_sid_name_use(enum SID_NAME_USE name_use) +{ + switch(name_use) { + case SID_NAME_USER: + return "User"; + case SID_NAME_DOM_GRP: + return "Domain group"; + case SID_NAME_DOMAIN: + return "Domain"; + case SID_NAME_ALIAS: + return "Local group"; + case SID_NAME_WKN_GRP: + return "Builtin group"; + case SID_NAME_DELETED: + return "Deleted"; + case SID_NAME_INVALID: + return "Invalid"; + case SID_NAME_UNKNOWN: + default: + return "Unknown type"; + } +} + +/**************************************************************************** + Open the group mapping tdb. +****************************************************************************/ +static TDB_CONTEXT *tdbgroup_open(const char *file) +{ + int32_t vers_id; + + TDB_CONTEXT *tdb = tdb_open(file, 0, TDB_DEFAULT, O_RDONLY, 0600); + if (!tdb) { + DEBUG(0,("Failed to open group mapping database\n")); + return NULL; + } + + /* Cope with byte-reversed older versions of the db. */ + vers_id = tdb_fetch_int32(tdb, "INFO/version"); + if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) { + /* Written on a bigendian machine with old fetch_int code. Save as le. */ + vers_id = DATABASE_VERSION_V2; + } + + if (vers_id != DATABASE_VERSION_V2) { + return NULL; + } + + return tdb; +} + +/**************************************************************************** + Return the sid and the type of the unix group. +****************************************************************************/ + +static BOOL get_group_map_from_sid(TDB_CONTEXT *tdb, struct dom_sid sid, struct samba3_groupmapping *map) +{ + TDB_DATA kbuf, dbuf; + const char *key; + int ret = 0; + + /* the key is the SID, retrieving is direct */ + + kbuf.dptr = talloc_asprintf(tdb, "%s%s", GROUP_PREFIX, dom_sid_string(tdb, &sid)); + kbuf.dsize = strlen(key)+1; + + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + return False; + + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + + SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n")); + return False; + } + + map->sid = dom_sid_dup(tdb, &sid); + + return True; +} + +/**************************************************************************** + Return the sid and the type of the unix group. +****************************************************************************/ + +static BOOL get_group_map_from_gid(TDB_CONTEXT *tdb, gid_t gid, struct samba3_groupmapping *map) +{ + TDB_DATA kbuf, dbuf, newkey; + int ret; + + /* we need to enumerate the TDB to find the GID */ + + for (kbuf = tdb_firstkey(tdb); + kbuf.dptr; + newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + + if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue; + + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + continue; + + + map->sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); + + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + + SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n")); + return False; + } + + if (gid==map->gid) { + SAFE_FREE(kbuf.dptr); + return True; + } + } + + return False; +} + +/**************************************************************************** + Return the sid and the type of the unix group. +****************************************************************************/ + +static BOOL get_group_map_from_ntname(TDB_CONTEXT *tdb, const char *name, struct samba3_groupmapping *map) +{ + TDB_DATA kbuf, dbuf, newkey; + int ret; + + /* we need to enumerate the TDB to find the name */ + + for (kbuf = tdb_firstkey(tdb); + kbuf.dptr; + newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + + if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue; + + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + continue; + + map->sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); + + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + + SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n")); + return False; + } + + if (StrCaseCmp(name, map->nt_name)==0) { + SAFE_FREE(kbuf.dptr); + return True; + } + } + + return False; +} + +/**************************************************************************** + Enumerate the group mapping. +****************************************************************************/ + +static BOOL enum_group_mapping(TDB_CONTEXT *tdb, enum SID_NAME_USE sid_name_use, struct samba3_groupmapping **rmap, + int *num_entries, BOOL unix_only) +{ + TDB_DATA kbuf, dbuf, newkey; + struct samba3_groupmapping map; + struct samba3_groupmapping *mapt; + int ret; + int entries=0; + + *num_entries=0; + *rmap=NULL; + + for (kbuf = tdb_firstkey(tdb); + kbuf.dptr; + newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + + if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) + continue; + + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + continue; + + map.sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); + + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", + &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); + + SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); + continue; + } + + /* list only the type or everything if UNKNOWN */ + if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) { + DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); + continue; + } + + if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) { + DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name)); + continue; + } + + DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,decode_sid_name_use(map.sid_name_use))); + + mapt = talloc_realloc(tdb, *rmap, struct samba3_groupmapping, entries+1); + if (!mapt) { + DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n")); + SAFE_FREE(*rmap); + return False; + } + else + (*rmap) = mapt; + + mapt[entries].gid = map.gid; + mapt[entries].sid = dom_sid_dup(tdb, map.sid); + mapt[entries].sid_name_use = map.sid_name_use; + mapt[entries].nt_name = map.nt_name; + mapt[entries].comment = map.comment; + + entries++; + + } + + *num_entries=entries; + + return True; +} + +/* This operation happens on session setup, so it should better be fast. We + * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */ + +static NTSTATUS one_alias_membership(TDB_CONTEXT *tdb, + const struct dom_sid *member, struct dom_sid **sids, int *num) +{ + TDB_DATA kbuf, dbuf; + const char *p; + + char * key = talloc_asprintf(tdb, "%s%s", MEMBEROF_PREFIX, dom_sid_string(tdb, member)); + + kbuf.dsize = strlen(key)+1; + kbuf.dptr = key; + + dbuf = tdb_fetch(tdb, kbuf); + + if (dbuf.dptr == NULL) { + return NT_STATUS_OK; + } + + p = dbuf.dptr; + + while (next_token(&p, string_sid, " ", sizeof(string_sid))) { + + struct dom_sid alias; + + if (!string_to_sid(&alias, string_sid)) + continue; + + add_sid_to_array_unique(NULL, &alias, sids, num); + + if (sids == NULL) + return NT_STATUS_NO_MEMORY; + } + + SAFE_FREE(dbuf.dptr); + return NT_STATUS_OK; +} + +static NTSTATUS alias_memberships(TDB_CONTEXT *tdb, const struct dom_sid *members, int num_members, + struct dom_sid **sids, int *num) +{ + int i; + + *num = 0; + *sids = NULL; + + for (i=0; ialias, &alias) != 0) + continue; + + /* Ok, we found the alias we're looking for in the membership + * list currently scanned. The key represents the alias + * member. Add that. */ + + member_string = strchr(key.dptr, '/'); + + /* Above we tested for MEMBEROF_PREFIX which includes the + * slash. */ + + SMB_ASSERT(member_string != NULL); + member_string += 1; + + if (!string_to_sid(&member, member_string)) + continue; + + add_sid_to_array(NULL, &member, closure->sids, closure->num); + } + + return 0; +} + +static NTSTATUS enum_aliasmem(TDB_CONTEXT *tdb, const struct dom_sid *alias, struct dom_sid **sids, int *num) +{ + struct samba3_groupmapping map; + struct aliasmem_closure closure; + + if (!get_group_map_from_sid(*alias, &map)) + return NT_STATUS_NO_SUCH_ALIAS; + + if ( (map.sid_name_use != SID_NAME_ALIAS) && + (map.sid_name_use != SID_NAME_WKN_GRP) ) + return NT_STATUS_NO_SUCH_ALIAS; + + *sids = NULL; + *num = 0; + + closure.alias = alias; + closure.sids = sids; + closure.num = num; + + tdb_traverse(tdb, collect_aliasmem, &closure); + return NT_STATUS_OK; +} + +/* + * + * High level functions + * better to use them than the lower ones. + * + * we are checking if the group is in the mapping file + * and if the group is an existing unix group + * + */ + +/* get a domain group from it's SID */ + +/* get a local (alias) group from it's SID */ + +static BOOL get_local_group_from_sid(TDB_CONTEXT *tdb, struct dom_sid *sid, struct samba3_groupmapping *map) +{ + BOOL ret; + + /* The group is in the mapping table */ + ret = pdb_getgrsid(map, *sid); + + if ( !ret ) + return False; + + if ( ( (map->sid_name_use != SID_NAME_ALIAS) && + (map->sid_name_use != SID_NAME_WKN_GRP) ) + || (map->gid == -1) + || (getgrgid(map->gid) == NULL) ) + { + return False; + } + +#if 1 /* JERRY */ + /* local groups only exist in the group mapping DB so this + is not necessary */ + + else { + /* the group isn't in the mapping table. + * make one based on the unix information */ + uint32_t alias_rid; + struct group *grp; + + sid_peek_rid(sid, &alias_rid); + map->gid=pdb_group_rid_to_gid(alias_rid); + + grp = getgrgid(map->gid); + if ( !grp ) { + DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid)); + return False; + } + + map->sid_name_use=SID_NAME_ALIAS; + + fstrcpy(map->nt_name, grp->gr_name); + fstrcpy(map->comment, "Local Unix Group"); + + sid_copy(&map->sid, sid); + } +#endif + + return True; +} -- cgit From 894a1ed5ae01a54c79b8bc8510e9a7d6090cd90d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 Aug 2005 17:20:34 +0000 Subject: r9451: some fixes now core.schema and cosine.schema are also read properly (This used to be commit 0a26ee04322a06069be48dbc33307e4997700f74) --- source4/lib/ldb/tools/oLschema2ldif.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/oLschema2ldif.c b/source4/lib/ldb/tools/oLschema2ldif.c index c24d160c3a..0a88ba6b71 100644 --- a/source4/lib/ldb/tools/oLschema2ldif.c +++ b/source4/lib/ldb/tools/oLschema2ldif.c @@ -53,9 +53,10 @@ #define SCHEMA_MAY 7 #define SCHEMA_SINGLE_VALUE 8 #define SCHEMA_EQUALITY 9 -#define SCHEMA_SUBSTR 10 -#define SCHEMA_SYNTAX 11 -#define SCHEMA_DESC 12 +#define SCHEMA_ORDERING 10 +#define SCHEMA_SUBSTR 11 +#define SCHEMA_SYNTAX 12 +#define SCHEMA_DESC 13 struct schema_conv { @@ -181,7 +182,15 @@ static struct token *get_next_schema_token(TALLOC_CTX *ctx, char **string) talloc_free(type); token->type = SCHEMA_SUP; - token->value = get_def_value(ctx, &c); + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } c = skip_spaces(c); *string = c; @@ -265,6 +274,17 @@ static struct token *get_next_schema_token(TALLOC_CTX *ctx, char **string) return token; } + if (strcasecmp("ORDERING", type) == 0) { + talloc_free(type); + token->type = SCHEMA_ORDERING; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + if (strcasecmp("SUBSTR", type) == 0) { talloc_free(type); token->type = SCHEMA_SUBSTR; @@ -381,7 +401,7 @@ static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry) break; case SCHEMA_SUP: - MSG_ADD_STRING("subClassOf", token->value); + MSG_ADD_M_STRING("subClassOf", token->value); break; case SCHEMA_STRUCTURAL: @@ -412,6 +432,10 @@ static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry) /* TODO */ break; + case SCHEMA_ORDERING: + /* TODO */ + break; + case SCHEMA_SUBSTR: /* TODO */ break; -- cgit From 6e388c27d86d77f2c7f9414fbb152c246ca53022 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Aug 2005 20:01:10 +0000 Subject: r9455: Support for reading the policy database (This used to be commit 7548a5012aad41bde0652d4532d184545997be86) --- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/policy.c | 67 +++++++++++++++++++++++++++++++++++++++ source4/lib/samba3/policy.h | 37 +++++++++++++++++++++ source4/lib/samba3/samba3dump.c | 26 +++++++++++++++ source4/lib/tdb/include/tdbutil.h | 2 ++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 source4/lib/samba3/policy.c create mode 100644 source4/lib/samba3/policy.h (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 5045901b3b..ba6c1a8dbc 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -3,7 +3,8 @@ [SUBSYSTEM::LIBSAMBA3] INIT_OBJ_FILES = \ lib/samba3/smbpasswd.o \ - lib/samba3/tdbsam.o + lib/samba3/tdbsam.o \ + lib/samba3/policy.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c new file mode 100644 index 0000000000..796e6eefac --- /dev/null +++ b/source4/lib/samba3/policy.c @@ -0,0 +1,67 @@ +/* + * Unix SMB/CIFS implementation. + * account policy storage + * Copyright (C) Jean François Micouleau 1998-2001. + * Copyright (C) Andrew Bartlett 2002 + * + * 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 + * (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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "lib/tdb/include/tdbutil.h" +#include "lib/samba3/policy.h" +#include "system/filesys.h" + +#define DATABASE_VERSION 2 + +/**************************************************************************** + Open the account policy tdb. +****************************************************************************/ + +struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn) +{ + struct samba3_policy *ret; + const char *vstring = "INFO/version"; + uint32_t version; + + TDB_CONTEXT *tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600); + if (!tdb) { + DEBUG(0,("Failed to open account policy database\n")); + return NULL; + } + + /* handle a Samba upgrade */ + if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { + tdb_store_uint32(tdb, vstring, DATABASE_VERSION); + } + + ret = talloc_zero(ctx, struct samba3_policy); + + tdb_fetch_uint32(tdb, "min password length", &ret->min_password_length); + tdb_fetch_uint32(tdb, "password history", &ret->password_history); + tdb_fetch_uint32(tdb, "user must logon to change pasword", &ret->user_must_logon_to_change_password); + tdb_fetch_uint32(tdb, "maximum password age", &ret->maximum_password_age); + tdb_fetch_uint32(tdb, "minimum password age", &ret->minimum_password_age); + tdb_fetch_uint32(tdb, "lockout duration", &ret->lockout_duration); + tdb_fetch_uint32(tdb, "reset count minutes", &ret->reset_count_minutes); + tdb_fetch_uint32(tdb, "bad lockout minutes", &ret->bad_lockout_minutes); + tdb_fetch_uint32(tdb, "disconnect time", &ret->disconnect_time); + tdb_fetch_uint32(tdb, "refuse machine password change", &ret->refuse_machine_password_change); + + tdb_close(tdb); + + return ret; +} + diff --git a/source4/lib/samba3/policy.h b/source4/lib/samba3/policy.h new file mode 100644 index 0000000000..b41f38a394 --- /dev/null +++ b/source4/lib/samba3/policy.h @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SAMBA3_POLICY_H /* _SAMBA3_POLICY_H */ +#define _SAMBA3_POLICY_H + +struct samba3_policy +{ + uint32_t min_password_length; + uint32_t password_history; + uint32_t user_must_logon_to_change_password; + uint32_t maximum_password_age; + uint32_t minimum_password_age; + uint32_t lockout_duration; + uint32_t reset_count_minutes; + uint32_t bad_lockout_minutes; + uint32_t disconnect_time; + uint32_t refuse_machine_password_change; +}; + +#endif /* _SAMBA3_POLICY_H */ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index 4071ba1bf9..72052092ff 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -20,11 +20,34 @@ */ #include "includes.h" +#include "lib/samba3/policy.h" #include "lib/samba3/sam.h" #include "lib/cmdline/popt_common.h" static const char *libdir = "/var/lib/samba"; +static NTSTATUS print_policy(void) +{ + struct samba3_policy *ret; + char *policy_file; + TALLOC_CTX *mem_ctx = talloc_init(NULL); + + policy_file = talloc_asprintf(mem_ctx, "%s/account_policy.tdb", libdir); + + printf("Opening policy file %s\n", policy_file); + + ret = samba3_read_account_policy(mem_ctx, policy_file); + + if (ret == NULL) + return NT_STATUS_UNSUCCESSFUL; + + printf("Min password length: %d\n", ret->min_password_length); + + talloc_free(mem_ctx); + + return NT_STATUS_OK; +} + static NTSTATUS print_sam(void) { struct samba3_samaccount *accounts; @@ -39,8 +62,10 @@ static NTSTATUS print_sam(void) status = samba3_read_tdbsam(NULL, tdbsam_file, &accounts, &count); if (NT_STATUS_IS_ERR(status)) { fprintf(stderr, "Error reading tdbsam database %s\n", tdbsam_file); + SAFE_FREE(tdbsam_file); return status; } + SAFE_FREE(tdbsam_file); for (i = 0; i < count; i++) { printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); @@ -68,6 +93,7 @@ int main(int argc, char **argv) } print_sam(); + print_policy(); poptFreeContext(pc); diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index 0d86ddc993..2f7c0ec234 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -38,7 +38,9 @@ int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *o int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval); void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval); int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr); +BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t value); int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v); +BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t *value); int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags); -- cgit From 81556a90785c90f928690929c5735bc3ee9c8eca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 22 Aug 2005 01:51:02 +0000 Subject: r9464: fixed a problem with child pointers copied into non-allocated mpr variables. We now use the same free technique as is used for mpr strings, rather than relying on being a child of the variable (This used to be commit 3d6739eaa6e1b56d67bc7d9b5350a6911c96597a) --- source4/lib/appweb/mpr/var.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c index 77f4cbc55a..09979156e8 100644 --- a/source4/lib/appweb/mpr/var.c +++ b/source4/lib/appweb/mpr/var.c @@ -181,6 +181,13 @@ static bool freeVarStorage(MprVar *vp, int force) } break; + case MPR_TYPE_PTR: + if (vp->allocatedData) { + vp->allocatedData = 0; + mprFree(vp->ptr); + } + break; + case MPR_TYPE_OBJECT: #if VAR_DEBUG /* @@ -1418,7 +1425,12 @@ static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) case MPR_TYPE_PTR: /* we have to reference here so talloc structures survive a copy */ - dest->ptr = talloc_reference(dest, src->ptr); + if (src->allocatedData) { + dest->ptr = talloc_reference(mprMemCtx(), src->ptr); + dest->allocatedData = 1; + } else { + dest->ptr = src->ptr; + } break; case MPR_TYPE_STRING_CFUNCTION: -- cgit From 5b15e435d101f87a0833625f217643acae5a7a75 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 22 Aug 2005 11:37:20 +0000 Subject: r9472: Add read-only version of Samba3 registry database (doesn't compile yet) (This used to be commit 77cbb6299847bab1272cc681f4b8f54a9fca1339) --- source4/lib/samba3/registry.c | 172 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 source4/lib/samba3/registry.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/registry.c b/source4/lib/samba3/registry.c new file mode 100644 index 0000000000..22fa2b2636 --- /dev/null +++ b/source4/lib/samba3/registry.c @@ -0,0 +1,172 @@ +/* + * Unix SMB/CIFS implementation. + * Virtual Windows Registry Layer + * Copyright (C) Gerald Carter 2002-2005 + * Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of internal registry database functions. */ + +#include "includes.h" + +#define VALUE_PREFIX "SAMBA_REGVAL" +#define REGVER_V1 1 /* first db version with write support */ + +/*********************************************************************** + Open the registry database + ***********************************************************************/ + +static TDB_CONTEXT *samba3_open_registry ( const char *fn ) +{ + uint32_t vers_id; + + /* placeholder tdb; reinit upon startup */ + + if ( !(tdb = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0600)) ) + { + return NULL; + } + + vers_id = tdb_fetch_int32(tdb, "INFO/version"); + + if (vers_id > REGVER_V1) + return NULL; + + return True; +} + +/*********************************************************************** + Retrieve an array of strings containing subkeys. Memory should be + released by the caller. + ***********************************************************************/ + +int regdb_fetch_keys( TDB_CONTEXT *tdb, const char* key, REGSUBKEY_CTR *ctr ) +{ + char *path; + uint32_t num_items; + TDB_DATA dbuf; + char *buf; + uint32_t buflen, len; + int i; + fstring subkeyname; + + DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); + + path = talloc_strdup(key); + + /* convert to key format */ + for ( i = 0; path[i]; i++) { + if ( path[i] == '\\' ) + path[i] = '/'; + } + strupper_m( path ); + + dbuf = tdb_fetch_bystring( tdb, path ); + + buf = dbuf.dptr; + buflen = dbuf.dsize; + + if ( !buf ) { + DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key)); + return -1; + } + + len = tdb_unpack( buf, buflen, "d", &num_items); + + for (i=0; i Date: Tue, 23 Aug 2005 03:22:25 +0000 Subject: r9503: removed duplicate REG_* defines from registry.h now that they are generated in winreg.h (This used to be commit fc15e1b003a2b24dc73a6a7f2bbc45e20373dda1) --- source4/lib/registry/common/reg_util.c | 1 + source4/lib/registry/reg_backend_ldb.c | 5 +++-- source4/lib/registry/tools/regpatch.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 2d933f2e6b..65f1167832 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -20,6 +20,7 @@ #include "includes.h" #include "registry.h" +#include "librpc/gen_ndr/winreg.h" static const struct { uint32_t id; diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 404dab4dc1..76ad1facc1 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -22,6 +22,7 @@ #include "registry.h" #include "lib/ldb/include/ldb.h" #include "db_wrap.h" +#include "librpc/gen_ndr/winreg.h" struct ldb_key_data { @@ -51,7 +52,7 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c *len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, data); break; - case REG_DWORD_LE: + case REG_DWORD: *len = 4; *data = talloc(mem_ctx, uint32_t); SIVAL(*data, 0, strtol(val->data, NULL, 0)); @@ -78,7 +79,7 @@ static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CT val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, data, len, &val.data); ldb_msg_add_value(ctx, msg, "data", &val); break; - case REG_DWORD_LE: + case REG_DWORD: ldb_msg_add_string(ctx, msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data, 0))); break; default: diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 3ada9f66e2..c2f01ce5b4 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -25,6 +25,7 @@ #include "registry.h" #include "lib/cmdline/popt_common.h" #include "system/filesys.h" +#include "librpc/gen_ndr/winreg.h" /* * Routines to parse a REGEDIT4 file -- cgit From 8f9478b09d39d8c13871684a6af3d3e1629a0e84 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 23 Aug 2005 05:21:04 +0000 Subject: r9504: use some low level ejs hackery to give much better exception error messages in both the web server and smbscript. We can now give backtraces for all internal asserts, not just high level errors (This used to be commit 84c756b25ccb2bd75360bdb9b7b7643975d1f3b3) --- source4/lib/appweb/ejs/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/config.h b/source4/lib/appweb/ejs/config.h index 320318a0b2..de8a1096c9 100644 --- a/source4/lib/appweb/ejs/config.h +++ b/source4/lib/appweb/ejs/config.h @@ -8,7 +8,7 @@ #define BLD_APPWEB_CONFIG "normal.conf" #define BLD_APPWEB 0 #define BLD_COMPANY "Mbedthis" -#define BLD_DEBUG 1 +#define BLD_DEBUG 0 #define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" #define BLD_HTTP_PORT 7777 #define BLD_LIB_VERSION "1.0.0" -- cgit From c1b6fd5c4bce4035d99b03eb8f9f66db590fee3d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 23 Aug 2005 23:55:41 +0000 Subject: r9552: Add idmap support. (This used to be commit 37882f22873fdeb3bf4ae90128e335abbd90db5f) --- source4/lib/samba3/idmap.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 source4/lib/samba3/idmap.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c new file mode 100644 index 0000000000..c541c5bc92 --- /dev/null +++ b/source4/lib/samba3/idmap.c @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + + idmap TDB backend + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Simo Sorce 2003 + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/tdb/include/tdbutil.h" +#include "lib/samba3/sam.h" +#include "system/filesys.h" + +/* High water mark keys */ +#define HWM_GROUP "GROUP HWM" +#define HWM_USER "USER HWM" + +/* idmap version determines auto-conversion */ +#define IDMAP_VERSION 2 + +/***************************************************************************** + Initialise idmap database. +*****************************************************************************/ + +NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmap *idmap ) +{ + int32_t version; + TDB_CONTEXT *tdb; + TDB_DATA key, val; + + /* Open idmap repository */ + if (!(tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0644))) { + DEBUG(0, ("idmap_init: Unable to open idmap database\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* check against earlier versions */ + version = tdb_fetch_int32(tdb, "IDMAP_VERSION"); + if (version != IDMAP_VERSION) { + DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + + idmap->mapping_count = 0; + idmap->mappings = NULL; + idmap->user_hwm = tdb_fetch_int32(tdb, HWM_USER); + idmap->group_hwm = tdb_fetch_int32(tdb, HWM_GROUP); + + for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) + { + struct samba3_idmap_mapping map; + + if (strncmp(key.dptr, "GID ", 4) == 0) { + map.type = IDMAP_GROUP; + map.unix_id = atoi(key.dptr+4); + val = tdb_fetch(tdb, key); + map.sid = dom_sid_parse_talloc(ctx, val.dptr); + } else if (strncmp(key.dptr, "UID ", 4) == 0) { + map.type = IDMAP_USER; + map.unix_id = atoi(key.dptr+4); + val = tdb_fetch(tdb, key); + map.sid = dom_sid_parse_talloc(ctx, val.dptr); + } else { + continue; + } + + idmap->mappings = talloc_realloc(ctx, idmap->mappings, struct samba3_idmap_mapping, idmap->mapping_count+1); + + idmap->mappings[idmap->mapping_count] = map; + idmap->mapping_count++; + } + + tdb_close(tdb); + + return NT_STATUS_OK; +} -- cgit From c0ab8767118bc0e8a57bc1b31e37a261272fbc33 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 00:58:52 +0000 Subject: r9555: More updates. Everything except for secrets.c compiles now.. (This used to be commit e59d6156b2d569ca788fe1824148f05f4a7a9918) --- source4/lib/samba3/config.mk | 5 +- source4/lib/samba3/group.c | 2 +- source4/lib/samba3/idmap.c | 2 +- source4/lib/samba3/policy.c | 4 +- source4/lib/samba3/policy.h | 37 --------- source4/lib/samba3/sam.h | 78 ----------------- source4/lib/samba3/samba3.h | 119 ++++++++++++++++++++++++++ source4/lib/samba3/samba3dump.c | 3 +- source4/lib/samba3/secrets.c | 160 ++++++++++++++++++++++------------- source4/lib/samba3/tdbsam.c | 2 +- source4/lib/samba3/winsdb.c | 179 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 413 insertions(+), 178 deletions(-) delete mode 100644 source4/lib/samba3/policy.h delete mode 100644 source4/lib/samba3/sam.h create mode 100644 source4/lib/samba3/samba3.h create mode 100644 source4/lib/samba3/winsdb.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index ba6c1a8dbc..15802d3b8e 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -4,7 +4,10 @@ INIT_OBJ_FILES = \ lib/samba3/smbpasswd.o \ lib/samba3/tdbsam.o \ - lib/samba3/policy.o + lib/samba3/policy.o \ + lib/samba3/idmap.o \ + lib/samba3/winsdb.o +# lib/samba3/secrets.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index b8cc0d6819..d7097f596a 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -21,7 +21,7 @@ #include "includes.h" #include "system/iconv.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "lib/tdb/include/tdbutil.h" #include "system/filesys.h" diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index c541c5bc92..64d6387ed4 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -25,7 +25,7 @@ #include "includes.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "system/filesys.h" /* High water mark keys */ diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c index 796e6eefac..bfb3ac373e 100644 --- a/source4/lib/samba3/policy.c +++ b/source4/lib/samba3/policy.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/policy.h" +#include "lib/samba3/samba3.h" #include "system/filesys.h" #define DATABASE_VERSION 2 @@ -65,3 +65,5 @@ struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn return ret; } + +/* FIXME: Read privileges as well */ diff --git a/source4/lib/samba3/policy.h b/source4/lib/samba3/policy.h deleted file mode 100644 index b41f38a394..0000000000 --- a/source4/lib/samba3/policy.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _SAMBA3_POLICY_H /* _SAMBA3_POLICY_H */ -#define _SAMBA3_POLICY_H - -struct samba3_policy -{ - uint32_t min_password_length; - uint32_t password_history; - uint32_t user_must_logon_to_change_password; - uint32_t maximum_password_age; - uint32_t minimum_password_age; - uint32_t lockout_duration; - uint32_t reset_count_minutes; - uint32_t bad_lockout_minutes; - uint32_t disconnect_time; - uint32_t refuse_machine_password_change; -}; - -#endif /* _SAMBA3_POLICY_H */ diff --git a/source4/lib/samba3/sam.h b/source4/lib/samba3/sam.h deleted file mode 100644 index bc13b28e2a..0000000000 --- a/source4/lib/samba3/sam.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Registry interface - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _SAMBA3_SAM_H /* _SAMBA3_SAM_H */ -#define _SAMBA3_SAM_H - -#include "librpc/gen_ndr/security.h" - -struct samba3_samaccount { - uint32_t logon_time, - logoff_time, - kickoff_time, - bad_password_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time; - char *username; - char *domain; - char *nt_username; - char *dir_drive; - char *unknown_str; - char *munged_dial; - char *fullname; - char *homedir; - char *logon_script; - char *profile_path; - char *acct_desc; - char *workstations; - uint32_t user_rid, group_rid, hours_len, unknown_6; - uint16_t acct_ctrl, logon_divs; - uint16_t bad_password_count, logon_count; - uint8_t *lm_pw_ptr, *nt_pw_ptr; - uint8_t *nt_pw_hist_ptr; - uint8_t *hours; -}; - -/* SID Types */ -enum SID_NAME_USE -{ - SID_NAME_USE_NONE = 0, - SID_NAME_USER = 1, /* user */ - SID_NAME_DOM_GRP, /* domain group */ - SID_NAME_DOMAIN, /* domain sid */ - SID_NAME_ALIAS, /* local group */ - SID_NAME_WKN_GRP, /* well-known group */ - SID_NAME_DELETED, /* deleted account: needed for c2 rating */ - SID_NAME_INVALID, /* invalid account */ - SID_NAME_UNKNOWN, /* unknown sid type */ - SID_NAME_COMPUTER /* sid for a computer */ -}; - -struct samba3_groupmapping { - struct pdb_methods *methods; - gid_t gid; - struct dom_sid *sid; - enum SID_NAME_USE sid_name_use; - const char *nt_name; - const char *comment; -}; - -#endif /* _SAMBA3_SAM_H */ diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h new file mode 100644 index 0000000000..d3e03cf923 --- /dev/null +++ b/source4/lib/samba3/samba3.h @@ -0,0 +1,119 @@ +/* + Unix SMB/CIFS implementation. + Samba3 interfaces + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SAMBA3_H /* _SAMBA3_H */ +#define _SAMBA3_H + +#include "librpc/gen_ndr/security.h" + +struct samba3_samaccount { + uint32_t logon_time, + logoff_time, + kickoff_time, + bad_password_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time; + char *username; + char *domain; + char *nt_username; + char *dir_drive; + char *unknown_str; + char *munged_dial; + char *fullname; + char *homedir; + char *logon_script; + char *profile_path; + char *acct_desc; + char *workstations; + uint32_t user_rid, group_rid, hours_len, unknown_6; + uint16_t acct_ctrl, logon_divs; + uint16_t bad_password_count, logon_count; + uint8_t *lm_pw_ptr, *nt_pw_ptr; + uint8_t *nt_pw_hist_ptr; + uint8_t *hours; +}; + +/* SID Types */ +enum SID_NAME_USE +{ + SID_NAME_USE_NONE = 0, + SID_NAME_USER = 1, /* user */ + SID_NAME_DOM_GRP, /* domain group */ + SID_NAME_DOMAIN, /* domain sid */ + SID_NAME_ALIAS, /* local group */ + SID_NAME_WKN_GRP, /* well-known group */ + SID_NAME_DELETED, /* deleted account: needed for c2 rating */ + SID_NAME_INVALID, /* invalid account */ + SID_NAME_UNKNOWN, /* unknown sid type */ + SID_NAME_COMPUTER /* sid for a computer */ +}; + +struct samba3_groupmapping { + struct pdb_methods *methods; + gid_t gid; + struct dom_sid *sid; + enum SID_NAME_USE sid_name_use; + const char *nt_name; + const char *comment; +}; + +struct samba3_idmap_mapping +{ + enum { IDMAP_GROUP, IDMAP_USER } type; + uint32_t unix_id; + struct dom_sid *sid; +}; + +struct samba3_idmap +{ + /* High water marks */ + uint32_t user_hwm; + uint32_t group_hwm; + + uint32_t mapping_count; + struct samba3_idmap_mapping *mappings; +}; + +struct samba3_winsdb_entry +{ + char *name; + int nb_flags; + int type; + time_t ttl; + uint32_t ip_count; + struct ipv4_addr *ips; +}; + +struct samba3_policy +{ + uint32_t min_password_length; + uint32_t password_history; + uint32_t user_must_logon_to_change_password; + uint32_t maximum_password_age; + uint32_t minimum_password_age; + uint32_t lockout_duration; + uint32_t reset_count_minutes; + uint32_t bad_lockout_minutes; + uint32_t disconnect_time; + uint32_t refuse_machine_password_change; +}; + +#endif /* _SAMBA3_H */ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index 72052092ff..6bcfce96fa 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -20,8 +20,7 @@ */ #include "includes.h" -#include "lib/samba3/policy.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "lib/cmdline/popt_common.h" static const char *libdir = "/var/lib/samba"; diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index ccd53c0398..ab19f166ee 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -42,6 +42,7 @@ #include "tdb.h" #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" +#include "lib/tdb/include/tdbutil.h" /* structure for storing machine account password (ie. when samba server is member of a domain */ @@ -57,6 +58,78 @@ struct afs_key { char key[8]; }; +/* + * storage structure for trusted domain + */ +typedef struct trusted_dom_pass { + size_t uni_name_len; + const char *uni_name[32]; /* unicode domain name */ + size_t pass_len; + const char *pass; /* trust relationship's password */ + time_t mod_time; + struct dom_sid domain_sid; /* remote domain's sid */ +} TRUSTED_DOM_PASS; + +/** + * Unpack SID into a pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param sid pointer to sid structure to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid) +{ + int idx, len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb", + &sid->sid_rev_num, &sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); + } + + for (idx = 0; idx < 15; idx++) { + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); + } + + return len; +} + +/** + * Unpack TRUSTED_DOM_PASS passed by pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param pass pointer to trusted domain password to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) +{ + int idx, len = 0; + + if (!pack_buf || !pass) return -1; + + /* unpack unicode domain name and plaintext password */ + len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len); + + for (idx = 0; idx < 32; idx++) + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]); + + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass, + &pass->mod_time); + + /* unpack domain sid */ + len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid); + + return len; +} + + static TDB_CONTEXT *secrets_open(const char *fname) { TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600); @@ -69,31 +142,18 @@ static TDB_CONTEXT *secrets_open(const char *fname) return tdb; } -/* read a entry from the secrets database - the caller must free the result - if size is non-null then the size of the entry is put in there - */ -static void *secrets_fetch(TDB_CONTEXT *tdb, const char *key, size_t *size) -{ - TDB_DATA kbuf, dbuf; - - kbuf.dptr = strdup(key); - kbuf.dsize = strlen(key); - dbuf = tdb_fetch(tdb, kbuf); - if (size) - *size = dbuf.dsize; - free(kbuf.dptr); - return dbuf.dptr; -} - static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid) { struct dom_sid *dyn_sid; + TDB_DATA val; char *key; size_t size; asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain); strupper_m(key); - dyn_sid = (struct dom_sid *)secrets_fetch(tdb, key, &size); + + val = tdb_fetch_bystring(tdb, key); + /* FIXME: Convert val to dyn_sid */ SAFE_FREE(key); if (dyn_sid == NULL) @@ -114,17 +174,20 @@ static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, stru { struct GUID *dyn_guid; char *key; + TDB_DATA val; size_t size; asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); - dyn_guid = (struct GUID *)secrets_fetch(tdb, key, &size); + val = tdb_fetch_bystring(tdb, key); + + dyn_guid = (struct GUID *)val.dptr; if (!dyn_guid) { return False; } - if (size != sizeof(struct GUID)) + if (val.dsize != sizeof(struct GUID)) { DEBUG(1,("GUID size %d is wrong!\n", (int)size)); SAFE_FREE(dyn_guid); @@ -183,7 +246,7 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, { struct machine_acct_pass *pass; char *plaintext; - size_t size; + TDB_DATA val; plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, channel); @@ -193,23 +256,22 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, SAFE_FREE(plaintext); return True; } - - if (!(pass = secrets_fetch(tdb, trust_keystr(domain), &size))) { - DEBUG(5, ("secrets_fetch failed!\n")); + + val = tdb_fetch_bystring(tdb, trust_keystr(domain)); + if (!val.dptr) { + DEBUG(5, ("tdb_fetch_bystring failed!\n")); return False; } - if (size != sizeof(*pass)) { + if (val.dsize != sizeof(*pass)) { DEBUG(0, ("secrets were of incorrect size!\n")); return False; } + pass = (struct machine_acct_pass *)val.dptr; + if (pass_last_set_time) *pass_last_set_time = pass->mod_time; memcpy(ret_pwd, pass->hash, 16); - SAFE_FREE(pass); - - if (channel) - *channel = get_default_sec_channel(); return True; } @@ -221,25 +283,24 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time) { struct trusted_dom_pass pass; - size_t size; /* unpacking structures */ - char* pass_buf; int pass_len = 0; + TDB_DATA val; ZERO_STRUCT(pass); /* fetching trusted domain password structure */ - if (!(pass_buf = secrets_fetch(tdb, trustdom_keystr(domain), &size))) { + val = tdb_fetch_bystring(tdb, trustdom_keystr(domain)); + if (!val.dptr) { DEBUG(5, ("secrets_fetch failed!\n")); return False; } /* unpack trusted domain password */ - pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass); - SAFE_FREE(pass_buf); + pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass); - if (pass_len != size) { + if (pass_len != val.dsize) { DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n")); return False; } @@ -272,38 +333,23 @@ static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain { char *key = NULL; char *ret; + TDB_DATA val; asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); strupper_m(key); - ret = (char *)secrets_fetch(tdb, key, NULL); + val = tdb_fetch_bystring(tdb, key); SAFE_FREE(key); if (pass_last_set_time) { - size_t size; - uint32_t *last_set_time; asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); strupper_m(key); - last_set_time = secrets_fetch(tdb, key, &size); - if (last_set_time) { - *pass_last_set_time = IVAL(last_set_time,0); - SAFE_FREE(last_set_time); - } else { - *pass_last_set_time = 0; - } + tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time); SAFE_FREE(key); } if (channel) { - size_t size; - uint32_t *channel_type; asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); strupper_m(key); - channel_type = secrets_fetch(tdb, key, &size); - if (channel_type) { - *channel = IVAL(channel_type,0); - SAFE_FREE(channel_type); - } else { - *channel = get_default_sec_channel(); - } + tdb_fetch_uint32(tdb, key, channel); SAFE_FREE(key); } @@ -317,12 +363,14 @@ static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw) { char *key = NULL; size_t size; + TDB_DATA val; if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) { DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); } - *pw=secrets_fetch(tdb, key, &size); + val = tdb_fetch_bystring(tdb, key); + *pw = val.dptr; SAFE_FREE(key); if (!size) { @@ -363,8 +411,6 @@ static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, i struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass); NTSTATUS status; - if (!secrets_init()) return NT_STATUS_ACCESS_DENIED; - if (!pass) { DEBUG(0, ("talloc_zero failed!\n")); return NT_STATUS_NO_MEMORY; @@ -540,3 +586,5 @@ static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char * *password = smb_xstrdup(""); } } + + diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index a16c07d2d1..aba01d0db6 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -28,7 +28,7 @@ #include "system/iconv.h" #include "system/filesys.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" diff --git a/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c new file mode 100644 index 0000000000..7c3253e101 --- /dev/null +++ b/source4/lib/samba3/winsdb.c @@ -0,0 +1,179 @@ +/* + Unix SMB/CIFS implementation. + Wins Database + + Copyright (C) Jeremy Allison 1994-2003 + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "pstring.h" +#include "lib/samba3/samba3.h" + +#define WINS_VERSION 1 + +NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_winsdb_entry **entries, uint32_t *count ) +{ + XFILE *fp; + char *line; + + if((fp = x_fopen(fn,O_RDONLY,0)) == NULL) { + DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", + fn, strerror(errno) )); + return NT_STATUS_UNSUCCESSFUL; + } + + *count = 0; + *entries = NULL; + + while (!x_feof(fp)) { + struct samba3_winsdb_entry entry; + pstring name_str, ip_str, ttl_str, nb_flags_str; + const char *ptr; + char *p; + BOOL got_token; + BOOL was_ip; + int i; + unsigned int hash; + int version; + + /* Read a line from the wins.dat file. Strips whitespace + from the beginning and end of the line. */ + line = fgets_slash(NULL,-1,fp); + if (!line) + return NT_STATUS_UNSUCCESSFUL; + + if (*line == '#') { + SAFE_FREE(line); + continue; + } + + if (strncmp(line,"VERSION ", 8) == 0) { + if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || + version != WINS_VERSION) { + DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); + SAFE_FREE(line); + x_fclose(fp); + return NT_STATUS_UNSUCCESSFUL; + } + SAFE_FREE(line); + + continue; + } + + ptr = line; + + /* + * Now we handle multiple IP addresses per name we need + * to iterate over the line twice. The first time to + * determine how many IP addresses there are, the second + * time to actually parse them into the ip_list array. + */ + + if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { + DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { + DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + /* + * Determine the number of IP addresses per line. + */ + entry.ip_count = 0; + do { + got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); + was_ip = False; + + if(got_token && strchr(ip_str, '.')) { + entry.ip_count++; + was_ip = True; + } + } while( got_token && was_ip); + + if(entry.ip_count == 0) { + DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + if(!got_token) { + DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + /* Allocate the space for the ip_list. */ + if((entry.ips = talloc_array ( ctx, struct ipv4_addr, entry.ip_count)) == NULL) { + DEBUG(0,("initialise_wins: Malloc fail !\n")); + SAFE_FREE(line); + return NT_STATUS_NO_MEMORY; + } + + /* Reset and re-parse the line. */ + ptr = line; + next_token(&ptr,name_str,NULL,sizeof(name_str)); + next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); + for(i = 0; i < entry.ip_count; i++) { + next_token(&ptr, ip_str, NULL, sizeof(ip_str)); + entry.ips[i] = interpret_addr2(ip_str); + } + next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); + + /* + * Deal with SELF or REGISTER name encoding. Default is REGISTER + * for compatibility with old nmbds. + */ + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { + DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); + talloc_free(entry.ips); + SAFE_FREE(line); + continue; + } + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') + nb_flags_str[strlen(nb_flags_str)-1] = '\0'; + + /* Netbios name. # divides the name from the type (hex): netbios#xx */ + entry.name = talloc_strdup(ctx, name_str); + + if((p = strchr(entry.name,'#')) != NULL) { + *p = 0; + sscanf(p+1,"%x",&entry.type); + } + + /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ + sscanf(nb_flags_str,"%x",&entry.nb_flags); + entry.ttl = atol(ttl_str); + + *entries = talloc_realloc(ctx, *entries, struct samba3_winsdb_entry, (*count)+1); + *entries[*count] = entry; + + (*count)++; + } + + x_fclose(fp); + return NT_STATUS_OK; +} -- cgit From 479ef0a3874098bdc90021908b329f6d74aa1b4b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 01:52:17 +0000 Subject: r9557: Some more updates. Use combined function for parsing a set of samba3 databases (This used to be commit b91a695bd854c6d37ec536edb2db7b6f97fe69dc) --- source4/lib/samba3/config.mk | 4 +- source4/lib/samba3/group.c | 448 +++++----------------------------------- source4/lib/samba3/idmap.c | 2 +- source4/lib/samba3/policy.c | 12 +- source4/lib/samba3/samba3.c | 51 +++++ source4/lib/samba3/samba3.h | 29 ++- source4/lib/samba3/samba3dump.c | 47 +---- source4/lib/samba3/tdbsam.c | 2 +- 8 files changed, 150 insertions(+), 445 deletions(-) create mode 100644 source4/lib/samba3/samba3.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 15802d3b8e..5d96e233b4 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -6,7 +6,9 @@ INIT_OBJ_FILES = \ lib/samba3/tdbsam.o \ lib/samba3/policy.o \ lib/samba3/idmap.o \ - lib/samba3/winsdb.o + lib/samba3/winsdb.o \ + lib/samba3/samba3.o \ + lib/samba3/group.o # lib/samba3/secrets.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index d7097f596a..fc8f8c40b8 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -24,6 +24,7 @@ #include "lib/samba3/samba3.h" #include "lib/tdb/include/tdbutil.h" #include "system/filesys.h" +#include "pstring.h" #define DATABASE_VERSION_V1 1 /* native byte format. */ #define DATABASE_VERSION_V2 2 /* le format. */ @@ -37,47 +38,19 @@ */ #define MEMBEROF_PREFIX "MEMBEROF/" -#define ENUM_ONLY_MAPPED True -#define ENUM_ALL_MAPPED False - - -/**************************************************************************** -dump the mapping group mapping to a text file -****************************************************************************/ -static const char *decode_sid_name_use(enum SID_NAME_USE name_use) -{ - switch(name_use) { - case SID_NAME_USER: - return "User"; - case SID_NAME_DOM_GRP: - return "Domain group"; - case SID_NAME_DOMAIN: - return "Domain"; - case SID_NAME_ALIAS: - return "Local group"; - case SID_NAME_WKN_GRP: - return "Builtin group"; - case SID_NAME_DELETED: - return "Deleted"; - case SID_NAME_INVALID: - return "Invalid"; - case SID_NAME_UNKNOWN: - default: - return "Unknown type"; - } -} - /**************************************************************************** Open the group mapping tdb. ****************************************************************************/ -static TDB_CONTEXT *tdbgroup_open(const char *file) +NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_groupdb *db) { int32_t vers_id; + TDB_DATA kbuf, dbuf, newkey; + int ret; TDB_CONTEXT *tdb = tdb_open(file, 0, TDB_DEFAULT, O_RDONLY, 0600); if (!tdb) { DEBUG(0,("Failed to open group mapping database\n")); - return NULL; + return NT_STATUS_UNSUCCESSFUL; } /* Cope with byte-reversed older versions of the db. */ @@ -88,396 +61,77 @@ static TDB_CONTEXT *tdbgroup_open(const char *file) } if (vers_id != DATABASE_VERSION_V2) { - return NULL; - } - - return tdb; -} - -/**************************************************************************** - Return the sid and the type of the unix group. -****************************************************************************/ - -static BOOL get_group_map_from_sid(TDB_CONTEXT *tdb, struct dom_sid sid, struct samba3_groupmapping *map) -{ - TDB_DATA kbuf, dbuf; - const char *key; - int ret = 0; - - /* the key is the SID, retrieving is direct */ - - kbuf.dptr = talloc_asprintf(tdb, "%s%s", GROUP_PREFIX, dom_sid_string(tdb, &sid)); - kbuf.dsize = strlen(key)+1; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - return False; - - ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); - - SAFE_FREE(dbuf.dptr); - - if ( ret == -1 ) { - DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n")); - return False; + return NT_STATUS_UNSUCCESSFUL; } - map->sid = dom_sid_dup(tdb, &sid); - - return True; -} - -/**************************************************************************** - Return the sid and the type of the unix group. -****************************************************************************/ - -static BOOL get_group_map_from_gid(TDB_CONTEXT *tdb, gid_t gid, struct samba3_groupmapping *map) -{ - TDB_DATA kbuf, dbuf, newkey; - int ret; - - /* we need to enumerate the TDB to find the GID */ + db->groupmappings = NULL; + db->groupmap_count = 0; + db->aliases = NULL; + db->alias_count = 0; for (kbuf = tdb_firstkey(tdb); kbuf.dptr; newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + struct samba3_groupmapping map; - if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; + if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) == 0) + { + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + continue; + map.sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); - map->sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); - - ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", + &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); - SAFE_FREE(dbuf.dptr); + SAFE_FREE(dbuf.dptr); - if ( ret == -1 ) { - DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n")); - return False; - } - - if (gid==map->gid) { - SAFE_FREE(kbuf.dptr); - return True; - } - } + if ( ret == -1 ) { + DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); + continue; + } - return False; -} + db->groupmappings = talloc_realloc(tdb, db->groupmappings, struct samba3_groupmapping, db->groupmap_count+1); -/**************************************************************************** - Return the sid and the type of the unix group. -****************************************************************************/ + if (!db->groupmappings) + return NT_STATUS_NO_MEMORY; -static BOOL get_group_map_from_ntname(TDB_CONTEXT *tdb, const char *name, struct samba3_groupmapping *map) -{ - TDB_DATA kbuf, dbuf, newkey; - int ret; - - /* we need to enumerate the TDB to find the name */ + db->groupmappings[db->groupmap_count] = map; - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + db->groupmap_count++; + } - if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; + if (strncmp(kbuf.dptr, MEMBEROF_PREFIX, strlen(MEMBEROF_PREFIX)) == 0) + { + struct samba3_alias alias; + pstring alias_string; + const char *p; - map->sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); - - ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + continue; - SAFE_FREE(dbuf.dptr); - - if ( ret == -1 ) { - DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n")); - return False; - } + alias.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(MEMBEROF_PREFIX)); + alias.member_count = 0; + alias.members = NULL; - if (StrCaseCmp(name, map->nt_name)==0) { - SAFE_FREE(kbuf.dptr); - return True; - } - } + p = dbuf.dptr; + while (next_token(&p, alias_string, " ", sizeof(alias_string))) { - return False; -} + alias.members = talloc_realloc(ctx, alias.members, struct dom_sid *, alias.member_count+1); + alias.members[alias.member_count] = dom_sid_parse_talloc(ctx, alias_string); + alias.member_count++; -/**************************************************************************** - Enumerate the group mapping. -****************************************************************************/ + } -static BOOL enum_group_mapping(TDB_CONTEXT *tdb, enum SID_NAME_USE sid_name_use, struct samba3_groupmapping **rmap, - int *num_entries, BOOL unix_only) -{ - TDB_DATA kbuf, dbuf, newkey; - struct samba3_groupmapping map; - struct samba3_groupmapping *mapt; - int ret; - int entries=0; - - *num_entries=0; - *rmap=NULL; - - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - - if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) - continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; - - map.sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); - - ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", - &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); - - SAFE_FREE(dbuf.dptr); - - if ( ret == -1 ) { - DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); - continue; - } - - /* list only the type or everything if UNKNOWN */ - if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) { - DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); - continue; + db->aliases = talloc_realloc(ctx, db->aliases, struct samba3_alias, db->alias_count+1); + db->aliases[db->alias_count] = alias; + db->alias_count++; } - - if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) { - DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name)); - continue; - } - - DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,decode_sid_name_use(map.sid_name_use))); - - mapt = talloc_realloc(tdb, *rmap, struct samba3_groupmapping, entries+1); - if (!mapt) { - DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n")); - SAFE_FREE(*rmap); - return False; - } - else - (*rmap) = mapt; - - mapt[entries].gid = map.gid; - mapt[entries].sid = dom_sid_dup(tdb, map.sid); - mapt[entries].sid_name_use = map.sid_name_use; - mapt[entries].nt_name = map.nt_name; - mapt[entries].comment = map.comment; - - entries++; - - } - - *num_entries=entries; - - return True; -} - -/* This operation happens on session setup, so it should better be fast. We - * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */ - -static NTSTATUS one_alias_membership(TDB_CONTEXT *tdb, - const struct dom_sid *member, struct dom_sid **sids, int *num) -{ - TDB_DATA kbuf, dbuf; - const char *p; - - char * key = talloc_asprintf(tdb, "%s%s", MEMBEROF_PREFIX, dom_sid_string(tdb, member)); - - kbuf.dsize = strlen(key)+1; - kbuf.dptr = key; - - dbuf = tdb_fetch(tdb, kbuf); - - if (dbuf.dptr == NULL) { - return NT_STATUS_OK; - } - - p = dbuf.dptr; - - while (next_token(&p, string_sid, " ", sizeof(string_sid))) { - - struct dom_sid alias; - - if (!string_to_sid(&alias, string_sid)) - continue; - - add_sid_to_array_unique(NULL, &alias, sids, num); - - if (sids == NULL) - return NT_STATUS_NO_MEMORY; - } - - SAFE_FREE(dbuf.dptr); - return NT_STATUS_OK; -} - -static NTSTATUS alias_memberships(TDB_CONTEXT *tdb, const struct dom_sid *members, int num_members, - struct dom_sid **sids, int *num) -{ - int i; - - *num = 0; - *sids = NULL; - - for (i=0; ialias, &alias) != 0) - continue; - - /* Ok, we found the alias we're looking for in the membership - * list currently scanned. The key represents the alias - * member. Add that. */ - - member_string = strchr(key.dptr, '/'); - - /* Above we tested for MEMBEROF_PREFIX which includes the - * slash. */ - - SMB_ASSERT(member_string != NULL); - member_string += 1; - - if (!string_to_sid(&member, member_string)) - continue; - - add_sid_to_array(NULL, &member, closure->sids, closure->num); } - return 0; -} - -static NTSTATUS enum_aliasmem(TDB_CONTEXT *tdb, const struct dom_sid *alias, struct dom_sid **sids, int *num) -{ - struct samba3_groupmapping map; - struct aliasmem_closure closure; - - if (!get_group_map_from_sid(*alias, &map)) - return NT_STATUS_NO_SUCH_ALIAS; - - if ( (map.sid_name_use != SID_NAME_ALIAS) && - (map.sid_name_use != SID_NAME_WKN_GRP) ) - return NT_STATUS_NO_SUCH_ALIAS; - - *sids = NULL; - *num = 0; + tdb_close(tdb); - closure.alias = alias; - closure.sids = sids; - closure.num = num; - - tdb_traverse(tdb, collect_aliasmem, &closure); return NT_STATUS_OK; } - -/* - * - * High level functions - * better to use them than the lower ones. - * - * we are checking if the group is in the mapping file - * and if the group is an existing unix group - * - */ - -/* get a domain group from it's SID */ - -/* get a local (alias) group from it's SID */ - -static BOOL get_local_group_from_sid(TDB_CONTEXT *tdb, struct dom_sid *sid, struct samba3_groupmapping *map) -{ - BOOL ret; - - /* The group is in the mapping table */ - ret = pdb_getgrsid(map, *sid); - - if ( !ret ) - return False; - - if ( ( (map->sid_name_use != SID_NAME_ALIAS) && - (map->sid_name_use != SID_NAME_WKN_GRP) ) - || (map->gid == -1) - || (getgrgid(map->gid) == NULL) ) - { - return False; - } - -#if 1 /* JERRY */ - /* local groups only exist in the group mapping DB so this - is not necessary */ - - else { - /* the group isn't in the mapping table. - * make one based on the unix information */ - uint32_t alias_rid; - struct group *grp; - - sid_peek_rid(sid, &alias_rid); - map->gid=pdb_group_rid_to_gid(alias_rid); - - grp = getgrgid(map->gid); - if ( !grp ) { - DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid)); - return False; - } - - map->sid_name_use=SID_NAME_ALIAS; - - fstrcpy(map->nt_name, grp->gr_name); - fstrcpy(map->comment, "Local Unix Group"); - - sid_copy(&map->sid, sid); - } -#endif - - return True; -} diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index 64d6387ed4..1583ad4476 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -39,7 +39,7 @@ Initialise idmap database. *****************************************************************************/ -NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmap *idmap ) +NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmapdb *idmap ) { int32_t version; TDB_CONTEXT *tdb; diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c index bfb3ac373e..bec3eb7d93 100644 --- a/source4/lib/samba3/policy.c +++ b/source4/lib/samba3/policy.c @@ -30,16 +30,15 @@ Open the account policy tdb. ****************************************************************************/ -struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn) +NTSTATUS samba3_read_account_policy(const char *fn, TALLOC_CTX *ctx, struct samba3_policy *ret) { - struct samba3_policy *ret; const char *vstring = "INFO/version"; uint32_t version; TDB_CONTEXT *tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600); if (!tdb) { DEBUG(0,("Failed to open account policy database\n")); - return NULL; + return NT_STATUS_UNSUCCESSFUL; } /* handle a Samba upgrade */ @@ -60,10 +59,9 @@ struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn tdb_fetch_uint32(tdb, "disconnect time", &ret->disconnect_time); tdb_fetch_uint32(tdb, "refuse machine password change", &ret->refuse_machine_password_change); + /* FIXME: Read privileges as well */ + tdb_close(tdb); - return ret; + return NT_STATUS_OK; } - - -/* FIXME: Read privileges as well */ diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c new file mode 100644 index 0000000000..37576a8642 --- /dev/null +++ b/source4/lib/samba3/samba3.c @@ -0,0 +1,51 @@ +/* + * Unix SMB/CIFS implementation. + * Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "lib/samba3/samba3.h" + +struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) +{ + struct samba3 *ret; + char *dbfile; + + ret = talloc(ctx, struct samba3); + + asprintf(&dbfile, "%s/winsdb.dat", libdir); + samba3_read_winsdb(dbfile, ret, &ret->winsdb_entries, &ret->winsdb_count); + SAFE_FREE(dbfile); + + asprintf(&dbfile, "%s/passdb.tdb", libdir); + samba3_read_tdbsam(dbfile, ctx, &ret->samaccounts, &ret->samaccount_count); + SAFE_FREE(dbfile); + + asprintf(&dbfile, "%s/groupdb.tdb", libdir); + samba3_read_grouptdb(dbfile, ctx, &ret->group); + SAFE_FREE(dbfile); + + asprintf(&dbfile, "%s/idmap.tdb", libdir); + samba3_read_idmap(dbfile, ctx, &ret->idmap); + SAFE_FREE(dbfile); + + asprintf(&dbfile, "%s/account_policy.tdb", libdir); + samba3_read_account_policy(dbfile, ctx, &ret->policy); + SAFE_FREE(dbfile); + + return ret; +} diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index d3e03cf923..adb7b8973a 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -75,6 +75,20 @@ struct samba3_groupmapping { const char *comment; }; +struct samba3_alias { + struct dom_sid *sid; + uint32_t member_count; + struct dom_sid **members; +}; + +struct samba3_groupdb { + uint32_t groupmap_count; + struct samba3_groupmapping *groupmappings; + + uint32_t alias_count; + struct samba3_alias *aliases; +}; + struct samba3_idmap_mapping { enum { IDMAP_GROUP, IDMAP_USER } type; @@ -82,7 +96,7 @@ struct samba3_idmap_mapping struct dom_sid *sid; }; -struct samba3_idmap +struct samba3_idmapdb { /* High water marks */ uint32_t user_hwm; @@ -116,4 +130,17 @@ struct samba3_policy uint32_t refuse_machine_password_change; }; +struct samba3 +{ + uint32_t winsdb_count; + struct samba3_winsdb_entry *winsdb_entries; + + uint32_t samaccount_count; + struct samba3_samaccount *samaccounts; + + struct samba3_groupdb group; + struct samba3_idmapdb idmap; + struct samba3_policy policy; +}; + #endif /* _SAMBA3_H */ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index 6bcfce96fa..88d5cf9369 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -23,49 +23,18 @@ #include "lib/samba3/samba3.h" #include "lib/cmdline/popt_common.h" -static const char *libdir = "/var/lib/samba"; - -static NTSTATUS print_policy(void) +static NTSTATUS print_policy(struct samba3_policy *ret) { - struct samba3_policy *ret; - char *policy_file; - TALLOC_CTX *mem_ctx = talloc_init(NULL); - - policy_file = talloc_asprintf(mem_ctx, "%s/account_policy.tdb", libdir); - - printf("Opening policy file %s\n", policy_file); - - ret = samba3_read_account_policy(mem_ctx, policy_file); - - if (ret == NULL) - return NT_STATUS_UNSUCCESSFUL; - printf("Min password length: %d\n", ret->min_password_length); - talloc_free(mem_ctx); - return NT_STATUS_OK; } -static NTSTATUS print_sam(void) +static NTSTATUS print_sam(struct samba3 *samba3) { - struct samba3_samaccount *accounts; - uint32_t count, i; - char *tdbsam_file; - NTSTATUS status; + struct samba3_samaccount *accounts = samba3->samaccounts; + uint32_t count = samba3->samaccount_count, i; - asprintf(&tdbsam_file, "%s/passdb.tdb", libdir); - - printf("Opening TDB sam %s\n", tdbsam_file); - - status = samba3_read_tdbsam(NULL, tdbsam_file, &accounts, &count); - if (NT_STATUS_IS_ERR(status)) { - fprintf(stderr, "Error reading tdbsam database %s\n", tdbsam_file); - SAFE_FREE(tdbsam_file); - return status; - } - SAFE_FREE(tdbsam_file); - for (i = 0; i < count; i++) { printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); } @@ -76,6 +45,8 @@ static NTSTATUS print_sam(void) int main(int argc, char **argv) { int opt; + const char *libdir = "/var/lib/samba"; + struct samba3 *samba3; poptContext pc; struct poptOption long_options[] = { POPT_AUTOHELP @@ -91,8 +62,10 @@ int main(int argc, char **argv) while((opt = poptGetNextOpt(pc)) != -1) { } - print_sam(); - print_policy(); + samba3 = samba3_read(libdir, NULL); + + print_sam(samba3); + print_policy(&samba3->policy); poptFreeContext(pc); diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index aba01d0db6..577b663381 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -266,7 +266,7 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * return True; } -NTSTATUS samba3_read_tdbsam(TALLOC_CTX *ctx, const char *filename, struct samba3_samaccount **accounts, uint32_t *count) +NTSTATUS samba3_read_tdbsam(const char *filename, TALLOC_CTX *ctx, struct samba3_samaccount **accounts, uint32_t *count) { int32_t version; TDB_CONTEXT *tdb = tdbsam_open(filename, &version); -- cgit From 00e79ceb49d2e21acd90ffa21b931205ff012ef1 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 24 Aug 2005 03:39:25 +0000 Subject: r9563: I think this INIT_OBJ_FILES should be ADD_OBJ_FILES so that the lib/samba3 source files are included in make proto. Fixes the build with ./configure.developer. (This used to be commit 691d6a04d76d55bfd61d581759b9be6a72880019) --- source4/lib/samba3/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 5d96e233b4..64a2293614 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -1,7 +1,7 @@ ################################################ # Start SUBSYSTEM LIBSAMBA3 [SUBSYSTEM::LIBSAMBA3] -INIT_OBJ_FILES = \ +ADD_OBJ_FILES = \ lib/samba3/smbpasswd.o \ lib/samba3/tdbsam.o \ lib/samba3/policy.o \ -- cgit From 649882d8d59f35cf51166bedd73c2eab4cea7e50 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 Aug 2005 08:31:39 +0000 Subject: r9567: fixed the winreg IDL for CreateKey, including a security descriptor. To keep it simple I just use normal IDL buffers for now, avoiding the complex methods metze used in spoolss. We might change that later Also added decoding of the security_descriptor in winreg_GetKeySecurity() in smbtorture (This used to be commit 439f34a9621e2e96329c30cfed8d78b8fdfbd8a2) --- source4/lib/registry/reg_backend_rpc.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 5734b96770..44de3bcd77 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -29,14 +29,7 @@ static struct hive_operations reg_backend_rpc; static void init_winreg_String(struct winreg_String *name, const char *s) { - name->name = s; - if (s) { - name->name_len = 2 * (strlen_m(s) + 1); - name->name_size = name->name_len; - } else { - name->name_len = 0; - name->name_size = 0; - } + name->name = s; } @@ -255,14 +248,14 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, cons NTSTATUS status; struct winreg_CreateKey r; - init_winreg_String(&r.in.key, name); + init_winreg_String(&r.in.name, name); init_winreg_String(&r.in.class, NULL); r.in.handle = parent->backend_data; - r.out.handle = talloc(mem_ctx, struct policy_handle); + r.out.new_handle = talloc(mem_ctx, struct policy_handle); r.in.options = 0; - r.in.access_mask = access_mask; - r.in.sec_desc = NULL; + r.in.access_required = access_mask; + r.in.secdesc = NULL; status = dcerpc_winreg_CreateKey((struct dcerpc_pipe *)(parent->hive->backend_data), mem_ctx, &r); @@ -274,7 +267,7 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, cons if (W_ERROR_IS_OK(r.out.result)) { *key = talloc(mem_ctx, struct registry_key); (*key)->name = talloc_strdup(*key, name); - (*key)->backend_data = r.out.handle; + (*key)->backend_data = r.out.new_handle; } return r.out.result; -- cgit From ca71549d5af608a280645f69016749ae9da89747 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 12:21:19 +0000 Subject: r9581: Registry db (This used to be commit b264e9f56a434400277bb73898484aff93522fe8) --- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/registry.c | 182 ++++++++++++++++++------------------------ source4/lib/samba3/samba3.c | 4 + source4/lib/samba3/samba3.h | 40 ++++++---- 4 files changed, 107 insertions(+), 122 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 64a2293614..23f07106f0 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -8,7 +8,8 @@ ADD_OBJ_FILES = \ lib/samba3/idmap.o \ lib/samba3/winsdb.o \ lib/samba3/samba3.o \ - lib/samba3/group.o + lib/samba3/group.o \ + lib/samba3/registry.o # lib/samba3/secrets.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/registry.c b/source4/lib/samba3/registry.c index 22fa2b2636..82a08c9088 100644 --- a/source4/lib/samba3/registry.c +++ b/source4/lib/samba3/registry.c @@ -22,151 +22,123 @@ /* Implementation of internal registry database functions. */ #include "includes.h" +#include "lib/samba3/samba3.h" +#include "librpc/gen_ndr/winreg.h" +#include "lib/tdb/include/tdbutil.h" +#include "system/filesys.h" +#include "pstring.h" #define VALUE_PREFIX "SAMBA_REGVAL" #define REGVER_V1 1 /* first db version with write support */ - -/*********************************************************************** - Open the registry database - ***********************************************************************/ - -static TDB_CONTEXT *samba3_open_registry ( const char *fn ) -{ - uint32_t vers_id; - - /* placeholder tdb; reinit upon startup */ - - if ( !(tdb = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0600)) ) - { - return NULL; - } - - vers_id = tdb_fetch_int32(tdb, "INFO/version"); - - if (vers_id > REGVER_V1) - return NULL; - - return True; -} - -/*********************************************************************** - Retrieve an array of strings containing subkeys. Memory should be - released by the caller. - ***********************************************************************/ - -int regdb_fetch_keys( TDB_CONTEXT *tdb, const char* key, REGSUBKEY_CTR *ctr ) -{ - char *path; - uint32_t num_items; - TDB_DATA dbuf; - char *buf; - uint32_t buflen, len; - int i; - fstring subkeyname; - - DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); - - path = talloc_strdup(key); - - /* convert to key format */ - for ( i = 0; path[i]; i++) { - if ( path[i] == '\\' ) - path[i] = '/'; - } - strupper_m( path ); - - dbuf = tdb_fetch_bystring( tdb, path ); - - buf = dbuf.dptr; - buflen = dbuf.dsize; - - if ( !buf ) { - DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key)); - return -1; - } - - len = tdb_unpack( buf, buflen, "d", &num_items); - - for (i=0; ivalues = talloc_realloc(ctx, key->values, struct samba3_regval, key->value_count+1); + key->values[key->value_count] = val; + key->value_count++; } return len; } + + /*********************************************************************** - Retrieve an array of strings containing subkeys. Memory should be - released by the caller. + Open the registry database ***********************************************************************/ - -int regdb_fetch_values( TDB_CONTEXT *tdb, const char* key, REGVAL_CTR *values ) + +NTSTATUS samba3_read_regdb ( const char *fn, TALLOC_CTX *ctx, struct samba3_regdb *db ) { - TDB_DATA data; - pstring keystr; + uint32_t vers_id; + TDB_CONTEXT *tdb; + TDB_DATA kbuf, vbuf; - DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key)); - - pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key ); - normalize_reg_path( keystr ); - - data = tdb_fetch_bystring( tdb, keystr ); + /* placeholder tdb; reinit upon startup */ - if ( !data.dptr ) { - /* all keys have zero values by default */ - return 0; + if ( !(tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600)) ) + { + return NT_STATUS_UNSUCCESSFUL; } + + vers_id = tdb_fetch_int32(tdb, "INFO/version"); + + db->key_count = 0; + db->keys = NULL; + + if (vers_id > REGVER_V1) + return NT_STATUS_UNSUCCESSFUL; + + for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf)) + { + uint32_t len; + int i; + struct samba3_regkey key; + char *skey; + + if (strncmp(kbuf.dptr, VALUE_PREFIX, strlen(VALUE_PREFIX))) + continue; + + vbuf = tdb_fetch(tdb, kbuf); + + key.name = talloc_strdup(ctx, kbuf.dptr); + + len = tdb_unpack(tdb, vbuf.dptr, vbuf.dsize, "d", &key.subkey_count); + + key.value_count = 0; + key.values = NULL; + key.subkeys = talloc_array(ctx, char *, key.subkey_count); - regdb_unpack_values( values, data.dptr, data.dsize ); + for (i = 0; i < key.subkey_count; i++) { + fstring tmp; + len += tdb_unpack( tdb, vbuf.dptr+len, vbuf.dsize-len, "f", tmp ); + key.subkeys[i] = talloc_strdup(ctx, tmp); + } + + skey = talloc_asprintf(ctx, "%s/%s", VALUE_PREFIX, kbuf.dptr ); - SAFE_FREE( data.dptr ); + vbuf = tdb_fetch_bystring( tdb, skey ); - return regval_ctr_numvals(values); + if ( vbuf.dptr ) { + regdb_unpack_values( tdb, ctx, &key, vbuf ); + } + + db->keys = talloc_realloc(ctx, db->keys, struct samba3_regkey, db->key_count+1); + db->keys[i] = key; + db->key_count++; + } + + tdb_close(tdb); + + return NT_STATUS_OK; } diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 37576a8642..c74b1b5279 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -47,5 +47,9 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) samba3_read_account_policy(dbfile, ctx, &ret->policy); SAFE_FREE(dbfile); + asprintf(&dbfile, "%s/registry.tdb", libdir); + samba3_read_regdb(dbfile, ctx, &ret->registry); + SAFE_FREE(dbfile); + return ret; } diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index adb7b8973a..bebd120704 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -51,26 +51,11 @@ struct samba3_samaccount { uint8_t *hours; }; -/* SID Types */ -enum SID_NAME_USE -{ - SID_NAME_USE_NONE = 0, - SID_NAME_USER = 1, /* user */ - SID_NAME_DOM_GRP, /* domain group */ - SID_NAME_DOMAIN, /* domain sid */ - SID_NAME_ALIAS, /* local group */ - SID_NAME_WKN_GRP, /* well-known group */ - SID_NAME_DELETED, /* deleted account: needed for c2 rating */ - SID_NAME_INVALID, /* invalid account */ - SID_NAME_UNKNOWN, /* unknown sid type */ - SID_NAME_COMPUTER /* sid for a computer */ -}; - struct samba3_groupmapping { struct pdb_methods *methods; gid_t gid; struct dom_sid *sid; - enum SID_NAME_USE sid_name_use; + int sid_name_use; const char *nt_name; const char *comment; }; @@ -130,6 +115,28 @@ struct samba3_policy uint32_t refuse_machine_password_change; }; +struct samba3_regval { + char *name; + uint16_t type; + DATA_BLOB data; +}; + +struct samba3_regkey { + char *name; + + uint32_t value_count; + struct samba3_regval *values; + + uint32_t subkey_count; + char **subkeys; +}; + +struct samba3_regdb +{ + uint32_t key_count; + struct samba3_regkey *keys; +}; + struct samba3 { uint32_t winsdb_count; @@ -141,6 +148,7 @@ struct samba3 struct samba3_groupdb group; struct samba3_idmapdb idmap; struct samba3_policy policy; + struct samba3_regdb registry; }; #endif /* _SAMBA3_H */ -- cgit From cdf218e270bb6e0e3e04419279292c80ed39fb98 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 16:39:28 +0000 Subject: r9589: Support reading secrets tdb (This used to be commit dd15131b5219ecf0d09329c0de37c426b9147f45) --- source4/lib/samba3/config.mk | 4 +- source4/lib/samba3/samba3.c | 4 + source4/lib/samba3/samba3.h | 48 ++++ source4/lib/samba3/secrets.c | 614 ++++++++++--------------------------------- 4 files changed, 194 insertions(+), 476 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 23f07106f0..75073048d0 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -9,8 +9,8 @@ ADD_OBJ_FILES = \ lib/samba3/winsdb.o \ lib/samba3/samba3.o \ lib/samba3/group.o \ - lib/samba3/registry.o -# lib/samba3/secrets.o + lib/samba3/registry.o \ + lib/samba3/secrets.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index c74b1b5279..bfd41d6554 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -51,5 +51,9 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) samba3_read_regdb(dbfile, ctx, &ret->registry); SAFE_FREE(dbfile); + asprintf(&dbfile, "%s/secrets.tdb", libdir); + samba3_read_secrets(dbfile, ctx, &ret->secrets); + SAFE_FREE(dbfile); + return ret; } diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index bebd120704..575ee83825 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -137,6 +137,53 @@ struct samba3_regdb struct samba3_regkey *keys; }; +struct samba3_secrets +{ + struct cli_credentials *ipc_cred; + + uint32_t ldappw_count; + struct samba3_ldappw + { + char *dn; + char *password; + } *ldappws; + + uint32_t domain_count; + struct samba3_domainsecrets + { + char *name; + struct dom_sid sid; + struct GUID guid; + char *plaintext_pw; + time_t last_change_time; + struct { + uint8_t hash[16]; + time_t mod_time; + } hash_pw;; + int sec_channel_type; + } *domains; + + uint32_t trusted_domain_count; + struct samba3_trusted_dom_pass { + uint32_t uni_name_len; + const char *uni_name[32]; /* unicode domain name */ + const char *pass; /* trust relationship's password */ + time_t mod_time; + struct dom_sid domain_sid; /* remote domain's sid */ + } *trusted_domains; + + uint32_t afs_keyfile_count; + + struct samba3_afs_keyfile { + uint32_t nkeys; + struct { + uint32_t kvno; + char key[8]; + } entry[8]; + char *cell; + } *afs_keyfiles; +}; + struct samba3 { uint32_t winsdb_count; @@ -145,6 +192,7 @@ struct samba3 uint32_t samaccount_count; struct samba3_samaccount *samaccounts; + struct samba3_secrets secrets; struct samba3_groupdb group; struct samba3_idmapdb idmap; struct samba3_policy policy; diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index ab19f166ee..4aacffda34 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -24,52 +24,13 @@ /* the Samba secrets database stores any generated, private information such as the local SID and machine trust password */ -#define SECRETS_DOMAIN_SID "SECRETS/SID" -#define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID" -#define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW" -#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC" -#define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC" -#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD" -#define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME" -#define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE" -#define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE" -#define SECRETS_AUTH_USER "SECRETS/AUTH_USER" -#define SECRETS_AUTH_DOMAIN "SECRETS/AUTH_DOMAIN" -#define SECRETS_AUTH_PASSWORD "SECRETS/AUTH_PASSWORD" - - #include "includes.h" #include "tdb.h" +#include "lib/samba3/samba3.h" #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" #include "lib/tdb/include/tdbutil.h" -/* structure for storing machine account password - (ie. when samba server is member of a domain */ -struct machine_acct_pass { - uint8_t hash[16]; - time_t mod_time; -}; - -#define SECRETS_AFS_MAXKEYS 8 - -struct afs_key { - uint32_t kvno; - char key[8]; -}; - -/* - * storage structure for trusted domain - */ -typedef struct trusted_dom_pass { - size_t uni_name_len; - const char *uni_name[32]; /* unicode domain name */ - size_t pass_len; - const char *pass; /* trust relationship's password */ - time_t mod_time; - struct dom_sid domain_sid; /* remote domain's sid */ -} TRUSTED_DOM_PASS; - /** * Unpack SID into a pointer * @@ -99,492 +60,197 @@ static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, stru return len; } -/** - * Unpack TRUSTED_DOM_PASS passed by pointer - * - * @param pack_buf pointer to buffer with packed representation - * @param bufsize size of the buffer - * @param pass pointer to trusted domain password to be filled with unpacked data - * - * @return size of structure unpacked from buffer - **/ -static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) +static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct samba3_secrets *db, const char *key) { - int idx, len = 0; - - if (!pack_buf || !pass) return -1; + int i; - /* unpack unicode domain name and plaintext password */ - len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len); - - for (idx = 0; idx < 32; idx++) - len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]); + for (i = 0; i < db->domain_count; i++) + { + if (!StrCaseCmp(db->domains[i].name, key)) + return &db->domains[i]; + } - len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass, - &pass->mod_time); - - /* unpack domain sid */ - len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid); + db->domains = talloc_realloc(ctx, db->domains, struct samba3_domainsecrets, db->domain_count+1); + ZERO_STRUCT(db->domains[db->domain_count]); + db->domains[db->domain_count].name = talloc_strdup(ctx, key); + + db->domain_count++; - return len; + return &db->domains[db->domain_count-1]; } - -static TDB_CONTEXT *secrets_open(const char *fname) +static NTSTATUS ipc_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600); - - if (!tdb) { - DEBUG(0,("Failed to open %s\n", fname)); - return NULL; - } - - return tdb; + cli_credentials_set_password(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED); + return NT_STATUS_OK; } -static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid) +static NTSTATUS ipc_username (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - struct dom_sid *dyn_sid; - TDB_DATA val; - char *key; - size_t size; - - asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain); - strupper_m(key); + cli_credentials_set_username(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED); + return NT_STATUS_OK; +} - val = tdb_fetch_bystring(tdb, key); - /* FIXME: Convert val to dyn_sid */ - SAFE_FREE(key); - - if (dyn_sid == NULL) - return False; - - if (size != sizeof(struct dom_sid)) - { - SAFE_FREE(dyn_sid); - return False; - } - - *sid = *dyn_sid; - SAFE_FREE(dyn_sid); - return True; +static NTSTATUS ipc_domain (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) +{ + cli_credentials_set_domain(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED); + return NT_STATUS_OK; } -static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, struct GUID *guid) +static NTSTATUS domain_sid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - struct GUID *dyn_guid; - char *key; - TDB_DATA val; - size_t size; - - asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain); - strupper_m(key); - val = tdb_fetch_bystring(tdb, key); - - dyn_guid = (struct GUID *)val.dptr; - - if (!dyn_guid) { - return False; - } - - if (val.dsize != sizeof(struct GUID)) - { - DEBUG(1,("GUID size %d is wrong!\n", (int)size)); - SAFE_FREE(dyn_guid); - return False; - } - - *guid = *dyn_guid; - SAFE_FREE(dyn_guid); - return True; + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); + domainsec->sid.sub_auths = talloc_array(ctx, uint32_t, 15); + tdb_sid_unpack(tdb, vbuf.dptr, vbuf.dsize, &domainsec->sid); + return NT_STATUS_OK; } -/** - * Form a key for fetching the machine trust account password - * - * @param domain domain name - * - * @return stored password's key - **/ -static char *trust_keystr(const char *domain) +static NTSTATUS domain_guid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - char *keystr; - - asprintf(&keystr, "%s/%s", SECRETS_MACHINE_ACCT_PASS, domain); - strupper_m(keystr); - - return keystr; + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); + memcpy(&domainsec->guid, vbuf.dptr, vbuf.dsize); + return NT_STATUS_OK; } -/** - * Form a key for fetching a trusted domain password - * - * @param domain trusted domain name - * - * @return stored password's key - **/ -static char *trustdom_keystr(const char *domain) +static NTSTATUS ldap_bind_pw (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - char *keystr; - - asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); - strupper_m(keystr); - - return keystr; + struct samba3_ldappw pw; + pw.dn = talloc_strdup(ctx, key); + pw.password = talloc_strdup(ctx, vbuf.dptr); + + db->ldappws = talloc_realloc(ctx, db->ldappws, struct samba3_ldappw, db->ldappw_count+1); + db->ldappws[db->ldappw_count] = pw; + db->ldappw_count++; + return NT_STATUS_OK; } -/************************************************************************ - Routine to get the trust account password for a domain. - The user of this function must have locked the trust password file using - the above secrets_lock_trust_account_password(). -************************************************************************/ - -static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, - const char *domain, uint8_t ret_pwd[16], - time_t *pass_last_set_time, - uint32_t *channel) +static NTSTATUS afs_keyfile (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - struct machine_acct_pass *pass; - char *plaintext; - TDB_DATA val; - - plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, - channel); - if (plaintext) { - DEBUG(4,("Using cleartext machine password\n")); - E_md4hash(plaintext, ret_pwd); - SAFE_FREE(plaintext); - return True; - } - - val = tdb_fetch_bystring(tdb, trust_keystr(domain)); - if (!val.dptr) { - DEBUG(5, ("tdb_fetch_bystring failed!\n")); - return False; - } - - if (val.dsize != sizeof(*pass)) { - DEBUG(0, ("secrets were of incorrect size!\n")); - return False; - } - - pass = (struct machine_acct_pass *)val.dptr; + struct samba3_afs_keyfile keyfile; + memcpy(&keyfile, vbuf.dptr, vbuf.dsize); + keyfile.cell = talloc_strdup(ctx, key); - if (pass_last_set_time) *pass_last_set_time = pass->mod_time; - memcpy(ret_pwd, pass->hash, 16); - - return True; + db->afs_keyfiles = talloc_realloc(ctx, db->afs_keyfiles, struct samba3_afs_keyfile, db->afs_keyfile_count+1); + db->afs_keyfiles[db->afs_keyfile_count] = keyfile; + db->afs_keyfile_count++; + + return NT_STATUS_OK; } -/************************************************************************ - Routine to get account password to trusted domain -************************************************************************/ - -static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time) +static NTSTATUS machine_sec_channel_type (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - struct trusted_dom_pass pass; - - /* unpacking structures */ - int pass_len = 0; - TDB_DATA val; + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); - ZERO_STRUCT(pass); - - /* fetching trusted domain password structure */ - val = tdb_fetch_bystring(tdb, trustdom_keystr(domain)); - if (!val.dptr) { - DEBUG(5, ("secrets_fetch failed!\n")); - return False; - } - - /* unpack trusted domain password */ - pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass); - - if (pass_len != val.dsize) { - DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n")); - return False; - } - - /* the trust's password */ - if (pwd) { - *pwd = strdup(pass.pass); - if (!*pwd) { - return False; - } - } - - /* last change time */ - if (pass_last_set_time) *pass_last_set_time = pass.mod_time; - - /* domain sid */ - - *sid = dom_sid_dup(tdb, &pass.domain_sid); - - return True; + domainsec->sec_channel_type = IVAL(vbuf.dptr, 0); + return NT_STATUS_OK; } -/************************************************************************ - Routine to fetch the plaintext machine account password for a realm -the password is assumed to be a null terminated ascii string -************************************************************************/ -static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain, - time_t *pass_last_set_time, - uint32_t *channel) +static NTSTATUS machine_last_change_time (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - char *key = NULL; - char *ret; - TDB_DATA val; - asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); - strupper_m(key); - val = tdb_fetch_bystring(tdb, key); - SAFE_FREE(key); - - if (pass_last_set_time) { - asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); - strupper_m(key); - tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time); - SAFE_FREE(key); - } - - if (channel) { - asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); - strupper_m(key); - tdb_fetch_uint32(tdb, key, channel); - SAFE_FREE(key); - } - - return ret; + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); + domainsec->last_change_time = IVAL(vbuf.dptr, 0); + return NT_STATUS_OK; } -/******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw) +static NTSTATUS machine_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - char *key = NULL; - size_t size; - TDB_DATA val; - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) { - DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); - } - - val = tdb_fetch_bystring(tdb, key); - *pw = val.dptr; - SAFE_FREE(key); - - if (!size) { - return False; - } - - return True; + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); + domainsec->plaintext_pw = talloc_strdup(ctx, vbuf.dptr); + return NT_STATUS_OK; } +static NTSTATUS machine_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) +{ + struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key); -/** - * Get trusted domains info from secrets.tdb. - * - * The linked list is allocated on the supplied talloc context, caller gets to destroy - * when done. - * - * @param ctx Allocation context - * @param enum_ctx Starting index, eg. we can start fetching at third - * or sixth trusted domain entry. Zero is the first index. - * Value it is set to is the enum context for the next enumeration. - * @param num_domains Number of domain entries to fetch at one call - * @param domains Pointer to array of trusted domain structs to be filled up - * - * @return nt status code of rpc response - **/ + memcpy(&domainsec->hash_pw, vbuf.dptr, vbuf.dsize); + + return NT_STATUS_OK; +} -static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains, - int *num_domains, struct samba3_trustdom ***domains) +static NTSTATUS domtrust_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { - TDB_LIST_NODE *keys, *k; - struct samba3_trustdom *dom = NULL; - char *pattern; - unsigned int start_idx; - uint32_t idx = 0; - size_t size, packed_size = 0; - fstring dom_name; - char *packed_pass; - struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass); - NTSTATUS status; - - if (!pass) { - DEBUG(0, ("talloc_zero failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - *num_domains = 0; - start_idx = *enum_ctx; - - /* generate searching pattern */ - if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) { - DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n")); - return NT_STATUS_NO_MEMORY; - } + int idx, len = 0; + struct samba3_trusted_dom_pass pass; + int pass_len; + + if (!vbuf.dptr) + return NT_STATUS_UNSUCCESSFUL; - DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", - max_num_domains, *enum_ctx)); - - *domains = talloc_zero_array(ctx, struct samba3_trustdom *, max_num_domains); - - /* fetching trusted domains' data and collecting them in a list */ - keys = tdb_search_keys(tdb, pattern); - - /* - * if there's no keys returned ie. no trusted domain, - * return "no more entries" code - */ - status = NT_STATUS_NO_MORE_ENTRIES; - - /* searching for keys in secrets db -- way to go ... */ - for (k = keys; k; k = k->next) { - char *secrets_key; - - /* important: ensure null-termination of the key string */ - secrets_key = strndup(k->node_key.dptr, k->node_key.dsize); - if (!secrets_key) { - DEBUG(0, ("strndup failed!\n")); - return NT_STATUS_NO_MEMORY; - } + /* unpack unicode domain name and plaintext password */ + len += tdb_unpack(tdb, vbuf.dptr, vbuf.dsize - len, "d", &pass.uni_name_len); + + for (idx = 0; idx < 32; idx++) + len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "w", &pass.uni_name[idx]); - packed_pass = secrets_fetch(tdb, secrets_key, &size); - packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass); - /* packed representation isn't needed anymore */ - SAFE_FREE(packed_pass); - - if (size != packed_size) { - DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key)); - continue; - } - - pull_ucs2_fstring(dom_name, pass->uni_name); - DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n", - idx, dom_name, sid_string_static(&pass->domain_sid))); - - SAFE_FREE(secrets_key); - - if (idx >= start_idx && idx < start_idx + max_num_domains) { - dom = talloc(ctx, struct samba3_trustdom); - if (!dom) { - /* free returned tdb record */ - return NT_STATUS_NO_MEMORY; - } - - /* copy domain sid */ - SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid)); - memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid)); - - /* copy unicode domain name */ - dom->name = talloc_memdup(ctx, pass->uni_name, - (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t)); - - (*domains)[idx - start_idx] = dom; - - DEBUG(18, ("Secret record is in required range.\n \ - start_idx = %d, max_num_domains = %d. Added to returned array.\n", - start_idx, max_num_domains)); - - *enum_ctx = idx + 1; - (*num_domains)++; - - /* set proper status code to return */ - if (k->next) { - /* there are yet some entries to enumerate */ - status = STATUS_MORE_ENTRIES; - } else { - /* this is the last entry in the whole enumeration */ - status = NT_STATUS_OK; - } - } else { - DEBUG(18, ("Secret is outside the required range.\n \ - start_idx = %d, max_num_domains = %d. Not added to returned array\n", - start_idx, max_num_domains)); - } - - idx++; - } + len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass_len); + pass.pass = talloc_strdup(ctx, vbuf.dptr+len); + len += strlen(vbuf.dptr)+1; + len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass.mod_time); - DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains)); + pass.domain_sid.sub_auths = talloc_array(ctx, uint32_t, 15); + /* unpack domain sid */ + len += tdb_sid_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, &pass.domain_sid); - /* free the results of searching the keys */ - tdb_search_list_free(keys); + /* FIXME: Add to list */ - return status; + return NT_STATUS_OK; } -/******************************************************************************* - Fetch the current (highest) AFS key from secrets.tdb -*******************************************************************************/ -static BOOL secrets_fetch_afs_key(TDB_CONTEXT *tdb, const char *cell, struct afs_key *result) -{ - fstring key; - struct afs_keyfile *keyfile; - size_t size; - uint32_t i; - - slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell); +static const struct { + const char *prefix; + NTSTATUS (*handler) (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db); +} secrets_handlers[] = { + { "SECRETS/AUTH_PASSWORD", ipc_password }, + { "SECRETS/AUTH_DOMAIN", ipc_domain }, + { "SECRETS/AUTH_USER", ipc_username }, + { "SECRETS/SID/", domain_sid }, + { "SECRETS/DOMGUID/", domain_guid }, + { "SECRETS/LDAP_BIND_PW/", ldap_bind_pw }, + { "SECRETS/AFS_KEYFILE/", afs_keyfile }, + { "SECRETS/MACHINE_SEC_CHANNEL_TYPE/", machine_sec_channel_type }, + { "SECRETS/MACHINE_LAST_CHANGE_TIME/", machine_last_change_time }, + { "SECRETS/MACHINE_PASSWORD/", machine_password }, + { "SECRETS/$MACHINE.ACC/", machine_acc }, + { "SECRETS/$DOMTRUST.ACC/", domtrust_acc }, +}; - keyfile = (struct afs_keyfile *)secrets_fetch(tdb, key, &size); - if (keyfile == NULL) - return False; +NTSTATUS samba3_read_secrets(const char *fname, TALLOC_CTX *ctx, struct samba3_secrets *db) +{ + TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600); + TDB_DATA kbuf, vbuf; - if (size != sizeof(struct afs_keyfile)) { - SAFE_FREE(keyfile); - return False; + if (!tdb) { + DEBUG(0,("Failed to open %s\n", fname)); + return NT_STATUS_UNSUCCESSFUL; } - i = ntohl(keyfile->nkeys); + ZERO_STRUCTP(db); + + db->ipc_cred = cli_credentials_init(ctx); + + for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf)) + { + int i; + char *key; + vbuf = tdb_fetch(tdb, kbuf); + + for (i = 0; secrets_handlers[i].prefix; i++) { + if (!strncmp(kbuf.dptr, secrets_handlers[i].prefix, strlen(secrets_handlers[i].prefix))) { + key = talloc_strndup(ctx, kbuf.dptr+strlen(secrets_handlers[i].prefix), kbuf.dsize-strlen(secrets_handlers[i].prefix)); + secrets_handlers[i].handler(tdb, key, vbuf, ctx, db); + talloc_free(key); + break; + } + } - if (i > SECRETS_AFS_MAXKEYS) { - SAFE_FREE(keyfile); - return False; + if (!secrets_handlers[i].prefix) { + DEBUG(0, ("Unable to find handler for string %s", kbuf.dptr)); + } } - - *result = keyfile->entry[i-1]; - - result->kvno = ntohl(result->kvno); - - return True; -} - -/****************************************************************************** - When kerberos is not available, choose between anonymous or - authenticated connections. - - We need to use an authenticated connection if DCs have the - RestrictAnonymous registry entry set > 0, or the "Additional - restrictions for anonymous connections" set in the win2k Local - Security Policy. - - Caller to free() result in domain, username, password -*******************************************************************************/ -static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char **domain, char **password) -{ - *username = secrets_fetch(tdb, SECRETS_AUTH_USER, NULL); - *domain = secrets_fetch(tdb, SECRETS_AUTH_DOMAIN, NULL); - *password = secrets_fetch(tdb, SECRETS_AUTH_PASSWORD, NULL); - if (*username && **username) { - - if (!*domain || !**domain) - *domain = smb_xstrdup(lp_workgroup()); - - if (!*password || !**password) - *password = smb_xstrdup(""); - - DEBUG(3, ("IPC$ connections done by user %s\\%s\n", - *domain, *username)); - - } else { - DEBUG(3, ("IPC$ connections done anonymously\n")); - *username = smb_xstrdup(""); - *domain = smb_xstrdup(""); - *password = smb_xstrdup(""); - } -} - + tdb_close(tdb); + return NT_STATUS_OK; +} -- cgit From 47843f2b64001552b4606b2a2ecd6cefbf3971ba Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 17:01:23 +0000 Subject: r9591: - Remove empty file - Fix a couple of typo's - Fix build of lib/samba3/secrets.c for systems that don't have /usr/include/tdb.h... (This used to be commit b8c52900636515d1215ae79a70416db93ce4531c) --- source4/lib/ldb/README_gcov.txt | 2 +- source4/lib/ldb/samba/ldb_samba3.c | 29 +++++++++++++++++++++++++++++ source4/lib/samba3/secrets.c | 2 +- source4/lib/select.c | 2 +- source4/lib/substitute.c | 2 +- source4/lib/tdb_helper.c | 27 --------------------------- source4/lib/unix_privs.c | 3 +-- 7 files changed, 34 insertions(+), 33 deletions(-) create mode 100644 source4/lib/ldb/samba/ldb_samba3.c delete mode 100644 source4/lib/tdb_helper.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/README_gcov.txt b/source4/lib/ldb/README_gcov.txt index 02f090f69f..9684379c6e 100644 --- a/source4/lib/ldb/README_gcov.txt +++ b/source4/lib/ldb/README_gcov.txt @@ -25,7 +25,7 @@ You can also combine steps 2 to 4 like this: make -sf Makefile.ldb clean all test-tdb gcov Note that you should not expect 100% coverage, as some error paths -(such as memory allocation failures) are verr hard to trigger. There +(such as memory allocation failures) are very hard to trigger. There are ways of working around this, but they are quite tricky (they involve allocation wrappers that "fork and fail on malloc"). diff --git a/source4/lib/ldb/samba/ldb_samba3.c b/source4/lib/ldb/samba/ldb_samba3.c new file mode 100644 index 0000000000..6a7bfc6298 --- /dev/null +++ b/source4/lib/ldb/samba/ldb_samba3.c @@ -0,0 +1,29 @@ +/* + ldb database library - Samba3 compatibility backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/ldb_map/ldb_map.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 4aacffda34..6b629d1eff 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -25,7 +25,7 @@ such as the local SID and machine trust password */ #include "includes.h" -#include "tdb.h" +#include "lib/tdb/include/tdb.h" #include "lib/samba3/samba3.h" #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" diff --git a/source4/lib/select.c b/source4/lib/select.c index 066465c1be..a1b2e04065 100644 --- a/source4/lib/select.c +++ b/source4/lib/select.c @@ -51,7 +51,7 @@ void sys_select_signal(void) /******************************************************************* Like select() but avoids the signal race using a pipe - it also guuarantees that fds on return only ever contains bits set + it also guarantees that fds on return only ever contains bits set for file descriptors that were readable. ********************************************************************/ diff --git a/source4/lib/substitute.c b/source4/lib/substitute.c index a351db1af2..34a2ad9f82 100644 --- a/source4/lib/substitute.c +++ b/source4/lib/substitute.c @@ -22,7 +22,7 @@ #include "includes.h" #include "smb_server/smb_server.h" -/* oh bugger - I realy didn't want to have a top-level context +/* oh bugger - I really didn't want to have a top-level context anywhere, but until we change all lp_*() calls to take a context argument this is needed */ static struct substitute_context *sub; diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c deleted file mode 100644 index e29a8a7211..0000000000 --- a/source4/lib/tdb_helper.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - Unix SMB/CIFS implementation. - tdb utility functions - Copyright (C) Andrew Tridgell 1992-1998 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include - -/* these are little tdb utility functions that are meant to make - dealing with a tdb database a little less cumbersome in Samba */ - - diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c index 5cc7d5f26e..2ea4d1b2a0 100644 --- a/source4/lib/unix_privs.c +++ b/source4/lib/unix_privs.c @@ -31,7 +31,7 @@ talloc_free() this pointer. Note that this call is considered successful even if it does not - manage to gain too privileges, but it will call smb_abort() if it + manage to gain root privileges, but it will call smb_abort() if it fails to restore the privileges afterwards. The logic is that failing to gain root access can be caught by whatever operation needs to be run as root failing, but failing to lose the root @@ -67,4 +67,3 @@ void *root_privileges(void) talloc_set_destructor(s, privileges_destructor); return s; } - -- cgit From 98b303e2ebf0814856759499a99c40d5cd4f9f00 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 24 Aug 2005 22:06:26 +0000 Subject: r9595: Add ldb map module (This used to be commit e0a0d3f092d601a22b7549a0278735e66239b301) --- source4/lib/ldb/config.mk | 8 ++ source4/lib/ldb/ldb_map/ldb_map.c | 238 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/ldb_map/ldb_map.h | 46 +++---- source4/lib/ldb/samba/ldb_samba3.c | 29 ----- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/ldb_samba3.c | 50 ++++++++ 6 files changed, 323 insertions(+), 51 deletions(-) create mode 100644 source4/lib/ldb/ldb_map/ldb_map.c delete mode 100644 source4/lib/ldb/samba/ldb_samba3.c create mode 100644 source4/lib/samba3/ldb_samba3.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index d3f60b74ca..76059b3b60 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -37,6 +37,14 @@ NOPROTO = YES # End MODULE libldb_ildap ################################################ +################################################ +# Start MODULE libldb_map +[MODULE::libldb_map] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = lib/ldb/ldb_map/ldb_map.o +# End MODULE libldb_map +################################################ + ################################################ # Start MODULE libldb_sqlite3 [MODULE::libldb_sqlite3] diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c new file mode 100644 index 0000000000..39bab2c4c6 --- /dev/null +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -0,0 +1,238 @@ +/* + ldb database library - map backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_private.h" +#include "lib/ldb/ldb_map/ldb_map.h" + +struct map_private { + struct ldb_map_mappings *mappings; +}; + +static struct ldb_dn *ldb_map_dn(struct ldb_module *module, const struct ldb_dn *dn) +{ + /* FIXME */ + return NULL; +} + +static char *ldb_map_expression(struct ldb_module *module, const char *expr) +{ + /* FIXME */ + return NULL; +} + +static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) +{ + /* FIXME */ + return NULL; +} + +static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const struct ldb_message *mi) +{ + /* FIXME */ + return NULL; +} + +static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mi) +{ + /* FIXME */ + return NULL; +} + +/* + rename a record +*/ +static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) +{ + struct ldb_dn *n_olddn, *n_newdn; + int ret; + + n_olddn = ldb_map_dn(module, olddn); + n_newdn = ldb_map_dn(module, newdn); + + ret = ldb_next_rename_record(module, n_olddn, n_newdn); + + talloc_free(n_olddn); + talloc_free(n_newdn); + + return ret; +} + +/* + delete a record +*/ +static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int ret; + + newdn = ldb_map_dn(module, dn); + + ret = ldb_next_delete_record(module, newdn); + + talloc_free(newdn); + + return ret; +} + + +/* + search for matching records +*/ +static int map_search(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + char *newexpr; + int ret; + const char **newattrs; + struct ldb_dn *new_base; + struct ldb_message **newres; + int i; + + newexpr = ldb_map_expression(module, expression); + newattrs = ldb_map_attrs(module, attrs); + new_base = ldb_map_dn(module, base); + + ret = ldb_next_search(module, new_base, scope, newexpr, newattrs, &newres); + + talloc_free(new_base); + talloc_free(newexpr); + talloc_free(newattrs); + + for (i = 0; i < ret; i++) { + *res[i] = ldb_map_message_incoming(module, newres[i]); + talloc_free(newres[i]); + } + + return ret; +} + +/* + add a record +*/ +static int map_add(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg); + int ret; + + ret = ldb_next_add_record(module, nmsg); + + talloc_free(nmsg); + + return ret; +} + + +/* + search for matching records using a ldb_parse_tree +*/ +static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct map_private *privdat = module->private_data; + char *expression; + int ret; + + expression = ldb_filter_from_tree(privdat, tree); + if (expression == NULL) { + return -1; + } + ret = map_search(module, base, scope, expression, attrs, res); + talloc_free(expression); + return ret; +} + +/* + modify a record +*/ +static int map_modify(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg); + int ret; + + ret = ldb_next_modify_record(module, nmsg); + + talloc_free(nmsg); + + return ret; +} + +static int map_lock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_lock(module, lockname); +} + +static int map_unlock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_unlock(module, lockname); +} + +/* + return extended error information +*/ +static const char *map_errstring(struct ldb_module *module) +{ + return ldb_next_errstring(module); +} + +static const struct ldb_module_ops map_ops = { + .name = "map", + .search = map_search, + .search_bytree = map_search_bytree, + .add_record = map_add, + .modify_record = map_modify, + .delete_record = map_delete, + .rename_record = map_rename, + .named_lock = map_lock, + .named_unlock = map_unlock, + .errstring = map_errstring +}; + +/* the init function */ +struct ldb_module *ldb_map_init(struct ldb_context *ldb, struct ldb_map_mappings *mappings, const char *options[]) +{ + struct ldb_module *ctx; + struct map_private *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct map_private); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->mappings = mappings; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &map_ops; + + return ctx; +} diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h index 6d6e47873c..3ebf2fa9d1 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -1,29 +1,33 @@ -struct objectclass_mapping { - char *local_name; - char *remote_name; +/* + ldb database library - map backend - char *key; /* Name of attribute used in rdn */ + Copyright (C) Jelmer Vernooij 2005 - /* For mapping attributes used in searches */ - struct local_attribute_mapping { - char *local_name; + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - /* Attributes to request from the server for this attribute, - * needed by generate */ - char *required_attributes[]; + This library 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 + Lesser General Public License for more details. - /* If not set, the value for the first element of - * required_attributes will simply be used here */ - struct ldb_message_element *(*generate) (LDAPMessage *msg); - } *local_attribute_mappings; + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ - /* Generate LDAPMod for adds and modifies */ - LDAPMod *(*generate_mod)(struct ldb_message *); -} +#ifndef __LDB_MAP_H__ +#define __LDB_MAP_H__ + +struct ldb_map_mappings +{ -struct ldb_map_backend { - struct objectclass_mapping *objectclass_mappings; }; -const char *ldb_map_dn(const char *old); -const char *ldb_map_rdn(const char *old); +#endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/ldb/samba/ldb_samba3.c b/source4/lib/ldb/samba/ldb_samba3.c deleted file mode 100644 index 6a7bfc6298..0000000000 --- a/source4/lib/ldb/samba/ldb_samba3.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - ldb database library - Samba3 compatibility backend - - Copyright (C) Jelmer Vernooij 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "includes.h" -#include "ldb/ldb_map/ldb_map.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" - diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 75073048d0..b5bf3fadb9 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -10,7 +10,8 @@ ADD_OBJ_FILES = \ lib/samba3/samba3.o \ lib/samba3/group.o \ lib/samba3/registry.o \ - lib/samba3/secrets.o + lib/samba3/secrets.o \ + lib/samba3/ldb_samba3.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c new file mode 100644 index 0000000000..fa13daa611 --- /dev/null +++ b/source4/lib/samba3/ldb_samba3.c @@ -0,0 +1,50 @@ +/* + ldb database library - Samba3 compatibility backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/ldb_map/ldb_map.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + +/* + * sambaGroupMapping -> group + * gidNumber -> ??? + * sambaSID -> member + * sambaGroupType -> groupType + * displayName -> name + * description -> description + * sambaSIDList -> member + */ + +struct ldb_map_mappings samba3_mappings; + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *ldb_samba3_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + return ldb_map_init(ldb, &samba3_mappings, options); +} -- cgit From 2dc45bd4841a0b7ea640d9a41e381f4601809262 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 25 Aug 2005 00:57:21 +0000 Subject: r9600: fixed the intermittent failures we were getting with ejs in the build farm. (This used to be commit b23bffcba62df954c7fb439c78b962fbd262cc5e) --- source4/lib/appweb/ejs/ejsParser.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c index 871907dd10..da7b544c90 100644 --- a/source4/lib/appweb/ejs/ejsParser.c +++ b/source4/lib/appweb/ejs/ejsParser.c @@ -1485,6 +1485,23 @@ static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) return 0; } + +/* + return true if this string is a valid number +*/ +static int string_is_number(const char *s) +{ + char *endptr = NULL; + if (s == NULL || *s == 0) { + return 0; + } + strtod(s, &endptr); + if (endptr != NULL && *endptr == 0) { + return 1; + } + return 0; +} + /******************************************************************************/ /* * Evaluate an operation. Returns with the result in ep->result. Returns -1 @@ -1533,6 +1550,24 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) /* Nothing more can be done */ } + /* undefined and null are special, in that they don't get promoted when + comparing */ + if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) { + if (lhs->type == MPR_TYPE_UNDEFINED || rhs->type == MPR_TYPE_UNDEFINED) { + return evalBoolExpr(ep, + lhs->type == MPR_TYPE_UNDEFINED, + rel, + rhs->type == MPR_TYPE_UNDEFINED); + } + + if (lhs->type == MPR_TYPE_NULL || rhs->type == MPR_TYPE_NULL) { + return evalBoolExpr(ep, + lhs->type == MPR_TYPE_NULL, + rel, + rhs->type == MPR_TYPE_NULL); + } + } + /* * From here on, lhs and rhs may contain allocated data (strings), so * we must always destroy before overwriting. @@ -1556,7 +1591,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) */ if (lhs->type != rhs->type) { if (lhs->type == MPR_TYPE_STRING) { - if (isdigit((int) lhs->string[0])) { + if (string_is_number(lhs->string)) { num = mprVarToNumber(lhs); lhs->allocatedVar = 0; mprDestroyVar(lhs); -- cgit From dcd27d550fcc6fc8ddbec2f4a310a862f3fbbffc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 25 Aug 2005 01:12:43 +0000 Subject: r9602: Add support for reading share_info.tdb and smb.conf. Add userdata argument to function pointers for pm_process() (This used to be commit 84b2fb34675fa557173621433838c5a7ec0f1283) --- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/ldb_samba3.c | 60 ++++++++++++++++++++++++++++- source4/lib/samba3/samba3.c | 69 +++++++++++++++++++++++++++++++++ source4/lib/samba3/samba3.h | 16 ++++++++ source4/lib/samba3/share_info.c | 85 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 source4/lib/samba3/share_info.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index b5bf3fadb9..79142e4f67 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -11,7 +11,8 @@ ADD_OBJ_FILES = \ lib/samba3/group.o \ lib/samba3/registry.o \ lib/samba3/secrets.o \ - lib/samba3/ldb_samba3.o + lib/samba3/ldb_samba3.o \ + lib/samba3/share_info.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c index fa13daa611..030b051938 100644 --- a/source4/lib/samba3/ldb_samba3.c +++ b/source4/lib/samba3/ldb_samba3.c @@ -34,9 +34,67 @@ * sambaGroupType -> groupType * displayName -> name * description -> description - * sambaSIDList -> member + * sambaSIDList -> member (special!) */ +/* + * sambaTrustPassword + */ + +/* sambaDomain + * sambaDomainName + * sambaSID + * sambaNextRid + * sambaNextGroupRid + * sambaNextUserRid + * sambaAlgorithmicRidBase + */ + +/* sambaUnixIdPool + */ + +/* sambaIdmapEntry */ + +/* sambaAccountPolicy */ + +/* sambaSidEntry: FIXME */ + +/* sambaSamAccount -> user: + * uid -> unixName (magic!) + * sambaSID -> objectSid + * cn -> cn + * sambaLMPassword -> lmPwdHash + * sambaNTPassword -> ntPwdHash + * sambaPwdLastSet -> pwdLastSet + * sambaLogonTime -> lastLogon + * sambaLogoffTime -> lastLogoff + * sambaKickoffTime -> ??? + * sambaPwdCanChange -> ??? + * sambaPwdMustChange -> ??? + * sambaAcctFlags -> systemFlags ? + * displayName -> name + * sambaHomePath -> ??? + * sambaHomeDrive -> ??? + * sambaLogonScript -> ??? + * sambaProfilePath -> ??? + * description -> description + * sambaUserWorkstations -> ??? + * sambaPrimaryGroupSID -> primaryGroupID + * sambaDomainName -> ??? + * sambaMungedDial -> ??? + * sambaBadPasswordCount -> badPwdcount + * sambaBadPasswordTime -> badPasswordtime + * sambaPasswordHistory -> ntPwdHistory + * sambaLogonHours -> ??? + */ + +/* Not necessary: + * sambaConfig + * sambaShare + * sambaConfigOption + */ + + struct ldb_map_mappings samba3_mappings; /* the init function */ diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index bfd41d6554..4eda3bd154 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -20,6 +20,71 @@ #include "includes.h" #include "lib/samba3/samba3.h" +struct smbconf_data { + TALLOC_CTX *ctx; + struct samba3 *db; + struct samba3_share_info *current_share; +}; + +struct samba3_share_info *samba3_find_share(struct samba3 *db, TALLOC_CTX* ctx, const char *name) +{ + int i; + for (i = 0; i < db->share_count; i++) { + if (!StrCaseCmp(db->shares[i].name, name)) + return &db->shares[i]; + } + + db->shares = talloc_realloc(ctx, db->shares, struct samba3_share_info, db->share_count+1); + ZERO_STRUCT(db->shares[i]); + db->shares[i].name = talloc_strdup(ctx, name); + db->share_count++; + + return &db->shares[i]; +} + +static BOOL samba3_sfunc (const char *name, void *_db) +{ + struct smbconf_data *privdat = _db; + + privdat->current_share = samba3_find_share(privdat->db, privdat->ctx, name); + + return True; +} + +static BOOL samba3_pfunc (const char *name, const char *value, void *_db) +{ + struct smbconf_data *privdat = _db; + struct samba3_parameter *p; + + privdat->current_share->parameters = + talloc_realloc(privdat->ctx, privdat->current_share->parameters, + struct samba3_parameter, + privdat->current_share->parameter_count+1); + + p = &privdat->current_share->parameters[privdat->current_share->parameter_count]; + p->name = talloc_strdup(privdat->ctx, name); + p->value = talloc_strdup(privdat->ctx, value); + + privdat->current_share->parameter_count++; + + return True; +} + +NTSTATUS samba3_read_smbconf(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) +{ + struct smbconf_data privdat; + + privdat.ctx = ctx; + privdat.db = db; + privdat.current_share = samba3_find_share(db, ctx, "global"); + + if (!pm_process( fn, samba3_sfunc, samba3_pfunc, &privdat )) { + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) { struct samba3 *ret; @@ -55,5 +120,9 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) samba3_read_secrets(dbfile, ctx, &ret->secrets); SAFE_FREE(dbfile); + asprintf(&dbfile, "%s/share_info.tdb", libdir); + samba3_read_share_info(dbfile, ctx, ret); + SAFE_FREE(dbfile); + return ret; } diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index 575ee83825..fe4db560a8 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -184,6 +184,19 @@ struct samba3_secrets } *afs_keyfiles; }; +struct samba3_parameter { + char *name; + char *value; +}; + +struct samba3_share_info { + char *name; + struct security_descriptor secdesc; + + uint32_t parameter_count; + struct samba3_parameter *parameters; +}; + struct samba3 { uint32_t winsdb_count; @@ -192,6 +205,9 @@ struct samba3 uint32_t samaccount_count; struct samba3_samaccount *samaccounts; + uint32_t share_count; + struct samba3_share_info *shares; + struct samba3_secrets secrets; struct samba3_groupdb group; struct samba3_idmapdb idmap; diff --git a/source4/lib/samba3/share_info.c b/source4/lib/samba3/share_info.c new file mode 100644 index 0000000000..098d6c552e --- /dev/null +++ b/source4/lib/samba3/share_info.c @@ -0,0 +1,85 @@ +/* + * Unix SMB/CIFS implementation. + * Share Info parsing + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Nigel Williams 2001. + * Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "lib/tdb/include/tdbutil.h" +#include "lib/samba3/samba3.h" +#include "system/filesys.h" + +#define SHARE_DATABASE_VERSION_V1 1 +#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */ + +NTSTATUS samba3_read_share_info(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) +{ + int32_t vers_id; + TDB_CONTEXT *tdb; + TDB_DATA kbuf, vbuf; + DATA_BLOB blob; + + tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600); + if (!tdb) { + DEBUG(0,("Failed to open share info database %s (%s)\n", + fn, strerror(errno) )); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Cope with byte-reversed older versions of the db. */ + vers_id = tdb_fetch_int32(tdb, "INFO/version"); + if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) { + /* Written on a bigendian machine with old fetch_int code. Save as le. */ + vers_id = SHARE_DATABASE_VERSION_V2; + } + + if (vers_id != SHARE_DATABASE_VERSION_V2) { + return NT_STATUS_UNSUCCESSFUL; + } + + for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf)) + { + struct ndr_pull *pull; + struct samba3_share_info *share; + char *name; + + if (strncmp(kbuf.dptr, "SECDESC/", strlen("SECDESC/")) != 0) + continue; + + name = talloc_strndup(ctx, kbuf.dptr+strlen("SECDESC/"), kbuf.dsize-strlen("SECDESC/")); + + share = samba3_find_share(db, ctx, name); + + vbuf = tdb_fetch(tdb, kbuf); + blob.data = (uint8_t *)vbuf.dptr; + blob.length = vbuf.dsize; + + pull = ndr_pull_init_blob(&blob, ctx); + + ndr_pull_security_descriptor(pull, NDR_SCALARS|NDR_BUFFERS, &share->secdesc); + + talloc_free(pull); + } + + tdb_close(tdb); + + return NT_STATUS_OK; +} -- cgit From 9bf5e494f7ccbb2a9587dce961a99fa07392bf97 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 25 Aug 2005 15:25:22 +0000 Subject: r9616: Finish ldb_map module (still needs a lot of testing though...) Add initial mapping table for ldb_samba3. Contains most attributes. (This used to be commit b73441b04d048919e95ee7f7bcae330c4dafefe7) --- source4/lib/ldb/ldb_map/ldb_map.c | 450 ++++++++++++++++++++++++++++++++++---- source4/lib/ldb/ldb_map/ldb_map.h | 81 ++++++- source4/lib/samba3/ldb_samba3.c | 214 +++++++++++++----- 3 files changed, 650 insertions(+), 95 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 39bab2c4c6..4006ccbbd7 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -27,38 +27,391 @@ #include "lib/ldb/include/ldb_private.h" #include "lib/ldb/ldb_map/ldb_map.h" +/* TODO: + * - objectclass hint in ldb_map_attribute + * for use when multiple remote attributes (independant of each other) + * map to one local attribute. E.g.: (uid, gidNumber) -> unixName + */ + struct map_private { - struct ldb_map_mappings *mappings; + const struct ldb_map_mappings *mappings; + const char *last_err_string; }; -static struct ldb_dn *ldb_map_dn(struct ldb_module *module, const struct ldb_dn *dn) +/* find an attribute by the local name */ +static const struct ldb_map_attribute *map_find_attr_local(struct ldb_module *module, const char *attr) { - /* FIXME */ + struct map_private *privdat = module->private_data; + int i; + for (i = 0; privdat->mappings->attribute_maps[i]; i++) { + if (!strcmp(privdat->mappings->attribute_maps[i]->local_name, attr)) + return privdat->mappings->attribute_maps[i]; + } + return NULL; } -static char *ldb_map_expression(struct ldb_module *module, const char *expr) +/* find an attribute by the remote name */ +static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_module *module, const char *attr) { - /* FIXME */ + struct map_private *privdat = module->private_data; + int i; + for (i = 0; privdat->mappings->attribute_maps[i]; i++) { + if (privdat->mappings->attribute_maps[i]->type != MAP_RENAME && + privdat->mappings->attribute_maps[i]->type != MAP_CONVERT) + continue; + + if (!strcmp(privdat->mappings->attribute_maps[i]->u.rename.remote_name, attr)) + return privdat->mappings->attribute_maps[i]; + } + return NULL; } +static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, const struct ldb_parse_tree *tree) +{ + int i; + const struct ldb_map_attribute *attr; + struct ldb_parse_tree *new_tree = talloc_memdup(module, tree, sizeof(*tree)); + + /* Find attr in question and: + * - if it has a convert_operator function, run that + * - otherwise, replace attr name with required[0] */ + + if (tree->operation == LDB_OP_AND || + tree->operation == LDB_OP_OR) { + for (i = 0; i < tree->u.list.num_elements; i++) { + new_tree->u.list.elements[i] = ldb_map_parse_tree(module, tree->u.list.elements[i]); + } + + return new_tree; + } + + if (tree->operation == LDB_OP_NOT) { + new_tree->u.isnot.child = ldb_map_parse_tree(module, tree->u.isnot.child); + return new_tree; + } + + /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER, + * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED + * + * (all have attr as the first element) + */ + + attr = map_find_attr_local(module, tree->u.equality.attr); + + if (!attr) { + DEBUG(0, ("Unable to find local attribute '%s', leaving as is", tree->u.equality.attr)); + return new_tree; + } + + if (attr->type == MAP_IGNORE) + return NULL; + + if (attr->convert_operator) { + /* Run convert_operator */ + talloc_free(new_tree); + new_tree = attr->convert_operator(module, tree); + } else { + new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); + } + + return new_tree; +} + +/* Remote DN -> Local DN */ +static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int i; + + newdn = talloc_memdup(module, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_remote(module, dn->components[i].name); + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) + continue; + + if (attr->type == MAP_IGNORE) { + DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + } + + if (attr->type == MAP_GENERATE) { + DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + + return NULL; + } + + if (attr->type == MAP_CONVERT) { + struct ldb_message_element elm, *newelm; + struct ldb_val vals[1] = { dn->components[i].value }; + elm.flags = 0; + elm.name = attr->u.convert.remote_name; + elm.num_values = 1; + elm.values = vals; + + newelm = attr->u.convert.convert_remote(module, attr->local_name, &elm); + + newdn->components[i].name = talloc_strdup(module, newelm->name); + newdn->components[i].value = newelm->values[0]; + } else if (attr->type == MAP_RENAME) { + newdn->components[i].name = talloc_strdup(module, attr->local_name); + } + } + return newdn; +} + +/* Local DN -> Remote DN */ +static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_dn *dn) +{ struct ldb_dn *newdn; + int i; + struct ldb_parse_tree eqtree, *new_eqtree; + + newdn = talloc_memdup(module, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn using an equality convert_operator call */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(module, dn->components[i].name); + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) + continue; + + if (attr->type == MAP_IGNORE) { + DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + } + + if (attr->type == MAP_GENERATE) { + DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + + return NULL; + } + + /* Simple rename/convert only */ + if (attr->convert_operator) { + /* Fancy stuff */ + eqtree.operation = LDB_OP_EQUALITY; + eqtree.u.equality.attr = dn->components[i].name; + eqtree.u.equality.value = dn->components[i].value; + + new_eqtree = ldb_map_parse_tree(module, &eqtree); + + /* Silently continue for now */ + if (!new_eqtree) { + DEBUG(0, ("Unable to convert RDN for attribute %s\n", dn->components[i].name)); + continue; + } + + newdn->components[i].name = new_eqtree->u.equality.attr; + newdn->components[i].value = new_eqtree->u.equality.value; + } else if (attr->type == MAP_CONVERT) { + struct ldb_message_element elm, *newelm; + struct ldb_val vals[1] = { dn->components[i].value }; + elm.flags = 0; + elm.name = attr->local_name; + elm.num_values = 1; + elm.values = vals; + + newelm = attr->u.convert.convert_local(module, attr->u.convert.remote_name, &elm); + + newdn->components[i].name = talloc_strdup(module, newelm->name); + newdn->components[i].value = newelm->values[0]; + } else if (attr->type == MAP_RENAME) { + newdn->components[i].name = talloc_strdup(module, attr->u.rename.remote_name); + } + } + + return newdn; +} + + + +/* Loop over ldb_map_attribute array and add remote_names */ static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) { - /* FIXME */ + int i; + const char **ret; + int ar_size = 0, last_element = 0; + + /* Start with good guess of number of elements */ + for (i = 0; attrs[i]; i++); + + ret = talloc_array(module, const char *, i); + ar_size = i; + + for (i = 0; attrs[i]; i++) { + int j; + const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]); + + if (!attr) { + DEBUG(0, ("Local attribute '%s' does not have a definition!\n", attrs[i])); + continue; + } + + switch (attr->type) + { + case MAP_IGNORE: break; + case MAP_KEEP: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->local_name; + last_element++; + break; + + case MAP_RENAME: + case MAP_CONVERT: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.rename.remote_name; + last_element++; + break; + + case MAP_GENERATE: + /* Add remote_names[] for this attribute to the list of + * attributes to request from the remote server */ + for (j = 0; attr->u.generate.remote_names[j]; j++) { + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.generate.remote_names[j]; + last_element++; + } + break; + } + } + return NULL; } -static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const struct ldb_message *mi) +static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) { - /* FIXME */ - return NULL; + int i; + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm, *oldelm; + + msg->dn = map_remote_dn(module, mi->dn); + + /* Loop over attrs, find in ldb_map_attribute array and + * run generate() */ + + for (i = 0; attrs[i]; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]); + + if (!attr) { + DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message", attrs[i])); + continue; + } + + switch (attr->type) { + case MAP_IGNORE:break; + case MAP_RENAME: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + elm = talloc_memdup(msg, oldelm, sizeof(*oldelm)); + elm->name = talloc_strdup(elm, attr->local_name); + + ldb_msg_add(module->ldb, msg, elm, 0); + break; + + case MAP_CONVERT: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + elm = attr->u.convert.convert_local(msg, attr->local_name, oldelm); + + ldb_msg_add(module->ldb, msg, elm, 0); + break; + + case MAP_KEEP: + ldb_msg_add(module->ldb, msg, ldb_msg_find_element(mi, attr->local_name), 0); + break; + + case MAP_GENERATE: + elm = attr->u.generate.generate_local(msg, attr->local_name, mi); + ldb_msg_add(module->ldb, msg, elm, 0); + break; + default: + DEBUG(0, ("Unknown attr->type for %s", attr->local_name)); + break; + } + } + + return msg; } -static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mi) +static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo) { - /* FIXME */ - return NULL; + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm; + int i; + + msg->private_data = mo->private_data; + + msg->dn = map_local_dn(module, mo->dn); + + /* Loop over mi and call generate_remote for each attribute */ + for (i = 0; i < mo->num_elements; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(module, mo->elements[i].name); + + if (!attr) { + DEBUG(0, ("Undefined local attribute '%s', ignoring\n", mo->elements[i].name)); + continue; + } + + switch (attr->type) { + case MAP_IGNORE: break; + case MAP_RENAME: + elm = talloc_memdup(msg, &msg->elements[i], sizeof(*elm)); + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + + ldb_msg_add(module->ldb, msg, elm, 0); + break; + + case MAP_CONVERT: + elm = attr->u.convert.convert_remote(msg, attr->local_name, &msg->elements[i]); + ldb_msg_add(module->ldb, msg, elm, 0); + break; + + case MAP_KEEP: + ldb_msg_add(module->ldb, msg, &msg->elements[i], 0); + break; + + case MAP_GENERATE: + attr->u.generate.generate_remote(attr->local_name, mo, msg); + break; + } + } + + return msg; } /* @@ -69,8 +422,8 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con struct ldb_dn *n_olddn, *n_newdn; int ret; - n_olddn = ldb_map_dn(module, olddn); - n_newdn = ldb_map_dn(module, newdn); + n_olddn = map_local_dn(module, olddn); + n_newdn = map_local_dn(module, newdn); ret = ldb_next_rename_record(module, n_olddn, n_newdn); @@ -88,7 +441,7 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) struct ldb_dn *newdn; int ret; - newdn = ldb_map_dn(module, dn); + newdn = map_local_dn(module, dn); ret = ldb_next_delete_record(module, newdn); @@ -97,38 +450,58 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) return ret; } - /* - search for matching records + search for matching records using a ldb_parse_tree */ -static int map_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) +static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { - char *newexpr; int ret; const char **newattrs; + struct ldb_parse_tree *new_tree; struct ldb_dn *new_base; struct ldb_message **newres; int i; - newexpr = ldb_map_expression(module, expression); + new_tree = ldb_map_parse_tree(module, tree); newattrs = ldb_map_attrs(module, attrs); - new_base = ldb_map_dn(module, base); + new_base = map_local_dn(module, base); - ret = ldb_next_search(module, new_base, scope, newexpr, newattrs, &newres); + ret = ldb_next_search_bytree(module, new_base, scope, new_tree, newattrs, &newres); talloc_free(new_base); - talloc_free(newexpr); + talloc_free(new_tree); talloc_free(newattrs); for (i = 0; i < ret; i++) { - *res[i] = ldb_map_message_incoming(module, newres[i]); + *res[i] = ldb_map_message_incoming(module, attrs, newres[i]); talloc_free(newres[i]); } return ret; } +/* + search for matching records +*/ +static int map_search(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + struct map_private *map = module->private_data; + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(map, expression); + if (tree == NULL) { + map->last_err_string = "expression parse failed"; + return -1; + } + + ret = map_search_bytree(module, base, scope, tree, attrs, res); + talloc_free(tree); + return ret; +} /* add a record @@ -146,25 +519,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) } -/* - search for matching records using a ldb_parse_tree -*/ -static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - struct map_private *privdat = module->private_data; - char *expression; - int ret; - expression = ldb_filter_from_tree(privdat, tree); - if (expression == NULL) { - return -1; - } - ret = map_search(module, base, scope, expression, attrs, res); - talloc_free(expression); - return ret; -} /* modify a record @@ -196,6 +551,11 @@ static int map_unlock(struct ldb_module *module, const char *lockname) */ static const char *map_errstring(struct ldb_module *module) { + struct map_private *map = module->private_data; + + if (map->last_err_string) + return map->last_err_string; + return ldb_next_errstring(module); } @@ -213,7 +573,7 @@ static const struct ldb_module_ops map_ops = { }; /* the init function */ -struct ldb_module *ldb_map_init(struct ldb_context *ldb, struct ldb_map_mappings *mappings, const char *options[]) +struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_mappings *mappings, const char *options[]) { struct ldb_module *ctx; struct map_private *data; diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h index 3ebf2fa9d1..da3198429d 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -25,9 +25,88 @@ #ifndef __LDB_MAP_H__ #define __LDB_MAP_H__ -struct ldb_map_mappings +/* ldb_map is a skeleton LDB module that can be used for any other modules + * that need to map attributes. + * + * The term 'remote' in this header refers to the connection where the + * original schema is used on while 'local' means the local connection + * that any upper layers will use. + * + * All local attributes will have to have a definition. Not all remote + * attributes need a definition as LDB is a lot less stricter then LDAP + * (in other words, sending unknown attributes to an LDAP server hurts us, + * returning too much attributes in ldb_search() doesn't) + */ + +struct ldb_map_attribute { + const char *local_name; /* local name */ + + enum { + MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ + MAP_KEEP, /* Keep as is */ + MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ + MAP_CONVERT, /* Rename + convert data */ + MAP_GENERATE /* Use generate function for generating new name/data. + Used for generating attributes based on + multiple remote attributes. */ + } type; + + /* if set, will be called for expressions that contain this attribute */ + struct ldb_parse_tree *(*convert_operator) (TALLOC_CTX *ctx, const struct ldb_parse_tree *); + + union { + struct { + const char *remote_name; + } rename; + + struct { + const char *remote_name; + struct ldb_message_element *(*convert_local) ( + TALLOC_CTX *ctx, + const char *remote_attr, + const struct ldb_message_element *); + + struct ldb_message_element *(*convert_remote) ( + TALLOC_CTX *ctx, + const char *local_attr, + const struct ldb_message_element *); + } convert; + + struct { + /* Generate the local attribute from remote message */ + struct ldb_message_element *(*generate_local) ( + TALLOC_CTX *ctx, + const char *attr, + const struct ldb_message *remote); + + /* Update remote message with information from local message */ + void (*generate_remote) ( + const char *local_attr, + const struct ldb_message *local, + struct ldb_message *remote); + + /* Name(s) for this attribute on the remote server. This is an array since + * one local attribute's data can be split up into several attributes + * remotely */ + const char *remote_names[]; + } generate; + } u; }; +struct ldb_map_objectclass +{ + const char *local_name; + const char *remote_name; +}; + +/* Base ldb_map struct. Fill this in to create a mapping backend */ +struct ldb_map_mappings +{ + const char *name; + const struct ldb_map_attribute *attribute_maps[]; +}; + + #endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c index 030b051938..53d8964d0d 100644 --- a/source4/lib/samba3/ldb_samba3.c +++ b/source4/lib/samba3/ldb_samba3.c @@ -28,74 +28,190 @@ #include "ldb/include/ldb_private.h" /* - * sambaGroupMapping -> group * gidNumber -> ??? * sambaSID -> member - * sambaGroupType -> groupType - * displayName -> name - * description -> description * sambaSIDList -> member (special!) */ -/* - * sambaTrustPassword - */ +/* sambaTrustPassword */ -/* sambaDomain - * sambaDomainName - * sambaSID - * sambaNextRid - * sambaNextGroupRid - * sambaNextUserRid - * sambaAlgorithmicRidBase - */ +/* sambaDomainName -> name */ -/* sambaUnixIdPool - */ +/* sambaUnixIdPool */ /* sambaIdmapEntry */ -/* sambaAccountPolicy */ +/* sambaAccountPolicy: FIXME */ /* sambaSidEntry: FIXME */ -/* sambaSamAccount -> user: - * uid -> unixName (magic!) - * sambaSID -> objectSid - * cn -> cn - * sambaLMPassword -> lmPwdHash - * sambaNTPassword -> ntPwdHash - * sambaPwdLastSet -> pwdLastSet - * sambaLogonTime -> lastLogon - * sambaLogoffTime -> lastLogoff - * sambaKickoffTime -> ??? - * sambaPwdCanChange -> ??? - * sambaPwdMustChange -> ??? - * sambaAcctFlags -> systemFlags ? - * displayName -> name - * sambaHomePath -> ??? - * sambaHomeDrive -> ??? - * sambaLogonScript -> ??? - * sambaProfilePath -> ??? - * description -> description - * sambaUserWorkstations -> ??? - * sambaPrimaryGroupSID -> primaryGroupID - * sambaDomainName -> ??? - * sambaMungedDial -> ??? - * sambaBadPasswordCount -> badPwdcount - * sambaBadPasswordTime -> badPasswordtime - * sambaPasswordHistory -> ntPwdHistory - * sambaLogonHours -> ??? - */ - /* Not necessary: * sambaConfig * sambaShare * sambaConfigOption + * sambaNextGroupRid + * sambaNextUserRid + * sambaAlgorithmicRidBase */ - -struct ldb_map_mappings samba3_mappings; +/* sambaKickoffTime -> ???*/ +/* sambaPwdCanChange -> ???*/ +/* sambaPwdMustChange -> ???*/ +/* sambaAcctFlags -> systemFlags ?*/ +/* sambaHomePath -> ???*/ +/* sambaHomeDrive -> ???*/ +/* sambaLogonScript -> ???*/ +/* sambaProfilePath -> ???*/ +/* sambaUserWorkstations -> ???*/ +/* sambaDomainName -> ???*/ +/* sambaMungedDial -> ???*/ +/* sambaPasswordHistory -> ntPwdHistory*/ +/* sambaLogonHours -> ???*/ + +/* sambaNextRid -> nextRid */ +const struct ldb_map_attribute attr_nextRid = { + .local_name = "nextRid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNextRid", +}; + +/* sambaBadPasswordTime -> badPasswordtime*/ +const struct ldb_map_attribute attr_badPasswordTime = { + .local_name = "badPasswordTime", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordTime", +}; + +/* sambaLMPassword -> lmPwdHash*/ +const struct ldb_map_attribute attr_lmPwdHash = { + .local_name = "lmPwdHash", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLMPassword", +}; + +/* sambaGroupType -> groupType */ +const struct ldb_map_attribute attr_groupType = { + .local_name = "groupType", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaGroupType", +}; + +/* sambaNTPassword -> ntPwdHash*/ +const struct ldb_map_attribute attr_ntPwdHash = { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNTPassword", +}; + +/* sambaPrimaryGroupSID -> primaryGroupID */ +const struct ldb_map_attribute attr_primaryGroupID = { + .local_name = "primaryGroupID", + .type = MAP_CONVERT, + .u.convert.remote_name = "sambaPrimaryGroupSID", + .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ + .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ +}; + +/* sambaBadPasswordCount -> badPwdCount */ +const struct ldb_map_attribute attr_badPwdCount = { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordCount", +}; + +/* sambaLogonTime -> lastLogon*/ +const struct ldb_map_attribute attr_lastLogon = { + .local_name = "lastLogon", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogonTime", +}; + +/* sambaLogoffTime -> lastLogoff*/ +const struct ldb_map_attribute attr_lastLogoff = { + .local_name = "lastLogoff", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogoffTime", +}; + +/* gidNumber -> unixName */ +const struct ldb_map_attribute attr_unixName_gid = { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "gidNumber", + .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ +}; + +/* uid -> unixName */ +const struct ldb_map_attribute attr_unixName_uid = { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "uid", + .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ +}; + +/* displayName -> name */ +const struct ldb_map_attribute attr_name = { + .local_name = "name", + .type = MAP_RENAME, + .u.rename.remote_name = "displayName", +}; + +/* cn */ +const struct ldb_map_attribute attr_cn = { + .local_name = "cn", + .type = MAP_KEEP, +}; + +/* description */ +const struct ldb_map_attribute attr_description = { + .local_name = "description", + .type = MAP_KEEP, +}; + +/* sambaSID -> objectSid*/ +const struct ldb_map_attribute attr_objectSid = { + .local_name = "objectSid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaSID", +}; + +/* sambaPwdLastSet -> pwdLastSet*/ +const struct ldb_map_attribute attr_pwdLastSet = { + .local_name = "pwdLastSet", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaPwdLastSet", +}; + +const struct ldb_map_objectclass samba3_objectclasses[] = { + { "group", "sambaGroupMapping" }, + { "user", "sambaSAMAccount" }, + { "domain", "sambaDomain" }, +}; + +const struct ldb_map_mappings samba3_mappings = +{ + .name = "samba3", + { + &attr_objectSid, + &attr_pwdLastSet, + &attr_description, + &attr_cn, + &attr_unixName_uid, + &attr_unixName_gid, + &attr_name, + &attr_lastLogoff, + &attr_lastLogon, + &attr_primaryGroupID, + &attr_badPwdCount, + &attr_ntPwdHash, + &attr_lmPwdHash, + &attr_groupType, + &attr_badPasswordTime, + &attr_nextRid, + } +}; /* the init function */ #ifdef HAVE_DLOPEN_DISABLED -- cgit From 69fb6840637e07318914d632571c8481f3573461 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 25 Aug 2005 19:02:03 +0000 Subject: r9621: Bunch of bug fixes. Add 'format' option to samba3dump (text,summary,ldif) (This used to be commit dc6aab8d4a6d0fe47756c90d3d311b6009d571ff) --- source4/lib/ldb/include/ldb.h | 3 +- source4/lib/samba3/group.c | 12 ++-- source4/lib/samba3/idmap.c | 8 --- source4/lib/samba3/ldb_samba3.c | 52 ++++++--------- source4/lib/samba3/policy.c | 19 +----- source4/lib/samba3/registry.c | 9 ++- source4/lib/samba3/samba3.c | 17 +++-- source4/lib/samba3/samba3dump.c | 144 ++++++++++++++++++++++++++++++++++++++-- source4/lib/samba3/secrets.c | 7 ++ source4/lib/samba3/winsdb.c | 2 +- 10 files changed, 193 insertions(+), 80 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 89e88fd4e9..46b359b8ba 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -162,8 +162,7 @@ struct ldb_debug_ops { #define PRINTF_ATTRIBUTE(a,b) #endif - -/* structues for ldb_parse_tree handling code */ +/* structures for ldb_parse_tree handling code */ enum ldb_parse_op { LDB_OP_AND=1, LDB_OP_OR=2, LDB_OP_NOT=3, LDB_OP_EQUALITY=4, LDB_OP_SUBSTRING=5, LDB_OP_GREATER=6, LDB_OP_LESS=7, LDB_OP_PRESENT=8, diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index fc8f8c40b8..68ac5987d0 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -46,8 +46,9 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g int32_t vers_id; TDB_DATA kbuf, dbuf, newkey; int ret; - - TDB_CONTEXT *tdb = tdb_open(file, 0, TDB_DEFAULT, O_RDONLY, 0600); + TDB_CONTEXT *tdb; + + tdb = tdb_open(file, 0, TDB_DEFAULT, O_RDONLY, 0600); if (!tdb) { DEBUG(0,("Failed to open group mapping database\n")); return NT_STATUS_UNSUCCESSFUL; @@ -61,6 +62,7 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g } if (vers_id != DATABASE_VERSION_V2) { + DEBUG(0, ("Group database version mismatch: %d\n", vers_id)); return NT_STATUS_UNSUCCESSFUL; } @@ -80,19 +82,17 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g if (!dbuf.dptr) continue; - map.sid = dom_sid_parse_talloc(tdb, kbuf.dptr+strlen(GROUP_PREFIX)); + map.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(GROUP_PREFIX)); ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); - SAFE_FREE(dbuf.dptr); - if ( ret == -1 ) { DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); continue; } - db->groupmappings = talloc_realloc(tdb, db->groupmappings, struct samba3_groupmapping, db->groupmap_count+1); + db->groupmappings = talloc_realloc(ctx, db->groupmappings, struct samba3_groupmapping, db->groupmap_count+1); if (!db->groupmappings) return NT_STATUS_NO_MEMORY; diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index 1583ad4476..ce3d098d3a 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -41,7 +41,6 @@ NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmapdb *idmap ) { - int32_t version; TDB_CONTEXT *tdb; TDB_DATA key, val; @@ -51,13 +50,6 @@ NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmap return NT_STATUS_UNSUCCESSFUL; } - /* check against earlier versions */ - version = tdb_fetch_int32(tdb, "IDMAP_VERSION"); - if (version != IDMAP_VERSION) { - DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } - idmap->mapping_count = 0; idmap->mappings = NULL; idmap->user_hwm = tdb_fetch_int32(tdb, HWM_USER); diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c index 53d8964d0d..4cfdd3db75 100644 --- a/source4/lib/samba3/ldb_samba3.c +++ b/source4/lib/samba3/ldb_samba3.c @@ -27,23 +27,17 @@ #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -/* - * gidNumber -> ??? - * sambaSID -> member - * sambaSIDList -> member (special!) - */ - -/* sambaTrustPassword */ - -/* sambaDomainName -> name */ - -/* sambaUnixIdPool */ - -/* sambaIdmapEntry */ - -/* sambaAccountPolicy: FIXME */ - -/* sambaSidEntry: FIXME */ +/* FIXME: + * sambaSID -> member + * sambaSIDList -> member (special!) + * sambaDomainName -> name + * sambaTrustPassword + * sambaUnixIdPool + * sambaIdmapEntry + * sambaAccountPolicy + * sambaSidEntry + * sambaAcctFlags -> systemFlags ? + * sambaPasswordHistory -> ntPwdHistory*/ /* Not necessary: * sambaConfig @@ -54,19 +48,17 @@ * sambaAlgorithmicRidBase */ -/* sambaKickoffTime -> ???*/ -/* sambaPwdCanChange -> ???*/ -/* sambaPwdMustChange -> ???*/ -/* sambaAcctFlags -> systemFlags ?*/ -/* sambaHomePath -> ???*/ -/* sambaHomeDrive -> ???*/ -/* sambaLogonScript -> ???*/ -/* sambaProfilePath -> ???*/ -/* sambaUserWorkstations -> ???*/ -/* sambaDomainName -> ???*/ -/* sambaMungedDial -> ???*/ -/* sambaPasswordHistory -> ntPwdHistory*/ -/* sambaLogonHours -> ???*/ +/* Not in Samba4: + * sambaKickoffTime + * sambaPwdCanChange + * sambaPwdMustChange + * sambaHomePath + * sambaHomeDrive + * sambaLogonScript + * sambaProfilePath + * sambaUserWorkstations + * sambaMungedDial + * sambaLogonHours */ /* sambaNextRid -> nextRid */ const struct ldb_map_attribute attr_nextRid = { diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c index bec3eb7d93..cfe6284fc4 100644 --- a/source4/lib/samba3/policy.c +++ b/source4/lib/samba3/policy.c @@ -1,8 +1,7 @@ /* * Unix SMB/CIFS implementation. * account policy storage - * Copyright (C) Jean François Micouleau 1998-2001. - * Copyright (C) Andrew Bartlett 2002 + * Copyright (C) Jelmer Vernooij 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 @@ -24,30 +23,14 @@ #include "lib/samba3/samba3.h" #include "system/filesys.h" -#define DATABASE_VERSION 2 - -/**************************************************************************** - Open the account policy tdb. -****************************************************************************/ - NTSTATUS samba3_read_account_policy(const char *fn, TALLOC_CTX *ctx, struct samba3_policy *ret) { - const char *vstring = "INFO/version"; - uint32_t version; - TDB_CONTEXT *tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600); if (!tdb) { DEBUG(0,("Failed to open account policy database\n")); return NT_STATUS_UNSUCCESSFUL; } - /* handle a Samba upgrade */ - if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { - tdb_store_uint32(tdb, vstring, DATABASE_VERSION); - } - - ret = talloc_zero(ctx, struct samba3_policy); - tdb_fetch_uint32(tdb, "min password length", &ret->min_password_length); tdb_fetch_uint32(tdb, "password history", &ret->password_history); tdb_fetch_uint32(tdb, "user must logon to change pasword", &ret->user_must_logon_to_change_password); diff --git a/source4/lib/samba3/registry.c b/source4/lib/samba3/registry.c index 82a08c9088..5f00a944e6 100644 --- a/source4/lib/samba3/registry.c +++ b/source4/lib/samba3/registry.c @@ -88,6 +88,7 @@ NTSTATUS samba3_read_regdb ( const char *fn, TALLOC_CTX *ctx, struct samba3_regd if ( !(tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0600)) ) { + DEBUG(0, ("Unable to open registry database %s\n", fn)); return NT_STATUS_UNSUCCESSFUL; } @@ -96,8 +97,10 @@ NTSTATUS samba3_read_regdb ( const char *fn, TALLOC_CTX *ctx, struct samba3_regd db->key_count = 0; db->keys = NULL; - if (vers_id > REGVER_V1) + if (vers_id != -1 && vers_id >= REGVER_V1) { + DEBUG(0, ("Registry version mismatch: %d\n", vers_id)); return NT_STATUS_UNSUCCESSFUL; + } for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf)) { @@ -106,7 +109,7 @@ NTSTATUS samba3_read_regdb ( const char *fn, TALLOC_CTX *ctx, struct samba3_regd struct samba3_regkey key; char *skey; - if (strncmp(kbuf.dptr, VALUE_PREFIX, strlen(VALUE_PREFIX))) + if (strncmp(kbuf.dptr, VALUE_PREFIX, strlen(VALUE_PREFIX)) == 0) continue; vbuf = tdb_fetch(tdb, kbuf); @@ -134,7 +137,7 @@ NTSTATUS samba3_read_regdb ( const char *fn, TALLOC_CTX *ctx, struct samba3_regd } db->keys = talloc_realloc(ctx, db->keys, struct samba3_regkey, db->key_count+1); - db->keys[i] = key; + db->keys[db->key_count] = key; db->key_count++; } diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 4eda3bd154..f8ee24ee3b 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -85,14 +85,17 @@ NTSTATUS samba3_read_smbconf(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) return NT_STATUS_OK; } -struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) +NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, struct samba3 **samba3) { struct samba3 *ret; char *dbfile; - ret = talloc(ctx, struct samba3); - - asprintf(&dbfile, "%s/winsdb.dat", libdir); + ret = talloc_zero(ctx, struct samba3); + + if (smbconf) + samba3_read_smbconf(smbconf, ctx, ret); + + asprintf(&dbfile, "%s/wins.dat", libdir); samba3_read_winsdb(dbfile, ret, &ret->winsdb_entries, &ret->winsdb_count); SAFE_FREE(dbfile); @@ -100,7 +103,7 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) samba3_read_tdbsam(dbfile, ctx, &ret->samaccounts, &ret->samaccount_count); SAFE_FREE(dbfile); - asprintf(&dbfile, "%s/groupdb.tdb", libdir); + asprintf(&dbfile, "%s/group_mapping.tdb", libdir); samba3_read_grouptdb(dbfile, ctx, &ret->group); SAFE_FREE(dbfile); @@ -124,5 +127,7 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx) samba3_read_share_info(dbfile, ctx, ret); SAFE_FREE(dbfile); - return ret; + *samba3 = ret; + + return NT_STATUS_OK; } diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index 88d5cf9369..b00074be56 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -23,17 +23,36 @@ #include "lib/samba3/samba3.h" #include "lib/cmdline/popt_common.h" -static NTSTATUS print_policy(struct samba3_policy *ret) +static void print_header(const char *txt) { + int i; + printf("\n%s\n", txt); + for (i = 0; txt[i]; i++) putchar('='); + putchar('\n'); +} + +static NTSTATUS print_samba3_policy(struct samba3_policy *ret) +{ + print_header("Account Policies"); printf("Min password length: %d\n", ret->min_password_length); + printf("Password history length: %d\n", ret->password_history); + printf("User must logon to change password: %d\n", ret->user_must_logon_to_change_password); + printf("Maximum password age: %d\n", ret->maximum_password_age); + printf("Minimum password age: %d\n", ret->minimum_password_age); + printf("Lockout duration: %d\n", ret->lockout_duration); + printf("Reset Count Minutes: %d\n", ret->reset_count_minutes); + printf("Bad Lockout Minutes: %d\n", ret->bad_lockout_minutes); + printf("Disconnect Time: %d\n", ret->disconnect_time); + printf("Refuse Machine Password Change: %d\n", ret->refuse_machine_password_change); return NT_STATUS_OK; } -static NTSTATUS print_sam(struct samba3 *samba3) +static NTSTATUS print_samba3_sam(struct samba3 *samba3) { struct samba3_samaccount *accounts = samba3->samaccounts; uint32_t count = samba3->samaccount_count, i; + print_header("SAM Database"); for (i = 0; i < count; i++) { printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); @@ -41,15 +60,118 @@ static NTSTATUS print_sam(struct samba3 *samba3) return NT_STATUS_OK; } + +static NTSTATUS print_samba3_shares(struct samba3 *samba3) +{ + int i, j; + print_header("Configured shares"); + for (i = 0; i < samba3->share_count; i++) { + struct samba3_share_info *share = &samba3->shares[i]; + printf("--- %s ---\n", share->name); + + for (j = 0; j < share->parameter_count; j++) { + printf("\t%s = %s\n", share->parameters[j].name, share->parameters[j].value); + } + + printf("\n"); + } + + return NT_STATUS_OK; +} + +static NTSTATUS print_samba3_secrets(struct samba3_secrets *secrets) +{ + int i; + print_header("Secrets"); + + printf("IPC Credentials:\n"); + printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred)); + printf(" Password: %s\n", cli_credentials_get_password(secrets->ipc_cred)); + printf(" Domain: %s\n\n", cli_credentials_get_domain(secrets->ipc_cred)); + + printf("LDAP passwords:\n"); + for (i = 0; i < secrets->ldappw_count; i++) { + printf("\t%s -> %s\n", secrets->ldappws[i].dn, secrets->ldappws[i].password); + } + printf("\n"); + + printf("Domains:\n"); + for (i = 0; i < secrets->domain_count; i++) { + printf("\t--- %s ---\n", secrets->domains[i].name); + printf("\tSID: %s\n", dom_sid_string(NULL, &secrets->domains[i].sid)); + printf("\tGUID: %s\n", GUID_string(NULL, &secrets->domains[i].guid)); + printf("\tPlaintext pwd: %s\n", secrets->domains[i].plaintext_pw); + printf("\tLast Changed: %lu\n", secrets->domains[i].last_change_time); + printf("\tSecure Channel Type: %d\n\n", secrets->domains[i].sec_channel_type); + } + + printf("Trusted domains:\n"); + for (i = 0; i < secrets->trusted_domain_count; i++) { + int j; + for (j = 0; j < secrets->trusted_domains[i].uni_name_len; j++) { + printf("\t--- %s ---\n", secrets->trusted_domains[i].uni_name[j]); + } + printf("\tPassword: %s\n", secrets->trusted_domains[i].pass); + printf("\tModified: %lu\n", secrets->trusted_domains[i].mod_time); + printf("\tSID: %s\n", dom_sid_string(NULL, &secrets->trusted_domains[i].domain_sid)); + } + + return NT_STATUS_OK; +} + +static NTSTATUS print_samba3_regdb(struct samba3_regdb *regdb) +{ + int i; + print_header("Registry"); + + for (i = 0; i < regdb->key_count; i++) { + int j; + printf("%s\n", regdb->keys[i].name); + for (j = 0; j < regdb->keys[i].value_count; j++) { + printf("\t%s: type %d, length %d\n", + regdb->keys[i].values[j].name, + regdb->keys[i].values[j].type, + regdb->keys[i].values[j].data.length); + } + } + + return NT_STATUS_OK; +} + +static NTSTATUS print_samba3_winsdb(struct samba3 *samba3) +{ + int i; + print_header("WINS Database"); + + for (i = 0; i < samba3->winsdb_count; i++) { + printf("%s, nb_flags: %x, type: %d, ttl: %lu, %d ips\n", samba3->winsdb_entries[i].name, samba3->winsdb_entries[i].nb_flags, samba3->winsdb_entries[i].type, samba3->winsdb_entries[i].ttl, samba3->winsdb_entries[i].ip_count); + } + + return NT_STATUS_OK; +} + +static NTSTATUS print_samba3(struct samba3 *samba3) +{ + print_samba3_sam(samba3); + print_samba3_policy(&samba3->policy); + print_samba3_shares(samba3); + print_samba3_winsdb(samba3); + print_samba3_regdb(&samba3->registry); + print_samba3_secrets(&samba3->secrets); + + return NT_STATUS_OK; +} int main(int argc, char **argv) { int opt; + const char *format = "summary"; const char *libdir = "/var/lib/samba"; struct samba3 *samba3; poptContext pc; struct poptOption long_options[] = { POPT_AUTOHELP + { "format", 0, POPT_ARG_STRING, &format, 'f', "Format to use (one of: summary, text, ldif)" }, { "libdir", 0, POPT_ARG_STRING, &libdir, 'l', "Set libdir [/var/lib/samba]", "LIBDIR" }, POPT_COMMON_SAMBA POPT_TABLEEND @@ -62,11 +184,21 @@ int main(int argc, char **argv) while((opt = poptGetNextOpt(pc)) != -1) { } - samba3 = samba3_read(libdir, NULL); - - print_sam(samba3); - print_policy(&samba3->policy); + samba3_read(poptGetArg(pc), libdir, NULL, &samba3); + if (!strcmp(format, "summary")) { + printf("WINS db entries: %d\n", samba3->winsdb_count); + printf("SAM Accounts: %d\n", samba3->samaccount_count); + printf("Registry key count: %d\n", samba3->registry.key_count); + printf("Shares (including [global]): %d\n", samba3->share_count); + printf("Groupmap count: %d\n", samba3->group.groupmap_count); + printf("Alias count: %d\n", samba3->group.alias_count); + printf("Idmap count: %d\n", samba3->idmap.mapping_count); + } else if (!strcmp(format, "text")) { + print_samba3(samba3); + } else if (!strcmp(format, "ldif")) { + printf("FIXME\n"); + } poptFreeContext(pc); return 0; diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 6b629d1eff..25ab8f5db5 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -168,6 +168,12 @@ static NTSTATUS machine_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, T return NT_STATUS_OK; } +static NTSTATUS random_seed (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) +{ + /* Ignore */ + return NT_STATUS_OK; +} + static NTSTATUS domtrust_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db) { int idx, len = 0; @@ -213,6 +219,7 @@ static const struct { { "SECRETS/MACHINE_PASSWORD/", machine_password }, { "SECRETS/$MACHINE.ACC/", machine_acc }, { "SECRETS/$DOMTRUST.ACC/", domtrust_acc }, + { "INFO/random_seed", random_seed }, }; diff --git a/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c index 7c3253e101..c6ead1de39 100644 --- a/source4/lib/samba3/winsdb.c +++ b/source4/lib/samba3/winsdb.c @@ -34,7 +34,7 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins char *line; if((fp = x_fopen(fn,O_RDONLY,0)) == NULL) { - DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", + DEBUG(0,("initialise_wins: Can't open wins database file %s. Error was %s\n", fn, strerror(errno) )); return NT_STATUS_UNSUCCESSFUL; } -- cgit From c9d3763bfc92b7e99565065fb44b03c47f1f1a0d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 25 Aug 2005 22:29:55 +0000 Subject: r9623: samba3dump now generates LDIF for the registry hives from registry.tdb couple of other small fixes (This used to be commit 06bc5d8e0950dd85b6f26a1355fa0a2ae178d30f) --- source4/lib/samba3/PLAN | 5 +- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/samba3.h | 1 - source4/lib/samba3/samba3dump.c | 116 ++++++++++++++++++++++++++++++++++-- source4/lib/samba3/tdbsam.c | 74 +++++++++-------------- source4/lib/samba3/upgrade.c | 128 ++++++++++++++++++++++++++++++++++++++++ source4/lib/samba3/winsdb.c | 4 +- 7 files changed, 273 insertions(+), 58 deletions(-) create mode 100644 source4/lib/samba3/upgrade.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 6076141ac0..26bf54634c 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,9 +1,12 @@ Three possible viable approaches: 1) TDB conversion approach. Read in TDB dump out LDIF (one-way) - - samr.ldb: from tdbsam/smbpasswd, account_policy.tdb, secrets.tdb, group_mapping.tdb, idmap.tdb, privilege.tdb + - samr.ldb: from tdbsam/smbpasswd, account_policy.tdb, secrets.tdb, group_mapping.tdb, privilege.tdb - registry.ldb: from registry.tdb - wins.ldif: from wins.tdb/wins.dat - smb.conf/ea's: generated from the old smb.conf + share_info.tdb + - winbind.ldif: from winbindd_idmap.tdb (custom file format, not used + by samba4 yet as it doesn't + have Winbind yet) (one-way upgrades can be done by using ldbsearch -a on these dynamically generated ldb's) diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 79142e4f67..eba694c2af 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -12,7 +12,8 @@ ADD_OBJ_FILES = \ lib/samba3/registry.o \ lib/samba3/secrets.o \ lib/samba3/ldb_samba3.o \ - lib/samba3/share_info.o + lib/samba3/share_info.o \ + lib/samba3/upgrade.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index fe4db560a8..5aba790c4e 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -52,7 +52,6 @@ struct samba3_samaccount { }; struct samba3_groupmapping { - struct pdb_methods *methods; gid_t gid; struct dom_sid *sid; int sid_name_use; diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index b00074be56..a6166a1c6b 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -22,6 +22,7 @@ #include "includes.h" #include "lib/samba3/samba3.h" #include "lib/cmdline/popt_common.h" +#include "lib/ldb/include/ldb.h" static void print_header(const char *txt) { @@ -51,10 +52,10 @@ static NTSTATUS print_samba3_policy(struct samba3_policy *ret) static NTSTATUS print_samba3_sam(struct samba3 *samba3) { struct samba3_samaccount *accounts = samba3->samaccounts; - uint32_t count = samba3->samaccount_count, i; + uint32_t i; print_header("SAM Database"); - for (i = 0; i < count; i++) { + for (i = 0; i < samba3->samaccount_count; i++) { printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); } @@ -85,9 +86,13 @@ static NTSTATUS print_samba3_secrets(struct samba3_secrets *secrets) print_header("Secrets"); printf("IPC Credentials:\n"); - printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred)); - printf(" Password: %s\n", cli_credentials_get_password(secrets->ipc_cred)); - printf(" Domain: %s\n\n", cli_credentials_get_domain(secrets->ipc_cred)); + if (secrets->ipc_cred->username_obtained) + printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred)); + if (secrets->ipc_cred->password_obtained) + printf(" Password: %s\n", cli_credentials_get_password(secrets->ipc_cred)); + + if (secrets->ipc_cred->domain_obtained) + printf(" Domain: %s\n\n", cli_credentials_get_domain(secrets->ipc_cred)); printf("LDAP passwords:\n"); for (i = 0; i < secrets->ldappw_count; i++) { @@ -150,6 +155,50 @@ static NTSTATUS print_samba3_winsdb(struct samba3 *samba3) return NT_STATUS_OK; } +static NTSTATUS print_samba3_groupdb(struct samba3_groupdb *db) +{ + int i; + print_header("Group Mappings"); + + for (i = 0; i < db->groupmap_count; i++) + { + printf("\t--- Group: %s ---\n", db->groupmappings[i].nt_name); + printf("\tComment: %s\n", db->groupmappings[i].comment); + printf("\tGID: %d\n", db->groupmappings[i].gid); + printf("\tSID Name Use: %d\n", db->groupmappings[i].sid_name_use); + printf("\tSID: %s\n\n", dom_sid_string(NULL, db->groupmappings[i].sid)); + } + + for (i = 0; i < db->alias_count; i++) + { + int j; + printf("\t--- Alias: %s ---\n", dom_sid_string(NULL, db->aliases[i].sid)); + for (j = 0; j < db->aliases[i].member_count; j++) { + printf("\t%s\n", dom_sid_string(NULL,db->aliases[i].members[j])); + } + } + + return NT_STATUS_OK; +} + +static NTSTATUS print_samba3_idmapdb(struct samba3_idmapdb *db) +{ + int i; + print_header("Winbindd SID<->GID/UID mappings"); + + printf("User High Water Mark: %d\n", db->user_hwm); + printf("Group High Water Mark: %d\n\n", db->group_hwm); + + for (i = 0; i < db->mapping_count; i++) { + printf("%s -> %cID %d", + dom_sid_string(NULL, db->mappings[i].sid), + (db->mappings[i].type == IDMAP_GROUP)?'G':'U', + db->mappings[i].unix_id); + } + + return NT_STATUS_OK; +} + static NTSTATUS print_samba3(struct samba3 *samba3) { print_samba3_sam(samba3); @@ -158,9 +207,38 @@ static NTSTATUS print_samba3(struct samba3 *samba3) print_samba3_winsdb(samba3); print_samba3_regdb(&samba3->registry); print_samba3_secrets(&samba3->secrets); + print_samba3_groupdb(&samba3->group); + print_samba3_idmapdb(&samba3->idmap); return NT_STATUS_OK; } + +static BOOL write_ldif(const char *fn, struct ldb_message **messages, int count) +{ + FILE *f = fopen(fn, "w+"); + struct ldb_ldif ldif; + int i; + struct ldb_context *ldb = ldb_init(NULL); + + if (!f) { + DEBUG(0, ("Unable to open LDIF file '%s'\n", fn)); + talloc_free(ldb); + return False; + } + + for (i = 0; i < count; i++) { + ldif.changetype = LDB_CHANGETYPE_ADD; + ldif.msg = messages[i]; + + ldb_ldif_write_file(ldb, f, &ldif); + } + + talloc_free(ldb); + + fclose(f); + + return True; +} int main(int argc, char **argv) { @@ -197,7 +275,33 @@ int main(int argc, char **argv) } else if (!strcmp(format, "text")) { print_samba3(samba3); } else if (!strcmp(format, "ldif")) { - printf("FIXME\n"); + struct ldb_message **msgs; + struct ldb_context *ldb = ldb_init(NULL); + int i, ret; + const char *hives[] = { "hklm", "hkcr", "hku", "hkpd", "hkpt", NULL }; + + for (i = 0; hives[i]; i++) { + char *fn; + + ret = samba3_upgrade_registry(&samba3->registry, hives[i], ldb, &msgs); + + printf("Writing %s.ldif\n", hives[i]); + asprintf(&fn, "%s.ldif", hives[i]); + write_ldif(fn, msgs, ret); + SAFE_FREE(fn); + } + + ret = samba3_upgrade_sam(samba3, ldb, &msgs); + printf("Writing sam.ldif\n"); + write_ldif("sam.ldif", msgs, ret); + + ret = samba3_upgrade_winsdb(samba3, ldb, &msgs); + printf("Writing wins.ldif\n"); + write_ldif("wins.ldif", msgs, ret); + + ret = samba3_upgrade_winbind(samba3, ldb, &msgs); + printf("Writing winbind.ldif\n"); + write_ldif("winbind.ldif", msgs, ret); } poptFreeContext(pc); diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index 577b663381..23e68717c7 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -2,11 +2,7 @@ Unix SMB/CIFS implementation. tdb passdb backend format routines - Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Simo Sorce 2000-2003 - Copyright (C) Gerald Carter 2000 - Copyright (C) Jeremy Allison 2001 - Copyright (C) Andrew Bartlett 2002 Copyright (C) Jelmer Vernooij 2005 This program is free software; you can redistribute it and/or modify @@ -35,41 +31,6 @@ #define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" #define TDBSAM_VERSION_STRING "INFO/version" -/** - * Open the TDB passwd database, check version and convert it if needed. - * @param name filename of the tdbsam file. - * @param version version of the tdbsam database - * @return a TDB_CONTEXT handle on the tdbsam file. - **/ - -static TDB_CONTEXT *tdbsam_open (const char *name, int32_t *version) -{ - TDB_CONTEXT *pdb_tdb; - - /* Try to open tdb passwd */ - if (!(pdb_tdb = tdb_open(name, 0, TDB_DEFAULT, - O_RDONLY, 0600))) { - DEBUG(0, ("Unable to open TDB passwd\n")); - return NULL; - } - - /* Check the version */ - *version = tdb_fetch_int32(pdb_tdb, - TDBSAM_VERSION_STRING); - if (*version == -1) - *version = 0; /* Version not found, assume version 0 */ - - /* Compare the version */ - if (*version > 2) { - /* Version more recent than the latest known */ - DEBUG(0, ("TDBSAM version unknown: %d\n", *version)); - tdb_close(pdb_tdb); - pdb_tdb = NULL; - } - - return pdb_tdb; -} - static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf) { uint32_t username_len, domain_len, nt_username_len, @@ -269,22 +230,37 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * NTSTATUS samba3_read_tdbsam(const char *filename, TALLOC_CTX *ctx, struct samba3_samaccount **accounts, uint32_t *count) { int32_t version; - TDB_CONTEXT *tdb = tdbsam_open(filename, &version); + TDB_CONTEXT *tdb; TDB_DATA key, val; - if (tdb == NULL) + /* Try to open tdb passwd */ + if (!(tdb = tdb_open(filename, 0, TDB_DEFAULT, O_RDONLY, 0600))) { + DEBUG(0, ("Unable to open TDB passwd file '%s'\n", filename)); return NT_STATUS_UNSUCCESSFUL; + } - if (version < 0 || version > 2) { + /* Check the version */ + version = tdb_fetch_int32(tdb, + TDBSAM_VERSION_STRING); + if (version == -1) + version = 0; /* Version not found, assume version 0 */ + + /* Compare the version */ + if (version > 2) { + /* Version more recent than the latest known */ + DEBUG(0, ("TDBSAM version unknown: %d\n", version)); + tdb_close(tdb); return NT_STATUS_NOT_SUPPORTED; - } + } *accounts = NULL; *count = 0; for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) { - if (strncmp(key.dptr, "RID/", 4) == 0) continue; + BOOL ret; + if (strncmp(key.dptr, "USER_", 5) != 0) + continue; val = tdb_fetch(tdb, key); @@ -292,10 +268,14 @@ NTSTATUS samba3_read_tdbsam(const char *filename, TALLOC_CTX *ctx, struct samba3 switch (version) { - case 0: init_sam_from_buffer_v0(tdb, &(*accounts)[*count], val); break; - case 1: init_sam_from_buffer_v1(tdb, &(*accounts)[*count], val); break; - case 2: init_sam_from_buffer_v2(tdb, &(*accounts)[*count], val); break; + case 0: ret = init_sam_from_buffer_v0(tdb, &(*accounts)[*count], val); break; + case 1: ret = init_sam_from_buffer_v1(tdb, &(*accounts)[*count], val); break; + case 2: ret = init_sam_from_buffer_v2(tdb, &(*accounts)[*count], val); break; + + } + if (!ret) { + DEBUG(0, ("Unable to parse SAM account %s\n", key.dptr)); } (*count)++; diff --git a/source4/lib/samba3/upgrade.c b/source4/lib/samba3/upgrade.c new file mode 100644 index 0000000000..907df75c2e --- /dev/null +++ b/source4/lib/samba3/upgrade.c @@ -0,0 +1,128 @@ +/* + Unix SMB/CIFS implementation. + Generate ldb_message 's for samba3_* + + Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/samba3/samba3.h" +#include "lib/ldb/include/ldb.h" + +static struct ldb_message *msg_array_add(struct ldb_context *ctx, struct ldb_message ***msgs, int *count) +{ + struct ldb_message *ret; + *msgs = talloc_realloc(ctx, *msgs, struct ldb_message *, (*count)+1); + + ret = (*msgs)[*count] = talloc_zero(ctx, struct ldb_message); + (*count)++; + + return ret; +} + +static struct ldb_dn *regkey_to_dn(struct ldb_context *ldb, const char *name) +{ + char *p, *n, *dup; + struct ldb_dn *ret = ldb_dn_explode(ldb, "hive=NONE"); + + p = dup = talloc_strdup(ldb, name); + + while (p) { + n = strchr(p, '/'); + if (n) { *n = '\0'; n++; } + + ret = ldb_dn_build_child(ldb, "key", p, ret); + + p = n; + } + + talloc_free(dup); + + return ret; +} + +/* Where prefix is any of: + * - HKLM + * HKU + * HKCR + * HKPD + * HKPT + */ + +int samba3_upgrade_registry(struct samba3_regdb *regdb, const char *prefix, struct ldb_context *ldb, struct ldb_message ***msgs) +{ + int i; + struct ldb_message *msg; + int count = 0; + char *prefix_up = strupper_talloc(ldb, prefix); + *msgs = NULL; + + for (i = 0; i < regdb->key_count; i++) { + int j; + struct samba3_regkey *rk = ®db->keys[i]; + struct ldb_dn *keydn; + + /* Only handle selected hive */ + if (strncmp(prefix_up, rk->name, strlen(prefix_up)) != 0) { + continue; + } + + msg = msg_array_add(ldb, msgs, &count); + + msg->num_elements = 0; + msg->elements = NULL; + msg->private_data = NULL; + + /* Convert key name to dn */ + keydn = msg->dn = regkey_to_dn(ldb, rk->name); + + ldb_msg_add_string(ldb, msg, "name", strrchr(rk->name, '/')?strrchr(rk->name, '/')+1:rk->name); + + for (j = 0; j < rk->value_count; j++) { + struct samba3_regval *rv = &rk->values[j]; + + msg = msg_array_add(ldb, msgs, &count); + msg->dn = ldb_dn_build_child(ldb, "value", rv->name, keydn); + + ldb_msg_add_string(ldb, msg, "value", rv->name); + ldb_msg_add_fmt(ldb, msg, "type", "%d", rv->type); + ldb_msg_add_value(ldb, msg, "data", &rv->data); + } + } + + talloc_free(prefix_up); + + return count; +} + +int samba3_upgrade_sam(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +{ + /* FIXME */ + return -1; +} + +int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +{ + /* FIXME */ + return -1; +} + +int samba3_upgrade_winsdb(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +{ + /* FIXME */ + return -1; +} diff --git a/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c index c6ead1de39..f543ebd3f0 100644 --- a/source4/lib/samba3/winsdb.c +++ b/source4/lib/samba3/winsdb.c @@ -55,7 +55,7 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins /* Read a line from the wins.dat file. Strips whitespace from the beginning and end of the line. */ - line = fgets_slash(NULL,-1,fp); + line = fgets_slash(NULL,8,fp); if (!line) return NT_STATUS_UNSUCCESSFUL; @@ -169,7 +169,7 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins entry.ttl = atol(ttl_str); *entries = talloc_realloc(ctx, *entries, struct samba3_winsdb_entry, (*count)+1); - *entries[*count] = entry; + (*entries)[*count] = entry; (*count)++; } -- cgit From a16c390fe07cb5908b042cc88b0928a92d8326b6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 25 Aug 2005 22:57:56 +0000 Subject: r9624: Support writing wins.ldif (This used to be commit b0595d238bbcc4a3927914d1fd6032e9293da5cc) --- source4/lib/samba3/upgrade.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/upgrade.c b/source4/lib/samba3/upgrade.c index 907df75c2e..941b0fe196 100644 --- a/source4/lib/samba3/upgrade.c +++ b/source4/lib/samba3/upgrade.c @@ -121,8 +121,29 @@ int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ctx, struc return -1; } -int samba3_upgrade_winsdb(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +int samba3_upgrade_winsdb(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) { - /* FIXME */ - return -1; + int i; + int count = 0; + + for (i = 0; i < samba3->winsdb_count; i++) { + struct samba3_winsdb_entry *e = &samba3->winsdb_entries[i]; + int j; + struct ldb_message *msg = msg_array_add(ldb, msgs, &count); + + msg->dn = ldb_dn_string_compose(ldb, NULL, "type=%d,name=%s", e->type, e->name); + + ldb_msg_add_string(ldb, msg, "name", e->name); + ldb_msg_add_fmt(ldb, msg, "type", "%d", e->type); + ldb_msg_add_string(ldb, msg, "objectClass", "wins"); + ldb_msg_add_fmt(ldb, msg, "nbFlags", "%x", e->nb_flags); + ldb_msg_add_string(ldb, msg, "expires", + ldap_timestring(msg, e->ttl)); + + for (j = 0; j < e->ip_count; j++) { + ldb_msg_add_string(ldb, msg, "address", sys_inet_ntoa(e->ips[j])); + } + } + + return count; } -- cgit From a45c4fd5e24c8ae50bd86c6c84d1a3278e1bdab6 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 25 Aug 2005 23:05:41 +0000 Subject: r9625: Get rid of "duplicate const" warning. (This used to be commit 0ec755cfa0499bf1f271584db3c028d87973f1af) --- source4/lib/ldb/include/ldb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 46b359b8ba..66b0343891 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -268,7 +268,7 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co use talloc_free to free the ldb_message returned */ int ldb_search(struct ldb_context *ldb, - const const struct ldb_dn *base, + const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res); -- cgit From 7fd36b79ebaff8821b3786725510b0d428631a0a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 27 Aug 2005 01:42:20 +0000 Subject: r9671: patch from Kai Blin fixing a bug in our base64 encoder (This used to be commit efa143cb3b4815fed7b037e05d591eadb828536b) --- source4/lib/ldb/common/ldb_ldif.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 6359c9a014..38866d7031 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -155,10 +155,10 @@ char *ldb_base64_encode(void *mem_ctx, const char *buf, int len) const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; const uint8_t *d = (const uint8_t *)buf; - int bytes = (len*8 + 5)/6; + int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0; char *out; - out = talloc_array(mem_ctx, char, bytes+2); + out = talloc_array(mem_ctx, char, bytes+pad_bytes+1); if (!out) return NULL; for (i=0;i Date: Sat, 27 Aug 2005 02:10:28 +0000 Subject: r9672: Fix build for compilers that don't like undefined-length arrays at the end of structs... (This used to be commit c2211df586337ff68bb805801959147065040c01) --- source4/lib/ldb/ldb_map/ldb_map.c | 24 ++-- source4/lib/ldb/ldb_map/ldb_map.h | 11 +- source4/lib/samba3/ldb_samba3.c | 244 ++++++++++++++++++-------------------- 3 files changed, 128 insertions(+), 151 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 4006ccbbd7..dea3c24e37 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -34,7 +34,8 @@ */ struct map_private { - const struct ldb_map_mappings *mappings; + const struct ldb_map_attribute *attribute_maps; + const struct ldb_map_objectclass *objectclass_maps; const char *last_err_string; }; @@ -43,9 +44,9 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_module *mo { struct map_private *privdat = module->private_data; int i; - for (i = 0; privdat->mappings->attribute_maps[i]; i++) { - if (!strcmp(privdat->mappings->attribute_maps[i]->local_name, attr)) - return privdat->mappings->attribute_maps[i]; + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (!strcmp(privdat->attribute_maps[i].local_name, attr)) + return &privdat->attribute_maps[i]; } return NULL; @@ -56,13 +57,13 @@ static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_module *m { struct map_private *privdat = module->private_data; int i; - for (i = 0; privdat->mappings->attribute_maps[i]; i++) { - if (privdat->mappings->attribute_maps[i]->type != MAP_RENAME && - privdat->mappings->attribute_maps[i]->type != MAP_CONVERT) + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (privdat->attribute_maps[i].type != MAP_RENAME && + privdat->attribute_maps[i].type != MAP_CONVERT) continue; - if (!strcmp(privdat->mappings->attribute_maps[i]->u.rename.remote_name, attr)) - return privdat->mappings->attribute_maps[i]; + if (!strcmp(privdat->attribute_maps[i].u.rename.remote_name, attr)) + return &privdat->attribute_maps[i]; } return NULL; @@ -573,7 +574,7 @@ static const struct ldb_module_ops map_ops = { }; /* the init function */ -struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_mappings *mappings, const char *options[]) +struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *options[]) { struct ldb_module *ctx; struct map_private *data; @@ -588,7 +589,8 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_ma return NULL; } - data->mappings = mappings; + data->attribute_maps = attrs; + data->objectclass_maps = ocls; ctx->private_data = data; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h index da3198429d..bdeafc827a 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -90,7 +90,8 @@ struct ldb_map_attribute /* Name(s) for this attribute on the remote server. This is an array since * one local attribute's data can be split up into several attributes * remotely */ - const char *remote_names[]; +#define LDB_MAP_MAX_REMOTE_NAMES 10 + const char *remote_names[LDB_MAP_MAX_REMOTE_NAMES]; } generate; } u; }; @@ -101,12 +102,4 @@ struct ldb_map_objectclass const char *remote_name; }; -/* Base ldb_map struct. Fill this in to create a mapping backend */ -struct ldb_map_mappings -{ - const char *name; - const struct ldb_map_attribute *attribute_maps[]; -}; - - #endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c index 4cfdd3db75..68f5412c90 100644 --- a/source4/lib/samba3/ldb_samba3.c +++ b/source4/lib/samba3/ldb_samba3.c @@ -60,157 +60,139 @@ * sambaMungedDial * sambaLogonHours */ -/* sambaNextRid -> nextRid */ -const struct ldb_map_attribute attr_nextRid = { - .local_name = "nextRid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNextRid", -}; - -/* sambaBadPasswordTime -> badPasswordtime*/ -const struct ldb_map_attribute attr_badPasswordTime = { - .local_name = "badPasswordTime", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordTime", -}; -/* sambaLMPassword -> lmPwdHash*/ -const struct ldb_map_attribute attr_lmPwdHash = { - .local_name = "lmPwdHash", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLMPassword", -}; -/* sambaGroupType -> groupType */ -const struct ldb_map_attribute attr_groupType = { - .local_name = "groupType", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaGroupType", +const struct ldb_map_objectclass samba3_objectclasses[] = { + { "group", "sambaGroupMapping" }, + { "user", "sambaSAMAccount" }, + { "domain", "sambaDomain" }, }; -/* sambaNTPassword -> ntPwdHash*/ -const struct ldb_map_attribute attr_ntPwdHash = { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNTPassword", -}; +const struct ldb_map_attribute samba3_attributes[] = +{ + /* sambaNextRid -> nextRid */ + { + .local_name = "nextRid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNextRid", + }, -/* sambaPrimaryGroupSID -> primaryGroupID */ -const struct ldb_map_attribute attr_primaryGroupID = { - .local_name = "primaryGroupID", - .type = MAP_CONVERT, - .u.convert.remote_name = "sambaPrimaryGroupSID", - .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ - .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ -}; + /* sambaBadPasswordTime -> badPasswordtime*/ + { + .local_name = "badPasswordTime", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordTime", + }, -/* sambaBadPasswordCount -> badPwdCount */ -const struct ldb_map_attribute attr_badPwdCount = { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordCount", -}; + /* sambaLMPassword -> lmPwdHash*/ + { + .local_name = "lmPwdHash", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLMPassword", + }, -/* sambaLogonTime -> lastLogon*/ -const struct ldb_map_attribute attr_lastLogon = { - .local_name = "lastLogon", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogonTime", -}; + /* sambaGroupType -> groupType */ + { + .local_name = "groupType", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaGroupType", + }, -/* sambaLogoffTime -> lastLogoff*/ -const struct ldb_map_attribute attr_lastLogoff = { - .local_name = "lastLogoff", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogoffTime", -}; + /* sambaNTPassword -> ntPwdHash*/ + { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNTPassword", + }, -/* gidNumber -> unixName */ -const struct ldb_map_attribute attr_unixName_gid = { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "gidNumber", - .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ -}; + /* sambaPrimaryGroupSID -> primaryGroupID */ + { + .local_name = "primaryGroupID", + .type = MAP_CONVERT, + .u.convert.remote_name = "sambaPrimaryGroupSID", + .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ + .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ + }, + + /* sambaBadPasswordCount -> badPwdCount */ + { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordCount", + }, -/* uid -> unixName */ -const struct ldb_map_attribute attr_unixName_uid = { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "uid", - .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ -}; + /* sambaLogonTime -> lastLogon*/ + { + .local_name = "lastLogon", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogonTime", + }, -/* displayName -> name */ -const struct ldb_map_attribute attr_name = { - .local_name = "name", - .type = MAP_RENAME, - .u.rename.remote_name = "displayName", -}; + /* sambaLogoffTime -> lastLogoff*/ + { + .local_name = "lastLogoff", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogoffTime", + }, -/* cn */ -const struct ldb_map_attribute attr_cn = { - .local_name = "cn", - .type = MAP_KEEP, -}; + /* gidNumber -> unixName */ + { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "gidNumber", + .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ + }, + + /* uid -> unixName */ + { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "uid", + .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ + }, + + /* displayName -> name */ + { + .local_name = "name", + .type = MAP_RENAME, + .u.rename.remote_name = "displayName", + }, -/* description */ -const struct ldb_map_attribute attr_description = { - .local_name = "description", - .type = MAP_KEEP, -}; + /* cn */ + { + .local_name = "cn", + .type = MAP_KEEP, + }, -/* sambaSID -> objectSid*/ -const struct ldb_map_attribute attr_objectSid = { - .local_name = "objectSid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaSID", -}; + /* description */ + { + .local_name = "description", + .type = MAP_KEEP, + }, -/* sambaPwdLastSet -> pwdLastSet*/ -const struct ldb_map_attribute attr_pwdLastSet = { - .local_name = "pwdLastSet", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaPwdLastSet", -}; + /* sambaSID -> objectSid*/ + { + .local_name = "objectSid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaSID", + }, -const struct ldb_map_objectclass samba3_objectclasses[] = { - { "group", "sambaGroupMapping" }, - { "user", "sambaSAMAccount" }, - { "domain", "sambaDomain" }, + /* sambaPwdLastSet -> pwdLastSet*/ + { + .local_name = "pwdLastSet", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaPwdLastSet", + }, }; -const struct ldb_map_mappings samba3_mappings = -{ - .name = "samba3", - { - &attr_objectSid, - &attr_pwdLastSet, - &attr_description, - &attr_cn, - &attr_unixName_uid, - &attr_unixName_gid, - &attr_name, - &attr_lastLogoff, - &attr_lastLogon, - &attr_primaryGroupID, - &attr_badPwdCount, - &attr_ntPwdHash, - &attr_lmPwdHash, - &attr_groupType, - &attr_badPasswordTime, - &attr_nextRid, - } -}; - -/* the init function */ + /* the init function */ #ifdef HAVE_DLOPEN_DISABLED - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) #else -struct ldb_module *ldb_samba3_module_init(struct ldb_context *ldb, const char *options[]) + struct ldb_module *ldb_samba3_module_init(struct ldb_context *ldb, const char *options[]) #endif { - return ldb_map_init(ldb, &samba3_mappings, options); + return ldb_map_init(ldb, &samba3_attributes, &samba3_objectclasses, options); } -- cgit From 7e3838dd2d8647e9c621a08c61a2a22ef1d94bb2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Aug 2005 15:13:15 +0000 Subject: r9685: Add tests for samba3sam mapping module Fix a couple of bugs Move samba3sam backend to lib/ldb/ Remove some more unused parameters (This used to be commit 7f864d446d6af7cfd9fb8dbc496a29b36ec57ce9) --- source4/lib/ldb/common/ldb_modules.c | 11 ++ source4/lib/ldb/config.mk | 3 +- source4/lib/ldb/ldb_map/ldb_map.c | 11 +- source4/lib/ldb/samba/samba3sam.c | 198 +++++++++++++++++++++++++++++++ source4/lib/ldb/tests/samba3.ldif | 203 ++++++++++++++++++++++++++++++++ source4/lib/ldb/tests/test-samba3sam.sh | 8 ++ source4/lib/ldb/tools/cmdline.c | 5 +- source4/lib/samba3/config.mk | 1 - source4/lib/samba3/ldb_samba3.c | 198 ------------------------------- 9 files changed, 434 insertions(+), 204 deletions(-) create mode 100644 source4/lib/ldb/samba/samba3sam.c create mode 100644 source4/lib/ldb/tests/samba3.ldif create mode 100755 source4/lib/ldb/tests/test-samba3sam.sh delete mode 100644 source4/lib/samba3/ldb_samba3.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index ab743d1b49..20e8ad061e 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -226,6 +226,17 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) DLIST_ADD(ldb->modules, current); continue; } + + if (strcmp(modules[i], "samba3sam") == 0) { + current = ldb_samba3sam_module_init(ldb, options); + if (!current) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + continue; + } + #endif ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", modules[i]); diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 76059b3b60..23a99e367b 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -115,7 +115,8 @@ REQUIRED_SUBSYSTEMS = \ # Start SUBSYSTEM LDBSAMBA [SUBSYSTEM::LDBSAMBA] OBJ_FILES = \ - lib/ldb/samba/ldif_handlers.o + lib/ldb/samba/ldif_handlers.o \ + lib/ldb/samba/samba3sam.o # End SUBSYSTEM LDBSAMBA ################################################ diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index dea3c24e37..2082abe79a 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -126,6 +126,9 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ struct ldb_dn *newdn; int i; + if (dn == NULL) + return NULL; + newdn = talloc_memdup(module, dn, sizeof(*dn)); if (!newdn) return NULL; @@ -183,6 +186,9 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d int i; struct ldb_parse_tree eqtree, *new_eqtree; + if (dn == NULL) + return NULL; + newdn = talloc_memdup(module, dn, sizeof(*dn)); if (!newdn) return NULL; @@ -252,8 +258,6 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d return newdn; } - - /* Loop over ldb_map_attribute array and add remote_names */ static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) { @@ -261,6 +265,9 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a const char **ret; int ar_size = 0, last_element = 0; + if (attrs == NULL) + return NULL; + /* Start with good guess of number of elements */ for (i = 0; attrs[i]; i++); diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c new file mode 100644 index 0000000000..6c98ffc5c1 --- /dev/null +++ b/source4/lib/ldb/samba/samba3sam.c @@ -0,0 +1,198 @@ +/* + ldb database library - Samba3 SAM compatibility backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "ldb/ldb_map/ldb_map.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" + +/* FIXME: + * sambaSID -> member + * sambaSIDList -> member (special!) + * sambaDomainName -> name + * sambaTrustPassword + * sambaUnixIdPool + * sambaIdmapEntry + * sambaAccountPolicy + * sambaSidEntry + * sambaAcctFlags -> systemFlags ? + * sambaPasswordHistory -> ntPwdHistory*/ + +/* Not necessary: + * sambaConfig + * sambaShare + * sambaConfigOption + * sambaNextGroupRid + * sambaNextUserRid + * sambaAlgorithmicRidBase + */ + +/* Not in Samba4: + * sambaKickoffTime + * sambaPwdCanChange + * sambaPwdMustChange + * sambaHomePath + * sambaHomeDrive + * sambaLogonScript + * sambaProfilePath + * sambaUserWorkstations + * sambaMungedDial + * sambaLogonHours */ + + + +const struct ldb_map_objectclass samba3_objectclasses[] = { + { "group", "sambaGroupMapping" }, + { "user", "sambaSAMAccount" }, + { "domain", "sambaDomain" }, +}; + +const struct ldb_map_attribute samba3_attributes[] = +{ + /* sambaNextRid -> nextRid */ + { + .local_name = "nextRid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNextRid", + }, + + /* sambaBadPasswordTime -> badPasswordtime*/ + { + .local_name = "badPasswordTime", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordTime", + }, + + /* sambaLMPassword -> lmPwdHash*/ + { + .local_name = "lmPwdHash", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLMPassword", + }, + + /* sambaGroupType -> groupType */ + { + .local_name = "groupType", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaGroupType", + }, + + /* sambaNTPassword -> ntPwdHash*/ + { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaNTPassword", + }, + + /* sambaPrimaryGroupSID -> primaryGroupID */ + { + .local_name = "primaryGroupID", + .type = MAP_CONVERT, + .u.convert.remote_name = "sambaPrimaryGroupSID", + .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ + .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ + }, + + /* sambaBadPasswordCount -> badPwdCount */ + { + .local_name = "badPwdCount", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaBadPasswordCount", + }, + + /* sambaLogonTime -> lastLogon*/ + { + .local_name = "lastLogon", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogonTime", + }, + + /* sambaLogoffTime -> lastLogoff*/ + { + .local_name = "lastLogoff", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaLogoffTime", + }, + + /* gidNumber -> unixName */ + { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "gidNumber", + .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ + }, + + /* uid -> unixName */ + { + .local_name = "unixName", + .type = MAP_CONVERT, + .u.convert.remote_name = "uid", + .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ + .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ + }, + + /* displayName -> name */ + { + .local_name = "name", + .type = MAP_RENAME, + .u.rename.remote_name = "displayName", + }, + + /* cn */ + { + .local_name = "cn", + .type = MAP_KEEP, + }, + + /* description */ + { + .local_name = "description", + .type = MAP_KEEP, + }, + + /* sambaSID -> objectSid*/ + { + .local_name = "objectSid", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaSID", + }, + + /* sambaPwdLastSet -> pwdLastSet*/ + { + .local_name = "pwdLastSet", + .type = MAP_RENAME, + .u.rename.remote_name = "sambaPwdLastSet", + }, +}; + + /* the init function */ +#ifdef HAVE_DLOPEN_DISABLED +struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + return ldb_map_init(ldb, &samba3_attributes, &samba3_objectclasses, options); +} diff --git a/source4/lib/ldb/tests/samba3.ldif b/source4/lib/ldb/tests/samba3.ldif new file mode 100644 index 0000000000..fb0a1386d4 --- /dev/null +++ b/source4/lib/ldb/tests/samba3.ldif @@ -0,0 +1,203 @@ +dn: dc=idealx,dc=org +objectClass: dcObject +objectclass: organization +o: idealx +dc: idealx + +dn: ou=Users,dc=idealx,dc=org +objectClass: organizationalUnit +ou: Users + +dn: ou=Groups,dc=idealx,dc=org +objectClass: organizationalUnit +ou: Groups + +dn: ou=Computers,dc=idealx,dc=org +objectClass: organizationalUnit +ou: Computers +dn: uid=Administrator,ou=Users,dc=idealx,dc=org +cn: Administrator +sn: Administrator +objectClass: inetOrgPerson +objectClass: sambaSAMAccount +objectClass: posixAccount +objectClass: shadowAccount +gidNumber: 512 +uid: Administrator +uidNumber: 0 +homeDirectory: /home/%U +sambaPwdLastSet: 0 +sambaLogonTime: 0 +sambaLogoffTime: 2147483647 +sambaKickoffTime: 2147483647 +sambaPwdCanChange: 0 +sambaPwdMustChange: 2147483647 +sambaHomePath: \\PDC-SMB3\home\%U +sambaHomeDrive: H: +sambaProfilePath: \\PDC-SMB3\profiles\%U\Administrator +sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 +sambaLMPassword: XXX +sambaNTPassword: XXX +sambaAcctFlags: [U ] +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2996 +loginShell: /bin/false +gecos: Netbios Domain Administrator + +dn: uid=nobody,ou=Users,dc=idealx,dc=org +cn: nobody +sn: nobody +objectClass: inetOrgPerson +objectClass: sambaSAMAccount +objectClass: posixAccount +objectClass: shadowAccount +gidNumber: 514 +uid: nobody +uidNumber: 999 +homeDirectory: /dev/null +sambaPwdLastSet: 0 +sambaLogonTime: 0 +sambaLogoffTime: 2147483647 +sambaKickoffTime: 2147483647 +sambaPwdCanChange: 0 +sambaPwdMustChange: 2147483647 +sambaHomePath: \\PDC-SMB3\home\%U +sambaHomeDrive: H: +sambaProfilePath: \\PDC-SMB3\profiles\%U\nobody +sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-514 +sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX +sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX +sambaAcctFlags: [NU ] +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2998 +loginShell: /bin/false + +dn: cn=Domain Admins,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 512 +cn: Domain Admins +memberUid: Administrator +description: Netbios Domain Administrators +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-512 +sambaGroupType: 2 +displayName: Domain Admins + +dn: cn=Domain Users,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 513 +cn: Domain Users +description: Netbios Domain Users +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-513 +sambaGroupType: 2 +displayName: Domain Users + +dn: cn=Domain Guests,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 514 +cn: Domain Guests +description: Netbios Domain Guests Users +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-514 +sambaGroupType: 2 +displayName: Domain Guests + +dn: cn=Print Operators,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 550 +cn: Print Operators +description: Netbios Domain Print Operators +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-550 +sambaGroupType: 2 +displayName: Print Operators + +dn: cn=Backup Operators,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 551 +cn: Backup Operators +description: Netbios Domain Members can bypass file security to back up files +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-551 +sambaGroupType: 2 +displayName: Backup Operators + +dn: cn=Replicator,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 552 +cn: Replicator +description: Netbios Domain Supports file replication in a sambaDomainName +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 +sambaGroupType: 2 +displayName: Replicator + +dn: cn=Domain Computers,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 553 +cn: Domain Computers +description: Netbios Domain Computers accounts +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-553 +sambaGroupType: 2 +displayName: Domain Computers + +dn: cn=Administrators,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 544 +cn: Administrators +description: Netbios Domain Members can fully administer the computer/sambaDomainName +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-544 +sambaGroupType: 2 +displayName: Administrators + +dn: cn=Users,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 545 +cn: Users +description: Netbios Domain Ordinary users +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-545 +sambaGroupType: 2 +displayName: users + +dn: cn=Guests,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 546 +cn: Guests +memberUid: nobody +description: Netbios Domain Users granted guest access to the computer/sambaDomainName +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-546 +sambaGroupType: 2 +displayName: Guests + +dn: cn=Power Users,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 547 +cn: Power Users +description: Netbios Domain Members can share directories and printers +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-547 +sambaGroupType: 2 +displayName: Power Users + +dn: cn=Account Operators,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 548 +cn: Account Operators +description: Netbios Domain Users to manipulate users accounts +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-548 +sambaGroupType: 2 +displayName: Account Operators + +dn: cn=Server Operators,ou=Groups,dc=idealx,dc=org +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 549 +cn: Server Operators +description: Netbios Domain Server Operators +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-549 +sambaGroupType: 2 +displayName: Server Operators diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh new file mode 100755 index 0000000000..60d429e3b1 --- /dev/null +++ b/source4/lib/ldb/tests/test-samba3sam.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +rm -f samba3.ldb + +$VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif + +OPT="-o modules:samba3sam -H tdb://samba3.ldb " +$VALGRIND ldbsearch $OPT "(cn=Administrator)" diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index cde357a088..fb0292b7d9 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -124,13 +124,14 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const case 'o': options.options = talloc_realloc(ret, options.options, - const char *, num_options+2); + const char *, num_options+3); if (options.options == NULL) { ldb_oom(ldb); goto failed; } - options.options[num_options++] = poptGetOptArg(pc); + options.options[num_options] = poptGetOptArg(pc); options.options[num_options+1] = NULL; + num_options++; break; default: diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index eba694c2af..06b7e5e256 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -11,7 +11,6 @@ ADD_OBJ_FILES = \ lib/samba3/group.o \ lib/samba3/registry.o \ lib/samba3/secrets.o \ - lib/samba3/ldb_samba3.o \ lib/samba3/share_info.o \ lib/samba3/upgrade.o # End SUBSYSTEM LIBSAMBA3 diff --git a/source4/lib/samba3/ldb_samba3.c b/source4/lib/samba3/ldb_samba3.c deleted file mode 100644 index 68f5412c90..0000000000 --- a/source4/lib/samba3/ldb_samba3.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - ldb database library - Samba3 compatibility backend - - Copyright (C) Jelmer Vernooij 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "includes.h" -#include "ldb/ldb_map/ldb_map.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" - -/* FIXME: - * sambaSID -> member - * sambaSIDList -> member (special!) - * sambaDomainName -> name - * sambaTrustPassword - * sambaUnixIdPool - * sambaIdmapEntry - * sambaAccountPolicy - * sambaSidEntry - * sambaAcctFlags -> systemFlags ? - * sambaPasswordHistory -> ntPwdHistory*/ - -/* Not necessary: - * sambaConfig - * sambaShare - * sambaConfigOption - * sambaNextGroupRid - * sambaNextUserRid - * sambaAlgorithmicRidBase - */ - -/* Not in Samba4: - * sambaKickoffTime - * sambaPwdCanChange - * sambaPwdMustChange - * sambaHomePath - * sambaHomeDrive - * sambaLogonScript - * sambaProfilePath - * sambaUserWorkstations - * sambaMungedDial - * sambaLogonHours */ - - - -const struct ldb_map_objectclass samba3_objectclasses[] = { - { "group", "sambaGroupMapping" }, - { "user", "sambaSAMAccount" }, - { "domain", "sambaDomain" }, -}; - -const struct ldb_map_attribute samba3_attributes[] = -{ - /* sambaNextRid -> nextRid */ - { - .local_name = "nextRid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNextRid", - }, - - /* sambaBadPasswordTime -> badPasswordtime*/ - { - .local_name = "badPasswordTime", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordTime", - }, - - /* sambaLMPassword -> lmPwdHash*/ - { - .local_name = "lmPwdHash", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLMPassword", - }, - - /* sambaGroupType -> groupType */ - { - .local_name = "groupType", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaGroupType", - }, - - /* sambaNTPassword -> ntPwdHash*/ - { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNTPassword", - }, - - /* sambaPrimaryGroupSID -> primaryGroupID */ - { - .local_name = "primaryGroupID", - .type = MAP_CONVERT, - .u.convert.remote_name = "sambaPrimaryGroupSID", - .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ - .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ - }, - - /* sambaBadPasswordCount -> badPwdCount */ - { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordCount", - }, - - /* sambaLogonTime -> lastLogon*/ - { - .local_name = "lastLogon", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogonTime", - }, - - /* sambaLogoffTime -> lastLogoff*/ - { - .local_name = "lastLogoff", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogoffTime", - }, - - /* gidNumber -> unixName */ - { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "gidNumber", - .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ - }, - - /* uid -> unixName */ - { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "uid", - .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ - }, - - /* displayName -> name */ - { - .local_name = "name", - .type = MAP_RENAME, - .u.rename.remote_name = "displayName", - }, - - /* cn */ - { - .local_name = "cn", - .type = MAP_KEEP, - }, - - /* description */ - { - .local_name = "description", - .type = MAP_KEEP, - }, - - /* sambaSID -> objectSid*/ - { - .local_name = "objectSid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaSID", - }, - - /* sambaPwdLastSet -> pwdLastSet*/ - { - .local_name = "pwdLastSet", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaPwdLastSet", - }, -}; - - /* the init function */ -#ifdef HAVE_DLOPEN_DISABLED - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) -#else - struct ldb_module *ldb_samba3_module_init(struct ldb_context *ldb, const char *options[]) -#endif -{ - return ldb_map_init(ldb, &samba3_attributes, &samba3_objectclasses, options); -} -- cgit From e8635da74d4b55b51c1be4fb090a86f8b8a64e78 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Aug 2005 16:33:42 +0000 Subject: r9686: Another round of bugfixes. Works somewhat now, when running under valgrind ;-) (This used to be commit 786379064f0ed779b965330fb3b74deaca75ce99) --- source4/lib/ldb/ldb_map/ldb_map.c | 74 ++++++++++++++++++++++++++++++++++++--- source4/lib/ldb/samba/samba3sam.c | 40 +++++++++++++++++---- 2 files changed, 102 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 2082abe79a..89c6934f5c 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -73,7 +73,12 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons { int i; const struct ldb_map_attribute *attr; - struct ldb_parse_tree *new_tree = talloc_memdup(module, tree, sizeof(*tree)); + struct ldb_parse_tree *new_tree; + + if (tree == NULL) + return NULL; + + new_tree = talloc_memdup(module, tree, sizeof(*tree)); /* Find attr in question and: * - if it has a convert_operator function, run that @@ -102,7 +107,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons attr = map_find_attr_local(module, tree->u.equality.attr); if (!attr) { - DEBUG(0, ("Unable to find local attribute '%s', leaving as is", tree->u.equality.attr)); + DEBUG(0, ("Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr)); return new_tree; } @@ -323,22 +328,77 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a return NULL; } +static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) +{ + struct map_private *map = module->private_data; + int i, j; + int count = 0; + const char **ret = talloc_array(module, const char *, 1); + + ret[0] = NULL; + + for (i = 0; map->attribute_maps[i].local_name; i++) { + BOOL avail = False; + const struct ldb_map_attribute *attr = &map->attribute_maps[i]; + + /* If all remote attributes for this attribute are present, add the + * local one to the list */ + + switch (attr->type) { + case MAP_IGNORE: break; + case MAP_KEEP: + avail = (ldb_msg_find_ldb_val(msg, attr->local_name) != NULL); + break; + + case MAP_RENAME: + case MAP_CONVERT: + avail = (ldb_msg_find_ldb_val(msg, attr->u.rename.remote_name) != NULL); + break; + + case MAP_GENERATE: + avail = True; + for (j = 0; attr->u.generate.remote_names[j]; j++) { + avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); + } + break; + } + + if (!avail) + continue; + + ret = talloc_realloc(module, ret, const char *, count+2); + ret[count] = attr->local_name; + ret[count+1] = NULL; + count++; + } + + return ret; +} + static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) { int i; struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm, *oldelm; + const char **newattrs = NULL; msg->dn = map_remote_dn(module, mi->dn); /* Loop over attrs, find in ldb_map_attribute array and * run generate() */ + if (attrs == NULL) { + /* Generate list of the local attributes that /can/ be generated + * using the specific remote attributes */ + + attrs = newattrs = available_local_attributes(module, mi); + } + for (i = 0; attrs[i]; i++) { const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]); if (!attr) { - DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message", attrs[i])); + DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message\n", attrs[i])); continue; } @@ -373,6 +433,8 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c } } + talloc_free(newattrs); + return msg; } @@ -482,8 +544,10 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas talloc_free(new_tree); talloc_free(newattrs); + *res = talloc_array(module, struct ldb_message *, ret); + for (i = 0; i < ret; i++) { - *res[i] = ldb_map_message_incoming(module, attrs, newres[i]); + (*res)[i] = ldb_map_message_incoming(module, attrs, newres[i]); talloc_free(newres[i]); } @@ -500,7 +564,7 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, struct ldb_parse_tree *tree; int ret; - tree = ldb_parse_tree(map, expression); + tree = ldb_parse_tree(NULL, expression); if (tree == NULL) { map->last_err_string = "expression parse failed"; return -1; diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index 6c98ffc5c1..7c1e61ca4d 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -60,7 +60,33 @@ * sambaMungedDial * sambaLogonHours */ +static struct ldb_message_element *convert_sid_rid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +{ + printf("Converting SID TO RID *\n"); + + return talloc_memdup(ctx, el, sizeof(*el)); +} + +static struct ldb_message_element *convert_rid_sid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +{ + printf("Converting RID TO SID *\n"); + + return talloc_memdup(ctx, el, sizeof(*el)); +} +static struct ldb_message_element *convert_unix_id2name(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +{ + printf("Converting UNIX ID to name\n"); + + return talloc_memdup(ctx, el, sizeof(*el)); +} + +static struct ldb_message_element *convert_unix_name2id(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +{ + printf("Converting UNIX name to ID\n"); + + return talloc_memdup(ctx, el, sizeof(*el)); +} const struct ldb_map_objectclass samba3_objectclasses[] = { { "group", "sambaGroupMapping" }, @@ -110,8 +136,8 @@ const struct ldb_map_attribute samba3_attributes[] = .local_name = "primaryGroupID", .type = MAP_CONVERT, .u.convert.remote_name = "sambaPrimaryGroupSID", - .u.convert.convert_local = NULL, /* FIXME: Add domain SID */ - .u.convert.convert_remote = NULL, /* FIXME: Extract RID */ + .u.convert.convert_local = convert_rid_sid, + .u.convert.convert_remote = convert_sid_rid, }, /* sambaBadPasswordCount -> badPwdCount */ @@ -140,8 +166,8 @@ const struct ldb_map_attribute samba3_attributes[] = .local_name = "unixName", .type = MAP_CONVERT, .u.convert.remote_name = "gidNumber", - .u.convert.convert_local = NULL, /* FIXME: Lookup gid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup groupname */ + .u.convert.convert_local = convert_unix_id2name, + .u.convert.convert_remote = convert_unix_name2id, }, /* uid -> unixName */ @@ -149,8 +175,8 @@ const struct ldb_map_attribute samba3_attributes[] = .local_name = "unixName", .type = MAP_CONVERT, .u.convert.remote_name = "uid", - .u.convert.convert_local = NULL, /* FIXME: Lookup uid */ - .u.convert.convert_remote = NULL, /* FIXME: Lookup username */ + .u.convert.convert_local = convert_unix_id2name, + .u.convert.convert_remote = convert_unix_name2id, }, /* displayName -> name */ @@ -194,5 +220,5 @@ struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[]) #endif { - return ldb_map_init(ldb, &samba3_attributes, &samba3_objectclasses, options); + return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, options); } -- cgit From afb62ee775c3e5b56d786f8246df4a56002b133f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Aug 2005 18:30:00 +0000 Subject: r9689: valgrind-clean now. Editing works now mostly, you just lose half of your database every time you do it... (This used to be commit 40ea2af427911d9a3e65ca9ebed438e9a0a83af8) --- source4/lib/ldb/ldb_map/ldb_map.c | 144 +++++++++++++++++++++++--------------- source4/lib/ldb/samba/samba3sam.c | 56 +++++++++++++-- 2 files changed, 141 insertions(+), 59 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 89c6934f5c..d2eea49877 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -69,7 +69,7 @@ static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_module *m return NULL; } -static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, const struct ldb_parse_tree *tree) +static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_parse_tree *tree) { int i; const struct ldb_map_attribute *attr; @@ -78,7 +78,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons if (tree == NULL) return NULL; - new_tree = talloc_memdup(module, tree, sizeof(*tree)); + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); /* Find attr in question and: * - if it has a convert_operator function, run that @@ -86,15 +86,16 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) { - for (i = 0; i < tree->u.list.num_elements; i++) { - new_tree->u.list.elements[i] = ldb_map_parse_tree(module, tree->u.list.elements[i]); + new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); + for (i = 0; i < new_tree->u.list.num_elements; i++) { + new_tree->u.list.elements[i] = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); } return new_tree; } if (tree->operation == LDB_OP_NOT) { - new_tree->u.isnot.child = ldb_map_parse_tree(module, tree->u.isnot.child); + new_tree->u.isnot.child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); return new_tree; } @@ -104,6 +105,19 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons * (all have attr as the first element) */ + if (new_tree->operation == LDB_OP_EQUALITY) { + new_tree->u.equality.value = ldb_val_dup(new_tree, &tree->u.equality.value); + } else if (new_tree->operation == LDB_OP_SUBSTRING) { + new_tree->u.substring.chunks = NULL; /* FIXME! */ + } else if (new_tree->operation == LDB_OP_LESS || + new_tree->operation == LDB_OP_GREATER || + new_tree->operation == LDB_OP_APPROX) { + new_tree->u.comparison.value = ldb_val_dup(new_tree, &tree->u.comparison.value); + } else if (new_tree->operation == LDB_OP_EXTENDED) { + new_tree->u.extended.value = ldb_val_dup(new_tree, &tree->u.extended.value); + new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); + } + attr = map_find_attr_local(module, tree->u.equality.attr); if (!attr) { @@ -111,17 +125,21 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, cons return new_tree; } - if (attr->type == MAP_IGNORE) + if (attr->type == MAP_IGNORE) { + talloc_free(new_tree); return NULL; + } if (attr->convert_operator) { /* Run convert_operator */ talloc_free(new_tree); new_tree = attr->convert_operator(module, tree); + + return new_tree; } else { new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); } - + return new_tree; } @@ -138,7 +156,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ if (!newdn) return NULL; - newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); if (!newdn->components) return NULL; @@ -150,25 +168,17 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ const struct ldb_map_attribute *attr = map_find_attr_remote(module, dn->components[i].name); /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr) - continue; - - if (attr->type == MAP_IGNORE) { - DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name)); - talloc_free(newdn); - return NULL; - } - - if (attr->type == MAP_GENERATE) { - DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + if (!attr || attr->type == MAP_KEEP) { + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + } else if (attr->type == MAP_IGNORE || attr->type == MAP_GENERATE) { + DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); talloc_free(newdn); - return NULL; - } - - if (attr->type == MAP_CONVERT) { + } else if (attr->type == MAP_CONVERT) { struct ldb_message_element elm, *newelm; struct ldb_val vals[1] = { dn->components[i].value }; + elm.flags = 0; elm.name = attr->u.convert.remote_name; elm.num_values = 1; @@ -176,10 +186,13 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ newelm = attr->u.convert.convert_remote(module, attr->local_name, &elm); - newdn->components[i].name = talloc_strdup(module, newelm->name); - newdn->components[i].value = newelm->values[0]; + newdn->components[i].name = talloc_strdup(newdn->components, newelm->name); + newdn->components[i].value = ldb_val_dup(newdn->components, &newelm->values[0]); + + talloc_free(newelm); } else if (attr->type == MAP_RENAME) { - newdn->components[i].name = talloc_strdup(module, attr->local_name); + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); } } return newdn; @@ -198,7 +211,7 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d if (!newdn) return NULL; - newdn->components = talloc_memdup(newdn, dn->components, sizeof(struct ldb_dn_component) * newdn->comp_num); + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); if (!newdn->components) return NULL; @@ -210,22 +223,16 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d const struct ldb_map_attribute *attr = map_find_attr_local(module, dn->components[i].name); /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr) + if (!attr || attr->type == MAP_KEEP) { + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); continue; - - if (attr->type == MAP_IGNORE) { - DEBUG(0, ("Local MAP_IGNORE attribute '%s' used in DN!", dn->components[i].name)); + } else if (attr->type == MAP_IGNORE || attr->type == MAP_GENERATE) { + DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); talloc_free(newdn); return NULL; } - if (attr->type == MAP_GENERATE) { - DEBUG(0, ("Local MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); - talloc_free(newdn); - - return NULL; - } - /* Simple rename/convert only */ if (attr->convert_operator) { /* Fancy stuff */ @@ -233,7 +240,7 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d eqtree.u.equality.attr = dn->components[i].name; eqtree.u.equality.value = dn->components[i].value; - new_eqtree = ldb_map_parse_tree(module, &eqtree); + new_eqtree = ldb_map_parse_tree(module, newdn, &eqtree); /* Silently continue for now */ if (!new_eqtree) { @@ -241,8 +248,10 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d continue; } - newdn->components[i].name = new_eqtree->u.equality.attr; - newdn->components[i].value = new_eqtree->u.equality.value; + newdn->components[i].name = talloc_strdup(newdn->components, new_eqtree->u.equality.attr); + newdn->components[i].value = ldb_val_dup(newdn->components, &new_eqtree->u.equality.value); + + talloc_free(new_eqtree); } else if (attr->type == MAP_CONVERT) { struct ldb_message_element elm, *newelm; struct ldb_val vals[1] = { dn->components[i].value }; @@ -253,10 +262,13 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d newelm = attr->u.convert.convert_local(module, attr->u.convert.remote_name, &elm); - newdn->components[i].name = talloc_strdup(module, newelm->name); - newdn->components[i].value = newelm->values[0]; + newdn->components[i].name = talloc_strdup(newdn->components, newelm->name); + newdn->components[i].value = ldb_val_dup(newdn->components, &newelm->values[0]); + + talloc_free(newelm); } else if (attr->type == MAP_RENAME) { - newdn->components[i].name = talloc_strdup(module, attr->u.rename.remote_name); + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); } } @@ -406,26 +418,37 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_IGNORE:break; case MAP_RENAME: oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - elm = talloc_memdup(msg, oldelm, sizeof(*oldelm)); + + elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); - ldb_msg_add(module->ldb, msg, elm, 0); + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_CONVERT: oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); elm = attr->u.convert.convert_local(msg, attr->local_name, oldelm); - ldb_msg_add(module->ldb, msg, elm, 0); + ldb_msg_add(module->ldb, msg, elm, elm->flags); break; case MAP_KEEP: - ldb_msg_add(module->ldb, msg, ldb_msg_find_element(mi, attr->local_name), 0); + oldelm = ldb_msg_find_element(mi, attr->local_name); + + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); + elm->name = talloc_strdup(elm, oldelm->name); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_GENERATE: elm = attr->u.generate.generate_local(msg, attr->local_name, mi); - ldb_msg_add(module->ldb, msg, elm, 0); + ldb_msg_add(module->ldb, msg, elm, elm->flags); break; default: DEBUG(0, ("Unknown attr->type for %s", attr->local_name)); @@ -460,19 +483,28 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c switch (attr->type) { case MAP_IGNORE: break; case MAP_RENAME: - elm = talloc_memdup(msg, &msg->elements[i], sizeof(*elm)); + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); - ldb_msg_add(module->ldb, msg, elm, 0); + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); break; case MAP_CONVERT: - elm = attr->u.convert.convert_remote(msg, attr->local_name, &msg->elements[i]); - ldb_msg_add(module->ldb, msg, elm, 0); + elm = attr->u.convert.convert_remote(msg, attr->local_name, &mo->elements[i]); + ldb_msg_add(module->ldb, msg, elm, elm->flags); break; case MAP_KEEP: - ldb_msg_add(module->ldb, msg, &msg->elements[i], 0); + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); break; case MAP_GENERATE: @@ -534,7 +566,7 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas struct ldb_message **newres; int i; - new_tree = ldb_map_parse_tree(module, tree); + new_tree = ldb_map_parse_tree(module, module, tree); newattrs = ldb_map_attrs(module, attrs); new_base = map_local_dn(module, base); @@ -660,6 +692,8 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at return NULL; } + data->last_err_string = NULL; + data->attribute_maps = attrs; data->objectclass_maps = ocls; ctx->private_data = data; diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index 7c1e61ca4d..23f794d90b 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -62,30 +62,78 @@ static struct ldb_message_element *convert_sid_rid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) { + struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); + int i; + printf("Converting SID TO RID *\n"); - return talloc_memdup(ctx, el, sizeof(*el)); + ret->flags = el->flags; + ret->name = talloc_strdup(ret, remote_attr); + ret->num_values = el->num_values; + ret->values = talloc_array(ret, struct ldb_val, ret->num_values); + + for (i = 0; i < ret->num_values; i++) { + ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); + } + + return ret; } static struct ldb_message_element *convert_rid_sid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) { + struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); + int i; + printf("Converting RID TO SID *\n"); - return talloc_memdup(ctx, el, sizeof(*el)); + ret->flags = el->flags; + ret->name = talloc_strdup(ret, remote_attr); + ret->num_values = el->num_values; + ret->values = talloc_array(ret, struct ldb_val, ret->num_values); + + for (i = 0; i < ret->num_values; i++) { + ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); + } + + return ret; } static struct ldb_message_element *convert_unix_id2name(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) { + int i; + struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); + printf("Converting UNIX ID to name\n"); - return talloc_memdup(ctx, el, sizeof(*el)); + ret->flags = el->flags; + ret->name = talloc_strdup(ret, remote_attr); + ret->num_values = el->num_values; + ret->values = talloc_array(ret, struct ldb_val, ret->num_values); + + for (i = 0; i < ret->num_values; i++) { + ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); + } + + return ret; } static struct ldb_message_element *convert_unix_name2id(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) { + struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); + int i; + printf("Converting UNIX name to ID\n"); - return talloc_memdup(ctx, el, sizeof(*el)); + ret->flags = el->flags; + ret->name = talloc_strdup(ret, remote_attr); + ret->num_values = el->num_values; + ret->values = talloc_array(ret, struct ldb_val, ret->num_values); + + for (i = 0; i < ret->num_values; i++) { + ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); + } + + return ret; } const struct ldb_map_objectclass samba3_objectclasses[] = { -- cgit From e1269bafe8449f2417d7c666bf0f95af5d7a005f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Aug 2005 19:46:28 +0000 Subject: r9690: Extend test + fix several bugs (This used to be commit 0cff0e03fca0ddccaff3b463aadba63d29e061a9) --- source4/lib/ldb/ldb_map/ldb_map.c | 18 ++++++++++++++---- source4/lib/ldb/samba/samba3sam.c | 8 ++++---- source4/lib/ldb/tests/test-samba3sam.sh | 32 +++++++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index d2eea49877..d2bbea7c7a 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -120,8 +120,9 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL attr = map_find_attr_local(module, tree->u.equality.attr); - if (!attr) { + if (!attr || attr->type == MAP_KEEP) { DEBUG(0, ("Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr)); + new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); return new_tree; } @@ -387,6 +388,7 @@ static const char **available_local_attributes(struct ldb_module *module, const return ret; } +/* Used for search */ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) { int i; @@ -418,6 +420,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_IGNORE:break; case MAP_RENAME: oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + if (!oldelm) continue; elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); @@ -429,14 +432,18 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_CONVERT: oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - elm = attr->u.convert.convert_local(msg, attr->local_name, oldelm); + if (!oldelm) continue; + + elm = attr->u.convert.convert_remote(msg, attr->local_name, oldelm); + if (!elm) continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); break; case MAP_KEEP: oldelm = ldb_msg_find_element(mi, attr->local_name); - + if (!oldelm) continue; + elm = talloc(msg, struct ldb_message_element); elm->num_values = oldelm->num_values; @@ -448,6 +455,8 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_GENERATE: elm = attr->u.generate.generate_local(msg, attr->local_name, mi); + if (!elm) continue; + ldb_msg_add(module->ldb, msg, elm, elm->flags); break; default: @@ -461,6 +470,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c return msg; } +/* Used for add, modify */ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo) { struct ldb_message *msg = talloc_zero(module, struct ldb_message); @@ -493,7 +503,7 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c break; case MAP_CONVERT: - elm = attr->u.convert.convert_remote(msg, attr->local_name, &mo->elements[i]); + elm = attr->u.convert.convert_local(msg, attr->u.convert.remote_name, &mo->elements[i]); ldb_msg_add(module->ldb, msg, elm, elm->flags); break; diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index 23f794d90b..c1ac691e92 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -214,8 +214,8 @@ const struct ldb_map_attribute samba3_attributes[] = .local_name = "unixName", .type = MAP_CONVERT, .u.convert.remote_name = "gidNumber", - .u.convert.convert_local = convert_unix_id2name, - .u.convert.convert_remote = convert_unix_name2id, + .u.convert.convert_local = convert_unix_name2id, + .u.convert.convert_remote = convert_unix_id2name, }, /* uid -> unixName */ @@ -223,8 +223,8 @@ const struct ldb_map_attribute samba3_attributes[] = .local_name = "unixName", .type = MAP_CONVERT, .u.convert.remote_name = "uid", - .u.convert.convert_local = convert_unix_id2name, - .u.convert.convert_remote = convert_unix_name2id, + .u.convert.convert_local = convert_unix_name2id, + .u.convert.convert_remote = convert_unix_id2name, }, /* displayName -> name */ diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh index 60d429e3b1..73610a2be2 100755 --- a/source4/lib/ldb/tests/test-samba3sam.sh +++ b/source4/lib/ldb/tests/test-samba3sam.sh @@ -2,7 +2,33 @@ rm -f samba3.ldb -$VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif +echo "Adding samba3 LDIF..." +$VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif || exit 1 + +LOC="-H tdb://samba3.ldb" +OPT="-o modules:samba3sam $LOC" + +echo "Looking up by non-mapped attribute" +$VALGRIND ldbsearch $OPT "(cn=Administrator)" || exit 1 + +echo "Looking up by mapped attribute" +$VALGRIND ldbsearch $OPT "(name=Backup Operators)" || exit 1 + +echo "Looking up by old name of renamed attribute" +$VALGRIND ldbsearch $OPT "(displayName=Backup Operators)" || exit 1 + +echo "Adding a record" +$VALGRIND ldbadd $OPT < Date: Sat, 27 Aug 2005 23:47:17 +0000 Subject: r9698: Fix a bit of memory management More minor bugfixes Support mapping objectclasses and do mapping on 'dn' field as well (not just msg->dn) (This used to be commit b7b079167d5c6616f7c5c4afb7dd80c15707cfd9) --- source4/lib/ldb/ldb_map/ldb_map.c | 442 ++++++++++++++++++++++---------- source4/lib/ldb/ldb_map/ldb_map.h | 30 ++- source4/lib/ldb/samba/samba3sam.c | 76 ++---- source4/lib/ldb/tests/test-samba3sam.sh | 15 +- 4 files changed, 354 insertions(+), 209 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index d2bbea7c7a..5ae4a435d8 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -31,21 +31,24 @@ * - objectclass hint in ldb_map_attribute * for use when multiple remote attributes (independant of each other) * map to one local attribute. E.g.: (uid, gidNumber) -> unixName + * (use MAP_GENERATE instead ?) */ +static const struct ldb_map_attribute builtin_attribute_maps[]; + struct map_private { - const struct ldb_map_attribute *attribute_maps; - const struct ldb_map_objectclass *objectclass_maps; + struct ldb_map_context context; const char *last_err_string; }; + /* find an attribute by the local name */ -static const struct ldb_map_attribute *map_find_attr_local(struct ldb_module *module, const char *attr) +static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) { - struct map_private *privdat = module->private_data; int i; + for (i = 0; privdat->attribute_maps[i].local_name; i++) { - if (!strcmp(privdat->attribute_maps[i].local_name, attr)) + if (!ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr)) return &privdat->attribute_maps[i]; } @@ -53,17 +56,26 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_module *mo } /* find an attribute by the remote name */ -static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_module *module, const char *attr) +static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) { - struct map_private *privdat = module->private_data; int i; + for (i = 0; privdat->attribute_maps[i].local_name; i++) { - if (privdat->attribute_maps[i].type != MAP_RENAME && - privdat->attribute_maps[i].type != MAP_CONVERT) + if (privdat->attribute_maps[i].type == MAP_IGNORE) + continue; + + if (privdat->attribute_maps[i].type == MAP_GENERATE) continue; - if (!strcmp(privdat->attribute_maps[i].u.rename.remote_name, attr)) + if (privdat->attribute_maps[i].type == MAP_KEEP && + ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr) == 0) return &privdat->attribute_maps[i]; + + if ((privdat->attribute_maps[i].type == MAP_RENAME || + privdat->attribute_maps[i].type == MAP_CONVERT) && + ldb_attr_cmp(privdat->attribute_maps[i].u.rename.remote_name, attr) == 0) + return &privdat->attribute_maps[i]; + } return NULL; @@ -74,11 +86,13 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL int i; const struct ldb_map_attribute *attr; struct ldb_parse_tree *new_tree; + enum ldb_map_attr_type map_type; + struct ldb_val value, newvalue; + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; if (tree == NULL) return NULL; - new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); /* Find attr in question and: * - if it has a convert_operator function, run that @@ -86,6 +100,8 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) { + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); for (i = 0; i < new_tree->u.list.num_elements; i++) { new_tree->u.list.elements[i] = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); @@ -95,6 +111,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (tree->operation == LDB_OP_NOT) { + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); new_tree->u.isnot.child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); return new_tree; } @@ -105,47 +122,74 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL * (all have attr as the first element) */ - if (new_tree->operation == LDB_OP_EQUALITY) { - new_tree->u.equality.value = ldb_val_dup(new_tree, &tree->u.equality.value); - } else if (new_tree->operation == LDB_OP_SUBSTRING) { - new_tree->u.substring.chunks = NULL; /* FIXME! */ - } else if (new_tree->operation == LDB_OP_LESS || - new_tree->operation == LDB_OP_GREATER || - new_tree->operation == LDB_OP_APPROX) { - new_tree->u.comparison.value = ldb_val_dup(new_tree, &tree->u.comparison.value); - } else if (new_tree->operation == LDB_OP_EXTENDED) { - new_tree->u.extended.value = ldb_val_dup(new_tree, &tree->u.extended.value); - new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); - } - - attr = map_find_attr_local(module, tree->u.equality.attr); + attr = map_find_attr_local(privdat, tree->u.equality.attr); - if (!attr || attr->type == MAP_KEEP) { + if (!attr) { DEBUG(0, ("Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr)); - new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); - return new_tree; + map_type = MAP_KEEP; + } else { + map_type = attr->type; } - if (attr->type == MAP_IGNORE) { - talloc_free(new_tree); + if (attr && attr->convert_operator) { + /* Run convert_operator */ + return attr->convert_operator(privdat, module, tree); + } + + if (map_type == MAP_IGNORE) + return NULL; + + if (map_type == MAP_GENERATE) { + DEBUG(0, ("Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr)); return NULL; } - if (attr->convert_operator) { - /* Run convert_operator */ - talloc_free(new_tree); - new_tree = attr->convert_operator(module, tree); + if (tree->operation == LDB_OP_EQUALITY) { + value = tree->u.equality.value; + } else if (tree->operation == LDB_OP_LESS || tree->operation == LDB_OP_GREATER || + tree->operation == LDB_OP_APPROX) { + value = tree->u.comparison.value; + } else if (tree->operation == LDB_OP_EXTENDED) { + value = tree->u.extended.value; + } + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + if (map_type == MAP_KEEP) { + new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); + } else { /* MAP_RENAME / MAP_CONVERT */ + new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); + } + + if (new_tree->operation == LDB_OP_PRESENT) + return new_tree; + + if (new_tree->operation == LDB_OP_SUBSTRING) { + new_tree->u.substring.chunks = NULL; /* FIXME! */ return new_tree; + } + + if (map_type == MAP_CONVERT) { + newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); } else { - new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); + newvalue = ldb_val_dup(new_tree, &value); + } + + if (new_tree->operation == LDB_OP_EQUALITY) { + new_tree->u.equality.value = newvalue; + } else if (new_tree->operation == LDB_OP_LESS || new_tree->operation == LDB_OP_GREATER || + new_tree->operation == LDB_OP_APPROX) { + new_tree->u.comparison.value = newvalue; + } else if (new_tree->operation == LDB_OP_EXTENDED) { + new_tree->u.extended.value = newvalue; + new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); } return new_tree; } /* Remote DN -> Local DN */ -static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_dn *dn) +static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) { struct ldb_dn *newdn; int i; @@ -153,7 +197,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ if (dn == NULL) return NULL; - newdn = talloc_memdup(module, dn, sizeof(*dn)); + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); if (!newdn) return NULL; @@ -166,49 +210,49 @@ static struct ldb_dn *map_remote_dn(struct ldb_module *module, const struct ldb_ * complete rdn */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_remote(module, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr || attr->type == MAP_KEEP) { - newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - } else if (attr->type == MAP_IGNORE || attr->type == MAP_GENERATE) { + if (!attr) map_type = MAP_KEEP; + else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: + case MAP_GENERATE: DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); talloc_free(newdn); return NULL; - } else if (attr->type == MAP_CONVERT) { - struct ldb_message_element elm, *newelm; - struct ldb_val vals[1] = { dn->components[i].value }; - - elm.flags = 0; - elm.name = attr->u.convert.remote_name; - elm.num_values = 1; - elm.values = vals; - - newelm = attr->u.convert.convert_remote(module, attr->local_name, &elm); - - newdn->components[i].name = talloc_strdup(newdn->components, newelm->name); - newdn->components[i].value = ldb_val_dup(newdn->components, &newelm->values[0]); - talloc_free(newelm); - } else if (attr->type == MAP_RENAME) { + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); + break; + + case MAP_RENAME: newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; } } return newdn; } /* Local DN -> Remote DN */ -static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_dn *dn) -{ struct ldb_dn *newdn; +static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; int i; - struct ldb_parse_tree eqtree, *new_eqtree; if (dn == NULL) return NULL; - newdn = talloc_memdup(module, dn, sizeof(*dn)); + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); if (!newdn) return NULL; @@ -221,55 +265,34 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, const struct ldb_d * complete rdn using an equality convert_operator call */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(module, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr || attr->type == MAP_KEEP) { - newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - continue; - } else if (attr->type == MAP_IGNORE || attr->type == MAP_GENERATE) { + if (!attr) map_type = MAP_KEEP; else map_type = attr->type; + + switch (map_type) + { + case MAP_IGNORE: + case MAP_GENERATE: DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); talloc_free(newdn); return NULL; - } - - /* Simple rename/convert only */ - if (attr->convert_operator) { - /* Fancy stuff */ - eqtree.operation = LDB_OP_EQUALITY; - eqtree.u.equality.attr = dn->components[i].name; - eqtree.u.equality.value = dn->components[i].value; - new_eqtree = ldb_map_parse_tree(module, newdn, &eqtree); - - /* Silently continue for now */ - if (!new_eqtree) { - DEBUG(0, ("Unable to convert RDN for attribute %s\n", dn->components[i].name)); - continue; - } - - newdn->components[i].name = talloc_strdup(newdn->components, new_eqtree->u.equality.attr); - newdn->components[i].value = ldb_val_dup(newdn->components, &new_eqtree->u.equality.value); - - talloc_free(new_eqtree); - } else if (attr->type == MAP_CONVERT) { - struct ldb_message_element elm, *newelm; - struct ldb_val vals[1] = { dn->components[i].value }; - elm.flags = 0; - elm.name = attr->local_name; - elm.num_values = 1; - elm.values = vals; - - newelm = attr->u.convert.convert_local(module, attr->u.convert.remote_name, &elm); - - newdn->components[i].name = talloc_strdup(newdn->components, newelm->name); - newdn->components[i].value = ldb_val_dup(newdn->components, &newelm->values[0]); + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); + newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); + break; + + case MAP_RENAME: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; - talloc_free(newelm); - } else if (attr->type == MAP_RENAME) { - newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + continue; } } @@ -282,6 +305,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a int i; const char **ret; int ar_size = 0, last_element = 0; + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; if (attrs == NULL) return NULL; @@ -294,14 +318,15 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a for (i = 0; attrs[i]; i++) { int j; - const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]); + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; if (!attr) { DEBUG(0, ("Local attribute '%s' does not have a definition!\n", attrs[i])); - continue; - } + map_type = MAP_IGNORE; + } else map_type = attr->type; - switch (attr->type) + switch (map_type) { case MAP_IGNORE: break; case MAP_KEEP: @@ -337,22 +362,29 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a break; } } + + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } - return NULL; + ret[last_element] = NULL; + + return ret; } static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) { - struct map_private *map = module->private_data; + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; int i, j; int count = 0; const char **ret = talloc_array(module, const char *, 1); ret[0] = NULL; - for (i = 0; map->attribute_maps[i].local_name; i++) { + for (i = 0; privdat->attribute_maps[i].local_name; i++) { BOOL avail = False; - const struct ldb_map_attribute *attr = &map->attribute_maps[i]; + const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; /* If all remote attributes for this attribute are present, add the * local one to the list */ @@ -391,12 +423,13 @@ static const char **available_local_attributes(struct ldb_module *module, const /* Used for search */ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) { - int i; + int i, j; struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm, *oldelm; + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; const char **newattrs = NULL; - msg->dn = map_remote_dn(module, mi->dn); + msg->dn = map_remote_dn(privdat, module, mi->dn); /* Loop over attrs, find in ldb_map_attribute array and * run generate() */ @@ -409,14 +442,15 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c } for (i = 0; attrs[i]; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(module, attrs[i]); + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; if (!attr) { DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message\n", attrs[i])); - continue; - } + map_type = MAP_IGNORE; + } else map_type = attr->type; - switch (attr->type) { + switch (map_type) { case MAP_IGNORE:break; case MAP_RENAME: oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); @@ -434,10 +468,15 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); if (!oldelm) continue; - elm = attr->u.convert.convert_remote(msg, attr->local_name, oldelm); - if (!elm) continue; + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - ldb_msg_add(module->ldb, msg, elm, elm->flags); + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_KEEP: @@ -454,7 +493,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c break; case MAP_GENERATE: - elm = attr->u.generate.generate_local(msg, attr->local_name, mi); + elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); if (!elm) continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); @@ -473,24 +512,27 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c /* Used for add, modify */ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo) { + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm; - int i; + int i,j; msg->private_data = mo->private_data; - msg->dn = map_local_dn(module, mo->dn); + msg->dn = map_local_dn(privdat, module, mo->dn); /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < mo->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(module, mo->elements[i].name); + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); + enum ldb_map_attr_type map_type; if (!attr) { DEBUG(0, ("Undefined local attribute '%s', ignoring\n", mo->elements[i].name)); + map_type = MAP_IGNORE; continue; - } + } else map_type = attr->type; - switch (attr->type) { + switch (map_type) { case MAP_IGNORE: break; case MAP_RENAME: elm = talloc(msg, struct ldb_message_element); @@ -503,8 +545,17 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c break; case MAP_CONVERT: - elm = attr->u.convert.convert_local(msg, attr->u.convert.remote_name, &mo->elements[i]); - ldb_msg_add(module->ldb, msg, elm, elm->flags); + elm = talloc(msg, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); + } + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); break; case MAP_KEEP: @@ -518,7 +569,7 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c break; case MAP_GENERATE: - attr->u.generate.generate_remote(attr->local_name, mo, msg); + attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); break; } } @@ -531,11 +582,12 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c */ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; struct ldb_dn *n_olddn, *n_newdn; int ret; - n_olddn = map_local_dn(module, olddn); - n_newdn = map_local_dn(module, newdn); + n_olddn = map_local_dn(privdat, module, olddn); + n_newdn = map_local_dn(privdat, module, newdn); ret = ldb_next_rename_record(module, n_olddn, n_newdn); @@ -550,10 +602,11 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con */ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; struct ldb_dn *newdn; int ret; - newdn = map_local_dn(module, dn); + newdn = map_local_dn(privdat, module, dn); ret = ldb_next_delete_record(module, newdn); @@ -574,11 +627,12 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas struct ldb_parse_tree *new_tree; struct ldb_dn *new_base; struct ldb_message **newres; + struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; int i; new_tree = ldb_map_parse_tree(module, module, tree); newattrs = ldb_map_attrs(module, attrs); - new_base = map_local_dn(module, base); + new_base = map_local_dn(privdat, module, base); ret = ldb_next_search_bytree(module, new_base, scope, new_tree, newattrs, &newres); @@ -633,8 +687,6 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) } - - /* modify a record */ @@ -689,6 +741,7 @@ static const struct ldb_module_ops map_ops = { /* the init function */ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *options[]) { + int i, j; struct ldb_module *ctx; struct map_private *data; @@ -704,8 +757,26 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at data->last_err_string = NULL; - data->attribute_maps = attrs; - data->objectclass_maps = ocls; + /* Get list of attribute maps */ + j = 0; + data->context.attribute_maps = NULL; + + for (i = 0; attrs[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = attrs[i]; + j++; + } + + for (i = 0; builtin_attribute_maps[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = builtin_attribute_maps[i]; + j++; + } + + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + ZERO_STRUCT(data->context.attribute_maps[j].local_name); + + data->context.objectclass_maps = ocls; ctx->private_data = data; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; @@ -713,3 +784,100 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at return ctx; } + +static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_local_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_remote_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].local_name; i++) { + if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].remote_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + DEBUG(1, ("Unable to map local object class '%s'\n", (char *)val->data)); + return ldb_val_dup(ctx, val); +} + +static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].remote_name; i++) { + if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].local_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + DEBUG(1, ("Unable to map remote object class '%s'\n", (char *)val->data)); + return ldb_val_dup(ctx, val); +} + +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = MAP_CONVERT, + .u.convert.remote_name = "dn", + .u.convert.convert_local = map_convert_local_dn, + .u.convert.convert_remote = map_convert_remote_dn, + }, + { + .local_name = "objectclass", + .type = MAP_CONVERT, + .u.convert.remote_name = "objectclass", + .u.convert.convert_local = map_convert_local_objectclass, + .u.convert.convert_remote = map_convert_remote_objectclass, + }, + { + .local_name = NULL, + } +}; + diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h index bdeafc827a..60e09975b7 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -38,13 +38,15 @@ * returning too much attributes in ldb_search() doesn't) */ +struct ldb_map_context; + struct ldb_map_attribute { const char *local_name; /* local name */ - enum { + enum ldb_map_attr_type { MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ - MAP_KEEP, /* Keep as is */ + MAP_KEEP, /* Keep as is. Same name locally and remotely. */ MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ MAP_CONVERT, /* Rename + convert data */ MAP_GENERATE /* Use generate function for generating new name/data. @@ -53,7 +55,7 @@ struct ldb_map_attribute } type; /* if set, will be called for expressions that contain this attribute */ - struct ldb_parse_tree *(*convert_operator) (TALLOC_CTX *ctx, const struct ldb_parse_tree *); + struct ldb_parse_tree *(*convert_operator) (struct ldb_map_context *, TALLOC_CTX *ctx, const struct ldb_parse_tree *); union { struct { @@ -62,27 +64,21 @@ struct ldb_map_attribute struct { const char *remote_name; - - struct ldb_message_element *(*convert_local) ( - TALLOC_CTX *ctx, - const char *remote_attr, - const struct ldb_message_element *); - - struct ldb_message_element *(*convert_remote) ( - TALLOC_CTX *ctx, - const char *local_attr, - const struct ldb_message_element *); + struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); } convert; struct { /* Generate the local attribute from remote message */ struct ldb_message_element *(*generate_local) ( + struct ldb_map_context *, TALLOC_CTX *ctx, - const char *attr, + const char *attr, const struct ldb_message *remote); /* Update remote message with information from local message */ void (*generate_remote) ( + struct ldb_map_context *, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote); @@ -102,4 +98,10 @@ struct ldb_map_objectclass const char *remote_name; }; +struct ldb_map_context +{ + struct ldb_map_attribute *attribute_maps; + const struct ldb_map_objectclass *objectclass_maps; +}; + #endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index c1ac691e92..ceb52b8a16 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -60,86 +60,39 @@ * sambaMungedDial * sambaLogonHours */ -static struct ldb_message_element *convert_sid_rid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +static struct ldb_val convert_sid_rid(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); - int i; - printf("Converting SID TO RID *\n"); - ret->flags = el->flags; - ret->name = talloc_strdup(ret, remote_attr); - ret->num_values = el->num_values; - ret->values = talloc_array(ret, struct ldb_val, ret->num_values); - - for (i = 0; i < ret->num_values; i++) { - ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); - } - - return ret; + return ldb_val_dup(ctx, val); } -static struct ldb_message_element *convert_rid_sid(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +static struct ldb_val convert_rid_sid(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); - int i; - printf("Converting RID TO SID *\n"); - ret->flags = el->flags; - ret->name = talloc_strdup(ret, remote_attr); - ret->num_values = el->num_values; - ret->values = talloc_array(ret, struct ldb_val, ret->num_values); - - for (i = 0; i < ret->num_values; i++) { - ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); - } - - return ret; + return ldb_val_dup(ctx, val); } -static struct ldb_message_element *convert_unix_id2name(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +static struct ldb_val convert_unix_id2name(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) { - int i; - struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); - printf("Converting UNIX ID to name\n"); - ret->flags = el->flags; - ret->name = talloc_strdup(ret, remote_attr); - ret->num_values = el->num_values; - ret->values = talloc_array(ret, struct ldb_val, ret->num_values); - - for (i = 0; i < ret->num_values; i++) { - ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); - } - - return ret; + return ldb_val_dup(ctx, val); } -static struct ldb_message_element *convert_unix_name2id(TALLOC_CTX *ctx, const char *remote_attr, const struct ldb_message_element *el) +static struct ldb_val convert_unix_name2id(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_message_element *ret = talloc(ctx, struct ldb_message_element); - int i; - printf("Converting UNIX name to ID\n"); - ret->flags = el->flags; - ret->name = talloc_strdup(ret, remote_attr); - ret->num_values = el->num_values; - ret->values = talloc_array(ret, struct ldb_val, ret->num_values); - - for (i = 0; i < ret->num_values; i++) { - ret->values[i] = ldb_val_dup(ret->values, &el->values[i]); - } - - return ret; + return ldb_val_dup(ctx, val); } const struct ldb_map_objectclass samba3_objectclasses[] = { { "group", "sambaGroupMapping" }, { "user", "sambaSAMAccount" }, { "domain", "sambaDomain" }, + { NULL, NULL } }; const struct ldb_map_attribute samba3_attributes[] = @@ -253,12 +206,21 @@ const struct ldb_map_attribute samba3_attributes[] = .u.rename.remote_name = "sambaSID", }, - /* sambaPwdLastSet -> pwdLastSet*/ + /* sambaPwdLastSet -> pwdLastSet */ { .local_name = "pwdLastSet", .type = MAP_RENAME, .u.rename.remote_name = "sambaPwdLastSet", }, + + /* cn -> cn */ + { + .local_name = "cn", + .type = MAP_KEEP, + }, + { + .local_name = NULL, + } }; /* the init function */ diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh index 73610a2be2..988806d895 100755 --- a/source4/lib/ldb/tests/test-samba3sam.sh +++ b/source4/lib/ldb/tests/test-samba3sam.sh @@ -30,5 +30,18 @@ echo "Checking for existance of record (mapped)" $VALGRIND ldbsearch $OPT "(cn=Foo)" unixName lastLogon cn || exit 1 echo "Checking for existance of record (non-mapped)" -$VALGRIND ldbsearch $LOC "(cn=Foo)" uid sambaLogonTime cn || exit 1 +$VALGRIND ldbsearch $LOC"(cn=foo)" uid sambaLogonTime cn || exit 1 +echo "Adding record with mapped attribute in dn" +$VALGRIND ldbadd $OPT < Date: Sun, 28 Aug 2005 00:34:14 +0000 Subject: r9699: Add as much attributes the current Samba4 SAM has to the mapping table (ignoring most of them, currently..) (This used to be commit 5100ae211c380024baa67b1f643c7294a29c1713) --- source4/lib/ldb/samba/samba3sam.c | 407 +++++++++++++++++++++++++++++++++++++- 1 file changed, 402 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index ceb52b8a16..d114839047 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -28,8 +28,8 @@ #include "ldb/include/ldb_private.h" /* FIXME: - * sambaSID -> member - * sambaSIDList -> member (special!) + * sambaSID -> member (dn!) + * sambaSIDList -> member (dn!) * sambaDomainName -> name * sambaTrustPassword * sambaUnixIdPool @@ -60,6 +60,9 @@ * sambaMungedDial * sambaLogonHours */ +/* In Samba4 but not in Samba3: +*/ + static struct ldb_val convert_sid_rid(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) { printf("Converting SID TO RID *\n"); @@ -193,6 +196,117 @@ const struct ldb_map_attribute samba3_attributes[] = .type = MAP_KEEP, }, + /* sAMAccountName -> cn */ + { + .local_name = "sAMAccountName", + .type = MAP_RENAME, + .u.rename.remote_name = "cn", + }, + + /* objectCategory */ + { + .local_name = "objectCategory", + .type = MAP_IGNORE, + }, + + /* objectGUID */ + { + .local_name = "objectGUID", + .type = MAP_IGNORE, + }, + + /* objectVersion */ + { + .local_name = "objectVersion", + .type = MAP_IGNORE, + }, + + /* codePage */ + { + .local_name = "codePage", + .type = MAP_IGNORE, + }, + + /* dNSHostName */ + { + .local_name = "dNSHostName", + .type = MAP_IGNORE, + }, + + + /* dnsDomain */ + { + .local_name = "dnsDomain", + .type = MAP_IGNORE, + }, + + /* dnsRoot */ + { + .local_name = "dnsRoot", + .type = MAP_IGNORE, + }, + + /* countryCode */ + { + .local_name = "countryCode", + .type = MAP_IGNORE, + }, + + /* nTMixedDomain */ + { + .local_name = "nTMixedDomain", + .type = MAP_IGNORE, + }, + + /* operatingSystem */ + { + .local_name = "operatingSystem", + .type = MAP_IGNORE, + }, + + /* operatingSystemVersion */ + { + .local_name = "operatingSystemVersion", + .type = MAP_IGNORE, + }, + + + /* servicePrincipalName */ + { + .local_name = "servicePrincipalName", + .type = MAP_IGNORE, + }, + + /* msDS-Behavior-Version */ + { + .local_name = "msDS-Behavior-Version", + .type = MAP_IGNORE, + }, + + /* msDS-KeyVersionNumber */ + { + .local_name = "msDS-KeyVersionNumber", + .type = MAP_IGNORE, + }, + + /* msDs-masteredBy */ + { + .local_name = "msDs-masteredBy", + .type = MAP_IGNORE, + }, + + /* ou */ + { + .local_name = "ou", + .type = MAP_KEEP, + }, + + /* dc */ + { + .local_name = "dc", + .type = MAP_KEEP, + }, + /* description */ { .local_name = "description", @@ -212,12 +326,295 @@ const struct ldb_map_attribute samba3_attributes[] = .type = MAP_RENAME, .u.rename.remote_name = "sambaPwdLastSet", }, + + /* accountExpires */ + { + .local_name = "accountExpires", + .type = MAP_IGNORE, + }, + + /* adminCount */ + { + .local_name = "adminCount", + .type = MAP_IGNORE, + }, + + /* canonicalName */ + { + .local_name = "canonicalName", + .type = MAP_IGNORE, + }, + + /* createTimestamp */ + { + .local_name = "createTimestamp", + .type = MAP_IGNORE, + }, - /* cn -> cn */ + /* creationTime */ { - .local_name = "cn", - .type = MAP_KEEP, + .local_name = "creationTime", + .type = MAP_IGNORE, + }, + + /* dMDLocation */ + { + .local_name = "dMDLocation", + .type = MAP_IGNORE, + }, + + /* fSMORoleOwner */ + { + .local_name = "fSMORoleOwner", + .type = MAP_IGNORE, + }, + + /* forceLogoff */ + { + .local_name = "forceLogoff", + .type = MAP_IGNORE, + }, + + /* instanceType */ + { + .local_name = "instanceType", + .type = MAP_IGNORE, + }, + + /* invocationId */ + { + .local_name = "invocationId", + .type = MAP_IGNORE, + }, + + /* isCriticalSystemObject */ + { + .local_name = "isCriticalSystemObject", + .type = MAP_IGNORE, + }, + + /* localPolicyFlags */ + { + .local_name = "localPolicyFlags", + .type = MAP_IGNORE, + }, + + /* lockOutObservationWindow */ + { + .local_name = "lockOutObservationWindow", + .type = MAP_IGNORE, + }, + + /* lockoutDuration */ + { + .local_name = "lockoutDuration", + .type = MAP_IGNORE, + }, + + /* lockoutThreshold */ + { + .local_name = "lockoutThreshold", + .type = MAP_IGNORE, + }, + + /* logonCount */ + { + .local_name = "logonCount", + .type = MAP_IGNORE, + }, + + /* masteredBy */ + { + .local_name = "masteredBy", + .type = MAP_IGNORE, + }, + + /* maxPwdAge */ + { + .local_name = "maxPwdAge", + .type = MAP_IGNORE, + }, + + /* member */ + { + .local_name = "member", + .type = MAP_IGNORE, }, + + /* memberOf */ + { + .local_name = "memberOf", + .type = MAP_IGNORE, + }, + + /* minPwdAge */ + { + .local_name = "minPwdAge", + .type = MAP_IGNORE, + }, + + /* minPwdLength */ + { + .local_name = "minPwdLength", + .type = MAP_IGNORE, + }, + + /* modifiedCount */ + { + .local_name = "modifiedCount", + .type = MAP_IGNORE, + }, + + /* modifiedCountAtLastProm */ + { + .local_name = "modifiedCountAtLastProm", + .type = MAP_IGNORE, + }, + + /* modifyTimestamp */ + { + .local_name = "modifyTimestamp", + .type = MAP_IGNORE, + }, + + /* nCName */ + { + .local_name = "nCName", + .type = MAP_IGNORE, + }, + + /* nETBIOSName */ + { + .local_name = "nETBIOSName", + .type = MAP_IGNORE, + }, + + /* oEMInformation */ + { + .local_name = "oEMInformation", + .type = MAP_IGNORE, + }, + + /* privilege */ + { + .local_name = "privilege", + .type = MAP_IGNORE, + }, + + /* pwdHistoryLength */ + { + .local_name = "pwdHistoryLength", + .type = MAP_IGNORE, + }, + + /* pwdProperties */ + { + .local_name = "pwdProperties", + .type = MAP_IGNORE, + }, + + /* rIDAvailablePool */ + { + .local_name = "rIDAvailablePool", + .type = MAP_IGNORE, + }, + + /* revision */ + { + .local_name = "revision", + .type = MAP_IGNORE, + }, + + /* ridManagerReference */ + { + .local_name = "ridManagerReference", + .type = MAP_IGNORE, + }, + + /* sAMAccountType */ + { + .local_name = "sAMAccountType", + .type = MAP_IGNORE, + }, + + /* sPNMappings */ + { + .local_name = "sPNMappings", + .type = MAP_IGNORE, + }, + + /* serverReference */ + { + .local_name = "serverReference", + .type = MAP_IGNORE, + }, + + /* serverState */ + { + .local_name = "serverState", + .type = MAP_IGNORE, + }, + + /* showInAdvancedViewOnly */ + { + .local_name = "showInAdvancedViewOnly", + .type = MAP_IGNORE, + }, + + /* subRefs */ + { + .local_name = "subRefs", + .type = MAP_IGNORE, + }, + + /* systemFlags */ + { + .local_name = "systemFlags", + .type = MAP_IGNORE, + }, + + /* uASCompat */ + { + .local_name = "uASCompat", + .type = MAP_IGNORE, + }, + + /* uSNChanged */ + { + .local_name = "uSNChanged", + .type = MAP_IGNORE, + }, + + /* uSNCreated */ + { + .local_name = "uSNCreated", + .type = MAP_IGNORE, + }, + + /* unicodePwd */ + { + .local_name = "unicodePwd", + .type = MAP_IGNORE, + }, + + /* userAccountControl */ + { + .local_name = "userAccountControl", + .type = MAP_IGNORE, + }, + + /* whenChanged */ + { + .local_name = "whenChanged", + .type = MAP_IGNORE, + }, + + /* whenCreated */ + { + .local_name = "whenCreated", + .type = MAP_IGNORE, + }, + { .local_name = NULL, } -- cgit From 37059d70d9ef905bbcea715e93f5057caf0759d1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 28 Aug 2005 01:37:27 +0000 Subject: r9700: Change DATA_BLOB in ejs back to struct datablob Support writing idmap mappings to winbind.ldif (This used to be commit 3709def35303f1afed0f344628fe2c89250ee087) --- source4/lib/samba3/idmap.c | 2 +- source4/lib/samba3/samba3.c | 2 +- source4/lib/samba3/upgrade.c | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index ce3d098d3a..ad0ef72ef2 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -46,7 +46,7 @@ NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmap /* Open idmap repository */ if (!(tdb = tdb_open(fn, 0, TDB_DEFAULT, O_RDONLY, 0644))) { - DEBUG(0, ("idmap_init: Unable to open idmap database\n")); + DEBUG(0, ("idmap_init: Unable to open idmap database '%s'\n", fn)); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index f8ee24ee3b..08debe96b1 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -107,7 +107,7 @@ NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, s samba3_read_grouptdb(dbfile, ctx, &ret->group); SAFE_FREE(dbfile); - asprintf(&dbfile, "%s/idmap.tdb", libdir); + asprintf(&dbfile, "%s/winbindd_idmap.tdb", libdir); samba3_read_idmap(dbfile, ctx, &ret->idmap); SAFE_FREE(dbfile); diff --git a/source4/lib/samba3/upgrade.c b/source4/lib/samba3/upgrade.c index 941b0fe196..eeb77310ec 100644 --- a/source4/lib/samba3/upgrade.c +++ b/source4/lib/samba3/upgrade.c @@ -109,16 +109,48 @@ int samba3_upgrade_registry(struct samba3_regdb *regdb, const char *prefix, stru return count; } -int samba3_upgrade_sam(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +int samba3_upgrade_sam(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) { + int count = 0; + struct ldb_message *msg; + struct ldb_dn *domaindn = NULL; + *msgs = NULL; + + /* Domain */ + msg = msg_array_add(ldb, msgs, &count); + + /* FIXME: Guess domain DN by taking ldap bind dn? */ + /* FIXME */ return -1; } -int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ctx, struct ldb_message ***msgs) +int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) { - /* FIXME */ - return -1; + int i; + int count = 0; + struct ldb_message *msg; + struct ldb_dn *basedn = NULL; + *msgs = NULL; + + msg = msg_array_add(ldb, msgs, &count); + + msg->dn = basedn; + + ldb_msg_add_fmt(ldb, msg, "userHwm", "%d", samba3->idmap.user_hwm); + ldb_msg_add_fmt(ldb, msg, "groupHwm", "%d", samba3->idmap.group_hwm); + + for (i = 0; i < samba3->idmap.mapping_count; i++) { + char *sid = dom_sid_string(msg, samba3->idmap.mappings[i].sid); + msg = msg_array_add(ldb, msgs, &count); + + msg->dn = ldb_dn_build_child(ldb, "SID", sid, basedn); + ldb_msg_add_string(ldb, msg, "SID", sid); + ldb_msg_add_fmt(ldb, msg, "type", "%d", samba3->idmap.mappings[i].type); + ldb_msg_add_fmt(ldb, msg, "unixID", "%u", samba3->idmap.mappings[i].unix_id); + } + + return count; } int samba3_upgrade_winsdb(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) -- cgit From c98c6aa5611f26ab591c50fcded1fc55e81a0d07 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Aug 2005 02:37:14 +0000 Subject: r9702: r9680@blu: tridge | 2005-08-27 18:45:08 +1000 - fixed ncacn_ip_tcp to use the generic async name resolution methods, so NBT names now work (as requested several times by abartlet!) - changed resolve_name() to take an event_context, so it doesn't cause the whole process to block - cleaned up the talloc_find_parent_bytype() calls to go via a cleaner event_context_find() call (This used to be commit b3d491b210a8b889a25efcb273e70fefbd01b7f7) --- source4/lib/db_wrap.c | 8 ++------ source4/lib/events/events.c | 14 ++++++++++++++ source4/lib/events/events.h | 2 ++ source4/lib/socket/connect.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 8698e9affd..77af27ff36 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -29,6 +29,7 @@ #include "includes.h" #include "dlinklist.h" +#include "lib/events/events.h" #include "lib/tdb/include/tdb.h" #include "lib/ldb/include/ldb.h" #include "db_wrap.h" @@ -76,12 +77,7 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, /* we want to use the existing event context if possible. This relies on the fact that in smbd, everything is a child of the main event_context */ - ev = talloc_find_parent_bytype(mem_ctx, struct event_context); - if (ev) { - ldb_set_opaque(ldb, "EventContext", ev); - } else { - DEBUG(5,("WARNING: event_context not found\n")); - } + ev = event_context_find(ldb); ret = ldb_register_samba_handlers(ldb); if (ret == -1) { diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index 83b013f366..b6ba79430c 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -153,3 +153,17 @@ int event_loop_wait(struct event_context *ev) { return ev->ops->loop_wait(ev); } + +/* + find an event context that is a parent of the given memory context, + or create a new event context as a child of the given context if + none is found +*/ +struct event_context *event_context_find(TALLOC_CTX *mem_ctx) +{ + struct event_context *ev = talloc_find_parent_bytype(mem_ctx, struct event_context); + if (ev == NULL) { + ev = event_context_init(mem_ctx); + } + return ev; +} diff --git a/source4/lib/events/events.h b/source4/lib/events/events.h index 794407204b..3570229715 100644 --- a/source4/lib/events/events.h +++ b/source4/lib/events/events.h @@ -49,6 +49,8 @@ int event_loop_wait(struct event_context *ev); uint16_t event_get_fd_flags(struct fd_event *fde); void event_set_fd_flags(struct fd_event *fde, uint16_t flags); +struct event_context *event_context_find(TALLOC_CTX *mem_ctx); + /* bits for file descriptor event flags */ #define EVENT_FD_READ 1 #define EVENT_FD_WRITE 2 diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c index abe474720c..567c8f41d2 100644 --- a/source4/lib/socket/connect.c +++ b/source4/lib/socket/connect.c @@ -24,6 +24,29 @@ #include "includes.h" #include "lib/socket/socket.h" #include "lib/events/events.h" +#include "librpc/gen_ndr/nbt.h" + + +/* + async name resolution handler for socket_connect_ev, returnes either + an IP address or 'localhost' (which is specially recognised) +*/ +static NTSTATUS connect_resolve(TALLOC_CTX *mem_ctx, const char *address, + struct event_context *ev, const char **ret_address) +{ + struct nbt_name name; + + if (is_ipaddress(address) || strcasecmp("localhost", address) == 0) { + *ret_address = address; + return NT_STATUS_OK; + } + + name.name = address; + name.scope = NULL; + name.type = NBT_NAME_CLIENT; + + return resolve_name(&name, mem_ctx, ret_address, ev); +} /* @@ -52,6 +75,16 @@ NTSTATUS socket_connect_ev(struct socket_context *sock, TALLOC_CTX *tmp_ctx = talloc_new(sock); NTSTATUS status; + /* + we resolve separately to ensure that the name resolutions happens + asynchronously + */ + status = connect_resolve(tmp_ctx, server_address, ev, &server_address); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + set_blocking(socket_get_fd(sock), False); status = socket_connect(sock, my_address, my_port, -- cgit From c9d937b7ebd372a91cbd94130e5995c76e155a0a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Aug 2005 02:37:27 +0000 Subject: r9703: r9683@blu: tridge | 2005-08-27 18:56:05 +1000 added a comment about event_context_find() (This used to be commit 9c230082215dd1f7f19f6b797e7f0c60a9e933fd) --- source4/lib/events/events.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/events/events.c b/source4/lib/events/events.c index b6ba79430c..4e6eeef78e 100644 --- a/source4/lib/events/events.c +++ b/source4/lib/events/events.c @@ -158,6 +158,10 @@ int event_loop_wait(struct event_context *ev) find an event context that is a parent of the given memory context, or create a new event context as a child of the given context if none is found + + This should be used in preference to event_context_init() in places + where you would prefer to use the existing event context if possible + (which is most situations) */ struct event_context *event_context_find(TALLOC_CTX *mem_ctx) { -- cgit From 75c29073ce12723598e4e204ccb616cd52fa2c13 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Aug 2005 02:37:38 +0000 Subject: r9704: r9684@blu: tridge | 2005-08-27 19:38:31 +1000 don't try to call the name resolver on non-ipv4 names! (This used to be commit 4bb3d36fe6705bc625fe4122500f681ab7f2dc53) --- source4/lib/socket/connect.c | 15 ++++++++++----- source4/lib/socket/socket.h | 1 + source4/lib/socket/socket_ipv4.c | 2 ++ source4/lib/socket/socket_ipv6.c | 2 ++ source4/lib/socket/socket_unix.c | 2 ++ 5 files changed, 17 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c index 567c8f41d2..bb4d7cc843 100644 --- a/source4/lib/socket/connect.c +++ b/source4/lib/socket/connect.c @@ -74,15 +74,20 @@ NTSTATUS socket_connect_ev(struct socket_context *sock, { TALLOC_CTX *tmp_ctx = talloc_new(sock); NTSTATUS status; - + /* we resolve separately to ensure that the name resolutions happens asynchronously + + the check for ipv4 is ugly, but how to do it better? We don't want + to try to resolve unix pathnames here */ - status = connect_resolve(tmp_ctx, server_address, ev, &server_address); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return status; + if (strcmp(sock->backend_name, "ipv4") == 0) { + status = connect_resolve(tmp_ctx, server_address, ev, &server_address); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } } set_blocking(socket_get_fd(sock), False); diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h index 8645ba28bc..27a1dfe041 100644 --- a/source4/lib/socket/socket.h +++ b/source4/lib/socket/socket.h @@ -102,6 +102,7 @@ struct socket_context { void *private_data; const struct socket_ops *ops; + const char *backend_name; }; diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 0fc65698c4..9c393a77ec 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -46,6 +46,8 @@ static NTSTATUS ipv4_init(struct socket_context *sock) return map_nt_error_from_unix(errno); } + sock->backend_name = "ipv4"; + return NT_STATUS_OK; } diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index 58e35d87de..da3a69e81e 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -44,6 +44,8 @@ static NTSTATUS ipv6_tcp_init(struct socket_context *sock) return map_nt_error_from_unix(errno); } + sock->backend_name = "ipv6"; + return NT_STATUS_OK; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index 9c19aaace5..c5af48da0f 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -57,6 +57,8 @@ static NTSTATUS unixdom_init(struct socket_context *sock) } sock->private_data = NULL; + sock->backend_name = "unix"; + return NT_STATUS_OK; } -- cgit From 1ef362c89d98777651c8789af4b74a0a6fb9fcdc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 28 Aug 2005 02:37:49 +0000 Subject: r9705: r9685@blu: tridge | 2005-08-27 19:43:44 +1000 set the backend_name on socket_accept() too (This used to be commit 10ac2732881ac73dd9cb8162beb1efd741bfe3d2) --- source4/lib/socket/socket.c | 1 + source4/lib/socket/socket_ipv4.c | 1 + source4/lib/socket/socket_ipv6.c | 1 + source4/lib/socket/socket_unix.c | 1 + 4 files changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c index db249522a2..380071f46d 100644 --- a/source4/lib/socket/socket.c +++ b/source4/lib/socket/socket.c @@ -53,6 +53,7 @@ static NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ (*new_sock)->private_data = NULL; (*new_sock)->ops = ops; + (*new_sock)->backend_name = NULL; status = (*new_sock)->ops->fn_init((*new_sock)); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/lib/socket/socket_ipv4.c b/source4/lib/socket/socket_ipv4.c index 9c393a77ec..34ae0b2b73 100644 --- a/source4/lib/socket/socket_ipv4.c +++ b/source4/lib/socket/socket_ipv4.c @@ -226,6 +226,7 @@ static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context * (*new_sock)->private_data = NULL; (*new_sock)->ops = sock->ops; + (*new_sock)->backend_name = sock->backend_name; return NT_STATUS_OK; } diff --git a/source4/lib/socket/socket_ipv6.c b/source4/lib/socket/socket_ipv6.c index da3a69e81e..ee3e118349 100644 --- a/source4/lib/socket/socket_ipv6.c +++ b/source4/lib/socket/socket_ipv6.c @@ -203,6 +203,7 @@ static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_conte (*new_sock)->private_data = NULL; (*new_sock)->ops = sock->ops; + (*new_sock)->backend_name = sock->backend_name; return NT_STATUS_OK; } diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c index c5af48da0f..0c65bb46fb 100644 --- a/source4/lib/socket/socket_unix.c +++ b/source4/lib/socket/socket_unix.c @@ -200,6 +200,7 @@ static NTSTATUS unixdom_accept(struct socket_context *sock, (*new_sock)->private_data = NULL; (*new_sock)->ops = sock->ops; + (*new_sock)->backend_name = sock->backend_name; return NT_STATUS_OK; } -- cgit From 8b15ef881d21b713817bb3aa3599288ecdde0d28 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 28 Aug 2005 14:55:26 +0000 Subject: r9712: Bunch of small fixes Write out basic sam.ldif (This used to be commit 67593bef7f0f8dc2258b2fe9c06779f0025d240e) --- source4/lib/ldb/samba/samba3sam.c | 2 +- source4/lib/samba3/group.c | 15 +++--- source4/lib/samba3/idmap.c | 2 +- source4/lib/samba3/samba3.c | 102 +++++++++++++++++++++++++----------- source4/lib/samba3/samba3dump.c | 20 ++++++-- source4/lib/samba3/share_info.c | 2 +- source4/lib/samba3/tdbsam.c | 1 + source4/lib/samba3/upgrade.c | 105 ++++++++++++++++++++++++++++++++++++-- 8 files changed, 201 insertions(+), 48 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index d114839047..aef50e4d3e 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -200,7 +200,7 @@ const struct ldb_map_attribute samba3_attributes[] = { .local_name = "sAMAccountName", .type = MAP_RENAME, - .u.rename.remote_name = "cn", + .u.rename.remote_name = "uid", }, /* objectCategory */ diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index 68ac5987d0..220f206e99 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -82,16 +82,21 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g if (!dbuf.dptr) continue; - map.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(GROUP_PREFIX)); + ZERO_STRUCT(map); - ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "ddff", - &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); + map.sid = dom_sid_parse_talloc(ctx, kbuf.dptr+strlen(GROUP_PREFIX)); + ret = tdb_unpack(tdb, dbuf.dptr, dbuf.dsize, "dd", + &map.gid, &map.sid_name_use); + if ( ret == -1 ) { DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); continue; } + map.nt_name = talloc_strdup(ctx, dbuf.dptr+ret); + map.comment = talloc_strdup(ctx, dbuf.dptr+ret+strlen(map.nt_name)); + db->groupmappings = talloc_realloc(ctx, db->groupmappings, struct samba3_groupmapping, db->groupmap_count+1); if (!db->groupmappings) @@ -100,9 +105,7 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g db->groupmappings[db->groupmap_count] = map; db->groupmap_count++; - } - - if (strncmp(kbuf.dptr, MEMBEROF_PREFIX, strlen(MEMBEROF_PREFIX)) == 0) + } else if (strncmp(kbuf.dptr, MEMBEROF_PREFIX, strlen(MEMBEROF_PREFIX)) == 0) { struct samba3_alias alias; pstring alias_string; diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index ad0ef72ef2..b1c7c0dcca 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -39,7 +39,7 @@ Initialise idmap database. *****************************************************************************/ -NTSTATUS samba3_read_idmap( const char *fn, TALLOC_CTX *ctx, struct samba3_idmapdb *idmap ) +NTSTATUS samba3_read_idmap(const char *fn, TALLOC_CTX *ctx, struct samba3_idmapdb *idmap) { TDB_CONTEXT *tdb; TDB_DATA key, val; diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 08debe96b1..4b893c585a 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -26,7 +26,19 @@ struct smbconf_data { struct samba3_share_info *current_share; }; -struct samba3_share_info *samba3_find_share(struct samba3 *db, TALLOC_CTX* ctx, const char *name) +struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const char *name) +{ + int i; + + for (i = 0; i < db->secrets.domain_count; i++) { + if (!StrCaseCmp(db->secrets.domains[i].name, name)) + return &db->secrets.domains[i]; + } + + return NULL; +} + +struct samba3_share_info *samba3_find_share(struct samba3 *db, const char *name) { int i; for (i = 0; i < db->share_count; i++) { @@ -34,19 +46,47 @@ struct samba3_share_info *samba3_find_share(struct samba3 *db, TALLOC_CTX* ctx, return &db->shares[i]; } + return NULL; +} + + +struct samba3_share_info *samba3_find_add_share(struct samba3 *db, TALLOC_CTX* ctx, const char *name) +{ + struct samba3_share_info *share = samba3_find_share(db, name); + + if (share) + return share; + db->shares = talloc_realloc(ctx, db->shares, struct samba3_share_info, db->share_count+1); - ZERO_STRUCT(db->shares[i]); - db->shares[i].name = talloc_strdup(ctx, name); + ZERO_STRUCT(db->shares[db->share_count]); + db->shares[db->share_count].name = talloc_strdup(ctx, name); db->share_count++; - return &db->shares[i]; + return &db->shares[db->share_count-1]; +} + +const char *samba3_get_param(struct samba3 *samba3, const char *section, const char *param) +{ + int i; + struct samba3_share_info *share = samba3_find_share(samba3, section); + + if (share == NULL) + return NULL; + + for (i = 0; i < share->parameter_count; i++) { + if (!StrCaseCmp(share->parameters[i].name, param)) + return share->parameters[i].value; + } + + return NULL; } + static BOOL samba3_sfunc (const char *name, void *_db) { struct smbconf_data *privdat = _db; - privdat->current_share = samba3_find_share(privdat->db, privdat->ctx, name); + privdat->current_share = samba3_find_add_share(privdat->db, privdat->ctx, name); return True; } @@ -76,7 +116,7 @@ NTSTATUS samba3_read_smbconf(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) privdat.ctx = ctx; privdat.db = db; - privdat.current_share = samba3_find_share(db, ctx, "global"); + privdat.current_share = samba3_find_add_share(db, ctx, "global"); if (!pm_process( fn, samba3_sfunc, samba3_pfunc, &privdat )) { return NT_STATUS_UNSUCCESSFUL; @@ -88,44 +128,44 @@ NTSTATUS samba3_read_smbconf(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, struct samba3 **samba3) { struct samba3 *ret; - char *dbfile; + char *dbfile = NULL; ret = talloc_zero(ctx, struct samba3); if (smbconf) samba3_read_smbconf(smbconf, ctx, ret); - asprintf(&dbfile, "%s/wins.dat", libdir); - samba3_read_winsdb(dbfile, ret, &ret->winsdb_entries, &ret->winsdb_count); - SAFE_FREE(dbfile); - - asprintf(&dbfile, "%s/passdb.tdb", libdir); - samba3_read_tdbsam(dbfile, ctx, &ret->samaccounts, &ret->samaccount_count); - SAFE_FREE(dbfile); - - asprintf(&dbfile, "%s/group_mapping.tdb", libdir); - samba3_read_grouptdb(dbfile, ctx, &ret->group); - SAFE_FREE(dbfile); - - asprintf(&dbfile, "%s/winbindd_idmap.tdb", libdir); - samba3_read_idmap(dbfile, ctx, &ret->idmap); - SAFE_FREE(dbfile); - - asprintf(&dbfile, "%s/account_policy.tdb", libdir); + dbfile = talloc_asprintf(ctx, "%s/account_policy.tdb", libdir); samba3_read_account_policy(dbfile, ctx, &ret->policy); - SAFE_FREE(dbfile); + talloc_free(dbfile); - asprintf(&dbfile, "%s/registry.tdb", libdir); + dbfile = talloc_asprintf(ctx, "%s/registry.tdb", libdir); samba3_read_regdb(dbfile, ctx, &ret->registry); - SAFE_FREE(dbfile); + talloc_free(dbfile); - asprintf(&dbfile, "%s/secrets.tdb", libdir); + dbfile = talloc_asprintf(ctx, "%s/secrets.tdb", libdir); samba3_read_secrets(dbfile, ctx, &ret->secrets); - SAFE_FREE(dbfile); + talloc_free(dbfile); - asprintf(&dbfile, "%s/share_info.tdb", libdir); + dbfile = talloc_asprintf(ctx, "%s/share_info.tdb", libdir); samba3_read_share_info(dbfile, ctx, ret); - SAFE_FREE(dbfile); + talloc_free(dbfile); + + dbfile = talloc_asprintf(ctx, "%s/winbindd_idmap.tdb", libdir); + samba3_read_idmap(dbfile, ctx, &ret->idmap); + talloc_free(dbfile); + + dbfile = talloc_asprintf(ctx, "%s/wins.dat", libdir); + samba3_read_winsdb(dbfile, ret, &ret->winsdb_entries, &ret->winsdb_count); + talloc_free(dbfile); + + dbfile = talloc_asprintf(ctx, "%s/passdb.tdb", libdir); + samba3_read_tdbsam(dbfile, ctx, &ret->samaccounts, &ret->samaccount_count); + talloc_free(dbfile); + + dbfile = talloc_asprintf(ctx, "%s/group_mapping.tdb", libdir); + samba3_read_grouptdb(dbfile, ctx, &ret->group); + talloc_free(dbfile); *samba3 = ret; diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index a6166a1c6b..b95fc0d4b2 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -244,25 +244,35 @@ int main(int argc, char **argv) { int opt; const char *format = "summary"; - const char *libdir = "/var/lib/samba"; + char *libdir = NULL; + char *smbconf = NULL; struct samba3 *samba3; poptContext pc; + TALLOC_CTX *mem_ctx; struct poptOption long_options[] = { POPT_AUTOHELP { "format", 0, POPT_ARG_STRING, &format, 'f', "Format to use (one of: summary, text, ldif)" }, - { "libdir", 0, POPT_ARG_STRING, &libdir, 'l', "Set libdir [/var/lib/samba]", "LIBDIR" }, POPT_COMMON_SAMBA POPT_TABLEEND }; pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); - poptSetOtherOptionHelp(pc, ""); + poptSetOtherOptionHelp(pc, " "); while((opt = poptGetNextOpt(pc)) != -1) { } - samba3_read(poptGetArg(pc), libdir, NULL, &samba3); + samba3dump_init_subsystems; + + mem_ctx = talloc_init("samba3dump_context"); + + libdir = talloc_strdup(mem_ctx, poptGetArg(pc)); + smbconf = talloc_strdup(mem_ctx, poptGetArg(pc)); + + printf("Reading from libdir '%s', smb.conf file '%s'\n", libdir, smbconf); + + samba3_read(smbconf, libdir, mem_ctx, &samba3); if (!strcmp(format, "summary")) { printf("WINS db entries: %d\n", samba3->winsdb_count); @@ -276,7 +286,7 @@ int main(int argc, char **argv) print_samba3(samba3); } else if (!strcmp(format, "ldif")) { struct ldb_message **msgs; - struct ldb_context *ldb = ldb_init(NULL); + struct ldb_context *ldb = ldb_init(mem_ctx); int i, ret; const char *hives[] = { "hklm", "hkcr", "hku", "hkpd", "hkpt", NULL }; diff --git a/source4/lib/samba3/share_info.c b/source4/lib/samba3/share_info.c index 098d6c552e..3479a7063c 100644 --- a/source4/lib/samba3/share_info.c +++ b/source4/lib/samba3/share_info.c @@ -66,7 +66,7 @@ NTSTATUS samba3_read_share_info(const char *fn, TALLOC_CTX *ctx, struct samba3 * name = talloc_strndup(ctx, kbuf.dptr+strlen("SECDESC/"), kbuf.dsize-strlen("SECDESC/")); - share = samba3_find_share(db, ctx, name); + share = samba3_find_add_share(db, ctx, name); vbuf = tdb_fetch(tdb, kbuf); blob.data = (uint8_t *)vbuf.dptr; diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index 23e68717c7..c9b121ca77 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -271,6 +271,7 @@ NTSTATUS samba3_read_tdbsam(const char *filename, TALLOC_CTX *ctx, struct samba3 case 0: ret = init_sam_from_buffer_v0(tdb, &(*accounts)[*count], val); break; case 1: ret = init_sam_from_buffer_v1(tdb, &(*accounts)[*count], val); break; case 2: ret = init_sam_from_buffer_v2(tdb, &(*accounts)[*count], val); break; + default: ret = False; break; } diff --git a/source4/lib/samba3/upgrade.c b/source4/lib/samba3/upgrade.c index eeb77310ec..00000c68df 100644 --- a/source4/lib/samba3/upgrade.c +++ b/source4/lib/samba3/upgrade.c @@ -114,15 +114,114 @@ int samba3_upgrade_sam(struct samba3 *samba3, struct ldb_context *ldb, struct ld int count = 0; struct ldb_message *msg; struct ldb_dn *domaindn = NULL; + const char *domainname; + struct samba3_domainsecrets *domsec; + int i; *msgs = NULL; + domainname = samba3_get_param(samba3, "global", "workgroup"); + + if (domainname == NULL) { + DEBUG(0, ("No domain name specified in smb.conf!\n")); + return -1; + } + + domsec = samba3_find_domainsecrets(samba3, domainname); + /* Domain */ msg = msg_array_add(ldb, msgs, &count); - /* FIXME: Guess domain DN by taking ldap bind dn? */ - /* FIXME */ - return -1; + ldb_msg_add_string(ldb, msg, "objectClass", "top"); + ldb_msg_add_string(ldb, msg, "objectClass", "domain"); + ldb_msg_add_string(ldb, msg, "objectSid", dom_sid_string(msg, &domsec->sid)); + ldb_msg_add_string(ldb, msg, "objectGUID", GUID_string(msg, &domsec->guid)); + ldb_msg_add_string(ldb, msg, "name", domainname); + ldb_msg_add_string(ldb, msg, "oEMInformation", "Provisioned by Samba4 (upgraded from Samba3)"); + + /* account policy as well */ + + ldb_msg_add_fmt(ldb, msg, "minPwdLength", "%d", samba3->policy.min_password_length); + ldb_msg_add_fmt(ldb, msg, "pwdHistoryLength", "%d", samba3->policy.password_history); + ldb_msg_add_fmt(ldb, msg, "minPwdAge", "%d", samba3->policy.minimum_password_age); + ldb_msg_add_fmt(ldb, msg, "maxPwdAge", "%d", samba3->policy.maximum_password_age); + ldb_msg_add_fmt(ldb, msg, "lockoutDuration", "%d", samba3->policy.lockout_duration); + ldb_msg_add_fmt(ldb, msg, "samba3ResetCountMinutes", "%d", samba3->policy.reset_count_minutes); + ldb_msg_add_fmt(ldb, msg, "samba3UserMustLogonToChangePassword", "%d", samba3->policy.user_must_logon_to_change_password); + ldb_msg_add_fmt(ldb, msg, "samba3BadLockoutMinutes", "%d", samba3->policy.bad_lockout_minutes); + ldb_msg_add_fmt(ldb, msg, "samba3DisconnectTime", "%d", samba3->policy.disconnect_time); + ldb_msg_add_fmt(ldb, msg, "samba3RefuseMachinePwdChange", "%d", samba3->policy.refuse_machine_password_change); + + /* Users */ + for (i = 0; i < samba3->samaccount_count; i++) { + struct samba3_samaccount *sam = &samba3->samaccounts[i]; + + msg = msg_array_add(ldb, msgs, &count); + msg->dn = ldb_dn_build_child(msg, "cn", sam->fullname, domaindn); + + ldb_msg_add_string(ldb, msg, "objectClass", "top"); + ldb_msg_add_string(ldb, msg, "objectClass", "person"); + ldb_msg_add_string(ldb, msg, "objectClass", "user"); + ldb_msg_add_fmt(ldb, msg, "lastLogon", "%d", sam->logon_time); + ldb_msg_add_fmt(ldb, msg, "lastLogoff", "%d", sam->logoff_time); + ldb_msg_add_string(ldb, msg, "unixName", sam->username); + ldb_msg_add_string(ldb, msg, "name", sam->nt_username); + ldb_msg_add_string(ldb, msg, "cn", sam->fullname); + ldb_msg_add_string(ldb, msg, "description", sam->acct_desc); + ldb_msg_add_fmt(ldb, msg, "primaryGroupID", "%d", sam->group_rid); + ldb_msg_add_fmt(ldb, msg, "badPwdcount", "%d", sam->bad_password_count); + ldb_msg_add_fmt(ldb, msg, "logonCount", "%d", sam->logon_count); + + ldb_msg_add_string(ldb, msg, "samba3Domain", sam->domain); + if (sam->dir_drive) + ldb_msg_add_string(ldb, msg, "samba3DirDrive", sam->dir_drive); + + if (sam->munged_dial) + ldb_msg_add_string(ldb, msg, "samba3MungedDial", sam->munged_dial); + + if (sam->homedir) + ldb_msg_add_string(ldb, msg, "samba3Homedir", sam->homedir); + + if (sam->logon_script) + ldb_msg_add_string(ldb, msg, "samba3LogonScript", sam->logon_script); + + if (sam->profile_path) + ldb_msg_add_string(ldb, msg, "samba3ProfilePath", sam->profile_path); + + if (sam->workstations) + ldb_msg_add_string(ldb, msg, "samba3Workstations", sam->workstations); + + ldb_msg_add_fmt(ldb, msg, "samba3KickOffTime", "%d", sam->kickoff_time); + ldb_msg_add_fmt(ldb, msg, "samba3BadPwdTime", "%d", sam->bad_password_time); + ldb_msg_add_fmt(ldb, msg, "samba3PassLastSetTime", "%d", sam->pass_last_set_time); + ldb_msg_add_fmt(ldb, msg, "samba3PassCanChangeTime", "%d", sam->pass_can_change_time); + ldb_msg_add_fmt(ldb, msg, "samba3PassMustChangeTime", "%d", sam->pass_must_change_time); + ldb_msg_add_fmt(ldb, msg, "samba3Rid", "%d", sam->user_rid); + + /* FIXME: Passwords */ + } + + /* Groups */ + for (i = 0; i < samba3->group.groupmap_count; i++) { + struct samba3_groupmapping *grp = &samba3->group.groupmappings[i]; + + msg = msg_array_add(ldb, msgs, &count); + + if (grp->nt_name != NULL) + msg->dn = ldb_dn_build_child(msg, "cn", grp->nt_name, domaindn); + else + msg->dn = ldb_dn_build_child(msg, "cn", dom_sid_string(msg, grp->sid), domaindn); + + ldb_msg_add_string(ldb, msg, "objectClass", "top"); + ldb_msg_add_string(ldb, msg, "objectClass", "group"); + ldb_msg_add_string(ldb, msg, "description", grp->comment); + ldb_msg_add_string(ldb, msg, "cn", grp->nt_name); + ldb_msg_add_string(ldb, msg, "objectSid", dom_sid_string(msg, grp->sid)); + ldb_msg_add_string(ldb, msg, "unixName", "FIXME"); + ldb_msg_add_fmt(ldb, msg, "samba3SidNameUse", "%d", grp->sid_name_use); + } + + return count; } int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) -- cgit From d6cd54fb0a1c3ac51479d1fdcff91893c27ef9d7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 28 Aug 2005 22:17:07 +0000 Subject: r9718: Work a bit on the SWAT interface (This used to be commit b1844905d2c1ca26aef0ccba799ff16383348fc1) --- source4/lib/ldb/ldb_map/ldb_map.c | 4 +- source4/lib/ldb/tests/samba3.ldif | 106 +++++++++++++++++--------------------- source4/lib/samba3/PLAN | 12 ++++- source4/lib/samba3/README | 3 ++ 4 files changed, 64 insertions(+), 61 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 5ae4a435d8..1a8ea2afc4 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -136,8 +136,10 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL return attr->convert_operator(privdat, module, tree); } - if (map_type == MAP_IGNORE) + if (map_type == MAP_IGNORE) { + DEBUG(0, ("Search on ignored attribute '%s'!\n", tree->u.equality.attr)); return NULL; + } if (map_type == MAP_GENERATE) { DEBUG(0, ("Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr)); diff --git a/source4/lib/ldb/tests/samba3.ldif b/source4/lib/ldb/tests/samba3.ldif index fb0a1386d4..02103b65b6 100644 --- a/source4/lib/ldb/tests/samba3.ldif +++ b/source4/lib/ldb/tests/samba3.ldif @@ -1,49 +1,4 @@ -dn: dc=idealx,dc=org -objectClass: dcObject -objectclass: organization -o: idealx -dc: idealx - -dn: ou=Users,dc=idealx,dc=org -objectClass: organizationalUnit -ou: Users - -dn: ou=Groups,dc=idealx,dc=org -objectClass: organizationalUnit -ou: Groups - -dn: ou=Computers,dc=idealx,dc=org -objectClass: organizationalUnit -ou: Computers -dn: uid=Administrator,ou=Users,dc=idealx,dc=org -cn: Administrator -sn: Administrator -objectClass: inetOrgPerson -objectClass: sambaSAMAccount -objectClass: posixAccount -objectClass: shadowAccount -gidNumber: 512 -uid: Administrator -uidNumber: 0 -homeDirectory: /home/%U -sambaPwdLastSet: 0 -sambaLogonTime: 0 -sambaLogoffTime: 2147483647 -sambaKickoffTime: 2147483647 -sambaPwdCanChange: 0 -sambaPwdMustChange: 2147483647 -sambaHomePath: \\PDC-SMB3\home\%U -sambaHomeDrive: H: -sambaProfilePath: \\PDC-SMB3\profiles\%U\Administrator -sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 -sambaLMPassword: XXX -sambaNTPassword: XXX -sambaAcctFlags: [U ] -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2996 -loginShell: /bin/false -gecos: Netbios Domain Administrator - -dn: uid=nobody,ou=Users,dc=idealx,dc=org +dn: uid=nobody,ou=Users,dc=test,dc=vernstok,dc=nl cn: nobody sn: nobody objectClass: inetOrgPerson @@ -70,7 +25,7 @@ sambaAcctFlags: [NU ] sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2998 loginShell: /bin/false -dn: cn=Domain Admins,ou=Groups,dc=idealx,dc=org +dn: cn=Domain Admins,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 512 @@ -81,7 +36,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-512 sambaGroupType: 2 displayName: Domain Admins -dn: cn=Domain Users,ou=Groups,dc=idealx,dc=org +dn: cn=Domain Users,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 513 @@ -91,7 +46,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-513 sambaGroupType: 2 displayName: Domain Users -dn: cn=Domain Guests,ou=Groups,dc=idealx,dc=org +dn: cn=Domain Guests,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 514 @@ -101,7 +56,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-514 sambaGroupType: 2 displayName: Domain Guests -dn: cn=Print Operators,ou=Groups,dc=idealx,dc=org +dn: cn=Print Operators,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 550 @@ -111,7 +66,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-550 sambaGroupType: 2 displayName: Print Operators -dn: cn=Backup Operators,ou=Groups,dc=idealx,dc=org +dn: cn=Backup Operators,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 551 @@ -121,7 +76,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-551 sambaGroupType: 2 displayName: Backup Operators -dn: cn=Replicator,ou=Groups,dc=idealx,dc=org +dn: cn=Replicator,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 552 @@ -131,7 +86,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 sambaGroupType: 2 displayName: Replicator -dn: cn=Domain Computers,ou=Groups,dc=idealx,dc=org +dn: cn=Domain Computers,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 553 @@ -141,7 +96,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-553 sambaGroupType: 2 displayName: Domain Computers -dn: cn=Administrators,ou=Groups,dc=idealx,dc=org +dn: cn=Administrators,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 544 @@ -151,7 +106,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-544 sambaGroupType: 2 displayName: Administrators -dn: cn=Users,ou=Groups,dc=idealx,dc=org +dn: cn=Users,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 545 @@ -161,7 +116,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-545 sambaGroupType: 2 displayName: users -dn: cn=Guests,ou=Groups,dc=idealx,dc=org +dn: cn=Guests,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 546 @@ -172,7 +127,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-546 sambaGroupType: 2 displayName: Guests -dn: cn=Power Users,ou=Groups,dc=idealx,dc=org +dn: cn=Power Users,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 547 @@ -182,7 +137,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-547 sambaGroupType: 2 displayName: Power Users -dn: cn=Account Operators,ou=Groups,dc=idealx,dc=org +dn: cn=Account Operators,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 548 @@ -192,7 +147,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-548 sambaGroupType: 2 displayName: Account Operators -dn: cn=Server Operators,ou=Groups,dc=idealx,dc=org +dn: cn=Server Operators,ou=Groups,dc=test,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 549 @@ -201,3 +156,36 @@ description: Netbios Domain Server Operators sambaSID: S-1-5-21-4231626423-2410014848-2360679739-549 sambaGroupType: 2 displayName: Server Operators + +dn: ou=Computers,dc=test,dc=vernstok,dc=nl +objectClass: organizationalUnit +ou: Computers +dn: uid=Administrator,ou=Users,dc=test,dc=vernstok,dc=nl +cn: Administrator +sn: Administrator +objectClass: inetOrgPerson +objectClass: sambaSAMAccount +objectClass: posixAccount +objectClass: shadowAccount +gidNumber: 512 +uid: Administrator +uidNumber: 0 +homeDirectory: /home/%U +sambaPwdLastSet: 0 +sambaLogonTime: 0 +sambaLogoffTime: 2147483647 +sambaKickoffTime: 2147483647 +sambaPwdCanChange: 0 +sambaPwdMustChange: 2147483647 +sambaHomePath: \\PDC-SMB3\home\%U +sambaHomeDrive: H: +sambaProfilePath: \\PDC-SMB3\profiles\%U\Administrator +sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 +sambaLMPassword: XXX +sambaNTPassword: XXX +sambaAcctFlags: [U ] +sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2996 +loginShell: /bin/false +gecos: Netbios Domain Administrator + + diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 26bf54634c..8bc90da427 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,6 +1,6 @@ Three possible viable approaches: 1) TDB conversion approach. Read in TDB dump out LDIF (one-way) - - samr.ldb: from tdbsam/smbpasswd, account_policy.tdb, secrets.tdb, group_mapping.tdb, privilege.tdb + - samr.ldb: from tdbsam/smbpasswd, account_policy.tdb, secrets.tdb, group_mapping.tdb - registry.ldb: from registry.tdb - wins.ldif: from wins.tdb/wins.dat - smb.conf/ea's: generated from the old smb.conf + share_info.tdb @@ -29,3 +29,13 @@ Three possible viable approaches: - convert smb.conf (using Jerry's registry hack) (going with a combination of 1 and 2) + +ldb mapping backend: + - do search in new and old (mapped) backend and merge results? + +Upgrade process: + - take libdir & smb.conf + - read various tdb files / old smb.conf + - write new smb.conf (ejs?) + - list of parameters to keep.. generate some of the others + - add generated LDIF (ejs?) diff --git a/source4/lib/samba3/README b/source4/lib/samba3/README index 3f6553f7e8..83520f673d 100644 --- a/source4/lib/samba3/README +++ b/source4/lib/samba3/README @@ -3,3 +3,6 @@ Samba3 import, migration and compatibility. For example, the first file in this directory (smbpasswd.c) handles portions of the smbpasswd file format. + +The other files in this directory support reading the various +TDB databases from Samba3. -- cgit From 24186a80eb4887b5fb3e72e4b877b456cbe8e35f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Aug 2005 04:30:22 +0000 Subject: r9728: A *major* update to the credentials system, to incorporate the Kerberos CCACHE into the system. This again allows the use of the system ccache when no username is specified, and brings more code in common between gensec_krb5 and gensec_gssapi. It also has a side-effect that may (or may not) be expected: If there is a ccache, even if it is not used (perhaps the remote server didn't want kerberos), it will change the default username. Andrew Bartlett (This used to be commit 6202267f6ec1446d6bd11d1d37d05a977bc8d315) --- source4/lib/cmdline/credentials.c | 19 +- source4/lib/cmdline/popt_common.c | 8 +- source4/lib/credentials.c | 318 ++++++++++++++++++++++++++++++---- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 3 +- source4/lib/samba3/samba3dump.c | 7 +- 5 files changed, 312 insertions(+), 43 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c index d827baed76..7832e01e4b 100644 --- a/source4/lib/cmdline/credentials.c +++ b/source4/lib/cmdline/credentials.c @@ -29,14 +29,23 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) { char *prompt; char *ret; - - prompt = talloc_asprintf(NULL, "Password for [%s\\%s]:", - cli_credentials_get_domain(credentials), - cli_credentials_get_username(credentials)); + char *domain; + char *username; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + domain = cli_credentials_get_domain(credentials); + username = cli_credentials_get_username(credentials, mem_ctx); + if (domain && domain[0]) { + prompt = talloc_asprintf(mem_ctx, "Password for [%s\\%s]:", + domain, username); + } else { + prompt = talloc_asprintf(mem_ctx, "Password for [%s]:", + username); + } ret = getpass(prompt); - talloc_free(prompt); + talloc_free(mem_ctx); return ret; } diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 4e808652f7..d3bd0a35a4 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -220,9 +220,11 @@ static void popt_common_credentials_callback(poptContext con, char *lp; cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED); - - if (cmdline_credentials->password && (lp=strchr_m(arg,'%'))) { - memset(lp,0,strlen(cmdline_credentials->password)); + /* This breaks the abstraction, including the const above */ + if (lp=strchr_m(arg,'%')) { + lp[0]='\0'; + lp++; + memset(lp,0,strlen(lp)); } } break; diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index aae55be800..69e237428c 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -25,6 +25,9 @@ #include "include/secrets.h" #include "lib/ldb/include/ldb.h" #include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */ +#include "system/kerberos.h" +#include "auth/kerberos/kerberos.h" + /** * Create a new credentials structure @@ -44,6 +47,8 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) cred->password_obtained = CRED_UNINITIALISED; cred->domain_obtained = CRED_UNINITIALISED; cred->realm_obtained = CRED_UNINITIALISED; + cred->ccache_obtained = CRED_UNINITIALISED; + cred->principal_obtained = CRED_UNINITIALISED; return cred; } @@ -53,18 +58,23 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) * @retval The username set on this context. * @note Return value will never be NULL except by programmer error. */ -const char *cli_credentials_get_username(struct cli_credentials *cred) +const char *cli_credentials_get_username(struct cli_credentials *cred, TALLOC_CTX *mem_ctx) { if (cred->machine_account_pending) { cli_credentials_set_machine_account(cred); } + /* If we have a principal set on this, we want to login with "" domain and user@realm */ + if (cred->username_obtained < cred->principal_obtained) { + return cli_credentials_get_principal(cred, mem_ctx); + } + if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; } - return cred->username; + return talloc_reference(mem_ctx, cred->username); } BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) @@ -78,6 +88,53 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, return False; } +/** + * Obtain the client principal for this credentials context. + * @param cred credentials context + * @retval The username set on this context. + * @note Return value will never be NULL except by programmer error. + */ +const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx) +{ + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + + if (cred->principal_obtained == CRED_CALLBACK) { + cred->principal = cred->principal_cb(cred); + cred->principal_obtained = CRED_SPECIFIED; + } + + if (cred->principal_obtained < cred->username_obtained) { + return talloc_asprintf(mem_ctx, "%s@%s", + cli_credentials_get_username(cred, mem_ctx), + cli_credentials_get_realm(cred)); + } + return talloc_reference(mem_ctx, cred->principal); +} + +BOOL cli_credentials_set_principal(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +{ + if (obtained >= cred->principal_obtained) { + cred->principal = talloc_strdup(cred, val); + cred->principal_obtained = obtained; + return True; + } + + return False; +} + +BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) +{ + if (cred->principal_obtained == CRED_SPECIFIED) { + return True; + } + if (cred->username_obtained >= CRED_SPECIFIED) { + return True; + } + return False; +} + /** * Obtain the password for this credentials context. * @param cred credentials context @@ -148,6 +205,207 @@ BOOL cli_credentials_set_nt_hash(struct cli_credentials *cred, return False; } +int cli_credentials_set_from_ccache(struct cli_credentials *cred, + enum credentials_obtained obtained) +{ + + krb5_principal princ; + krb5_error_code ret; + char *name; + char **realm; + + ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, + cred->ccache->ccache, &princ); + + if (ret) { + char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred); + DEBUG(1,("failed to get principal from ccache: %s\n", + err_mess)); + talloc_free(err_mess); + return ret; + } + + ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name); + if (ret) { + char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred); + DEBUG(1,("failed to unparse principal from ccache: %s\n", + err_mess)); + talloc_free(err_mess); + return ret; + } + + realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ); + + cli_credentials_set_realm(cred, *realm, obtained); + cli_credentials_set_principal(cred, name, obtained); + + free(name); + + krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ); + + cred->ccache_obtained = obtained; + + return 0; +} + + +static int free_mccache(void *ptr) { + struct ccache_container *ccc = ptr; + krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache); + + return 0; +} + +static int free_dccache(void *ptr) { + struct ccache_container *ccc = ptr; + krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache); + + return 0; +} + +static int cli_credentials_set_ccache(struct cli_credentials *cred, + const char *name, + enum credentials_obtained obtained) +{ + krb5_error_code ret; + krb5_principal princ; + struct ccache_container *ccc = talloc(cred, struct ccache_container); + if (!ccc) { + return ENOMEM; + } + + ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); + if (ret) { + talloc_free(ccc); + return ret; + } + if (name) { + ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); + if (ret) { + DEBUG(1,("failed to read krb5 ccache: %s: %s\n", + name, + smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); + talloc_free(ccc); + return ret; + } + } else { + ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); + if (ret) { + DEBUG(1,("failed to read default krb5 ccache: %s\n", + smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); + talloc_free(ccc); + return ret; + } + } + + talloc_set_destructor(ccc, free_dccache); + + ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); + + if (ret) { + DEBUG(1,("failed to get principal from default ccache: %s\n", + smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); + talloc_free(ccc); + return ret; + } + + krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ); + + cred->ccache = ccc; + talloc_steal(cred, ccc); + + ret = cli_credentials_set_from_ccache(cred, obtained); + + if (ret) { + return ret; + } + + return 0; +} + + +int cli_credentials_new_ccache(struct cli_credentials *cred) +{ + krb5_error_code ret; + char *rand_string; + struct ccache_container *ccc = talloc(cred, struct ccache_container); + char *ccache_name; + if (!ccc) { + return ENOMEM; + } + + rand_string = generate_random_str(NULL, 16); + if (!rand_string) { + talloc_free(ccc); + return ENOMEM; + } + + ccache_name = talloc_asprintf(ccc, "MEMORY:%s", + rand_string); + talloc_free(rand_string); + + if (!ccache_name) { + talloc_free(ccc); + return ENOMEM; + } + + ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); + if (ret) { + talloc_free(ccache_name); + talloc_free(ccc); + return ret; + } + + ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache); + if (ret) { + DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", + ccache_name, + smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); + talloc_free(ccache_name); + talloc_free(ccc); + return ret; + } + + talloc_set_destructor(ccc, free_mccache); + + cred->ccache = ccc; + talloc_steal(cred, ccc); + talloc_free(ccache_name); + + return ret; +} + +int cli_credentials_get_ccache(struct cli_credentials *cred, struct ccache_container **ccc) +{ + krb5_error_code ret; + + if (cred->ccache_obtained >= (MAX(cred->principal_obtained, + cred->username_obtained))) { + *ccc = cred->ccache; + return 0; + } + if (cli_credentials_is_anonymous(cred)) { + return EINVAL; + } + + ret = cli_credentials_new_ccache(cred); + if (ret) { + return ret; + } + ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache); + if (ret) { + return ret; + } + ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained); + + if (ret) { + return ret; + } + *ccc = cred->ccache; + return ret; +} + + /** * Obtain the 'short' or 'NetBIOS' domain for this credentials context. * @param cred credentials context @@ -160,6 +418,11 @@ const char *cli_credentials_get_domain(struct cli_credentials *cred) cli_credentials_set_machine_account(cred); } + /* If we have a principal set on this, we want to login with "" domain and user@realm */ + if (cred->domain_obtained < cred->principal_obtained) { + return ""; + } + if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -200,21 +463,6 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) return cred->realm; } -/** - * Obtain the user's Kerberos principal for this credentials context. - * @param cred credentials context - * @param mem_ctx A talloc context to return the prinipal name on. - * @retval The user's Kerberos principal - * @note Return value may be NULL due to out-of memeory or invalid mem_ctx - */ -char *cli_credentials_get_principal(struct cli_credentials *cred, - TALLOC_CTX *mem_ctx) -{ - return talloc_asprintf(mem_ctx, "%s@%s", - cli_credentials_get_username(cred), - cli_credentials_get_realm(cred)); -} - /** * Set the realm for this credentials context, and force it to * uppercase for the sainity of our local kerberos libraries @@ -419,8 +667,10 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha } if ((p = strchr_m(uname,'@'))) { + cli_credentials_set_principal(credentials, uname, obtained); *p = 0; cli_credentials_set_realm(credentials, p+1, obtained); + return; } else if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) { *p = 0; cli_credentials_set_domain(credentials, uname, obtained); @@ -437,9 +687,10 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha */ void cli_credentials_set_conf(struct cli_credentials *cred) { - cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); - cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); - cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); + cli_credentials_set_username(cred, "", CRED_UNINITIALISED); + cli_credentials_set_domain(cred, lp_workgroup(), CRED_UNINITIALISED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_UNINITIALISED); + cli_credentials_set_realm(cred, lp_realm(), CRED_UNINITIALISED); } /** @@ -452,35 +703,36 @@ void cli_credentials_guess(struct cli_credentials *cred) { char *p; - cli_credentials_set_username(cred, "", CRED_GUESSED); cli_credentials_set_conf(cred); if (getenv("LOGNAME")) { - cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); + cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESS_ENV); } if (getenv("USER")) { - cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESSED); + cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESS_ENV); if ((p = strchr_m(getenv("USER"),'%'))) { memset(p,0,strlen(cred->password)); } } if (getenv("DOMAIN")) { - cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESSED); + cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESS_ENV); } if (getenv("PASSWD")) { - cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESSED); + cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESS_ENV); } if (getenv("PASSWD_FD")) { - cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESSED); + cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESS_FILE); } if (getenv("PASSWD_FILE")) { - cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESSED); + cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESS_FILE); } + + cli_credentials_set_ccache(cred, NULL, CRED_GUESS_FILE); } /** @@ -690,13 +942,17 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) { - const char *username = cli_credentials_get_username(cred); - + TALLOC_CTX *tmp_ctx = talloc_new(cred); + const char *username = cli_credentials_get_username(cred, tmp_ctx); + /* Yes, it is deliberate that we die if we have a NULL pointer * here - anonymous is "", not NULL, which is 'never specified, * never guessed', ie programmer bug */ - if (!username[0]) + if (!username[0]) { + talloc_free(tmp_ctx); return True; - + } + + talloc_free(tmp_ctx); return False; } diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index bb89fc910e..3d47863067 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -474,8 +474,7 @@ int ildb_connect(struct ldb_context *ldb, const char *url, ldb->modules->private_data = ildb; ldb->modules->ops = &ildb_ops; - if (cmdline_credentials != NULL && - cmdline_credentials->username_obtained > CRED_GUESSED) { + if (cmdline_credentials != NULL && cli_credentials_authentication_requested(cmdline_credentials)) { status = ldap_bind_sasl(ildb->ldap, cmdline_credentials); if (!NT_STATUS_IS_OK(status)) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n", diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index b95fc0d4b2..6be91c0db2 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -86,8 +86,11 @@ static NTSTATUS print_samba3_secrets(struct samba3_secrets *secrets) print_header("Secrets"); printf("IPC Credentials:\n"); - if (secrets->ipc_cred->username_obtained) - printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred)); + if (secrets->ipc_cred->username_obtained) { + TALLOC_CTX *mem_ctx = talloc_new(NULL); + printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred, mem_ctx)); + talloc_free(mem_ctx); + } if (secrets->ipc_cred->password_obtained) printf(" Password: %s\n", cli_credentials_get_password(secrets->ipc_cred)); -- cgit From efcba52ae5b5ff0e709da56a64eeb3621c7ebe51 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 29 Aug 2005 04:38:37 +0000 Subject: r9731: Fix typo (This used to be commit e4492951e56d89a2b805f644d83d4bd4be31a6b0) --- source4/lib/credentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 69e237428c..579f199d2e 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -126,7 +126,7 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred, const char *val BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) { - if (cred->principal_obtained == CRED_SPECIFIED) { + if (cred->principal_obtained >= CRED_SPECIFIED) { return True; } if (cred->username_obtained >= CRED_SPECIFIED) { -- cgit From 0549763600b26fadac443555e1cbec5680f91340 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 12:31:32 +0000 Subject: r9735: More work on generating a valid Samba4 configuration using the Samba3 data (both console and SWAT) (This used to be commit d569465dc4def55c27878028f2fc762960f453d8) --- source4/lib/samba3/PLAN | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 8bc90da427..dd2f8e0005 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -31,11 +31,11 @@ Three possible viable approaches: (going with a combination of 1 and 2) ldb mapping backend: - - do search in new and old (mapped) backend and merge results? + - do search in new and old (mapped) backend and merge results Upgrade process: - take libdir & smb.conf - read various tdb files / old smb.conf - - write new smb.conf (ejs?) + - write new smb.conf (ejs) - list of parameters to keep.. generate some of the others - - add generated LDIF (ejs?) + - add generated LDIF (ejs). Call out to current provisioning -- cgit From 0a72d9a5f7c8705a68b03e2f391603252d896342 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 15:54:10 +0000 Subject: r9744: - [upgrade.js] Start working on smb.conf conversion. - [ldb_map] Support storing non-mappable data in a fallback LDB (This used to be commit 435e4c6389b9d9b545beec8036289620ee5883db) --- source4/lib/ldb/ldb_map/ldb_map.c | 315 +++++++++++++++++++++++++++----- source4/lib/ldb/ldb_map/ldb_map.h | 1 + source4/lib/ldb/samba/samba3sam.c | 2 +- source4/lib/ldb/tests/test-samba3sam.sh | 39 ++-- source4/lib/samba3/PLAN | 5 +- 5 files changed, 302 insertions(+), 60 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 1a8ea2afc4..79d3c26f90 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -34,6 +34,22 @@ * (use MAP_GENERATE instead ?) */ +/* + - special attribute 'isMapped' + - add/modify + - split up ldb_message into fallback and mapped parts if is_mappable + - search: + - search local one for not isMapped entries + - remove remote attributes from ldb_parse_tree + - search remote one + - per record, search local one for additional data (by dn) + - test if (full expression) is now true + - delete + - delete both + - rename + - rename locally and remotely +*/ + static const struct ldb_map_attribute builtin_attribute_maps[]; struct map_private { @@ -41,6 +57,16 @@ struct map_private { const char *last_err_string; }; +static struct ldb_map_context *map_get_privdat(struct ldb_module *module) +{ + return &((struct map_private *)module->private_data)->context; +} + +static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +{ + /* FIXME */ + return True; +} /* find an attribute by the local name */ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) @@ -88,7 +114,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL struct ldb_parse_tree *new_tree; enum ldb_map_attr_type map_type; struct ldb_val value, newvalue; - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); if (tree == NULL) return NULL; @@ -103,16 +129,31 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); - for (i = 0; i < new_tree->u.list.num_elements; i++) { - new_tree->u.list.elements[i] = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); + new_tree->u.list.num_elements = 0; + for (i = 0; i < tree->u.list.num_elements; i++) { + struct ldb_parse_tree *child = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); + + if (child) { + new_tree->u.list.elements[i] = child; + new_tree->u.list.num_elements++; + } } return new_tree; } if (tree->operation == LDB_OP_NOT) { + struct ldb_parse_tree *child; + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); - new_tree->u.isnot.child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); + child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); + + if (!child) { + talloc_free(new_tree); + return NULL; + } + + new_tree->u.isnot.child = child; return new_tree; } @@ -125,7 +166,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL attr = map_find_attr_local(privdat, tree->u.equality.attr); if (!attr) { - DEBUG(0, ("Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr)); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); map_type = MAP_KEEP; } else { map_type = attr->type; @@ -137,12 +178,12 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_IGNORE) { - DEBUG(0, ("Search on ignored attribute '%s'!\n", tree->u.equality.attr)); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); return NULL; } if (map_type == MAP_GENERATE) { - DEBUG(0, ("Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr); return NULL; } @@ -307,7 +348,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a int i; const char **ret; int ar_size = 0, last_element = 0; - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); if (attrs == NULL) return NULL; @@ -324,7 +365,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a enum ldb_map_attr_type map_type; if (!attr) { - DEBUG(0, ("Local attribute '%s' does not have a definition!\n", attrs[i])); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); map_type = MAP_IGNORE; } else map_type = attr->type; @@ -377,7 +418,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) { - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); int i, j; int count = 0; const char **ret = talloc_array(module, const char *, 1); @@ -428,11 +469,13 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c int i, j; struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm, *oldelm; - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); const char **newattrs = NULL; msg->dn = map_remote_dn(privdat, module, mi->dn); + ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); + /* Loop over attrs, find in ldb_map_attribute array and * run generate() */ @@ -448,7 +491,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c enum ldb_map_attr_type map_type; if (!attr) { - DEBUG(0, ("Unable to find local attribute '%s' when generating incoming message\n", attrs[i])); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s' when generating incoming message\n", attrs[i]); map_type = MAP_IGNORE; } else map_type = attr->type; @@ -501,7 +544,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c ldb_msg_add(module->ldb, msg, elm, elm->flags); break; default: - DEBUG(0, ("Unknown attr->type for %s", attr->local_name)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); break; } } @@ -512,13 +555,18 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c } /* Used for add, modify */ -static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo) +static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) { - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm; int i,j; - + + *fb = talloc_zero(module, struct ldb_message); + (*fb)->dn = talloc_reference(*fb, mo->dn); + + *mp = msg; + msg->private_data = mo->private_data; msg->dn = map_local_dn(privdat, module, mo->dn); @@ -529,13 +577,21 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c enum ldb_map_attr_type map_type; if (!attr) { - DEBUG(0, ("Undefined local attribute '%s', ignoring\n", mo->elements[i].name)); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); map_type = MAP_IGNORE; continue; } else map_type = attr->type; switch (map_type) { - case MAP_IGNORE: break; + case MAP_IGNORE: /* Add to fallback message */ + elm = talloc(*fb, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); + break; case MAP_RENAME: elm = talloc(msg, struct ldb_message_element); @@ -576,22 +632,25 @@ static struct ldb_message *ldb_map_message_outgoing(struct ldb_module *module, c } } - return msg; + return 0; } + /* rename a record */ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; int ret; + + ret = ldb_next_rename_record(module, olddn, newdn); n_olddn = map_local_dn(privdat, module, olddn); n_newdn = map_local_dn(privdat, module, newdn); - ret = ldb_next_rename_record(module, n_olddn, n_newdn); + ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); talloc_free(n_olddn); talloc_free(n_newdn); @@ -604,53 +663,149 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con */ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *newdn; int ret; + ret = ldb_next_delete_record(module, dn); + newdn = map_local_dn(privdat, module, dn); - ret = ldb_next_delete_record(module, newdn); + ret = ldb_delete(privdat->mapped_ldb, newdn); talloc_free(newdn); return ret; } -/* - search for matching records using a ldb_parse_tree -*/ -static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, +/* search fallback database */ +static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { int ret; - const char **newattrs; + struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; + + t_present.operation = LDB_OP_PRESENT; + t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); + + t_not.operation = LDB_OP_NOT; + t_not.u.isnot.child = &t_present; + + childs[0] = &t_not; + childs[1] = tree; + t_and.operation = LDB_OP_AND; + t_and.u.list.num_elements = 2; + t_and.u.list.elements = childs; + + ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); + + talloc_free(t_present.u.present.attr); + + return ret; +} + +static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ struct ldb_parse_tree *new_tree; struct ldb_dn *new_base; struct ldb_message **newres; - struct ldb_map_context *privdat = &((struct map_private *)module->private_data)->context; + const char **newattrs; + int mpret, ret; + struct ldb_map_context *privdat = map_get_privdat(module); int i; + /*- search mapped database */ + new_tree = ldb_map_parse_tree(module, module, tree); newattrs = ldb_map_attrs(module, attrs); new_base = map_local_dn(privdat, module, base); - ret = ldb_next_search_bytree(module, new_base, scope, new_tree, newattrs, &newres); + mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); talloc_free(new_base); talloc_free(new_tree); talloc_free(newattrs); - *res = talloc_array(module, struct ldb_message *, ret); + /* + - per returned record, search local one for additional data (by dn) + - test if (full expression) is now true + */ + + + *res = talloc_array(module, struct ldb_message *, mpret); - for (i = 0; i < ret; i++) { - (*res)[i] = ldb_map_message_incoming(module, attrs, newres[i]); + ret = 0; + + for (i = 0; i < mpret; i++) { + struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); + struct ldb_message **extrares = NULL; + int extraret; + + /* Merge with additional data from local database */ + extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_ONELEVEL, "", NULL, &extrares); + + if (extraret > 1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More then one result for extra data!\n"); + return -1; + } else if (extraret == 1) { + int j; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); + for (j = 0; j < merged->num_elements; j++) { + ldb_msg_add(module->ldb, merged, &extrares[0]->elements[j], extrares[0]->elements[j].flags); + } + } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + } + + talloc_free(extrares); + + if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { + (*res)[ret] = merged; + ret++; + } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match"); + } + talloc_free(newres[i]); } return ret; } + + +/* + search for matching records using a ldb_parse_tree +*/ +static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + int ret; + struct ldb_message **fbres, **mpres; + int i; + int ret_fb, ret_mp; + + ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); + if (ret_fb == -1) + return -1; + + ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); + if (ret_mp == -1) + return -1; + + /* Merge results */ + *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); + + for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; + for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; + + return ret_fb + ret_mp; + + return ret; +} /* search for matching records */ @@ -678,12 +833,33 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, */ static int map_add(struct ldb_module *module, const struct ldb_message *msg) { - struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg); int ret; + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; - ret = ldb_next_add_record(module, nmsg); + if (!map_is_mappable(privdat, msg)) { + return ldb_next_add_record(module, msg); + } - talloc_free(nmsg); + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); + return -1; + } + + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); + return -1; + } + + talloc_free(fb); + talloc_free(mp); return ret; } @@ -694,12 +870,25 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) */ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) { - struct ldb_message *nmsg = ldb_map_message_outgoing(module, msg); + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; int ret; - ret = ldb_next_modify_record(module, nmsg); + if (!map_is_mappable(privdat, msg)) + return ldb_next_modify_record(module, msg); + + + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_modify_record(module, fb); + + ret = ldb_modify(privdat->mapped_ldb, mp); - talloc_free(nmsg); + talloc_free(fb); + talloc_free(mp); return ret; } @@ -740,12 +929,41 @@ static const struct ldb_module_ops map_ops = { .errstring = map_errstring }; +static char *map_find_url(struct ldb_context *ldb, const char *name) +{ + const char * const attrs[] = { "@MAP_URL" , NULL}; + struct ldb_message **msg = NULL; + struct ldb_dn *mods; + char *url; + int ret; + + mods = ldb_dn_string_compose(ldb, NULL, "@MAP=%s", name); + if (mods == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Can't construct DN"); + return NULL; + } + + ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg); + talloc_free(mods); + if (ret < 1) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Not enough results found looking for @MAP"); + return NULL; + } + + url = talloc_strdup(ldb, ldb_msg_find_string(msg[0], "@MAP_URL", NULL)); + + talloc_free(msg); + + return url; +} + /* the init function */ -struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *options[]) +struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name) { int i, j; struct ldb_module *ctx; struct map_private *data; + char *url; ctx = talloc(ldb, struct ldb_module); if (!ctx) @@ -757,6 +975,21 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at return NULL; } + data->context.mapped_ldb = ldb_init(data); + url = map_find_url(ldb, name); + + if (!url) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "@MAP=%s not set!\n", name); + return NULL; + } + + if (ldb_connect(data->context.mapped_ldb, url, 0, NULL) != 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to open mapped database for %s at '%s'\n", name, url); + return NULL; + } + + talloc_free(url); + data->last_err_string = NULL; /* Get list of attribute maps */ @@ -841,7 +1074,6 @@ static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, } } - DEBUG(1, ("Unable to map local object class '%s'\n", (char *)val->data)); return ldb_val_dup(ctx, val); } @@ -859,7 +1091,6 @@ static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map } } - DEBUG(1, ("Unable to map remote object class '%s'\n", (char *)val->data)); return ldb_val_dup(ctx, val); } diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h index 60e09975b7..02fec649c6 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ b/source4/lib/ldb/ldb_map/ldb_map.h @@ -102,6 +102,7 @@ struct ldb_map_context { struct ldb_map_attribute *attribute_maps; const struct ldb_map_objectclass *objectclass_maps; + struct ldb_context *mapped_ldb; }; #endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c index aef50e4d3e..f7d83ced8f 100644 --- a/source4/lib/ldb/samba/samba3sam.c +++ b/source4/lib/ldb/samba/samba3sam.c @@ -627,5 +627,5 @@ struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[]) #endif { - return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, options); + return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, "samba3sam"); } diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh index 988806d895..995a513d54 100755 --- a/source4/lib/ldb/tests/test-samba3sam.sh +++ b/source4/lib/ldb/tests/test-samba3sam.sh @@ -1,39 +1,49 @@ #!/bin/sh -rm -f samba3.ldb +rm -f samba3.ldb samba4.ldb echo "Adding samba3 LDIF..." $VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif || exit 1 -LOC="-H tdb://samba3.ldb" -OPT="-o modules:samba3sam $LOC" +echo "Adding samba4 LDIF..." +$VALGRIND ldbadd -H tdb://samba4.ldb < Date: Mon, 29 Aug 2005 17:31:19 +0000 Subject: r9751: Remove C version of samba3dump (the EJS version works nicely as well). Fix a couple of bugs in ldb_map. (This used to be commit 66df76a63433aea4081eab8b20bf3ba86e0a606d) --- source4/lib/ldb/ldb_map/ldb_map.c | 59 +++++-- source4/lib/samba3/config.mk | 10 -- source4/lib/samba3/samba3dump.c | 322 -------------------------------------- 3 files changed, 44 insertions(+), 347 deletions(-) delete mode 100644 source4/lib/samba3/samba3dump.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 79d3c26f90..f68ba3d545 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -62,10 +62,35 @@ static struct ldb_map_context *map_get_privdat(struct ldb_module *module) return &((struct map_private *)module->private_data)->context; } +static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) +{ + int i; + for (i = 0; privdat->objectclass_maps[i].local_name; i++) { + if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) + return &privdat->objectclass_maps[i]; + } + + return NULL; +} + +/* Decide whether a add/modify should be pushed to the + * remote LDAP server. We currently only do this if we see an objectClass we know */ static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) { - /* FIXME */ - return True; + int i; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + + /* No objectClass... */ + if (el == NULL) { + return False; + } + + for (i = 0; i < el->num_values; i++) { + if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) + return True; + } + + return False; } /* find an attribute by the local name */ @@ -745,22 +770,29 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * int extraret; /* Merge with additional data from local database */ - extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_ONELEVEL, "", NULL, &extrares); + extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); - if (extraret > 1) { + if (extraret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n"); + } else if (extraret > 1) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More then one result for extra data!\n"); + talloc_free(newres); return -1; - } else if (extraret == 1) { + } else if (extraret == 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + } + + if (extraret == 1) { int j; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); - for (j = 0; j < merged->num_elements; j++) { - ldb_msg_add(module->ldb, merged, &extrares[0]->elements[j], extrares[0]->elements[j].flags); + for (j = 0; j < extrares[0]->num_elements; j++) { + ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } + + ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); } else { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); } - - talloc_free(extrares); if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { (*res)[ret] = merged; @@ -768,10 +800,10 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * } else { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match"); } - - talloc_free(newres[i]); } + talloc_free(newres); + return ret; } @@ -783,7 +815,6 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - int ret; struct ldb_message **fbres, **mpres; int i; int ret_fb, ret_mp; @@ -803,8 +834,6 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; return ret_fb + ret_mp; - - return ret; } /* search for matching records diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 06b7e5e256..6a122546a5 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -15,13 +15,3 @@ ADD_OBJ_FILES = \ lib/samba3/upgrade.o # End SUBSYSTEM LIBSAMBA3 ################################################ - -################################################ -# Start BINARY samba3dump -[BINARY::samba3dump] -INSTALLDIR = BINDIR -INIT_OBJ_FILES = \ - lib/samba3/samba3dump.o -REQUIRED_SUBSYSTEMS = LIBBASIC LIBCMDLINE LIBSAMBA3 -# End BINARY samba3dump -################################################ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c deleted file mode 100644 index 6be91c0db2..0000000000 --- a/source4/lib/samba3/samba3dump.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba3 database dump utility - - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/samba3/samba3.h" -#include "lib/cmdline/popt_common.h" -#include "lib/ldb/include/ldb.h" - -static void print_header(const char *txt) -{ - int i; - printf("\n%s\n", txt); - for (i = 0; txt[i]; i++) putchar('='); - putchar('\n'); -} - -static NTSTATUS print_samba3_policy(struct samba3_policy *ret) -{ - print_header("Account Policies"); - printf("Min password length: %d\n", ret->min_password_length); - printf("Password history length: %d\n", ret->password_history); - printf("User must logon to change password: %d\n", ret->user_must_logon_to_change_password); - printf("Maximum password age: %d\n", ret->maximum_password_age); - printf("Minimum password age: %d\n", ret->minimum_password_age); - printf("Lockout duration: %d\n", ret->lockout_duration); - printf("Reset Count Minutes: %d\n", ret->reset_count_minutes); - printf("Bad Lockout Minutes: %d\n", ret->bad_lockout_minutes); - printf("Disconnect Time: %d\n", ret->disconnect_time); - printf("Refuse Machine Password Change: %d\n", ret->refuse_machine_password_change); - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_sam(struct samba3 *samba3) -{ - struct samba3_samaccount *accounts = samba3->samaccounts; - uint32_t i; - print_header("SAM Database"); - - for (i = 0; i < samba3->samaccount_count; i++) { - printf("%d: %s\n", accounts[i].user_rid, accounts[i].username); - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_shares(struct samba3 *samba3) -{ - int i, j; - print_header("Configured shares"); - for (i = 0; i < samba3->share_count; i++) { - struct samba3_share_info *share = &samba3->shares[i]; - printf("--- %s ---\n", share->name); - - for (j = 0; j < share->parameter_count; j++) { - printf("\t%s = %s\n", share->parameters[j].name, share->parameters[j].value); - } - - printf("\n"); - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_secrets(struct samba3_secrets *secrets) -{ - int i; - print_header("Secrets"); - - printf("IPC Credentials:\n"); - if (secrets->ipc_cred->username_obtained) { - TALLOC_CTX *mem_ctx = talloc_new(NULL); - printf(" User: %s\n", cli_credentials_get_username(secrets->ipc_cred, mem_ctx)); - talloc_free(mem_ctx); - } - if (secrets->ipc_cred->password_obtained) - printf(" Password: %s\n", cli_credentials_get_password(secrets->ipc_cred)); - - if (secrets->ipc_cred->domain_obtained) - printf(" Domain: %s\n\n", cli_credentials_get_domain(secrets->ipc_cred)); - - printf("LDAP passwords:\n"); - for (i = 0; i < secrets->ldappw_count; i++) { - printf("\t%s -> %s\n", secrets->ldappws[i].dn, secrets->ldappws[i].password); - } - printf("\n"); - - printf("Domains:\n"); - for (i = 0; i < secrets->domain_count; i++) { - printf("\t--- %s ---\n", secrets->domains[i].name); - printf("\tSID: %s\n", dom_sid_string(NULL, &secrets->domains[i].sid)); - printf("\tGUID: %s\n", GUID_string(NULL, &secrets->domains[i].guid)); - printf("\tPlaintext pwd: %s\n", secrets->domains[i].plaintext_pw); - printf("\tLast Changed: %lu\n", secrets->domains[i].last_change_time); - printf("\tSecure Channel Type: %d\n\n", secrets->domains[i].sec_channel_type); - } - - printf("Trusted domains:\n"); - for (i = 0; i < secrets->trusted_domain_count; i++) { - int j; - for (j = 0; j < secrets->trusted_domains[i].uni_name_len; j++) { - printf("\t--- %s ---\n", secrets->trusted_domains[i].uni_name[j]); - } - printf("\tPassword: %s\n", secrets->trusted_domains[i].pass); - printf("\tModified: %lu\n", secrets->trusted_domains[i].mod_time); - printf("\tSID: %s\n", dom_sid_string(NULL, &secrets->trusted_domains[i].domain_sid)); - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_regdb(struct samba3_regdb *regdb) -{ - int i; - print_header("Registry"); - - for (i = 0; i < regdb->key_count; i++) { - int j; - printf("%s\n", regdb->keys[i].name); - for (j = 0; j < regdb->keys[i].value_count; j++) { - printf("\t%s: type %d, length %d\n", - regdb->keys[i].values[j].name, - regdb->keys[i].values[j].type, - regdb->keys[i].values[j].data.length); - } - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_winsdb(struct samba3 *samba3) -{ - int i; - print_header("WINS Database"); - - for (i = 0; i < samba3->winsdb_count; i++) { - printf("%s, nb_flags: %x, type: %d, ttl: %lu, %d ips\n", samba3->winsdb_entries[i].name, samba3->winsdb_entries[i].nb_flags, samba3->winsdb_entries[i].type, samba3->winsdb_entries[i].ttl, samba3->winsdb_entries[i].ip_count); - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_groupdb(struct samba3_groupdb *db) -{ - int i; - print_header("Group Mappings"); - - for (i = 0; i < db->groupmap_count; i++) - { - printf("\t--- Group: %s ---\n", db->groupmappings[i].nt_name); - printf("\tComment: %s\n", db->groupmappings[i].comment); - printf("\tGID: %d\n", db->groupmappings[i].gid); - printf("\tSID Name Use: %d\n", db->groupmappings[i].sid_name_use); - printf("\tSID: %s\n\n", dom_sid_string(NULL, db->groupmappings[i].sid)); - } - - for (i = 0; i < db->alias_count; i++) - { - int j; - printf("\t--- Alias: %s ---\n", dom_sid_string(NULL, db->aliases[i].sid)); - for (j = 0; j < db->aliases[i].member_count; j++) { - printf("\t%s\n", dom_sid_string(NULL,db->aliases[i].members[j])); - } - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3_idmapdb(struct samba3_idmapdb *db) -{ - int i; - print_header("Winbindd SID<->GID/UID mappings"); - - printf("User High Water Mark: %d\n", db->user_hwm); - printf("Group High Water Mark: %d\n\n", db->group_hwm); - - for (i = 0; i < db->mapping_count; i++) { - printf("%s -> %cID %d", - dom_sid_string(NULL, db->mappings[i].sid), - (db->mappings[i].type == IDMAP_GROUP)?'G':'U', - db->mappings[i].unix_id); - } - - return NT_STATUS_OK; -} - -static NTSTATUS print_samba3(struct samba3 *samba3) -{ - print_samba3_sam(samba3); - print_samba3_policy(&samba3->policy); - print_samba3_shares(samba3); - print_samba3_winsdb(samba3); - print_samba3_regdb(&samba3->registry); - print_samba3_secrets(&samba3->secrets); - print_samba3_groupdb(&samba3->group); - print_samba3_idmapdb(&samba3->idmap); - - return NT_STATUS_OK; -} - -static BOOL write_ldif(const char *fn, struct ldb_message **messages, int count) -{ - FILE *f = fopen(fn, "w+"); - struct ldb_ldif ldif; - int i; - struct ldb_context *ldb = ldb_init(NULL); - - if (!f) { - DEBUG(0, ("Unable to open LDIF file '%s'\n", fn)); - talloc_free(ldb); - return False; - } - - for (i = 0; i < count; i++) { - ldif.changetype = LDB_CHANGETYPE_ADD; - ldif.msg = messages[i]; - - ldb_ldif_write_file(ldb, f, &ldif); - } - - talloc_free(ldb); - - fclose(f); - - return True; -} - -int main(int argc, char **argv) -{ - int opt; - const char *format = "summary"; - char *libdir = NULL; - char *smbconf = NULL; - struct samba3 *samba3; - poptContext pc; - TALLOC_CTX *mem_ctx; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "format", 0, POPT_ARG_STRING, &format, 'f', "Format to use (one of: summary, text, ldif)" }, - POPT_COMMON_SAMBA - POPT_TABLEEND - }; - - pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); - - poptSetOtherOptionHelp(pc, " "); - - while((opt = poptGetNextOpt(pc)) != -1) { - } - - samba3dump_init_subsystems; - - mem_ctx = talloc_init("samba3dump_context"); - - libdir = talloc_strdup(mem_ctx, poptGetArg(pc)); - smbconf = talloc_strdup(mem_ctx, poptGetArg(pc)); - - printf("Reading from libdir '%s', smb.conf file '%s'\n", libdir, smbconf); - - samba3_read(smbconf, libdir, mem_ctx, &samba3); - - if (!strcmp(format, "summary")) { - printf("WINS db entries: %d\n", samba3->winsdb_count); - printf("SAM Accounts: %d\n", samba3->samaccount_count); - printf("Registry key count: %d\n", samba3->registry.key_count); - printf("Shares (including [global]): %d\n", samba3->share_count); - printf("Groupmap count: %d\n", samba3->group.groupmap_count); - printf("Alias count: %d\n", samba3->group.alias_count); - printf("Idmap count: %d\n", samba3->idmap.mapping_count); - } else if (!strcmp(format, "text")) { - print_samba3(samba3); - } else if (!strcmp(format, "ldif")) { - struct ldb_message **msgs; - struct ldb_context *ldb = ldb_init(mem_ctx); - int i, ret; - const char *hives[] = { "hklm", "hkcr", "hku", "hkpd", "hkpt", NULL }; - - for (i = 0; hives[i]; i++) { - char *fn; - - ret = samba3_upgrade_registry(&samba3->registry, hives[i], ldb, &msgs); - - printf("Writing %s.ldif\n", hives[i]); - asprintf(&fn, "%s.ldif", hives[i]); - write_ldif(fn, msgs, ret); - SAFE_FREE(fn); - } - - ret = samba3_upgrade_sam(samba3, ldb, &msgs); - printf("Writing sam.ldif\n"); - write_ldif("sam.ldif", msgs, ret); - - ret = samba3_upgrade_winsdb(samba3, ldb, &msgs); - printf("Writing wins.ldif\n"); - write_ldif("wins.ldif", msgs, ret); - - ret = samba3_upgrade_winbind(samba3, ldb, &msgs); - printf("Writing winbind.ldif\n"); - write_ldif("winbind.ldif", msgs, ret); - } - poptFreeContext(pc); - - return 0; -} -- cgit From 11f3f0fa6cfb0486bdc526465dc4c0e19467a30f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 18:52:24 +0000 Subject: r9754: Upgrading with the command line utility now works, at least partially (-: Upgrading using SWAT should work as well now. (This used to be commit 8baa2ac377315ae8b365f58c2bda0bf3d0c5aec3) --- source4/lib/samba3/secrets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 25ab8f5db5..43f0a2ec12 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -72,7 +72,7 @@ static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct db->domains = talloc_realloc(ctx, db->domains, struct samba3_domainsecrets, db->domain_count+1); ZERO_STRUCT(db->domains[db->domain_count]); - db->domains[db->domain_count].name = talloc_strdup(ctx, key); + db->domains[db->domain_count].name = talloc_strdup(db->domains, key); db->domain_count++; -- cgit From c9ace93ce22fed9e1b4e44a853e23bf66cf99184 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 20:18:51 +0000 Subject: r9756: One-way upgrade from Samba3->Samba4 basically works now Still need to polish some rough edges (This used to be commit a8f309aa812533f57a90410722dfb342c8cf3b48) --- source4/lib/samba3/config.mk | 3 +- source4/lib/samba3/upgrade.c | 280 ------------------------------------------- 2 files changed, 1 insertion(+), 282 deletions(-) delete mode 100644 source4/lib/samba3/upgrade.c (limited to 'source4/lib') diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index 6a122546a5..db5d04ddaa 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -11,7 +11,6 @@ ADD_OBJ_FILES = \ lib/samba3/group.o \ lib/samba3/registry.o \ lib/samba3/secrets.o \ - lib/samba3/share_info.o \ - lib/samba3/upgrade.o + lib/samba3/share_info.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/upgrade.c b/source4/lib/samba3/upgrade.c deleted file mode 100644 index 00000c68df..0000000000 --- a/source4/lib/samba3/upgrade.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Generate ldb_message 's for samba3_* - - Copyright (C) Jelmer Vernooij 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/samba3/samba3.h" -#include "lib/ldb/include/ldb.h" - -static struct ldb_message *msg_array_add(struct ldb_context *ctx, struct ldb_message ***msgs, int *count) -{ - struct ldb_message *ret; - *msgs = talloc_realloc(ctx, *msgs, struct ldb_message *, (*count)+1); - - ret = (*msgs)[*count] = talloc_zero(ctx, struct ldb_message); - (*count)++; - - return ret; -} - -static struct ldb_dn *regkey_to_dn(struct ldb_context *ldb, const char *name) -{ - char *p, *n, *dup; - struct ldb_dn *ret = ldb_dn_explode(ldb, "hive=NONE"); - - p = dup = talloc_strdup(ldb, name); - - while (p) { - n = strchr(p, '/'); - if (n) { *n = '\0'; n++; } - - ret = ldb_dn_build_child(ldb, "key", p, ret); - - p = n; - } - - talloc_free(dup); - - return ret; -} - -/* Where prefix is any of: - * - HKLM - * HKU - * HKCR - * HKPD - * HKPT - */ - -int samba3_upgrade_registry(struct samba3_regdb *regdb, const char *prefix, struct ldb_context *ldb, struct ldb_message ***msgs) -{ - int i; - struct ldb_message *msg; - int count = 0; - char *prefix_up = strupper_talloc(ldb, prefix); - *msgs = NULL; - - for (i = 0; i < regdb->key_count; i++) { - int j; - struct samba3_regkey *rk = ®db->keys[i]; - struct ldb_dn *keydn; - - /* Only handle selected hive */ - if (strncmp(prefix_up, rk->name, strlen(prefix_up)) != 0) { - continue; - } - - msg = msg_array_add(ldb, msgs, &count); - - msg->num_elements = 0; - msg->elements = NULL; - msg->private_data = NULL; - - /* Convert key name to dn */ - keydn = msg->dn = regkey_to_dn(ldb, rk->name); - - ldb_msg_add_string(ldb, msg, "name", strrchr(rk->name, '/')?strrchr(rk->name, '/')+1:rk->name); - - for (j = 0; j < rk->value_count; j++) { - struct samba3_regval *rv = &rk->values[j]; - - msg = msg_array_add(ldb, msgs, &count); - msg->dn = ldb_dn_build_child(ldb, "value", rv->name, keydn); - - ldb_msg_add_string(ldb, msg, "value", rv->name); - ldb_msg_add_fmt(ldb, msg, "type", "%d", rv->type); - ldb_msg_add_value(ldb, msg, "data", &rv->data); - } - } - - talloc_free(prefix_up); - - return count; -} - -int samba3_upgrade_sam(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) -{ - int count = 0; - struct ldb_message *msg; - struct ldb_dn *domaindn = NULL; - const char *domainname; - struct samba3_domainsecrets *domsec; - int i; - *msgs = NULL; - - domainname = samba3_get_param(samba3, "global", "workgroup"); - - if (domainname == NULL) { - DEBUG(0, ("No domain name specified in smb.conf!\n")); - return -1; - } - - domsec = samba3_find_domainsecrets(samba3, domainname); - - /* Domain */ - msg = msg_array_add(ldb, msgs, &count); - /* FIXME: Guess domain DN by taking ldap bind dn? */ - - ldb_msg_add_string(ldb, msg, "objectClass", "top"); - ldb_msg_add_string(ldb, msg, "objectClass", "domain"); - ldb_msg_add_string(ldb, msg, "objectSid", dom_sid_string(msg, &domsec->sid)); - ldb_msg_add_string(ldb, msg, "objectGUID", GUID_string(msg, &domsec->guid)); - ldb_msg_add_string(ldb, msg, "name", domainname); - ldb_msg_add_string(ldb, msg, "oEMInformation", "Provisioned by Samba4 (upgraded from Samba3)"); - - /* account policy as well */ - - ldb_msg_add_fmt(ldb, msg, "minPwdLength", "%d", samba3->policy.min_password_length); - ldb_msg_add_fmt(ldb, msg, "pwdHistoryLength", "%d", samba3->policy.password_history); - ldb_msg_add_fmt(ldb, msg, "minPwdAge", "%d", samba3->policy.minimum_password_age); - ldb_msg_add_fmt(ldb, msg, "maxPwdAge", "%d", samba3->policy.maximum_password_age); - ldb_msg_add_fmt(ldb, msg, "lockoutDuration", "%d", samba3->policy.lockout_duration); - ldb_msg_add_fmt(ldb, msg, "samba3ResetCountMinutes", "%d", samba3->policy.reset_count_minutes); - ldb_msg_add_fmt(ldb, msg, "samba3UserMustLogonToChangePassword", "%d", samba3->policy.user_must_logon_to_change_password); - ldb_msg_add_fmt(ldb, msg, "samba3BadLockoutMinutes", "%d", samba3->policy.bad_lockout_minutes); - ldb_msg_add_fmt(ldb, msg, "samba3DisconnectTime", "%d", samba3->policy.disconnect_time); - ldb_msg_add_fmt(ldb, msg, "samba3RefuseMachinePwdChange", "%d", samba3->policy.refuse_machine_password_change); - - /* Users */ - for (i = 0; i < samba3->samaccount_count; i++) { - struct samba3_samaccount *sam = &samba3->samaccounts[i]; - - msg = msg_array_add(ldb, msgs, &count); - msg->dn = ldb_dn_build_child(msg, "cn", sam->fullname, domaindn); - - ldb_msg_add_string(ldb, msg, "objectClass", "top"); - ldb_msg_add_string(ldb, msg, "objectClass", "person"); - ldb_msg_add_string(ldb, msg, "objectClass", "user"); - ldb_msg_add_fmt(ldb, msg, "lastLogon", "%d", sam->logon_time); - ldb_msg_add_fmt(ldb, msg, "lastLogoff", "%d", sam->logoff_time); - ldb_msg_add_string(ldb, msg, "unixName", sam->username); - ldb_msg_add_string(ldb, msg, "name", sam->nt_username); - ldb_msg_add_string(ldb, msg, "cn", sam->fullname); - ldb_msg_add_string(ldb, msg, "description", sam->acct_desc); - ldb_msg_add_fmt(ldb, msg, "primaryGroupID", "%d", sam->group_rid); - ldb_msg_add_fmt(ldb, msg, "badPwdcount", "%d", sam->bad_password_count); - ldb_msg_add_fmt(ldb, msg, "logonCount", "%d", sam->logon_count); - - ldb_msg_add_string(ldb, msg, "samba3Domain", sam->domain); - if (sam->dir_drive) - ldb_msg_add_string(ldb, msg, "samba3DirDrive", sam->dir_drive); - - if (sam->munged_dial) - ldb_msg_add_string(ldb, msg, "samba3MungedDial", sam->munged_dial); - - if (sam->homedir) - ldb_msg_add_string(ldb, msg, "samba3Homedir", sam->homedir); - - if (sam->logon_script) - ldb_msg_add_string(ldb, msg, "samba3LogonScript", sam->logon_script); - - if (sam->profile_path) - ldb_msg_add_string(ldb, msg, "samba3ProfilePath", sam->profile_path); - - if (sam->workstations) - ldb_msg_add_string(ldb, msg, "samba3Workstations", sam->workstations); - - ldb_msg_add_fmt(ldb, msg, "samba3KickOffTime", "%d", sam->kickoff_time); - ldb_msg_add_fmt(ldb, msg, "samba3BadPwdTime", "%d", sam->bad_password_time); - ldb_msg_add_fmt(ldb, msg, "samba3PassLastSetTime", "%d", sam->pass_last_set_time); - ldb_msg_add_fmt(ldb, msg, "samba3PassCanChangeTime", "%d", sam->pass_can_change_time); - ldb_msg_add_fmt(ldb, msg, "samba3PassMustChangeTime", "%d", sam->pass_must_change_time); - ldb_msg_add_fmt(ldb, msg, "samba3Rid", "%d", sam->user_rid); - - /* FIXME: Passwords */ - } - - /* Groups */ - for (i = 0; i < samba3->group.groupmap_count; i++) { - struct samba3_groupmapping *grp = &samba3->group.groupmappings[i]; - - msg = msg_array_add(ldb, msgs, &count); - - if (grp->nt_name != NULL) - msg->dn = ldb_dn_build_child(msg, "cn", grp->nt_name, domaindn); - else - msg->dn = ldb_dn_build_child(msg, "cn", dom_sid_string(msg, grp->sid), domaindn); - - ldb_msg_add_string(ldb, msg, "objectClass", "top"); - ldb_msg_add_string(ldb, msg, "objectClass", "group"); - ldb_msg_add_string(ldb, msg, "description", grp->comment); - ldb_msg_add_string(ldb, msg, "cn", grp->nt_name); - ldb_msg_add_string(ldb, msg, "objectSid", dom_sid_string(msg, grp->sid)); - ldb_msg_add_string(ldb, msg, "unixName", "FIXME"); - ldb_msg_add_fmt(ldb, msg, "samba3SidNameUse", "%d", grp->sid_name_use); - } - - return count; -} - -int samba3_upgrade_winbind(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) -{ - int i; - int count = 0; - struct ldb_message *msg; - struct ldb_dn *basedn = NULL; - *msgs = NULL; - - msg = msg_array_add(ldb, msgs, &count); - - msg->dn = basedn; - - ldb_msg_add_fmt(ldb, msg, "userHwm", "%d", samba3->idmap.user_hwm); - ldb_msg_add_fmt(ldb, msg, "groupHwm", "%d", samba3->idmap.group_hwm); - - for (i = 0; i < samba3->idmap.mapping_count; i++) { - char *sid = dom_sid_string(msg, samba3->idmap.mappings[i].sid); - msg = msg_array_add(ldb, msgs, &count); - - msg->dn = ldb_dn_build_child(ldb, "SID", sid, basedn); - ldb_msg_add_string(ldb, msg, "SID", sid); - ldb_msg_add_fmt(ldb, msg, "type", "%d", samba3->idmap.mappings[i].type); - ldb_msg_add_fmt(ldb, msg, "unixID", "%u", samba3->idmap.mappings[i].unix_id); - } - - return count; -} - -int samba3_upgrade_winsdb(struct samba3 *samba3, struct ldb_context *ldb, struct ldb_message ***msgs) -{ - int i; - int count = 0; - - for (i = 0; i < samba3->winsdb_count; i++) { - struct samba3_winsdb_entry *e = &samba3->winsdb_entries[i]; - int j; - struct ldb_message *msg = msg_array_add(ldb, msgs, &count); - - msg->dn = ldb_dn_string_compose(ldb, NULL, "type=%d,name=%s", e->type, e->name); - - ldb_msg_add_string(ldb, msg, "name", e->name); - ldb_msg_add_fmt(ldb, msg, "type", "%d", e->type); - ldb_msg_add_string(ldb, msg, "objectClass", "wins"); - ldb_msg_add_fmt(ldb, msg, "nbFlags", "%x", e->nb_flags); - ldb_msg_add_string(ldb, msg, "expires", - ldap_timestring(msg, e->ttl)); - - for (j = 0; j < e->ip_count; j++) { - ldb_msg_add_string(ldb, msg, "address", sys_inet_ntoa(e->ips[j])); - } - } - - return count; -} -- cgit From ec934124db8a5234d8c83799a23c7bdced5dd95a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 22:01:18 +0000 Subject: r9762: Add support for reading good old smbpasswd files Fix password support Make base64 decode/encode functions available to EJS (This used to be commit 1376a1fe44cd6b01709819095a711c14626b1d3e) --- source4/lib/samba3/samba3.h | 4 +- source4/lib/samba3/smbpasswd.c | 132 +++++++++++++++++++++++++++++++++++++++++ source4/lib/samba3/tdbsam.c | 32 +++++----- 3 files changed, 151 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index 5aba790c4e..a41109a145 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -22,6 +22,7 @@ #define _SAMBA3_H #include "librpc/gen_ndr/security.h" +#include "librpc/gen_ndr/samr.h" struct samba3_samaccount { uint32_t logon_time, @@ -43,10 +44,11 @@ struct samba3_samaccount { char *profile_path; char *acct_desc; char *workstations; + uid_t uid; uint32_t user_rid, group_rid, hours_len, unknown_6; uint16_t acct_ctrl, logon_divs; uint16_t bad_password_count, logon_count; - uint8_t *lm_pw_ptr, *nt_pw_ptr; + struct samr_Password lm_pw, nt_pw; uint8_t *nt_pw_hist_ptr; uint8_t *hours; }; diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index bcbb5e56d8..5976d2db57 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -7,6 +7,7 @@ Modified by Gerald (Jerry) Carter 2000-2001 Copyright (C) Tim Potter 2001 Copyright (C) Andrew Bartlett 2005 + Copyright (C) Jelmer Vernooij 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 @@ -54,6 +55,7 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_samr.h" +#include "lib/samba3/samba3.h" #include "system/iconv.h" /*! Convert 32 hex characters into a 16 byte array. */ @@ -206,3 +208,133 @@ char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info) return acct_str; } + +NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct samba3_samaccount **accounts, uint32_t *count) +{ + int numlines; + char **lines; + *count = 0; + *accounts = NULL; + int i; + + lines = file_lines_load(filename, &numlines, ctx); + + *accounts = talloc_array(ctx, struct samba3_samaccount, numlines); + + for (i = 0; i < numlines; i++) { + char *p = lines[i], *q; + struct samba3_samaccount *acc = &((*accounts)[*count]); + + if (p[0] == '\0' || p[0] == '#') + continue; + + ZERO_STRUCTP(acc); + + q = strchr(p, ':'); + if (!q) { + DEBUG(0, ("%s:%d: expected ':'\n", filename, i)); + continue; + } + + acc->username = talloc_strndup(ctx, p, PTR_DIFF(q, p)); + p = q+1; + + acc->uid = atoi(p); + + q = strchr(p, ':'); + if (!q) { + DEBUG(0, ("%s:%d: expected ':'\n", filename, i)); + continue; + } + p = q+1; + + if (strlen(p) < 33) { + DEBUG(0, ("%s:%d: expected 32 byte password blob\n", filename, i)); + continue; + } + + if (!strncmp(p, "NO PASSWORD", strlen("NO PASSWORD"))) { + acc->acct_ctrl |= ACB_PWNOTREQ; + } else if (p[0] == '*' || p[0] == 'X') { + /* No password set */ + } else { + struct samr_Password *pw = smbpasswd_gethexpwd(*accounts, p); + + if (!pw) { + DEBUG(0, ("%s:%d: Malformed LM pw entry\n", filename, i)); + continue; + } + + memcpy(acc->lm_pw.hash, pw, sizeof(*pw)); + } + + if (p[32] != ':') { + DEBUG(0, ("%s:%d: expected ':' after 32 byte password blob\n", filename, i)); + continue; + } + + p += 33; + + if (p[0] == '*' || p[0] == 'X') { + /* No password set */ + } else { + struct samr_Password *pw = smbpasswd_gethexpwd(*accounts, p); + + if (!pw) { + DEBUG(0, ("%s:%d: Malformed LM pw entry\n", filename, i)); + continue; + } + + memcpy(acc->nt_pw.hash, pw, sizeof(*pw)); + } + + if (p[32] != ':') { + DEBUG(0, ("%s:%d: expected ':' after 32 byte password blob\n", filename, i)); + continue; + } + + p += 33; + + if (p[0] == '[') { + q = strchr(p, ']'); + if (!q) { + DEBUG(0, ("%s:%d: expected ']'\n", filename, i)); + continue; + } + + acc->acct_ctrl |= smbpasswd_decode_acb_info(p); + + p = q+1; + if (p[0] == ':' && strncmp(p, "LCT-", 4) == 0) { + int j; + p += 4; + + for(j = 0; j < 8; j++) { + if(p[j] == '\0' || !isxdigit(p[j])) { + break; + } + } + if(i == 8) { + acc->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16); + } + } + } else { + /* 'Old' style file. Fake up based on user name. */ + /* + * Currently trust accounts are kept in the same + * password file as 'normal accounts'. If this changes + * we will have to fix this code. JRA. + */ + if(acc->username[strlen(acc->username) - 1] == '$') { + acc->acct_ctrl &= ~ACB_NORMAL; + acc->acct_ctrl |= ACB_WSTRUST; + } + } + + (*count)++; + } + + talloc_free(lines); + + return NT_STATUS_OK; +} diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index c9b121ca77..fc293d5df9 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -69,8 +69,8 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ &sampass->acct_ctrl, /* w */ &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ &sampass->logon_divs, /* w */ @@ -85,11 +85,11 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * } if (lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + return False; } if (nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + return False; } return True; @@ -135,8 +135,8 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ &sampass->acct_ctrl, /* w */ &remove_me, /* d */ &sampass->logon_divs, /* w */ @@ -150,12 +150,12 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * return False; } - if (sampass->lm_pw_ptr && lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + if (lm_pw_len != 16) { + return False; } - if (sampass->nt_pw_ptr && nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + if (nt_pw_len != 16) { + return False; } return True; @@ -199,8 +199,8 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ /* Change from V1 is addition of password history field. */ &nt_pw_hist_len, &sampass->nt_pw_hist_ptr, /* B */ &sampass->acct_ctrl, /* w */ @@ -216,12 +216,12 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * return False; } - if (sampass->lm_pw_ptr && lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + if (lm_pw_len != 16) { + return False; } - if (sampass->nt_pw_ptr && nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + if (nt_pw_len != 16) { + return False; } return True; -- cgit From fe1ee4494e172ea8045b4847806241e9dfaefeef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 23:20:40 +0000 Subject: r9766: Prevent erroneous OOM message ldb_dup_val() sets out->data to NULL if in->length == 0 (This used to be commit 7ecb6988e74f4273b2ca3ea76562117e1be54b08) --- source4/lib/ldb/common/attrib_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index da2d945419..412146360c 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -38,7 +38,7 @@ int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { *out = ldb_val_dup(mem_ctx, in); - if (out->data == NULL) { + if (in->length > 0 && out->data == NULL) { ldb_oom(ldb); return -1; } -- cgit From 37194224416d7509a457ee4aa18991b8bab0da7d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Aug 2005 00:36:12 +0000 Subject: r9769: r11592@blu: tridge | 2005-08-30 10:40:19 +1000 added a tdb optimisation that speeds up non-indexed ldb by a large margin (often 10x or more). I'd be interested in any comments on the safety of this optimisation. See the comment in the code for an explanation. (This used to be commit 7f9efaceb6d6dfc0c82923344cc45ec34493f2ed) --- source4/lib/tdb/common/tdb.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 4c2d9a1add..8e8e3ce3b3 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1250,6 +1250,43 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, /* Lock each chain from the start one. */ for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then thats OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of more than 10 in speed on a linux 2.6.x + system. + */ + if (!tlock->off && tlock->hash != 0) { + u32 off; + if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && + off == 0) { + continue; + } + } + if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) return -1; -- cgit From 7be4cf8c1ded42daf7e86ecd2c0dbfeeed312b22 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 00:41:02 +0000 Subject: r9770: Couple other bugfixes Update TODO-list (This used to be commit d9541535e3f9e1c058410eeb0a54d60181572f2b) --- source4/lib/ldb/ldb_map/ldb_map.c | 16 ++++++++---- source4/lib/ldb/tests/samba3.ldif | 41 +++++++++++++++++------------ source4/lib/ldb/tests/test-samba3sam.sh | 17 ++++++++---- source4/lib/samba3/PLAN | 46 +++------------------------------ source4/lib/samba3/tdbsam.c | 24 ----------------- 5 files changed, 51 insertions(+), 93 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index f68ba3d545..7a620f3b81 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -754,12 +754,17 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * talloc_free(new_tree); talloc_free(newattrs); + if (mpret == -1) { + struct map_private *map_private = module->private_data; + map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); + return -1; + } + /* - - per returned record, search local one for additional data (by dn) + - per returned record, search fallback database for additional data (by dn) - test if (full expression) is now true */ - *res = talloc_array(module, struct ldb_message *, mpret); ret = 0; @@ -775,7 +780,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * if (extraret == -1) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n"); } else if (extraret > 1) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More then one result for extra data!\n"); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More than one result for extra data!\n"); talloc_free(newres); return -1; } else if (extraret == 0) { @@ -820,12 +825,13 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas int ret_fb, ret_mp; ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); - if (ret_fb == -1) + if (ret_fb == -1) return -1; ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); - if (ret_mp == -1) + if (ret_mp == -1) { return -1; + } /* Merge results */ *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); diff --git a/source4/lib/ldb/tests/samba3.ldif b/source4/lib/ldb/tests/samba3.ldif index 02103b65b6..035eb1c516 100644 --- a/source4/lib/ldb/tests/samba3.ldif +++ b/source4/lib/ldb/tests/samba3.ldif @@ -1,4 +1,12 @@ -dn: uid=nobody,ou=Users,dc=test,dc=vernstok,dc=nl +dn: ou=Users,ou=Tests,dc=vernstok,dc=nl +objectClass: organizationalUnit +ou: Users + +dn: ou=Groups,ou=Tests,dc=vernstok,dc=nl +objectClass: organizationalUnit +ou: Groups + +dn: uid=nobody,ou=Users,ou=Tests,dc=vernstok,dc=nl cn: nobody sn: nobody objectClass: inetOrgPerson @@ -25,7 +33,7 @@ sambaAcctFlags: [NU ] sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2998 loginShell: /bin/false -dn: cn=Domain Admins,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Domain Admins,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 512 @@ -36,7 +44,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-512 sambaGroupType: 2 displayName: Domain Admins -dn: cn=Domain Users,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Domain Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 513 @@ -46,7 +54,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-513 sambaGroupType: 2 displayName: Domain Users -dn: cn=Domain Guests,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Domain Guests,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 514 @@ -56,7 +64,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-514 sambaGroupType: 2 displayName: Domain Guests -dn: cn=Print Operators,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Print Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 550 @@ -66,7 +74,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-550 sambaGroupType: 2 displayName: Print Operators -dn: cn=Backup Operators,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Backup Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 551 @@ -76,7 +84,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-551 sambaGroupType: 2 displayName: Backup Operators -dn: cn=Replicator,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Replicator,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 552 @@ -86,7 +94,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 sambaGroupType: 2 displayName: Replicator -dn: cn=Domain Computers,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Domain Computers,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 553 @@ -96,7 +104,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-553 sambaGroupType: 2 displayName: Domain Computers -dn: cn=Administrators,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Administrators,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 544 @@ -106,7 +114,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-544 sambaGroupType: 2 displayName: Administrators -dn: cn=Users,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 545 @@ -116,7 +124,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-545 sambaGroupType: 2 displayName: users -dn: cn=Guests,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Guests,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 546 @@ -127,7 +135,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-546 sambaGroupType: 2 displayName: Guests -dn: cn=Power Users,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Power Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 547 @@ -137,7 +145,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-547 sambaGroupType: 2 displayName: Power Users -dn: cn=Account Operators,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Account Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 548 @@ -147,7 +155,7 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-548 sambaGroupType: 2 displayName: Account Operators -dn: cn=Server Operators,ou=Groups,dc=test,dc=vernstok,dc=nl +dn: cn=Server Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl objectClass: posixGroup objectClass: sambaGroupMapping gidNumber: 549 @@ -157,10 +165,11 @@ sambaSID: S-1-5-21-4231626423-2410014848-2360679739-549 sambaGroupType: 2 displayName: Server Operators -dn: ou=Computers,dc=test,dc=vernstok,dc=nl +dn: ou=Computers,ou=Tests,dc=vernstok,dc=nl objectClass: organizationalUnit ou: Computers -dn: uid=Administrator,ou=Users,dc=test,dc=vernstok,dc=nl + +dn: uid=Administrator,ou=Users,ou=Tests,dc=vernstok,dc=nl cn: Administrator sn: Administrator objectClass: inetOrgPerson diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh index 995a513d54..5baf0bf77a 100755 --- a/source4/lib/ldb/tests/test-samba3sam.sh +++ b/source4/lib/ldb/tests/test-samba3sam.sh @@ -1,17 +1,24 @@ #!/bin/sh -rm -f samba3.ldb samba4.ldb +S3URL=$1 -echo "Adding samba3 LDIF..." -$VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif || exit 1 +if [ -z "$S3URL" ]; +then + rm -f samba3.ldb + S3URL="tdb://samba3.ldb" + echo "Adding samba3 LDIF..." + $VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif || exit 1 +fi -echo "Adding samba4 LDIF..." +rm -f samba4.ldb + +echo "Initial samba4 LDIF..." $VALGRIND ldbadd -H tdb://samba4.ldb < Date: Tue, 30 Aug 2005 00:43:26 +0000 Subject: r9771: - Prevent ldb crash when a invalid DN is added - Don't silently drop records with empty attributes tridge/simo: Could you please verify this patch is correct? (This used to be commit 505c9b1d3d39475da141d3b3c156a7e5ba06790c) --- source4/lib/ldb/common/ldb_attributes.c | 2 +- source4/lib/ldb/common/ldb_ldif.c | 6 ++++++ source4/lib/ldb/common/ldb_msg.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index a915666d78..3973fc515c 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -66,7 +66,7 @@ static int ldb_default_copy(struct ldb_context *ldb, { *out = ldb_val_dup(mem_ctx, in); - if (out->length == 0) { + if (out->data == NULL && in->data != NULL) { return -1; } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index 38866d7031..a5768b9796 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -590,6 +590,12 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, msg->dn = ldb_dn_explode(msg, value.data); + if (msg->dn == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", + value.data); + goto failed; + } + while (next_attr(ldif, &s, &attr, &value) == 0) { const struct ldb_attrib_handler *h; struct ldb_message_element *el; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 197c42ddb5..f65c944eab 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -99,7 +99,7 @@ struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v) { struct ldb_val v2; v2.length = v->length; - if (v->length == 0) { + if (v->data == NULL) { v2.data = NULL; return v2; } -- cgit From 6f9b901fa0db18faae603db67d8d31e229d92c27 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 30 Aug 2005 01:19:41 +0000 Subject: r9772: Make credentials callbacks more consistant with the abstraction function interface used in the credentials code. Fix bug in ntlm_auth, where we would overwrite the PW specified as a first input. (Reported and chased by Kai Blin , bug #3040) Andrew Bartlett (This used to be commit 04af95bd31de39ad6aff349a4838dd77cb300034) --- source4/lib/cmdline/credentials.c | 9 ++-- source4/lib/credentials.c | 99 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c index 7832e01e4b..f46a03b236 100644 --- a/source4/lib/cmdline/credentials.c +++ b/source4/lib/cmdline/credentials.c @@ -29,8 +29,8 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) { char *prompt; char *ret; - char *domain; - char *username; + const char *domain; + const char *username; TALLOC_CTX *mem_ctx = talloc_new(NULL); domain = cli_credentials_get_domain(credentials); @@ -51,8 +51,5 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) void cli_credentials_set_cmdline_callbacks(struct cli_credentials *cred) { - if (cred->password_obtained <= CRED_CALLBACK) { - cred->password_cb = cmdline_get_userpassword; - cred->password_obtained = CRED_CALLBACK; - } + cli_credentials_set_password_callback(cred, cmdline_get_userpassword); } diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 579f199d2e..162b52e5d0 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -77,7 +77,8 @@ const char *cli_credentials_get_username(struct cli_credentials *cred, TALLOC_CT return talloc_reference(mem_ctx, cred->username); } -BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_username(struct cli_credentials *cred, + const char *val, enum credentials_obtained obtained) { if (obtained >= cred->username_obtained) { cred->username = talloc_strdup(cred, val); @@ -88,6 +89,20 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, return False; } +BOOL cli_credentials_set_username_callback(struct cli_credentials *cred, + const char *(*username_cb) (struct cli_credentials *)) +{ + if (cred->username_obtained < CRED_CALLBACK) { + cred->username_cb = username_cb; + cred->username_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + + + /** * Obtain the client principal for this credentials context. * @param cred credentials context @@ -124,6 +139,18 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred, const char *val return False; } +BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred, + const char *(*principal_cb) (struct cli_credentials *)) +{ + if (cred->principal_obtained < CRED_CALLBACK) { + cred->principal_cb = principal_cb; + cred->principal_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) { if (cred->principal_obtained >= CRED_SPECIFIED) { @@ -154,7 +181,9 @@ const char *cli_credentials_get_password(struct cli_credentials *cred) return cred->password; } -BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_password(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->password_obtained) { cred->password = talloc_strdup(cred, val); @@ -167,6 +196,18 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, return False; } +BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, + const char *(*password_cb) (struct cli_credentials *)) +{ + if (cred->password_obtained < CRED_CALLBACK) { + cred->password_cb = password_cb; + cred->password_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the password for this credentials context. * @param cred credentials context @@ -375,7 +416,8 @@ int cli_credentials_new_ccache(struct cli_credentials *cred) return ret; } -int cli_credentials_get_ccache(struct cli_credentials *cred, struct ccache_container **ccc) +int cli_credentials_get_ccache(struct cli_credentials *cred, + struct ccache_container **ccc) { krb5_error_code ret; @@ -432,7 +474,9 @@ const char *cli_credentials_get_domain(struct cli_credentials *cred) } -BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_domain(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->domain_obtained) { cred->domain = talloc_strdup(cred, val); @@ -443,6 +487,18 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e return False; } +BOOL cli_credentials_set_domain_callback(struct cli_credentials *cred, + const char *(*domain_cb) (struct cli_credentials *)) +{ + if (cred->domain_obtained < CRED_CALLBACK) { + cred->domain_cb = domain_cb; + cred->domain_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the Kerberos realm for this credentials context. * @param cred credentials context @@ -467,7 +523,9 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) * Set the realm for this credentials context, and force it to * uppercase for the sainity of our local kerberos libraries */ -BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_realm(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->realm_obtained) { cred->realm = strupper_talloc(cred, val); @@ -478,6 +536,18 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en return False; } +BOOL cli_credentials_set_realm_callback(struct cli_credentials *cred, + const char *(*realm_cb) (struct cli_credentials *)) +{ + if (cred->realm_obtained < CRED_CALLBACK) { + cred->realm_cb = realm_cb; + cred->realm_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context. * @@ -495,7 +565,9 @@ const char *cli_credentials_get_workstation(struct cli_credentials *cred) return cred->workstation; } -BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_workstation(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->workstation_obtained) { cred->workstation = talloc_strdup(cred, val); @@ -506,6 +578,18 @@ BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *v return False; } +BOOL cli_credentials_set_workstation_callback(struct cli_credentials *cred, + const char *(*workstation_cb) (struct cli_credentials *)) +{ + if (cred->workstation_obtained < CRED_CALLBACK) { + cred->workstation_cb = workstation_cb; + cred->workstation_obtained = CRED_CALLBACK; + return True; + } + + return False; +} + /** * Read a file descriptor, and parse it for a password (eg from a file or stdin) * @@ -514,7 +598,8 @@ BOOL cli_credentials_set_workstation(struct cli_credentials *cred, const char *v * @param obtained This enum describes how 'specified' this password is */ -BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, int fd, enum credentials_obtained obtained) +BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, + int fd, enum credentials_obtained obtained) { char *p; char pass[128]; -- cgit From cae788d5608b287b2c970ab28c0361350a5c7e95 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Aug 2005 01:51:36 +0000 Subject: r9773: r11599@blu: tridge | 2005-08-30 11:55:57 +1000 optimise this case a bit more. The total speedup using non-indexed ldbtest is now around a factor of 80x. The code is ugly as hell, but I think this speed is worth it. Of course, if we only ever do indexed searches in ldb then this doesn't help, but it seems all too common that we get unindexable searches, so the optimisation is worthwhile (This used to be commit 2e14fb893dd9815cdb2488c630131dc549e5c361) --- source4/lib/tdb/common/tdb.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 8e8e3ce3b3..d6861efe13 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1276,14 +1276,22 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, semantics don't change. With a non-indexed ldb search this trick gains us a - factor of more than 10 in speed on a linux 2.6.x - system. + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). */ if (!tlock->off && tlock->hash != 0) { u32 off; - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && - off == 0) { - continue; + if (tdb->map_ptr) { + for (;tlock->hash < tdb->header.hash_size;tlock->hash++) { + if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && + off == 0) { + continue; + } } } -- cgit From 8012fb2cfeede6ecae1346725141354f2897887e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Aug 2005 01:58:03 +0000 Subject: r9774: r11605@blu: tridge | 2005-08-30 12:02:19 +1000 make sure we don't walk off the end of the hash array (This used to be commit 3c32f24e2c6a99ec294fb16e1684cd22b08f2df4) --- source4/lib/tdb/common/tdb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index d6861efe13..3477d7e4be 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -1287,6 +1287,9 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, break; } } + if (tlock->hash == tdb->header.hash_size) { + continue; + } } else { if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && off == 0) { -- cgit From 5c6528336cecdb2d3f3316e6e73a78dcc0bc193a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Aug 2005 02:11:56 +0000 Subject: r9775: r11607@blu: tridge | 2005-08-30 12:16:19 +1000 fixed the help message (This used to be commit 5e3d9708f6592bf35f491f4ae979c20ad99e8358) --- source4/lib/ldb/tools/ldbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index a2e824dcdb..ef295b7411 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -363,8 +363,8 @@ static void usage(void) printf("Usage: ldbtest \n"); printf("Options:\n"); printf(" -H ldb_url choose the database (or $LDB_URL)\n"); - printf(" -r nrecords database size to use\n"); - printf(" -s nsearches number of searches to do\n"); + printf(" --num-records nrecords database size to use\n"); + printf(" --num-searches nsearches number of searches to do\n"); printf("\n"); printf("tests ldb API\n\n"); exit(1); -- cgit From f9447d2a17089178d311e03e398c25c749450f6d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:08:03 +0000 Subject: r9786: Move ldb_map into ldb/modules/ Move samba3sam to dsdb/ (This used to be commit eb9d615bcd49328131613f64745760a90553b7f2) --- source4/lib/ldb/config.mk | 5 +- source4/lib/ldb/ldb_map/README | 29 - source4/lib/ldb/ldb_map/ldb_map.c | 1151 ------------------------------------- source4/lib/ldb/ldb_map/ldb_map.h | 108 ---- source4/lib/ldb/modules/ldb_map.c | 1151 +++++++++++++++++++++++++++++++++++++ source4/lib/ldb/modules/ldb_map.h | 108 ++++ source4/lib/ldb/samba/samba3sam.c | 631 -------------------- source4/lib/ldb/tests/samba3.ldif | 200 ------- source4/lib/samba3/PLAN | 3 +- 9 files changed, 1263 insertions(+), 2123 deletions(-) delete mode 100644 source4/lib/ldb/ldb_map/README delete mode 100644 source4/lib/ldb/ldb_map/ldb_map.c delete mode 100644 source4/lib/ldb/ldb_map/ldb_map.h create mode 100644 source4/lib/ldb/modules/ldb_map.c create mode 100644 source4/lib/ldb/modules/ldb_map.h delete mode 100644 source4/lib/ldb/samba/samba3sam.c delete mode 100644 source4/lib/ldb/tests/samba3.ldif (limited to 'source4/lib') diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 23a99e367b..f75964c44f 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -41,7 +41,7 @@ NOPROTO = YES # Start MODULE libldb_map [MODULE::libldb_map] SUBSYSTEM = LIBLDB -INIT_OBJ_FILES = lib/ldb/ldb_map/ldb_map.o +INIT_OBJ_FILES = lib/ldb/modules/ldb_map.o # End MODULE libldb_map ################################################ @@ -115,8 +115,7 @@ REQUIRED_SUBSYSTEMS = \ # Start SUBSYSTEM LDBSAMBA [SUBSYSTEM::LDBSAMBA] OBJ_FILES = \ - lib/ldb/samba/ldif_handlers.o \ - lib/ldb/samba/samba3sam.o + lib/ldb/samba/ldif_handlers.o # End SUBSYSTEM LDBSAMBA ################################################ diff --git a/source4/lib/ldb/ldb_map/README b/source4/lib/ldb/ldb_map/README deleted file mode 100644 index 3c7e30a331..0000000000 --- a/source4/lib/ldb/ldb_map/README +++ /dev/null @@ -1,29 +0,0 @@ -This directory contains a skeleton backend for ldb backends that allow -using an LDAP server while mapping the attributes in that schema to -another schema. This backend will never be used itself but instead have -other backends based on it (e.g. ldb_samba3 for a Samba3-LDAP-to-samdb -backend) - -Each backend that uses this skeleton has to specify an array of -struct objectclass_mapping's (see ldb_map.h). - -If no mappings are defined for an objectclass, it will be kept as is. - -Special mapping routine for dn's (calls rdn mapping routine) -Special mapping routine for rdn's - -Keep cache of mapped dn's so we don't have to traverse the tree each time - -search - Simply uses search_bytree - -search_bytree - Map all attributes in parse_tree - -add -modify - Map ldb_message to LDAPMod - -rename -delete - Simply map dn diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c deleted file mode 100644 index 7a620f3b81..0000000000 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ /dev/null @@ -1,1151 +0,0 @@ -/* - ldb database library - map backend - - Copyright (C) Jelmer Vernooij 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "includes.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_private.h" -#include "lib/ldb/ldb_map/ldb_map.h" - -/* TODO: - * - objectclass hint in ldb_map_attribute - * for use when multiple remote attributes (independant of each other) - * map to one local attribute. E.g.: (uid, gidNumber) -> unixName - * (use MAP_GENERATE instead ?) - */ - -/* - - special attribute 'isMapped' - - add/modify - - split up ldb_message into fallback and mapped parts if is_mappable - - search: - - search local one for not isMapped entries - - remove remote attributes from ldb_parse_tree - - search remote one - - per record, search local one for additional data (by dn) - - test if (full expression) is now true - - delete - - delete both - - rename - - rename locally and remotely -*/ - -static const struct ldb_map_attribute builtin_attribute_maps[]; - -struct map_private { - struct ldb_map_context context; - const char *last_err_string; -}; - -static struct ldb_map_context *map_get_privdat(struct ldb_module *module) -{ - return &((struct map_private *)module->private_data)->context; -} - -static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) -{ - int i; - for (i = 0; privdat->objectclass_maps[i].local_name; i++) { - if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) - return &privdat->objectclass_maps[i]; - } - - return NULL; -} - -/* Decide whether a add/modify should be pushed to the - * remote LDAP server. We currently only do this if we see an objectClass we know */ -static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) -{ - int i; - struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); - - /* No objectClass... */ - if (el == NULL) { - return False; - } - - for (i = 0; i < el->num_values; i++) { - if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) - return True; - } - - return False; -} - -/* find an attribute by the local name */ -static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) -{ - int i; - - for (i = 0; privdat->attribute_maps[i].local_name; i++) { - if (!ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr)) - return &privdat->attribute_maps[i]; - } - - return NULL; -} - -/* find an attribute by the remote name */ -static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) -{ - int i; - - for (i = 0; privdat->attribute_maps[i].local_name; i++) { - if (privdat->attribute_maps[i].type == MAP_IGNORE) - continue; - - if (privdat->attribute_maps[i].type == MAP_GENERATE) - continue; - - if (privdat->attribute_maps[i].type == MAP_KEEP && - ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr) == 0) - return &privdat->attribute_maps[i]; - - if ((privdat->attribute_maps[i].type == MAP_RENAME || - privdat->attribute_maps[i].type == MAP_CONVERT) && - ldb_attr_cmp(privdat->attribute_maps[i].u.rename.remote_name, attr) == 0) - return &privdat->attribute_maps[i]; - - } - - return NULL; -} - -static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_parse_tree *tree) -{ - int i; - const struct ldb_map_attribute *attr; - struct ldb_parse_tree *new_tree; - enum ldb_map_attr_type map_type; - struct ldb_val value, newvalue; - struct ldb_map_context *privdat = map_get_privdat(module); - - if (tree == NULL) - return NULL; - - - /* Find attr in question and: - * - if it has a convert_operator function, run that - * - otherwise, replace attr name with required[0] */ - - if (tree->operation == LDB_OP_AND || - tree->operation == LDB_OP_OR) { - - new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); - new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); - new_tree->u.list.num_elements = 0; - for (i = 0; i < tree->u.list.num_elements; i++) { - struct ldb_parse_tree *child = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); - - if (child) { - new_tree->u.list.elements[i] = child; - new_tree->u.list.num_elements++; - } - } - - return new_tree; - } - - if (tree->operation == LDB_OP_NOT) { - struct ldb_parse_tree *child; - - new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); - child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); - - if (!child) { - talloc_free(new_tree); - return NULL; - } - - new_tree->u.isnot.child = child; - return new_tree; - } - - /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER, - * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED - * - * (all have attr as the first element) - */ - - attr = map_find_attr_local(privdat, tree->u.equality.attr); - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); - map_type = MAP_KEEP; - } else { - map_type = attr->type; - } - - if (attr && attr->convert_operator) { - /* Run convert_operator */ - return attr->convert_operator(privdat, module, tree); - } - - if (map_type == MAP_IGNORE) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); - return NULL; - } - - if (map_type == MAP_GENERATE) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr); - return NULL; - } - - if (tree->operation == LDB_OP_EQUALITY) { - value = tree->u.equality.value; - } else if (tree->operation == LDB_OP_LESS || tree->operation == LDB_OP_GREATER || - tree->operation == LDB_OP_APPROX) { - value = tree->u.comparison.value; - } else if (tree->operation == LDB_OP_EXTENDED) { - value = tree->u.extended.value; - } - - new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); - - if (map_type == MAP_KEEP) { - new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); - } else { /* MAP_RENAME / MAP_CONVERT */ - new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); - } - - if (new_tree->operation == LDB_OP_PRESENT) - return new_tree; - - if (new_tree->operation == LDB_OP_SUBSTRING) { - new_tree->u.substring.chunks = NULL; /* FIXME! */ - return new_tree; - } - - if (map_type == MAP_CONVERT) { - newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); - } else { - newvalue = ldb_val_dup(new_tree, &value); - } - - if (new_tree->operation == LDB_OP_EQUALITY) { - new_tree->u.equality.value = newvalue; - } else if (new_tree->operation == LDB_OP_LESS || new_tree->operation == LDB_OP_GREATER || - new_tree->operation == LDB_OP_APPROX) { - new_tree->u.comparison.value = newvalue; - } else if (new_tree->operation == LDB_OP_EXTENDED) { - new_tree->u.extended.value = newvalue; - new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); - } - - return new_tree; -} - -/* Remote DN -> Local DN */ -static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) -{ - struct ldb_dn *newdn; - int i; - - if (dn == NULL) - return NULL; - - newdn = talloc_memdup(ctx, dn, sizeof(*dn)); - if (!newdn) - return NULL; - - newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); - - if (!newdn->components) - return NULL; - - /* For each rdn, map the attribute name and possibly the - * complete rdn */ - - for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); - enum ldb_map_attr_type map_type; - - /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr) map_type = MAP_KEEP; - else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: - case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); - talloc_free(newdn); - return NULL; - - case MAP_KEEP: - newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - break; - - case MAP_CONVERT: - newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); - newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); - break; - - case MAP_RENAME: - newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - break; - } - } - return newdn; -} - -/* Local DN -> Remote DN */ -static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) -{ - struct ldb_dn *newdn; - int i; - - if (dn == NULL) - return NULL; - - newdn = talloc_memdup(ctx, dn, sizeof(*dn)); - if (!newdn) - return NULL; - - newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); - - if (!newdn->components) - return NULL; - - /* For each rdn, map the attribute name and possibly the - * complete rdn using an equality convert_operator call */ - - for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); - enum ldb_map_attr_type map_type; - - /* Unknown attribute - leave this dn as is and hope the best... */ - if (!attr) map_type = MAP_KEEP; else map_type = attr->type; - - switch (map_type) - { - case MAP_IGNORE: - case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); - talloc_free(newdn); - return NULL; - - case MAP_CONVERT: - newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); - newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); - break; - - case MAP_RENAME: - newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - break; - - case MAP_KEEP: - newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); - newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); - continue; - } - } - - return newdn; -} - -/* Loop over ldb_map_attribute array and add remote_names */ -static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) -{ - int i; - const char **ret; - int ar_size = 0, last_element = 0; - struct ldb_map_context *privdat = map_get_privdat(module); - - if (attrs == NULL) - return NULL; - - /* Start with good guess of number of elements */ - for (i = 0; attrs[i]; i++); - - ret = talloc_array(module, const char *, i); - ar_size = i; - - for (i = 0; attrs[i]; i++) { - int j; - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); - enum ldb_map_attr_type map_type; - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); - map_type = MAP_IGNORE; - } else map_type = attr->type; - - switch (map_type) - { - case MAP_IGNORE: break; - case MAP_KEEP: - if (last_element >= ar_size) { - ret = talloc_realloc(module, ret, const char *, ar_size+1); - ar_size++; - } - ret[last_element] = attr->local_name; - last_element++; - break; - - case MAP_RENAME: - case MAP_CONVERT: - if (last_element >= ar_size) { - ret = talloc_realloc(module, ret, const char *, ar_size+1); - ar_size++; - } - ret[last_element] = attr->u.rename.remote_name; - last_element++; - break; - - case MAP_GENERATE: - /* Add remote_names[] for this attribute to the list of - * attributes to request from the remote server */ - for (j = 0; attr->u.generate.remote_names[j]; j++) { - if (last_element >= ar_size) { - ret = talloc_realloc(module, ret, const char *, ar_size+1); - ar_size++; - } - ret[last_element] = attr->u.generate.remote_names[j]; - last_element++; - } - break; - } - } - - if (last_element >= ar_size) { - ret = talloc_realloc(module, ret, const char *, ar_size+1); - ar_size++; - } - - ret[last_element] = NULL; - - return ret; -} - -static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - int i, j; - int count = 0; - const char **ret = talloc_array(module, const char *, 1); - - ret[0] = NULL; - - for (i = 0; privdat->attribute_maps[i].local_name; i++) { - BOOL avail = False; - const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; - - /* If all remote attributes for this attribute are present, add the - * local one to the list */ - - switch (attr->type) { - case MAP_IGNORE: break; - case MAP_KEEP: - avail = (ldb_msg_find_ldb_val(msg, attr->local_name) != NULL); - break; - - case MAP_RENAME: - case MAP_CONVERT: - avail = (ldb_msg_find_ldb_val(msg, attr->u.rename.remote_name) != NULL); - break; - - case MAP_GENERATE: - avail = True; - for (j = 0; attr->u.generate.remote_names[j]; j++) { - avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); - } - break; - } - - if (!avail) - continue; - - ret = talloc_realloc(module, ret, const char *, count+2); - ret[count] = attr->local_name; - ret[count+1] = NULL; - count++; - } - - return ret; -} - -/* Used for search */ -static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) -{ - int i, j; - struct ldb_message *msg = talloc_zero(module, struct ldb_message); - struct ldb_message_element *elm, *oldelm; - struct ldb_map_context *privdat = map_get_privdat(module); - const char **newattrs = NULL; - - msg->dn = map_remote_dn(privdat, module, mi->dn); - - ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); - - /* Loop over attrs, find in ldb_map_attribute array and - * run generate() */ - - if (attrs == NULL) { - /* Generate list of the local attributes that /can/ be generated - * using the specific remote attributes */ - - attrs = newattrs = available_local_attributes(module, mi); - } - - for (i = 0; attrs[i]; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); - enum ldb_map_attr_type map_type; - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s' when generating incoming message\n", attrs[i]); - map_type = MAP_IGNORE; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE:break; - case MAP_RENAME: - oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; - - elm = talloc(msg, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->local_name); - elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); - - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); - break; - - case MAP_CONVERT: - oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; - - elm = talloc(msg, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->local_name); - elm->num_values = oldelm->num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < oldelm->num_values; j++) - elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); - - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); - break; - - case MAP_KEEP: - oldelm = ldb_msg_find_element(mi, attr->local_name); - if (!oldelm) continue; - - elm = talloc(msg, struct ldb_message_element); - - elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); - elm->name = talloc_strdup(elm, oldelm->name); - - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); - break; - - case MAP_GENERATE: - elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); - if (!elm) continue; - - ldb_msg_add(module->ldb, msg, elm, elm->flags); - break; - default: - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); - break; - } - } - - talloc_free(newattrs); - - return msg; -} - -/* Used for add, modify */ -static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message *msg = talloc_zero(module, struct ldb_message); - struct ldb_message_element *elm; - int i,j; - - *fb = talloc_zero(module, struct ldb_message); - (*fb)->dn = talloc_reference(*fb, mo->dn); - - *mp = msg; - - msg->private_data = mo->private_data; - - msg->dn = map_local_dn(privdat, module, mo->dn); - - /* Loop over mi and call generate_remote for each attribute */ - for (i = 0; i < mo->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); - enum ldb_map_attr_type map_type; - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); - map_type = MAP_IGNORE; - continue; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: /* Add to fallback message */ - elm = talloc(*fb, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); - break; - case MAP_RENAME: - elm = talloc(msg, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); - break; - - case MAP_CONVERT: - elm = talloc(msg, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); - } - - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); - break; - - case MAP_KEEP: - elm = talloc(msg, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); - break; - - case MAP_GENERATE: - attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); - break; - } - } - - return 0; -} - - -/* - rename a record -*/ -static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_dn *n_olddn, *n_newdn; - int ret; - - ret = ldb_next_rename_record(module, olddn, newdn); - - n_olddn = map_local_dn(privdat, module, olddn); - n_newdn = map_local_dn(privdat, module, newdn); - - ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); - - talloc_free(n_olddn); - talloc_free(n_newdn); - - return ret; -} - -/* - delete a record -*/ -static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_dn *newdn; - int ret; - - ret = ldb_next_delete_record(module, dn); - - newdn = map_local_dn(privdat, module, dn); - - ret = ldb_delete(privdat->mapped_ldb, newdn); - - talloc_free(newdn); - - return ret; -} - -/* search fallback database */ -static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - int ret; - struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; - - t_present.operation = LDB_OP_PRESENT; - t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); - - t_not.operation = LDB_OP_NOT; - t_not.u.isnot.child = &t_present; - - childs[0] = &t_not; - childs[1] = tree; - t_and.operation = LDB_OP_AND; - t_and.u.list.num_elements = 2; - t_and.u.list.elements = childs; - - ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); - - talloc_free(t_present.u.present.attr); - - return ret; -} - -static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - struct ldb_parse_tree *new_tree; - struct ldb_dn *new_base; - struct ldb_message **newres; - const char **newattrs; - int mpret, ret; - struct ldb_map_context *privdat = map_get_privdat(module); - int i; - - /*- search mapped database */ - - new_tree = ldb_map_parse_tree(module, module, tree); - newattrs = ldb_map_attrs(module, attrs); - new_base = map_local_dn(privdat, module, base); - - mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); - - talloc_free(new_base); - talloc_free(new_tree); - talloc_free(newattrs); - - if (mpret == -1) { - struct map_private *map_private = module->private_data; - map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); - return -1; - } - - /* - - per returned record, search fallback database for additional data (by dn) - - test if (full expression) is now true - */ - - *res = talloc_array(module, struct ldb_message *, mpret); - - ret = 0; - - for (i = 0; i < mpret; i++) { - struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); - struct ldb_message **extrares = NULL; - int extraret; - - /* Merge with additional data from local database */ - extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); - - if (extraret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n"); - } else if (extraret > 1) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More than one result for extra data!\n"); - talloc_free(newres); - return -1; - } else if (extraret == 0) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); - } - - if (extraret == 1) { - int j; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); - for (j = 0; j < extrares[0]->num_elements; j++) { - ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); - } - - ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); - } else { - ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); - } - - if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { - (*res)[ret] = merged; - ret++; - } else { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match"); - } - } - - talloc_free(newres); - - return ret; -} - - -/* - search for matching records using a ldb_parse_tree -*/ -static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - struct ldb_message **fbres, **mpres; - int i; - int ret_fb, ret_mp; - - ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); - if (ret_fb == -1) - return -1; - - ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); - if (ret_mp == -1) { - return -1; - } - - /* Merge results */ - *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); - - for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; - for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; - - return ret_fb + ret_mp; -} -/* - search for matching records -*/ -static int map_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - struct map_private *map = module->private_data; - struct ldb_parse_tree *tree; - int ret; - - tree = ldb_parse_tree(NULL, expression); - if (tree == NULL) { - map->last_err_string = "expression parse failed"; - return -1; - } - - ret = map_search_bytree(module, base, scope, tree, attrs, res); - talloc_free(tree); - return ret; -} - -/* - add a record -*/ -static int map_add(struct ldb_module *module, const struct ldb_message *msg) -{ - int ret; - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message *fb, *mp; - - if (!map_is_mappable(privdat, msg)) { - return ldb_next_add_record(module, msg); - } - - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - - ret = ldb_next_add_record(module, fb); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); - return -1; - } - - ret = ldb_add(privdat->mapped_ldb, mp); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); - return -1; - } - - talloc_free(fb); - talloc_free(mp); - - return ret; -} - - -/* - modify a record -*/ -static int map_modify(struct ldb_module *module, const struct ldb_message *msg) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message *fb, *mp; - int ret; - - if (!map_is_mappable(privdat, msg)) - return ldb_next_modify_record(module, msg); - - - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - - ret = ldb_next_modify_record(module, fb); - - ret = ldb_modify(privdat->mapped_ldb, mp); - - talloc_free(fb); - talloc_free(mp); - - return ret; -} - -static int map_lock(struct ldb_module *module, const char *lockname) -{ - return ldb_next_named_lock(module, lockname); -} - -static int map_unlock(struct ldb_module *module, const char *lockname) -{ - return ldb_next_named_unlock(module, lockname); -} - -/* - return extended error information -*/ -static const char *map_errstring(struct ldb_module *module) -{ - struct map_private *map = module->private_data; - - if (map->last_err_string) - return map->last_err_string; - - return ldb_next_errstring(module); -} - -static const struct ldb_module_ops map_ops = { - .name = "map", - .search = map_search, - .search_bytree = map_search_bytree, - .add_record = map_add, - .modify_record = map_modify, - .delete_record = map_delete, - .rename_record = map_rename, - .named_lock = map_lock, - .named_unlock = map_unlock, - .errstring = map_errstring -}; - -static char *map_find_url(struct ldb_context *ldb, const char *name) -{ - const char * const attrs[] = { "@MAP_URL" , NULL}; - struct ldb_message **msg = NULL; - struct ldb_dn *mods; - char *url; - int ret; - - mods = ldb_dn_string_compose(ldb, NULL, "@MAP=%s", name); - if (mods == NULL) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Can't construct DN"); - return NULL; - } - - ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg); - talloc_free(mods); - if (ret < 1) { - ldb_debug(ldb, LDB_DEBUG_ERROR, "Not enough results found looking for @MAP"); - return NULL; - } - - url = talloc_strdup(ldb, ldb_msg_find_string(msg[0], "@MAP_URL", NULL)); - - talloc_free(msg); - - return url; -} - -/* the init function */ -struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name) -{ - int i, j; - struct ldb_module *ctx; - struct map_private *data; - char *url; - - ctx = talloc(ldb, struct ldb_module); - if (!ctx) - return NULL; - - data = talloc(ctx, struct map_private); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->context.mapped_ldb = ldb_init(data); - url = map_find_url(ldb, name); - - if (!url) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "@MAP=%s not set!\n", name); - return NULL; - } - - if (ldb_connect(data->context.mapped_ldb, url, 0, NULL) != 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to open mapped database for %s at '%s'\n", name, url); - return NULL; - } - - talloc_free(url); - - data->last_err_string = NULL; - - /* Get list of attribute maps */ - j = 0; - data->context.attribute_maps = NULL; - - for (i = 0; attrs[i].local_name; i++) { - data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); - data->context.attribute_maps[j] = attrs[i]; - j++; - } - - for (i = 0; builtin_attribute_maps[i].local_name; i++) { - data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); - data->context.attribute_maps[j] = builtin_attribute_maps[i]; - j++; - } - - data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); - ZERO_STRUCT(data->context.attribute_maps[j].local_name); - - data->context.objectclass_maps = ocls; - ctx->private_data = data; - ctx->ldb = ldb; - ctx->prev = ctx->next = NULL; - ctx->ops = &map_ops; - - return ctx; -} - -static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - struct ldb_dn *dn, *newdn;; - struct ldb_val *newval; - - dn = ldb_dn_explode(ctx, (char *)val->data); - - newdn = map_local_dn(map, ctx, dn); - - talloc_free(dn); - - newval = talloc(ctx, struct ldb_val); - newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); - - talloc_free(newdn); - - return *newval; -} - -static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - struct ldb_dn *dn, *newdn;; - struct ldb_val *newval; - - dn = ldb_dn_explode(ctx, (char *)val->data); - - newdn = map_remote_dn(map, ctx, dn); - - talloc_free(dn); - - newval = talloc(ctx, struct ldb_val); - newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); - - talloc_free(newdn); - - return *newval; -} - -static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - int i; - - for (i = 0; map->objectclass_maps[i].local_name; i++) { - if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { - struct ldb_val newval; - newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].remote_name); - newval.length = strlen((char *)newval.data); - - return ldb_val_dup(ctx, &newval); - } - } - - return ldb_val_dup(ctx, val); -} - -static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - int i; - - for (i = 0; map->objectclass_maps[i].remote_name; i++) { - if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { - struct ldb_val newval; - newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].local_name); - newval.length = strlen((char *)newval.data); - - return ldb_val_dup(ctx, &newval); - } - } - - return ldb_val_dup(ctx, val); -} - -static const struct ldb_map_attribute builtin_attribute_maps[] = { - { - .local_name = "dn", - .type = MAP_CONVERT, - .u.convert.remote_name = "dn", - .u.convert.convert_local = map_convert_local_dn, - .u.convert.convert_remote = map_convert_remote_dn, - }, - { - .local_name = "objectclass", - .type = MAP_CONVERT, - .u.convert.remote_name = "objectclass", - .u.convert.convert_local = map_convert_local_objectclass, - .u.convert.convert_remote = map_convert_remote_objectclass, - }, - { - .local_name = NULL, - } -}; - diff --git a/source4/lib/ldb/ldb_map/ldb_map.h b/source4/lib/ldb/ldb_map/ldb_map.h deleted file mode 100644 index 02fec649c6..0000000000 --- a/source4/lib/ldb/ldb_map/ldb_map.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - ldb database library - map backend - - Copyright (C) Jelmer Vernooij 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LDB_MAP_H__ -#define __LDB_MAP_H__ - -/* ldb_map is a skeleton LDB module that can be used for any other modules - * that need to map attributes. - * - * The term 'remote' in this header refers to the connection where the - * original schema is used on while 'local' means the local connection - * that any upper layers will use. - * - * All local attributes will have to have a definition. Not all remote - * attributes need a definition as LDB is a lot less stricter then LDAP - * (in other words, sending unknown attributes to an LDAP server hurts us, - * returning too much attributes in ldb_search() doesn't) - */ - -struct ldb_map_context; - -struct ldb_map_attribute -{ - const char *local_name; /* local name */ - - enum ldb_map_attr_type { - MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ - MAP_KEEP, /* Keep as is. Same name locally and remotely. */ - MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ - MAP_CONVERT, /* Rename + convert data */ - MAP_GENERATE /* Use generate function for generating new name/data. - Used for generating attributes based on - multiple remote attributes. */ - } type; - - /* if set, will be called for expressions that contain this attribute */ - struct ldb_parse_tree *(*convert_operator) (struct ldb_map_context *, TALLOC_CTX *ctx, const struct ldb_parse_tree *); - - union { - struct { - const char *remote_name; - } rename; - - struct { - const char *remote_name; - struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); - struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); - } convert; - - struct { - /* Generate the local attribute from remote message */ - struct ldb_message_element *(*generate_local) ( - struct ldb_map_context *, - TALLOC_CTX *ctx, - const char *attr, - const struct ldb_message *remote); - - /* Update remote message with information from local message */ - void (*generate_remote) ( - struct ldb_map_context *, - const char *local_attr, - const struct ldb_message *local, - struct ldb_message *remote); - - /* Name(s) for this attribute on the remote server. This is an array since - * one local attribute's data can be split up into several attributes - * remotely */ -#define LDB_MAP_MAX_REMOTE_NAMES 10 - const char *remote_names[LDB_MAP_MAX_REMOTE_NAMES]; - } generate; - } u; -}; - -struct ldb_map_objectclass -{ - const char *local_name; - const char *remote_name; -}; - -struct ldb_map_context -{ - struct ldb_map_attribute *attribute_maps; - const struct ldb_map_objectclass *objectclass_maps; - struct ldb_context *mapped_ldb; -}; - -#endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c new file mode 100644 index 0000000000..531d5ccd67 --- /dev/null +++ b/source4/lib/ldb/modules/ldb_map.c @@ -0,0 +1,1151 @@ +/* + ldb database library - map backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_private.h" +#include "lib/ldb/modules/ldb_map.h" + +/* TODO: + * - objectclass hint in ldb_map_attribute + * for use when multiple remote attributes (independant of each other) + * map to one local attribute. E.g.: (uid, gidNumber) -> unixName + * (use MAP_GENERATE instead ?) + */ + +/* + - special attribute 'isMapped' + - add/modify + - split up ldb_message into fallback and mapped parts if is_mappable + - search: + - search local one for not isMapped entries + - remove remote attributes from ldb_parse_tree + - search remote one + - per record, search local one for additional data (by dn) + - test if (full expression) is now true + - delete + - delete both + - rename + - rename locally and remotely +*/ + +static const struct ldb_map_attribute builtin_attribute_maps[]; + +struct map_private { + struct ldb_map_context context; + const char *last_err_string; +}; + +static struct ldb_map_context *map_get_privdat(struct ldb_module *module) +{ + return &((struct map_private *)module->private_data)->context; +} + +static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) +{ + int i; + for (i = 0; privdat->objectclass_maps[i].local_name; i++) { + if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) + return &privdat->objectclass_maps[i]; + } + + return NULL; +} + +/* Decide whether a add/modify should be pushed to the + * remote LDAP server. We currently only do this if we see an objectClass we know */ +static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +{ + int i; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + + /* No objectClass... */ + if (el == NULL) { + return False; + } + + for (i = 0; i < el->num_values; i++) { + if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) + return True; + } + + return False; +} + +/* find an attribute by the local name */ +static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) +{ + int i; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (!ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr)) + return &privdat->attribute_maps[i]; + } + + return NULL; +} + +/* find an attribute by the remote name */ +static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) +{ + int i; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + if (privdat->attribute_maps[i].type == MAP_IGNORE) + continue; + + if (privdat->attribute_maps[i].type == MAP_GENERATE) + continue; + + if (privdat->attribute_maps[i].type == MAP_KEEP && + ldb_attr_cmp(privdat->attribute_maps[i].local_name, attr) == 0) + return &privdat->attribute_maps[i]; + + if ((privdat->attribute_maps[i].type == MAP_RENAME || + privdat->attribute_maps[i].type == MAP_CONVERT) && + ldb_attr_cmp(privdat->attribute_maps[i].u.rename.remote_name, attr) == 0) + return &privdat->attribute_maps[i]; + + } + + return NULL; +} + +static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_parse_tree *tree) +{ + int i; + const struct ldb_map_attribute *attr; + struct ldb_parse_tree *new_tree; + enum ldb_map_attr_type map_type; + struct ldb_val value, newvalue; + struct ldb_map_context *privdat = map_get_privdat(module); + + if (tree == NULL) + return NULL; + + + /* Find attr in question and: + * - if it has a convert_operator function, run that + * - otherwise, replace attr name with required[0] */ + + if (tree->operation == LDB_OP_AND || + tree->operation == LDB_OP_OR) { + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, tree->u.list.num_elements); + new_tree->u.list.num_elements = 0; + for (i = 0; i < tree->u.list.num_elements; i++) { + struct ldb_parse_tree *child = ldb_map_parse_tree(module, new_tree, tree->u.list.elements[i]); + + if (child) { + new_tree->u.list.elements[i] = child; + new_tree->u.list.num_elements++; + } + } + + return new_tree; + } + + if (tree->operation == LDB_OP_NOT) { + struct ldb_parse_tree *child; + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + child = ldb_map_parse_tree(module, new_tree, tree->u.isnot.child); + + if (!child) { + talloc_free(new_tree); + return NULL; + } + + new_tree->u.isnot.child = child; + return new_tree; + } + + /* tree->operation is LDB_OP_EQUALITY, LDB_OP_SUBSTRING, LDB_OP_GREATER, + * LDB_OP_LESS, LDB_OP_APPROX, LDB_OP_PRESENT or LDB_OP_EXTENDED + * + * (all have attr as the first element) + */ + + attr = map_find_attr_local(privdat, tree->u.equality.attr); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); + map_type = MAP_KEEP; + } else { + map_type = attr->type; + } + + if (attr && attr->convert_operator) { + /* Run convert_operator */ + return attr->convert_operator(privdat, module, tree); + } + + if (map_type == MAP_IGNORE) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); + return NULL; + } + + if (map_type == MAP_GENERATE) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Can't do conversion for MAP_GENERATE in map_parse_tree without convert_operator for '%s'\n", tree->u.equality.attr); + return NULL; + } + + if (tree->operation == LDB_OP_EQUALITY) { + value = tree->u.equality.value; + } else if (tree->operation == LDB_OP_LESS || tree->operation == LDB_OP_GREATER || + tree->operation == LDB_OP_APPROX) { + value = tree->u.comparison.value; + } else if (tree->operation == LDB_OP_EXTENDED) { + value = tree->u.extended.value; + } + + new_tree = talloc_memdup(ctx, tree, sizeof(*tree)); + + if (map_type == MAP_KEEP) { + new_tree->u.equality.attr = talloc_strdup(new_tree, tree->u.equality.attr); + } else { /* MAP_RENAME / MAP_CONVERT */ + new_tree->u.equality.attr = talloc_strdup(new_tree, attr->u.rename.remote_name); + } + + if (new_tree->operation == LDB_OP_PRESENT) + return new_tree; + + if (new_tree->operation == LDB_OP_SUBSTRING) { + new_tree->u.substring.chunks = NULL; /* FIXME! */ + return new_tree; + } + + if (map_type == MAP_CONVERT) { + newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); + } else { + newvalue = ldb_val_dup(new_tree, &value); + } + + if (new_tree->operation == LDB_OP_EQUALITY) { + new_tree->u.equality.value = newvalue; + } else if (new_tree->operation == LDB_OP_LESS || new_tree->operation == LDB_OP_GREATER || + new_tree->operation == LDB_OP_APPROX) { + new_tree->u.comparison.value = newvalue; + } else if (new_tree->operation == LDB_OP_EXTENDED) { + new_tree->u.extended.value = newvalue; + new_tree->u.extended.rule_id = talloc_strdup(new_tree, tree->u.extended.rule_id); + } + + return new_tree; +} + +/* Remote DN -> Local DN */ +static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int i; + + if (dn == NULL) + return NULL; + + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) map_type = MAP_KEEP; + else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: + case MAP_GENERATE: + DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); + break; + + case MAP_RENAME: + newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + } + } + return newdn; +} + +/* Local DN -> Remote DN */ +static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +{ + struct ldb_dn *newdn; + int i; + + if (dn == NULL) + return NULL; + + newdn = talloc_memdup(ctx, dn, sizeof(*dn)); + if (!newdn) + return NULL; + + newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num); + + if (!newdn->components) + return NULL; + + /* For each rdn, map the attribute name and possibly the + * complete rdn using an equality convert_operator call */ + + for (i = 0; i < dn->comp_num; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); + enum ldb_map_attr_type map_type; + + /* Unknown attribute - leave this dn as is and hope the best... */ + if (!attr) map_type = MAP_KEEP; else map_type = attr->type; + + switch (map_type) + { + case MAP_IGNORE: + case MAP_GENERATE: + DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + talloc_free(newdn); + return NULL; + + case MAP_CONVERT: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); + newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); + break; + + case MAP_RENAME: + newdn->components[i].name = talloc_strdup(newdn->components, attr->u.rename.remote_name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + break; + + case MAP_KEEP: + newdn->components[i].name = talloc_strdup(newdn->components, dn->components[i].name); + newdn->components[i].value = ldb_val_dup(newdn->components, &dn->components[i].value); + continue; + } + } + + return newdn; +} + +/* Loop over ldb_map_attribute array and add remote_names */ +static const char **ldb_map_attrs(struct ldb_module *module, const char *const attrs[]) +{ + int i; + const char **ret; + int ar_size = 0, last_element = 0; + struct ldb_map_context *privdat = map_get_privdat(module); + + if (attrs == NULL) + return NULL; + + /* Start with good guess of number of elements */ + for (i = 0; attrs[i]; i++); + + ret = talloc_array(module, const char *, i); + ar_size = i; + + for (i = 0; attrs[i]; i++) { + int j; + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) + { + case MAP_IGNORE: break; + case MAP_KEEP: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->local_name; + last_element++; + break; + + case MAP_RENAME: + case MAP_CONVERT: + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.rename.remote_name; + last_element++; + break; + + case MAP_GENERATE: + /* Add remote_names[] for this attribute to the list of + * attributes to request from the remote server */ + for (j = 0; attr->u.generate.remote_names[j]; j++) { + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + ret[last_element] = attr->u.generate.remote_names[j]; + last_element++; + } + break; + } + } + + if (last_element >= ar_size) { + ret = talloc_realloc(module, ret, const char *, ar_size+1); + ar_size++; + } + + ret[last_element] = NULL; + + return ret; +} + +static const char **available_local_attributes(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + int i, j; + int count = 0; + const char **ret = talloc_array(module, const char *, 1); + + ret[0] = NULL; + + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + BOOL avail = False; + const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; + + /* If all remote attributes for this attribute are present, add the + * local one to the list */ + + switch (attr->type) { + case MAP_IGNORE: break; + case MAP_KEEP: + avail = (ldb_msg_find_ldb_val(msg, attr->local_name) != NULL); + break; + + case MAP_RENAME: + case MAP_CONVERT: + avail = (ldb_msg_find_ldb_val(msg, attr->u.rename.remote_name) != NULL); + break; + + case MAP_GENERATE: + avail = True; + for (j = 0; attr->u.generate.remote_names[j]; j++) { + avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); + } + break; + } + + if (!avail) + continue; + + ret = talloc_realloc(module, ret, const char *, count+2); + ret[count] = attr->local_name; + ret[count+1] = NULL; + count++; + } + + return ret; +} + +/* Used for search */ +static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, const char * const*attrs, const struct ldb_message *mi) +{ + int i, j; + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm, *oldelm; + struct ldb_map_context *privdat = map_get_privdat(module); + const char **newattrs = NULL; + + msg->dn = map_remote_dn(privdat, module, mi->dn); + + ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); + + /* Loop over attrs, find in ldb_map_attribute array and + * run generate() */ + + if (attrs == NULL) { + /* Generate list of the local attributes that /can/ be generated + * using the specific remote attributes */ + + attrs = newattrs = available_local_attributes(module, mi); + } + + for (i = 0; attrs[i]; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, attrs[i]); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s' when generating incoming message\n", attrs[i]); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE:break; + case MAP_RENAME: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_CONVERT: + oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + elm->name = talloc_strdup(elm, attr->local_name); + elm->num_values = oldelm->num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_KEEP: + oldelm = ldb_msg_find_element(mi, attr->local_name); + if (!oldelm) continue; + + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = oldelm->num_values; + elm->values = talloc_reference(elm, oldelm->values); + elm->name = talloc_strdup(elm, oldelm->name); + + ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + break; + + case MAP_GENERATE: + elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); + if (!elm) continue; + + ldb_msg_add(module->ldb, msg, elm, elm->flags); + break; + default: + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); + break; + } + } + + talloc_free(newattrs); + + return msg; +} + +/* Used for add, modify */ +static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *msg = talloc_zero(module, struct ldb_message); + struct ldb_message_element *elm; + int i,j; + + *fb = talloc_zero(module, struct ldb_message); + (*fb)->dn = talloc_reference(*fb, mo->dn); + + *mp = msg; + + msg->private_data = mo->private_data; + + msg->dn = map_local_dn(privdat, module, mo->dn); + + /* Loop over mi and call generate_remote for each attribute */ + for (i = 0; i < mo->num_elements; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); + enum ldb_map_attr_type map_type; + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); + map_type = MAP_IGNORE; + continue; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: /* Add to fallback message */ + elm = talloc(*fb, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); + break; + case MAP_RENAME: + elm = talloc(msg, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_CONVERT: + elm = talloc(msg, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); + } + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_KEEP: + elm = talloc(msg, struct ldb_message_element); + + elm->num_values = mo->elements[i].num_values; + elm->values = talloc_reference(elm, mo->elements[i].values); + elm->name = talloc_strdup(elm, mo->elements[i].name); + + ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + break; + + case MAP_GENERATE: + attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); + break; + } + } + + return 0; +} + + +/* + rename a record +*/ +static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_dn *n_olddn, *n_newdn; + int ret; + + ret = ldb_next_rename_record(module, olddn, newdn); + + n_olddn = map_local_dn(privdat, module, olddn); + n_newdn = map_local_dn(privdat, module, newdn); + + ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + + talloc_free(n_olddn); + talloc_free(n_newdn); + + return ret; +} + +/* + delete a record +*/ +static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_dn *newdn; + int ret; + + ret = ldb_next_delete_record(module, dn); + + newdn = map_local_dn(privdat, module, dn); + + ret = ldb_delete(privdat->mapped_ldb, newdn); + + talloc_free(newdn); + + return ret; +} + +/* search fallback database */ +static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + int ret; + struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; + + t_present.operation = LDB_OP_PRESENT; + t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); + + t_not.operation = LDB_OP_NOT; + t_not.u.isnot.child = &t_present; + + childs[0] = &t_not; + childs[1] = tree; + t_and.operation = LDB_OP_AND; + t_and.u.list.num_elements = 2; + t_and.u.list.elements = childs; + + ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); + + talloc_free(t_present.u.present.attr); + + return ret; +} + +static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct ldb_parse_tree *new_tree; + struct ldb_dn *new_base; + struct ldb_message **newres; + const char **newattrs; + int mpret, ret; + struct ldb_map_context *privdat = map_get_privdat(module); + int i; + + /*- search mapped database */ + + new_tree = ldb_map_parse_tree(module, module, tree); + newattrs = ldb_map_attrs(module, attrs); + new_base = map_local_dn(privdat, module, base); + + mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); + + talloc_free(new_base); + talloc_free(new_tree); + talloc_free(newattrs); + + if (mpret == -1) { + struct map_private *map_private = module->private_data; + map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); + return -1; + } + + /* + - per returned record, search fallback database for additional data (by dn) + - test if (full expression) is now true + */ + + *res = talloc_array(module, struct ldb_message *, mpret); + + ret = 0; + + for (i = 0; i < mpret; i++) { + struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); + struct ldb_message **extrares = NULL; + int extraret; + + /* Merge with additional data from local database */ + extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); + + if (extraret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error searching for extra data!\n"); + } else if (extraret > 1) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "More than one result for extra data!\n"); + talloc_free(newres); + return -1; + } else if (extraret == 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + } + + if (extraret == 1) { + int j; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); + for (j = 0; j < extrares[0]->num_elements; j++) { + ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); + } + + ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); + } else { + ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); + } + + if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { + (*res)[ret] = merged; + ret++; + } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Discarded merged message because it did not match"); + } + } + + talloc_free(newres); + + return ret; +} + + +/* + search for matching records using a ldb_parse_tree +*/ +static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + struct ldb_message **fbres, **mpres; + int i; + int ret_fb, ret_mp; + + ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); + if (ret_fb == -1) + return -1; + + ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); + if (ret_mp == -1) { + return -1; + } + + /* Merge results */ + *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); + + for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; + for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; + + return ret_fb + ret_mp; +} +/* + search for matching records +*/ +static int map_search(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) +{ + struct map_private *map = module->private_data; + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(NULL, expression); + if (tree == NULL) { + map->last_err_string = "expression parse failed"; + return -1; + } + + ret = map_search_bytree(module, base, scope, tree, attrs, res); + talloc_free(tree); + return ret; +} + +/* + add a record +*/ +static int map_add(struct ldb_module *module, const struct ldb_message *msg) +{ + int ret; + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; + + if (!map_is_mappable(privdat, msg)) { + return ldb_next_add_record(module, msg); + } + + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); + return -1; + } + + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); + return -1; + } + + talloc_free(fb); + talloc_free(mp); + + return ret; +} + + +/* + modify a record +*/ +static int map_modify(struct ldb_module *module, const struct ldb_message *msg) +{ + struct ldb_map_context *privdat = map_get_privdat(module); + struct ldb_message *fb, *mp; + int ret; + + if (!map_is_mappable(privdat, msg)) + return ldb_next_modify_record(module, msg); + + + if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) + return -1; + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + + ret = ldb_next_modify_record(module, fb); + + ret = ldb_modify(privdat->mapped_ldb, mp); + + talloc_free(fb); + talloc_free(mp); + + return ret; +} + +static int map_lock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_lock(module, lockname); +} + +static int map_unlock(struct ldb_module *module, const char *lockname) +{ + return ldb_next_named_unlock(module, lockname); +} + +/* + return extended error information +*/ +static const char *map_errstring(struct ldb_module *module) +{ + struct map_private *map = module->private_data; + + if (map->last_err_string) + return map->last_err_string; + + return ldb_next_errstring(module); +} + +static const struct ldb_module_ops map_ops = { + .name = "map", + .search = map_search, + .search_bytree = map_search_bytree, + .add_record = map_add, + .modify_record = map_modify, + .delete_record = map_delete, + .rename_record = map_rename, + .named_lock = map_lock, + .named_unlock = map_unlock, + .errstring = map_errstring +}; + +static char *map_find_url(struct ldb_context *ldb, const char *name) +{ + const char * const attrs[] = { "@MAP_URL" , NULL}; + struct ldb_message **msg = NULL; + struct ldb_dn *mods; + char *url; + int ret; + + mods = ldb_dn_string_compose(ldb, NULL, "@MAP=%s", name); + if (mods == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Can't construct DN"); + return NULL; + } + + ret = ldb_search(ldb, mods, LDB_SCOPE_BASE, "", attrs, &msg); + talloc_free(mods); + if (ret < 1) { + ldb_debug(ldb, LDB_DEBUG_ERROR, "Not enough results found looking for @MAP"); + return NULL; + } + + url = talloc_strdup(ldb, ldb_msg_find_string(msg[0], "@MAP_URL", NULL)); + + talloc_free(msg); + + return url; +} + +/* the init function */ +struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char *name) +{ + int i, j; + struct ldb_module *ctx; + struct map_private *data; + char *url; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct map_private); + if (!data) { + talloc_free(ctx); + return NULL; + } + + data->context.mapped_ldb = ldb_init(data); + url = map_find_url(ldb, name); + + if (!url) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "@MAP=%s not set!\n", name); + return NULL; + } + + if (ldb_connect(data->context.mapped_ldb, url, 0, NULL) != 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to open mapped database for %s at '%s'\n", name, url); + return NULL; + } + + talloc_free(url); + + data->last_err_string = NULL; + + /* Get list of attribute maps */ + j = 0; + data->context.attribute_maps = NULL; + + for (i = 0; attrs[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = attrs[i]; + j++; + } + + for (i = 0; builtin_attribute_maps[i].local_name; i++) { + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + data->context.attribute_maps[j] = builtin_attribute_maps[i]; + j++; + } + + data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); + ZERO_STRUCT(data->context.attribute_maps[j].local_name); + + data->context.objectclass_maps = ocls; + ctx->private_data = data; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &map_ops; + + return ctx; +} + +static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_local_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + struct ldb_dn *dn, *newdn;; + struct ldb_val *newval; + + dn = ldb_dn_explode(ctx, (char *)val->data); + + newdn = map_remote_dn(map, ctx, dn); + + talloc_free(dn); + + newval = talloc(ctx, struct ldb_val); + newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); + newval->length = strlen((char *)newval->data); + + talloc_free(newdn); + + return *newval; +} + +static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].local_name; i++) { + if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].remote_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + return ldb_val_dup(ctx, val); +} + +static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +{ + int i; + + for (i = 0; map->objectclass_maps[i].remote_name; i++) { + if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { + struct ldb_val newval; + newval.data = (uint8_t*)talloc_strdup(ctx, map->objectclass_maps[i].local_name); + newval.length = strlen((char *)newval.data); + + return ldb_val_dup(ctx, &newval); + } + } + + return ldb_val_dup(ctx, val); +} + +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = MAP_CONVERT, + .u.convert.remote_name = "dn", + .u.convert.convert_local = map_convert_local_dn, + .u.convert.convert_remote = map_convert_remote_dn, + }, + { + .local_name = "objectclass", + .type = MAP_CONVERT, + .u.convert.remote_name = "objectclass", + .u.convert.convert_local = map_convert_local_objectclass, + .u.convert.convert_remote = map_convert_remote_objectclass, + }, + { + .local_name = NULL, + } +}; + diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h new file mode 100644 index 0000000000..02fec649c6 --- /dev/null +++ b/source4/lib/ldb/modules/ldb_map.h @@ -0,0 +1,108 @@ +/* + ldb database library - map backend + + Copyright (C) Jelmer Vernooij 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LDB_MAP_H__ +#define __LDB_MAP_H__ + +/* ldb_map is a skeleton LDB module that can be used for any other modules + * that need to map attributes. + * + * The term 'remote' in this header refers to the connection where the + * original schema is used on while 'local' means the local connection + * that any upper layers will use. + * + * All local attributes will have to have a definition. Not all remote + * attributes need a definition as LDB is a lot less stricter then LDAP + * (in other words, sending unknown attributes to an LDAP server hurts us, + * returning too much attributes in ldb_search() doesn't) + */ + +struct ldb_map_context; + +struct ldb_map_attribute +{ + const char *local_name; /* local name */ + + enum ldb_map_attr_type { + MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ + MAP_KEEP, /* Keep as is. Same name locally and remotely. */ + MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ + MAP_CONVERT, /* Rename + convert data */ + MAP_GENERATE /* Use generate function for generating new name/data. + Used for generating attributes based on + multiple remote attributes. */ + } type; + + /* if set, will be called for expressions that contain this attribute */ + struct ldb_parse_tree *(*convert_operator) (struct ldb_map_context *, TALLOC_CTX *ctx, const struct ldb_parse_tree *); + + union { + struct { + const char *remote_name; + } rename; + + struct { + const char *remote_name; + struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + } convert; + + struct { + /* Generate the local attribute from remote message */ + struct ldb_message_element *(*generate_local) ( + struct ldb_map_context *, + TALLOC_CTX *ctx, + const char *attr, + const struct ldb_message *remote); + + /* Update remote message with information from local message */ + void (*generate_remote) ( + struct ldb_map_context *, + const char *local_attr, + const struct ldb_message *local, + struct ldb_message *remote); + + /* Name(s) for this attribute on the remote server. This is an array since + * one local attribute's data can be split up into several attributes + * remotely */ +#define LDB_MAP_MAX_REMOTE_NAMES 10 + const char *remote_names[LDB_MAP_MAX_REMOTE_NAMES]; + } generate; + } u; +}; + +struct ldb_map_objectclass +{ + const char *local_name; + const char *remote_name; +}; + +struct ldb_map_context +{ + struct ldb_map_attribute *attribute_maps; + const struct ldb_map_objectclass *objectclass_maps; + struct ldb_context *mapped_ldb; +}; + +#endif /* __LDB_MAP_H__ */ diff --git a/source4/lib/ldb/samba/samba3sam.c b/source4/lib/ldb/samba/samba3sam.c deleted file mode 100644 index f7d83ced8f..0000000000 --- a/source4/lib/ldb/samba/samba3sam.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - ldb database library - Samba3 SAM compatibility backend - - Copyright (C) Jelmer Vernooij 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "includes.h" -#include "ldb/ldb_map/ldb_map.h" -#include "ldb/include/ldb.h" -#include "ldb/include/ldb_private.h" - -/* FIXME: - * sambaSID -> member (dn!) - * sambaSIDList -> member (dn!) - * sambaDomainName -> name - * sambaTrustPassword - * sambaUnixIdPool - * sambaIdmapEntry - * sambaAccountPolicy - * sambaSidEntry - * sambaAcctFlags -> systemFlags ? - * sambaPasswordHistory -> ntPwdHistory*/ - -/* Not necessary: - * sambaConfig - * sambaShare - * sambaConfigOption - * sambaNextGroupRid - * sambaNextUserRid - * sambaAlgorithmicRidBase - */ - -/* Not in Samba4: - * sambaKickoffTime - * sambaPwdCanChange - * sambaPwdMustChange - * sambaHomePath - * sambaHomeDrive - * sambaLogonScript - * sambaProfilePath - * sambaUserWorkstations - * sambaMungedDial - * sambaLogonHours */ - -/* In Samba4 but not in Samba3: -*/ - -static struct ldb_val convert_sid_rid(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - printf("Converting SID TO RID *\n"); - - return ldb_val_dup(ctx, val); -} - -static struct ldb_val convert_rid_sid(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - printf("Converting RID TO SID *\n"); - - return ldb_val_dup(ctx, val); -} - -static struct ldb_val convert_unix_id2name(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - printf("Converting UNIX ID to name\n"); - - return ldb_val_dup(ctx, val); -} - -static struct ldb_val convert_unix_name2id(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) -{ - printf("Converting UNIX name to ID\n"); - - return ldb_val_dup(ctx, val); -} - -const struct ldb_map_objectclass samba3_objectclasses[] = { - { "group", "sambaGroupMapping" }, - { "user", "sambaSAMAccount" }, - { "domain", "sambaDomain" }, - { NULL, NULL } -}; - -const struct ldb_map_attribute samba3_attributes[] = -{ - /* sambaNextRid -> nextRid */ - { - .local_name = "nextRid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNextRid", - }, - - /* sambaBadPasswordTime -> badPasswordtime*/ - { - .local_name = "badPasswordTime", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordTime", - }, - - /* sambaLMPassword -> lmPwdHash*/ - { - .local_name = "lmPwdHash", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLMPassword", - }, - - /* sambaGroupType -> groupType */ - { - .local_name = "groupType", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaGroupType", - }, - - /* sambaNTPassword -> ntPwdHash*/ - { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaNTPassword", - }, - - /* sambaPrimaryGroupSID -> primaryGroupID */ - { - .local_name = "primaryGroupID", - .type = MAP_CONVERT, - .u.convert.remote_name = "sambaPrimaryGroupSID", - .u.convert.convert_local = convert_rid_sid, - .u.convert.convert_remote = convert_sid_rid, - }, - - /* sambaBadPasswordCount -> badPwdCount */ - { - .local_name = "badPwdCount", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaBadPasswordCount", - }, - - /* sambaLogonTime -> lastLogon*/ - { - .local_name = "lastLogon", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogonTime", - }, - - /* sambaLogoffTime -> lastLogoff*/ - { - .local_name = "lastLogoff", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaLogoffTime", - }, - - /* gidNumber -> unixName */ - { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "gidNumber", - .u.convert.convert_local = convert_unix_name2id, - .u.convert.convert_remote = convert_unix_id2name, - }, - - /* uid -> unixName */ - { - .local_name = "unixName", - .type = MAP_CONVERT, - .u.convert.remote_name = "uid", - .u.convert.convert_local = convert_unix_name2id, - .u.convert.convert_remote = convert_unix_id2name, - }, - - /* displayName -> name */ - { - .local_name = "name", - .type = MAP_RENAME, - .u.rename.remote_name = "displayName", - }, - - /* cn */ - { - .local_name = "cn", - .type = MAP_KEEP, - }, - - /* sAMAccountName -> cn */ - { - .local_name = "sAMAccountName", - .type = MAP_RENAME, - .u.rename.remote_name = "uid", - }, - - /* objectCategory */ - { - .local_name = "objectCategory", - .type = MAP_IGNORE, - }, - - /* objectGUID */ - { - .local_name = "objectGUID", - .type = MAP_IGNORE, - }, - - /* objectVersion */ - { - .local_name = "objectVersion", - .type = MAP_IGNORE, - }, - - /* codePage */ - { - .local_name = "codePage", - .type = MAP_IGNORE, - }, - - /* dNSHostName */ - { - .local_name = "dNSHostName", - .type = MAP_IGNORE, - }, - - - /* dnsDomain */ - { - .local_name = "dnsDomain", - .type = MAP_IGNORE, - }, - - /* dnsRoot */ - { - .local_name = "dnsRoot", - .type = MAP_IGNORE, - }, - - /* countryCode */ - { - .local_name = "countryCode", - .type = MAP_IGNORE, - }, - - /* nTMixedDomain */ - { - .local_name = "nTMixedDomain", - .type = MAP_IGNORE, - }, - - /* operatingSystem */ - { - .local_name = "operatingSystem", - .type = MAP_IGNORE, - }, - - /* operatingSystemVersion */ - { - .local_name = "operatingSystemVersion", - .type = MAP_IGNORE, - }, - - - /* servicePrincipalName */ - { - .local_name = "servicePrincipalName", - .type = MAP_IGNORE, - }, - - /* msDS-Behavior-Version */ - { - .local_name = "msDS-Behavior-Version", - .type = MAP_IGNORE, - }, - - /* msDS-KeyVersionNumber */ - { - .local_name = "msDS-KeyVersionNumber", - .type = MAP_IGNORE, - }, - - /* msDs-masteredBy */ - { - .local_name = "msDs-masteredBy", - .type = MAP_IGNORE, - }, - - /* ou */ - { - .local_name = "ou", - .type = MAP_KEEP, - }, - - /* dc */ - { - .local_name = "dc", - .type = MAP_KEEP, - }, - - /* description */ - { - .local_name = "description", - .type = MAP_KEEP, - }, - - /* sambaSID -> objectSid*/ - { - .local_name = "objectSid", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaSID", - }, - - /* sambaPwdLastSet -> pwdLastSet */ - { - .local_name = "pwdLastSet", - .type = MAP_RENAME, - .u.rename.remote_name = "sambaPwdLastSet", - }, - - /* accountExpires */ - { - .local_name = "accountExpires", - .type = MAP_IGNORE, - }, - - /* adminCount */ - { - .local_name = "adminCount", - .type = MAP_IGNORE, - }, - - /* canonicalName */ - { - .local_name = "canonicalName", - .type = MAP_IGNORE, - }, - - /* createTimestamp */ - { - .local_name = "createTimestamp", - .type = MAP_IGNORE, - }, - - /* creationTime */ - { - .local_name = "creationTime", - .type = MAP_IGNORE, - }, - - /* dMDLocation */ - { - .local_name = "dMDLocation", - .type = MAP_IGNORE, - }, - - /* fSMORoleOwner */ - { - .local_name = "fSMORoleOwner", - .type = MAP_IGNORE, - }, - - /* forceLogoff */ - { - .local_name = "forceLogoff", - .type = MAP_IGNORE, - }, - - /* instanceType */ - { - .local_name = "instanceType", - .type = MAP_IGNORE, - }, - - /* invocationId */ - { - .local_name = "invocationId", - .type = MAP_IGNORE, - }, - - /* isCriticalSystemObject */ - { - .local_name = "isCriticalSystemObject", - .type = MAP_IGNORE, - }, - - /* localPolicyFlags */ - { - .local_name = "localPolicyFlags", - .type = MAP_IGNORE, - }, - - /* lockOutObservationWindow */ - { - .local_name = "lockOutObservationWindow", - .type = MAP_IGNORE, - }, - - /* lockoutDuration */ - { - .local_name = "lockoutDuration", - .type = MAP_IGNORE, - }, - - /* lockoutThreshold */ - { - .local_name = "lockoutThreshold", - .type = MAP_IGNORE, - }, - - /* logonCount */ - { - .local_name = "logonCount", - .type = MAP_IGNORE, - }, - - /* masteredBy */ - { - .local_name = "masteredBy", - .type = MAP_IGNORE, - }, - - /* maxPwdAge */ - { - .local_name = "maxPwdAge", - .type = MAP_IGNORE, - }, - - /* member */ - { - .local_name = "member", - .type = MAP_IGNORE, - }, - - /* memberOf */ - { - .local_name = "memberOf", - .type = MAP_IGNORE, - }, - - /* minPwdAge */ - { - .local_name = "minPwdAge", - .type = MAP_IGNORE, - }, - - /* minPwdLength */ - { - .local_name = "minPwdLength", - .type = MAP_IGNORE, - }, - - /* modifiedCount */ - { - .local_name = "modifiedCount", - .type = MAP_IGNORE, - }, - - /* modifiedCountAtLastProm */ - { - .local_name = "modifiedCountAtLastProm", - .type = MAP_IGNORE, - }, - - /* modifyTimestamp */ - { - .local_name = "modifyTimestamp", - .type = MAP_IGNORE, - }, - - /* nCName */ - { - .local_name = "nCName", - .type = MAP_IGNORE, - }, - - /* nETBIOSName */ - { - .local_name = "nETBIOSName", - .type = MAP_IGNORE, - }, - - /* oEMInformation */ - { - .local_name = "oEMInformation", - .type = MAP_IGNORE, - }, - - /* privilege */ - { - .local_name = "privilege", - .type = MAP_IGNORE, - }, - - /* pwdHistoryLength */ - { - .local_name = "pwdHistoryLength", - .type = MAP_IGNORE, - }, - - /* pwdProperties */ - { - .local_name = "pwdProperties", - .type = MAP_IGNORE, - }, - - /* rIDAvailablePool */ - { - .local_name = "rIDAvailablePool", - .type = MAP_IGNORE, - }, - - /* revision */ - { - .local_name = "revision", - .type = MAP_IGNORE, - }, - - /* ridManagerReference */ - { - .local_name = "ridManagerReference", - .type = MAP_IGNORE, - }, - - /* sAMAccountType */ - { - .local_name = "sAMAccountType", - .type = MAP_IGNORE, - }, - - /* sPNMappings */ - { - .local_name = "sPNMappings", - .type = MAP_IGNORE, - }, - - /* serverReference */ - { - .local_name = "serverReference", - .type = MAP_IGNORE, - }, - - /* serverState */ - { - .local_name = "serverState", - .type = MAP_IGNORE, - }, - - /* showInAdvancedViewOnly */ - { - .local_name = "showInAdvancedViewOnly", - .type = MAP_IGNORE, - }, - - /* subRefs */ - { - .local_name = "subRefs", - .type = MAP_IGNORE, - }, - - /* systemFlags */ - { - .local_name = "systemFlags", - .type = MAP_IGNORE, - }, - - /* uASCompat */ - { - .local_name = "uASCompat", - .type = MAP_IGNORE, - }, - - /* uSNChanged */ - { - .local_name = "uSNChanged", - .type = MAP_IGNORE, - }, - - /* uSNCreated */ - { - .local_name = "uSNCreated", - .type = MAP_IGNORE, - }, - - /* unicodePwd */ - { - .local_name = "unicodePwd", - .type = MAP_IGNORE, - }, - - /* userAccountControl */ - { - .local_name = "userAccountControl", - .type = MAP_IGNORE, - }, - - /* whenChanged */ - { - .local_name = "whenChanged", - .type = MAP_IGNORE, - }, - - /* whenCreated */ - { - .local_name = "whenCreated", - .type = MAP_IGNORE, - }, - - { - .local_name = NULL, - } -}; - - /* the init function */ -#ifdef HAVE_DLOPEN_DISABLED -struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) -#else -struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[]) -#endif -{ - return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, "samba3sam"); -} diff --git a/source4/lib/ldb/tests/samba3.ldif b/source4/lib/ldb/tests/samba3.ldif deleted file mode 100644 index 035eb1c516..0000000000 --- a/source4/lib/ldb/tests/samba3.ldif +++ /dev/null @@ -1,200 +0,0 @@ -dn: ou=Users,ou=Tests,dc=vernstok,dc=nl -objectClass: organizationalUnit -ou: Users - -dn: ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: organizationalUnit -ou: Groups - -dn: uid=nobody,ou=Users,ou=Tests,dc=vernstok,dc=nl -cn: nobody -sn: nobody -objectClass: inetOrgPerson -objectClass: sambaSAMAccount -objectClass: posixAccount -objectClass: shadowAccount -gidNumber: 514 -uid: nobody -uidNumber: 999 -homeDirectory: /dev/null -sambaPwdLastSet: 0 -sambaLogonTime: 0 -sambaLogoffTime: 2147483647 -sambaKickoffTime: 2147483647 -sambaPwdCanChange: 0 -sambaPwdMustChange: 2147483647 -sambaHomePath: \\PDC-SMB3\home\%U -sambaHomeDrive: H: -sambaProfilePath: \\PDC-SMB3\profiles\%U\nobody -sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-514 -sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX -sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX -sambaAcctFlags: [NU ] -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2998 -loginShell: /bin/false - -dn: cn=Domain Admins,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 512 -cn: Domain Admins -memberUid: Administrator -description: Netbios Domain Administrators -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-512 -sambaGroupType: 2 -displayName: Domain Admins - -dn: cn=Domain Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 513 -cn: Domain Users -description: Netbios Domain Users -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-513 -sambaGroupType: 2 -displayName: Domain Users - -dn: cn=Domain Guests,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 514 -cn: Domain Guests -description: Netbios Domain Guests Users -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-514 -sambaGroupType: 2 -displayName: Domain Guests - -dn: cn=Print Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 550 -cn: Print Operators -description: Netbios Domain Print Operators -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-550 -sambaGroupType: 2 -displayName: Print Operators - -dn: cn=Backup Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 551 -cn: Backup Operators -description: Netbios Domain Members can bypass file security to back up files -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-551 -sambaGroupType: 2 -displayName: Backup Operators - -dn: cn=Replicator,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 552 -cn: Replicator -description: Netbios Domain Supports file replication in a sambaDomainName -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 -sambaGroupType: 2 -displayName: Replicator - -dn: cn=Domain Computers,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 553 -cn: Domain Computers -description: Netbios Domain Computers accounts -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-553 -sambaGroupType: 2 -displayName: Domain Computers - -dn: cn=Administrators,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 544 -cn: Administrators -description: Netbios Domain Members can fully administer the computer/sambaDomainName -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-544 -sambaGroupType: 2 -displayName: Administrators - -dn: cn=Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 545 -cn: Users -description: Netbios Domain Ordinary users -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-545 -sambaGroupType: 2 -displayName: users - -dn: cn=Guests,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 546 -cn: Guests -memberUid: nobody -description: Netbios Domain Users granted guest access to the computer/sambaDomainName -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-546 -sambaGroupType: 2 -displayName: Guests - -dn: cn=Power Users,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 547 -cn: Power Users -description: Netbios Domain Members can share directories and printers -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-547 -sambaGroupType: 2 -displayName: Power Users - -dn: cn=Account Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 548 -cn: Account Operators -description: Netbios Domain Users to manipulate users accounts -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-548 -sambaGroupType: 2 -displayName: Account Operators - -dn: cn=Server Operators,ou=Groups,ou=Tests,dc=vernstok,dc=nl -objectClass: posixGroup -objectClass: sambaGroupMapping -gidNumber: 549 -cn: Server Operators -description: Netbios Domain Server Operators -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-549 -sambaGroupType: 2 -displayName: Server Operators - -dn: ou=Computers,ou=Tests,dc=vernstok,dc=nl -objectClass: organizationalUnit -ou: Computers - -dn: uid=Administrator,ou=Users,ou=Tests,dc=vernstok,dc=nl -cn: Administrator -sn: Administrator -objectClass: inetOrgPerson -objectClass: sambaSAMAccount -objectClass: posixAccount -objectClass: shadowAccount -gidNumber: 512 -uid: Administrator -uidNumber: 0 -homeDirectory: /home/%U -sambaPwdLastSet: 0 -sambaLogonTime: 0 -sambaLogoffTime: 2147483647 -sambaKickoffTime: 2147483647 -sambaPwdCanChange: 0 -sambaPwdMustChange: 2147483647 -sambaHomePath: \\PDC-SMB3\home\%U -sambaHomeDrive: H: -sambaProfilePath: \\PDC-SMB3\profiles\%U\Administrator -sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 -sambaLMPassword: XXX -sambaNTPassword: XXX -sambaAcctFlags: [U ] -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-2996 -loginShell: /bin/false -gecos: Netbios Domain Administrator - - diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index abc3d5d6ae..67395ca84c 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,4 +1,5 @@ TODO (SoC project): - move ini parsing stuff to seperate file param/ini.c - - test ldb_map backend (testsuite?) - parse "passdb backend" setting and parse tdbsam/passdb based on it + - test ldb_map backend (testsuite?) + - testsuite for the static upgrade -- cgit From 81e130b592d128a1dc1e9f2abf91b1e376512b88 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:37:58 +0000 Subject: r9789: Patch from Volker that fixes the build on AIX. (This used to be commit 9a1a7fb60e6531ff74e6817313548f3cee37a990) --- source4/lib/ldb/modules/ldb_map.c | 53 +++++++++++++++++++++++---------------- source4/lib/samba3/samba3.h | 2 +- 2 files changed, 33 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 531d5ccd67..c5ddcc7e13 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -50,7 +50,38 @@ - rename locally and remotely */ -static const struct ldb_map_attribute builtin_attribute_maps[]; +static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); +static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, + TALLOC_CTX *ctx, + const struct ldb_val *val); + +static const struct ldb_map_attribute builtin_attribute_maps[] = { + { + .local_name = "dn", + .type = MAP_CONVERT, + .u.convert.remote_name = "dn", + .u.convert.convert_local = map_convert_local_dn, + .u.convert.convert_remote = map_convert_remote_dn, + }, + { + .local_name = "objectclass", + .type = MAP_CONVERT, + .u.convert.remote_name = "objectclass", + .u.convert.convert_local = map_convert_local_objectclass, + .u.convert.convert_remote = map_convert_remote_objectclass, + }, + { + .local_name = NULL, + } +}; struct map_private { struct ldb_map_context context; @@ -1129,23 +1160,3 @@ static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map return ldb_val_dup(ctx, val); } -static const struct ldb_map_attribute builtin_attribute_maps[] = { - { - .local_name = "dn", - .type = MAP_CONVERT, - .u.convert.remote_name = "dn", - .u.convert.convert_local = map_convert_local_dn, - .u.convert.convert_remote = map_convert_remote_dn, - }, - { - .local_name = "objectclass", - .type = MAP_CONVERT, - .u.convert.remote_name = "objectclass", - .u.convert.convert_local = map_convert_local_objectclass, - .u.convert.convert_remote = map_convert_remote_objectclass, - }, - { - .local_name = NULL, - } -}; - diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index a41109a145..b8a9c68617 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -160,7 +160,7 @@ struct samba3_secrets struct { uint8_t hash[16]; time_t mod_time; - } hash_pw;; + } hash_pw; int sec_channel_type; } *domains; -- cgit From b75ca9aa2cf9a932547228458e0b3ad8e1053826 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Aug 2005 11:44:00 +0000 Subject: r9791: r11611@blu: tridge | 2005-08-30 21:48:22 +1000 recognise any case combination of 'localhost' as 127.0.0.1 (This used to be commit 1d8dae5167a1a08b69274fc17e6e010174420ab5) --- source4/lib/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 173d755bec..2e0503b0d9 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -341,7 +341,7 @@ uint32_t interpret_addr(const char *str) } /* recognise 'localhost' as a special name. This fixes problems with some hosts that don't have localhost in /etc/hosts */ - if (strcmp(str,"localhost") == 0) { + if (strcasecmp(str,"localhost") == 0) { str = "127.0.0.1"; } -- cgit From b674411eb46c9e45f2740a1f9bac365e9a347e9c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:55:05 +0000 Subject: r9792: Rename StrCaseCmp -> strcasecmp_m. All these years I was thinking StrCaseCmp was sys_strcasecmp, while it is in fact strcasecmp_m! (This used to be commit 200a8f6652cb2de7a8037a7a4c2a204b50aee2b1) --- source4/lib/appweb/mpr/miniMpr.h | 2 +- source4/lib/ms_fnmatch.c | 2 +- source4/lib/samba3/samba3.c | 6 +++--- source4/lib/samba3/secrets.c | 2 +- source4/lib/util_str.c | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h index 6fc4d50c31..0f668ab1d4 100644 --- a/source4/lib/appweb/mpr/miniMpr.h +++ b/source4/lib/appweb/mpr/miniMpr.h @@ -274,7 +274,7 @@ extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); extern void mprSetCtx(void *ctx); extern void *mprMemCtx(void); -#define mprStrCmpAnyCase(s1, s2) StrCaseCmp(s1, s2) +#define mprStrCmpAnyCase(s1, s2) strcasecmp_m(s1, s2) #ifdef __cplusplus } diff --git a/source4/lib/ms_fnmatch.c b/source4/lib/ms_fnmatch.c index c405d2ff30..699341bede 100644 --- a/source4/lib/ms_fnmatch.c +++ b/source4/lib/ms_fnmatch.c @@ -163,7 +163,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot if (strpbrk(pattern, "<>*?\"") == NULL) { /* this is not just an optmisation - it is essential for LANMAN1 correctness */ - return StrCaseCmp(pattern, string); + return strcasecmp_m(pattern, string); } if (protocol <= PROTOCOL_LANMAN2) { diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 4b893c585a..56a7738693 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -31,7 +31,7 @@ struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const int i; for (i = 0; i < db->secrets.domain_count; i++) { - if (!StrCaseCmp(db->secrets.domains[i].name, name)) + if (!strcasecmp_m(db->secrets.domains[i].name, name)) return &db->secrets.domains[i]; } @@ -42,7 +42,7 @@ struct samba3_share_info *samba3_find_share(struct samba3 *db, const char *name) { int i; for (i = 0; i < db->share_count; i++) { - if (!StrCaseCmp(db->shares[i].name, name)) + if (!strcasecmp_m(db->shares[i].name, name)) return &db->shares[i]; } @@ -74,7 +74,7 @@ const char *samba3_get_param(struct samba3 *samba3, const char *section, const c return NULL; for (i = 0; i < share->parameter_count; i++) { - if (!StrCaseCmp(share->parameters[i].name, param)) + if (!strcasecmp_m(share->parameters[i].name, param)) return share->parameters[i].value; } diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 43f0a2ec12..0f3cc0c581 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -66,7 +66,7 @@ static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct for (i = 0; i < db->domain_count; i++) { - if (!StrCaseCmp(db->domains[i].name, key)) + if (!strcasecmp_m(db->domains[i].name, key)) return &db->domains[i]; } diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index a0e9da4160..685cc52c65 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -80,7 +80,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) /** Case insensitive string compararison **/ -int StrCaseCmp(const char *s1, const char *s2) +int strcasecmp_m(const char *s1, const char *s2) { codepoint_t c1=0, c2=0; size_t size1, size2; @@ -122,7 +122,7 @@ BOOL strequal(const char *s1, const char *s2) if (!s1 || !s2) return(False); - return StrCaseCmp(s1,s2) == 0; + return strcasecmp_m(s1,s2) == 0; } /** @@ -477,7 +477,7 @@ BOOL in_list(const char *s, const char *list, BOOL casesensitive) if (strcmp(tok,s) == 0) return(True); } else { - if (StrCaseCmp(tok,s) == 0) + if (strcasecmp_m(tok,s) == 0) return(True); } } -- cgit From a3a7881d39d0c294d0cd2ce13203478fb889b07c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 13:58:48 +0000 Subject: r9798: Add generic functions for handling smb.conf files (the parameters don't to be pre-declared). Also doesn't use any globals, so multiple files can be loaded at once. Currently uses the prefix "param" for all functions and structures; suggestions for better ones are welcome... Remove old smb.conf-parsing code from libsamba3. (This used to be commit 414e5f7f6dc38a8fde3b61d524a664f56f9ea592) --- source4/lib/samba3/samba3.c | 95 +---------------------------------------- source4/lib/samba3/samba3.h | 11 ++--- source4/lib/samba3/share_info.c | 6 ++- source4/lib/util_strlist.c | 21 ++++++++- 4 files changed, 29 insertions(+), 104 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 56a7738693..d90d5edbfe 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -20,12 +20,6 @@ #include "includes.h" #include "lib/samba3/samba3.h" -struct smbconf_data { - TALLOC_CTX *ctx; - struct samba3 *db; - struct samba3_share_info *current_share; -}; - struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const char *name) { int i; @@ -38,93 +32,6 @@ struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const return NULL; } -struct samba3_share_info *samba3_find_share(struct samba3 *db, const char *name) -{ - int i; - for (i = 0; i < db->share_count; i++) { - if (!strcasecmp_m(db->shares[i].name, name)) - return &db->shares[i]; - } - - return NULL; -} - - -struct samba3_share_info *samba3_find_add_share(struct samba3 *db, TALLOC_CTX* ctx, const char *name) -{ - struct samba3_share_info *share = samba3_find_share(db, name); - - if (share) - return share; - - db->shares = talloc_realloc(ctx, db->shares, struct samba3_share_info, db->share_count+1); - ZERO_STRUCT(db->shares[db->share_count]); - db->shares[db->share_count].name = talloc_strdup(ctx, name); - db->share_count++; - - return &db->shares[db->share_count-1]; -} - -const char *samba3_get_param(struct samba3 *samba3, const char *section, const char *param) -{ - int i; - struct samba3_share_info *share = samba3_find_share(samba3, section); - - if (share == NULL) - return NULL; - - for (i = 0; i < share->parameter_count; i++) { - if (!strcasecmp_m(share->parameters[i].name, param)) - return share->parameters[i].value; - } - - return NULL; -} - - -static BOOL samba3_sfunc (const char *name, void *_db) -{ - struct smbconf_data *privdat = _db; - - privdat->current_share = samba3_find_add_share(privdat->db, privdat->ctx, name); - - return True; -} - -static BOOL samba3_pfunc (const char *name, const char *value, void *_db) -{ - struct smbconf_data *privdat = _db; - struct samba3_parameter *p; - - privdat->current_share->parameters = - talloc_realloc(privdat->ctx, privdat->current_share->parameters, - struct samba3_parameter, - privdat->current_share->parameter_count+1); - - p = &privdat->current_share->parameters[privdat->current_share->parameter_count]; - p->name = talloc_strdup(privdat->ctx, name); - p->value = talloc_strdup(privdat->ctx, value); - - privdat->current_share->parameter_count++; - - return True; -} - -NTSTATUS samba3_read_smbconf(const char *fn, TALLOC_CTX *ctx, struct samba3 *db) -{ - struct smbconf_data privdat; - - privdat.ctx = ctx; - privdat.db = db; - privdat.current_share = samba3_find_add_share(db, ctx, "global"); - - if (!pm_process( fn, samba3_sfunc, samba3_pfunc, &privdat )) { - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; -} - NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, struct samba3 **samba3) { struct samba3 *ret; @@ -133,7 +40,7 @@ NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, s ret = talloc_zero(ctx, struct samba3); if (smbconf) - samba3_read_smbconf(smbconf, ctx, ret); + ret->configuration = param_read(ret, smbconf); dbfile = talloc_asprintf(ctx, "%s/account_policy.tdb", libdir); samba3_read_account_policy(dbfile, ctx, &ret->policy); diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index b8a9c68617..f0f4c99513 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -23,6 +23,7 @@ #include "librpc/gen_ndr/security.h" #include "librpc/gen_ndr/samr.h" +#include "param/generic.h" struct samba3_samaccount { uint32_t logon_time, @@ -185,21 +186,15 @@ struct samba3_secrets } *afs_keyfiles; }; -struct samba3_parameter { - char *name; - char *value; -}; - struct samba3_share_info { char *name; struct security_descriptor secdesc; - - uint32_t parameter_count; - struct samba3_parameter *parameters; }; struct samba3 { + struct param_context *configuration; + uint32_t winsdb_count; struct samba3_winsdb_entry *winsdb_entries; diff --git a/source4/lib/samba3/share_info.c b/source4/lib/samba3/share_info.c index 3479a7063c..e96adfc175 100644 --- a/source4/lib/samba3/share_info.c +++ b/source4/lib/samba3/share_info.c @@ -66,7 +66,11 @@ NTSTATUS samba3_read_share_info(const char *fn, TALLOC_CTX *ctx, struct samba3 * name = talloc_strndup(ctx, kbuf.dptr+strlen("SECDESC/"), kbuf.dsize-strlen("SECDESC/")); - share = samba3_find_add_share(db, ctx, name); + db->shares = talloc_realloc(db, db->shares, struct samba3_share_info, db->share_count+1); + share = &db->shares[db->share_count]; + db->share_count++; + + share->name = talloc_strdup(db, name); vbuf = tdb_fetch(tdb, kbuf); blob.data = (uint8_t *)vbuf.dptr; diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index d5c4d91585..8efa1f92d2 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -22,7 +22,7 @@ /* build a null terminated list of strings from a input string and a - separator list. The sepatator list must contain characters less than + separator list. The separator list must contain characters less than or equal to 0x2f for this to work correctly on multi-byte strings */ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) @@ -70,6 +70,25 @@ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char * return ret; } +/* join a list back to one string */ +char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + ret = talloc_asprintf_append(ret, "%c%s", seperator, list[i]); + } + + return ret; +} + + /* return the number of elements in a string list */ -- cgit From 9f4b32996c1c97122b198a13216c35ad40f6ea2d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 14:44:33 +0000 Subject: r9800: Add EJS interface to param. tridge, sorry this overlaps a bit with your loadparm interface. :-/ (This used to be commit bb0cef581a09a86113f3212c776c011ae73def14) --- source4/lib/samba3/samba3.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index d90d5edbfe..b919366ce3 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -32,15 +32,17 @@ struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const return NULL; } -NTSTATUS samba3_read(const char *smbconf, const char *libdir, TALLOC_CTX *ctx, struct samba3 **samba3) +NTSTATUS samba3_read(const char *libdir, const char *smbconf, TALLOC_CTX *ctx, struct samba3 **samba3) { struct samba3 *ret; char *dbfile = NULL; ret = talloc_zero(ctx, struct samba3); - if (smbconf) - ret->configuration = param_read(ret, smbconf); + if (smbconf) { + ret->configuration = param_init(ret); + param_read(ret->configuration, smbconf); + } dbfile = talloc_asprintf(ctx, "%s/account_policy.tdb", libdir); samba3_read_account_policy(dbfile, ctx, &ret->policy); -- cgit From 10ee597a786839dfa327c166c1919c0b11977632 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 17:21:41 +0000 Subject: r9807: Use talloc in fd_lines_load() and file_lines_load(). The return value now can be freed using talloc(). I couldn't find the free_lines_list() function that was supposed to free it before. (This used to be commit f6f31661d05e392a9f2819c5a0ceff92c1b7656a) --- source4/lib/util_file.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index fdf06c47c5..1330b0a70d 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -271,7 +271,7 @@ void *map_file(char *fname, size_t size) /**************************************************************************** parse a buffer into lines ****************************************************************************/ -static char **file_lines_parse(char *p, size_t size, int *numlines) +static char **file_lines_parse(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx) { int i; char *s, **ret; @@ -282,11 +282,14 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) if (s[0] == '\n') i++; } - ret = malloc_array_p(char *, i+2); + ret = talloc_array(mem_ctx, char *, i+2); if (!ret) { - SAFE_FREE(p); + talloc_free(p); return NULL; } + + talloc_reference(ret, p); + memset(ret, 0, sizeof(ret[0])*(i+2)); if (numlines) *numlines = i; @@ -306,33 +309,43 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) /**************************************************************************** load a file into memory and return an array of pointers to lines in the file -must be freed with file_lines_free(). +must be freed with talloc_free(). ****************************************************************************/ char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx) { char *p; + char **lines; size_t size; p = file_load(fname, &size, mem_ctx); if (!p) return NULL; - return file_lines_parse(p, size, numlines); + lines = file_lines_parse(p, size, numlines, mem_ctx); + + talloc_free(p); + + return lines; } /**************************************************************************** load a fd into memory and return an array of pointers to lines in the file -must be freed with file_lines_free(). If convert is true calls unix_to_dos on +must be freed with talloc_free(). If convert is true calls unix_to_dos on the list. ****************************************************************************/ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) { char *p; + char **lines; size_t size; p = fd_load(fd, &size, mem_ctx); if (!p) return NULL; - return file_lines_parse(p, size, numlines); + lines = file_lines_parse(p, size, numlines, mem_ctx); + + talloc_free(p); + + return lines; } -- cgit From 34305d74e19e09d304db4bfe7fcd46504831feaf Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 17:23:07 +0000 Subject: r9808: Improve code that selects what "passdb backend" to import from. (This used to be commit 7739d092d5ca99bd44a1612cc783e38a2f09a67f) --- source4/lib/samba3/PLAN | 2 -- source4/lib/samba3/samba3.c | 53 +++++++++++++++++++++++++++++++++++++++--- source4/lib/samba3/smbpasswd.c | 5 ++++ 3 files changed, 55 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 67395ca84c..f6cdf1cce4 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,5 +1,3 @@ TODO (SoC project): - - move ini parsing stuff to seperate file param/ini.c - - parse "passdb backend" setting and parse tdbsam/passdb based on it - test ldb_map backend (testsuite?) - testsuite for the static upgrade diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index b919366ce3..8d5ad77185 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -32,6 +32,55 @@ struct samba3_domainsecrets *samba3_find_domainsecrets(struct samba3 *db, const return NULL; } +NTSTATUS samba3_read_passdb_backends(TALLOC_CTX *ctx, const char *libdir, struct samba3 *samba3) +{ + char *dbfile; + NTSTATUS status = NT_STATUS_OK; + int i; + const char **backends = param_get_string_list(samba3->configuration, NULL, "passdb backends", NULL); + + /* Default to smbpasswd */ + if (backends == NULL) + backends = str_list_make(ctx, "smbpasswd", LIST_SEP); + else + backends = str_list_copy(ctx, backends); + + for (i = 0; backends[i]; i++) { + if (!strncmp(backends[i], "tdbsam", strlen("tdbsam"))) { + const char *p = strchr(backends[i], ':'); + if (p && p[1]) { + dbfile = talloc_strdup(ctx, p+1); + } else { + dbfile = talloc_asprintf(ctx, "%s/passdb.tdb", libdir); + } + samba3_read_tdbsam(dbfile, ctx, &samba3->samaccounts, &samba3->samaccount_count); + talloc_free(dbfile); + } else if (!strncmp(backends[i], "smbpasswd", strlen("smbpasswd"))) { + const char *p = strchr(backends[i], ':'); + if (p && p[1]) { + dbfile = talloc_strdup(ctx, p+1); + } else if ((p = param_get_string(samba3->configuration, NULL, "smb passwd file"))) { + dbfile = talloc_strdup(ctx, p); + } else { + dbfile = talloc_strdup(ctx, "/etc/samba/smbpasswd"); + } + + samba3_read_smbpasswd(dbfile, ctx, &samba3->samaccounts, &samba3->samaccount_count); + talloc_free(dbfile); + } else if (!strncmp(backends[i], "ldapsam", strlen("ldapsam"))) { + /* Will use samba3sam mapping module */ + } else { + DEBUG(0, ("Upgrade from %s database not supported", backends[i])); + status = NT_STATUS_NOT_SUPPORTED; + continue; + } + } + + talloc_free(backends); + + return status; +} + NTSTATUS samba3_read(const char *libdir, const char *smbconf, TALLOC_CTX *ctx, struct samba3 **samba3) { struct samba3 *ret; @@ -68,9 +117,7 @@ NTSTATUS samba3_read(const char *libdir, const char *smbconf, TALLOC_CTX *ctx, s samba3_read_winsdb(dbfile, ret, &ret->winsdb_entries, &ret->winsdb_count); talloc_free(dbfile); - dbfile = talloc_asprintf(ctx, "%s/passdb.tdb", libdir); - samba3_read_tdbsam(dbfile, ctx, &ret->samaccounts, &ret->samaccount_count); - talloc_free(dbfile); + samba3_read_passdb_backends(ctx, libdir, ret); dbfile = talloc_asprintf(ctx, "%s/group_mapping.tdb", libdir); samba3_read_grouptdb(dbfile, ctx, &ret->group); diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index 5976d2db57..fe0780c8d3 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -219,6 +219,11 @@ NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct sam lines = file_lines_load(filename, &numlines, ctx); + if (lines == NULL) { + DEBUG(0, ("Unable to load lines from %s\n", filename)); + return NT_STATUS_UNSUCCESSFUL; + } + *accounts = talloc_array(ctx, struct samba3_samaccount, numlines); for (i = 0; i < numlines; i++) { -- cgit From 40f85ace04abad7460d0f0afe9211c4280482c6c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 22:38:34 +0000 Subject: r9813: Conver testsuite for samba3sam module to EJS (This used to be commit 77f24ed131bf57c30bb500e1d8d387bd4b403ddc) --- source4/lib/ldb/tests/test-samba3sam.sh | 61 --------------------------------- 1 file changed, 61 deletions(-) delete mode 100755 source4/lib/ldb/tests/test-samba3sam.sh (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/test-samba3sam.sh b/source4/lib/ldb/tests/test-samba3sam.sh deleted file mode 100755 index 5baf0bf77a..0000000000 --- a/source4/lib/ldb/tests/test-samba3sam.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh - -S3URL=$1 - -if [ -z "$S3URL" ]; -then - rm -f samba3.ldb - S3URL="tdb://samba3.ldb" - echo "Adding samba3 LDIF..." - $VALGRIND ldbadd -H tdb://samba3.ldb < samba3.ldif || exit 1 -fi - -rm -f samba4.ldb - -echo "Initial samba4 LDIF..." -$VALGRIND ldbadd -H tdb://samba4.ldb < Date: Wed, 31 Aug 2005 02:39:57 +0000 Subject: r9816: Work on testsuite for upgrade Add 'paths' object to provision code. (This used to be commit 488d737fb0ebbc2535d0ec17c14f0dc1eaf2a578) --- source4/lib/samba3/PLAN | 2 +- source4/lib/samba3/samba3.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index f6cdf1cce4..8c1a673535 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,3 +1,3 @@ TODO (SoC project): - - test ldb_map backend (testsuite?) + - finish ldb_map testsuite - testsuite for the static upgrade diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index 8d5ad77185..b9bb6d7362 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -88,9 +88,12 @@ NTSTATUS samba3_read(const char *libdir, const char *smbconf, TALLOC_CTX *ctx, s ret = talloc_zero(ctx, struct samba3); - if (smbconf) { + if (smbconf != NULL) { ret->configuration = param_init(ret); - param_read(ret->configuration, smbconf); + if (param_read(ret->configuration, smbconf) == -1) { + talloc_free(ret); + return NT_STATUS_UNSUCCESSFUL; + } } dbfile = talloc_asprintf(ctx, "%s/account_policy.tdb", libdir); -- cgit From d991196655a5102275736a32bf4861ae193a3761 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 31 Aug 2005 14:27:17 +0000 Subject: r9827: Convert 'passdb backend' rather then 'passdb backends' Be a bit more verbose (This used to be commit fb2fd8da10b281b2064d4cae5d5a0630e8a207da) --- source4/lib/samba3/samba3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/samba3.c b/source4/lib/samba3/samba3.c index b9bb6d7362..51a442722b 100644 --- a/source4/lib/samba3/samba3.c +++ b/source4/lib/samba3/samba3.c @@ -37,7 +37,7 @@ NTSTATUS samba3_read_passdb_backends(TALLOC_CTX *ctx, const char *libdir, struct char *dbfile; NTSTATUS status = NT_STATUS_OK; int i; - const char **backends = param_get_string_list(samba3->configuration, NULL, "passdb backends", NULL); + const char **backends = param_get_string_list(samba3->configuration, NULL, "passdb backend", NULL); /* Default to smbpasswd */ if (backends == NULL) @@ -45,6 +45,7 @@ NTSTATUS samba3_read_passdb_backends(TALLOC_CTX *ctx, const char *libdir, struct else backends = str_list_copy(ctx, backends); + for (i = 0; backends[i]; i++) { if (!strncmp(backends[i], "tdbsam", strlen("tdbsam"))) { const char *p = strchr(backends[i], ':'); -- cgit From 84bfcd3c78afefd8d2869c695c116c9df7ee03c4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 31 Aug 2005 18:33:57 +0000 Subject: r9835: Make ldb_map compile in the stand-alone LDB build (This used to be commit 2283a336e0e31e6857621d9806bba54c400bd986) --- source4/lib/ldb/Makefile.in | 3 +- source4/lib/ldb/modules/ldb_map.c | 81 ++++++++++++++++++++------------------- source4/lib/ldb/modules/ldb_map.h | 8 ++-- source4/lib/samba3/PLAN | 1 - 4 files changed, 48 insertions(+), 45 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index 0b7c8c2c14..cb1ecae3e7 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -55,7 +55,8 @@ COMMON_OBJ=common/ldb.o common/ldb_ldif.o \ common/ldb_dn.o common/ldb_match.o common/ldb_attributes.o \ common/attrib_handlers.o -MODULES_OBJ=modules/timestamps.o modules/schema.o modules/rdn_name.o +MODULES_OBJ=modules/timestamps.o modules/schema.o modules/rdn_name.o \ + modules/ldb_map.o OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LDAP_OBJ) $(LDB_SQLITE3_OBJ) diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index c5ddcc7e13..f40506c03b 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -23,9 +23,9 @@ */ #include "includes.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_private.h" -#include "lib/ldb/modules/ldb_map.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include "ldb/modules/ldb_map.h" /* TODO: * - objectclass hint in ldb_map_attribute @@ -50,16 +50,16 @@ - rename locally and remotely */ -static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, +static struct ldb_val map_convert_local_dn(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, +static struct ldb_val map_convert_remote_dn(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, +static struct ldb_val map_convert_local_objectclass(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); -static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, +static struct ldb_val map_convert_remote_objectclass(struct ldb_module *map, TALLOC_CTX *ctx, const struct ldb_val *val); @@ -106,22 +106,22 @@ static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_m /* Decide whether a add/modify should be pushed to the * remote LDAP server. We currently only do this if we see an objectClass we know */ -static BOOL map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) { int i; struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); /* No objectClass... */ if (el == NULL) { - return False; + return 0; } for (i = 0; i < el->num_values; i++) { if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) - return True; + return 1; } - return False; + return 0; } /* find an attribute by the local name */ @@ -269,7 +269,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_CONVERT) { - newvalue = attr->u.convert.convert_local(privdat, new_tree, &value); + newvalue = attr->u.convert.convert_local(module, new_tree, &value); } else { newvalue = ldb_val_dup(new_tree, &value); } @@ -288,7 +288,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } /* Remote DN -> Local DN */ -static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +static struct ldb_dn *map_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn) { struct ldb_dn *newdn; int i; @@ -309,7 +309,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX * complete rdn */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_remote(privdat, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_remote(module->private_data, dn->components[i].name); enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ @@ -319,7 +319,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX switch (map_type) { case MAP_IGNORE: case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE or MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name); talloc_free(newdn); return NULL; @@ -330,7 +330,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->local_name); - newdn->components[i].value = attr->u.convert.convert_remote(privdat, ctx, &dn->components[i].value); + newdn->components[i].value = attr->u.convert.convert_remote(module, ctx, &dn->components[i].value); break; case MAP_RENAME: @@ -343,7 +343,7 @@ static struct ldb_dn *map_remote_dn(struct ldb_map_context *privdat, TALLOC_CTX } /* Local DN -> Remote DN */ -static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX *ctx, const struct ldb_dn *dn) +static struct ldb_dn *map_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_dn *dn) { struct ldb_dn *newdn; int i; @@ -364,7 +364,7 @@ static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX * * complete rdn using an equality convert_operator call */ for (i = 0; i < dn->comp_num; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, dn->components[i].name); + const struct ldb_map_attribute *attr = map_find_attr_local(module->private_data, dn->components[i].name); enum ldb_map_attr_type map_type; /* Unknown attribute - leave this dn as is and hope the best... */ @@ -374,13 +374,13 @@ static struct ldb_dn *map_local_dn(struct ldb_map_context *privdat, TALLOC_CTX * { case MAP_IGNORE: case MAP_GENERATE: - DEBUG(0, ("Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name)); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Local MAP_IGNORE/MAP_GENERATE attribute '%s' used in DN!", dn->components[i].name); talloc_free(newdn); return NULL; case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); - newdn->components[i].value = attr->u.convert.convert_local(privdat, newdn->components, &dn->components[i].value); + newdn->components[i].value = attr->u.convert.convert_local(module, newdn->components, &dn->components[i].value); break; case MAP_RENAME: @@ -482,7 +482,7 @@ static const char **available_local_attributes(struct ldb_module *module, const ret[0] = NULL; for (i = 0; privdat->attribute_maps[i].local_name; i++) { - BOOL avail = False; + int avail = 0; const struct ldb_map_attribute *attr = &privdat->attribute_maps[i]; /* If all remote attributes for this attribute are present, add the @@ -500,7 +500,7 @@ static const char **available_local_attributes(struct ldb_module *module, const break; case MAP_GENERATE: - avail = True; + avail = 1; for (j = 0; attr->u.generate.remote_names[j]; j++) { avail &= (ldb_msg_find_ldb_val(msg, attr->u.generate.remote_names[j]) != NULL); } @@ -528,7 +528,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c struct ldb_map_context *privdat = map_get_privdat(module); const char **newattrs = NULL; - msg->dn = map_remote_dn(privdat, module, mi->dn); + msg->dn = map_remote_dn(module, module, mi->dn); ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); @@ -575,7 +575,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < oldelm->num_values; j++) - elm->values[j] = attr->u.convert.convert_remote(privdat, elm, &oldelm->values[j]); + elm->values[j] = attr->u.convert.convert_remote(module, elm, &oldelm->values[j]); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; @@ -594,7 +594,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c break; case MAP_GENERATE: - elm = attr->u.generate.generate_local(privdat, msg, attr->local_name, mi); + elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); if (!elm) continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); @@ -625,7 +625,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ msg->private_data = mo->private_data; - msg->dn = map_local_dn(privdat, module, mo->dn); + msg->dn = map_local_dn(module, module, mo->dn); /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < mo->num_elements; i++) { @@ -666,7 +666,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(privdat, msg, &mo->elements[i].values[j]); + elm->values[j] = attr->u.convert.convert_local(module, msg, &mo->elements[i].values[j]); } ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); @@ -683,7 +683,7 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ break; case MAP_GENERATE: - attr->u.generate.generate_remote(privdat, attr->local_name, mo, msg); + attr->u.generate.generate_remote(module, attr->local_name, mo, msg); break; } } @@ -703,8 +703,8 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con ret = ldb_next_rename_record(module, olddn, newdn); - n_olddn = map_local_dn(privdat, module, olddn); - n_newdn = map_local_dn(privdat, module, newdn); + n_olddn = map_local_dn(module, module, olddn); + n_newdn = map_local_dn(module, module, newdn); ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); @@ -725,7 +725,7 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) ret = ldb_next_delete_record(module, dn); - newdn = map_local_dn(privdat, module, dn); + newdn = map_local_dn(module, module, dn); ret = ldb_delete(privdat->mapped_ldb, newdn); @@ -777,7 +777,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * new_tree = ldb_map_parse_tree(module, module, tree); newattrs = ldb_map_attrs(module, attrs); - new_base = map_local_dn(privdat, module, base); + new_base = map_local_dn(module, module, base); mpret = ldb_search_bytree(privdat->mapped_ldb, new_base, scope, new_tree, newattrs, &newres); @@ -1042,6 +1042,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at } data->context.mapped_ldb = ldb_init(data); + ldb_set_debug(data->context.mapped_ldb, ldb->debug_ops.debug, ldb->debug_ops.context); url = map_find_url(ldb, name); if (!url) { @@ -1075,7 +1076,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at } data->context.attribute_maps = talloc_realloc(data, data->context.attribute_maps, struct ldb_map_attribute, j+1); - ZERO_STRUCT(data->context.attribute_maps[j].local_name); + memset(&data->context.attribute_maps[j], 0, sizeof(struct ldb_map_attribute)); data->context.objectclass_maps = ocls; ctx->private_data = data; @@ -1086,14 +1087,14 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at return ctx; } -static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { struct ldb_dn *dn, *newdn;; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); - newdn = map_local_dn(map, ctx, dn); + newdn = map_local_dn(module, ctx, dn); talloc_free(dn); @@ -1106,14 +1107,14 @@ static struct ldb_val map_convert_local_dn(struct ldb_map_context *map, TALLOC_C return *newval; } -static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { struct ldb_dn *dn, *newdn;; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); - newdn = map_remote_dn(map, ctx, dn); + newdn = map_remote_dn(module, ctx, dn); talloc_free(dn); @@ -1126,9 +1127,10 @@ static struct ldb_val map_convert_remote_dn(struct ldb_map_context *map, TALLOC_ return *newval; } -static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_local_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { int i; + struct ldb_map_context *map = module->private_data; for (i = 0; map->objectclass_maps[i].local_name; i++) { if (!strcmp(map->objectclass_maps[i].local_name, (char *)val->data)) { @@ -1143,9 +1145,10 @@ static struct ldb_val map_convert_local_objectclass(struct ldb_map_context *map, return ldb_val_dup(ctx, val); } -static struct ldb_val map_convert_remote_objectclass(struct ldb_map_context *map, TALLOC_CTX *ctx, const struct ldb_val *val) +static struct ldb_val map_convert_remote_objectclass(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { int i; + struct ldb_map_context *map = module->private_data; for (i = 0; map->objectclass_maps[i].remote_name; i++) { if (!strcmp(map->objectclass_maps[i].remote_name, (char *)val->data)) { diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 02fec649c6..4077660160 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -64,21 +64,21 @@ struct ldb_map_attribute struct { const char *remote_name; - struct ldb_val (*convert_local) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); - struct ldb_val (*convert_remote) (struct ldb_map_context *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_local) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); + struct ldb_val (*convert_remote) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); } convert; struct { /* Generate the local attribute from remote message */ struct ldb_message_element *(*generate_local) ( - struct ldb_map_context *, + struct ldb_module *, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote); /* Update remote message with information from local message */ void (*generate_remote) ( - struct ldb_map_context *, + struct ldb_module *, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote); diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 8c1a673535..47b5edd408 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,3 +1,2 @@ TODO (SoC project): - finish ldb_map testsuite - - testsuite for the static upgrade -- cgit From 222fdd5237c1fd8551c39ce544171df3a5a41831 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 31 Aug 2005 21:04:17 +0000 Subject: r9842: More error checks in the ldb_map modules, extend testsuite (This used to be commit b7992de4b7d42a55e00509c887a269a07c19627d) --- source4/lib/ldb/modules/ldb_map.c | 143 ++++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 44 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index f40506c03b..513e065f2e 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -109,7 +109,12 @@ static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_m static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) { int i; - struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + struct ldb_message_element *el; + + if (ldb_dn_is_special(msg->dn)) + return 0; + + el = ldb_msg_find_element(msg, "objectClass"); /* No objectClass... */ if (el == NULL) { @@ -222,8 +227,8 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL attr = map_find_attr_local(privdat, tree->u.equality.attr); if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to find local attribute '%s', leaving as is\n", tree->u.equality.attr); - map_type = MAP_KEEP; + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Unable to find local attribute '%s', removing from parse tree\n", tree->u.equality.attr); + map_type = MAP_IGNORE; } else { map_type = attr->type; } @@ -234,7 +239,7 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_IGNORE) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Search on ignored attribute '%s'\n", tree->u.equality.attr); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Not mapping search on ignored attribute '%s'\n", tree->u.equality.attr); return NULL; } @@ -554,20 +559,26 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c switch (map_type) { case MAP_IGNORE:break; case MAP_RENAME: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Renaming remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name); oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; + if (!oldelm) + continue; elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_CONVERT: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting remote attribute %s to %s", attr->u.rename.remote_name, attr->local_name); oldelm = ldb_msg_find_element(mi, attr->u.rename.remote_name); - if (!oldelm) continue; + if (!oldelm) + continue; elm = talloc(msg, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->local_name); @@ -581,19 +592,24 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c break; case MAP_KEEP: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping remote attribute %s", attr->local_name); oldelm = ldb_msg_find_element(mi, attr->local_name); if (!oldelm) continue; elm = talloc(msg, struct ldb_message_element); elm->num_values = oldelm->num_values; - elm->values = talloc_reference(elm, oldelm->values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < oldelm->num_values; j++) + elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); + elm->name = talloc_strdup(elm, oldelm->name); ldb_msg_add(module->ldb, msg, elm, oldelm->flags); break; case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating local attribute %s", attr->local_name); elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); if (!elm) continue; @@ -614,18 +630,14 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) { struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message *msg = talloc_zero(module, struct ldb_message); struct ldb_message_element *elm; int i,j; *fb = talloc_zero(module, struct ldb_message); (*fb)->dn = talloc_reference(*fb, mo->dn); - *mp = msg; - - msg->private_data = mo->private_data; - - msg->dn = map_local_dn(module, module, mo->dn); + *mp = talloc_zero(module, struct ldb_message); + (*mp)->dn = map_local_dn(module, module, mo->dn); /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < mo->num_elements; i++) { @@ -649,45 +661,59 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); break; case MAP_RENAME: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = mo->elements[i].num_values; elm->values = talloc_reference(elm, mo->elements[i].values); - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_CONVERT: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = mo->elements[i].num_values; elm->values = talloc_array(elm, struct ldb_val, elm->num_values); for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, msg, &mo->elements[i].values[j]); + elm->values[j] = attr->u.convert.convert_local(module, *mp, &mo->elements[i].values[j]); } - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_KEEP: - elm = talloc(msg, struct ldb_message_element); + elm = talloc(*mp, struct ldb_message_element); elm->num_values = mo->elements[i].num_values; elm->values = talloc_reference(elm, mo->elements[i].values); elm->name = talloc_strdup(elm, mo->elements[i].name); - ldb_msg_add(module->ldb, msg, elm, mo->elements[i].flags); + ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); break; case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, mo, msg); + attr->u.generate.generate_remote(module, attr->local_name, mo, *mp); break; } } + if ((*fb)->num_elements == 0) { + /* No elements, discard.. */ + talloc_free(*fb); + *fb = NULL; + } else { + ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); + } + + if ((*mp)->num_elements == 0) { + /* No elements, discard.. */ + talloc_free(*mp); + *mp = NULL; + } + return 0; } @@ -761,6 +787,7 @@ static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn * return ret; } +/* Search in the database against which we are mapping */ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -776,6 +803,16 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * /*- search mapped database */ new_tree = ldb_map_parse_tree(module, module, tree); + if (new_tree == NULL) { + /* All attributes used in the parse tree are + * local, apparently. Fall back to enumerating the complete remote + * database... Rather a slow search then no results. */ + new_tree = talloc_zero(module, struct ldb_parse_tree); + new_tree->operation = LDB_OP_PRESENT; + new_tree->u.present.attr = talloc_strdup(new_tree, "dn"); + return 0; + } + newattrs = ldb_map_attrs(module, attrs); new_base = map_local_dn(module, module, base); @@ -801,9 +838,15 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * ret = 0; for (i = 0; i < mpret; i++) { - struct ldb_message *merged = ldb_map_message_incoming(module, attrs, newres[i]); + struct ldb_message *merged; struct ldb_message **extrares = NULL; int extraret; + + /* Always get special DN's from the fallback database */ + if (ldb_dn_is_special(newres[i]->dn)) + continue; + + merged = ldb_map_message_incoming(module, attrs, newres[i]); /* Merge with additional data from local database */ extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); @@ -815,12 +858,12 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * talloc_free(newres); return -1; } else if (extraret == 0) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "No extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); } if (extraret == 1) { int j; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); for (j = 0; j < extrares[0]->num_elements; j++) { ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } @@ -830,7 +873,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); } - if (ldb_match_msg(module->ldb, merged, tree, base, scope)) { + if (ldb_match_msg(module->ldb, merged, tree, base, scope) != 0) { (*res)[ret] = merged; ret++; } else { @@ -859,6 +902,12 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas if (ret_fb == -1) return -1; + /* special dn's are never mapped.. */ + if (ldb_dn_is_special(base)) { + *res = fbres; + return ret_fb; + } + ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); if (ret_mp == -1) { return -1; @@ -867,6 +916,8 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas /* Merge results */ *res = talloc_array(module, struct ldb_message *, ret_fb + ret_mp); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Merging %d mapped and %d fallback messages", ret_mp, ret_fb); + for (i = 0; i < ret_fb; i++) (*res)[i] = fbres[i]; for (i = 0; i < ret_mp; i++) (*res)[ret_fb+i] = mpres[i]; @@ -909,22 +960,25 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - ret = ldb_next_add_record(module, fb); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); - return -1; + if (fb != NULL) { + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); + return -1; + } } + + talloc_free(fb); - ret = ldb_add(privdat->mapped_ldb, mp); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); - return -1; + if (mp != NULL) { + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); + return -1; + } } - talloc_free(fb); talloc_free(mp); return ret; @@ -946,15 +1000,16 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; - - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); - ret = ldb_next_modify_record(module, fb); - - ret = ldb_modify(privdat->mapped_ldb, mp); + if (fb != NULL) { + ret = ldb_next_modify_record(module, fb); + talloc_free(fb); + } - talloc_free(fb); - talloc_free(mp); + if (mp != NULL) { + ret = ldb_modify(privdat->mapped_ldb, mp); + talloc_free(mp); + } return ret; } -- cgit From 05db3024ba6a8cd0b3182595f4f6f2f1f0987e44 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 00:37:52 +0000 Subject: r9854: Finish ldb_map testsuite Update PLAN Some more small other fixes (This used to be commit de2bde2526ffaf521253e3b9e58fc11417986321) --- source4/lib/ldb/modules/ldb_map.c | 25 ++++++++++++------------- source4/lib/samba3/PLAN | 4 +++- source4/lib/samba3/samba3.h | 1 - source4/lib/samba3/smbpasswd.c | 5 ++++- 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 513e065f2e..de7a00ef60 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,11 +27,15 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* TODO: - * - objectclass hint in ldb_map_attribute - * for use when multiple remote attributes (independant of each other) - * map to one local attribute. E.g.: (uid, gidNumber) -> unixName - * (use MAP_GENERATE instead ?) +/* + * - map_message_outgoing() should: + * - modify: not worry about anything simply map and hope everything + * will be ok. + * - make a list of remote objectclasses that will be used + * given the attributes that are available + * - only add attribute to the remote message if + * it is allowed by the objectclass + * */ /* @@ -701,10 +705,6 @@ static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_ } if ((*fb)->num_elements == 0) { - /* No elements, discard.. */ - talloc_free(*fb); - *fb = NULL; - } else { ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); } @@ -727,8 +727,8 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con struct ldb_dn *n_olddn, *n_newdn; int ret; - ret = ldb_next_rename_record(module, olddn, newdn); - + ret = ldb_next_rename_record(module, n_olddn, n_newdn); + n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); @@ -753,7 +753,7 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) newdn = map_local_dn(module, module, dn); - ret = ldb_delete(privdat->mapped_ldb, newdn); + ldb_delete(privdat->mapped_ldb, newdn); talloc_free(newdn); @@ -996,7 +996,6 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) if (!map_is_mappable(privdat, msg)) return ldb_next_modify_record(module, msg); - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) return -1; diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 47b5edd408..80885a4ec7 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,2 +1,4 @@ TODO (SoC project): - - finish ldb_map testsuite + - [ldb_map] some more strict checking when sending data to an LDAP server + - [ldb_map] fix rename + - fix ntPwdHash / lmPwdHash bug diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index f0f4c99513..a5f60bf1c2 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -45,7 +45,6 @@ struct samba3_samaccount { char *profile_path; char *acct_desc; char *workstations; - uid_t uid; uint32_t user_rid, group_rid, hours_len, unknown_6; uint16_t acct_ctrl, logon_divs; uint16_t bad_password_count, logon_count; diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index fe0780c8d3..baddb82545 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -228,6 +228,7 @@ NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct sam for (i = 0; i < numlines; i++) { char *p = lines[i], *q; + uid_t uid; struct samba3_samaccount *acc = &((*accounts)[*count]); if (p[0] == '\0' || p[0] == '#') @@ -244,7 +245,9 @@ NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct sam acc->username = talloc_strndup(ctx, p, PTR_DIFF(q, p)); p = q+1; - acc->uid = atoi(p); + uid = atoi(p); + + /* uid is ignored here.. */ q = strchr(p, ':'); if (!q) { -- cgit From 1b5cb7309d13b472eff12e1bfb5191ca8e0391ae Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 01:11:15 +0000 Subject: r9857: Fix rename/delete issues (This used to be commit d6dce7ef3eb21a5e90244cf2ce7403ab43b12d63) --- source4/lib/ldb/modules/ldb_map.c | 35 ++++++++++++++++++++++++----------- source4/lib/samba3/PLAN | 1 - 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index de7a00ef60..cdf0e29405 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -725,19 +725,26 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; - int ret; - - ret = ldb_next_rename_record(module, n_olddn, n_newdn); - + int fb_ret, mp_ret; + n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); - ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + mp_ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + if (mp_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); + } + + fb_ret = ldb_next_rename_record(module, olddn, newdn); + + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + } talloc_free(n_olddn); talloc_free(n_newdn); - return ret; + return (fb_ret == -1 && mp_ret == -1)?-1:0; } /* @@ -747,17 +754,23 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *newdn; - int ret; + int fb_ret, mp_ret; - ret = ldb_next_delete_record(module, dn); - newdn = map_local_dn(module, module, dn); - ldb_delete(privdat->mapped_ldb, newdn); + mp_ret = ldb_delete(privdat->mapped_ldb, newdn); + if (mp_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); + } + + fb_ret = ldb_next_delete_record(module, dn); + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + } talloc_free(newdn); - return ret; + return (fb_ret == -1 && mp_ret == -1)?-1:0; } /* search fallback database */ diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 80885a4ec7..4351ce2e61 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,4 +1,3 @@ TODO (SoC project): - [ldb_map] some more strict checking when sending data to an LDAP server - - [ldb_map] fix rename - fix ntPwdHash / lmPwdHash bug -- cgit From 7a3e0a89f11f11527bc5e35310185efd210fa9ce Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:29:33 +0000 Subject: r9879: A quick check to see if nested initialisers (?) is portable across the build farm. I have a feeling it isn't. (This used to be commit 7cc8df0c2f46fb9ce753e368ce645bcb69585334) --- source4/lib/ldb/modules/ldb_map.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index cdf0e29405..076aa4c1dc 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -71,7 +71,11 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { { .local_name = "dn", .type = MAP_CONVERT, - .u.convert.remote_name = "dn", + .u = { + .convert = { + .remote_name = "dn", + } + }, .u.convert.convert_local = map_convert_local_dn, .u.convert.convert_remote = map_convert_remote_dn, }, -- cgit From 4d0ec61e49b459b61fa45304e1ab434e7d337fc0 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:37:13 +0000 Subject: r9880: Convert remaining initialisers to more portable form. This should clean out a lot of build farm breakage. (This used to be commit c34fbdc6c3fd2c066c713bdd84e6f40f6aa8cd43) --- source4/lib/ldb/modules/ldb_map.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 076aa4c1dc..423dab38bb 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -74,17 +74,21 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { .u = { .convert = { .remote_name = "dn", - } + .convert_local = map_convert_local_dn, + .convert_remote = map_convert_remote_dn, + }, }, - .u.convert.convert_local = map_convert_local_dn, - .u.convert.convert_remote = map_convert_remote_dn, }, { .local_name = "objectclass", .type = MAP_CONVERT, - .u.convert.remote_name = "objectclass", - .u.convert.convert_local = map_convert_local_objectclass, - .u.convert.convert_remote = map_convert_remote_objectclass, + .u = { + .convert = { + .remote_name = "objectclass", + .convert_local = map_convert_local_objectclass, + .convert_remote = map_convert_remote_objectclass, + }, + }, }, { .local_name = NULL, -- cgit From b2c54c08bf2a5ac2fd564c219ecf54af9bb43e54 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 07:44:59 +0000 Subject: r9881: I can't believe this can make a difference... (This used to be commit 31069bfd18c4b7355dbf85df9fb479705b0e3b4b) --- source4/lib/ldb/modules/ldb_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 423dab38bb..5b1afb56bc 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1164,7 +1164,7 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_dn *dn, *newdn;; + struct ldb_dn *dn, *newdn; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); @@ -1184,7 +1184,7 @@ static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val) { - struct ldb_dn *dn, *newdn;; + struct ldb_dn *dn, *newdn; struct ldb_val *newval; dn = ldb_dn_explode(ctx, (char *)val->data); -- cgit From eb133639dc524cd03f2dd2ba24cf48cd673642f5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 1 Sep 2005 09:14:35 +0000 Subject: r9885: Fix code before declarations. (This used to be commit b7d982c94be05d357a4c3517afc60c7929fb4615) --- source4/lib/samba3/smbpasswd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index baddb82545..483fbcfe05 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -213,9 +213,10 @@ NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct sam { int numlines; char **lines; + int i; + *count = 0; *accounts = NULL; - int i; lines = file_lines_load(filename, &numlines, ctx); -- cgit From e2e2508b586a112e612bf3660f80d25c9bf8bc90 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 15:33:31 +0000 Subject: r9899: Be more conservative about what is sent to the remote server in ldb_map. (This used to be commit 76e943d4416e38ce4cce27d5403bc3e133d0025b) --- source4/lib/ldb/modules/ldb_map.c | 507 +++++++++++++++++++++++++------------- source4/lib/ldb/modules/ldb_map.h | 10 +- 2 files changed, 350 insertions(+), 167 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 5b1afb56bc..5a5575d1e0 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,15 +27,13 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* - * - map_message_outgoing() should: - * - modify: not worry about anything simply map and hope everything - * will be ok. - * - make a list of remote objectclasses that will be used - * given the attributes that are available - * - only add attribute to the remote message if - * it is allowed by the objectclass - * +/* FIXME: + * - per remote objectclass: + * - remote name + * - local name + * - remote bases + * - musts + * - mays */ /* @@ -95,6 +93,17 @@ static const struct ldb_map_attribute builtin_attribute_maps[] = { } }; +static const struct ldb_map_objectclass *map_find_objectclass_remote(struct ldb_map_context *privdat, const char *name) +{ + int i; + for (i = 0; privdat->objectclass_maps[i].remote_name; i++) { + if (!ldb_attr_cmp(privdat->objectclass_maps[i].remote_name, name)) + return &privdat->objectclass_maps[i]; + } + + return NULL; +} + struct map_private { struct ldb_map_context context; const char *last_err_string; @@ -105,41 +114,39 @@ static struct ldb_map_context *map_get_privdat(struct ldb_module *module) return &((struct map_private *)module->private_data)->context; } -static const struct ldb_map_objectclass *map_find_objectclass_local(struct ldb_map_context *privdat, const char *name) -{ - int i; - for (i = 0; privdat->objectclass_maps[i].local_name; i++) { - if (!ldb_attr_cmp(privdat->objectclass_maps[i].local_name, name)) - return &privdat->objectclass_maps[i]; - } - - return NULL; -} - -/* Decide whether a add/modify should be pushed to the - * remote LDAP server. We currently only do this if we see an objectClass we know */ -static int map_is_mappable(struct ldb_map_context *privdat, const struct ldb_message *msg) +/* Check whether the given attribute can fit into the specified + * message, obeying objectClass restrictions */ +static int map_msg_valid_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr) { - int i; - struct ldb_message_element *el; - - if (ldb_dn_is_special(msg->dn)) - return 0; - - el = ldb_msg_find_element(msg, "objectClass"); + struct ldb_map_context *map = module->private_data; + int i, j; + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); - /* No objectClass... */ if (el == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Can't find objectClass"); return 0; } for (i = 0; i < el->num_values; i++) { - if (map_find_objectclass_local(privdat, (char *)el->values[i].data)) - return 1; + const struct ldb_map_objectclass *class = map_find_objectclass_remote(map, (char *)el->values[i].data); + + if (!class) + continue; + + for (j = 0; class->musts[j]; j++) { + if (!ldb_attr_cmp(class->musts[j], attr)) + return 1; + } + + for (j = 0; class->mays[j]; j++) { + if (!ldb_attr_cmp(class->mays[j], attr)) + return 1; + } } return 0; -} +} + /* find an attribute by the local name */ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_context *privdat, const char *attr) @@ -154,6 +161,40 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_contex return NULL; } +/* Check if a given attribute can be created by doing mapping from a local attribute to a remote one */ +static int map_msg_can_map_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr_name) +{ + struct ldb_map_context *map = module->private_data; + int i, j; + + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr = map_find_attr_local(map, msg->elements[i].name); + + if (!attr) + continue; + + switch (attr->type) { + case MAP_IGNORE: continue; + case MAP_KEEP: + if (ldb_attr_cmp(attr->local_name, attr_name) == 0) return 1; + break; + case MAP_RENAME: + case MAP_CONVERT: + if (ldb_attr_cmp(attr->u.rename.remote_name, attr_name) == 0) return 1; + break; + case MAP_GENERATE: + for (j = 0; attr->u.generate.remote_names[j]; j++) { + if (ldb_attr_cmp(attr->u.generate.remote_names[j], attr_name) == 0) return 1; + } + break; + } + } + + return 0; +} + + + /* find an attribute by the remote name */ static const struct ldb_map_attribute *map_find_attr_remote(struct ldb_map_context *privdat, const char *attr) { @@ -547,8 +588,6 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c msg->dn = map_remote_dn(module, module, mi->dn); - ldb_msg_add_string(module->ldb, msg, "mappedFromDn", ldb_dn_linearize(msg, mi->dn)); - /* Loop over attrs, find in ldb_map_attribute array and * run generate() */ @@ -638,94 +677,6 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c return msg; } -/* Used for add, modify */ -static int ldb_map_message_outgoing(struct ldb_module *module, const struct ldb_message *mo, struct ldb_message **fb, struct ldb_message **mp) -{ - struct ldb_map_context *privdat = map_get_privdat(module); - struct ldb_message_element *elm; - int i,j; - - *fb = talloc_zero(module, struct ldb_message); - (*fb)->dn = talloc_reference(*fb, mo->dn); - - *mp = talloc_zero(module, struct ldb_message); - (*mp)->dn = map_local_dn(module, module, mo->dn); - - /* Loop over mi and call generate_remote for each attribute */ - for (i = 0; i < mo->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(privdat, mo->elements[i].name); - enum ldb_map_attr_type map_type; - - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", mo->elements[i].name); - map_type = MAP_IGNORE; - continue; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: /* Add to fallback message */ - elm = talloc(*fb, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, *fb, elm, mo->elements[i].flags); - break; - case MAP_RENAME: - elm = talloc(*mp, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_CONVERT: - elm = talloc(*mp, struct ldb_message_element); - - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, *mp, &mo->elements[i].values[j]); - } - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_KEEP: - elm = talloc(*mp, struct ldb_message_element); - - elm->num_values = mo->elements[i].num_values; - elm->values = talloc_reference(elm, mo->elements[i].values); - elm->name = talloc_strdup(elm, mo->elements[i].name); - - ldb_msg_add(module->ldb, *mp, elm, mo->elements[i].flags); - break; - - case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, mo, *mp); - break; - } - } - - if ((*fb)->num_elements == 0) { - ldb_msg_add_string(module->ldb, *fb, "isMapped", "TRUE"); - } - - if ((*mp)->num_elements == 0) { - /* No elements, discard.. */ - talloc_free(*mp); - *mp = NULL; - } - - return 0; -} - - /* rename a record */ @@ -734,6 +685,13 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; int fb_ret, mp_ret; + + fb_ret = ldb_next_rename_record(module, olddn, newdn); + + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + return fb_ret; + } n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); @@ -743,16 +701,12 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); } - fb_ret = ldb_next_rename_record(module, olddn, newdn); + ldb_next_rename_record(module, olddn, newdn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); - } - talloc_free(n_olddn); talloc_free(n_newdn); - return (fb_ret == -1 && mp_ret == -1)?-1:0; + return mp_ret; } /* @@ -764,6 +718,12 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) struct ldb_dn *newdn; int fb_ret, mp_ret; + fb_ret = ldb_next_delete_record(module, dn); + if (fb_ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + return fb_ret; + } + newdn = map_local_dn(module, module, dn); mp_ret = ldb_delete(privdat->mapped_ldb, newdn); @@ -771,14 +731,11 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); } - fb_ret = ldb_next_delete_record(module, dn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); - } + ldb_next_delete_record(module, newdn); talloc_free(newdn); - return (fb_ret == -1 && mp_ret == -1)?-1:0; + return mp_ret; } /* search fallback database */ @@ -869,7 +826,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * merged = ldb_map_message_incoming(module, attrs, newres[i]); - /* Merge with additional data from local database */ + /* Merge with additional data from fallback database */ extraret = ldb_next_search(module, merged->dn, LDB_SCOPE_BASE, "", NULL, &extrares); if (extraret == -1) { @@ -888,10 +845,6 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * for (j = 0; j < extrares[0]->num_elements; j++) { ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } - - ldb_msg_add_string(module->ldb, merged, "extraMapped", "TRUE"); - } else { - ldb_msg_add_string(module->ldb, merged, "extraMapped", "FALSE"); } if (ldb_match_msg(module->ldb, merged, tree, base, scope) != 0) { @@ -966,6 +919,20 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, return ret; } +static int msg_contains_objectclass(const struct ldb_message *msg, const char *name) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); + int i; + + for (i = 0; i < el->num_values; i++) { + if (ldb_attr_cmp((char *)el->values[i].data, name) == 0) { + return 1; + } + } + + return 0; +} + /* add a record */ @@ -974,32 +941,159 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) int ret; struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_message *fb, *mp; + struct ldb_message_element *ocs; + int i; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add"); - if (!map_is_mappable(privdat, msg)) { + if (ldb_dn_is_special(msg->dn)) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added fallback record"); return ldb_next_add_record(module, msg); } - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; + mp = talloc_zero(module, struct ldb_message); + mp->dn = map_local_dn(module, mp, msg->dn); - if (fb != NULL) { - ret = ldb_next_add_record(module, fb); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding fallback record failed"); - return -1; + fb = talloc_zero(module, struct ldb_message); + fb->dn = talloc_reference(fb, msg->dn); + + /* We add objectClass, so 'top' should be no problem */ + ldb_msg_add_string(module->ldb, mp, "objectClass", "top"); + + /* make a list of remote objectclasses that can be used + * given the attributes that are available and add to + * mp_msg */ + for (i = 0; privdat->objectclass_maps[i].local_name; i++) { + int j, has_musts, has_baseclasses; + + /* Add this objectClass to the list if all musts are present */ + for (j = 0; privdat->objectclass_maps[i].musts[j]; j++) { + if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) + break; } - } - talloc_free(fb); + has_musts = (privdat->objectclass_maps[i].musts[j] == NULL); + + /* Check if base classes are present as well */ + for (j = 0; privdat->objectclass_maps[i].base_classes[j]; j++) { + if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) + break; + } + + has_baseclasses = (privdat->objectclass_maps[i].base_classes[j] == NULL); - if (mp != NULL) { - ret = ldb_add(privdat->mapped_ldb, mp); - if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Adding mapped record failed"); - return -1; + /* Apparently, it contains all required elements */ + if (has_musts && has_baseclasses) { + ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); } } + ocs = ldb_msg_find_element(mp, "objectClass"); + if (ocs->num_values == 1) { /* Only top */ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added fallback record"); + return ldb_next_add_record(module, msg); + } + + /* + * - try to map as much attributes as possible where allowed and add them to mp_msg + * - add other attributes to fb_msg + */ + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr; + struct ldb_message_element *elm; + enum ldb_map_attr_type map_type; + int j; + int mapped = 0; + + if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) + continue; + + attr = map_find_attr_local(privdat, msg->elements[i].name); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + /* Decide whether or not we need to map or fallback */ + switch (map_type) { + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + continue; + case MAP_KEEP: + mapped = map_msg_valid_attr(module, mp, attr->local_name); + case MAP_IGNORE: mapped = 0; break; + case MAP_CONVERT: + case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); + break; + } + + if (mapped) { + switch (map_type) { + case MAP_KEEP: + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + break; + + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + break; + + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } + + mapped = map_msg_valid_attr(module, mp, attr->u.convert.remote_name); + + break; + + case MAP_GENERATE: + case MAP_IGNORE: + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); + break; + } + ldb_msg_add(module->ldb, mp, elm, 0); + } else { + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, fb, elm, 0); + } + } + + ret = ldb_add(privdat->mapped_ldb, mp); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding mapped record failed: %s", ldb_errstring(privdat->mapped_ldb)); + return -1; + } + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added mapped record"); + + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ret = ldb_next_add_record(module, fb); + if (ret == -1) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_next_errstring(module)); + return -1; + } + + talloc_free(fb); talloc_free(mp); return ret; @@ -1013,25 +1107,106 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_message *fb, *mp; - int ret; + struct ldb_message_element *elm; + int fb_ret, mp_ret; + int i,j; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_modify"); - if (!map_is_mappable(privdat, msg)) + if (ldb_dn_is_special(msg->dn)) return ldb_next_modify_record(module, msg); - if (ldb_map_message_outgoing(module, msg, &fb, &mp) == -1) - return -1; + fb = talloc_zero(module, struct ldb_message); + fb->dn = talloc_reference(fb, msg->dn); + + mp = talloc_zero(module, struct ldb_message); + mp->dn = map_local_dn(module, mp, msg->dn); + + /* Loop over mi and call generate_remote for each attribute */ + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_map_attribute *attr; + enum ldb_map_attr_type map_type; + + if (ldb_attr_cmp(msg->elements[i].name, "isMapped") == 0) + continue; + + attr = map_find_attr_local(privdat, msg->elements[i].name); + + if (!attr) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); + map_type = MAP_IGNORE; + } else map_type = attr->type; + + switch (map_type) { + case MAP_IGNORE: /* Add to fallback message */ + elm = talloc(fb, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); + break; + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); + + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_KEEP: + elm = talloc(mp, struct ldb_message_element); - if (fb != NULL) { - ret = ldb_next_modify_record(module, fb); - talloc_free(fb); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_reference(elm, msg->elements[i].values); + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + break; + + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + break; + } + } + + if (fb->num_elements > 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying fallback record with %d elements", fb->num_elements); + fb_ret = ldb_next_modify_record(module, fb); + if (fb_ret == -1) { + ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + fb_ret = ldb_next_add_record(module, fb); + } } + talloc_free(fb); - if (mp != NULL) { - ret = ldb_modify(privdat->mapped_ldb, mp); - talloc_free(mp); + if (mp->num_elements > 0) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying mapped record with %d elements", mp->num_elements); + mp_ret = ldb_modify(privdat->mapped_ldb, mp); } + talloc_free(mp); - return ret; + return (mp_ret == -1 || fb_ret == -1)?-1:0; } static int map_lock(struct ldb_module *module, const char *lockname) diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 4077660160..984a4a2cd5 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -81,7 +81,8 @@ struct ldb_map_attribute struct ldb_module *, const char *local_attr, const struct ldb_message *local, - struct ldb_message *remote); + struct ldb_message *remote_mp, + struct ldb_message *remote_fb); /* Name(s) for this attribute on the remote server. This is an array since * one local attribute's data can be split up into several attributes @@ -92,15 +93,22 @@ struct ldb_map_attribute } u; }; +#define LDB_MAP_MAX_SUBCLASSES 10 +#define LDB_MAP_MAX_MUSTS 10 +#define LDB_MAP_MAX_MAYS 50 struct ldb_map_objectclass { const char *local_name; const char *remote_name; + const char *base_classes[LDB_MAP_MAX_SUBCLASSES]; + const char *musts[LDB_MAP_MAX_MUSTS]; + const char *mays[LDB_MAP_MAX_MAYS]; }; struct ldb_map_context { struct ldb_map_attribute *attribute_maps; + /* NOTE: Always declare base classes first here */ const struct ldb_map_objectclass *objectclass_maps; struct ldb_context *mapped_ldb; }; -- cgit From ca6c0af86f3bbefbc29c4bf4815da963ca857cef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 18:04:23 +0000 Subject: r9908: Generate posixUser and posixGroup as well (This used to be commit ebed25b47d3d8bd350b51b462d605d713f17602d) --- source4/lib/ldb/modules/ldb_map.c | 116 ++++++++++++++++++++------------------ source4/lib/samba3/PLAN | 6 +- 2 files changed, 66 insertions(+), 56 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 5a5575d1e0..f3ece2621e 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -27,15 +27,6 @@ #include "ldb/include/ldb_private.h" #include "ldb/modules/ldb_map.h" -/* FIXME: - * - per remote objectclass: - * - remote name - * - local name - * - remote bases - * - musts - * - mays - */ - /* - special attribute 'isMapped' - add/modify @@ -164,33 +155,39 @@ static const struct ldb_map_attribute *map_find_attr_local(struct ldb_map_contex /* Check if a given attribute can be created by doing mapping from a local attribute to a remote one */ static int map_msg_can_map_attr(struct ldb_module *module, const struct ldb_message *msg, const char *attr_name) { - struct ldb_map_context *map = module->private_data; - int i, j; - - for (i = 0; i < msg->num_elements; i++) { - const struct ldb_map_attribute *attr = map_find_attr_local(map, msg->elements[i].name); + struct ldb_map_context *privdat = module->private_data; + int i,j; - if (!attr) + for (i = 0; privdat->attribute_maps[i].local_name; i++) { + switch (privdat->attribute_maps[i].type) { + case MAP_IGNORE: /* No remote name at all */ continue; - - switch (attr->type) { - case MAP_IGNORE: continue; case MAP_KEEP: - if (ldb_attr_cmp(attr->local_name, attr_name) == 0) return 1; - break; + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].local_name) == 0) + goto found; + break; case MAP_RENAME: case MAP_CONVERT: - if (ldb_attr_cmp(attr->u.rename.remote_name, attr_name) == 0) return 1; - break; + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].u.rename.remote_name) == 0) + goto found; + break; case MAP_GENERATE: - for (j = 0; attr->u.generate.remote_names[j]; j++) { - if (ldb_attr_cmp(attr->u.generate.remote_names[j], attr_name) == 0) return 1; - } - break; + for (j = 0; privdat->attribute_maps[i].u.generate.remote_names[j]; j++) { + if (ldb_attr_cmp(attr_name, privdat->attribute_maps[i].u.generate.remote_names[j]) == 0) + goto found; + } + break; } } return 0; + +found: + + if (ldb_msg_find_element(msg, privdat->attribute_maps[i].local_name)) + return 1; + + return 0; } @@ -684,29 +681,28 @@ static int map_rename(struct ldb_module *module, const struct ldb_dn *olddn, con { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *n_olddn, *n_newdn; - int fb_ret, mp_ret; + int ret; - fb_ret = ldb_next_rename_record(module, olddn, newdn); - - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); - return fb_ret; - } - n_olddn = map_local_dn(module, module, olddn); n_newdn = map_local_dn(module, module, newdn); - mp_ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); - if (mp_ret != -1) { + ret = ldb_rename(privdat->mapped_ldb, n_olddn, n_newdn); + if (ret != -1) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record renamed"); + ldb_next_rename_record(module, olddn, newdn); + } else { + ret = ldb_next_rename_record(module, olddn, newdn); + + if (ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record renamed"); + } } - ldb_next_rename_record(module, olddn, newdn); talloc_free(n_olddn); talloc_free(n_newdn); - return mp_ret; + return ret; } /* @@ -716,26 +712,25 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) { struct ldb_map_context *privdat = map_get_privdat(module); struct ldb_dn *newdn; - int fb_ret, mp_ret; - - fb_ret = ldb_next_delete_record(module, dn); - if (fb_ret != -1) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); - return fb_ret; - } + int ret; newdn = map_local_dn(module, module, dn); - mp_ret = ldb_delete(privdat->mapped_ldb, newdn); - if (mp_ret != -1) { + ret = ldb_delete(privdat->mapped_ldb, newdn); + if (ret != -1) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Mapped record deleted"); + } else { + ret = ldb_next_delete_record(module, dn); + if (ret != -1) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback record deleted"); + } } ldb_next_delete_record(module, newdn); talloc_free(newdn); - return mp_ret; + return ret; } /* search fallback database */ @@ -868,7 +863,7 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - struct ldb_message **fbres, **mpres; + struct ldb_message **fbres, **mpres = NULL; int i; int ret_fb, ret_mp; @@ -968,16 +963,20 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Add this objectClass to the list if all musts are present */ for (j = 0; privdat->objectclass_maps[i].musts[j]; j++) { - if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) + if (!map_msg_can_map_attr(module, msg, privdat->objectclass_maps[i].musts[j])) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Not adding objectClass %s because it is not possible to create remote attribute %s", privdat->objectclass_maps[i].local_name, privdat->objectclass_maps[i].musts[j]); break; + } } has_musts = (privdat->objectclass_maps[i].musts[j] == NULL); /* Check if base classes are present as well */ for (j = 0; privdat->objectclass_maps[i].base_classes[j]; j++) { - if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) + if (!msg_contains_objectclass(mp, privdat->objectclass_maps[i].base_classes[j])) { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Not adding objectClass %s of missing base class %s", privdat->objectclass_maps[i].local_name, privdat->objectclass_maps[i].base_classes[j]); break; + } } has_baseclasses = (privdat->objectclass_maps[i].base_classes[j] == NULL); @@ -985,6 +984,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Apparently, it contains all required elements */ if (has_musts && has_baseclasses) { ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Adding objectClass %s", privdat->objectclass_maps[i].remote_name); } } @@ -1000,7 +1000,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) */ for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; - struct ldb_message_element *elm; + struct ldb_message_element *elm = NULL; enum ldb_map_attr_type map_type; int j; int mapped = 0; @@ -1018,10 +1018,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Decide whether or not we need to map or fallback */ switch (map_type) { case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); continue; case MAP_KEEP: mapped = map_msg_valid_attr(module, mp, attr->local_name); + break; case MAP_IGNORE: mapped = 0; break; case MAP_CONVERT: case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); @@ -1031,6 +1033,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) if (mapped) { switch (map_type) { case MAP_KEEP: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping %s", attr->local_name); elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; @@ -1039,6 +1042,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) break; case MAP_RENAME: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Renaming %s -> %s", attr->local_name, attr->u.rename.remote_name); elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1047,6 +1051,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) break; case MAP_CONVERT: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting %s -> %s", attr->local_name, attr->u.convert.remote_name); elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1064,10 +1069,11 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) case MAP_GENERATE: case MAP_IGNORE: ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); - break; + continue; } ldb_msg_add(module->ldb, mp, elm, 0); } else { + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback storing %s", msg->elements[i].name); elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; @@ -1197,13 +1203,13 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); fb_ret = ldb_next_add_record(module, fb); } - } + } else fb_ret = 0; talloc_free(fb); if (mp->num_elements > 0) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying mapped record with %d elements", mp->num_elements); mp_ret = ldb_modify(privdat->mapped_ldb, mp); - } + } else mp_ret = 0; talloc_free(mp); return (mp_ret == -1 || fb_ret == -1)?-1:0; diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 4351ce2e61..916617638b 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,3 +1,7 @@ TODO (SoC project): - - [ldb_map] some more strict checking when sending data to an LDAP server - fix ntPwdHash / lmPwdHash bug + - ldb_map + - convert_remote() can be NULL! + - new way of finding remote attribute in map_add() + - loop over all attributes + - if local one present, run! -- cgit From 4f4dae05f03c76b81cbc71ee80f7f1a34644936f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 18:55:51 +0000 Subject: r9912: Fix another bug in ldb_map. (This used to be commit 4c3b37d660e798764e35a31221f4939ab6f36948) --- source4/lib/ldb/modules/ldb_map.c | 165 +++++++++++++++++++++----------------- source4/lib/ldb/modules/ldb_map.h | 4 + source4/lib/samba3/PLAN | 5 -- 3 files changed, 97 insertions(+), 77 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index f3ece2621e..3bbf893a27 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1001,37 +1001,39 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; struct ldb_message_element *elm = NULL; - enum ldb_map_attr_type map_type; - int j; + int j, k; int mapped = 0; if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) continue; - attr = map_find_attr_local(privdat, msg->elements[i].name); + /* Loop over all attribute_maps with msg->elements[i].name as local_name */ + for (k = 0; privdat->attribute_maps[k].local_name; k++) { + if (ldb_attr_cmp(msg->elements[i].name, privdat->attribute_maps[k].local_name) != 0) + continue; - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); - map_type = MAP_IGNORE; - } else map_type = attr->type; + attr = &privdat->attribute_maps[k]; - /* Decide whether or not we need to map or fallback */ - switch (map_type) { - case MAP_GENERATE: - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); - attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); - continue; - case MAP_KEEP: - mapped = map_msg_valid_attr(module, mp, attr->local_name); - break; - case MAP_IGNORE: mapped = 0; break; - case MAP_CONVERT: - case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name); - break; - } + /* Decide whether or not we need to map or fallback */ + switch (attr->type) { + case MAP_GENERATE: + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating from %s", attr->local_name); + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + mapped++; + continue; + case MAP_KEEP: + if (!map_msg_valid_attr(module, mp, attr->local_name)) + continue; + break; + case MAP_IGNORE: continue; + case MAP_CONVERT: + case MAP_RENAME: + if (!map_msg_valid_attr(module, mp, attr->u.rename.remote_name)) + continue; + break; + } - if (mapped) { - switch (map_type) { + switch (attr->type) { case MAP_KEEP: ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Keeping %s", attr->local_name); elm = talloc(fb, struct ldb_message_element); @@ -1062,8 +1064,6 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); } - mapped = map_msg_valid_attr(module, mp, attr->u.convert.remote_name); - break; case MAP_GENERATE: @@ -1071,8 +1071,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached"); continue; } + ldb_msg_add(module->ldb, mp, elm, 0); - } else { + mapped++; + } + + if (mapped == 0) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Fallback storing %s", msg->elements[i].name); elm = talloc(fb, struct ldb_message_element); @@ -1131,69 +1135,82 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) /* Loop over mi and call generate_remote for each attribute */ for (i = 0; i < msg->num_elements; i++) { const struct ldb_map_attribute *attr; - enum ldb_map_attr_type map_type; + int k; + int mapped = 0; if (ldb_attr_cmp(msg->elements[i].name, "isMapped") == 0) continue; - attr = map_find_attr_local(privdat, msg->elements[i].name); + for (k = 0; privdat->attribute_maps[k].local_name; k++) + { + if (ldb_attr_cmp(privdat->attribute_maps[k].local_name, msg->elements[i].name) != 0) + continue; - if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name); - map_type = MAP_IGNORE; - } else map_type = attr->type; - - switch (map_type) { - case MAP_IGNORE: /* Add to fallback message */ - elm = talloc(fb, struct ldb_message_element); + attr = &privdat->attribute_maps[k]; - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); - elm->name = talloc_strdup(elm, msg->elements[i].name); - - ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - break; - case MAP_RENAME: - elm = talloc(mp, struct ldb_message_element); + switch (attr->type) { + case MAP_IGNORE: continue; + case MAP_RENAME: + elm = talloc(mp, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = msg->elements[i].values[j]; - } + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; - case MAP_CONVERT: - elm = talloc(mp, struct ldb_message_element); + case MAP_CONVERT: + elm = talloc(mp, struct ldb_message_element); - elm->name = talloc_strdup(elm, attr->u.rename.remote_name); - elm->num_values = msg->elements[i].num_values; - elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - - for (j = 0; j < elm->num_values; j++) { - elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); - } + elm->name = talloc_strdup(elm, attr->u.rename.remote_name); + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); + } - case MAP_KEEP: - elm = talloc(mp, struct ldb_message_element); + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; + + case MAP_KEEP: + elm = talloc(mp, struct ldb_message_element); + + elm->num_values = msg->elements[i].num_values; + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = msg->elements[i].values[j]; + } + + elm->name = talloc_strdup(elm, msg->elements[i].name); + + ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + mapped++; + continue; + + case MAP_GENERATE: + attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); + mapped++; + continue; + } + } + + if (mapped == 0) {/* Add to fallback message */ + elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); - break; + ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - case MAP_GENERATE: - attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb); - break; - } + } } if (fb->num_elements > 0) { @@ -1356,7 +1373,11 @@ static struct ldb_val map_convert_local_dn(struct ldb_module *module, TALLOC_CTX newval = talloc(ctx, struct ldb_val); newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); + if (newval->data) { + newval->length = strlen((char *)newval->data); + } else { + newval->length = 0; + } talloc_free(newdn); diff --git a/source4/lib/ldb/modules/ldb_map.h b/source4/lib/ldb/modules/ldb_map.h index 984a4a2cd5..42eba23aa6 100644 --- a/source4/lib/ldb/modules/ldb_map.h +++ b/source4/lib/ldb/modules/ldb_map.h @@ -2,6 +2,7 @@ ldb database library - map backend Copyright (C) Jelmer Vernooij 2005 + Development sponsored by the Google Summer of Code program ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -65,6 +66,9 @@ struct ldb_map_attribute struct { const char *remote_name; struct ldb_val (*convert_local) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); + + /* an entry can have convert_remote set to NULL, as long as there as an entry with the same local_name + * that is non-NULL before it. */ struct ldb_val (*convert_remote) (struct ldb_module *, TALLOC_CTX *, const struct ldb_val *); } convert; diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN index 916617638b..9a24f70271 100644 --- a/source4/lib/samba3/PLAN +++ b/source4/lib/samba3/PLAN @@ -1,7 +1,2 @@ TODO (SoC project): - fix ntPwdHash / lmPwdHash bug - - ldb_map - - convert_remote() can be NULL! - - new way of finding remote attribute in map_add() - - loop over all attributes - - if local one present, run! -- cgit From 08f630be8230ce061badd84bef952d5753afdff0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 20:28:03 +0000 Subject: r9915: Some more mappings. Fix weird sAMAccountName values. (This used to be commit 8ff1358f401e0086b941f4ff73af5d4c38a1f8bf) --- source4/lib/ldb/modules/ldb_map.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 3bbf893a27..9b62b1314a 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -324,6 +324,8 @@ static struct ldb_parse_tree *ldb_map_parse_tree(struct ldb_module *module, TALL } if (map_type == MAP_CONVERT) { + if (!attr->u.convert.convert_local) + return NULL; newvalue = attr->u.convert.convert_local(module, new_tree, &value); } else { newvalue = ldb_val_dup(new_tree, &value); @@ -435,6 +437,11 @@ static struct ldb_dn *map_local_dn(struct ldb_module *module, TALLOC_CTX *ctx, c case MAP_CONVERT: newdn->components[i].name = talloc_strdup(newdn->components, attr->u.convert.remote_name); + if (attr->u.convert.convert_local == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "convert_local not set for attribute '%s' used in DN!", dn->components[i].name); + talloc_free(newdn); + return NULL; + } newdn->components[i].value = attr->u.convert.convert_local(module, newdn->components, &dn->components[i].value); break; @@ -658,8 +665,12 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c case MAP_GENERATE: ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Generating local attribute %s", attr->local_name); + if (!attr->u.generate.generate_local) + continue; + elm = attr->u.generate.generate_local(module, msg, attr->local_name, mi); - if (!elm) continue; + if (!elm) + continue; ldb_msg_add(module->ldb, msg, elm, elm->flags); break; @@ -1039,7 +1050,12 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm = talloc(fb, struct ldb_message_element); elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = ldb_val_dup(elm, &msg->elements[i].values[j]); + } + elm->name = talloc_strdup(elm, msg->elements[i].name); break; @@ -1049,10 +1065,16 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->name = talloc_strdup(elm, attr->u.rename.remote_name); elm->num_values = msg->elements[i].num_values; - elm->values = talloc_reference(elm, msg->elements[i].values); + elm->values = talloc_array(elm, struct ldb_val, elm->num_values); + + for (j = 0; j < elm->num_values; j++) { + elm->values[j] = ldb_val_dup(elm, &msg->elements[i].values[j]); + } break; case MAP_CONVERT: + if (attr->u.convert.convert_local == NULL) + continue; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Converting %s -> %s", attr->local_name, attr->u.convert.remote_name); elm = talloc(mp, struct ldb_message_element); @@ -1165,6 +1187,8 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) continue; case MAP_CONVERT: + if (!attr->u.convert.convert_local) + continue; elm = talloc(mp, struct ldb_message_element); elm->name = talloc_strdup(elm, attr->u.rename.remote_name); @@ -1397,7 +1421,11 @@ static struct ldb_val map_convert_remote_dn(struct ldb_module *module, TALLOC_CT newval = talloc(ctx, struct ldb_val); newval->data = (uint8_t *)ldb_dn_linearize(ctx, newdn); - newval->length = strlen((char *)newval->data); + if (newval->data) { + newval->length = strlen((char *)newval->data); + } else { + newval->length = 0; + } talloc_free(newdn); -- cgit From f14f4fd7068e0ce55350c713d1925680876606bb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 21:32:43 +0000 Subject: r9918: Fix two copy-n-paste bugs that were preventing the modification of special DN's when the rdn_name or timestamps modules were in use. (This used to be commit c61efb2ff851f8f55b4747c8068c7e780083e35c) --- source4/lib/ldb/modules/rdn_name.c | 4 ++-- source4/lib/ldb/modules/timestamps.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index d59205c6e4..09e9c72811 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -159,12 +159,12 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me /* do not manipulate our control entries */ if (ldb_dn_is_special(msg->dn)) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } /* Perhaps someone above us knows better */ if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } msg2 = talloc(module, struct ldb_message); diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 4819e0466b..f712505211 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -162,7 +162,7 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ /* do not manipulate our control entries */ if (ldb_dn_is_special(msg->dn)) { - return ldb_next_add_record(module, msg); + return ldb_next_modify_record(module, msg); } timeval = time(NULL); -- cgit From 74b26525ea06598e2cfd6d869344506f45955e68 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 1 Sep 2005 21:34:05 +0000 Subject: r9919: Remove debug statement from samba3sam Add SOC STATUS doc (This used to be commit 152c1a37b536c65e0b816319304d1fb46c2dc5a8) --- source4/lib/samba3/PLAN | 2 -- source4/lib/samba3/STATUS | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) delete mode 100644 source4/lib/samba3/PLAN create mode 100644 source4/lib/samba3/STATUS (limited to 'source4/lib') diff --git a/source4/lib/samba3/PLAN b/source4/lib/samba3/PLAN deleted file mode 100644 index 9a24f70271..0000000000 --- a/source4/lib/samba3/PLAN +++ /dev/null @@ -1,2 +0,0 @@ -TODO (SoC project): - - fix ntPwdHash / lmPwdHash bug diff --git a/source4/lib/samba3/STATUS b/source4/lib/samba3/STATUS new file mode 100644 index 0000000000..e4644526df --- /dev/null +++ b/source4/lib/samba3/STATUS @@ -0,0 +1,68 @@ +--- Samba3 -> Samba4 Upgrade --- +(C) 2005 Jelmer Vernooij +Published under the GNU GPL + +Sponsored by the Google Summer of Code program (http://code.google.com/summerofcode.html) +Mentored by Andrew Bartlett +Thanks! + +Done: + - Reading wins.dat + - Reading registry.tdb + - Reading passdb.tdb + - Reading account_policy.tdb + - Reading group_mappings.tdb + - Reading winbindd_idmap.tdb + - Reading share_info.tdb + - Reading secrets.tdb + - Reading smbpasswd + - Reading + writing (generic) smb.conf files + - Testsuite for read support mentioned above + - Console utility for dumping Samba information + - Import user accounts in Samba4 + - Import groups in Samba4 + - Import secrets in Samba4 + - Import WINS data in Samba4 + - Dump idmap data to LDB + - Import registry keys/values in Samba4 + - Import account policies in Samba4 + - Testsuite for upgrade + - Console utility from upgrading from Samba3 -> Samba4 + - SWAT (Web interface) support for upgrading from Samba3 -> Samba4 + - LDB generic mapping module + - (Experimental) Samba4 LDB <-> Samba3 LDAP mapping module based on LDB generic mapping module + - Testsuite for Samba4 LDB <-> Samba3 LDAP mapping module + +Source files: +source/lib/ldb/modules/ldb_map.c +source/lib/ldb/modules/ldb_map.h +source/lib/samba3/group.c +source/lib/samba3/idmap.c +source/lib/samba3/policy.c +source/lib/samba3/registry.c +source/lib/samba3/samba3.c +source/lib/samba3/secrets.c +source/lib/samba3/share_info.c +source/lib/samba3/smbpasswd.c +source/lib/samba3/tdbsam.c +source/lib/samba3/winsdb.c +source/lib/samba3/samba3.h +source/scripting/libjs/upgrade.js +source/scripting/ejs/smbcalls_param.c +source/scripting/ejs/smbcalls_samba3.c +source/param/generic.c +source/param/generic.h +testdata/samba3/verify +testprogs/ejs/samba3sam +source/setup/upgrade +source/scripting/bin/samba3dump +source/dsdb/samdb/ldb_modules/samba3sam.c +source/script/tests/test_s3upgrade.sh +swat/install/samba3.esp + +Known remaining issues: + - [upgrade] Conversion from the smbpasswd/TDB passwords to ntPwdHash / lmPwdHash is broken. Couldn't find out why. + - [ldb_map] Conversion of attribute names in DN's is still a bit dodgy + - [ldb_map] mapped objectClass names may be mentioned multiple times in returned records + - [ldb_map] add/modify support not tested very well with LDAP yet (only LDB+TDB) + - [ldb_map] group membership is not yet mapped (only primaryGroupID / sambaPrimaryGroupSID) -- cgit From ca875491688f755637aece917147f149906f9a8f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Sep 2005 23:24:16 +0000 Subject: r9928: ncName is a DN, and needs to use DN matching rules. Andrew Bartlett (This used to be commit b89e7a7fcdf80f2cab581f138358b4324d15d6bc) --- source4/lib/ldb/common/ldb_attributes.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index 3973fc515c..47b4b1788b 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -149,6 +149,7 @@ int ldb_setup_wellknown_attributes(struct ldb_context *ldb) const char *syntax; } wellknown[] = { { "dn", LDB_SYNTAX_DN }, + { "ncName", LDB_SYNTAX_DN }, { "distinguishedName", LDB_SYNTAX_DN }, { "cn", LDB_SYNTAX_DIRECTORY_STRING }, { "dc", LDB_SYNTAX_DIRECTORY_STRING }, -- cgit From 95fcf031b0480ada75ed5ed02826f4acf196be77 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Sep 2005 23:24:47 +0000 Subject: r9929: Fix indentation Andrew Bartlett (This used to be commit d6f57ec921839b46534eb64a7b6374161ff37835) --- source4/lib/credentials.c | 4 +++- source4/lib/ldb/common/ldb_dn.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 162b52e5d0..ce122197b8 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -128,7 +128,9 @@ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_C return talloc_reference(mem_ctx, cred->principal); } -BOOL cli_credentials_set_principal(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) +BOOL cli_credentials_set_principal(struct cli_credentials *cred, + const char *val, + enum credentials_obtained obtained) { if (obtained >= cred->principal_obtained) { cred->principal = talloc_strdup(cred, val); diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 20cef9dd81..d1a311dad6 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -688,7 +688,7 @@ struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn) } struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr, - const char *val) + const char *val) { struct ldb_dn_component *dc; @@ -783,7 +783,7 @@ struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const str for (i = 0; i < dn1->comp_num; i++) { new->components[i] = ldb_dn_copy_component(new->components, - &(dn1->components[i])); + &(dn1->components[i])); } return new; -- cgit From 9319cace3bb5320e943ec75348efefe199323499 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 2 Sep 2005 03:13:04 +0000 Subject: r9940: When guessing, don't make DEBUG(1,... errors. Andrew Bartlett (This used to be commit 664736e73df60ccfd24a41fda75031cb6b7d08cd) --- source4/lib/credentials.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index ce122197b8..a82c01d4c9 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -334,7 +334,7 @@ static int cli_credentials_set_ccache(struct cli_credentials *cred, } else { ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); if (ret) { - DEBUG(1,("failed to read default krb5 ccache: %s\n", + DEBUG(3,("failed to read default krb5 ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccc); return ret; @@ -346,7 +346,7 @@ static int cli_credentials_set_ccache(struct cli_credentials *cred, ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); if (ret) { - DEBUG(1,("failed to get principal from default ccache: %s\n", + DEBUG(3,("failed to get principal from default ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); talloc_free(ccc); return ret; -- cgit From 4462869db22983d1a6634fd7bec5c6a073404b10 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 2 Sep 2005 11:33:35 +0000 Subject: r9948: Be a bit less verbose (This used to be commit 071dba2d0ae964e9901adf0c4870894deed43650) --- source4/lib/ldb/modules/ldb_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 9b62b1314a..ba98a5f495 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -483,7 +483,7 @@ static const char **ldb_map_attrs(struct ldb_module *module, const char *const a enum ldb_map_attr_type map_type; if (!attr) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Local attribute '%s' does not have a definition!\n", attrs[i]); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Local attribute '%s' does not have a definition!\n", attrs[i]); map_type = MAP_IGNORE; } else map_type = attr->type; -- cgit From fc411bed80e3150a0d368daf9fb41f6c2aedf537 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 2 Sep 2005 11:35:58 +0000 Subject: r9949: Portability fixes for mingw32 (This used to be commit 994093b08ee463066c6bae494b10374bd700b0b0) --- source4/lib/replace/repdir/config.m4 | 4 +++- source4/lib/replace/win32/replace.h | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/repdir/config.m4 b/source4/lib/replace/repdir/config.m4 index 0ef40ad8cb..02fb6e1816 100644 --- a/source4/lib/replace/repdir/config.m4 +++ b/source4/lib/replace/repdir/config.m4 @@ -1,6 +1,8 @@ AC_CACHE_CHECK([for broken readdir],samba_cv_HAVE_BROKEN_READDIR,[ AC_TRY_RUN([#include "${srcdir-.}/build/tests/os2_delete.c"], - samba_cv_HAVE_BROKEN_READDIR=no,samba_cv_HAVE_BROKEN_READDIR=yes)]) + [samba_cv_HAVE_BROKEN_READDIR=no], + [samba_cv_HAVE_BROKEN_READDIR=yes], + [samba_cv_HAVE_BROKEN_READDIR="assuming not"])]) if test x"$samba_cv_HAVE_BROKEN_READDIR" = x"yes"; then AC_CACHE_CHECK([for replacing readdir],samba_cv_REPLACE_READDIR,[ diff --git a/source4/lib/replace/win32/replace.h b/source4/lib/replace/win32/replace.h index 2c6d0e1a3f..94fa140681 100644 --- a/source4/lib/replace/win32/replace.h +++ b/source4/lib/replace/win32/replace.h @@ -140,7 +140,4 @@ #undef SE_GROUP_ENABLED_BY_DEFAULT #undef SE_GROUP_ENABLED -typedef uint32_t u_int32_t; -typedef uint16_t u_int16_t; - #endif /* _WIN32_REPLACE_H */ -- cgit From c70405cd728c28c1c21c9e1e97279c2e4e9bcc91 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 2 Sep 2005 14:05:28 +0000 Subject: r9957: Switch to using DATA_BLOBs internally in TDR (This used to be commit 351149d160e893a3fdd4a5b11ec4b4b2bbf264a9) --- source4/lib/tdr/tdr.c | 51 +++++++++++++++++++++++---------------------------- source4/lib/tdr/tdr.h | 7 ++----- 2 files changed, 25 insertions(+), 33 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index 1c84d2229f..1d859fdcd5 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -29,25 +29,24 @@ #define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->offset+(n))) #define TDR_PULL_NEED_BYTES(tdr, n) do { \ - if ((n) > tdr->length || tdr->offset + (n) > tdr->length) { \ + if ((n) > tdr->data.length || tdr->offset + (n) > tdr->data.length) { \ return NT_STATUS_BUFFER_TOO_SMALL; \ } \ } while(0) #define TDR_BE(tdr) ((tdr)->flags & TDR_BIG_ENDIAN) -#define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data,ofs):SVAL(tdr->data,ofs)) -#define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data,ofs):IVAL(tdr->data,ofs)) -#define TDR_IVALS(tdr, ofs) (TDR_BE(tdr)?RIVALS(tdr->data,ofs):IVALS(tdr->data,ofs)) -#define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSSVAL(tdr->data,ofs,v); } else SSVAL(tdr->data,ofs,v); } while (0) -#define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data,ofs,v); } else SIVAL(tdr->data,ofs,v); } while (0) -#define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVALS(tdr->data,ofs,v); } else SIVALS(tdr->data,ofs,v); } while (0) +#define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data.data,ofs):SVAL(tdr->data.data,ofs)) +#define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data.data,ofs):IVAL(tdr->data.data,ofs)) +#define TDR_IVALS(tdr, ofs) (TDR_BE(tdr)?RIVALS(tdr->data.data,ofs):IVALS(tdr->data.data,ofs)) +#define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSSVAL(tdr->data.data,ofs,v); } else SSVAL(tdr->data.data,ofs,v); } while (0) +#define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data.data,ofs,v); } else SIVAL(tdr->data.data,ofs,v); } while (0) +#define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVALS(tdr->data.data,ofs,v); } else SIVALS(tdr->data.data,ofs,v); } while (0) -struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) { struct tdr_pull *tdr = talloc_zero(mem_ctx, struct tdr_pull); - tdr->data = blob->data; - tdr->length = blob->length; + tdr->data = *blob; return tdr; } @@ -66,15 +65,11 @@ struct tdr_print *tdr_print_init(TALLOC_CTX *mem_ctx) */ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) { - if (tdr->alloc_size >= size) { + if (talloc_get_size(tdr->data.data) >= size) { return NT_STATUS_OK; } - tdr->alloc_size += TDR_BASE_MARSHALL_SIZE; - if (size > tdr->alloc_size) { - tdr->length = size; - } - tdr->data = talloc_realloc(tdr, tdr->data, uint8_t, tdr->alloc_size); + tdr->data.data = talloc_realloc(tdr, tdr->data.data, uint8_t, tdr->data.length + TDR_BASE_MARSHALL_SIZE); return NT_STATUS_NO_MEMORY; } @@ -82,7 +77,7 @@ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) { TDR_PULL_NEED_BYTES(tdr, 1); - SCVAL(tdr->data, tdr->offset, *v); + SCVAL(tdr->data.data, tdr->offset, *v); tdr->offset += 1; return NT_STATUS_OK; } @@ -90,7 +85,7 @@ NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v) { TDR_PUSH_NEED_BYTES(tdr, 1); - SCVAL(tdr->data, tdr->offset, *v); + SCVAL(tdr->data.data, tdr->offset, *v); tdr->offset += 1; return NT_STATUS_OK; } @@ -152,10 +147,10 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, if (length == -1) { switch (chset) { case CH_DOS: - length = ascii_len_n((const char*)tdr->data+tdr->offset, tdr->length-tdr->offset); + length = ascii_len_n((const char*)tdr->data.data+tdr->offset, tdr->data.length-tdr->offset); break; case CH_UTF16: - length = utf16_len_n(tdr->data+tdr->offset, tdr->length-tdr->offset); + length = utf16_len_n(tdr->data.data+tdr->offset, tdr->data.length-tdr->offset); break; default: @@ -165,7 +160,7 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, TDR_PULL_NEED_BYTES(tdr, el_size*length); - ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, discard_const_p(void *, v)); + ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v)); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; @@ -181,7 +176,7 @@ NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, required = el_size * length; TDR_PUSH_NEED_BYTES(tdr, required); - ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data+tdr->offset, required); + ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->offset, required); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; @@ -189,7 +184,7 @@ NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, /* Make sure the remaining part of the string is filled with zeroes */ if (ret < required) { - memset(tdr->data+tdr->offset+ret, 0, required-ret); + memset(tdr->data.data+tdr->offset+ret, 0, required-ret); } tdr->offset += required; @@ -344,7 +339,7 @@ NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob) TDR_PUSH_NEED_BYTES(tdr, blob->length); - memcpy(tdr->data+tdr->offset, blob->data, blob->length); + memcpy(tdr->data.data+tdr->offset, blob->data, blob->length); return NT_STATUS_OK; } @@ -362,18 +357,18 @@ NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob) } else if (tdr->flags & TDR_ALIGN8) { length = TDR_ALIGN(tdr, 8); } else if (tdr->flags & TDR_REMAINING) { - length = tdr->length - tdr->offset; + length = tdr->data.length - tdr->offset; } else { return NT_STATUS_INVALID_PARAMETER; } - if (tdr->length - tdr->offset < length) { - length = tdr->length - tdr->offset; + if (tdr->data.length - tdr->offset < length) { + length = tdr->data.length - tdr->offset; } TDR_PULL_NEED_BYTES(tdr, length); - *blob = data_blob_talloc(tdr, tdr->data+tdr->offset, length); + *blob = data_blob_talloc(tdr, tdr->data.data+tdr->offset, length); tdr->offset += length; return NT_STATUS_OK; } diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index b6a1177c0d..9d9d2b8adf 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -25,17 +25,14 @@ #define TDR_REMAINING 0x10 struct tdr_pull { - uint8_t *data; + DATA_BLOB data; uint32_t offset; - uint32_t length; int flags; }; struct tdr_push { - uint8_t *data; - uint32_t alloc_size; + DATA_BLOB data; uint32_t offset; - uint32_t length; int flags; }; -- cgit From 52d995feb0565b458e026063e3bf3c259846bc8e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 2 Sep 2005 14:45:40 +0000 Subject: r9959: Fix bug where data offset was incorrect after parsing element with [charset] (This used to be commit b17478229e8e9220858fcc85a19ec751450f969d) --- source4/lib/tdr/tdr.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index 1d859fdcd5..c16a05ecf0 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -43,23 +43,6 @@ #define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data.data,ofs,v); } else SIVAL(tdr->data.data,ofs,v); } while (0) #define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVALS(tdr->data.data,ofs,v); } else SIVALS(tdr->data.data,ofs,v); } while (0) -struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) -{ - struct tdr_pull *tdr = talloc_zero(mem_ctx, struct tdr_pull); - tdr->data = *blob; - return tdr; -} - -struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx) -{ - return talloc_zero(mem_ctx, struct tdr_push); -} - -struct tdr_print *tdr_print_init(TALLOC_CTX *mem_ctx) -{ - return talloc_zero(mem_ctx, struct tdr_print); -} - /* expand the available space in the buffer to 'size' */ @@ -166,6 +149,8 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, return NT_STATUS_INVALID_PARAMETER; } + tdr->offset += length * el_size; + return NT_STATUS_OK; } -- cgit From 7f66d5ce255b07d5ae0c35a95340d2401c6409bb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sat, 3 Sep 2005 12:37:44 +0000 Subject: r9993: Gcc is fussy about the lack of parentheses around assignment statements. (This used to be commit 908ba892598af83ae2fbe661d40e9f10ff3e34a0) --- source4/lib/cmdline/popt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index d3bd0a35a4..333004e965 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -221,7 +221,7 @@ static void popt_common_credentials_callback(poptContext con, cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED); /* This breaks the abstraction, including the const above */ - if (lp=strchr_m(arg,'%')) { + if ((lp=strchr_m(arg,'%'))) { lp[0]='\0'; lp++; memset(lp,0,strlen(lp)); -- cgit From 201fd3bd72d5f080eb16455f35e182c266aaf64b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 14:58:00 +0000 Subject: r9995: Add file describing the REGF file format in IDL. (used in reg_backend_nt4.c rewrite) (This used to be commit 5e1a16eda28d432b94dc933b44da3ca556f92fdf) --- source4/lib/registry/regf.idl | 154 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 source4/lib/registry/regf.idl (limited to 'source4/lib') diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl new file mode 100644 index 0000000000..8bef15c79e --- /dev/null +++ b/source4/lib/registry/regf.idl @@ -0,0 +1,154 @@ +/* + Definitions for the REGF registry file format as used by + Windows NT4 and above. + + Written by Jelmer Vernooij, 2005 + + Based on two files from Samba 3: + regedit.c by Richard Sharpe + regfio.c by Jerry Carter + + Thanks to Wilco Baan Hofman for some of the info on li and ri fields. +*/ + +interface regf +{ + typedef struct { + uint32 major; + uint32 minor; + uint32 release; + uint32 build; + } regf_version; + + /* 1.3.0.1 for WinNT 4 + * 1.5.0.1 for WinXP + */ + + + /* + "regf" is obviously the abbreviation for "Registry file". "regf" is the + signature of the header-block which is always 4kb in size, although only + the first 64 bytes seem to be used and a checksum is calculated over + the first 0x200 bytes only! + */ + + typedef [public] struct { + [charset(DOS)] uint8 REGF_ID[4]; /* 'regf' */ + uint32 update_counter1; + uint32 update_counter2; + NTTIME modtime; + regf_version version; + uint32 data_offset; + uint32 last_block; + [value(1)] uint32 uk7; /* 1 */ + [charset(UTF16)] uint16 description[0x40]; + uint32 padding[83]; /* Padding */ + /* Checksum of first 0x200 bytes XOR-ed */ + uint32 chksum; + } regf_hdr; + + /* + hbin probably means hive-bin (what bin stands for I don't know) + This block is always a multiple + of 4kb in size. + */ + typedef [public] struct { + [charset(DOS)] uint8 HBIN_ID[4]; /* hbin */ + uint32 off_from_first; /* Offset from 1st hbin-Block */ + uint32 off_to_next; /* Offset to the next hbin-Block */ + uint32 unknown[2]; + NTTIME last_change; + uint32 block_size; /* Block size */ + uint8 data[block_size]; /* Filled with hbin_data blocks */ + } hbin_block; + + typedef struct { + uint32 length; + [charset(DOS)] uint8 header[2]; /* li, lh, ri, nk, vk, sk, lf or \0\0 */ + uint8 data[length-2]; + } hbin_data; + + typedef enum { + REG_ROOT_KEY = 0x20, + REG_SUB_KEY = 0x2C, + REG_SYM_LINK = 0x10 + } reg_key_type; + + /* + The nk-record can be treated as a combination of tree-record and + key-record of the win 95 registry. + */ + typedef struct { + reg_key_type type; + NTTIME last_change; + uint32 uk1; + uint32 parent_offset; + uint32 num_subkeys; + uint32 uk2; + uint32 subkeys_offset; + uint32 uk3; + uint32 num_values; + uint32 values_offset; + uint32 sk_offset; + uint32 clsnam_offset; + uint32 unk4[5]; + uint16 name_length; + uint16 clsname_length; + [charset(DOS)] uint8 key_name[name_length]; + } nk_block; + + /* sk (? Security Key ?) is the ACL of the registry. */ + typedef struct { + uint16 uk1; + uint32 prev_offset; + uint32 next_offset; + uint32 ref_cnt; + uint32 rec_size; + uint8 sec_desc[rec_size]; + } sk_block; + + typedef struct { + uint32 offset_nk; + uint32 base37; /* base37 of key name */ + } lh_hash; + + typedef struct { + uint16 key_count; + lh_hash hashes[key_count]; + } lh_block; + + typedef struct { + uint16 key_count; + uint32 offset_nk[key_count]; + } li_block; + + typedef struct { + uint16 key_count; + uint32 offset[key_count]; /* li/lh offset */ + } ri_block; + + /* The vk-record consists information to a single value (value key). */ + typedef struct { + uint16 name_length; + uint32 data_length; /* If top-bit set, offset contains the data */ + uint32 data_offset; + uint32 data_type; + uint16 flag; /* =1, has name, else no name (=Default). */ + uint16 unk1; + [charset(DOS)] uint8 data_name[name_length]; + } vk_block; + + typedef struct { + uint32 nk_off; + uint8 hash[4]; + } hash_record; + + /* + The lf-record is the counterpart to the RGKN-record (the + hash-function) + */ + typedef struct { + uint16 key_count; + hash_record hr[key_count]; /* Array of hash records, depending on key_count */ + } lf_block; +} -- cgit From 02b3abec25ed0b303906c5dae9dd527171762d9a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 17:17:30 +0000 Subject: r10007: Merge data_blk and data_len member of registry_value into a DATA_BLOB. Fix handling of REG_DWORD in the LDB backend. Fix a couple of warnings (This used to be commit 709fdc7ebf5a77cfb50359fad978884777decc3b) --- source4/lib/registry/TODO | 2 ++ source4/lib/registry/common/reg_interface.c | 10 ++++----- source4/lib/registry/common/reg_util.c | 34 ++++++++++------------------- source4/lib/registry/reg_backend_ldb.c | 34 ++++++++++++++--------------- source4/lib/registry/reg_backend_nt4.c | 30 ++++++++++++------------- source4/lib/registry/reg_backend_rpc.c | 9 ++++---- source4/lib/registry/reg_backend_w95.c | 5 ++--- source4/lib/registry/regf.idl | 22 ++++++++++--------- source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regpatch.c | 8 ++++--- source4/lib/registry/tools/regshell.c | 2 +- 11 files changed, 75 insertions(+), 83 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 1dea9d2650..3f48d031e1 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -31,3 +31,5 @@ gregedit.c: - support for editing values / adding values / deleting values - support for adding/deleting keys - support for security descriptors + +- pass parsed paths around rather then strings (i.e. just a list of strings) diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 2abe90f2d1..7f745143e6 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -252,7 +252,7 @@ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_OK; } -WERROR reg_key_num_subkeys(struct registry_key *key, int *count) +WERROR reg_key_num_subkeys(struct registry_key *key, uint32_t *count) { if(!key) return WERR_INVALID_PARAM; @@ -277,7 +277,7 @@ WERROR reg_key_num_subkeys(struct registry_key *key, int *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_num_values(struct registry_key *key, int *count) +WERROR reg_key_num_values(struct registry_key *key, uint32_t *count) { if(!key) return WERR_INVALID_PARAM; @@ -416,11 +416,11 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const return WERR_OK; } -WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data) { /* A 'real' set function has preference */ if (key->hive->functions->set_value) - return key->hive->functions->set_value(key, value, type, data, len); + return key->hive->functions->set_value(key, value, type, data); DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name)); return WERR_NOT_SUPPORTED; @@ -501,7 +501,7 @@ WERROR reg_key_valuesizes(struct registry_key *key, uint32_t *max_valnamelen, ui if (value->name) { *max_valnamelen = MAX(*max_valnamelen, strlen(value->name)); } - *max_valbufsize = MAX(*max_valbufsize, value->data_len); + *max_valbufsize = MAX(*max_valbufsize, value->data.length); } i++; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index 65f1167832..a0d4db6f57 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -48,35 +48,25 @@ const char *str_regtype(int type) char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) { - char *asciip; char *ret = NULL; - int i; - if(v->data_len == 0) return talloc_strdup(mem_ctx, ""); + if(v->data.length == 0) return talloc_strdup(mem_ctx, ""); switch (v->data_type) { case REG_EXPAND_SZ: case REG_SZ: - convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data_blk, v->data_len, (void **)&ret); + convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data.data, v->data.length, (void **)&ret); return ret; case REG_BINARY: - ret = talloc_array_size(mem_ctx, 3, v->data_len+1); - asciip = ret; - for (i=0; idata_len; i++) { - int str_rem = v->data_len * 3 - (asciip - ret); - asciip += snprintf(asciip, str_rem, "%02x", *(uint8_t *)(((char *)v->data_blk)+i)); - if (i < v->data_len && str_rem > 0) - *asciip = ' '; asciip++; - } - *asciip = '\0'; + ret = data_blob_hex_string(mem_ctx, &v->data); return ret; case REG_DWORD: - if (*(int *)v->data_blk == 0) + if (*(int *)v->data.data == 0) return talloc_strdup(mem_ctx, "0"); - return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data_blk); + return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data.data); case REG_MULTI_SZ: /* FIXME */ @@ -117,17 +107,17 @@ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *da { case REG_SZ: case REG_EXPAND_SZ: - (*value)->data_len = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), &(*value)->data_blk); + (*value)->data.length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&(*value)->data.data); break; - case REG_DWORD: - (*value)->data_len = sizeof(uint32_t); - (*value)->data_blk = talloc(mem_ctx, uint32_t); - *((uint32_t *)(*value)->data_blk) = strtol(data_str, NULL, 0); + + case REG_DWORD: { + uint32_t tmp = strtol(data_str, NULL, 0); + (*value)->data = data_blob_talloc(mem_ctx, &tmp, 4); + } break; case REG_NONE: - (*value)->data_len = 0; - (*value)->data_blk = NULL; + ZERO_STRUCT((*value)->data); break; default: diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 76ad1facc1..f51c02a286 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -38,7 +38,7 @@ static int ldb_free_hive (void *_hive) return 0; } -static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32_t *type, void **data, int *len) +static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32_t *type, DATA_BLOB *data) { const struct ldb_val *val; *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL)); @@ -49,23 +49,22 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c { case REG_SZ: case REG_EXPAND_SZ: - *len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, data); + data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data); break; - case REG_DWORD: - *len = 4; - *data = talloc(mem_ctx, uint32_t); - SIVAL(*data, 0, strtol(val->data, NULL, 0)); + case REG_DWORD: { + uint32_t tmp = strtoul((char *)val->data, NULL, 0); + *data = data_blob_talloc(mem_ctx, &tmp, 4); + } break; default: - *data = talloc_memdup(mem_ctx, val->data, val->length); - *len = val->length; + *data = data_blob_talloc(mem_ctx, val->data, val->length); break; } } -static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, void *data, int len) +static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data) { struct ldb_val val; struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message); @@ -76,16 +75,15 @@ static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CT switch (type) { case REG_SZ: case REG_EXPAND_SZ: - val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, data, len, &val.data); + val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val.data); ldb_msg_add_value(ctx, msg, "data", &val); break; + case REG_DWORD: - ldb_msg_add_string(ctx, msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data, 0))); + ldb_msg_add_string(ctx, msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0))); break; default: - val.length = len; - val.data = data; - ldb_msg_add_value(ctx, msg, "data", &val); + ldb_msg_add_value(ctx, msg, "data", &data); } @@ -177,7 +175,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, *subkey = talloc(mem_ctx, struct registry_key); talloc_set_destructor(*subkey, reg_close_ldb_key); - (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data); + (*subkey)->name = talloc_strdup(mem_ctx, (char *)el->values[0].data); (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data); (*subkey)->last_mod = 0; /* TODO: we need to add this to the ldb backend properly */ @@ -205,7 +203,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i *value = talloc(mem_ctx, struct registry_value); - reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data_blk, &(*value)->data_len); + reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data); return WERR_OK; } @@ -333,7 +331,7 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) return WERR_OK; } -static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32_t type, void *data, int len) +static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data) { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message *msg; @@ -341,7 +339,7 @@ static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint int ret; TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); - msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data, len); + msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data); msg->dn = ldb_dn_build_child(msg, "value", name, kd->dn); diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index e07534884c..06c0d78c85 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -624,7 +624,7 @@ static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) { REGF *regf = h->backend_data; - SMB_REG_ASSERT(regf); + SMB_ASSERT(regf); if (!regf->base) { /* Try to mmap etc the file */ @@ -650,7 +650,7 @@ static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) * header */ - SMB_REG_ASSERT(regf->base != NULL); + SMB_ASSERT(regf->base != NULL); return (REGF_HDR *)regf->base; } @@ -828,7 +828,7 @@ static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int /* Here, we have an item in the map that has been reserved, or tmp==NULL. */ - SMB_REG_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); + SMB_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); /* * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the @@ -870,10 +870,10 @@ static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_prev_off = IVAL(&sk_hdr->prev_off,0); tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off); - SMB_REG_ASSERT(tmp->prev != NULL); + SMB_ASSERT(tmp->prev != NULL); sk_next_off = IVAL(&sk_hdr->next_off,0); tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off); - SMB_REG_ASSERT(tmp->next != NULL); + SMB_ASSERT(tmp->next != NULL); return tmp; } @@ -934,9 +934,7 @@ static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR memcpy(dtmp, &dat_off, dat_len); } - - tmp->data_blk = dtmp; - tmp->data_len = dat_len; + tmp->data = data_blob_talloc(mem_ctx, dtmp, dat_len); } *value = tmp; @@ -968,14 +966,14 @@ static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) return WERR_OK; } -static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, int *count) +static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, uint32_t *count) { WERROR error; error = lf_verify(h, lf_hdr, size); if(!W_ERROR_IS_OK(error)) return error; - SMB_REG_ASSERT(size < 0); + SMB_ASSERT(size < 0); *count = SVAL(&lf_hdr->key_count,0); DEBUG(2, ("Key Count: %u\n", *count)); @@ -1004,7 +1002,7 @@ static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_ error = lf_verify(parent->hive, lf_hdr, size); if(!W_ERROR_IS_OK(error)) return error; - SMB_REG_ASSERT(size < 0); + SMB_ASSERT(size < 0); count = SVAL(&lf_hdr->key_count,0); DEBUG(2, ("Key Count: %u\n", count)); @@ -1035,7 +1033,7 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk return WERR_INVALID_PARAM; } - SMB_REG_ASSERT(size < 0); + SMB_ASSERT(size < 0); namlen = SVAL(&nk_hdr->nam_len,0); clsname_len = SVAL(&nk_hdr->clsnam_len,0); @@ -1059,7 +1057,7 @@ static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk /* Fish out the key name and process the LF list */ - SMB_REG_ASSERT(namlen < sizeof(key_name)); + SMB_ASSERT(namlen < sizeof(key_name)); strncpy(key_name, nk_hdr->key_nam, namlen); key_name[namlen] = '\0'; @@ -1194,7 +1192,7 @@ static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) if (!regf || !size || !off) return NULL; - SMB_REG_ASSERT(regf->blk_head != NULL); + SMB_ASSERT(regf->blk_head != NULL); /* * round up size to include header and then to 8-byte boundary @@ -1653,7 +1651,7 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) } -static WERROR nt_num_subkeys(struct registry_key *k, int *num) +static WERROR nt_num_subkeys(struct registry_key *k, uint32_t *num) { REGF *regf = k->hive->backend_data; LF_HDR *lf_hdr; @@ -1670,7 +1668,7 @@ static WERROR nt_num_subkeys(struct registry_key *k, int *num) return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); } -static WERROR nt_num_values(struct registry_key *k, int *count) +static WERROR nt_num_values(struct registry_key *k, uint32_t *count) { NK_HDR *nk_hdr = k->backend_data; *count = IVAL(&nk_hdr->val_cnt,0); diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 44de3bcd77..a00accc6be 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -204,8 +204,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p *value = talloc(mem_ctx, struct registry_value); (*value)->name = talloc_strdup(mem_ctx, r.out.name->name); (*value)->data_type = type; - (*value)->data_len = *r.out.length; - (*value)->data_blk = talloc_memdup(mem_ctx, r.out.value, *r.out.length); + (*value)->data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length); return WERR_OK; } @@ -318,7 +317,8 @@ static WERROR rpc_del_key(struct registry_key *parent, const char *name) return r.out.result; } -static WERROR rpc_num_values(struct registry_key *key, int *count) { +static WERROR rpc_num_values(struct registry_key *key, uint32_t *count) +{ struct rpc_key_data *mykeydata = key->backend_data; WERROR error; @@ -331,7 +331,8 @@ static WERROR rpc_num_values(struct registry_key *key, int *count) { return WERR_OK; } -static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { +static WERROR rpc_num_subkeys(struct registry_key *key, uint32_t *count) +{ struct rpc_key_data *mykeydata = key->backend_data; WERROR error; diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index 45b6105801..03460052da 100644 --- a/source4/lib/registry/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -303,7 +303,7 @@ static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key return WERR_NO_MORE_ITEMS; } -static WERROR w95_num_values(struct registry_key *k, int *count) +static WERROR w95_num_values(struct registry_key *k, uint32_t *count) { RGKN_KEY *rgkn_key = k->backend_data; RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); @@ -335,8 +335,7 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i *value = talloc(mem_ctx, struct registry_value); (*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len); - (*value)->data_len = curval->data_len; - (*value)->data_blk = talloc_memdup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); + (*value)->data = data_blob_talloc(mem_ctx, curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len); (*value)->data_type = curval->type; return WERR_OK; diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl index 8bef15c79e..03f63debc8 100644 --- a/source4/lib/registry/regf.idl +++ b/source4/lib/registry/regf.idl @@ -13,17 +13,18 @@ interface regf { - typedef struct { - uint32 major; - uint32 minor; - uint32 release; - uint32 build; - } regf_version; - - /* 1.3.0.1 for WinNT 4 + /* + * Registry version number + * 1.3.0.1 for WinNT 4 * 1.5.0.1 for WinXP */ + typedef struct { + [value(1)] uint32 major; + [value(3)] uint32 minor; + [value(0)] uint32 release; + [value(1)] uint32 build; + } regf_version; /* "regf" is obviously the abbreviation for "Registry file". "regf" is the @@ -70,7 +71,7 @@ interface regf typedef enum { REG_ROOT_KEY = 0x20, - REG_SUB_KEY = 0x2C, + REG_SUB_KEY = 0x2C, REG_SYM_LINK = 0x10 } reg_key_type; @@ -90,7 +91,7 @@ interface regf uint32 num_values; uint32 values_offset; uint32 sk_offset; - uint32 clsnam_offset; + uint32 clsname_offset; uint32 unk4[5]; uint16 name_length; uint16 clsname_length; @@ -112,6 +113,7 @@ interface regf uint32 base37; /* base37 of key name */ } lh_hash; + /* Subkey listing with hash of first 4 characters */ typedef struct { uint16 key_count; lh_hash hashes[key_count]; diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index a9d189c033..307ec3793e 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -72,7 +72,7 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); - if ((W_ERROR_IS_OK(error2) && (v2->data_len != v1->data_len || memcmp(v1->data_blk, v2->data_blk, v1->data_len))) + if ((W_ERROR_IS_OK(error2) && data_blob_equal(&v1->data, &v2->data)) || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { fprintf(out, "\"%s\"=%s:%s\n", v1->name, str_regtype(v1->data_type), reg_val_data_string(mem_ctx, v1)); } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index c2f01ce5b4..5f7d4376d4 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -704,9 +704,11 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd DEBUG(0, ("Error removing value '%s'\n", val->name)); } modified = True; - } - else { - if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, val->val, strlen(val->val)))) { + } else { + DATA_BLOB blob; + blob.data = (uint8_t *)val->val; + blob.length = strlen(val->val); + if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, blob))) { DEBUG(0, ("Error adding new value '%s'\n", val->name)); continue; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 108cc17336..496b9dc7e5 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -80,7 +80,7 @@ static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context } else { struct registry_value *val; if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val)) { - WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data_blk, val->data_len); + WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data); if (!W_ERROR_IS_OK(error)) { fprintf(stderr, "Error setting value: %s\n", win_errstr(error)); return NULL; -- cgit From 102a6ec95b2487d4ef13de2120be00e2818cce23 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 19:43:35 +0000 Subject: r10009: Fix bug in uint8 parsing functions (This used to be commit abb0db12185a3b3ef7da16fa3d742336afeb8ef0) --- source4/lib/tdr/tdr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index c16a05ecf0..e55060da25 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -36,9 +36,11 @@ #define TDR_BE(tdr) ((tdr)->flags & TDR_BIG_ENDIAN) +#define TDR_CVAL(tdr, ofs) CVAL(tdr->data.data,ofs) #define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data.data,ofs):SVAL(tdr->data.data,ofs)) #define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data.data,ofs):IVAL(tdr->data.data,ofs)) #define TDR_IVALS(tdr, ofs) (TDR_BE(tdr)?RIVALS(tdr->data.data,ofs):IVALS(tdr->data.data,ofs)) +#define TDR_SCVAL(tdr, ofs, v) SCVAL(tdr->data.data,ofs,v) #define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSSVAL(tdr->data.data,ofs,v); } else SSVAL(tdr->data.data,ofs,v); } while (0) #define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data.data,ofs,v); } else SIVAL(tdr->data.data,ofs,v); } while (0) #define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVALS(tdr->data.data,ofs,v); } else SIVALS(tdr->data.data,ofs,v); } while (0) @@ -60,7 +62,7 @@ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) { TDR_PULL_NEED_BYTES(tdr, 1); - SCVAL(tdr->data.data, tdr->offset, *v); + *v = TDR_CVAL(tdr, tdr->offset); tdr->offset += 1; return NT_STATUS_OK; } @@ -68,7 +70,7 @@ NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v) { TDR_PUSH_NEED_BYTES(tdr, 1); - SCVAL(tdr->data.data, tdr->offset, *v); + TDR_SCVAL(tdr, tdr->offset, *v); tdr->offset += 1; return NT_STATUS_OK; } -- cgit From 6a2c9e729fc8f576eacb7518d379839edf25d4e1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 22:56:02 +0000 Subject: r10013: Support zero-sized strings. (This used to be commit cf3be71c33ec8e43c883ce05fd1a63d1178446ad) --- source4/lib/tdr/tdr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index e55060da25..7f42d0cf15 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -143,6 +143,11 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, } } + if (length == 0) { + *v = talloc_strdup(tdr, ""); + return NT_STATUS_OK; + } + TDR_PULL_NEED_BYTES(tdr, el_size*length); ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v)); -- cgit From 40cbd4625ae7f9799238594faa4f8cc54ead72e4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 22:58:04 +0000 Subject: r10015: Change the NT4 registry backend to use the IDL-generate parse functions. (This used to be commit 0ad46ef804c0654e927f9c14ea93c45f9e3c718c) --- source4/lib/registry/config.mk | 10 + source4/lib/registry/reg_backend_nt4.c | 1815 ++++---------------------------- source4/lib/registry/regf.idl | 61 +- 3 files changed, 257 insertions(+), 1629 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index c533e17ea9..a1bb62f7df 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -7,9 +7,19 @@ INIT_FUNCTION = registry_nt4_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ lib/registry/reg_backend_nt4.o +REQUIRED_SUBSYSTEMS = TDR_REGF # End MODULE registry_nt4 ################################################ +[SUBSYSTEM::TDR_REGF] +REQUIRED_SUBSYSTEMS = TDR +NOPROTO = YES +INIT_OBJ_FILES = lib/registry/tdr_regf.o + +lib/registry/tdr_regf.c: lib/registry/regf.idl + @echo "Compiling lib/registry/regf.idl" + @./pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl + ################################################ # Start MODULE registry_w95 [MODULE::registry_w95] diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 06c0d78c85..e0f5ccd08c 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -1,7 +1,7 @@ /* - Samba Unix/Linux SMB client utility libeditreg.c - Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com - Copyright (C) 2003-2005 Jelmer Vernooij, jelmer@samba.org + Samba CIFS implementation + Registry backend for REGF files + Copyright (C) 2005 Jelmer Vernooij, jelmer@samba.org 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 @@ -17,1720 +17,331 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/************************************************************************* - - A utility to edit a Windows NT/2K etc registry file. - - Many of the ideas in here come from other people and software. - I first looked in Wine in misc/registry.c and was also influenced by - http://www.wednesday.demon.co.uk/dosreg.html - - Which seems to contain comments from someone else. I reproduce them here - incase the site above disappears. It actually comes from - http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt. - - The goal here is to read the registry into memory, manipulate it, and then - write it out if it was changed by any actions of the user. - -The windows NT registry has 2 different blocks, where one can occur many -times... - -the "regf"-Block -================ - -"regf" is obviously the abbreviation for "Registry file". "regf" is the -signature of the header-block which is always 4kb in size, although only -the first 64 bytes seem to be used and a checksum is calculated over -the first 0x200 bytes only! - -Offset Size Contents -0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 -0x00000004 D-Word ???? //see struct REG_HANDLE -0x00000008 D-Word ???? Always the same value as at 0x00000004 -0x0000000C Q-Word last modify date in WinNT date-format -0x00000014 D-Word 1 -0x00000018 D-Word 3 -0x0000001C D-Word 0 -0x00000020 D-Word 1 -0x00000024 D-Word Offset of 1st key record -0x00000028 D-Word Size of the data-blocks (Filesize-4kb) -0x0000002C D-Word 1 -0x000001FC D-Word Sum of all D-Words from 0x00000000 to -0x000001FB //XOR of all words. Nigel - -I have analyzed more registry files (from multiple machines running -NT 4.0 german version) and could not find an explanation for the values -marked with ???? the rest of the first 4kb page is not important... - -the "hbin"-Block -================ -hbin probably means hive-bin (what bin stands for I don't know) -This block is always a multiple -of 4kb in size. - -Inside these hbin-blocks the different records are placed. The memory- -management looks like a C-compiler heap management to me... - -hbin-Header -=========== -Offset Size Contents -0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 -0x0004 D-Word Offset from the 1st hbin-Block -0x0008 D-Word Offset to the next hbin-Block -0x001C D-Word Block-size - -The values in 0x0008 and 0x001C should be the same, so I don't know -if they are correct or swapped... - -From offset 0x0020 inside a hbin-block data is stored with the following -format: - -Offset Size Contents -0x0000 D-Word Data-block size //this size must be a -multiple of 8. Nigel -0x0004 ???? Data - -If the size field is negative (bit 31 set), the corresponding block -is free and has a size of -blocksize! - -That does not seem to be true. All block lengths seem to be negative! -(Richard Sharpe) - -The data is stored as one record per block. Block size is a multiple -of 4 and the last block reaches the next hbin-block, leaving no room. - -(That also seems incorrect, in that the block size if a multiple of 8. -That is, the block, including the 4 byte header, is always a multiple of -8 bytes. Richard Sharpe.) - -Records in the hbin-blocks -========================== - -nk-Record - - The nk-record can be treated as a combination of tree-record and - key-record of the win 95 registry. - -lf-Record - - The lf-record is the counterpart to the RGKN-record (the - hash-function) - -vk-Record - - The vk-record consists information to a single value (value key). - -sk-Record - - sk (? Security Key ?) is the ACL of the registry. - -Value-Lists - - The value-lists contain information about which values are inside a - sub-key and don't have a header. - -Datas - - The datas of the registry are (like the value-list) stored without a - header. - -All offset-values are relative to the first hbin-block and point to the -block-size field of the record-entry. to get the file offset, you have to add -the header size (4kb) and the size field (4 bytes)... - -the nk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"nk" = 0x6B6E -0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel -0x0004 Q-Word write-date/time in windows nt notation -0x0010 D-Word Offset of Owner/Parent key -0x0014 D-Word number of sub-Keys -0x001C D-Word Offset of the sub-key lf-Records -0x0024 D-Word number of values -0x0028 D-Word Offset of the Value-List -0x002C D-Word Offset of the sk-Record - -0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel -0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel -0x0048 Word name-length -0x004A Word class-name length -0x004C ???? key-name - -the Value-List -============== -Offset Size Contents -0x0000 D-Word Offset 1st Value -0x0004 D-Word Offset 2nd Value -0x???? D-Word Offset nth Value - -To determine the number of values, you have to look at the owner-nk-record! - -The vk-Record -============= -Offset Size Contents -0x0000 Word ID: ASCII-"vk" = 0x6B76 -0x0002 Word name length -0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel -0x0008 D-Word Offset of Data -0x000C D-Word Type of value -0x0010 Word Flag -0x0012 Word Unused (data-trash) -0x0014 ???? Name - -If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default) - -If the data-size is lower 5, the data-offset value is used to store the data itself! - -The data-types -============== -Wert Beteutung -0x0001 RegSZ: character string (in UNICODE!) -0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!) -0x0003 RegBin: raw-binary value -0x0004 RegDWord: Dword -0x0007 RegMultiSZ: multiple strings, seperated with 0 - (UNICODE!) - -The "lf"-record -=============== -Offset Size Contents -0x0000 Word ID: ASCII-"lf" = 0x666C -0x0002 Word number of keys -0x0004 ???? Hash-Records - -Hash-Record -=========== -Offset Size Contents -0x0000 D-Word Offset of corresponding "nk"-Record -0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv! - -Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the -key-name you have to change the hash-value too! - -//These hashrecords must be sorted low to high within the lf record. Nigel. - -The "sk"-block -============== -(due to the complexity of the SAM-info, not clear jet) -(This is just a self-relative security descriptor in the data. R Sharpe.) - - -Offset Size Contents -0x0000 Word ID: ASCII-"sk" = 0x6B73 -0x0002 Word Unused -0x0004 D-Word Offset of previous "sk"-Record -0x0008 D-Word Offset of next "sk"-Record -0x000C D-Word usage-counter -0x0010 D-Word Size of "sk"-record in bytes -???? //standard self -relative security desciptor. Nigel -???? ???? Security and auditing settings... -???? - -The usage counter counts the number of references to this -"sk"-record. You can use one "sk"-record for the entire registry! - -Windows nt date/time format -=========================== -The time-format is a 64-bit integer which is incremented every -0,0000001 seconds by 1 (I don't know how accurate it realy is!) -It starts with 0 at the 1st of january 1601 0:00! All values are -stored in GMT time! The time-zone is important to get the real -time! - -Common values for win95 and win-nt -================================== -Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF). -If a value has no name (length=0, flag(bit 0)=0), it is treated as the -"Default" entry... -If a value has no data (length=0), it is displayed as empty. - -simplyfied win-3.?? registry: -============================= - -+-----------+ -| next rec. |---+ +----->+------------+ -| first sub | | | | Usage cnt. | -| name | | +-->+------------+ | | length | -| value | | | | next rec. | | | text |------->+-------+ -+-----------+ | | | name rec. |--+ +------------+ | xxxxx | - +------------+ | | value rec. |-------->+------------+ +-------+ - v | +------------+ | Usage cnt. | -+-----------+ | | length | -| next rec. | | | text |------->+-------+ -| first sub |------+ +------------+ | xxxxx | -| name | +-------+ -| value | -+-----------+ - -Greatly simplyfied structure of the nt-registry: -================================================ - -+---------------------------------------------------------------+ -| | -v | -+---------+ +---------->+-----------+ +----->+---------+ | -| "nk" | | | lf-rec. | | | nk-rec. | | -| ID | | | # of keys | | | parent |---+ -| Date | | | 1st key |--+ | .... | -| parent | | +-----------+ +---------+ -| suk-keys|-----+ -| values |--------------------->+----------+ -| SK-rec. |---------------+ | 1. value |--> +----------+ -| class |--+ | +----------+ | vk-rec. | -+---------+ | | | .... | - v | | data |--> +-------+ - +------------+ | +----------+ | xxxxx | - | Class name | | +-------+ - +------------+ | - v - +---------+ +---------+ - +----->| next sk |--->| Next sk |--+ - | +---| prev sk |<---| prev sk | | - | | | .... | | ... | | - | | +---------+ +---------+ | - | | ^ | - | | | | - | +--------------------+ | - +----------------------------------+ - ---------------------------------------------------------------------------- - -Hope this helps.... (Although it was "fun" for me to uncover this things, - it took me several sleepless nights ;) - - B.D. - -*************************************************************************/ - #include "includes.h" #include "registry.h" #include "system/filesys.h" -#include "system/shmem.h" - -#define REG_KEY_LIST_SIZE 10 -#define FLAG_HAS_NAME 0x01 -/*FIXME*/ +#include "lib/registry/tdr_regf.h" /* - * Structures for dealing with the on-disk format of the registry + * Read HBIN blocks into memory */ -const char *def_owner_sid_str = NULL; - -/* - * These definitions are for the in-memory registry structure. - * It is a tree structure that mimics what you see with tools like regedit - */ - - -/* - * Definition of a Key. It has a name, classname, date/time last modified, - * sub-keys, values, and a security descriptor - */ - -#define REG_ROOT_KEY 1 -#define REG_SUB_KEY 2 -#define REG_SYM_LINK 3 - -/* - * All of the structures below actually have a four-byte length before them - * which always seems to be negative. The following macro retrieves that - * size as an integer - */ - -#define BLK_SIZE(b) ((int)*(int *)(((int *)b)-1)) - -typedef struct sk_struct SK_HDR; -/* - * This structure keeps track of the output format of the registry - */ -#define REG_OUTBLK_HDR 1 -#define REG_OUTBLK_HBIN 2 - -typedef struct regf_block { - uint32_t REGF_ID; /* regf */ - uint32_t update_counter1; - uint32_t update_counter2; - uint32_t tim1, tim2; - uint32_t uk3; /* 1 */ - uint32_t uk4; /* 3 */ - uint32_t uk5; /* 0 */ - uint32_t uk6; /* 1 */ - uint32_t first_key; /* offset */ - uint32_t dblk_size; - uint32_t uk7; /* 1 */ - wchar_t filename[64]; - uint32_t unused[83]; - uint32_t chksum; /* Checksum of first 0x200 bytes */ -} REGF_HDR; - -typedef struct hbin_sub_struct { - uint32_t dblocksize; - char data[1]; -} HBIN_SUB_HDR; - -typedef struct hbin_struct { - uint32_t HBIN_ID; /* hbin */ - uint32_t off_from_first; - uint32_t off_to_next; - uint32_t uk1; - uint32_t uk2; - uint32_t uk3; - uint32_t uk4; - uint32_t blk_size; - HBIN_SUB_HDR hbin_sub_hdr; -} HBIN_HDR; - -typedef struct nk_struct { - uint16_t NK_ID; - uint16_t type; - uint32_t t1, t2; - uint32_t uk1; - uint32_t own_off; - uint32_t subk_num; - uint32_t uk2; - uint32_t lf_off; - uint32_t uk3; - uint32_t val_cnt; - uint32_t val_off; - uint32_t sk_off; - uint32_t clsnam_off; - uint32_t unk4[4]; - uint32_t unk5; - uint16_t nam_len; - uint16_t clsnam_len; - char key_nam[1]; /* Actual length determined by nam_len */ -} NK_HDR; - -struct sk_struct { - uint16_t SK_ID; - uint16_t uk1; - uint32_t prev_off; - uint32_t next_off; - uint32_t ref_cnt; - uint32_t rec_size; - char sec_desc[1]; +struct regf_data { + DATA_BLOB data; + struct hbin_block **hbins; }; -typedef struct key_sec_desc_s { - struct key_sec_desc_s *prev, *next; - int ref_cnt; - int state; - int offset; - SK_HDR *sk_hdr; /* This means we must keep the registry in memory */ - struct security_descriptor *sec_desc; -} KEY_SEC_DESC; - -/* A map of sk offsets in the regf to KEY_SEC_DESCs for quick lookup etc */ -typedef struct sk_map_s { - int sk_off; - KEY_SEC_DESC *key_sec_desc; -} SK_MAP; - -typedef struct vk_struct { - uint16_t VK_ID; - uint16_t nam_len; - uint32_t dat_len; /* If top-bit set, offset contains the data */ - uint32_t dat_off; - uint32_t dat_type; - uint16_t flag; /* =1, has name, else no name (=Default). */ - uint16_t unk1; - char dat_name[1]; /* Name starts here ... */ -} VK_HDR; - -typedef uint32_t VL_TYPE[1]; /* Value list is an array of vk rec offsets */ - -typedef struct hash_struct { - uint32_t nk_off; - char hash[4]; -} HASH_REC; - - -typedef struct lf_struct { - uint16_t LF_ID; - uint16_t key_count; - struct hash_struct hr[1]; /* Array of hash records, depending on key_count */} LF_HDR; - - - /* - * This structure keeps track of the output format of the registry + * Validate a regf header + * For now, do nothing, but we should check the checksum */ -#define REG_OUTBLK_HDR 1 -#define REG_OUTBLK_HBIN 2 - -typedef struct hbin_blk_s { - int type, size; - struct hbin_blk_s *next; - char *data; /* The data block */ - uint_t file_offset; /* Offset in file */ - uint_t free_space; /* Amount of free space in block */ - uint_t fsp_off; /* Start of free space in block */ - int complete, stored; -} HBIN_BLK; - -typedef struct regf_struct_s { - int reg_type; - int fd; - struct stat sbuf; - char *base; - BOOL modified; - NTTIME last_mod_time; - NK_HDR *first_key; - int sk_count, sk_map_size; - SK_MAP *sk_map; - const char *owner_sid_str; - struct security_descriptor *def_sec_desc; - /* - * These next pointers point to the blocks used to contain the - * keys when we are preparing to write them to a file - */ - HBIN_BLK *blk_head, *blk_tail, *free_space; -} REGF; - -static uint32_t str_to_dword(const char *a) { +static uint32_t regf_hdr_checksum(const uint8_t *buffer) +{ + uint32_t checksum = 0, x; int i; - unsigned long ret = 0; - for(i = strlen(a)-1; i >= 0; i--) { - ret = ret * 0x100 + a[i]; + + for (i = 0; i < 0x01FB; i+= 4) { + x = IVAL(buffer, i); + checksum ^= x; } - return ret; -} - -#if 0 -/* - * Create an ACE - */ -static BOOL nt_create_ace(SEC_ACE *ace, int type, int flags, uint32_t perms, const char *sid) -{ - DOM_SID s; - SEC_ACCESS access; - access.mask = perms; - if(!string_to_sid(&s, sid))return False; - init_sec_ace(ace, &s, type, access, flags); - return True; + return checksum; } -/* - * Create a default ACL - */ -static SEC_ACL *nt_create_default_acl(struct registry_hive *regf) -{ - SEC_ACE aces[8]; - - if(!nt_create_ace(&aces[0], 0x00, 0x0, 0xF003F, regf->owner_sid_str)) return NULL; - if(!nt_create_ace(&aces[1], 0x00, 0x0, 0xF003F, "S-1-5-18")) return NULL; - if(!nt_create_ace(&aces[2], 0x00, 0x0, 0xF003F, "S-1-5-32-544")) return NULL; - if(!nt_create_ace(&aces[3], 0x00, 0x0, 0x20019, "S-1-5-12")) return NULL; - if(!nt_create_ace(&aces[4], 0x00, 0x0B, GENERIC_RIGHT_ALL_ACCESS, regf->owner_sid_str)) return NULL; - if(!nt_create_ace(&aces[5], 0x00, 0x0B, 0x10000000, "S-1-5-18")) return NULL; - if(!nt_create_ace(&aces[6], 0x00, 0x0B, 0x10000000, "S-1-5-32-544")) return NULL; - if(!nt_create_ace(&aces[7], 0x00, 0x0B, 0x80000000, "S-1-5-12")) return NULL; - - return make_sec_acl(regf->mem_ctx, 2, 8, aces); -} - -/* - * Create a default security descriptor. We pull in things from env - * if need be - */ -static SEC_DESC *nt_create_def_sec_desc(struct registry_hive *regf) -{ - SEC_DESC *tmp; - - tmp = malloc_p(SEC_DESC); - - tmp->revision = 1; - tmp->type = SEC_DESC_SELF_RELATIVE | SEC_DESC_DACL_PRESENT; - if (!string_to_sid(tmp->owner_sid, "S-1-5-32-544")) goto error; - if (!string_to_sid(tmp->grp_sid, "S-1-5-18")) goto error; - tmp->sacl = NULL; - tmp->dacl = nt_create_default_acl(regf); - - return tmp; - - error: - if (tmp) nt_delete_sec_desc(tmp); - return NULL; -} - -/* - * We will implement inheritence that is based on what the parent's SEC_DESC - * says, but the Owner and Group SIDs can be overwridden from the command line - * and additional ACEs can be applied from the command line etc. - */ -static KEY_SEC_DESC *nt_inherit_security(struct registry_key *key) +static DATA_BLOB regf_get_data(const struct regf_data *data, uint32_t offset) { - - if (!key) return NULL; - return key->security; -} - -/* - * Create an initial security descriptor and init other structures, if needed - * We assume that the initial security stuff is empty ... - */ -static KEY_SEC_DESC *nt_create_init_sec(struct registry_hive *h) -{ - REGF *regf = h->backend_data; - KEY_SEC_DESC *tsec = NULL; - - tsec = malloc_p(KEY_SEC_DESC); - - tsec->ref_cnt = 1; - tsec->state = SEC_DESC_NBK; - tsec->offset = 0; - - tsec->sec_desc = regf->def_sec_desc; - - return tsec; + int i; + DATA_BLOB ret; + ret.data = NULL; + ret.length = 0; + + for (i = 0; data->hbins[i]; i++) { + if (offset >= data->hbins[i]->offset_from_first && + offset < data->hbins[i]->offset_from_first+ + data->hbins[i]->offset_to_next) + break; + } + + if (data->hbins[i] == NULL) { + DEBUG(1, ("Can't find HBIN containing 0x%4x\n", offset)); + return ret; + } + + ret.length = IVAL(data->hbins[i]->data, + offset - data->hbins[i]->offset_from_first - 0x20); + if (ret.length & 0x80000000) { + /* absolute value */ + ret.length = (ret.length ^ 0xffffffff) + 1; + } + ret.data = data->hbins[i]->data + + (offset - data->hbins[i]->offset_from_first - 0x20) + 4; + + return ret; } -#endif -/* - * Get the starting record for NT Registry file - */ -/* - * Where we keep all the regf stuff for one registry. - * This is the structure that we use to tie the in memory tree etc - * together. By keeping separate structs, we can operate on different - * registries at the same time. - * Currently, the SK_MAP is an array of mapping structure. - * Since we only need this on input and output, we fill in the structure - * as we go on input. On output, we know how many SK items we have, so - * we can allocate the structure as we need to. - * If you add stuff here that is dynamically allocated, add the - * appropriate free statements below. - */ - -#define REG_HANDLE_REGTYPE_NONE 0 -#define REG_HANDLE_REGTYPE_NT 1 -#define REG_HANDLE_REGTYPE_W9X 2 - -#define TTTONTTIME(r, t1, t2) (r)->last_mod_time = (t1) | (((uint64_t)(t2)) << 32) - -#define REGF_HDR_BLKSIZ 0x1000 - -#define OFF(f) ((f) + REGF_HDR_BLKSIZ + 4) -#define LOCN(base, f) ((base) + OFF(f)) - -/* Get the header of the registry. Return a pointer to the structure - * If the mmap'd area has not been allocated, then mmap the input file - */ -static REGF_HDR *nt_get_regf_hdr(struct registry_hive *h) +static WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) { - REGF *regf = h->backend_data; - SMB_ASSERT(regf); - - if (!regf->base) { /* Try to mmap etc the file */ + struct nk_block *nk = key->backend_data; - if ((regf->fd = open(h->location, O_RDONLY, 0000)) <0) { - return NULL; /* What about errors? */ - } - - if (fstat(regf->fd, ®f->sbuf) < 0) { - return NULL; - } - - regf->base = mmap(0, regf->sbuf.st_size, PROT_READ, MAP_SHARED, regf->fd, 0); - - if ((int)regf->base == 1) { - DEBUG(0,("Could not mmap file: %s, %s\n", h->location, - strerror(errno))); - return NULL; - } - } - - /* - * At this point, regf->base != NULL, and we should be able to read the - * header - */ - - SMB_ASSERT(regf->base != NULL); - - return (REGF_HDR *)regf->base; -} - -/* - * Validate a regf header - * For now, do nothing, but we should check the checksum - */ -static int valid_regf_hdr(REGF_HDR *regf_hdr) -{ - if (!regf_hdr) return 0; - - return 1; -} - -#if 0 - -/* - * Process an SK header ... - * Every time we see a new one, add it to the map. Otherwise, just look it up. - * We will do a simple linear search for the moment, since many KEYs have the - * same security descriptor. - * We allocate the map in increments of 10 entries. - */ - -/* - * Create a new entry in the map, and increase the size of the map if needed - */ -static SK_MAP *alloc_sk_map_entry(struct registry_hive *h, KEY_SEC_DESC *tmp, int sk_off) -{ - REGF *regf = h->backend_data; - if (!regf->sk_map) { /* Allocate a block of 10 */ - regf->sk_map = malloc_array_p(SK_MAP, 10); - regf->sk_map_size = 10; - regf->sk_count = 1; - (regf->sk_map)[0].sk_off = sk_off; - (regf->sk_map)[0].key_sec_desc = tmp; - } - else { /* Simply allocate a new slot, unless we have to expand the list */ - int ndx = regf->sk_count; - if (regf->sk_count >= regf->sk_map_size) { - regf->sk_map = (SK_MAP *)realloc(regf->sk_map, - (regf->sk_map_size + 10)*sizeof(SK_MAP)); - if (!regf->sk_map) { - free(tmp); - return NULL; - } - /* - * ndx already points at the first entry of the new block - */ - regf->sk_map_size += 10; - } - (regf->sk_map)[ndx].sk_off = sk_off; - (regf->sk_map)[ndx].key_sec_desc = tmp; - regf->sk_count++; - } - return regf->sk_map; + *count = nk->num_subkeys; + + return WERR_OK; } -/* - * Search for a KEY_SEC_DESC in the sk_map, but don't create one if not - * found - */ -KEY_SEC_DESC *lookup_sec_key(SK_MAP *sk_map, int count, int sk_off) +static WERROR regf_num_values (struct registry_key *key, uint32_t *count) { - int i; + struct nk_block *nk = key->backend_data; - if (!sk_map) return NULL; - - for (i = 0; i < count; i++) { - - if (sk_map[i].sk_off == sk_off) - return sk_map[i].key_sec_desc; - - } - - return NULL; + *count = nk->num_values; + return WERR_OK; } -/* - * Allocate a KEY_SEC_DESC if we can't find one in the map - */ -static KEY_SEC_DESC *lookup_create_sec_key(struct registry_hive *h, SK_MAP *sk_map, int sk_off) +static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *regf, uint32_t offset) { - REGF *regf = h->backend_data; - KEY_SEC_DESC *tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off); + DATA_BLOB data = regf_get_data(regf, offset); + struct tdr_pull *pull; + struct registry_key *ret; + struct nk_block *nk; - if (tmp) { - return tmp; - } - else { /* Allocate a new one */ - tmp = malloc_p(KEY_SEC_DESC); - memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ - tmp->state = SEC_DESC_RES; - if (!alloc_sk_map_entry(h, tmp, sk_off)) { - return NULL; - } - return tmp; - } -} - -static SEC_DESC *process_sec_desc(struct registry_hive *regf, SEC_DESC *sec_desc) -{ - SEC_DESC *tmp = NULL; - - tmp = malloc_p(SEC_DESC); - - tmp->revision = SVAL(&sec_desc->revision,0); - tmp->type = SVAL(&sec_desc->type,0); - DEBUG(2, ("SEC_DESC Rev: %0X, Type: %0X\n", tmp->revision, tmp->type)); - DEBUGADD(2, ("SEC_DESC Owner Off: %0X\n", IVAL(&sec_desc->off_owner_sid,0))); - DEBUGADD(2, ("SEC_DESC Group Off: %0X\n", IVAL(&sec_desc->off_grp_sid,0))); - DEBUGADD(2, ("SEC_DESC DACL Off: %0X\n", IVAL(&sec_desc->off_dacl,0))); - tmp->owner_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_owner_sid,0))); - if (!tmp->owner_sid) { - free(tmp); + if (data.data == NULL) { + DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return NULL; } - tmp->grp_sid = sid_dup_talloc(regf->mem_ctx, (DOM_SID *)((char *)sec_desc + IVAL(&sec_desc->off_grp_sid,0))); - if (!tmp->grp_sid) { - free(tmp); - return NULL; - } - - /* Now pick up the SACL and DACL */ - - DEBUG(0, ("%d, %d\n", IVAL(&sec_desc->off_sacl,0), IVAL(&sec_desc->off_dacl,0))); - - if (sec_desc->off_sacl) - tmp->sacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_sacl,0))); - else - tmp->sacl = NULL; - - if (sec_desc->off_dacl) - tmp->dacl = dup_sec_acl(regf->mem_ctx, (SEC_ACL *)((char *)sec_desc + IVAL(&sec_desc->off_dacl,0))); - else - tmp->dacl = NULL; - - return tmp; -} -static KEY_SEC_DESC *process_sk(struct registry_hive *regf, SK_HDR *sk_hdr, int sk_off, int size) -{ - KEY_SEC_DESC *tmp = NULL; - int sk_next_off, sk_prev_off, sk_size; - SEC_DESC *sec_desc; - - if (!sk_hdr) return NULL; + ret = talloc_zero(ctx, struct registry_key); + pull = talloc_zero(ret, struct tdr_pull); + pull->data = data; + nk = talloc(ret, struct nk_block); - if (SVAL(&sk_hdr->SK_ID,0) != str_to_dword("sk")) { - DEBUG(0, ("Unrecognized SK Header ID: %08X, %s\n", (int)sk_hdr, - regf->regfile_name)); + if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, nk))) { + DEBUG(1, ("Error parsing 'nk' record\n")); + talloc_free(ret); return NULL; } - if (-size < (sk_size = IVAL(&sk_hdr->rec_size,0))) { - DEBUG(0, ("Incorrect SK record size: %d vs %d. %s\n", - -size, sk_size, regf->regfile_name)); + if (strcmp(nk->header, "nk") != 0) { + DEBUG(0, ("Expected nk record, got %s\n", nk->header)); + talloc_free(ret); return NULL; } - /* - * Now, we need to look up the SK Record in the map, and return it - * Since the map contains the SK_OFF mapped to KEY_SEC_DESC, we can - * use that - */ - - if (regf->sk_map && - ((tmp = lookup_sec_key(regf->sk_map, regf->sk_count, sk_off)) != NULL) - && (tmp->state == SEC_DESC_OCU)) { - tmp->ref_cnt++; - return tmp; - } - - /* Here, we have an item in the map that has been reserved, or tmp==NULL. */ - - SMB_ASSERT(tmp == NULL || (tmp && tmp->state != SEC_DESC_NON)); - - /* - * Now, allocate a KEY_SEC_DESC, and parse the structure here, and add the - * new KEY_SEC_DESC to the mapping structure, since the offset supplied is - * the actual offset of structure. The same offset will be used by - * all future references to this structure - * We could put all this unpleasantness in a function. - */ - - if (!tmp) { - tmp = malloc_p(KEY_SEC_DESC); - memset(tmp, 0, sizeof(KEY_SEC_DESC)); - - /* - * Allocate an entry in the SK_MAP ... - * We don't need to free tmp, because that is done for us if the - * sm_map entry can't be expanded when we need more space in the map. - */ - - if (!alloc_sk_map_entry(regf, tmp, sk_off)) { - return NULL; - } - } - - tmp->ref_cnt++; - tmp->state = SEC_DESC_OCU; - - /* - * Now, process the actual sec desc and plug the values in - */ + ret->name = talloc_steal(ret, nk->key_name); + ret->last_mod = nk->last_change; + ret->class_name = NULL; /* FIXME: get somehow using clsname_offset */ + ret->backend_data = nk; - sec_desc = (SEC_DESC *)&sk_hdr->sec_desc[0]; - tmp->sec_desc = process_sec_desc(regf, sec_desc); - - /* - * Now forward and back links. Here we allocate an entry in the sk_map - * if it does not exist, and mark it reserved - */ - - sk_prev_off = IVAL(&sk_hdr->prev_off,0); - tmp->prev = lookup_create_sec_key(regf, regf->sk_map, sk_prev_off); - SMB_ASSERT(tmp->prev != NULL); - sk_next_off = IVAL(&sk_hdr->next_off,0); - tmp->next = lookup_create_sec_key(regf, regf->sk_map, sk_next_off); - SMB_ASSERT(tmp->next != NULL); - - return tmp; + return ret; } -#endif -/* - * Process a VK header and return a value - */ -static WERROR vk_to_val(TALLOC_CTX *mem_ctx, struct registry_key *parent, VK_HDR *vk_hdr, int size, struct registry_value **value) +static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx, struct registry_value **ret) { - REGF *regf = parent->hive->backend_data; - int nam_len, dat_len, flag, dat_type, dat_off, vk_id; - struct registry_value *tmp = NULL; - - if (!vk_hdr) return WERR_INVALID_PARAM; - - if ((vk_id = SVAL(&vk_hdr->VK_ID,0)) != str_to_dword("vk")) { - DEBUG(0, ("Unrecognized VK header ID: %0X, block: %0X, %s\n", - vk_id, (int)vk_hdr, parent->hive->location)); + struct nk_block *nk = key->backend_data; + struct vk_block *vk; + struct tdr_pull *pull; + uint32_t vk_offset; + DATA_BLOB data; + + if (idx >= nk->num_values) + return WERR_NO_MORE_ITEMS; + + data = regf_get_data(key->hive->backend_data, nk->values_offset); + if (!data.data) { + DEBUG(0, ("Unable to find value list\n")); return WERR_GENERAL_FAILURE; } - nam_len = SVAL(&vk_hdr->nam_len,0); - flag = SVAL(&vk_hdr->flag,0); - dat_type = IVAL(&vk_hdr->dat_type,0); - dat_len = IVAL(&vk_hdr->dat_len,0); /* If top bit, offset contains data */ - dat_off = IVAL(&vk_hdr->dat_off,0); - - tmp = talloc(mem_ctx, struct registry_value); - tmp->data_type = dat_type; - - if (flag & FLAG_HAS_NAME) { - tmp->name = talloc_strndup(mem_ctx, vk_hdr->dat_name, nam_len); - } else { - tmp->name = NULL; + if (data.length < nk->num_values * 4) { + DEBUG(1, ("Value counts mismatch\n")); } - /* - * Allocate space and copy the data as a BLOB - */ - - if (dat_len&0x7FFFFFFF) { - - char *dtmp = talloc_size(mem_ctx, dat_len&0x7FFFFFFF); + vk_offset = IVAL(data.data, idx * 4); - if ((dat_len&0x80000000) == 0) { /* The data is pointed to by the offset */ - char *dat_ptr = LOCN(regf->base, dat_off); - memcpy(dtmp, dat_ptr, dat_len); - } - else { /* The data is in the offset or type */ - /* - * FIXME. - * Some registry files seem to have weird fields. If top bit is set, - * but len is 0, the type seems to be the value ... - * Not sure how to handle this last type for the moment ... - */ - dat_len = dat_len & 0x7FFFFFFF; - memcpy(dtmp, &dat_off, dat_len); - } - - tmp->data = data_blob_talloc(mem_ctx, dtmp, dat_len); + data = regf_get_data(key->hive->backend_data, vk_offset); + if (!data.data) { + DEBUG(0, ("Unable to find value\n")); + return WERR_GENERAL_FAILURE; } - *value = tmp; - return WERR_OK; -} + *ret = talloc_zero(ctx, struct registry_value); + if (!(*ret)) + return WERR_NOMEM; -#if 0 /* unused */ + vk = talloc(*ret, struct vk_block); + if (!vk) + return WERR_NOMEM; + + pull = talloc_zero(*ret, struct tdr_pull); + pull->data = data; -static BOOL vl_verify(VL_TYPE vl, int count, int size) -{ - if(!vl) return False; - if (-size < (count+1)*sizeof(int)){ - DEBUG(0, ("Error in VL header format. Size less than space required. %d\n", -size)); - return False; + if (NT_STATUS_IS_ERR(tdr_pull_vk_block(pull, vk))) { + DEBUG(0, ("Error parsing vk block\n")); + return WERR_GENERAL_FAILURE; } - return True; -} - -#endif -static WERROR lf_verify(struct registry_hive *h, LF_HDR *lf_hdr, int size) -{ - int lf_id; - if ((lf_id = SVAL(&lf_hdr->LF_ID,0)) != str_to_dword("lf")) { - DEBUG(0, ("Unrecognized LF Header format: %0X, Block: %0X, %s.\n", - lf_id, (int)lf_hdr, h->location)); - return WERR_INVALID_PARAM; + (*ret)->name = talloc_steal(*ret, vk->data_name); + (*ret)->data_type = vk->data_type; + if (vk->data_length & 0x80000000) { + vk->data_length &= ~0x80000000; + (*ret)->data.data = (uint8_t *)&vk->data_offset; + (*ret)->data.length = vk->data_length; + } else { + (*ret)->data = regf_get_data(key->hive->backend_data, vk->data_offset); } - return WERR_OK; -} - -static WERROR lf_num_entries(struct registry_hive *h, LF_HDR *lf_hdr, int size, uint32_t *count) -{ - WERROR error; - - error = lf_verify(h, lf_hdr, size); - if(!W_ERROR_IS_OK(error)) return error; - - SMB_ASSERT(size < 0); - - *count = SVAL(&lf_hdr->key_count,0); - DEBUG(2, ("Key Count: %u\n", *count)); - if (*count <= 0) return WERR_INVALID_PARAM; + if ((*ret)->data.length < vk->data_length) { + DEBUG(1, ("Read data less then indicated data length!\n")); + } + return WERR_OK; } - -static WERROR nk_to_key(TALLOC_CTX *, struct registry_hive *regf, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **); - - - -/* - * Process an LF Header and return a list of sub-keys - */ -static WERROR lf_get_entry(TALLOC_CTX *mem_ctx, struct registry_key *parent, LF_HDR *lf_hdr, int size, int n, struct registry_key **key) +static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int idx, struct registry_key **ret) { - REGF *regf = parent->hive->backend_data; - int count, nk_off; - NK_HDR *nk_hdr; - WERROR error; - - if (!lf_hdr) return WERR_INVALID_PARAM; - - error = lf_verify(parent->hive, lf_hdr, size); - if(!W_ERROR_IS_OK(error)) return error; - - SMB_ASSERT(size < 0); + DATA_BLOB data; + struct nk_block *nk = key->backend_data; + uint32_t key_off; - count = SVAL(&lf_hdr->key_count,0); - DEBUG(2, ("Key Count: %u\n", count)); - if (count <= 0) return WERR_GENERAL_FAILURE; - if (n >= count) return WERR_NO_MORE_ITEMS; + if (idx >= nk->num_subkeys) + return WERR_NO_MORE_ITEMS; - nk_off = IVAL(&lf_hdr->hr[n].nk_off,0); - DEBUG(2, ("NK Offset: %0X\n", nk_off)); - nk_hdr = (NK_HDR *)LOCN(regf->base, nk_off); - return nk_to_key(mem_ctx, parent->hive, nk_hdr, BLK_SIZE(nk_hdr), parent, key); -} - -static WERROR nk_to_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, NK_HDR *nk_hdr, int size, struct registry_key *parent, struct registry_key **key) -{ - REGF *regf = h->backend_data; - struct registry_key *tmp = NULL, *own; - int namlen, clsname_len, sk_off, own_off; - uint_t nk_id; - SK_HDR *sk_hdr; - int type; - char key_name[1024]; - - if (!nk_hdr) return WERR_INVALID_PARAM; - - if ((nk_id = SVAL(&nk_hdr->NK_ID,0)) != str_to_dword("nk")) { - DEBUG(0, ("Unrecognized NK Header format: %08X, Block: %0X. %s\n", - nk_id, (int)nk_hdr, parent->hive->location)); - return WERR_INVALID_PARAM; - } - - SMB_ASSERT(size < 0); - - namlen = SVAL(&nk_hdr->nam_len,0); - clsname_len = SVAL(&nk_hdr->clsnam_len,0); - - /* - * The value of -size should be ge - * (sizeof(NK_HDR) - 1 + namlen) - * The -1 accounts for the fact that we included the first byte of - * the name in the structure. clsname_len is the length of the thing - * pointed to by clsnam_off - */ - - if (-size < (sizeof(NK_HDR) - 1 + namlen)) { - DEBUG(0, ("Incorrect NK_HDR size: %d, %0X\n", -size, (int)nk_hdr)); - DEBUG(0, ("Sizeof NK_HDR: %d, name_len %d, clsname_len %d\n", - (int)sizeof(NK_HDR), namlen, clsname_len)); + data = regf_get_data(key->hive->backend_data, nk->subkeys_offset); + if (!data.data) { + DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; } - DEBUG(2, ("NK HDR: Name len: %d, class name len: %d\n", namlen, clsname_len)); + if (!strncmp((char *)data.data, "li", 2)) { + DEBUG(4, ("Subkeys in LI list\n")); + SMB_ASSERT(0); + } else if (!strncmp((char *)data.data, "lf", 2)) { + struct lf_block lf; + struct tdr_pull *pull = talloc_zero(ctx, struct tdr_pull); - /* Fish out the key name and process the LF list */ + DEBUG(10, ("Subkeys in LF list\n")); + pull->data = data; - SMB_ASSERT(namlen < sizeof(key_name)); + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_GENERAL_FAILURE; + } - strncpy(key_name, nk_hdr->key_nam, namlen); - key_name[namlen] = '\0'; + if (lf.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } - type = (SVAL(&nk_hdr->type,0)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); - if(type == REG_ROOT_KEY && parent) { - DEBUG(0,("Root key encountered below root level!\n")); + key_off = lf.hr[idx].nk_off; + + talloc_free(pull); + } else if (!strncmp((char *)data.data, "ri", 2)) { + DEBUG(4, ("Subkeys in RI list\n")); + SMB_ASSERT(0); + } else if (!strncmp((char *)data.data, "lh", 2)) { + DEBUG(4, ("Subkeys in LH list\n")); + SMB_ASSERT(0); + } else { + DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", nk->subkeys_offset, data.data[0], data.data[1])); return WERR_GENERAL_FAILURE; } - tmp = talloc(mem_ctx, struct registry_key); - tmp->name = talloc_strdup(mem_ctx, key_name); - tmp->backend_data = nk_hdr; - - DEBUG(2, ("Key name: %s\n", key_name)); - - /* - * Fish out the class name, it is in UNICODE, while the key name is - * ASCII :-) - */ - - if (clsname_len) { /* Just print in Ascii for now */ - void *clsnamep; - int clsnam_off; - - clsnam_off = IVAL(&nk_hdr->clsnam_off,0); - clsnamep = LOCN(regf->base, clsnam_off); - DEBUG(2, ("Class Name Offset: %0X\n", clsnam_off)); - - pull_ucs2_talloc(mem_ctx, &tmp->class_name, clsnamep); - - DEBUGADD(2,(" Class Name: %s\n", tmp->class_name)); - - } - - /* - * Process the owner offset ... - */ - - own_off = IVAL(&nk_hdr->own_off,0); - own = (struct registry_key *)LOCN(regf->base, own_off); - DEBUG(2, ("Owner Offset: %0X\n", own_off)); - - DEBUGADD(2, (" Owner locn: %0X, Our locn: %0X\n", - (uint_t)own, (uint_t)nk_hdr)); + *ret = regf_get_key (ctx, key->hive->backend_data, key_off); - /* - * We should verify that the owner field is correct ... - * for now, we don't worry ... - */ - - /* - * Also handle the SK header ... - */ - - sk_off = IVAL(&nk_hdr->sk_off,0); - sk_hdr = (SK_HDR *)LOCN(regf->base, sk_off); - DEBUG(2, ("SK Offset: %0X\n", sk_off)); - - if (sk_off != -1) { - -#if 0 - tmp->security = process_sk(regf, sk_hdr, sk_off, BLK_SIZE(sk_hdr)); -#endif - - } - - *key = tmp; return WERR_OK; } -#if 0 /* unused */ - -/* - * Allocate a new hbin block, set up the header for the block etc - */ -static HBIN_BLK *nt_create_hbin_blk(struct registry_hive *h, int size) -{ - REGF *regf = h->backend_data; - HBIN_BLK *tmp; - HBIN_HDR *hdr; - - if (!regf || !size) return NULL; - - /* Round size up to multiple of REGF_HDR_BLKSIZ */ - - size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); - - tmp = malloc_p(HBIN_BLK); - memset(tmp, 0, sizeof(HBIN_BLK)); - - tmp->data = malloc(size); - - memset(tmp->data, 0, size); /* Make it pristine */ - - tmp->size = size; - /*FIXMEtmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size;*/ - - tmp->free_space = size - (sizeof(HBIN_HDR) - sizeof(HBIN_SUB_HDR)); - tmp->fsp_off = size - tmp->free_space; - - /* - * Now, build the header in the data block - */ - hdr = (HBIN_HDR *)tmp->data; - hdr->HBIN_ID = str_to_dword("hbin"); - hdr->off_from_first = tmp->file_offset - REGF_HDR_BLKSIZ; - hdr->off_to_next = tmp->size; - hdr->blk_size = tmp->size; - - /* - * Now link it in - */ - - regf->blk_tail->next = tmp; - regf->blk_tail = tmp; - if (!regf->free_space) regf->free_space = tmp; - - return tmp; -} - -/* - * Allocate a unit of space ... and return a pointer as function param - * and the block's offset as a side effect - */ -static void *nt_alloc_regf_space(struct registry_hive *h, int size, uint_t *off) -{ - REGF *regf = h->backend_data; - int tmp = 0; - void *ret = NULL; - HBIN_BLK *blk; - - if (!regf || !size || !off) return NULL; - - SMB_ASSERT(regf->blk_head != NULL); - - /* - * round up size to include header and then to 8-byte boundary - */ - size = (size + 4 + 7) & ~7; - - /* - * Check if there is space, if none, grab a block - */ - if (!regf->free_space) { - if (!nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) - return NULL; - } - - /* - * Now, chain down the list of blocks looking for free space - */ - - for (blk = regf->free_space; blk != NULL; blk = blk->next) { - if (blk->free_space <= size) { - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret)+4);/* The pointer needs to be to the data struct */ - } - } - - /* - * If we got here, we need to add another block, which might be - * larger than one block -- deal with that later - */ - if (nt_create_hbin_blk(h, REGF_HDR_BLKSIZ)) { - blk = regf->free_space; - tmp = blk->file_offset + blk->fsp_off - REGF_HDR_BLKSIZ; - ret = blk->data + blk->fsp_off; - blk->free_space -= size; - blk->fsp_off += size; - - /* Insert the header */ - ((HBIN_SUB_HDR *)ret)->dblocksize = -size; - - /* - * Fix up the free space ptr - * If it is NULL, we fix it up next time - */ - - if (!blk->free_space) - regf->free_space = blk->next; - - *off = tmp; - return (((char *)ret) + 4);/* The pointer needs to be to the data struct */ - } - - return NULL; -} - -/* - * Store a SID at the location provided - */ -static int nt_store_SID(struct registry_hive *regf, DOM_SID *sid, uint8_t *locn) +static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { + struct regf_data *regf; + struct regf_hdr *regf_hdr; + struct tdr_pull *pull; int i; - uint8_t *p = locn; - - if (!regf || !sid || !locn) return 0; - - *p = sid->sid_rev_num; p++; - *p = sid->num_auths; p++; - - for (i=0; i < 6; i++) { - *p = sid->id_auth[i]; p++; - } - - for (i=0; i < sid->num_auths; i++) { - SIVAL(p, 0, sid->sub_auths[i]); p+=4; - } - - return p - locn; - -} - -static int nt_store_ace(struct registry_hive *regf, SEC_ACE *ace, uint8_t *locn) -{ - int size = 0; - SEC_ACE *reg_ace = (SEC_ACE *)locn; - uint8_t *p; - - if (!regf || !ace || !locn) return 0; - - reg_ace->type = ace->type; - reg_ace->flags = ace->flags; - - /* Deal with the length when we have stored the SID */ - - p = (uint8_t *)®_ace->info.mask; - - SIVAL(p, 0, ace->info.mask); p += 4; - - size = nt_store_SID(regf, &ace->trustee, p); - - size += 8; /* Size of the fixed header */ - - p = (uint8_t *)®_ace->size; - - SSVAL(p, 0, size); - - return size; -} - -/* - * Store an ACL at the location provided - */ -static int nt_store_acl(struct registry_hive *regf, SEC_ACL *acl, uint8_t *locn) { - int size = 0, i; - uint8_t *p = locn, *s; - - if (!regf || !acl || !locn) return 0; - - /* - * Now store the header and then the ACEs ... - */ - - SSVAL(p, 0, acl->revision); - - p += 2; s = p; /* Save this for the size field */ - - p += 2; - - SIVAL(p, 0, acl->num_aces); - - p += 4; - - for (i = 0; i < acl->num_aces; i++) { - size = nt_store_ace(regf, &acl->ace[i], p); - p += size; - } - - size = s - locn; - SSVAL(s, 0, size); - return size; -} - -/* - * Flatten and store the Sec Desc - * Windows lays out the DACL first, but since there is no SACL, it might be - * that first, then the owner, then the group SID. So, we do it that way - * too. - */ -static uint_t nt_store_sec_desc(struct registry_hive *regf, SEC_DESC *sd, char *locn) -{ - SEC_DESC *rsd = (SEC_DESC *)locn; - uint_t size = 0, off = 0; - - if (!regf || !sd || !locn) return 0; - - /* - * Now, fill in the first two fields, then lay out the various fields - * as needed - */ - - rsd->revision = SEC_DESC_REVISION; - rsd->type = SEC_DESC_DACL_PRESENT | SEC_DESC_SELF_RELATIVE; - - off = 4 * sizeof(uint32_t) + 4; - - if (sd->sacl){ - size = nt_store_acl(regf, sd->sacl, (char *)(locn + off)); - rsd->off_sacl = off; - } - else - rsd->off_sacl = 0; - - off += size; - - if (sd->dacl) { - rsd->off_dacl = off; - size = nt_store_acl(regf, sd->dacl, (char *)(locn + off)); - } - else { - rsd->off_dacl = 0; - } - off += size; - - /* Now the owner and group SIDs */ - - if (sd->owner_sid) { - rsd->off_owner_sid = off; - size = nt_store_SID(regf, sd->owner_sid, (char *)(locn + off)); - } - else { - rsd->off_owner_sid = 0; - } - - off += size; - - if (sd->grp_sid) { - rsd->off_grp_sid = off; - size = nt_store_SID(regf, sd->grp_sid, (char *)(locn + off)); - } - else { - rsd->off_grp_sid = 0; - } - - off += size; - - return size; -} - -/* - * Store the security information - * - * If it has already been stored, just get its offset from record - * otherwise, store it and record its offset - */ -static uint_t nt_store_security(struct registry_hive *regf, KEY_SEC_DESC *sec) -{ - int size = 0; - uint_t sk_off; - SK_HDR *sk_hdr; - - if (sec->offset) return sec->offset; - - /* - * OK, we don't have this one in the file yet. We must compute the - * size taken by the security descriptor as a self-relative SD, which - * means making one pass over each structure and figuring it out - */ - -/* FIXME size = sec_desc_size(sec->sec_desc); */ - - /* Allocate that much space */ - - sk_hdr = nt_alloc_regf_space(regf, size, &sk_off); - sec->sk_hdr = sk_hdr; - - if (!sk_hdr) return 0; - - /* Now, lay out the sec_desc in the space provided */ - - sk_hdr->SK_ID = str_to_dword("sk"); - - /* - * We can't deal with the next and prev offset in the SK_HDRs until the - * whole tree has been stored, then we can go and deal with them - */ - - sk_hdr->ref_cnt = sec->ref_cnt; - sk_hdr->rec_size = size; /* Is this correct */ - - /* Now, lay out the sec_desc */ - - if (!nt_store_sec_desc(regf, sec->sec_desc, (char *)&sk_hdr->sec_desc)) - return 0; - - return sk_off; - -} - -/* - * Store a KEY in the file ... - * - * We store this depth first, and defer storing the lf struct until - * all the sub-keys have been stored. - * - * We store the NK hdr, any SK header, class name, and VK structure, then - * recurse down the LF structures ... - * - * We return the offset of the NK struct - * FIXME, FIXME, FIXME: Convert to using SIVAL and SSVAL ... - */ -static int nt_store_reg_key(struct registry_hive *regf, struct registry_key *key) -{ - NK_HDR *nk_hdr; - uint_t nk_off, sk_off, size; - - if (!regf || !key) return 0; - - size = sizeof(NK_HDR) + strlen(key->name) - 1; - nk_hdr = nt_alloc_regf_space(regf, size, &nk_off); - if (!nk_hdr) goto error; - - key->offset = nk_off; /* We will need this later */ - - /* - * Now fill in each field etc ... - */ - - nk_hdr->NK_ID = str_to_dword("nk"); - if (key->type == REG_ROOT_KEY) - nk_hdr->type = 0x2C; - else - nk_hdr->type = 0x20; - - /* FIXME: Fill in the time of last update */ - - if (key->type != REG_ROOT_KEY) - nk_hdr->own_off = key->owner->offset; - - if (key->sub_keys) - nk_hdr->subk_num = key->sub_keys->key_count; - - /* - * Now, process the Sec Desc and then store its offset - */ - - sk_off = nt_store_security(regf, key->security); - nk_hdr->sk_off = sk_off; - - /* - * Then, store the val list and store its offset - */ - if (key->values) { - nk_hdr->val_cnt = key->values->val_count; - nk_hdr->val_off = nt_store_val_list(regf, key->values); - } - else { - nk_hdr->val_off = -1; - nk_hdr->val_cnt = 0; - } - - /* - * Finally, store the subkeys, and their offsets - */ - -error: - return 0; -} - -/* - * Store the registry header ... - * We actually create the registry header block and link it to the chain - * of output blocks. - */ -static REGF_HDR *nt_get_reg_header(struct registry_hive *h) { - REGF *regf = h->backend_data; - HBIN_BLK *tmp = NULL; - - tmp = malloc_p(HBIN_BLK); - - memset(tmp, 0, sizeof(HBIN_BLK)); - tmp->type = REG_OUTBLK_HDR; - tmp->size = REGF_HDR_BLKSIZ; - tmp->data = malloc(REGF_HDR_BLKSIZ); - if (!tmp->data) goto error; - - memset(tmp->data, 0, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ - regf->blk_head = regf->blk_tail = tmp; - - return (REGF_HDR *)tmp->data; - -error: - if (tmp) free(tmp); - return NULL; -} - -#endif - -static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) -{ - REGF *regf; - REGF_HDR *regf_hdr; - uint_t regf_id, hbin_id; - HBIN_HDR *hbin_hdr; - - regf = (REGF *)talloc(h, REGF); - memset(regf, 0, sizeof(REGF)); - regf->owner_sid_str = NULL; /* FIXME: Fill in */ + regf = (struct regf_data *)talloc_zero(h, struct regf_data); h->backend_data = regf; DEBUG(5, ("Attempting to load registry file\n")); /* Get the header */ - if ((regf_hdr = nt_get_regf_hdr(h)) == NULL) { - DEBUG(0, ("Unable to get header\n")); + regf->data.data = (uint8_t *)file_load(h->location, ®f->data.length, regf); + if (regf->data.data == NULL) { + DEBUG(0,("Could not load file: %s, %s\n", h->location, + strerror(errno))); return WERR_GENERAL_FAILURE; } - /* Now process that header and start to read the rest in */ + pull = talloc_zero(regf, struct tdr_pull); + if (!pull) + return WERR_NOMEM; - if ((regf_id = IVAL(®f_hdr->REGF_ID,0)) != str_to_dword("regf")) { - DEBUG(0, ("Unrecognized NT registry header id: %0X, %s\n", - regf_id, h->location)); - return WERR_GENERAL_FAILURE; - } + pull->data = regf->data; - /* - * Validate the header ... - */ - if (!valid_regf_hdr(regf_hdr)) { - DEBUG(0, ("Registry file header does not validate: %s\n", - h->location)); + regf_hdr = talloc(regf, struct regf_hdr); + if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr))) { return WERR_GENERAL_FAILURE; } - /* Update the last mod date, and then go get the first NK record and on */ - - TTTONTTIME(regf, IVAL(®f_hdr->tim1,0), IVAL(®f_hdr->tim2,0)); - - /* - * The hbin hdr seems to be just uninteresting garbage. Check that - * it is there, but that is all. - */ + if (strcmp(regf_hdr->REGF_ID, "regf") != 0) { + DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n", + regf_hdr->REGF_ID, h->location)); + } - hbin_hdr = (HBIN_HDR *)(regf->base + REGF_HDR_BLKSIZ); - - if ((hbin_id = IVAL(&hbin_hdr->HBIN_ID,0)) != str_to_dword("hbin")) { - DEBUG(0, ("Unrecognized registry hbin hdr ID: %0X, %s\n", - hbin_id, h->location)); - return WERR_GENERAL_FAILURE; - } + DEBUG(1, ("Registry '%s' read. Version %d.%d.%d.%d\n", + regf_hdr->description, regf_hdr->version.major, + regf_hdr->version.minor, regf_hdr->version.release, + regf_hdr->version.build)); /* - * Get a pointer to the first key from the hreg_hdr + * Validate the header ... */ + if (regf_hdr_checksum(regf->data.data) != regf_hdr->chksum) { + DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", + h->location, regf_hdr->chksum, regf_hdr_checksum(regf->data.data))); + return WERR_GENERAL_FAILURE; + } - DEBUG(2, ("First Key: %0X\n", - IVAL(®f_hdr->first_key, 0))); - - regf->first_key = (NK_HDR *)LOCN(regf->base, IVAL(®f_hdr->first_key,0)); - DEBUGADD(2, ("First Key Offset: %0X\n", - IVAL(®f_hdr->first_key, 0))); - - DEBUGADD(2, ("Data Block Size: %d\n", - IVAL(®f_hdr->dblk_size, 0))); - - DEBUGADD(2, ("Offset to next hbin block: %0X\n", - IVAL(&hbin_hdr->off_to_next, 0))); + pull->offset = 0x1000; - DEBUGADD(2, ("HBIN block size: %0X\n", - IVAL(&hbin_hdr->blk_size, 0))); + i = 0; + /* Read in all hbin blocks */ + regf->hbins = talloc_array(regf, struct hbin_block *, 1); + regf->hbins[0] = NULL; - /* - * Unmap the registry file, as we might want to read in another - * tree etc. - */ + while (pull->offset < pull->data.length) { + struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); - h->backend_data = regf; + if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin))) { + DEBUG(0, ("[%d] Error parsing HBIN block\n", i)); + return WERR_FOOBAR; + } - return nk_to_key(h, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); -} + if (strcmp(hbin->HBIN_ID, "hbin") != 0) { + DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", i, hbin->HBIN_ID)); + return WERR_FOOBAR; + } + regf->hbins[i] = hbin; + i++; + regf->hbins = talloc_realloc(regf, regf->hbins, struct hbin_block *, i+2); + regf->hbins[i] = NULL; + } -static WERROR nt_num_subkeys(struct registry_key *k, uint32_t *num) -{ - REGF *regf = k->hive->backend_data; - LF_HDR *lf_hdr; - int lf_off; - NK_HDR *nk_hdr = k->backend_data; - lf_off = IVAL(&nk_hdr->lf_off,0); - DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); - if(lf_off == -1) { - *num = 0; - return WERR_OK; - } - lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); + DEBUG(1, ("%d HBIN blocks read\n", i)); - return lf_num_entries(k->hive, lf_hdr, BLK_SIZE(lf_hdr), num); -} + *key = regf_get_key(h, regf, 0x20); -static WERROR nt_num_values(struct registry_key *k, uint32_t *count) -{ - NK_HDR *nk_hdr = k->backend_data; - *count = IVAL(&nk_hdr->val_cnt,0); return WERR_OK; } -static WERROR nt_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_value **value) -{ - VL_TYPE *vl; - int val_off, vk_off; - int val_count; - VK_HDR *vk_hdr; - REGF *regf = k->hive->backend_data; - NK_HDR *nk_hdr = k->backend_data; - val_count = IVAL(&nk_hdr->val_cnt,0); - val_off = IVAL(&nk_hdr->val_off,0); - vl = (VL_TYPE *)LOCN(regf->base, val_off); - DEBUG(2, ("Val List Offset: %0X\n", val_off)); - if(n < 0) return WERR_INVALID_PARAM; - if(n >= val_count) return WERR_NO_MORE_ITEMS; - - vk_off = IVAL(&vl[n],0); - vk_hdr = (VK_HDR *)LOCN(regf->base, vk_off); - return vk_to_val(mem_ctx, k, vk_hdr, BLK_SIZE(vk_hdr), value); -} - -static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n, struct registry_key **subkey) -{ - REGF *regf = k->hive->backend_data; - int lf_off; - NK_HDR *nk_hdr = k->backend_data; - LF_HDR *lf_hdr; - lf_off = IVAL(&nk_hdr->lf_off,0); - DEBUG(2, ("SubKey list offset: %0X\n", lf_off)); - - /* - * No more subkeys if lf_off == -1 - */ - - if (lf_off != -1) { - lf_hdr = (LF_HDR *)LOCN(regf->base, lf_off); - return lf_get_entry(mem_ctx, k, lf_hdr, BLK_SIZE(lf_hdr), n, subkey); - } - - return WERR_NO_MORE_ITEMS; -} - static struct hive_operations reg_backend_nt4 = { .name = "nt4", .open_hive = nt_open_hive, - .num_subkeys = nt_num_subkeys, - .num_values = nt_num_values, - .get_subkey_by_index = nt_key_by_index, - .get_value_by_index = nt_value_by_index, - - /* TODO: - .add_key - .add_value - .del_key - .del_value - .update_value - */ + .num_subkeys = regf_num_subkeys, + .num_values = regf_num_values, + .get_subkey_by_index = regf_get_subkey, + .get_value_by_index = regf_get_value, }; NTSTATUS registry_nt4_init(void) diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl index 03f63debc8..760183c01d 100644 --- a/source4/lib/registry/regf.idl +++ b/source4/lib/registry/regf.idl @@ -13,13 +13,15 @@ interface regf { + const int REGF_OFFSET_NONE = 0xffffffff; + /* * Registry version number * 1.3.0.1 for WinNT 4 * 1.5.0.1 for WinXP */ - typedef struct { + typedef [noprint] struct { [value(1)] uint32 major; [value(3)] uint32 minor; [value(0)] uint32 release; @@ -33,7 +35,7 @@ interface regf the first 0x200 bytes only! */ - typedef [public] struct { + typedef [public,noprint] struct { [charset(DOS)] uint8 REGF_ID[4]; /* 'regf' */ uint32 update_counter1; uint32 update_counter2; @@ -53,23 +55,21 @@ interface regf This block is always a multiple of 4kb in size. */ - typedef [public] struct { + typedef [public,noprint] struct { [charset(DOS)] uint8 HBIN_ID[4]; /* hbin */ - uint32 off_from_first; /* Offset from 1st hbin-Block */ - uint32 off_to_next; /* Offset to the next hbin-Block */ + uint32 offset_from_first; /* Offset from 1st hbin-Block */ + uint32 offset_to_next; /* Offset to the next hbin-Block */ uint32 unknown[2]; NTTIME last_change; - uint32 block_size; /* Block size */ - uint8 data[block_size]; /* Filled with hbin_data blocks */ + uint32 block_size; /* Block size (including the header!) */ + uint8 data[offset_to_next-0x20]; + /* data is filled with: + uint32 length + uint8_t data[length] + */ } hbin_block; - typedef struct { - uint32 length; - [charset(DOS)] uint8 header[2]; /* li, lh, ri, nk, vk, sk, lf or \0\0 */ - uint8 data[length-2]; - } hbin_data; - - typedef enum { + typedef [base_type(uint16),noprint] enum { REG_ROOT_KEY = 0x20, REG_SUB_KEY = 0x2C, REG_SYM_LINK = 0x10 @@ -79,7 +79,8 @@ interface regf The nk-record can be treated as a combination of tree-record and key-record of the win 95 registry. */ - typedef struct { + typedef [public,noprint] struct { + [charset(DOS)] uint8 header[2]; reg_key_type type; NTTIME last_change; uint32 uk1; @@ -87,19 +88,20 @@ interface regf uint32 num_subkeys; uint32 uk2; uint32 subkeys_offset; - uint32 uk3; + uint32 unknown_offset; uint32 num_values; - uint32 values_offset; + uint32 values_offset; /* Points to a list of offsets of vk-records */ uint32 sk_offset; uint32 clsname_offset; - uint32 unk4[5]; + uint32 unk3[5]; uint16 name_length; uint16 clsname_length; [charset(DOS)] uint8 key_name[name_length]; } nk_block; /* sk (? Security Key ?) is the ACL of the registry. */ - typedef struct { + typedef [noprint,nopush,nopull] struct { + [charset(DOS)] uint8 header[2]; uint16 uk1; uint32 prev_offset; uint32 next_offset; @@ -108,39 +110,43 @@ interface regf uint8 sec_desc[rec_size]; } sk_block; - typedef struct { + typedef [noprint,nopush,nopull] struct { uint32 offset_nk; uint32 base37; /* base37 of key name */ } lh_hash; /* Subkey listing with hash of first 4 characters */ - typedef struct { + typedef [noprint,nopush,nopull] struct { + [charset(DOS)] uint8 header[2]; uint16 key_count; lh_hash hashes[key_count]; } lh_block; - typedef struct { + typedef [noprint,nopush,nopull] struct { + [charset(DOS)] uint8 header[2]; uint16 key_count; uint32 offset_nk[key_count]; } li_block; - typedef struct { + typedef [noprint,nopush,nopull] struct { + [charset(DOS)] uint8 header[2]; uint16 key_count; uint32 offset[key_count]; /* li/lh offset */ } ri_block; /* The vk-record consists information to a single value (value key). */ - typedef struct { + typedef [public,noprint] struct { + [charset(DOS)] uint8 header[2]; uint16 name_length; uint32 data_length; /* If top-bit set, offset contains the data */ uint32 data_offset; uint32 data_type; uint16 flag; /* =1, has name, else no name (=Default). */ uint16 unk1; - [charset(DOS)] uint8 data_name[name_length]; + [charset(DOS)] uint8 data_name[name_length]; } vk_block; - typedef struct { + typedef [noprint] struct { uint32 nk_off; uint8 hash[4]; } hash_record; @@ -149,7 +155,8 @@ interface regf The lf-record is the counterpart to the RGKN-record (the hash-function) */ - typedef struct { + typedef [public,noprint] struct { + [charset(DOS)] uint8 header[2]; uint16 key_count; hash_record hr[key_count]; /* Array of hash records, depending on key_count */ } lf_block; -- cgit From eac7fe4ebc6eb819fe3721051751e60b12e95684 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Sep 2005 23:23:14 +0000 Subject: r10016: Support reading security descriptors on keys. (This used to be commit b349e902c7b0140cd94e241ba9f81c83fa54f603) --- source4/lib/registry/common/reg_interface.c | 9 ++++++ source4/lib/registry/reg_backend_nt4.c | 47 +++++++++++++++++++++++++++++ source4/lib/registry/regf.idl | 4 +-- source4/lib/registry/tools/regtree.c | 9 +++++- 4 files changed, 66 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 7f745143e6..5297b1b3cf 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -427,6 +427,15 @@ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, D } +WERROR reg_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **secdesc) +{ + /* A 'real' set function has preference */ + if (key->hive->functions->key_get_sec_desc) + return key->hive->functions->key_get_sec_desc(ctx, key, secdesc); + + DEBUG(1, ("Backend '%s' doesn't support method get_sec_desc\n", key->hive->functions->name)); + return WERR_NOT_SUPPORTED; +} WERROR reg_del_value(struct registry_key *key, const char *valname) { diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index e0f5ccd08c..b1c0d201f0 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -21,6 +21,7 @@ #include "registry.h" #include "system/filesys.h" #include "lib/registry/tdr_regf.h" +#include "librpc/gen_ndr/ndr_security.h" /* * Read HBIN blocks into memory @@ -251,6 +252,51 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id return WERR_OK; } +static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **sd) +{ + struct nk_block *nk = key->backend_data; + struct tdr_pull *tdr; + struct sk_block sk; + DATA_BLOB data; + + data = regf_get_data(key->hive->backend_data, nk->sk_offset); + if (!data.data) { + DEBUG(0, ("Unable to find security descriptor\n")); + return WERR_GENERAL_FAILURE; + } + + tdr = talloc_zero(ctx, struct tdr_pull); + if (!tdr) + return WERR_NOMEM; + + tdr->data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_sk_block(tdr, &sk))) { + DEBUG(0, ("Error parsing SK block\n")); + return WERR_GENERAL_FAILURE; + } + + if (strcmp(sk.header, "sk") != 0) { + DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header)); + return WERR_GENERAL_FAILURE; + } + + *sd = talloc(ctx, struct security_descriptor); + if (!*sd) + return WERR_NOMEM; + + data.data = sk.sec_desc; + data.length = sk.rec_size; + if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { + DEBUG(0, ("Error parsing security descriptor\n")); + return WERR_GENERAL_FAILURE; + } + + talloc_free(tdr); + + return WERR_OK; +} + static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { struct regf_data *regf; @@ -342,6 +388,7 @@ static struct hive_operations reg_backend_nt4 = { .num_values = regf_num_values, .get_subkey_by_index = regf_get_subkey, .get_value_by_index = regf_get_value, + .key_get_sec_desc = regf_get_sec_desc, }; NTSTATUS registry_nt4_init(void) diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl index 760183c01d..3b0a66fc54 100644 --- a/source4/lib/registry/regf.idl +++ b/source4/lib/registry/regf.idl @@ -100,9 +100,9 @@ interface regf } nk_block; /* sk (? Security Key ?) is the ACL of the registry. */ - typedef [noprint,nopush,nopull] struct { + typedef [noprint,public] struct { [charset(DOS)] uint8 header[2]; - uint16 uk1; + uint16 tag; uint32 prev_offset; uint32 next_offset; uint32 ref_cnt; diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 2385123b7f..38dffed85d 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -28,6 +28,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) { struct registry_key *subkey; struct registry_value *value; + struct security_descriptor *sec_desc; WERROR error; int i; TALLOC_CTX *mem_ctx; @@ -68,9 +69,15 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error))); } } + + mem_ctx = talloc_init("sec_desc"); + if (NT_STATUS_IS_ERR(reg_get_sec_desc(mem_ctx, p, &sec_desc))) { + DEBUG(0, ("Error getting security descriptor\n")); + } + talloc_free(mem_ctx); } - int main(int argc, char **argv) +int main(int argc, char **argv) { int opt, i; const char *backend = NULL; -- cgit From 16788f27a8f56f39f6d272427655b9869d6c3005 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 02:01:42 +0000 Subject: r10019: Only return NT_STATUS_NO_MEMORY if the alloc failed.. (This used to be commit ea92959209fa256a8190df19e8c27b368169724f) --- source4/lib/tdr/tdr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index 7f42d0cf15..e1e54622ac 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -55,7 +55,11 @@ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) } tdr->data.data = talloc_realloc(tdr, tdr->data.data, uint8_t, tdr->data.length + TDR_BASE_MARSHALL_SIZE); - return NT_STATUS_NO_MEMORY; + + if (tdr->data.data == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; } -- cgit From 23e6e07b280983b2ccdf60deac3c32584af16140 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 02:09:32 +0000 Subject: r10020: Support for malloc / realloc / free in HBIN blocks Initial support for adding keys (still broken though) (This used to be commit ff8d3a27c1b9bb37de39e7d7b974702b2b8c4437) --- source4/lib/registry/common/reg_interface.c | 5 + source4/lib/registry/reg_backend_nt4.c | 340 ++++++++++++++++++++++++++-- source4/lib/registry/regf.idl | 13 +- 3 files changed, 333 insertions(+), 25 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 5297b1b3cf..ddd4ecbe93 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -409,6 +409,11 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey); if(!W_ERROR_IS_OK(error)) return error; + + if (!*newkey) { + DEBUG(0, ("Backend returned WERR_OK, but didn't specify key!\n")); + return WERR_GENERAL_FAILURE; + } (*newkey)->hive = parent->hive; (*newkey)->backend_data = talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name); diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index b1c0d201f0..46057bcd63 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -20,6 +20,7 @@ #include "includes.h" #include "registry.h" #include "system/filesys.h" +#include "system/time.h" #include "lib/registry/tdr_regf.h" #include "librpc/gen_ndr/ndr_security.h" @@ -32,6 +33,23 @@ struct regf_data { struct hbin_block **hbins; }; +static struct hbin_block *hbin_by_offset (const struct regf_data *data, uint32_t offset, uint32_t *rel_offset) +{ + int i; + + for (i = 0; data->hbins[i]; i++) { + if (offset >= data->hbins[i]->offset_from_first && + offset < data->hbins[i]->offset_from_first+ + data->hbins[i]->offset_to_next) { + if (rel_offset) + *rel_offset = offset - data->hbins[i]->offset_from_first - 0x20; + return data->hbins[i]; + } + } + + return NULL; +} + /* * Validate a regf header * For now, do nothing, but we should check the checksum @@ -49,37 +67,216 @@ static uint32_t regf_hdr_checksum(const uint8_t *buffer) return checksum; } -static DATA_BLOB regf_get_data(const struct regf_data *data, uint32_t offset) +static DATA_BLOB hbin_get_data(const struct regf_data *data, uint32_t offset) { - int i; DATA_BLOB ret; + struct hbin_block *hbin; + uint32_t rel_offset; ret.data = NULL; ret.length = 0; - - for (i = 0; data->hbins[i]; i++) { - if (offset >= data->hbins[i]->offset_from_first && - offset < data->hbins[i]->offset_from_first+ - data->hbins[i]->offset_to_next) - break; - } - if (data->hbins[i] == NULL) { + hbin = hbin_by_offset(data, offset, &rel_offset); + + if (hbin == NULL) { DEBUG(1, ("Can't find HBIN containing 0x%4x\n", offset)); return ret; } - ret.length = IVAL(data->hbins[i]->data, - offset - data->hbins[i]->offset_from_first - 0x20); + ret.length = IVAL(hbin->data, rel_offset); if (ret.length & 0x80000000) { /* absolute value */ ret.length = (ret.length ^ 0xffffffff) + 1; } - ret.data = data->hbins[i]->data + - (offset - data->hbins[i]->offset_from_first - 0x20) + 4; + ret.length -= 4; /* 4 bytes for the length... */ + ret.data = hbin->data + + (offset - hbin->offset_from_first - 0x20) + 4; + + return ret; +} + +/* Allocate some new data */ +static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *offset) +{ + DATA_BLOB ret; + uint32_t rel_offset = -1; /* Relative offset ! */ + struct hbin_block *hbin = NULL; + int i; + + size += 4; /* Need to include uint32 for the length */ + + /* Allocate as a multiple of 8 */ + size = (size + 7) & ~7; + + ret.data = NULL; + ret.length = 0; + + if (size == 0) + return ret; + + for (i = 0; (hbin = data->hbins[i]); i++) { + int j; + uint32_t my_size; + for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) { + my_size = IVAL(hbin->data, j); + uint32_t header = IVAL(hbin->data, j + 4); + + if (my_size % 8 != 0) { + DEBUG(0, ("Encountered non-aligned block!\n")); + } + + if (my_size & 0x80000000) { /* Used... */ + my_size = (my_size ^ 0xffffffff) + 1; + } else if (my_size == size) { /* exact match */ + rel_offset = j; + break; + } else if (my_size > size) { /* data will remain */ + rel_offset = j; + SIVAL(hbin->data, rel_offset+size, my_size-size); + break; + } + + if (header == 0xffffffff && + hbin->offset_to_next-rel_offset >= size) { + rel_offset = j; + /* Mark new free block size */ + SIVAL(hbin->data, rel_offset+size,hbin->offset_to_next - rel_offset - size - 0x20); + SIVAL(hbin->data, rel_offset+size+0x4, 0xffffffff); + break; + } + + if (header == 0xffffffff) { + break; + } + } + + if (rel_offset != -1) + break; + } + /* No space available in previous hbins, + * allocate new one */ + if (data->hbins[i] == NULL) { + data->hbins = talloc_realloc(data, data->hbins, struct hbin_block *, i+2); + hbin = talloc(data->hbins, struct hbin_block); + data->hbins[i] = hbin; + data->hbins[i+1] = NULL; + + hbin->HBIN_ID = talloc_strdup(hbin, "hbin"); + hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next); + hbin->offset_to_next = 0x1000; + hbin->unknown[0] = 0; + hbin->unknown[0] = 0; + unix_to_nt_time(&hbin->last_change, time(NULL)); + hbin->block_size = hbin->offset_to_next; + hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20); + + rel_offset = 0x0; + SIVAL(hbin->data, size, hbin->block_size - size - 0x20); + SIVAL(hbin->data, size + 0x4, 0xffffffff); + } + + /* Set size and mark as used */ + SIVAL(hbin->data, rel_offset, size & 0x80000000); + + ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */ + ret.length = size - 0x4; + if (offset) + *offset = hbin->offset_from_first + rel_offset + 0x20; + return ret; } +/* Store a data blob. Return the offset at which it was stored */ +static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob) +{ + uint32_t ret; + DATA_BLOB dest = hbin_alloc(data, blob.length, &ret); + + memcpy(dest.data, blob.data, blob.length); + + return ret; +} + + +/* Free existing data */ +static void hbin_free (struct regf_data *data, uint32_t offset) +{ + uint32_t size; + uint32_t rel_offset; + struct hbin_block *hbin = hbin_by_offset(data, offset, &rel_offset); + + if (hbin == NULL) + return; + + /* Get original size */ + size = IVAL(hbin->data, rel_offset); + + if (!(size & 0x80000000)) { + DEBUG(1, ("Trying to free already freed block\n")); + return; + } + + /* Mark block as free */ + SIVAL(hbin->data, rel_offset, (size ^ 0xffffffff) + 1); +} + +/* Store a data blob data was already stored, but hsa changed in size + * Will try to save it at the current location if possible, otherwise + * does a free + store */ +static uint32_t hbin_store_resize (struct regf_data *data, uint32_t orig_offset, DATA_BLOB blob) +{ + uint32_t rel_offset; + struct hbin_block *hbin = hbin_by_offset(data, orig_offset, &rel_offset); + uint32_t orig_size; + uint32_t needed_size; + uint32_t possible_size; + int i; + + if (!hbin) + return hbin_store(data, blob); + + /* Get original size */ + orig_size = IVAL(hbin->data, rel_offset); + + /* Fits into current allocated block */ + if (orig_size - 4 >= blob.length) { + memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); + return orig_offset; + } + + needed_size = blob.length + 4; /* Add uint32 containing length */ + needed_size = (needed_size + 7) & ~7; /* Align */ + + possible_size = orig_size; + + /* Check if it can be combined with the next few free records */ + for (i = rel_offset; + i < hbin->offset_to_next - 0x20; + i = rel_offset + possible_size) { + uint32_t header; + if (IVAL(hbin->data, i) & 0x80000000) /* Used */ + break; + + header = IVAL(hbin->data, i + 4); + if (header == 0xffffffff) { + possible_size = hbin->offset_to_next - 0x20 - rel_offset; + } else { + possible_size += IVAL(hbin->data, i); + } + + if (possible_size >= blob.length) { + SIVAL(hbin->data, rel_offset, possible_size); + memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); + return orig_offset; + } + + if (header == 0xffffffff) + break; + } + + hbin_free(data, orig_offset); + return hbin_store(data, blob); +} static WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) { @@ -101,7 +298,7 @@ static WERROR regf_num_values (struct registry_key *key, uint32_t *count) static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *regf, uint32_t offset) { - DATA_BLOB data = regf_get_data(regf, offset); + DATA_BLOB data = hbin_get_data(regf, offset); struct tdr_pull *pull; struct registry_key *ret; struct nk_block *nk; @@ -147,7 +344,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx if (idx >= nk->num_values) return WERR_NO_MORE_ITEMS; - data = regf_get_data(key->hive->backend_data, nk->values_offset); + data = hbin_get_data(key->hive->backend_data, nk->values_offset); if (!data.data) { DEBUG(0, ("Unable to find value list\n")); return WERR_GENERAL_FAILURE; @@ -159,7 +356,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx vk_offset = IVAL(data.data, idx * 4); - data = regf_get_data(key->hive->backend_data, vk_offset); + data = hbin_get_data(key->hive->backend_data, vk_offset); if (!data.data) { DEBUG(0, ("Unable to find value\n")); return WERR_GENERAL_FAILURE; @@ -188,7 +385,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx (*ret)->data.data = (uint8_t *)&vk->data_offset; (*ret)->data.length = vk->data_length; } else { - (*ret)->data = regf_get_data(key->hive->backend_data, vk->data_offset); + (*ret)->data = hbin_get_data(key->hive->backend_data, vk->data_offset); } if ((*ret)->data.length < vk->data_length) { @@ -207,7 +404,7 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id if (idx >= nk->num_subkeys) return WERR_NO_MORE_ITEMS; - data = regf_get_data(key->hive->backend_data, nk->subkeys_offset); + data = hbin_get_data(key->hive->backend_data, nk->subkeys_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; @@ -259,7 +456,7 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc struct sk_block sk; DATA_BLOB data; - data = regf_get_data(key->hive->backend_data, nk->sk_offset); + data = hbin_get_data(key->hive->backend_data, nk->sk_offset); if (!data.data) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_GENERAL_FAILURE; @@ -297,6 +494,108 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc return WERR_OK; } +static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, const char *name, uint32_t key_offset) +{ + uint32_t ret; + struct lf_block lf; + struct tdr_pull *pull = NULL; + struct tdr_push *push; + + /* Add to subkeys list */ + if (list_offset == -1) { /* Need to create subkeys list */ + lf.header = "lf"; + lf.key_count = 0; + lf.hr = NULL; + } else { + DATA_BLOB data; + pull = talloc(regf, struct tdr_pull); + + data = hbin_get_data(regf, list_offset); + if (!data.data) { + DEBUG(0, ("Can't get subkeys list\n")); + talloc_free(pull); + return -1; + } + + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) { + DEBUG(0, ("Unable to parse lf list\n")); + talloc_free(pull); + return -1; + } + } + + lf.hr = talloc_realloc(pull, lf.hr, struct hash_record, lf.key_count+1); + lf.hr[lf.key_count].nk_off = key_offset; + lf.hr[lf.key_count].hash = name; + + push = talloc_zero(regf, struct tdr_push); + + if (NT_STATUS_IS_ERR(tdr_push_lf_block(push, &lf))) { + DEBUG(0, ("Error storing lf block\n")); + return -1; + } + + ret = hbin_store_resize (regf, list_offset, push->data); + + talloc_free(push); + talloc_free(pull); + + return ret; +} + +static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) +{ + struct nk_block *parent_nk = parent->backend_data, nk; + DATA_BLOB data; + struct tdr_push *push; + uint32_t offset; + + nk.header = "nk"; + nk.type = REG_SUB_KEY; + unix_to_nt_time(&nk.last_change, time(NULL)); + nk.uk1 = 0; + nk.parent_offset = 0; /* FIXME */ + nk.num_subkeys = 0; + nk.uk2 = 0; + nk.subkeys_offset = -1; + nk.unknown_offset = -1; + nk.num_values = 0; + nk.sk_offset = 0; + memset(nk.unk3, 0, 5); + nk.clsname_offset = -1; + nk.clsname_length = 0; + nk.key_name = name; + + push = talloc_zero(ctx, struct tdr_push); + if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, &nk))) { + DEBUG(0, ("Error storing 'nk' block\n")); + return WERR_GENERAL_FAILURE; + } + + offset = hbin_store(parent->hive->backend_data, push->data); + + parent_nk->subkeys_offset = lf_add_entry(parent->hive->backend_data, parent_nk->subkeys_offset, name, nk.parent_offset); + + parent_nk->num_subkeys++; + + ZERO_STRUCTP(push); + + if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, parent_nk))) { + DEBUG(0, ("Error storing parent 'nk' block\n")); + return WERR_GENERAL_FAILURE; + } + + data = hbin_get_data(parent->hive->backend_data, nk.parent_offset); + memcpy(data.data, push->data.data, push->data.length); + + talloc_free(push); + + /* FIXME: Set sec desc ! */ + + *ret = regf_get_key(ctx, parent->hive->backend_data, offset); + return WERR_OK; +} + static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { struct regf_data *regf; @@ -389,6 +688,7 @@ static struct hive_operations reg_backend_nt4 = { .get_subkey_by_index = regf_get_subkey, .get_value_by_index = regf_get_value, .key_get_sec_desc = regf_get_sec_desc, + .add_key = regf_add_key, }; NTSTATUS registry_nt4_init(void) diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl index 3b0a66fc54..85a879cc36 100644 --- a/source4/lib/registry/regf.idl +++ b/source4/lib/registry/regf.idl @@ -64,8 +64,11 @@ interface regf uint32 block_size; /* Block size (including the header!) */ uint8 data[offset_to_next-0x20]; /* data is filled with: - uint32 length - uint8_t data[length] + uint32 length; + Negative if in used, positive otherwise + Always a multiple of 8 + uint8_t data[length]; + Free space marker if 0xffffffff */ } hbin_block; @@ -94,7 +97,7 @@ interface regf uint32 sk_offset; uint32 clsname_offset; uint32 unk3[5]; - uint16 name_length; + [value(strlen(key_name))] uint16 name_length; uint16 clsname_length; [charset(DOS)] uint8 key_name[name_length]; } nk_block; @@ -137,7 +140,7 @@ interface regf /* The vk-record consists information to a single value (value key). */ typedef [public,noprint] struct { [charset(DOS)] uint8 header[2]; - uint16 name_length; + [value(strlen(data_name))] uint16 name_length; uint32 data_length; /* If top-bit set, offset contains the data */ uint32 data_offset; uint32 data_type; @@ -148,7 +151,7 @@ interface regf typedef [noprint] struct { uint32 nk_off; - uint8 hash[4]; + [charset(DOS)] uint8 hash[4]; } hash_record; /* -- cgit From 4729c3db26f719cd936825d91b2514df7ac0e61b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 13:13:47 +0000 Subject: r10025: Add some utility functions for storing/loading tdr encoded data (This used to be commit bcd433bfc1450317b75e22942dee1c42bb24ae79) --- source4/lib/registry/reg_backend_nt4.c | 171 +++++++++++++++------------------ source4/lib/tdr/tdr.h | 3 + 2 files changed, 82 insertions(+), 92 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 46057bcd63..cf67abb322 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -31,6 +31,7 @@ struct regf_data { DATA_BLOB data; struct hbin_block **hbins; + struct regf_hdr *header; }; static struct hbin_block *hbin_by_offset (const struct regf_data *data, uint32_t offset, uint32_t *rel_offset) @@ -67,7 +68,7 @@ static uint32_t regf_hdr_checksum(const uint8_t *buffer) return checksum; } -static DATA_BLOB hbin_get_data(const struct regf_data *data, uint32_t offset) +static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) { DATA_BLOB ret; struct hbin_block *hbin; @@ -94,6 +95,31 @@ static DATA_BLOB hbin_get_data(const struct regf_data *data, uint32_t offset) return ret; } +static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, tdr_pull_fn_t pull_fn, void *p) +{ + DATA_BLOB data; + struct tdr_pull *pull; + + data = hbin_get(regf, offset); + if (!data.data) { + DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); + return False; + } + + pull = talloc_zero(regf, struct tdr_pull); + pull->data = data; + + if (NT_STATUS_IS_ERR(pull_fn(pull, p))) { + DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); + talloc_free(pull); + return False; + } + + /* FIXME: Free pull ! */ + + return True; +} + /* Allocate some new data */ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *offset) { @@ -197,6 +223,23 @@ static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob) return ret; } +static uint32_t hbin_store_tdr (struct regf_data *data, tdr_push_fn_t push_fn, void *p) +{ + struct tdr_push *push = talloc_zero(data, struct tdr_push); + uint32_t ret; + + if (NT_STATUS_IS_ERR(push_fn(push, p))) { + DEBUG(0, ("Error during push\n")); + return -1; + } + + ret = hbin_store(data, push->data); + + talloc_free(push); + + return ret; +} + /* Free existing data */ static void hbin_free (struct regf_data *data, uint32_t offset) @@ -278,6 +321,23 @@ static uint32_t hbin_store_resize (struct regf_data *data, uint32_t orig_offset, return hbin_store(data, blob); } +static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t push_fn, uint32_t orig_offset, void *p) +{ + struct tdr_push *push = talloc_zero(regf, struct tdr_push); + uint32_t ret; + + if (NT_STATUS_IS_ERR(push_fn(push, p))) { + DEBUG(0, ("Error during push\n")); + return -1; + } + + ret = hbin_store_resize(regf, orig_offset, push->data); + + talloc_free(push); + + return ret; +} + static WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) { struct nk_block *nk = key->backend_data; @@ -298,24 +358,13 @@ static WERROR regf_num_values (struct registry_key *key, uint32_t *count) static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *regf, uint32_t offset) { - DATA_BLOB data = hbin_get_data(regf, offset); - struct tdr_pull *pull; struct registry_key *ret; struct nk_block *nk; - if (data.data == NULL) { - DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); - return NULL; - } - ret = talloc_zero(ctx, struct registry_key); - pull = talloc_zero(ret, struct tdr_pull); - pull->data = data; nk = talloc(ret, struct nk_block); - - if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, nk))) { - DEBUG(1, ("Error parsing 'nk' record\n")); - talloc_free(ret); + if (!hbin_get_tdr(regf, offset, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { + DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return NULL; } @@ -337,14 +386,14 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx { struct nk_block *nk = key->backend_data; struct vk_block *vk; - struct tdr_pull *pull; + struct regf_data *regf = key->hive->backend_data; uint32_t vk_offset; DATA_BLOB data; if (idx >= nk->num_values) return WERR_NO_MORE_ITEMS; - data = hbin_get_data(key->hive->backend_data, nk->values_offset); + data = hbin_get(regf, nk->values_offset); if (!data.data) { DEBUG(0, ("Unable to find value list\n")); return WERR_GENERAL_FAILURE; @@ -356,12 +405,6 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx vk_offset = IVAL(data.data, idx * 4); - data = hbin_get_data(key->hive->backend_data, vk_offset); - if (!data.data) { - DEBUG(0, ("Unable to find value\n")); - return WERR_GENERAL_FAILURE; - } - *ret = talloc_zero(ctx, struct registry_value); if (!(*ret)) return WERR_NOMEM; @@ -370,11 +413,8 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx if (!vk) return WERR_NOMEM; - pull = talloc_zero(*ret, struct tdr_pull); - pull->data = data; - - if (NT_STATUS_IS_ERR(tdr_pull_vk_block(pull, vk))) { - DEBUG(0, ("Error parsing vk block\n")); + if (!hbin_get_tdr(regf, vk_offset, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); return WERR_GENERAL_FAILURE; } @@ -385,7 +425,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx (*ret)->data.data = (uint8_t *)&vk->data_offset; (*ret)->data.length = vk->data_length; } else { - (*ret)->data = hbin_get_data(key->hive->backend_data, vk->data_offset); + (*ret)->data = hbin_get(regf, vk->data_offset); } if ((*ret)->data.length < vk->data_length) { @@ -404,7 +444,7 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id if (idx >= nk->num_subkeys) return WERR_NO_MORE_ITEMS; - data = hbin_get_data(key->hive->backend_data, nk->subkeys_offset); + data = hbin_get(key->hive->backend_data, nk->subkeys_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; @@ -452,27 +492,15 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **sd) { struct nk_block *nk = key->backend_data; - struct tdr_pull *tdr; struct sk_block sk; + struct regf_data *regf = key->hive->backend_data; DATA_BLOB data; - data = hbin_get_data(key->hive->backend_data, nk->sk_offset); - if (!data.data) { + if (!hbin_get_tdr(regf, nk->sk_offset, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_GENERAL_FAILURE; } - - tdr = talloc_zero(ctx, struct tdr_pull); - if (!tdr) - return WERR_NOMEM; - - tdr->data = data; - - if (NT_STATUS_IS_ERR(tdr_pull_sk_block(tdr, &sk))) { - DEBUG(0, ("Error parsing SK block\n")); - return WERR_GENERAL_FAILURE; - } - + if (strcmp(sk.header, "sk") != 0) { DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header)); return WERR_GENERAL_FAILURE; @@ -489,8 +517,6 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc return WERR_GENERAL_FAILURE; } - talloc_free(tdr); - return WERR_OK; } @@ -498,8 +524,6 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons { uint32_t ret; struct lf_block lf; - struct tdr_pull *pull = NULL; - struct tdr_push *push; /* Add to subkeys list */ if (list_offset == -1) { /* Need to create subkeys list */ @@ -507,38 +531,17 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons lf.key_count = 0; lf.hr = NULL; } else { - DATA_BLOB data; - pull = talloc(regf, struct tdr_pull); - - data = hbin_get_data(regf, list_offset); - if (!data.data) { + if (!hbin_get_tdr(regf, list_offset, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) { DEBUG(0, ("Can't get subkeys list\n")); - talloc_free(pull); - return -1; - } - - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) { - DEBUG(0, ("Unable to parse lf list\n")); - talloc_free(pull); return -1; } } - lf.hr = talloc_realloc(pull, lf.hr, struct hash_record, lf.key_count+1); + lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1); lf.hr[lf.key_count].nk_off = key_offset; lf.hr[lf.key_count].hash = name; - push = talloc_zero(regf, struct tdr_push); - - if (NT_STATUS_IS_ERR(tdr_push_lf_block(push, &lf))) { - DEBUG(0, ("Error storing lf block\n")); - return -1; - } - - ret = hbin_store_resize (regf, list_offset, push->data); - - talloc_free(push); - talloc_free(pull); + ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); return ret; } @@ -546,8 +549,6 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) { struct nk_block *parent_nk = parent->backend_data, nk; - DATA_BLOB data; - struct tdr_push *push; uint32_t offset; nk.header = "nk"; @@ -566,29 +567,13 @@ static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const nk.clsname_length = 0; nk.key_name = name; - push = talloc_zero(ctx, struct tdr_push); - if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, &nk))) { - DEBUG(0, ("Error storing 'nk' block\n")); - return WERR_GENERAL_FAILURE; - } - - offset = hbin_store(parent->hive->backend_data, push->data); + offset = hbin_store_tdr(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, &nk); parent_nk->subkeys_offset = lf_add_entry(parent->hive->backend_data, parent_nk->subkeys_offset, name, nk.parent_offset); parent_nk->num_subkeys++; - ZERO_STRUCTP(push); - - if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, parent_nk))) { - DEBUG(0, ("Error storing parent 'nk' block\n")); - return WERR_GENERAL_FAILURE; - } - - data = hbin_get_data(parent->hive->backend_data, nk.parent_offset); - memcpy(data.data, push->data.data, push->data.length); - - talloc_free(push); + hbin_store_tdr_resize(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); /* FIXME: Set sec desc ! */ @@ -628,6 +613,8 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) return WERR_GENERAL_FAILURE; } + regf->header = regf_hdr; + if (strcmp(regf_hdr->REGF_ID, "regf") != 0) { DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n", regf_hdr->REGF_ID, h->location)); diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index 9d9d2b8adf..a37a1efaaa 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -52,3 +52,6 @@ struct tdr_print { (s) = talloc_array_size(tdr, sizeof(*(s)), n); \ if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ } while (0) + +typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, void *); +typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, void *); -- cgit From ff7342a4ad1cc1ac8571c86466c197b6a8fa6b41 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 14:47:19 +0000 Subject: r10026: Move registry header file to lib/registry Add support for showing security descriptor in regshell Add support for saving files in NT4 registry backend (This used to be commit 47cecd4726e6568f1aafb404646d2664f630a9bb) --- source4/lib/registry/common/reg_interface.c | 2 +- source4/lib/registry/common/reg_util.c | 2 +- source4/lib/registry/reg_backend_nt4.c | 32 ++++++- source4/lib/registry/registry.h | 136 ++++++++++++++++++++++++++++ source4/lib/registry/tools/regdiff.c | 2 +- source4/lib/registry/tools/regpatch.c | 2 +- source4/lib/registry/tools/regshell.c | 16 +++- source4/lib/registry/tools/regtree.c | 2 +- 8 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 source4/lib/registry/registry.h (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index ddd4ecbe93..74f158b027 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -20,7 +20,7 @@ #include "includes.h" #include "dlinklist.h" -#include "registry.h" +#include "lib/registry/registry.h" /* List of available backends */ static struct reg_init_function_entry *backends = NULL; diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index a0d4db6f57..ae30839cca 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -19,7 +19,7 @@ */ #include "includes.h" -#include "registry.h" +#include "lib/registry/registry.h" #include "librpc/gen_ndr/winreg.h" static const struct { diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index cf67abb322..4fc458dee4 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -376,7 +376,11 @@ static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *reg ret->name = talloc_steal(ret, nk->key_name); ret->last_mod = nk->last_change; - ret->class_name = NULL; /* FIXME: get somehow using clsname_offset */ + + if (nk->clsname_offset != -1) { + DATA_BLOB data = hbin_get(regf, nk->clsname_offset); + ret->class_name = talloc_strndup(ret, (char*)data.data, nk->clsname_length); + } ret->backend_data = nk; return ret; @@ -581,6 +585,30 @@ static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const return WERR_OK; } +static WERROR regf_set_value (struct registry_key *key, const char *name, uint32_t type, DATA_BLOB data) +{ + /* FIXME */ + + return WERR_NOT_SUPPORTED; +} + +static WERROR regf_save(struct registry_hive *hive, const char *location) +{ + struct regf_data *regf = hive->backend_data; + struct tdr_push *push = talloc_zero(regf, struct tdr_push); + int i; + + tdr_push_regf_hdr(push, regf->header); + + for (i = 0; regf->hbins[i]; i++) { + tdr_push_hbin_block(push, regf->hbins[i]); + } + + file_save(location, push->data.data, push->data.length); + + return WERR_OK; +} + static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { struct regf_data *regf; @@ -676,6 +704,8 @@ static struct hive_operations reg_backend_nt4 = { .get_value_by_index = regf_get_value, .key_get_sec_desc = regf_get_sec_desc, .add_key = regf_add_key, + .set_value = regf_set_value, + .save_hive = regf_save, }; NTSTATUS registry_nt4_init(void) diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h new file mode 100644 index 0000000000..f9e8a7698c --- /dev/null +++ b/source4/lib/registry/registry.h @@ -0,0 +1,136 @@ +/* + Unix SMB/CIFS implementation. + Registry interface + Copyright (C) Gerald Carter 2002. + Copyright (C) Jelmer Vernooij 2003-2004. + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _REGISTRY_H /* _REGISTRY_H */ +#define _REGISTRY_H + +/* Handles for the predefined keys */ +#define HKEY_CLASSES_ROOT 0x80000000 +#define HKEY_CURRENT_USER 0x80000001 +#define HKEY_LOCAL_MACHINE 0x80000002 +#define HKEY_USERS 0x80000003 +#define HKEY_PERFORMANCE_DATA 0x80000004 +#define HKEY_CURRENT_CONFIG 0x80000005 +#define HKEY_DYN_DATA 0x80000006 +#define HKEY_PERFORMANCE_TEXT 0x80000050 +#define HKEY_PERFORMANCE_NLSTEXT 0x80000060 + +#define REG_DELETE -1 + +/* + * The general idea here is that every backend provides a 'hive'. Combining + * various hives gives you a complete registry like windows has + */ + +#define REGISTRY_INTERFACE_VERSION 1 + +/* structure to store the registry handles */ +struct registry_key { + char *name; /* Name of the key */ + const char *path; /* Full path to the key */ + char *class_name; /* Name of key class */ + NTTIME last_mod; /* Time last modified */ + struct registry_hive *hive; + void *backend_data; +}; + +struct registry_value { + char *name; + unsigned int data_type; + DATA_BLOB data; +}; + +/* FIXME */ +typedef void (*key_notification_function) (void); +typedef void (*value_notification_function) (void); + +/* + * Container for function pointers to enumeration routines + * for virtual registry view + * + * Backends can provide : + * - just one hive (example: nt4, w95) + * - several hives (example: rpc). + * + * Backends should always do case-insensitive compares + * (everything is case-insensitive but case-preserving, + * just like the FS) + */ + +struct hive_operations { + const char *name; + + /* Implement this one */ + WERROR (*open_hive) (struct registry_hive *, struct registry_key **); + WERROR (*save_hive) (struct registry_hive *, const char *location); + + /* Or this one */ + WERROR (*open_key) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); + + WERROR (*num_subkeys) (struct registry_key *, uint32_t *count); + WERROR (*num_values) (struct registry_key *, uint32_t *count); + WERROR (*get_subkey_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_key **); + + /* Can not contain more then one level */ + WERROR (*get_subkey_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); + WERROR (*get_value_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_value **); + + /* Can not contain more then one level */ + WERROR (*get_value_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_value **); + + /* Security control */ + WERROR (*key_get_sec_desc) (TALLOC_CTX *, struct registry_key *, struct security_descriptor **); + WERROR (*key_set_sec_desc) (struct registry_key *, struct security_descriptor *); + + /* Notification */ + WERROR (*request_key_change_notify) (struct registry_key *, key_notification_function); + WERROR (*request_value_change_notify) (struct registry_value *, value_notification_function); + + /* Key management */ + WERROR (*add_key)(TALLOC_CTX *, struct registry_key *, const char *name, uint32_t access_mask, struct security_descriptor *, struct registry_key **); + WERROR (*del_key)(struct registry_key *, const char *name); + WERROR (*flush_key) (struct registry_key *); + + /* Value management */ + WERROR (*set_value)(struct registry_key *, const char *name, uint32_t type, DATA_BLOB data); + WERROR (*del_value)(struct registry_key *, const char *valname); +}; + +struct registry_hive { + const struct hive_operations *functions; + struct registry_key *root; + void *backend_data; + const char *location; +}; + +/* Handle to a full registry + * contains zero or more hives */ +struct registry_context { + void *backend_data; + WERROR (*get_predefined_key) (struct registry_context *, uint32_t hkey, struct registry_key **); +}; + +struct reg_init_function_entry { + const struct hive_operations *hive_functions; + struct reg_init_function_entry *prev, *next; +}; + +#endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 307ec3793e..3d8201330e 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -21,7 +21,7 @@ #include "includes.h" #include "dynconfig.h" -#include "registry.h" +#include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 5f7d4376d4..887f53df37 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -22,7 +22,7 @@ #include "includes.h" #include "dynconfig.h" -#include "registry.h" +#include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" #include "system/filesys.h" #include "librpc/gen_ndr/winreg.h" diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 496b9dc7e5..08da5ae2fd 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -21,9 +21,10 @@ #include "includes.h" #include "dynconfig.h" -#include "registry.h" +#include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" #include "system/time.h" +#include "librpc/gen_ndr/ndr_security.h" /* * ck/cd - change key @@ -33,19 +34,30 @@ * mkkey/mkdir - make key * ch - change hive * info - show key info + * save - save hive * help * exit */ static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { + struct security_descriptor *sec_desc = NULL; time_t last_mod; + WERROR error; + printf("Name: %s\n", cur->name); printf("Full path: %s\n", cur->path); printf("Key Class: %s\n", cur->class_name); last_mod = nt_time_to_unix(cur->last_mod); printf("Time Last Modified: %s\n", ctime(&last_mod)); - /* FIXME: Security info */ + + error = reg_get_sec_desc(mem_ctx, cur, &sec_desc); + if (!W_ERROR_IS_OK(error)) { + printf("Error getting security descriptor\n"); + } else { + ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "Security", sec_desc); + } + talloc_free(sec_desc); return cur; } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 38dffed85d..c24e66412f 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -21,7 +21,7 @@ #include "includes.h" #include "dynconfig.h" -#include "registry.h" +#include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" static void print_tree(int l, struct registry_key *p, int fullpath, int novals) -- cgit From f4910eff485b0ad786c063870ff79a9391e0927b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 17:25:04 +0000 Subject: r10027: Use blob length for keeping track of buffer length, add TODO (This used to be commit a924bec84b6d0a84db05c4315126474c9248fe2d) --- source4/lib/tdr/TODO | 2 ++ source4/lib/tdr/tdr.c | 66 +++++++++++++++++++++++++++++++++++---------------- source4/lib/tdr/tdr.h | 3 +-- 3 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 source4/lib/tdr/TODO (limited to 'source4/lib') diff --git a/source4/lib/tdr/TODO b/source4/lib/tdr/TODO new file mode 100644 index 0000000000..93c9cb255f --- /dev/null +++ b/source4/lib/tdr/TODO @@ -0,0 +1,2 @@ +- Support read/write (to fd) as well as push/pull (to DATA_BLOB) +- Specify memory context explicitly diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index e1e54622ac..fdb6f1ca6e 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -23,10 +23,11 @@ #include "includes.h" #include "system/network.h" +#include "system/filesys.h" #define TDR_BASE_MARSHALL_SIZE 1024 -#define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->offset+(n))) +#define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->data.length+(n))) #define TDR_PULL_NEED_BYTES(tdr, n) do { \ if ((n) > tdr->data.length || tdr->offset + (n) > tdr->data.length) { \ @@ -74,8 +75,8 @@ NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v) { TDR_PUSH_NEED_BYTES(tdr, 1); - TDR_SCVAL(tdr, tdr->offset, *v); - tdr->offset += 1; + TDR_SCVAL(tdr, tdr->data.length, *v); + tdr->data.length += 1; return NT_STATUS_OK; } @@ -96,8 +97,8 @@ NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, uint16_t *v) NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v) { TDR_PUSH_NEED_BYTES(tdr, 2); - TDR_SSVAL(tdr, tdr->offset, *v); - tdr->offset += 2; + TDR_SSVAL(tdr, tdr->data.length, *v); + tdr->data.length += 2; return NT_STATUS_OK; } @@ -118,8 +119,8 @@ NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint32_t *v) NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v) { TDR_PUSH_NEED_BYTES(tdr, 4); - TDR_SIVAL(tdr, tdr->offset, *v); - tdr->offset += 4; + TDR_SIVAL(tdr, tdr->data.length, *v); + tdr->data.length += 4; return NT_STATUS_OK; } @@ -172,7 +173,7 @@ NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, required = el_size * length; TDR_PUSH_NEED_BYTES(tdr, required); - ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->offset, required); + ret = convert_string(CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->data.length, required); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; @@ -180,10 +181,10 @@ NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, /* Make sure the remaining part of the string is filled with zeroes */ if (ret < required) { - memset(tdr->data.data+tdr->offset+ret, 0, required-ret); + memset(tdr->data.data+tdr->data.length+ret, 0, required-ret); } - tdr->offset += required; + tdr->data.length += required; return NT_STATUS_OK; } @@ -245,9 +246,9 @@ NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, uint64_t *v) NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v) { TDR_PUSH_NEED_BYTES(tdr, 8); - TDR_SIVAL(tdr, tdr->offset, ((*v) & 0xFFFFFFFF)); - TDR_SIVAL(tdr, tdr->offset+4, ((*v)>>32)); - tdr->offset += 8; + TDR_SIVAL(tdr, tdr->data.length, ((*v) & 0xFFFFFFFF)); + TDR_SIVAL(tdr, tdr->data.length+4, ((*v)>>32)); + tdr->data.length += 8; return NT_STATUS_OK; } @@ -318,7 +319,7 @@ NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB return NT_STATUS_OK; } -#define TDR_ALIGN(tdr,n) (((tdr)->offset & ((n)-1)) == 0?0:((n)-((tdr)->offset&((n)-1)))) +#define TDR_ALIGN(l,n) (((l) & ((n)-1)) == 0?0:((n)-((l)&((n)-1)))) /* push a DATA_BLOB onto the wire. @@ -326,16 +327,16 @@ NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob) { if (tdr->flags & TDR_ALIGN2) { - blob->length = TDR_ALIGN(tdr, 2); + blob->length = TDR_ALIGN(tdr->data.length, 2); } else if (tdr->flags & TDR_ALIGN4) { - blob->length = TDR_ALIGN(tdr, 4); + blob->length = TDR_ALIGN(tdr->data.length, 4); } else if (tdr->flags & TDR_ALIGN8) { - blob->length = TDR_ALIGN(tdr, 8); + blob->length = TDR_ALIGN(tdr->data.length, 8); } TDR_PUSH_NEED_BYTES(tdr, blob->length); - memcpy(tdr->data.data+tdr->offset, blob->data, blob->length); + memcpy(tdr->data.data+tdr->data.length, blob->data, blob->length); return NT_STATUS_OK; } @@ -347,11 +348,11 @@ NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob) uint32_t length; if (tdr->flags & TDR_ALIGN2) { - length = TDR_ALIGN(tdr, 2); + length = TDR_ALIGN(tdr->offset, 2); } else if (tdr->flags & TDR_ALIGN4) { - length = TDR_ALIGN(tdr, 4); + length = TDR_ALIGN(tdr->offset, 4); } else if (tdr->flags & TDR_ALIGN8) { - length = TDR_ALIGN(tdr, 8); + length = TDR_ALIGN(tdr->offset, 8); } else if (tdr->flags & TDR_REMAINING) { length = tdr->data.length - tdr->offset; } else { @@ -368,3 +369,26 @@ NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob) tdr->offset += length; return NT_STATUS_OK; } + +NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p) +{ + struct tdr_push *push = talloc_zero(NULL, struct tdr_push); + + if (push == NULL) + return NT_STATUS_NO_MEMORY; + + if (NT_STATUS_IS_ERR(push_fn(push, p))) { + DEBUG(1, ("Error pushing data\n")); + talloc_free(push); + return NT_STATUS_UNSUCCESSFUL; + } + + if (write(fd, push->data.data, push->data.length) < push->data.length) { + DEBUG(1, ("Error writing all data\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + talloc_free(push); + + return NT_STATUS_OK; +} diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index a37a1efaaa..fdd877f41d 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -32,7 +32,6 @@ struct tdr_pull { struct tdr_push { DATA_BLOB data; - uint32_t offset; int flags; }; @@ -53,5 +52,5 @@ struct tdr_print { if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ } while (0) -typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, void *); +typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, const void *); typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, void *); -- cgit From a487b6c19c28100041ceb2b7a5798c236983509c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 17:26:23 +0000 Subject: r10028: More registry fixes. Remove save_hive() function (there is a flush_key function already). Fixes for the allocation mechanism in the REGF backend (This used to be commit 499d03bc90382bcd33c8c3a1577a58d2c76e5129) --- source4/lib/registry/reg_backend_nt4.c | 152 ++++++++++++++++++++++++--------- source4/lib/registry/registry.h | 4 +- 2 files changed, 115 insertions(+), 41 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 4fc458dee4..4a3576f85e 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -24,12 +24,17 @@ #include "lib/registry/tdr_regf.h" #include "librpc/gen_ndr/ndr_security.h" +/* TODO: + * - Return error codes that make more sense + * - Locking + */ + /* * Read HBIN blocks into memory */ struct regf_data { - DATA_BLOB data; + int fd; struct hbin_block **hbins; struct regf_hdr *header; }; @@ -79,15 +84,19 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) hbin = hbin_by_offset(data, offset, &rel_offset); if (hbin == NULL) { - DEBUG(1, ("Can't find HBIN containing 0x%4x\n", offset)); + DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset)); return ret; } ret.length = IVAL(hbin->data, rel_offset); - if (ret.length & 0x80000000) { - /* absolute value */ - ret.length = (ret.length ^ 0xffffffff) + 1; + if (!(ret.length & 0x80000000)) { + DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset)); + return ret; } + + /* remove high bit */ + ret.length = (ret.length ^ 0xffffffff) + 1; + ret.length -= 4; /* 4 bytes for the length... */ ret.data = hbin->data + (offset - hbin->offset_from_first - 0x20) + 4; @@ -128,6 +137,9 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of struct hbin_block *hbin = NULL; int i; + if (size == 0) + return ret; + size += 4; /* Need to include uint32 for the length */ /* Allocate as a multiple of 8 */ @@ -136,9 +148,6 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of ret.data = NULL; ret.length = 0; - if (size == 0) - return ret; - for (i = 0; (hbin = data->hbins[i]); i++) { int j; uint32_t my_size; @@ -146,6 +155,11 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of my_size = IVAL(hbin->data, j); uint32_t header = IVAL(hbin->data, j + 4); + if (my_size == 0x0) { + DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); + return ret; + } + if (my_size % 8 != 0) { DEBUG(0, ("Encountered non-aligned block!\n")); } @@ -154,16 +168,20 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of my_size = (my_size ^ 0xffffffff) + 1; } else if (my_size == size) { /* exact match */ rel_offset = j; + DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n", size)); break; } else if (my_size > size) { /* data will remain */ rel_offset = j; SIVAL(hbin->data, rel_offset+size, my_size-size); + DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n", my_size, size)); break; } if (header == 0xffffffff && hbin->offset_to_next-rel_offset >= size) { rel_offset = j; + + DEBUG(4, ("Found free block of size %d at end of HBIN\n", size)); /* Mark new free block size */ SIVAL(hbin->data, rel_offset+size,hbin->offset_to_next - rel_offset - size - 0x20); SIVAL(hbin->data, rel_offset+size+0x4, 0xffffffff); @@ -182,6 +200,7 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of /* No space available in previous hbins, * allocate new one */ if (data->hbins[i] == NULL) { + DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", size)); data->hbins = talloc_realloc(data, data->hbins, struct hbin_block *, i+2); hbin = talloc(data->hbins, struct hbin_block); data->hbins[i] = hbin; @@ -202,12 +221,16 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of } /* Set size and mark as used */ - SIVAL(hbin->data, rel_offset, size & 0x80000000); + SIVAL(hbin->data, rel_offset, size | 0x80000000); ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */ ret.length = size - 0x4; - if (offset) + if (offset) { + uint32_t new_rel_offset; *offset = hbin->offset_from_first + rel_offset + 0x20; + SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin); + SMB_ASSERT(new_rel_offset == rel_offset); + } return ret; } @@ -246,7 +269,11 @@ static void hbin_free (struct regf_data *data, uint32_t offset) { uint32_t size; uint32_t rel_offset; - struct hbin_block *hbin = hbin_by_offset(data, offset, &rel_offset); + struct hbin_block *hbin; + + SMB_ASSERT (offset > 0); + + hbin = hbin_by_offset(data, offset, &rel_offset); if (hbin == NULL) return; @@ -255,12 +282,12 @@ static void hbin_free (struct regf_data *data, uint32_t offset) size = IVAL(hbin->data, rel_offset); if (!(size & 0x80000000)) { - DEBUG(1, ("Trying to free already freed block\n")); + DEBUG(1, ("Trying to free already freed block at 0x%04x\n", offset)); return; } /* Mark block as free */ - SIVAL(hbin->data, rel_offset, (size ^ 0xffffffff) + 1); + SIVAL(hbin->data, rel_offset, size &~ 0x80000000); } /* Store a data blob data was already stored, but hsa changed in size @@ -270,41 +297,48 @@ static uint32_t hbin_store_resize (struct regf_data *data, uint32_t orig_offset, { uint32_t rel_offset; struct hbin_block *hbin = hbin_by_offset(data, orig_offset, &rel_offset); + uint32_t my_size; uint32_t orig_size; uint32_t needed_size; uint32_t possible_size; int i; + SMB_ASSERT(orig_offset > 0); + if (!hbin) return hbin_store(data, blob); /* Get original size */ orig_size = IVAL(hbin->data, rel_offset); + needed_size = blob.length + 4; /* Add uint32 containing length */ + needed_size = (needed_size + 7) & ~7; /* Align */ + /* Fits into current allocated block */ - if (orig_size - 4 >= blob.length) { + if (orig_size >= needed_size) { memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); return orig_offset; } - needed_size = blob.length + 4; /* Add uint32 containing length */ - needed_size = (needed_size + 7) & ~7; /* Align */ - possible_size = orig_size; /* Check if it can be combined with the next few free records */ for (i = rel_offset; i < hbin->offset_to_next - 0x20; - i = rel_offset + possible_size) { + i += my_size) { uint32_t header; if (IVAL(hbin->data, i) & 0x80000000) /* Used */ break; + my_size = IVAL(hbin->data, i); header = IVAL(hbin->data, i + 4); if (header == 0xffffffff) { possible_size = hbin->offset_to_next - 0x20 - rel_offset; + } else if (my_size == 0x0) { + DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); + break; } else { - possible_size += IVAL(hbin->data, i); + possible_size += my_size; } if (possible_size >= blob.length) { @@ -425,7 +459,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx (*ret)->name = talloc_steal(*ret, vk->data_name); (*ret)->data_type = vk->data_type; if (vk->data_length & 0x80000000) { - vk->data_length &= ~0x80000000; + vk->data_length &=~0x80000000; (*ret)->data.data = (uint8_t *)&vk->data_offset; (*ret)->data.length = vk->data_length; } else { @@ -493,6 +527,13 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id return WERR_OK; } + +static WERROR regf_set_sec_desc (struct registry_key *key, struct security_descriptor *sec_desc) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} + static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **sd) { struct nk_block *nk = key->backend_data; @@ -543,16 +584,39 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1); lf.hr[lf.key_count].nk_off = key_offset; - lf.hr[lf.key_count].hash = name; + lf.hr[lf.key_count].hash = talloc_strndup(regf, name, 4); + lf.key_count++; ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); return ret; } +static WERROR regf_del_value (struct registry_key *parent, const char *name) +{ + /* FIXME */ + return WERR_NOT_SUPPORTED; +} + + +static WERROR regf_del_key (struct registry_key *parent, const char *name) +{ + struct nk_block *nk = parent->backend_data; + + SMB_ASSERT(nk); + + if (nk->subkeys_offset == -1) + return WERR_BADFILE; + + /* FIXME */ + + return WERR_NOT_SUPPORTED; +} + static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) { struct nk_block *parent_nk = parent->backend_data, nk; + struct regf_data *regf = parent->hive->backend_data; uint32_t offset; nk.header = "nk"; @@ -571,17 +635,17 @@ static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const nk.clsname_length = 0; nk.key_name = name; - offset = hbin_store_tdr(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, &nk); + offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk); - parent_nk->subkeys_offset = lf_add_entry(parent->hive->backend_data, parent_nk->subkeys_offset, name, nk.parent_offset); + parent_nk->subkeys_offset = lf_add_entry(regf, parent_nk->subkeys_offset, name, nk.parent_offset); parent_nk->num_subkeys++; - hbin_store_tdr_resize(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); - /* FIXME: Set sec desc ! */ + *ret = regf_get_key(ctx, regf, offset); - *ret = regf_get_key(ctx, parent->hive->backend_data, offset); + /* FIXME: Set sec desc ! */ return WERR_OK; } @@ -592,19 +656,20 @@ static WERROR regf_set_value (struct registry_key *key, const char *name, uint32 return WERR_NOT_SUPPORTED; } -static WERROR regf_save(struct registry_hive *hive, const char *location) +static WERROR regf_save_hbin(struct registry_hive *hive, struct hbin_block *hbin) { struct regf_data *regf = hive->backend_data; - struct tdr_push *push = talloc_zero(regf, struct tdr_push); - int i; - tdr_push_regf_hdr(push, regf->header); - - for (i = 0; regf->hbins[i]; i++) { - tdr_push_hbin_block(push, regf->hbins[i]); + /* go to right offset */ + if (lseek(regf->fd, SEEK_SET, regf->header->data_offset + hbin->offset_from_first) == -1) { + DEBUG(0, ("Error lseeking in regf file\n")); + return WERR_GENERAL_FAILURE; } - file_save(location, push->data.data, push->data.length); + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, (tdr_push_fn_t)tdr_push_hbin_block, hbin))) { + DEBUG(0, ("Error writing HBIN block\n")); + return WERR_GENERAL_FAILURE; + } return WERR_OK; } @@ -622,9 +687,9 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) DEBUG(5, ("Attempting to load registry file\n")); /* Get the header */ + regf->fd = open(h->location, O_RDWR); - regf->data.data = (uint8_t *)file_load(h->location, ®f->data.length, regf); - if (regf->data.data == NULL) { + if (regf->fd == -1) { DEBUG(0,("Could not load file: %s, %s\n", h->location, strerror(errno))); return WERR_GENERAL_FAILURE; @@ -634,7 +699,12 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) if (!pull) return WERR_NOMEM; - pull->data = regf->data; + pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf); + + if (pull->data.data == NULL) { + DEBUG(0, ("Error reading data\n")); + return WERR_GENERAL_FAILURE; + } regf_hdr = talloc(regf, struct regf_hdr); if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr))) { @@ -656,9 +726,9 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) /* * Validate the header ... */ - if (regf_hdr_checksum(regf->data.data) != regf_hdr->chksum) { + if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) { DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", - h->location, regf_hdr->chksum, regf_hdr_checksum(regf->data.data))); + h->location, regf_hdr->chksum, regf_hdr_checksum(pull->data.data))); return WERR_GENERAL_FAILURE; } @@ -703,9 +773,11 @@ static struct hive_operations reg_backend_nt4 = { .get_subkey_by_index = regf_get_subkey, .get_value_by_index = regf_get_value, .key_get_sec_desc = regf_get_sec_desc, + .key_set_sec_desc = regf_set_sec_desc, .add_key = regf_add_key, .set_value = regf_set_value, - .save_hive = regf_save, + .del_key = regf_del_key, + .del_value = regf_del_value, }; NTSTATUS registry_nt4_init(void) diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index f9e8a7698c..e843e1a0be 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -73,6 +73,9 @@ typedef void (*value_notification_function) (void); * Backends should always do case-insensitive compares * (everything is case-insensitive but case-preserving, * just like the FS) + * + * There is no save function as all operations are expected to + * be atomic. */ struct hive_operations { @@ -80,7 +83,6 @@ struct hive_operations { /* Implement this one */ WERROR (*open_hive) (struct registry_hive *, struct registry_key **); - WERROR (*save_hive) (struct registry_hive *, const char *location); /* Or this one */ WERROR (*open_key) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); -- cgit From a3e0e69196cc5e3420ebb1a83b026ee36cbaab83 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 20:17:21 +0000 Subject: r10030: Add hierarchical memory allocation to TDR's pull functions (This used to be commit 0e358de93a007db921ad5e9a892114122254de39) --- source4/lib/registry/config.mk | 1 - source4/lib/registry/reg_backend_nt4.c | 61 +++++++++++++++------------------- source4/lib/tdr/TODO | 1 - source4/lib/tdr/tdr.c | 28 ++++++++-------- source4/lib/tdr/tdr.h | 6 ++-- 5 files changed, 44 insertions(+), 53 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index a1bb62f7df..43149f88aa 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -17,7 +17,6 @@ NOPROTO = YES INIT_OBJ_FILES = lib/registry/tdr_regf.o lib/registry/tdr_regf.c: lib/registry/regf.idl - @echo "Compiling lib/registry/regf.idl" @./pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl ################################################ diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 4a3576f85e..f31a2f52e7 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -104,28 +104,23 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) return ret; } -static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, tdr_pull_fn_t pull_fn, void *p) +static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) { - DATA_BLOB data; - struct tdr_pull *pull; + struct tdr_pull pull; - data = hbin_get(regf, offset); - if (!data.data) { + ZERO_STRUCT(pull); + + pull.data = hbin_get(regf, offset); + if (!pull.data.data) { DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); return False; } - pull = talloc_zero(regf, struct tdr_pull); - pull->data = data; - - if (NT_STATUS_IS_ERR(pull_fn(pull, p))) { + if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) { DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); - talloc_free(pull); return False; } - /* FIXME: Free pull ! */ - return True; } @@ -397,7 +392,7 @@ static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *reg ret = talloc_zero(ctx, struct registry_key); nk = talloc(ret, struct nk_block); - if (!hbin_get_tdr(regf, offset, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { + if (!hbin_get_tdr(regf, offset, nk, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return NULL; } @@ -451,7 +446,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx if (!vk) return WERR_NOMEM; - if (!hbin_get_tdr(regf, vk_offset, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { + if (!hbin_get_tdr(regf, vk_offset, vk, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); return WERR_GENERAL_FAILURE; } @@ -493,12 +488,13 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id SMB_ASSERT(0); } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; - struct tdr_pull *pull = talloc_zero(ctx, struct tdr_pull); + struct tdr_pull pull; DEBUG(10, ("Subkeys in LF list\n")); - pull->data = data; + ZERO_STRUCT(pull); + pull.data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) { + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); return WERR_GENERAL_FAILURE; } @@ -509,8 +505,6 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id } key_off = lf.hr[idx].nk_off; - - talloc_free(pull); } else if (!strncmp((char *)data.data, "ri", 2)) { DEBUG(4, ("Subkeys in RI list\n")); SMB_ASSERT(0); @@ -541,7 +535,7 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc struct regf_data *regf = key->hive->backend_data; DATA_BLOB data; - if (!hbin_get_tdr(regf, nk->sk_offset, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + if (!hbin_get_tdr(regf, nk->sk_offset, ctx, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_GENERAL_FAILURE; } @@ -576,7 +570,7 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons lf.key_count = 0; lf.hr = NULL; } else { - if (!hbin_get_tdr(regf, list_offset, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) { + if (!hbin_get_tdr(regf, list_offset, regf, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) { DEBUG(0, ("Can't get subkeys list\n")); return -1; } @@ -588,6 +582,8 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons lf.key_count++; ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); + + talloc_free(lf.hr); return ret; } @@ -678,7 +674,7 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { struct regf_data *regf; struct regf_hdr *regf_hdr; - struct tdr_pull *pull; + struct tdr_pull pull; int i; regf = (struct regf_data *)talloc_zero(h, struct regf_data); @@ -695,19 +691,16 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) return WERR_GENERAL_FAILURE; } - pull = talloc_zero(regf, struct tdr_pull); - if (!pull) - return WERR_NOMEM; - - pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf); + ZERO_STRUCT(pull); + pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf); - if (pull->data.data == NULL) { + if (pull.data.data == NULL) { DEBUG(0, ("Error reading data\n")); return WERR_GENERAL_FAILURE; } regf_hdr = talloc(regf, struct regf_hdr); - if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr))) { + if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) { return WERR_GENERAL_FAILURE; } @@ -726,23 +719,23 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) /* * Validate the header ... */ - if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) { + if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) { DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", - h->location, regf_hdr->chksum, regf_hdr_checksum(pull->data.data))); + h->location, regf_hdr->chksum, regf_hdr_checksum(pull.data.data))); return WERR_GENERAL_FAILURE; } - pull->offset = 0x1000; + pull.offset = 0x1000; i = 0; /* Read in all hbin blocks */ regf->hbins = talloc_array(regf, struct hbin_block *, 1); regf->hbins[0] = NULL; - while (pull->offset < pull->data.length) { + while (pull.offset < pull.data.length) { struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); - if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin))) { + if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) { DEBUG(0, ("[%d] Error parsing HBIN block\n", i)); return WERR_FOOBAR; } diff --git a/source4/lib/tdr/TODO b/source4/lib/tdr/TODO index 93c9cb255f..5093afd438 100644 --- a/source4/lib/tdr/TODO +++ b/source4/lib/tdr/TODO @@ -1,2 +1 @@ - Support read/write (to fd) as well as push/pull (to DATA_BLOB) -- Specify memory context explicitly diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index fdb6f1ca6e..34611683e2 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -64,7 +64,7 @@ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) } -NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v) +NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v) { TDR_PULL_NEED_BYTES(tdr, 1); *v = TDR_CVAL(tdr, tdr->offset); @@ -86,7 +86,7 @@ NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, uint16_t *v) +NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v) { TDR_PULL_NEED_BYTES(tdr, 2); *v = TDR_SVAL(tdr, tdr->offset); @@ -108,7 +108,7 @@ NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint32_t *v) +NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v) { TDR_PULL_NEED_BYTES(tdr, 4); *v = TDR_IVAL(tdr, tdr->offset); @@ -130,7 +130,7 @@ NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v) return NT_STATUS_OK; } -NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, uint32_t el_size, int chset) +NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, int chset) { int ret; @@ -149,13 +149,13 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, } if (length == 0) { - *v = talloc_strdup(tdr, ""); + *v = talloc_strdup(ctx, ""); return NT_STATUS_OK; } TDR_PULL_NEED_BYTES(tdr, el_size*length); - ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v)); + ret = convert_string_talloc(ctx, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v)); if (ret == -1) { return NT_STATUS_INVALID_PARAMETER; @@ -198,10 +198,10 @@ NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char * /* pull a ipv4address */ -NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, const char **address) +NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **address) { struct ipv4_addr in; - TDR_CHECK(tdr_pull_uint32(tdr, &in.addr)); + TDR_CHECK(tdr_pull_uint32(tdr, ctx, &in.addr)); in.addr = htonl(in.addr); *address = talloc_strdup(tdr, sys_inet_ntoa(in)); NT_STATUS_HAVE_NO_MEMORY(*address); @@ -231,7 +231,7 @@ NTSTATUS tdr_print_ipv4address(struct tdr_print *tdr, const char *name, /* parse a hyper */ -NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, uint64_t *v) +NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v) { TDR_PULL_NEED_BYTES(tdr, 8); *v = TDR_IVAL(tdr, tdr->offset); @@ -266,9 +266,9 @@ NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t) /* pull a NTTIME */ -NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, NTTIME *t) +NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t) { - TDR_CHECK(tdr_pull_hyper(tdr, t)); + TDR_CHECK(tdr_pull_hyper(tdr, ctx, t)); return NT_STATUS_OK; } @@ -283,10 +283,10 @@ NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t) /* pull a time_t */ -NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, time_t *t) +NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t) { uint32_t tt; - TDR_CHECK(tdr_pull_uint32(tdr, &tt)); + TDR_CHECK(tdr_pull_uint32(tdr, ctx, &tt)); *t = tt; return NT_STATUS_OK; } @@ -343,7 +343,7 @@ NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob) /* pull a DATA_BLOB from the wire. */ -NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob) +NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob) { uint32_t length; diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index fdd877f41d..f882a63275 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -47,10 +47,10 @@ struct tdr_print { return _status; \ } while (0) -#define TDR_ALLOC(tdr, s, n) do { \ - (s) = talloc_array_size(tdr, sizeof(*(s)), n); \ +#define TDR_ALLOC(ctx, s, n) do { \ + (s) = talloc_array_size(ctx, sizeof(*(s)), n); \ if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ } while (0) typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, const void *); -typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, void *); +typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, TALLOC_CTX *, void *); -- cgit From 3ca370b3db92c12d6dc649e93b33febd248a945f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Sep 2005 18:11:15 +0000 Subject: r10038: Update instructions on using gcov with ldb (This used to be commit 8d246fac49332426699e797f52ef694083b5e2ea) --- source4/lib/ldb/README_gcov.txt | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/README_gcov.txt b/source4/lib/ldb/README_gcov.txt index 9684379c6e..2abd9378f4 100644 --- a/source4/lib/ldb/README_gcov.txt +++ b/source4/lib/ldb/README_gcov.txt @@ -1,18 +1,14 @@ Here is how to use gcov to test code coverage in ldb. -Step 1: enable gcov support +Step 1: build ldb with gcov enabled - Edit Makefile.ldb and uncommend the two GCOV_ lines - -Step 2: build ldb - - make -sf Makefile.ldb clean all + make clean all WITH_GCOV=1 Step 3: run the test suite - make -sf Makefile.ldb test-tdb + make test-tdb Step 4: produce the gcov report - make -sf Makefile.ldb gcov + make gcov Step 5: read the summary reports less *.report.gcov @@ -22,7 +18,7 @@ Step 6: examine the per-file reports You can also combine steps 2 to 4 like this: - make -sf Makefile.ldb clean all test-tdb gcov + make clean all test-tdb gcov WITH_GCOV=1 Note that you should not expect 100% coverage, as some error paths (such as memory allocation failures) are very hard to trigger. There -- cgit From e3a1ee4788788307d9bffaca9ee63f2bf4614967 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 5 Sep 2005 20:56:28 +0000 Subject: r10043: Only recompile subsystems that actually need recompilation (This used to be commit de9830979788528754175b17fe45477e6ce9ce9e) --- source4/lib/registry/config.mk | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 43149f88aa..d0939c720b 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -16,6 +16,7 @@ REQUIRED_SUBSYSTEMS = TDR NOPROTO = YES INIT_OBJ_FILES = lib/registry/tdr_regf.o +lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c lib/registry/tdr_regf.c: lib/registry/regf.idl @./pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl -- cgit From db400b4a58d834cca165f1fc6ad84e9f5ace280f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 6 Sep 2005 15:44:08 +0000 Subject: r10052: Add 'print' command (This used to be commit d99c9e2817fbbe2a0a34910672c8473889bc6176) --- source4/lib/registry/tools/regshell.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 08da5ae2fd..24979943b3 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -35,6 +35,7 @@ * ch - change hive * info - show key info * save - save hive + * print - print value * help * exit */ @@ -123,6 +124,26 @@ static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_context return new; } +static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) +{ + struct registry_value *value; + WERROR error; + + if (argc != 2) { + fprintf(stderr, "Usage: print "); + return NULL; + } + + error = reg_key_get_value_by_name(mem_ctx, cur, argv[1], &value); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "No such value '%s'\n", argv[1]); + return NULL; + } + + printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); + return NULL; +} + static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv) { int i; @@ -208,6 +229,7 @@ static struct { {"ck", "cd", "Change current key", cmd_ck }, {"info", "i", "Show detailed information of a key", cmd_info }, {"list", "ls", "List values/keys in current key", cmd_ls }, + {"print", "p", "Print value", cmd_print }, {"mkkey", "mkdir", "Make new key", cmd_mkkey }, {"rmval", "rm", "Remove value", cmd_rmval }, {"rmkey", "rmdir", "Remove key", cmd_rmkey }, -- cgit From c070fd62228a4fb0af0d275edc3d141e44dff389 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 8 Sep 2005 10:35:55 +0000 Subject: r10074: Pass CPP to pidl via environment variables rather then config.pm. This fixes the standalone pidl build (as used for ethereal) (This used to be commit 9c9ebd2214423c58357854f09bd744e13e807d8f) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index d0939c720b..4a518321a4 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -18,7 +18,7 @@ INIT_OBJ_FILES = lib/registry/tdr_regf.o lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c lib/registry/tdr_regf.c: lib/registry/regf.idl - @./pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl + @CPP="$(CPP) $(PERL) pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl ################################################ # Start MODULE registry_w95 -- cgit From a769fa3467e836c6074314d6a67a2a64a96baa9e Mon Sep 17 00:00:00 2001 From: Rafal Szczesniak Date: Thu, 8 Sep 2005 19:58:59 +0000 Subject: r10089: Fix a typo breaking the Makefile generator and therefore - the build. rafal (This used to be commit d6936185d5e4a85b188d5117d7a3b3d6bea2f96b) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 4a518321a4..b68046ca69 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -18,7 +18,7 @@ INIT_OBJ_FILES = lib/registry/tdr_regf.o lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c lib/registry/tdr_regf.c: lib/registry/regf.idl - @CPP="$(CPP) $(PERL) pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl + @CPP="$(CPP)" $(PERL) pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl ################################################ # Start MODULE registry_w95 -- cgit From 289127b0262246147c370f3261ce94b0e3669969 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 9 Sep 2005 04:22:58 +0000 Subject: r10104: Fix code before declaration. (This used to be commit 05c020181560afd4e6957be29795536e2d83d71e) --- source4/lib/registry/reg_backend_nt4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index f31a2f52e7..e5c0221504 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -147,8 +147,8 @@ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *of int j; uint32_t my_size; for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) { - my_size = IVAL(hbin->data, j); uint32_t header = IVAL(hbin->data, j + 4); + my_size = IVAL(hbin->data, j); if (my_size == 0x0) { DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); -- cgit From 8b5a9537250e2d55a782c40f51fbedafa3d6bee7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 9 Sep 2005 10:59:54 +0000 Subject: r10111: Make pidl by default assume the input file is an IDL file rather then a .pidl file. (This used to be commit d8a31d3048a6421a3d49d3c121bc86d748838b3a) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index b68046ca69..4cf73bf66a 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -18,7 +18,7 @@ INIT_OBJ_FILES = lib/registry/tdr_regf.o lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c lib/registry/tdr_regf.c: lib/registry/regf.idl - @CPP="$(CPP)" $(PERL) pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl + @CPP="$(CPP)" $(PERL) pidl/pidl --header --outputdir=lib/registry --tdr-header --tdr-parser -- lib/registry/regf.idl ################################################ # Start MODULE registry_w95 -- cgit From 3818f7793b2d63d3a6deeae881dc19482602b1c0 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 12 Sep 2005 02:34:22 +0000 Subject: r10161: Check for alloca.h to prevent incorrect local declaration. (This used to be commit efc70d267285a94bcadd690ae4392d278cdeea94) --- source4/lib/popt/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/popt/config.m4 b/source4/lib/popt/config.m4 index d5a8df9200..227c9a1237 100644 --- a/source4/lib/popt/config.m4 +++ b/source4/lib/popt/config.m4 @@ -38,4 +38,4 @@ else AC_MSG_RESULT(no) fi -AC_CHECK_HEADERS([float.h]) +AC_CHECK_HEADERS([float.h alloca.h]) -- cgit From 45f760973d9b5c0663608e779eb337c0648e9313 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Sep 2005 12:46:03 +0000 Subject: r10200: added a composite_trigger_done() call that allows a composite function to cause an event to happen immediately. This allows metzes patch for recognising IPs in resolve_name() to work, and also allows us to remove some of the other code where we currently do specific checks for is_ipaddress(). (This used to be commit 9cc000d868e1257ef6429f6f6f1f9d3c28ca330f) --- source4/lib/socket/connect.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c index bb4d7cc843..04902442e3 100644 --- a/source4/lib/socket/connect.c +++ b/source4/lib/socket/connect.c @@ -36,11 +36,6 @@ static NTSTATUS connect_resolve(TALLOC_CTX *mem_ctx, const char *address, { struct nbt_name name; - if (is_ipaddress(address) || strcasecmp("localhost", address) == 0) { - *ret_address = address; - return NT_STATUS_OK; - } - name.name = address; name.scope = NULL; name.type = NBT_NAME_CLIENT; -- cgit From 5d2c2edc19d471cb2b757c53eeb007f4dd7f9348 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 13 Sep 2005 17:28:18 +0000 Subject: r10207: Add some const (This used to be commit b1ad340b4720e922ae1e332c2a74986b1656358b) --- source4/lib/registry/common/reg_interface.c | 29 +++++++--------- source4/lib/registry/reg_backend_dir.c | 8 ++--- source4/lib/registry/reg_backend_ldb.c | 16 ++++----- source4/lib/registry/reg_backend_nt4.c | 20 +++++------ source4/lib/registry/reg_backend_rpc.c | 18 +++++----- source4/lib/registry/reg_backend_w95.c | 6 ++-- source4/lib/registry/regf.idl | 2 +- source4/lib/registry/registry.h | 53 +++++++++++++++-------------- 8 files changed, 75 insertions(+), 77 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index 74f158b027..7a35c97c43 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -237,7 +237,7 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char return WERR_OK; } -WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_value **val) +WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val) { if(!key) return WERR_INVALID_PARAM; @@ -252,7 +252,7 @@ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_OK; } -WERROR reg_key_num_subkeys(struct registry_key *key, uint32_t *count) +WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count) { if(!key) return WERR_INVALID_PARAM; @@ -277,7 +277,7 @@ WERROR reg_key_num_subkeys(struct registry_key *key, uint32_t *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_num_values(struct registry_key *key, uint32_t *count) +WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count) { if(!key) return WERR_INVALID_PARAM; @@ -303,7 +303,7 @@ WERROR reg_key_num_values(struct registry_key *key, uint32_t *count) return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key, int idx, struct registry_key **subkey) +WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey) { if(!key) return WERR_INVALID_PARAM; @@ -323,7 +323,7 @@ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *key return WERR_OK;; } -WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_key **subkey) +WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey) { int i; WERROR error = WERR_OK; @@ -356,7 +356,7 @@ WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_OK; } -WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, const char *name, struct registry_value **val) +WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val) { int i; WERROR error = WERR_OK; @@ -395,7 +395,7 @@ WERROR reg_key_del(struct registry_key *parent, const char *name) return WERR_OK; } -WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey) +WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey) { WERROR error; @@ -432,7 +432,7 @@ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, D } -WERROR reg_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **secdesc) +WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc) { /* A 'real' set function has preference */ if (key->hive->functions->key_get_sec_desc) @@ -442,7 +442,7 @@ WERROR reg_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct securi return WERR_NOT_SUPPORTED; } -WERROR reg_del_value(struct registry_key *key, const char *valname) +WERROR reg_del_value(const struct registry_key *key, const char *valname) { WERROR ret = WERR_OK; if(!key->hive->functions->del_value) @@ -455,12 +455,7 @@ WERROR reg_del_value(struct registry_key *key, const char *valname) return ret; } -WERROR reg_save (struct registry_context *ctx, const char *location) -{ - return WERR_NOT_SUPPORTED; -} - -WERROR reg_key_flush(struct registry_key *key) +WERROR reg_key_flush(const struct registry_key *key) { if (!key) { return WERR_INVALID_PARAM; @@ -474,7 +469,7 @@ WERROR reg_key_flush(struct registry_key *key) return WERR_OK; } -WERROR reg_key_subkeysizes(struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize) +WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize) { int i = 0; struct registry_key *subkey; @@ -499,7 +494,7 @@ WERROR reg_key_subkeysizes(struct registry_key *key, uint32_t *max_subkeylen, ui return WERR_OK; } -WERROR reg_key_valuesizes(struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize) +WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize) { int i = 0; struct registry_value *value; diff --git a/source4/lib/registry/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 68f02d1745..da22d8d9ee 100644 --- a/source4/lib/registry/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -23,7 +23,7 @@ #include "system/dir.h" #include "system/filesys.h" -static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result) +static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result) { char *path; int ret; @@ -35,7 +35,7 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, return WERR_INVALID_PARAM; } -static WERROR reg_dir_del_key(struct registry_key *k, const char *name) +static WERROR reg_dir_del_key(const struct registry_key *k, const char *name) { char *child = talloc_asprintf(NULL, "%s/%s", (char *)k->backend_data, name); WERROR ret; @@ -47,7 +47,7 @@ static WERROR reg_dir_del_key(struct registry_key *k, const char *name) return ret; } -static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, struct registry_key **subkey) +static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *p, const char *name, struct registry_key **subkey) { DIR *d; char *fullpath, *unixpath; @@ -76,7 +76,7 @@ static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, cons return WERR_OK; } -static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **key) +static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **key) { struct dirent *e; char *fullpath = k->backend_data; diff --git a/source4/lib/registry/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index f51c02a286..469961dfb4 100644 --- a/source4/lib/registry/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -112,7 +112,7 @@ static int reg_close_ldb_key (void *data) return 0; } -static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, const char *path, const char *add) +static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const struct registry_key *from, const char *path, const char *add) { TALLOC_CTX *local_ctx; struct ldb_dn *ret = ldb_dn_new(mem_ctx); @@ -153,7 +153,7 @@ static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key * } -static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey) +static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **subkey) { struct ldb_context *c = k->hive->backend_data; struct ldb_message_element *el; @@ -184,7 +184,7 @@ static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, return WERR_OK; } -static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) +static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value) { struct ldb_context *c = k->hive->backend_data; struct ldb_key_data *kd = k->backend_data; @@ -208,7 +208,7 @@ static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i return WERR_OK; } -static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) +static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key) { struct ldb_context *c = h->hive->backend_data; struct ldb_message **msg; @@ -265,7 +265,7 @@ static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) return WERR_OK; } -static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey) +static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey) { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message *msg; @@ -293,7 +293,7 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con return WERR_OK; } -static WERROR ldb_del_key (struct registry_key *key, const char *child) +static WERROR ldb_del_key (const struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; @@ -312,7 +312,7 @@ static WERROR ldb_del_key (struct registry_key *key, const char *child) return WERR_OK; } -static WERROR ldb_del_value (struct registry_key *key, const char *child) +static WERROR ldb_del_value (const struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; @@ -331,7 +331,7 @@ static WERROR ldb_del_value (struct registry_key *key, const char *child) return WERR_OK; } -static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data) +static WERROR ldb_set_value (const struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data) { struct ldb_context *ctx = parent->hive->backend_data; struct ldb_message *msg; diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index e5c0221504..4d33f481e6 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -367,7 +367,7 @@ static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t pus return ret; } -static WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) +static WERROR regf_num_subkeys (const struct registry_key *key, uint32_t *count) { struct nk_block *nk = key->backend_data; @@ -376,7 +376,7 @@ static WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) return WERR_OK; } -static WERROR regf_num_values (struct registry_key *key, uint32_t *count) +static WERROR regf_num_values (const struct registry_key *key, uint32_t *count) { struct nk_block *nk = key->backend_data; @@ -415,7 +415,7 @@ static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *reg return ret; } -static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx, struct registry_value **ret) +static WERROR regf_get_value (TALLOC_CTX *ctx, const struct registry_key *key, int idx, struct registry_value **ret) { struct nk_block *nk = key->backend_data; struct vk_block *vk; @@ -468,7 +468,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx return WERR_OK; } -static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int idx, struct registry_key **ret) +static WERROR regf_get_subkey (TALLOC_CTX *ctx, const struct registry_key *key, int idx, struct registry_key **ret) { DATA_BLOB data; struct nk_block *nk = key->backend_data; @@ -522,13 +522,13 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id } -static WERROR regf_set_sec_desc (struct registry_key *key, struct security_descriptor *sec_desc) +static WERROR regf_set_sec_desc (const struct registry_key *key, const struct security_descriptor *sec_desc) { /* FIXME */ return WERR_NOT_SUPPORTED; } -static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **sd) +static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **sd) { struct nk_block *nk = key->backend_data; struct sk_block sk; @@ -588,14 +588,14 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons return ret; } -static WERROR regf_del_value (struct registry_key *parent, const char *name) +static WERROR regf_del_value (const struct registry_key *parent, const char *name) { /* FIXME */ return WERR_NOT_SUPPORTED; } -static WERROR regf_del_key (struct registry_key *parent, const char *name) +static WERROR regf_del_key (const struct registry_key *parent, const char *name) { struct nk_block *nk = parent->backend_data; @@ -609,7 +609,7 @@ static WERROR regf_del_key (struct registry_key *parent, const char *name) return WERR_NOT_SUPPORTED; } -static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) +static WERROR regf_add_key (TALLOC_CTX *ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) { struct nk_block *parent_nk = parent->backend_data, nk; struct regf_data *regf = parent->hive->backend_data; @@ -645,7 +645,7 @@ static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const return WERR_OK; } -static WERROR regf_set_value (struct registry_key *key, const char *name, uint32_t type, DATA_BLOB data) +static WERROR regf_set_value (const struct registry_key *key, const char *name, uint32_t type, const DATA_BLOB data) { /* FIXME */ diff --git a/source4/lib/registry/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index a00accc6be..1e9fff4d7c 100644 --- a/source4/lib/registry/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -81,7 +81,7 @@ static struct { { 0, NULL } }; -static WERROR rpc_query_key(struct registry_key *k); +static WERROR rpc_query_key(const struct registry_key *k); static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hkey_type, struct registry_key **k) { @@ -137,7 +137,7 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) } #endif -static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key) +static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key) { struct rpc_key_data *mykeydata; struct winreg_OpenKey r; @@ -163,7 +163,7 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const ch return r.out.result; } -static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_value **value) +static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_value **value) { struct rpc_key_data *mykeydata = parent->backend_data; WERROR error; @@ -211,7 +211,7 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, struct registry_key *p return r.out.result; } -static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **subkey) +static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **subkey) { struct winreg_EnumKey r; struct rpc_key_data *mykeydata = parent->backend_data; @@ -242,7 +242,7 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, struct registry_key * return r.out.result; } -static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key) +static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key) { NTSTATUS status; struct winreg_CreateKey r; @@ -272,7 +272,7 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, cons return r.out.result; } -static WERROR rpc_query_key(struct registry_key *k) +static WERROR rpc_query_key(const struct registry_key *k) { NTSTATUS status; struct winreg_QueryInfoKey r; @@ -300,7 +300,7 @@ static WERROR rpc_query_key(struct registry_key *k) return r.out.result; } -static WERROR rpc_del_key(struct registry_key *parent, const char *name) +static WERROR rpc_del_key(const struct registry_key *parent, const char *name) { NTSTATUS status; struct rpc_key_data *mykeydata = parent->backend_data; @@ -317,7 +317,7 @@ static WERROR rpc_del_key(struct registry_key *parent, const char *name) return r.out.result; } -static WERROR rpc_num_values(struct registry_key *key, uint32_t *count) +static WERROR rpc_num_values(const struct registry_key *key, uint32_t *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; @@ -331,7 +331,7 @@ static WERROR rpc_num_values(struct registry_key *key, uint32_t *count) return WERR_OK; } -static WERROR rpc_num_subkeys(struct registry_key *key, uint32_t *count) +static WERROR rpc_num_subkeys(const struct registry_key *key, uint32_t *count) { struct rpc_key_data *mykeydata = key->backend_data; WERROR error; diff --git a/source4/lib/registry/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index 03460052da..d5ce0e33f8 100644 --- a/source4/lib/registry/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -267,7 +267,7 @@ static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) return WERR_OK; } -static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key *parent, int n, struct registry_key **key) +static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **key) { CREG *creg = parent->hive->backend_data; RGKN_KEY *rgkn_key = parent->backend_data; @@ -303,7 +303,7 @@ static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, struct registry_key return WERR_NO_MORE_ITEMS; } -static WERROR w95_num_values(struct registry_key *k, uint32_t *count) +static WERROR w95_num_values(const struct registry_key *k, uint32_t *count) { RGKN_KEY *rgkn_key = k->backend_data; RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id); @@ -315,7 +315,7 @@ static WERROR w95_num_values(struct registry_key *k, uint32_t *count) return WERR_OK; } -static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value) +static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value) { RGKN_KEY *rgkn_key = k->backend_data; DWORD i; diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl index 85a879cc36..dcb1df039b 100644 --- a/source4/lib/registry/regf.idl +++ b/source4/lib/registry/regf.idl @@ -51,7 +51,7 @@ interface regf } regf_hdr; /* - hbin probably means hive-bin (what bin stands for I don't know) + hbin probably means hive-bin (i.e. hive-container) This block is always a multiple of 4kb in size. */ diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index e843e1a0be..69f3606736 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -43,24 +43,26 @@ #define REGISTRY_INTERFACE_VERSION 1 /* structure to store the registry handles */ -struct registry_key { - char *name; /* Name of the key */ - const char *path; /* Full path to the key */ - char *class_name; /* Name of key class */ - NTTIME last_mod; /* Time last modified */ +struct registry_key +{ + char *name; + const char *path; + char *class_name; + NTTIME last_mod; struct registry_hive *hive; void *backend_data; }; -struct registry_value { +struct registry_value +{ char *name; unsigned int data_type; DATA_BLOB data; }; /* FIXME */ -typedef void (*key_notification_function) (void); -typedef void (*value_notification_function) (void); +typedef void (*reg_key_notification_function) (void); +typedef void (*reg_value_notification_function) (void); /* * Container for function pointers to enumeration routines @@ -85,38 +87,39 @@ struct hive_operations { WERROR (*open_hive) (struct registry_hive *, struct registry_key **); /* Or this one */ - WERROR (*open_key) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); + WERROR (*open_key) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **); - WERROR (*num_subkeys) (struct registry_key *, uint32_t *count); - WERROR (*num_values) (struct registry_key *, uint32_t *count); - WERROR (*get_subkey_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_key **); + WERROR (*num_subkeys) (const struct registry_key *, uint32_t *count); + WERROR (*num_values) (const struct registry_key *, uint32_t *count); + WERROR (*get_subkey_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_key **); /* Can not contain more then one level */ - WERROR (*get_subkey_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_key **); - WERROR (*get_value_by_index) (TALLOC_CTX *, struct registry_key *, int idx, struct registry_value **); + WERROR (*get_subkey_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **); + WERROR (*get_value_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_value **); /* Can not contain more then one level */ - WERROR (*get_value_by_name) (TALLOC_CTX *, struct registry_key *, const char *name, struct registry_value **); + WERROR (*get_value_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_value **); /* Security control */ - WERROR (*key_get_sec_desc) (TALLOC_CTX *, struct registry_key *, struct security_descriptor **); - WERROR (*key_set_sec_desc) (struct registry_key *, struct security_descriptor *); + WERROR (*key_get_sec_desc) (TALLOC_CTX *, const struct registry_key *, struct security_descriptor **); + WERROR (*key_set_sec_desc) (const struct registry_key *, const struct security_descriptor *); /* Notification */ - WERROR (*request_key_change_notify) (struct registry_key *, key_notification_function); - WERROR (*request_value_change_notify) (struct registry_value *, value_notification_function); + WERROR (*request_key_change_notify) (const struct registry_key *, reg_key_notification_function); + WERROR (*request_value_change_notify) (const struct registry_value *, reg_value_notification_function); /* Key management */ - WERROR (*add_key)(TALLOC_CTX *, struct registry_key *, const char *name, uint32_t access_mask, struct security_descriptor *, struct registry_key **); - WERROR (*del_key)(struct registry_key *, const char *name); - WERROR (*flush_key) (struct registry_key *); + WERROR (*add_key)(TALLOC_CTX *, const struct registry_key *, const char *name, uint32_t access_mask, struct security_descriptor *, struct registry_key **); + WERROR (*del_key)(const struct registry_key *, const char *name); + WERROR (*flush_key) (const struct registry_key *); /* Value management */ - WERROR (*set_value)(struct registry_key *, const char *name, uint32_t type, DATA_BLOB data); - WERROR (*del_value)(struct registry_key *, const char *valname); + WERROR (*set_value)(const struct registry_key *, const char *name, uint32_t type, const DATA_BLOB data); + WERROR (*del_value)(const struct registry_key *, const char *valname); }; -struct registry_hive { +struct registry_hive +{ const struct hive_operations *functions; struct registry_key *root; void *backend_data; -- cgit From 2b2e1337523aa45f2028c15d46471e59e898ee50 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Sep 2005 22:39:24 +0000 Subject: r10231: seem I flipped these, fix. (This used to be commit 8ddf4de162f42ed53ab0603dd0e1536796f9197e) --- source4/lib/ldb/common/ldb_dn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index d1a311dad6..2cd7d590fe 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -518,12 +518,12 @@ int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1) if (dn0 == NULL || dn1 == NULL) return dn1 - dn0; edn0 = ldb_dn_explode_casefold(ldb, dn0); - if (edn0 == NULL) return 0; + if (edn0 == NULL) return 1; edn1 = ldb_dn_explode_casefold(ldb, dn1); if (edn1 == NULL) { talloc_free(edn0); - return 0; + return -1; } ret = ldb_dn_compare(ldb, edn0, edn1); -- cgit From 38b04883fe07fe92ef52aaff51eb7f1ea041008a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Sep 2005 22:45:49 +0000 Subject: r10232: Some work on ldb_sqlite3. It is still far from being usable in samba4 but I want to commit so that the work does not get lost by mistake. This is also a good way to get comments if somebody is interested. Sorry Derrell I ended up rewriting large parts of the code but I find this style much more readable. Thanks for the hard work done. Your work was a good reference for me. ah the current code also shows some good numbers sqlite3 generic test: uid search took 0.05 seconds real 0m12.492s user 0m0.492s sys 0m0.345s with tdb we still get better numbers: uid search took 0.46 seconds real 0m0.892s user 0m0.360s sys 0m0.468s but most of the time is spent in adding operations and I think there's still a lot of space for improvement. Simo. (This used to be commit ace9990060c10d0931f418934b2121aea9512ff7) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 3787 ++++++++++++----------------- source4/lib/ldb/tests/test-sqlite3.sh | 14 +- 2 files changed, 1576 insertions(+), 2225 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 76ef703ca5..e283e6b0c1 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -36,7 +36,6 @@ #include "includes.h" #include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" -#include "ldb/include/ldb_explode_dn.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" /* @@ -48,644 +47,436 @@ # define TRUE (! FALSE) #endif -#define FILTER_ATTR_TABLE "temp_filter_attrs" #define RESULT_ATTR_TABLE "temp_result_attrs" //#define TEMPTAB /* for testing, create non-temporary table */ #define TEMPTAB "TEMPORARY" -//#define DEBUG_LOCKS +/* + * Static variables + */ +sqlite3_stmt * stmtGetEID = NULL; -#ifndef DEBUG_LOCKS -# define LOCK_DB(mod, name) lsqlite3_lock(mod, name) -# define UNLOCK_DB(mod, name) lsqlite3_unlock(mod, name) -#else -# define LOCK_DB(mod, name) lock_debug(mod, name, __FILE__, __LINE__) -# define UNLOCK_DB(mod, name) unlock_debug(mod, name, __FILE__, __LINE__) -#endif +static char *lsqlite3_tprintf(TALLOC_CTX *mem_ctx, const char *fmt, ...) +{ + char *str, *ret; + va_list ap; + + va_start(ap, fmt); + str = sqlite3_vmprintf(fmt, ap); + va_end(ap); + + if (str == NULL) return NULL; + + ret = talloc_strdup(mem_ctx, str); + if (ret == NULL) { + sqlite3_free(str); + return NULL; + } + + sqlite3_free(str); + return ret; +} + +static unsigned char base160tab[161] = { + 48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */ + 58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */ + 73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 , /* I-R */ + 83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,97 ,98 , /* S-Z , a-b */ + 99 ,100,101,102,103,104,105,106,107,108, /* c-l */ + 109,110,111,112,113,114,115,116,117,118, /* m-v */ + 119,120,121,122,160,161,162,163,164,165, /* w-z, latin1 */ + 166,167,168,169,170,171,172,173,174,175, /* latin1 */ + 176,177,178,179,180,181,182,183,184,185, /* latin1 */ + 186,187,188,189,190,191,192,193,194,195, /* latin1 */ + 196,197,198,199,200,201,202,203,204,205, /* latin1 */ + 206,207,208,209,210,211,212,213,214,215, /* latin1 */ + 216,217,218,219,220,221,222,223,224,225, /* latin1 */ + 226,227,228,229,230,231,232,233,234,235, /* latin1 */ + 236,237,238,239,240,241,242,243,244,245, /* latin1 */ + 246,247,248,249,250,251,252,253,254,255, /* latin1 */ + '\0' +}; -#define QUERY_NOROWS(lsqlite3, bRollbackOnError, sql...) \ - do { \ - if (query_norows(lsqlite3, sql) != 0) { \ - if (bRollbackOnError) { \ - UNLOCK_DB(module, "rollback"); \ - } \ - return -1; \ - } \ - } while (0) - -#define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \ - do { \ - if (query_int(lsqlite3, &result_var, sql) != 0) { \ - if (bRollbackOnError) { \ - UNLOCK_DB(module, "rollback"); \ - } \ - return -1; \ - } \ - } while (0) - -#define GET_EID(lsqlite3, result_var, bRollbackOnError, pDN) \ - do { \ - if (getEID(lsqlite3, &result_var, pDN) != 0) { \ - if (bRollbackOnError) { \ - UNLOCK_DB(module, "rollback"); \ - } \ - return -1; \ - } \ - } while (0) - - -#define SQLITE3_DEBUG_QUERY (1 << 0) -#define SQLITE3_DEBUG_INIT (1 << 1) -#define SQLITE3_DEBUG_ADD (1 << 2) -#define SQLITE3_DEBUG_NEWDN (1 << 3) -#define SQLITE3_DEBUG_SEARCH (1 << 4) /* - * Static variables + * base160() + * + * Convert an unsigned long integer into a base160 representation of the + * number. + * + * Parameters: + * val -- + * value to be converted + * + * result -- + * character array, 5 bytes long, into which the base160 representation + * will be placed. The result will be a four-digit representation of the + * number (with leading zeros prepended as necessary), and null + * terminated. + * + * Returns: + * Nothing */ -static int lsqlite3_debug = FALSE; -sqlite3_stmt * stmtGetEID = NULL; +static void +base160_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + long long val; + char result[5]; + + val = sqlite3_value_int64(argv[0]); + + for (i = 3; i >= 0; i--) { + + result[i] = base160tab[val % 160]; + val /= 160; + } + + result[4] = '\0'; + + sqlite3_result_text(hContext, result, -1, SQLITE_TRANSIENT); +} + /* - * Forward declarations + * base160next_sql() + * + * This function enhances sqlite by adding a "base160_next()" function which is + * accessible via queries. + * + * Retrieve the next-greater number in the base160 sequence for the terminal + * tree node (the last four digits). Only one tree level (four digits) is + * operated on. + * + * Input: + * A character string: either an empty string (in which case no operation is + * performed), or a string of base160 digits with a length of a multiple of + * four digits. + * + * Output: + * Upon return, the trailing four digits (one tree level) will have been + * incremented by 1. */ -static int -lsqlite3_rename(struct ldb_module * module, - const char * olddn, - const char * newdn); +static void +base160next_sql(sqlite3_context * hContext, + int argc, + sqlite3_value ** argv) +{ + int i; + int len; + unsigned char * pTab; + unsigned char * pBase160 = + strdup(sqlite3_value_text(argv[0])); + unsigned char * pStart = pBase160; -static int -lsqlite3_delete(struct ldb_module *module, - const char *dn); + /* + * We need a minimum of four digits, and we will always get a multiple + * of four digits. + */ + if (pBase160 != NULL && + (len = strlen(pBase160)) >= 4 && + len % 4 == 0) { -static int -lsqlite3_search_bytree(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - struct ldb_parse_tree * pTree, - const char * const * attrs, - struct ldb_message *** pppRes); + if (pBase160 == NULL) { -static int -lsqlite3_search(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - const char * pExpression, - const char * const attrs[], - struct ldb_message *** pppRes); + sqlite3_result_null(hContext); + return; + } -static int -lsqlite3_add(struct ldb_module *module, - const struct ldb_message *msg); + pBase160 += strlen(pBase160) - 1; -static int -lsqlite3_modify(struct ldb_module *module, - const struct ldb_message *msg); + /* We only carry through four digits: one level in the tree */ + for (i = 0; i < 4; i++) { -static int -lsqlite3_lock(struct ldb_module *module, - const char *lockname); + /* What base160 value does this digit have? */ + pTab = strchr(base160tab, *pBase160); -static int -lsqlite3_unlock(struct ldb_module *module, - const char *lockname); + /* Is there a carry? */ + if (pTab < base160tab + sizeof(base160tab) - 1) { -static const char * -lsqlite3_errstring(struct ldb_module *module); + /* + * Nope. Just increment this value and we're + * done. + */ + *pBase160 = *++pTab; + break; + } else { -static int -initialize(struct lsqlite3_private *lsqlite3, - const char *url); + /* + * There's a carry. This value gets + * base160tab[0], we decrement the buffer + * pointer to get the next higher-order digit, + * and continue in the loop. + */ + *pBase160-- = base160tab[0]; + } + } -static int -destructor(void *p); + sqlite3_result_text(hContext, + pStart, + strlen(pStart), + free); + } else { + sqlite3_result_value(hContext, argv[0]); + if (pBase160 != NULL) { + free(pBase160); + } + } +} -static int -query_norows(const struct lsqlite3_private *lsqlite3, - const char *pSql, - ...); +static char *parsetree_to_sql(struct ldb_module *module, + void *mem_ctx, + const struct ldb_parse_tree *t) +{ + const struct ldb_attrib_handler *h; + struct ldb_val value, subval; + char *wild_card_string; + char *child, *tmp; + char *ret = NULL; + int i; -static int -query_int(const struct lsqlite3_private * lsqlite3, - long long * pRet, - const char * pSql, - ...); -static int -getEID(const struct lsqlite3_private * lsqlite3, - long long * pRet, - const char * pNormalizedDN); + switch(t->operation) { + case LDB_OP_AND: -static int case_fold_attr_required(void * hUserData, - char *attr); + tmp = parsetree_to_sql(module, mem_ctx, t->u.list.elements[0]); + if (tmp == NULL) return NULL; -static int case_fold_attr_not_required(void * hUserData, - char *attr); + for (i = 1; i < t->u.list.num_elements; i++) { -static int -add_msg_attr(void * hTalloc, - long long eid, - const char * pDN, - const char * pAttrName, - const char * pAttrValue, - long long prevEID, - int * pAllocated, - struct ldb_message *** pppRes); - -static char * -parsetree_to_sql(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t); + child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); + if (child == NULL) return NULL; -static int -parsetree_to_attrlist(struct ldb_module *module, - const struct ldb_parse_tree * t); + tmp = talloc_asprintf_append(tmp, "INTERSECT %s ", child); + if (tmp == NULL) return NULL; + } -static int -msg_to_sql(struct ldb_module * module, - const struct ldb_message * msg, - long long eid, - int use_flags); + ret = talloc_asprintf(mem_ctx, "SELECT * FROM ( %s )\n", tmp); -static int -new_dn(struct ldb_module * module, - char * pDN, - long long * pEID); + return ret; + + case LDB_OP_OR: -static void -base160_sql(sqlite3_context * hContext, - int argc, - sqlite3_value ** argv); + tmp = parsetree_to_sql(module, mem_ctx, t->u.list.elements[0]); + if (tmp == NULL) return NULL; -static void -base160next_sql(sqlite3_context * hContext, - int argc, - sqlite3_value ** argv); - -#ifdef DEBUG_LOCKS -static int lock_debug(struct ldb_module * module, - const char * lockname, - const char * pFileName, - int linenum); - -static int unlock_debug(struct ldb_module * module, - const char * lockname, - const char * pFileName, - int linenum); -#endif + for (i = 1; i < t->u.list.num_elements; i++) { + child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); + if (child == NULL) return NULL; -/* - * Table of operations for the sqlite3 backend - */ -static const struct ldb_module_ops lsqlite3_ops = { - .name = "sqlite", - .search = lsqlite3_search, - .search_bytree = lsqlite3_search_bytree, - .add_record = lsqlite3_add, - .modify_record = lsqlite3_modify, - .delete_record = lsqlite3_delete, - .rename_record = lsqlite3_rename, - .named_lock = lsqlite3_lock, - .named_unlock = lsqlite3_unlock, - .errstring = lsqlite3_errstring -}; + tmp = talloc_asprintf_append(tmp, "UNION %s ", child); + if (tmp == NULL) return NULL; + } + return talloc_asprintf(mem_ctx, "SELECT * FROM ( %s )", tmp); + case LDB_OP_NOT: + child = parsetree_to_sql(module, mem_ctx, t->u.isnot.child); + if (child == NULL) return NULL; -/* - * Public functions - */ + return talloc_asprintf(mem_ctx, + "SELECT eid FROM ldb_entry " + "WHERE eid NOT IN ( %s )", child); + + case LDB_OP_EQUALITY: + /* + * For simple searches, we want to retrieve the list of EIDs that + * match the criteria. + */ + h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + if (strcasecmp(t->u.equality.attr, "objectclass") == 0) { + /* + * For object classes, we want to search for all objectclasses + * that are subclasses as well. + */ + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values\n" + "WHERE norm_attr_name = 'OBJECTCLASS' " + "AND norm_attr_value IN\n" + " (SELECT class_name FROM ldb_object_classes\n" + " WHERE tree_key GLOB\n" + " (SELECT tree_key FROM ldb_object_classes\n" + " WHERE class_name = '%q'\n" + " ) || '*'\n" + " )\n", value.data); + + } else if (strcasecmp(t->u.equality.attr, "dn") == 0) { + /* DN query is a special ldb case */ + char *cdn = ldb_dn_linearize_casefold(module->ldb, + ldb_dn_explode(module->ldb, + value.data)); + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_entry " + "WHERE norm_dn = '%q'", cdn); + + } else { + /* A normal query. */ + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q') " + "AND norm_attr_value = '%q'", + t->u.equality.attr, + value.data); + + } + + case LDB_OP_SUBSTRING: + + wild_card_string = talloc_strdup(mem_ctx, + (t->u.substring.start_with_wildcard)?"*":""); + if (wild_card_string == NULL) return NULL; + + for (i = 0; t->u.substring.chunks[i]; i++) { + wild_card_string = talloc_asprintf_append(wild_card_string, "%s*", + t->u.substring.chunks[i]); + if (wild_card_string == NULL) return NULL; + } + + if ( ! t->u.substring.end_with_wildcard ) { + /* remove last wildcard */ + wild_card_string[strlen(wild_card_string) - 1] = '\0'; + } + + h = ldb_attrib_handler(module->ldb, t->u.substring.attr); + + subval.data = wild_card_string; + subval.length = strlen(wild_card_string) + 1; + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, mem_ctx, &(subval), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q') " + "AND norm_attr_value GLOB '%q'", + t->u.substring.attr, + value.data); + + case LDB_OP_GREATER: + h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q') " + "AND norm_attr_value >= '%q'", + t->u.equality.attr, + value.data); + + case LDB_OP_LESS: + h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q') " + "AND norm_attr_value <= '%q'", + t->u.equality.attr, + value.data); + + case LDB_OP_PRESENT: + if (strcasecmp(t->u.present.attr, "dn")) { + return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry"); + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q')", + t->u.present.attr); + + case LDB_OP_APPROX: + h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); + if (value.data == NULL) { + return NULL; + } + + return lsqlite3_tprintf(mem_ctx, + "SELECT eid FROM ldb_attribute_values " + "WHERE norm_attr_name = upper('%q') " + "AND norm_attr_value LIKE '%q'", + t->u.equality.attr, + value.data); + + case LDB_OP_EXTENDED: +#warning "work out how to handle bitops" + return NULL; + + default: + break; + }; + + /* should never occur */ + abort(); + return NULL; +} /* - * connect to the database + * query_norows() + * + * This function is used for queries that are not expected to return any rows, + * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. + * There are no provisions here for returning data from rows in a table, so do + * not pass SELECT queries to this function. */ -int lsqlite3_connect(struct ldb_context *ldb, - const char *url, - unsigned int flags, - const char *options[]) +static int +query_norows(const struct lsqlite3_private *lsqlite3, + const char *pSql, + ...) { - int i; - int ret; - struct lsqlite3_private * lsqlite3 = NULL; - - lsqlite3 = talloc(ldb, struct lsqlite3_private); - if (!lsqlite3) { - goto failed; - } - - lsqlite3->sqlite = NULL; - lsqlite3->options = NULL; - lsqlite3->lock_count = 0; - - ret = initialize(lsqlite3, url); - if (ret != SQLITE_OK) { - goto failed; - } - - talloc_set_destructor(lsqlite3, destructor); - - ldb->modules = talloc(ldb, struct ldb_module); - if (!ldb->modules) { - goto failed; - } - ldb->modules->ldb = ldb; - ldb->modules->prev = ldb->modules->next = NULL; - ldb->modules->private_data = lsqlite3; - ldb->modules->ops = &lsqlite3_ops; - - if (options) { - /* - * take a copy of the options array, so we don't have to rely - * on the caller keeping it around (it might be dynamic) - */ - for (i=0;options[i];i++) ; - - lsqlite3->options = talloc_array(lsqlite3, char *, i+1); - if (!lsqlite3->options) { - goto failed; - } - - for (i=0;options[i];i++) { - - lsqlite3->options[i+1] = NULL; - lsqlite3->options[i] = - talloc_strdup(lsqlite3->options, options[i]); - if (!lsqlite3->options[i]) { - goto failed; - } - } - } - - return 0; - -failed: - if (lsqlite3->sqlite != NULL) { - (void) sqlite3_close(lsqlite3->sqlite); - } - talloc_free(lsqlite3); - return -1; -} - - -/* - * Interface functions referenced by lsqlite3_ops - */ - -/* rename a record */ -static int -lsqlite3_rename(struct ldb_module * module, - const char * pOldDN, - const char * pNewDN) -{ - const char *pOldNormalizedDN; - const char *pNewNormalizedDN; - long long eid; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* ignore ltdb specials */ - if (*pOldDN == '@' || *pNewDN == '@') { - return 0; - } - - /* Case-fold each of the DNs */ - pOldNormalizedDN = - ldb_dn_fold(module->ldb, pOldDN, module, case_fold_attr_required); - pNewNormalizedDN = - ldb_dn_fold(module->ldb, pNewDN, module, case_fold_attr_required); - - /* Begin a transaction */ - if (LOCK_DB(module, "transaction") < 0) { - return -1; - } - - /* Determine the eid of the DN being renamed */ - GET_EID(lsqlite3, eid, TRUE, pOldNormalizedDN); - - QUERY_NOROWS(lsqlite3, - TRUE, - "UPDATE ldb_entry " - " SET dn = %Q, " - " normalized_dn = %Q " - " WHERE eid = %lld;", - pNewDN, pNewNormalizedDN, eid); - - QUERY_NOROWS(lsqlite3, - TRUE, - "UPDATE ldb_attribute_values " - " SET attr_value = %Q, " - " attr_value_normalized = %Q " - " WHERE eid = %lld " - " AND attr_name = 'DN';", - pNewDN, - pNewNormalizedDN, - eid); - - /* Commit the transaction */ - if (UNLOCK_DB(module, "transaction") < 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - - return 0; -} - -/* delete a record */ -static int -lsqlite3_delete(struct ldb_module * module, - const char * pDN) -{ - char *pNormalizedDN; - long long eid; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* ignore ltdb specials */ - if (*pDN == '@') { - return 0; - } - - /* Begin a transaction */ - if (LOCK_DB(module, "transaction") < 0) { - return -1; - } - - /* Case-fold the DNs */ - pNormalizedDN = - ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); - - /* Determine the eid of the DN being deleted */ - GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); - - /* Delete attribute/value table entries pertaining to this DN */ - QUERY_NOROWS(lsqlite3, - TRUE, - "DELETE FROM ldb_attribute_values " - " WHERE eid = %lld;", - eid); - - /* Delete this entry */ - QUERY_NOROWS(lsqlite3, - TRUE, - "DELETE FROM ldb_entry " - " WHERE eid = %lld;", - eid); - - /* Commit the transaction */ - if (UNLOCK_DB(module, "transaction") < 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - - return 0; -} - -/* search for matching records, by tree */ -static int -lsqlite3_search_bytree(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - struct ldb_parse_tree * pTree, - const char * const * attrs, - struct ldb_message *** pppRes) -{ - int ret; - int allocated; - int bLoop; - long long eid = 0; - long long prevEID; - char * pSql = NULL; - char * pSqlConstraints; - char * hTalloc = NULL; - const char * pDN; - const char * pNormalizedBaseDN; - const char * pAttrName; - const char * pAttrValue; - const char * pResultAttrList; - const char * const * pRequestedAttrs; - sqlite3_stmt * pStmt; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* Allocate a temporary talloc context */ - if ((hTalloc = talloc_new(module->ldb)) == NULL) { - return -1; - } - - /* Case-fold the base DN */ - if ((pNormalizedBaseDN = - ldb_dn_fold(hTalloc, - pBaseDN == NULL ? "" : pBaseDN, - module, - case_fold_attr_required)) == NULL) { - - talloc_free(hTalloc); - return -1; - } - - /* Begin a transaction */ - if (LOCK_DB(module, "transaction") < 0) { - talloc_free(hTalloc); - return -1; - } + int ret; + int bLoop; + char * p; + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); - /* - * Obtain the eid of the base DN - */ - if ((ret = getEID(lsqlite3, &eid, pNormalizedBaseDN)) == SQLITE_DONE) { - UNLOCK_DB(module, "rollback"); - talloc_free(hTalloc); - return 0; - } else if (ret != SQLITE_OK) { - UNLOCK_DB(module, "rollback"); - talloc_free(hTalloc); + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { return -1; } - /* Convert filter into a series of SQL conditions (constraints) */ - pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree); - - /* Ensure we're starting with an empty result attribute table */ - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM " RESULT_ATTR_TABLE "\n" - " WHERE 1;");/* avoid a schema change with WHERE 1 */ - - /* Initially, we don't know what the requested attributes are */ - pResultAttrList = NULL; - - /* Insert the list of requested attributes into this table */ - for (pRequestedAttrs = (const char * const *) attrs; - pRequestedAttrs != NULL && *pRequestedAttrs != NULL; - pRequestedAttrs++) { - - /* If any attribute in the list is "*" then... */ - if (strcmp(*pRequestedAttrs, "*") == 0) { - /* we want all attribute types */ - pResultAttrList = ""; - break; - - } else { - /* otherwise, add this name to the resuult list */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT OR IGNORE\n" - " INTO " RESULT_ATTR_TABLE "\n" - " (attr_name)\n" - " VALUES\n" - " (%Q);", - *pRequestedAttrs); - } - } - - /* If we didn't get a "*" for all attributes in the result list... */ - if (pResultAttrList == NULL) { - /* ... then we'll use the result attribute table */ - pResultAttrList = - " AND upper(av.attr_name) IN\n" - " (SELECT attr_name\n" - " FROM " RESULT_ATTR_TABLE ") "; - } - - /* Ensure we're starting with an empty filter attribute table */ - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM " FILTER_ATTR_TABLE "\n" - " WHERE 1;");/* avoid a schema change with WHERE 1 */ - - /* - * Create a table of unique attribute names for our extra table list - */ - if ((ret = parsetree_to_attrlist(module, pTree)) != 0) { - ret = -1; - goto cleanup; - } - - switch(scope) { - case LDB_SCOPE_DEFAULT: - case LDB_SCOPE_SUBTREE: - pSql = sqlite3_mprintf( - "SELECT entry.eid,\n" - " entry.dn,\n" - " av.attr_name,\n" - " av.attr_value\n" - " FROM ldb_entry AS entry\n" - - " LEFT OUTER JOIN ldb_attribute_values AS av\n" - " ON av.eid = entry.eid\n" - " %s\n" - - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry\n" - " WHERE ldb_entry.tree_key >=\n" - " (SELECT tree_key\n" - " FROM ldb_entry\n" - " WHERE eid = %lld)\n" - " AND ldb_entry.tree_key <\n" - " (SELECT base160_next(tree_key)\n" - " FROM ldb_entry\n" - " WHERE eid = %lld)\n" - " AND ldb_entry.eid IN\n(%s)\n" - " )\n" - " ORDER BY entry.tree_key DESC,\n" - " COALESCE(av.attr_name, '');", - pResultAttrList, - eid, - eid, - pSqlConstraints); - break; - - case LDB_SCOPE_BASE: - pSql = sqlite3_mprintf( - "SELECT entry.eid,\n" - " entry.dn,\n" - " av.attr_name,\n" - " av.attr_value\n" - " FROM ldb_entry AS entry\n" - - " LEFT OUTER JOIN ldb_attribute_values AS av\n" - " ON av.eid = entry.eid\n" - " %s\n" - - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry\n" - " WHERE ldb_entry.eid = %lld\n" - " AND ldb_entry.eid IN\n(%s)\n" - " )\n" - " ORDER BY entry.tree_key DESC,\n" - " COALESCE(av.attr_name, '');", - pResultAttrList, - eid, - pSqlConstraints); - break; - - case LDB_SCOPE_ONELEVEL: - pSql = sqlite3_mprintf( - "SELECT entry.eid,\n" - " entry.dn,\n" - " av.attr_name,\n" - " av.attr_value\n" - " FROM ldb_entry AS entry\n" - - " LEFT OUTER JOIN ldb_attribute_values AS av\n" - " ON av.eid = entry.eid\n" - " %s\n" - - " WHERE entry.eid IN\n" - " (SELECT DISTINCT ldb_entry.eid\n" - " FROM ldb_entry\n" - " WHERE ldb_entry.tree_key >=\n" - " (SELECT tree_key\n" - " FROM ldb_entry\n" - " WHERE eid = %lld)\n" - " AND ldb_entry.tree_key <\n" - " (SELECT base160_next(tree_key)\n" - " FROM ldb_entry\n" - " WHERE eid = %lld)\n" - " AND length(ldb_entry.tree_key) =\n" - " (SELECT length(tree_key) + 4\n" - " FROM ldb_entry\n" - " WHERE eid = %lld)\n" - " AND ldb_entry.eid IN\n(%s)\n" - " )\n" - - " ORDER BY entry.tree_key DESC,\n" - " COALESCE(av.attr_name, '');\n", - pResultAttrList, - eid, - eid, - eid, - pSqlConstraints); - break; - } - - if (pSql == NULL) { - ret = -1; - goto cleanup; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_SEARCH) { - printf("%s\n", pSql); - } - /* * Prepare and execute the SQL statement. Loop allows retrying on * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, * requiring retrying the operation. */ for (bLoop = TRUE; bLoop; ) { - /* There are no allocate message structures yet */ - allocated = 0; - if (pppRes != NULL) { - *pppRes = NULL; - } /* Compile the SQL statement into sqlite virtual machine */ if ((ret = sqlite3_prepare(lsqlite3->sqlite, - pSql, + p, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { @@ -693,62 +484,19 @@ lsqlite3_search_bytree(struct ldb_module * module, sqlite3_finalize(stmtGetEID); stmtGetEID = NULL; } - - if (pppRes != NULL && *pppRes != NULL) { - talloc_free(*pppRes); - } - continue; } else if (ret != SQLITE_OK) { ret = -1; break; } - /* Initially, we have no previous eid */ - prevEID = -1; - - /* Loop through the returned rows */ - for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) { - - /* Get the next row */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { - - /* Get the values from this row */ - eid = sqlite3_column_int64(pStmt, 0); - pDN = sqlite3_column_text(pStmt, 1); - pAttrName = sqlite3_column_text(pStmt, 2); - pAttrValue = sqlite3_column_text(pStmt, 3); - - /* Add this result to the result set */ - if (add_msg_attr(hTalloc, - eid, - pDN, - pAttrName, - pAttrValue, - prevEID, - &allocated, - pppRes) != 0) { - - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Save the most recent EID */ - prevEID = eid; - } - } - - if (ret == SQLITE_SCHEMA) { + /* No rows expected, so just step through machine code once */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { if (stmtGetEID != NULL) { sqlite3_finalize(stmtGetEID); stmtGetEID = NULL; } - (void) sqlite3_finalize(pStmt); - if (pppRes != NULL && *pppRes != NULL) { - talloc_free(*pppRes); - } continue; } else if (ret != SQLITE_DONE) { (void) sqlite3_finalize(pStmt); @@ -762,10 +510,6 @@ lsqlite3_search_bytree(struct ldb_module * module, sqlite3_finalize(stmtGetEID); stmtGetEID = NULL; } - - if (pppRes != NULL && *pppRes != NULL) { - talloc_free(*pppRes); - } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -781,184 +525,24 @@ lsqlite3_search_bytree(struct ldb_module * module, bLoop = FALSE; } - /* We're alll done with this query */ - sqlite3_free(pSql); - - /* End the transaction */ - UNLOCK_DB(module, "rollback"); - - /* Were there any results? */ - if (ret != 0 || allocated == 0) { - /* Nope. We can free the results. */ - if (pppRes != NULL && *pppRes != NULL) { - talloc_free(*pppRes); - } - } - -cleanup: - /* Clean up our temporary tables */ - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM " RESULT_ATTR_TABLE "\n" - " WHERE 1;");/* avoid a schema change with WHERE 1 */ - - QUERY_NOROWS(lsqlite3, - FALSE, - "DELETE FROM " FILTER_ATTR_TABLE "\n" - " WHERE 1;");/* avoid a schema change with WHERE 1 */ - + /* All done with variable argument list */ + va_end(args); - if (hTalloc != NULL) { - talloc_free(hTalloc); - } + /* Free the memory we allocated for our query string */ + sqlite3_free(p); - /* If error, return error code; otherwise return number of results */ - return ret == 0 ? allocated : ret; + return ret; } -/* search for matching records, by expression */ + +/* obtain a named lock */ static int -lsqlite3_search(struct ldb_module * module, - const char * pBaseDN, - enum ldb_scope scope, - const char * pExpression, - const char * const * attrs, - struct ldb_message *** pppRes) +lsqlite3_lock(struct ldb_module * module, + const char * lockname) { - int ret; - struct ldb_parse_tree * pTree; - - /* Handle tdb specials */ - if (pBaseDN != NULL && *pBaseDN == '@') { -#warning "handle tdb specials" - return 0; - } - -#if 0 -/* (|(objectclass=*)(dn=*)) is passed by the command line tool now instead */ - /* Handle the special case of requesting all */ - if (pExpression != NULL && *pExpression == '\0') { - pExpression = "dn=*"; - } -#endif - - /* Parse the filter expression into a tree we can work with */ - if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) { - return -1; - } - - /* Now use the bytree function for the remainder of processing */ - ret = lsqlite3_search_bytree(module, pBaseDN, scope, - pTree, attrs, pppRes); - - /* Free the parse tree */ - talloc_free(pTree); - - /* All done. */ - return ret; -} - - -/* add a record */ -static int -lsqlite3_add(struct ldb_module *module, - const struct ldb_message *msg) -{ - long long eid; - - /* See if this is an ltdb special */ - if (*msg->dn == '@') { - /* Yup. We handle a few of these and ignore others */ - if (strcmp(msg->dn, "@SUBCLASSES") == 0) { -#warning "insert subclasses into object class tree" - } - - if (strcmp(msg->dn, "@INDEXLIST") == 0) { - /* explicitly ignored */ - return 0; - } - - /* Others are implicitly ignored */ - return 0; - } - - /* Begin a transaction */ - if (LOCK_DB(module, "transaction") < 0) { - return -1; - } - - /* - * Build any portions of the directory tree that don't exist. If the - * final component already exists, it's an error. - */ - if (new_dn(module, msg->dn, &eid) != 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - - /* Add attributes to this new entry */ - if (msg_to_sql(module, msg, eid, FALSE) != 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - - /* Everything worked. Commit it! */ - if (UNLOCK_DB(module, "transaction") < 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - return 0; -} - - -/* modify a record */ -static int -lsqlite3_modify(struct ldb_module * module, - const struct ldb_message * msg) -{ - char * pNormalizedDN; - long long eid; - struct lsqlite3_private * lsqlite3 = module->private_data; - - /* ignore ltdb specials */ - if (*msg->dn == '@') { - return 0; - } - - /* Begin a transaction */ - if (LOCK_DB(module, "transaction") < 0) { - return -1; - } - - /* Case-fold the DN so we can compare it to what's in the database */ - pNormalizedDN = ldb_dn_fold(module->ldb, msg->dn, - module, case_fold_attr_required); - - /* Determine the eid of the DN being deleted */ - GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); - - /* Apply the message attributes */ - if (msg_to_sql(module, msg, eid, TRUE) != 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - - - /* Everything worked. Commit it! */ - if (UNLOCK_DB(module, "transaction") < 0) { - UNLOCK_DB(module, "rollback"); - return -1; - } - return 0 ; -} - -/* obtain a named lock */ -static int -lsqlite3_lock(struct ldb_module * module, - const char * lockname) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; + struct lsqlite3_private * lsqlite3 = module->private_data; +/* FIXME if (lockname == NULL) { return -1; } @@ -971,7 +555,7 @@ lsqlite3_lock(struct ldb_module * module, } ++lsqlite3->lock_count; } - +*/ return 0; } @@ -982,6 +566,7 @@ lsqlite3_unlock(struct ldb_module *module, { struct lsqlite3_private * lsqlite3 = module->private_data; +/* FIXME if (lockname == NULL) { return -1; } @@ -997,1559 +582,1313 @@ lsqlite3_unlock(struct ldb_module *module, } else if (strcmp(lockname, "rollback") == 0) { query_norows(lsqlite3, "ROLLBACK;"); } - +*/ return 0; } -/* return extended error information */ -static const char * -lsqlite3_errstring(struct ldb_module *module) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - - return sqlite3_errmsg(lsqlite3->sqlite); -} - - - - /* - * Static functions + * query_int() + * + * This function is used for the common case of queries that return a single + * integer value. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. */ - static int -initialize(struct lsqlite3_private *lsqlite3, - const char *url) +query_int(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pSql, + ...) { int ret; - long long queryInt; - const char * pTail; - sqlite3_stmt * stmt; - const char * schema = - + int bLoop; + char * p; + sqlite3_stmt * pStmt; + va_list args; + + /* Begin access to variable argument list */ + va_start(args, pSql); + + /* Format the query */ + if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { + return SQLITE_NOMEM; + } + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { - "CREATE TABLE ldb_info AS " - " SELECT 'LDB' AS database_type," - " '1.0' AS version;" + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + p, + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + continue; + } else if (ret != SQLITE_OK) { + break; + } - /* - * The entry table holds the information about an entry. - * This table is used to obtain the EID of the entry and to - * support scope=one and scope=base. The parent and child - * table is included in the entry table since all the other - * attributes are dependent on EID. - */ - "CREATE TABLE ldb_entry " - "(" - " eid INTEGER PRIMARY KEY," - " peid INTEGER REFERENCES ldb_entry," - " dn TEXT UNIQUE NOT NULL," - " normalized_dn TEXT UNIQUE NOT NULL," - " tree_key TEXT UNIQUE," - " max_child_num INTEGER DEFAULT 0," - " create_timestamp INTEGER," - " modify_timestamp INTEGER" - ");" + /* One row expected */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_finalize(pStmt); + break; + } - - "CREATE TABLE ldb_object_classes" - "(" - " class_name TEXT PRIMARY KEY," - " parent_class_name TEXT," - " tree_key TEXT UNIQUE," - " max_child_num INTEGER DEFAULT 0" - ");" + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(pStmt, 0); - /* - * We keep a full listing of attribute/value pairs here - */ - "CREATE TABLE ldb_attribute_values" - "(" - " eid INTEGER REFERENCES ldb_entry," - " attr_name TEXT," - " attr_value TEXT," - " attr_value_normalized TEXT " - ");" + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + break; + } - /* - * Indexes + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. */ - "CREATE INDEX ldb_entry_tree_key_idx " - " ON ldb_entry (tree_key);" + bLoop = FALSE; + } + + /* All done with variable argument list */ + va_end(args); + - "CREATE INDEX ldb_attribute_values_eid_idx " - " ON ldb_attribute_values (eid);" - - "CREATE INDEX ldb_attribute_values_name_value_idx " - " ON ldb_attribute_values (attr_name, attr_value_normalized);" - - + /* Free the memory we allocated for our query string */ + sqlite3_free(p); + + return ret; +} - /* - * Triggers - */ - - "CREATE TRIGGER ldb_entry_insert_tr" - " AFTER INSERT" - " ON ldb_entry" - " FOR EACH ROW" - " BEGIN" - " UPDATE ldb_entry" - " SET create_timestamp = strftime('%s', 'now')," - " modify_timestamp = strftime('%s', 'now')" - " ," - " tree_key = COALESCE(tree_key, " - " (" - " SELECT tree_key || " - " (SELECT base160(max_child_num + 1)" - " FROM ldb_entry" - " WHERE eid = new.peid)" - " FROM ldb_entry " - " WHERE eid = new.peid " - " ));" - " UPDATE ldb_entry " - " SET max_child_num = max_child_num + 1" - " WHERE eid = new.peid;" - " END;" - - "CREATE TRIGGER ldb_entry_update_tr" - " AFTER UPDATE" - " ON ldb_entry" - " FOR EACH ROW" - " BEGIN" - " UPDATE ldb_entry" - " SET modify_timestamp = strftime('%s', 'now')" - " WHERE eid = old.eid;" - " END;" - - "CREATE TRIGGER ldb_object_classes_insert_tr" - " AFTER INSERT" - " ON ldb_object_classes" - " FOR EACH ROW" - " BEGIN" - " UPDATE ldb_object_classes" - " SET tree_key = COALESCE(tree_key, " - " (" - " SELECT tree_key || " - " (SELECT base160(max_child_num + 1)" - " FROM ldb_object_classes" - " WHERE class_name = " - " new.parent_class_name)" - " FROM ldb_object_classes " - " WHERE class_name = new.parent_class_name " - " ));" - " UPDATE ldb_object_classes " - " SET max_child_num = max_child_num + 1" - " WHERE class_name = new.parent_class_name;" - " END;" - - /* - * Table initialization - */ +/* rename a record */ +static int lsqlite3_safe_rollback(sqlite3 *sqlite) +{ + char *errmsg; + int ret; - /* The root node */ - "INSERT INTO ldb_entry " - " (eid, peid, dn, normalized_dn, tree_key) " - " VALUES " - " (0, NULL, '', '', '0001');" + /* execute */ + ret = sqlite3_exec(sqlite, "ROLLBACK;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_safe_rollback: Serious Error: %s\n", errmsg); + free(errmsg); + } + return -1; + } - /* And the root node "dn" attribute */ - "INSERT INTO ldb_attribute_values " - " (eid, attr_name, attr_value, attr_value_normalized) " - " VALUES " - " (0, 'DN', '', '');" + return 0; +} - "INSERT INTO ldb_object_classes " - " (class_name, tree_key) " - " VALUES " - " ('TOP', '0001');" +/* return an eid as result */ +static int lsqlite3_eid_callback(void *result, int col_num, char **cols, char **names) +{ + long long *eid = (long long *)result; - ; - - /* Skip protocol indicator of url */ - if (strncmp(url, "sqlite://", 9) != 0) { - return SQLITE_MISUSE; - } - - /* Update pointer to just after the protocol indicator */ - url += 9; - - /* Try to open the (possibly empty/non-existent) database */ - if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) { - return ret; - } - - /* In case this is a new database, enable auto_vacuum */ - if (query_norows(lsqlite3, "PRAGMA auto_vacuum=1;") != 0) { - return -1; - } - - /* Establish a busy timeout of 30 seconds */ - if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, - 30000)) != SQLITE_OK) { - return ret; - } + if (col_num != 1) return SQLITE_ABORT; + if (strcasecmp(names[0], "eid") != 0) return SQLITE_ABORT; - /* Create a function, callable from sql, to increment a tree_key */ - if ((ret = - sqlite3_create_function(lsqlite3->sqlite,/* handle */ - "base160_next", /* function name */ - 1, /* number of args */ - SQLITE_ANY, /* preferred text type */ - NULL, /* user data */ - base160next_sql, /* called func */ - NULL, /* step func */ - NULL /* final func */ - )) != SQLITE_OK) { - return ret; - } + *eid = atoll(cols[0]); + return SQLITE_OK; +} - /* Create a function, callable from sql, to convert int to base160 */ - if ((ret = - sqlite3_create_function(lsqlite3->sqlite,/* handle */ - "base160", /* function name */ - 1, /* number of args */ - SQLITE_ANY, /* preferred text type */ - NULL, /* user data */ - base160_sql, /* called func */ - NULL, /* step func */ - NULL /* final func */ - )) != SQLITE_OK) { - return ret; - } +struct lsqlite3_msgs { + int count; + struct ldb_message **msgs; + long long current_eid; + TALLOC_CTX *mem_ctx; +}; - /* Begin a transaction */ - if ((ret = query_norows(lsqlite3, "BEGIN EXCLUSIVE;")) != 0) { - return ret; - } - - /* Determine if this is a new database. No tables means it is. */ - if (query_int(lsqlite3, - &queryInt, - "SELECT COUNT(*)\n" - " FROM sqlite_master\n" - " WHERE type = 'table';") != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return -1; - } - - if (queryInt == 0) { - /* - * Create the database schema - */ - for (pTail = discard_const_p(char, schema); - pTail != NULL && *pTail != '\0'; - ) { - - if (lsqlite3_debug & SQLITE3_DEBUG_INIT) { - printf("Execute first query in:\n%s\n", pTail); - } - - if ((ret = sqlite3_prepare( - lsqlite3->sqlite, - pTail, - -1, - &stmt, - &pTail)) != SQLITE_OK || - (ret = sqlite3_step(stmt)) != SQLITE_DONE || - (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - - if (lsqlite3_debug & SQLITE3_DEBUG_INIT) { - printf("%s\n", - sqlite3_errmsg(lsqlite3->sqlite)); - printf("pTail = [%s]\n", pTail); - } - - query_norows(lsqlite3, "ROLLBACK;"); - (void) sqlite3_close(lsqlite3->sqlite); - return ret; - } - } - } else { - /* - * Ensure that the database we opened is one of ours - */ - if (query_int(lsqlite3, - &queryInt, - "SELECT " - " (SELECT COUNT(*) = 2" - " FROM sqlite_master " - " WHERE type = 'table' " - " AND name IN " - " (" - " 'ldb_entry', " - " 'ldb_object_classes' " - " ) " - " ) " - " AND " - " (SELECT 1 " - " FROM ldb_info " - " WHERE database_type = 'LDB' " - " AND version = '1.0'" - " );") != 0 || - queryInt != 1) { - - /* It's not one that we created. See ya! */ - query_norows(lsqlite3, "ROLLBACK;"); - (void) sqlite3_close(lsqlite3->sqlite); - return SQLITE_MISUSE; - } - } - - /* - * Create a temporary table to hold attributes requested in the result - * set of a search. - */ - query_norows(lsqlite3, "DROP TABLE " RESULT_ATTR_TABLE ";\n"); - if ((ret = - query_norows(lsqlite3, - "CREATE " TEMPTAB " TABLE " RESULT_ATTR_TABLE "\n" - " (\n" - " attr_name TEXT PRIMARY KEY\n" - " );")) != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return ret; - } +/* + * add a single set of ldap message values to a ldb_message + */ - /* - * Create a temporary table to hold the attributes used by filters - * during a search. - */ - query_norows(lsqlite3, "DROP TABLE " FILTER_ATTR_TABLE ";\n"); - if ((ret = - query_norows(lsqlite3, - "CREATE " TEMPTAB " TABLE " FILTER_ATTR_TABLE "\n" - " (\n" - " attr_name TEXT PRIMARY KEY\n" - " );")) != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return ret; - } +static int lsqlite3_search_callback(void *result, int col_num, char **cols, char **names) +{ + struct lsqlite3_msgs *msgs = (struct lsqlite3_msgs *)result; + struct ldb_message *msg; + long long eid; - /* Commit the transaction */ - if ((ret = query_norows(lsqlite3, "COMMIT;")) != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return ret; - } - - return SQLITE_OK; + /* eid, dn, attr_name, attr_value */ + if (col_num != 4) return SQLITE_ABORT; + + eid = atoll(cols[0]); + + if (eid != msgs->current_eid) { + msgs->msgs = talloc_realloc(msgs->mem_ctx, + msgs->msgs, + struct ldb_message *, + msgs->count + 2); + if (msgs->msgs == NULL) return SQLITE_ABORT; + + msgs->msgs[msgs->count] = talloc(msgs->msgs, struct ldb_message); + if (msgs->msgs[msgs->count] == NULL) return SQLITE_ABORT; + + msgs->msgs[msgs->count]->dn = NULL; + msgs->msgs[msgs->count]->num_elements = 0; + msgs->msgs[msgs->count]->elements = NULL; + msgs->msgs[msgs->count]->private_data = NULL; + + msgs->count++; + msgs->current_eid = eid; + } + + msg = msgs->msgs[msgs->count -1]; + + if (msg->dn == NULL) { + msg->dn = ldb_dn_explode(msg, cols[1]); + if (msg->dn == NULL) return SQLITE_ABORT; + } + + msg->elements = talloc_realloc(msg, + msg->elements, + struct ldb_message_element, + msg->num_elements + 1); + if (msg->elements == NULL) return SQLITE_ABORT; + + msg->elements[msg->num_elements].flags = 0; + msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, cols[2]); + if (msg->elements[msg->num_elements].name == NULL) return SQLITE_ABORT; + + msg->elements[msg->num_elements].num_values = 1; + msg->elements[msg->num_elements].values = talloc_array(msg->elements, + struct ldb_val, 1); + if (msg->elements[msg->num_elements].values == NULL) return SQLITE_ABORT; + + msg->elements[msg->num_elements].values[0].length = strlen(cols[3]); + msg->elements[msg->num_elements].values[0].data = talloc_strdup(msg->elements, cols[3]); + if (msg->elements[msg->num_elements].values[0].data == NULL) return SQLITE_ABORT; + + msg->num_elements++; + + return SQLITE_OK; } -static int -destructor(void *p) + +/* + * lsqlite3_get_eid() + * lsqlite3_get_eid_ndn() + * + * These functions are used for the very common case of retrieving an EID value + * given a (normalized) DN. + */ + +static long long lsqlite3_get_eid_ndn(sqlite3 *sqlite, void *mem_ctx, const char *norm_dn) { - struct lsqlite3_private * lsqlite3 = p; - - if (lsqlite3->sqlite) { - sqlite3_close(lsqlite3->sqlite); + char *errmsg; + char *query; + long long eid = -1; + long long ret; + + /* get object eid */ + query = lsqlite3_tprintf(mem_ctx, "SELECT eid " + "FROM ldb_entry " + "WHERE norm_dn = '%q';", norm_dn); + if (query == NULL) return -1; + + ret = sqlite3_exec(sqlite, query, lsqlite3_eid_callback, &eid, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_get_eid: Fatal Error: %s\n", errmsg); + free(errmsg); + } + return -1; } - return 0; + + return eid; } +static long long lsqlite3_get_eid(struct ldb_module *module, const struct ldb_dn *dn) +{ + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + long long eid = -1; + char *cdn; + + /* ignore ltdb specials */ + if (ldb_dn_is_special(dn)) { + return -1; + } + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_get_eid local context"); + if (local_ctx == NULL) { + return -1; + } + + cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, dn)); + if (!cdn) goto done; + + eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, cdn); + +done: + talloc_free(local_ctx); + return eid; +} /* - * query_norows() - * - * This function is used for queries that are not expected to return any rows, - * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. - * There are no provisions here for returning data from rows in a table, so do - * not pass SELECT queries to this function. + * Interface functions referenced by lsqlite3_ops */ -static int -query_norows(const struct lsqlite3_private *lsqlite3, - const char *pSql, - ...) + +/* search for matching records, by tree */ +static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_dn* basedn, + enum ldb_scope scope, struct ldb_parse_tree * tree, + const char * const * attrs, struct ldb_message *** res) { - int ret; - int bLoop; - char * p; - sqlite3_stmt * pStmt; - va_list args; - double t0 = 0; - double t1; - struct timeval tv; - struct timezone tz; - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - gettimeofday(&tv, &tz); - t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + struct lsqlite3_msgs msgs; + char *norm_basedn; + char *attr_list; + char *sqlfilter; + char *errmsg; + char *query; + int ret, i; + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_search_by_tree local context"); + if (local_ctx == NULL) { + return -1; } - /* Begin access to variable argument list */ - va_start(args, pSql); - - /* Format the query */ - if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return -1; - } + if (basedn) { + norm_basedn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, basedn)); + if (norm_basedn == NULL) goto failed; + } else norm_basedn = talloc_strdup(local_ctx, ""); + + if (*norm_basedn == '\0' && + (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) + goto failed; + + /* Convert filter into a series of SQL conditions (constraints) */ + sqlfilter = parsetree_to_sql(module, local_ctx, tree); - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - p, - -1, - &pStmt, - NULL)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - ret = -1; - break; - } - - /* No rows expected, so just step through machine code once */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_DONE) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } + /* Initially, we don't know what the requested attributes are */ + if (attrs != NULL) { + attr_list = talloc_strdup(local_ctx, "AND norm_attr_name IN ("); + if (attr_list == NULL) goto failed; + + for (i = 0; attrs[i]; i++) { + char *norm_attr_name; + + /* If any attribute in the list is "*" then... */ + if (strcmp(attrs[i], "*") == 0) { + /* we want all attribute types */ + attr_list = talloc_strdup(local_ctx, ""); + if (attr_list == NULL) goto failed; + break; + } + + norm_attr_name = ldb_casefold(local_ctx, attrs[i]); + if (norm_attr_name == NULL) goto failed; + + attr_list = talloc_asprintf_append(attr_list, "'%q', ", + norm_attr_name); + if (attr_list == NULL) goto failed; + + } + + /* substitute the last ',' with ')' */ + attr_list[strlen(attr_list)-2] = ')'; + + } else { + attr_list = talloc_strdup(local_ctx, ""); + if (attr_list == NULL) goto failed; + } + + switch(scope) { + case LDB_SCOPE_DEFAULT: + case LDB_SCOPE_SUBTREE: + if (*norm_basedn != '\0') { + query = lsqlite3_tprintf(local_ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE (ldb_entry.norm_dn GLOB('*,%q')\n" + " OR ldb_entry.norm_dn = '%q')\n" + " AND ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " %s\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + norm_basedn, + sqlfilter, + attr_list); + } else { + query = lsqlite3_tprintf(local_ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " %s\n" + + " ORDER BY entry.eid ASC;", + sqlfilter, + attr_list); + } + + break; - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } + case LDB_SCOPE_BASE: + query = lsqlite3_tprintf(local_ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE ldb_entry.norm_dn = '%q'\n" + " AND ldb_entry.eid IN\n" + " (%s)\n" + " )\n" + + " %s\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + sqlfilter, + attr_list); + break; - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; + case LDB_SCOPE_ONELEVEL: + query = lsqlite3_tprintf(local_ctx, + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry\n" + + " LEFT OUTER JOIN ldb_attribute_values AS av\n" + " ON av.eid = entry.eid\n" + + " WHERE entry.eid IN\n" + " (SELECT DISTINCT ldb_entry.eid\n" + " FROM ldb_entry\n" + " WHERE norm_dn GLOB('*,%q')\n" + " AND NOT norm_dn GLOB('*,*,%q')\n" + " AND ldb_entry.eid IN\n(%s)\n" + " )\n" + + " %s\n" + + " ORDER BY entry.eid ASC;", + norm_basedn, + norm_basedn, + sqlfilter, + attr_list); + break; } - - /* All done with variable argument list */ - va_end(args); - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - gettimeofday(&tv, NULL); - t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); - printf("%1.6lf %s\n%s\n\n", t1 - t0, - ret == 0 ? "SUCCESS" : "FAIL", - p); + + if (query == NULL) { + ret = -1; + goto failed; } - /* Free the memory we allocated for our query string */ - sqlite3_free(p); - - return ret; -} + /* printf ("%s\n", query); */ + msgs.msgs = NULL; + msgs.count = 0; + msgs.current_eid = 0; + msgs.mem_ctx = local_ctx; -/* - * query_int() - * - * This function is used for the common case of queries that return a single - * integer value. - * - * NOTE: If more than one value is returned by the query, all but the first - * one will be ignored. - */ -static int -query_int(const struct lsqlite3_private * lsqlite3, - long long * pRet, - const char * pSql, - ...) -{ - int ret; - int bLoop; - char * p; - sqlite3_stmt * pStmt; - va_list args; - double t0 = 0; - double t1; - struct timeval tv; - struct timezone tz; - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - gettimeofday(&tv, &tz); - t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); + ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, &msgs, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_search_bytree: Fatal Error: %s\n", errmsg); + free(errmsg); + } + goto failed; } - /* Begin access to variable argument list */ - va_start(args, pSql); - - /* Format the query */ - if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return SQLITE_NOMEM; - } + for (i = 0; i < msgs.count; i++) { + msgs.msgs[i] = ldb_msg_canonicalize(module->ldb, msgs.msgs[i]); + if (msgs.msgs[i] == NULL) goto failed; + } + + *res = talloc_steal(module, msgs.msgs); + ret = msgs.count; + + talloc_free(local_ctx); + return ret; + +/* If error, return error code; otherwise return number of results */ +failed: + talloc_free(local_ctx); + return -1; +} + +/* search for matching records, by expression */ +static int lsqlite3_search(struct ldb_module * module, const struct ldb_dn *basedn, + enum ldb_scope scope, const char * expression, + const char * const *attrs, struct ldb_message *** res) +{ + struct ldb_parse_tree * tree; + int ret; - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - printf("%s\n", p); + /* Handle tdb specials */ + if (ldb_dn_is_special(basedn)) { +#warning "handle tdb specials" + return 0; } - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - p, - -1, - &pStmt, - NULL)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - break; - } - - /* One row expected */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_ROW) { - (void) sqlite3_finalize(pStmt); - break; - } - - /* Get the value to be returned */ - *pRet = sqlite3_column_int64(pStmt, 0); - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - bLoop = FALSE; +#if 0 +/* (|(objectclass=*)(dn=*)) is passed by the command line tool now instead */ + /* Handle the special case of requesting all */ + if (pExpression != NULL && *pExpression == '\0') { + pExpression = "dn=*"; } +#endif + + /* Parse the filter expression into a tree we can work with */ + if ((tree = ldb_parse_tree(module->ldb, expression)) == NULL) { + return -1; + } - /* All done with variable argument list */ - va_end(args); + /* Now use the bytree function for the remainder of processing */ + ret = lsqlite3_search_bytree(module, basedn, scope, tree, attrs, res); - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - gettimeofday(&tv, NULL); - t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); - printf("%1.6lf %s\n%s\n\n", t1 - t0, - ret == 0 ? "SUCCESS" : "FAIL", - p); - } - - /* Free the memory we allocated for our query string */ - sqlite3_free(p); + /* Free the parse tree */ + talloc_free(tree); + /* All done. */ return ret; } -/* - * getEID() - * - * This function is used for the very common case of retrieving an EID value - * given a normalized DN. - * - * NOTE: If more than one value is returned by the query, all but the first - * one will be ignored. - */ -static int -getEID(const struct lsqlite3_private * lsqlite3, - long long * pRet, - const char * pNormalizedDN) +/* add a record */ +static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) { - int ret; - int bLoop; - const char * query = - "SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = 'DN'\n" - " AND attr_value_normalized = :dn;"; - - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - ret = SQLITE_OK; - if (stmtGetEID == NULL && - (ret = sqlite3_prepare(lsqlite3->sqlite, - query, - -1, - &stmtGetEID, - NULL)) == SQLITE_SCHEMA) { - continue; - } else if (ret != SQLITE_OK) { - break; - } - - /* Bind our parameter */ - if ((ret = sqlite3_bind_text(stmtGetEID, - 1, - pNormalizedDN, - -1, - SQLITE_STATIC)) != SQLITE_OK) { - break; - } + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + long long eid; + char *dn, *ndn; + char *errmsg; + char *query; + int rollback = 0; + int ret; + int i; + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_add local context"); + if (local_ctx == NULL) { + return -1; + } - /* One row expected */ - if ((ret = sqlite3_step(stmtGetEID)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - continue; - } else if (ret != SQLITE_ROW) { - (void) sqlite3_reset(stmtGetEID); - break; - } - - /* Get the value to be returned */ - *pRet = sqlite3_column_int64(stmtGetEID, 0); - - /* Free the virtual machine */ - if ((ret = sqlite3_reset(stmtGetEID)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - bLoop = FALSE; - } - - return ret; -} + /* See if this is an ltdb special */ + if (ldb_dn_is_special(msg->dn)) { + struct ldb_dn *c; + c = ldb_dn_explode(local_ctx, "@SUBCLASSES"); + if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { +#warning "insert subclasses into object class tree" + goto failed; + } -/* - callback function used in call to ldb_dn_fold() for determining whether an - attribute type requires case folding. -*/ -static int -case_fold_attr_required(void * hUserData, - char *attr) -{ -// struct ldb_module * module = hUserData; - - return TRUE; -} + c = ldb_dn_explode(local_ctx, "@INDEXLIST"); + if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { +#warning "should we handle indexes somehow ?" + goto failed; + } -static int -case_fold_attr_not_required(void * hUserData, - char *attr) -{ -// struct ldb_module * module = hUserData; - - return FALSE; -} + /* Others are implicitly ignored */ + return 0; + } + + /* create linearized and normalized dns */ + dn = ldb_dn_linearize(local_ctx, msg->dn); + ndn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, msg->dn)); + if (dn == NULL || ndn == NULL) goto failed; + + query = lsqlite3_tprintf(local_ctx, + /* Begin the transaction */ + "BEGIN EXCLUSIVE; " + /* Add new entry */ + "INSERT OR ABORT INTO ldb_entry " + "('dn', 'norm_dn') " + "VALUES ('%q', '%q');", + dn, ndn); + if (query == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_add: exec error: %s\n", errmsg); + free(errmsg); + } + lsqlite3_safe_rollback(lsqlite3->sqlite); + goto failed; + } + rollback = 1; + eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, ndn); + if (eid == -1) goto failed; -/* - * add a single set of ldap message values to a ldb_message - */ + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_attrib_handler *h; + char *attr; + int j; -static int -add_msg_attr(void * hTalloc, - long long eid, - const char * pDN, - const char * pAttrName, - const char * pAttrValue, - long long prevEID, - int * pAllocated, - struct ldb_message *** pppRes) -{ - void * x; - struct ldb_message * msg; - struct ldb_message_element * el; - - /* Is this a different EID than the previous one? */ - if (eid != prevEID) { - /* Yup. Add another result to the result array */ - if ((x = talloc_realloc(hTalloc, - *pAllocated == 0 ? NULL : *pppRes, - struct ldb_message *, - *pAllocated + 1)) == NULL) { - - return -1; - } - - /* Save the new result list */ - *pppRes = x; + /* Get a case-folded copy of the attribute name */ + attr = ldb_casefold(local_ctx, el->name); + if (attr == NULL) goto failed; - /* Allocate a new result structure */ - if ((x = talloc(*pppRes, struct ldb_message)) == NULL) { - return -1; - } + h = ldb_attrib_handler(module->ldb, el->name); - /* Save the new result */ - (*pppRes)[*pAllocated] = x; + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + char *insert; + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); + if (value.data == NULL) goto failed; + + insert = lsqlite3_tprintf(local_ctx, + "INSERT OR ROLLBACK INTO ldb_attribute_values " + "('eid', 'attr_name', 'norm_attr_name'," + " 'attr_value', 'norm_attr_value') " + "VALUES ('%lld', '%q', '%q', '%q', '%q');", + eid, el->name, attr, + el->values[j].data, value.data); + if (insert == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, insert, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_add: insert error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } + } - /* Steal the initial result and put it in its own context */ - talloc_steal(NULL, *pppRes); + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_add: commit error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } - /* We've allocated one more result */ - ++*pAllocated; - - /* Ensure that the message is initialized */ - msg = x; - if ((msg->dn = talloc_strdup(msg, pDN)) == NULL) { - return -1; - } - msg->num_elements = 0; - msg->elements = NULL; - msg->private_data = NULL; - } else { - /* Same EID. Point to the previous most-recent message */ - msg = (*pppRes)[*pAllocated - 1]; - } - - if (pAttrName != NULL && pAttrValue != NULL) { - /* - * Point to the most recent previous element. (If there are none, - * this will point to non-allocated memory, but the pointer will - * never be dereferenced.) - */ - el = &msg->elements[msg->num_elements - 1]; - - /* - * See if the most recent previous element has the same attr_name - */ - if (msg->num_elements == 0 || strcmp(el->name, pAttrName) != 0) { - - /* It's a new attr_name. Allocate another message element */ - if ((el = talloc_realloc(msg, - msg->elements, - struct ldb_message_element, - msg->num_elements + 1)) == NULL) { - return -1; - } - - /* Save the new element */ - msg->elements = el; - - /* Save the attribute name */ - if ((el->name = - talloc_strdup(msg->elements, pAttrName)) == NULL) { - - return -1; - } - - /* There's now one additional element */ - msg->num_elements++; - - /* No flags */ - el->flags = 0; - - /* Initialize number of attribute values for this type */ - el->num_values = 0; - el->values = NULL; - } - - /* Increase the value array size by 1 */ - if ((el->values = - talloc_realloc(el, - el->num_values == 0 ? NULL : el->values, - struct ldb_val, - el->num_values + 1)) == NULL) { - return -1; - } - - /* Save the new attribute value length */ - el->values[el->num_values].length = strlen(pAttrValue); - - /* Copy the new attribute value */ - if ((el->values[el->num_values].data = - talloc_memdup(el->values, - pAttrValue, - el->values[el->num_values].length)) == NULL) { - return -1; - } - - /* We now have one additional value of this type */ - el->num_values++; - } - - return 0; + talloc_free(local_ctx); + return 0; + +failed: + if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); + talloc_free(local_ctx); + return -1; } -static char * -parsetree_to_sql(struct ldb_module *module, - char * hTalloc, - const struct ldb_parse_tree *t) + +/* modify a record */ +static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg) { - int i; - char * pNormalizedDN; - char * child; - char * p; - char * ret = NULL; - char * pAttrName; - - - switch(t->operation) { - case LDB_OP_SIMPLE: - break; - - case LDB_OP_EXTENDED: -#warning "work out how to handle bitops" - return NULL; + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + long long eid; + char *errmsg; + int rollback = 0; + int ret; + int i; + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_modify local context"); + if (local_ctx == NULL) { + return -1; + } - case LDB_OP_AND: - ret = parsetree_to_sql(module, - hTalloc, - t->u.list.elements[0]); - - for (i = 1; i < t->u.list.num_elements; i++) { - child = - parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "INTERSECT\n" - "%s\n", - child); - talloc_free(child); - } - - child = ret; - ret = talloc_asprintf(hTalloc, - "SELECT * FROM (\n" - "%s\n" - ")\n", - child); - talloc_free(child); - return ret; - - case LDB_OP_OR: - ret = parsetree_to_sql(module, - hTalloc, - t->u.list.elements[0]); - - for (i = 1; i < t->u.list.num_elements; i++) { - child = - parsetree_to_sql( - module, - hTalloc, - t->u.list.elements[i]); - ret = talloc_asprintf_append(ret, - "UNION\n" - "%s\n", - child); - talloc_free(child); - } - child = ret; - ret = talloc_asprintf(hTalloc, - "SELECT * FROM (\n" - "%s\n" - ")\n", - child); - talloc_free(child); - return ret; - - case LDB_OP_NOT: - child = - parsetree_to_sql( - module, - hTalloc, - t->u.not.child); - ret = talloc_asprintf(hTalloc, - " SELECT eid\n" - " FROM ldb_entry\n" - " WHERE eid NOT IN (%s)\n", - child); - talloc_free(child); - return ret; - - default: - /* should never occur */ - abort(); - }; - - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, - t->u.simple.attr); - - /* - * For simple searches, we want to retrieve the list of EIDs that - * match the criteria. - */ - if (t->u.simple.value.length == 1 && - (*(const char *) t->u.simple.value.data) == '*') { - /* - * Special case for "attr_name=*". In this case, we want the - * eid corresponding to all values in the specified attribute - * table. - */ - if ((p = sqlite3_mprintf(" SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = %Q", - pAttrName)) == NULL) { - return NULL; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - printf("%s\n", p); - } + /* See if this is an ltdb special */ + if (ldb_dn_is_special(msg->dn)) { + struct ldb_dn *c; - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); + c = ldb_dn_explode(local_ctx, "@SUBCLASSES"); + if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { +#warning "modify subclasses into object class tree" + goto failed; + } - } else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) { - /* - * For object classes, we want to search for all objectclasses - * that are subclasses as well. - */ - if ((p = sqlite3_mprintf( - " SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = 'OBJECTCLASS' " - " AND attr_value_normalized IN\n" - " (SELECT class_name\n" - " FROM ldb_object_classes\n" - " WHERE tree_key GLOB\n" - " (SELECT tree_key\n" - " FROM ldb_object_classes\n" - " WHERE class_name = upper(%Q)) " - " || '*')\n", - t->u.simple.value.data)) == NULL) { - return NULL; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - printf("%s\n", p); - } + c = ldb_dn_explode(local_ctx, "@INDEXLIST"); + if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { +#warning "should we handle indexes somehow ?" + goto failed; + } - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); - - } else if (strcasecmp(t->u.simple.attr, "dn") == 0) { - pNormalizedDN = ldb_dn_fold(module->ldb, t->u.simple.value.data, - module, case_fold_attr_required); - if ((p = sqlite3_mprintf( - " SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = %Q\n" - " AND attr_value_normalized = %Q\n", - pAttrName, - pNormalizedDN)) == NULL) { - return NULL; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - printf("%s\n", p); - } + /* Others are implicitly ignored */ + return 0; + } - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); - } else { - /* A normal query. */ - if ((p = sqlite3_mprintf( - " SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = %Q\n" - " AND attr_value_normalized = upper(%Q)\n", - pAttrName, - t->u.simple.value.data)) == NULL) { - return NULL; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_QUERY) { - printf("%s\n", p); - } + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN EXCLUSIVE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + rollback = 1; - ret = talloc_strdup(hTalloc, p); - sqlite3_free(p); + eid = lsqlite3_get_eid(module, msg->dn); + if (eid == -1) { + goto failed; } - return ret; -} + for (i = 0; i < msg->num_elements; i++) { + const struct ldb_message_element *el = &msg->elements[i]; + const struct ldb_attrib_handler *h; + int flags = el->flags & LDB_FLAG_MOD_MASK; + char *attr; + char *mod; + int j; + + /* Get a case-folded copy of the attribute name */ + attr = ldb_casefold(local_ctx, el->name); + if (attr == NULL) { + goto failed; + } + h = ldb_attrib_handler(module->ldb, el->name); + + switch (flags) { + + case LDB_FLAG_MOD_REPLACE: + + /* remove all attributes before adding the replacements */ + mod = lsqlite3_tprintf(local_ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q';", + eid, attr); + if (mod == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } -static int -parsetree_to_attrlist(struct ldb_module *module, - const struct ldb_parse_tree * t) -{ - int i; - struct lsqlite3_private * lsqlite3 = module->private_data; - - switch(t->operation) { - case LDB_OP_SIMPLE: - break; - - case LDB_OP_EXTENDED: -#warning "work out how to handle bitops" - return -1; + /* MISSING break is INTENTIONAL */ + + case LDB_FLAG_MOD_ADD: +#warning "We should throw an error if no value is provided!" + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); + if (value.data == NULL) { + goto failed; + } + + mod = lsqlite3_tprintf(local_ctx, + "INSERT OR ROLLBACK INTO ldb_attribute_values " + "('eid', 'attr_name', 'norm_attr_name'," + " 'attr_value', 'norm_attr_value') " + "VALUES ('%lld', '%q', '%q', '%q', '%q');", + eid, el->name, attr, + el->values[j].data, value.data); + + if (mod == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } - case LDB_OP_AND: - if (parsetree_to_attrlist( - module, - t->u.list.elements[0]) != 0) { - return -1; - } - - for (i = 1; i < t->u.list.num_elements; i++) { - if (parsetree_to_attrlist( - module, - t->u.list.elements[i]) != 0) { - return -1; - } - } - - return 0; - - case LDB_OP_OR: - if (parsetree_to_attrlist( - module, - t->u.list.elements[0]) != 0) { - return -1; - } - - for (i = 1; i < t->u.list.num_elements; i++) { - if (parsetree_to_attrlist( - module, - t->u.list.elements[i]) != 0) { - return -1; - } - } - - return 0; - - case LDB_OP_NOT: - if (parsetree_to_attrlist(module, - t->u.not.child) != 0) { - return -1; - } - - return 0; - - default: - /* should never occur */ - abort(); - }; - - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT OR IGNORE INTO " FILTER_ATTR_TABLE "\n" - " (attr_name)\n" - " VALUES\n" - " (%Q);", - t->u.simple.attr); - return 0; -} + break; + + case LDB_FLAG_MOD_DELETE: +#warning "We should throw an error if the attribute we are trying to delete does not exist!" + if (el->num_values == 0) { + mod = lsqlite3_tprintf(local_ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q';", + eid, attr); + if (mod == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } + /* For each value of the specified attribute name... */ + for (j = 0; j < el->num_values; j++) { + struct ldb_val value; + + /* Get a canonicalised copy of the data */ + h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); + if (value.data == NULL) { + goto failed; + } + + mod = lsqlite3_tprintf(local_ctx, + "DELETE FROM ldb_attribute_values " + "WHERE eid = '%lld' " + "AND norm_attr_name = '%q' " + "AND norm_attr_value = '%q';", + eid, attr, value.data); + + if (mod == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + } -/* - * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE - * requests in the ldb_message - */ -static int -msg_to_sql(struct ldb_module * module, - const struct ldb_message * msg, - long long eid, - int use_flags) -{ - int flags; - char * pAttrName; - unsigned int i; - unsigned int j; - struct lsqlite3_private * lsqlite3 = module->private_data; - - for (i = 0; i < msg->num_elements; i++) { - const struct ldb_message_element *el = &msg->elements[i]; - - if (! use_flags) { - flags = LDB_FLAG_MOD_ADD; - } else { - flags = el->flags & LDB_FLAG_MOD_MASK; - } - - /* Get a case-folded copy of the attribute name */ - pAttrName = ldb_casefold((struct ldb_context *) module, - el->name); - - /* For each value of the specified attribute name... */ - for (j = 0; j < el->num_values; j++) { - - /* ... bind the attribute value, if necessary */ - switch (flags) { - case LDB_FLAG_MOD_ADD: - QUERY_NOROWS( - lsqlite3, - FALSE, - "INSERT INTO ldb_attribute_values\n" - " (eid,\n" - " attr_name,\n" - " attr_value,\n" - " attr_value_normalized)\n" - " VALUES\n" - " (%lld, %Q, %Q, upper(%Q));", - eid, - pAttrName, - el->values[j].data, /* FIX ME */ - el->values[j].data); - - /* Is this a special "objectclass"? */ - if (strcasecmp(pAttrName, - "objectclass") != 0) { - /* Nope. */ - break; - } - - /* Handle special "objectclass" type */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT OR IGNORE " - " INTO ldb_object_classes " - " (class_name, " - " parent_class_name) " - " VALUES " - " (upper(%Q), 'TOP');", - ldb_casefold(module, - el->values[j].data)); - break; - - case LDB_FLAG_MOD_REPLACE: - QUERY_NOROWS( - lsqlite3, - FALSE, - "UPDATE ldb_attribute_values\n" - " SET attr_value = %Q,\n" - " attr_value_normalized =\n" - " upper(%Q)\n" - " WHERE eid = %lld\n" - " AND attr_name = %Q;", - el->values[j].data, /* FIX ME */ - el->values[j].data, - eid, - pAttrName); - break; - - case LDB_FLAG_MOD_DELETE: - /* No additional parameters to this query */ - QUERY_NOROWS( - lsqlite3, - FALSE, - "DELETE FROM ldb_attribute_values" - " WHERE eid = %lld " - " AND attr_name = %Q " - " AND attr_value_normalized =\n" - " upper(%Q);", - eid, - el->name, - el->values[j].data); - break; - } + break; } } - - return 0; -} + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_modify: error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + + talloc_free(local_ctx); + return 0; +failed: + if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); + talloc_free(local_ctx); + return -1; +} -static int -new_dn(struct ldb_module * module, - char * pDN, - long long * pEID) +/* delete a record */ +static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) { - int ret; - int bFirst; - int nComponent; - char * p; - char * pPartialDN; - char * pPartialNormalizedDN; - long long eid; - long long peid; - double t0 = 0; - double t1 = 0; - struct timeval tv; - struct timezone tz; - struct ldb_dn * pExplodedDN; - struct ldb_dn_component * pComponent; - struct ldb_context * ldb = module->ldb; - struct lsqlite3_private * lsqlite3 = module->private_data; - - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, &tz); - t0 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); - } + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + long long eid; + char *errmsg; + char *query; + int ret; + + /* ignore ltdb specials */ + if (ldb_dn_is_special(dn)) { + return 0; + } - /* Explode the DN */ - if ((pExplodedDN = - ldb_explode_dn(ldb, - pDN, - ldb, - case_fold_attr_not_required)) == NULL) { - return -1; - } - - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0); - printf("%1.6lf loc 1\n", t1 - t0); - t0 = t1; - } + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_delete local context"); + if (local_ctx == NULL) { + return -1; + } - /* Allocate a string to hold the partial DN of each component */ - if ((pPartialDN = talloc_strdup(ldb, "")) == NULL) { - return -1; - } - - if ((pPartialNormalizedDN = talloc_strdup(pPartialDN, "")) == NULL) { - return -1; - } + eid = lsqlite3_get_eid(module, dn); + if (eid == -1) goto failed; + + query = lsqlite3_tprintf(local_ctx, + /* Begin the transaction */ + "BEGIN EXCLUSIVE; " + /* Delete entry */ + "DELETE FROM ldb_entry WHERE eid = %lld; " + /* Delete attributes */ + "DELETE FROM ldb_attribute_values WHERE eid = %lld; " + /* Commit */ + "COMMIT;", + eid, eid); + if (query == NULL) goto failed; + + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_delete: error getting eid: %s\n", errmsg); + free(errmsg); + } + lsqlite3_safe_rollback(lsqlite3->sqlite); + goto failed; + } + + talloc_free(local_ctx); + return 0; + +failed: + talloc_free(local_ctx); + return -1; +} + +/* rename a record */ +static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) +{ + TALLOC_CTX *local_ctx; + struct lsqlite3_private *lsqlite3 = module->private_data; + char *new_dn, *new_cdn, *old_cdn; + char *errmsg; + char *query; + int ret; + + /* ignore ltdb specials */ + if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) { + return 0; + } + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_rename local context"); + if (local_ctx == NULL) { + return -1; + } + + /* create linearized and normalized dns */ + old_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, olddn)); + new_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, newdn)); + new_dn = ldb_dn_linearize(local_ctx, newdn); + if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) goto failed; + + /* build the SQL query */ + query = lsqlite3_tprintf(local_ctx, + "UPDATE ldb_entry SET dn = '%q', norm_dn = '%q' " + "WHERE norm_dn = '%q';", + new_dn, new_cdn, old_cdn); + if (query == NULL) goto failed; + + /* execute */ + ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_rename: sqlite3_exec error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + + /* clean up and exit */ + talloc_free(local_ctx); + return 0; + +failed: + talloc_free(local_ctx); + return -1; +} +/* return extended error information */ +static const char * +lsqlite3_errstring(struct ldb_module *module) +{ + struct lsqlite3_private * lsqlite3 = module->private_data; - /* For each component of the DN (starting with the last one)... */ -#warning "convert this loop to recursive, and search backwards instead" - eid = 0; + return sqlite3_errmsg(lsqlite3->sqlite); +} + + + + +/* + * Static functions + */ - for (nComponent = pExplodedDN->comp_num - 1, bFirst = TRUE; - nComponent >= 0; - nComponent--, bFirst = FALSE) { +static int initialize(struct lsqlite3_private *lsqlite3, const char *url) +{ + int ret; + long long queryInt; + const char *pTail; + sqlite3_stmt *stmt; + const char *schema = - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 2\n", t1 - t0); - t0 = t1; - } - /* Point to the component */ - pComponent = pExplodedDN->components[nComponent]; + "CREATE TABLE ldb_info AS " + " SELECT 'LDB' AS database_type," + " '1.0' AS version;" - /* Add this component on to the partial DN to date */ - if ((p = talloc_asprintf(ldb, - "%s%s%s", - pComponent->component, - bFirst ? "" : ",", - pPartialDN)) == NULL) { - return -1; - } + /* + * The entry table holds the information about an entry. + * This table is used to obtain the EID of the entry and to + * support scope=one and scope=base. The parent and child + * table is included in the entry table since all the other + * attributes are dependent on EID. + */ + "CREATE TABLE ldb_entry " + "(" + " eid INTEGER PRIMARY KEY AUTOINCREMENT," + " dn TEXT UNIQUE NOT NULL," + " norm_dn TEXT UNIQUE NOT NULL" + ");" - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 3\n", t1 - t0); - t0 = t1; - } + + "CREATE TABLE ldb_object_classes" + "(" + " class_name TEXT PRIMARY KEY," + " parent_class_name TEXT," + " tree_key TEXT UNIQUE," + " max_child_num INTEGER DEFAULT 0" + ");" - /* No need for the old partial DN any more */ - talloc_free(pPartialDN); + /* + * We keep a full listing of attribute/value pairs here + */ + "CREATE TABLE ldb_attribute_values" + "(" + " eid INTEGER REFERENCES ldb_entry," + " attr_name TEXT," + " norm_attr_name TEXT," + " attr_value TEXT," + " norm_attr_value TEXT " + ");" - /* Save the new partial DN */ - pPartialDN = p; - pPartialNormalizedDN = ldb_dn_fold(pPartialDN, - p, - module, - case_fold_attr_required); + + /* + * Indexes + */ + "CREATE INDEX ldb_attribute_values_eid_idx " + " ON ldb_attribute_values (eid);" - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 4\n", t1 - t0); - t0 = t1; - } + "CREATE INDEX ldb_attribute_values_name_value_idx " + " ON ldb_attribute_values (attr_name, norm_attr_value);" + + /* - * Ensure that an entry is in the ldb_entry table for this - * component. + * Triggers */ - if ((ret = getEID(lsqlite3, - &eid, - pPartialNormalizedDN)) == SQLITE_DONE) { - - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_entry\n" - " (peid, dn, normalized_dn)\n" - " VALUES\n" - " (%lld, %Q, %Q);", - eid, pPartialDN, pPartialNormalizedDN); - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 5\n", t1 - t0); - t0 = t1; - } - - /* Get the EID of the just inserted row */ - eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); - - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 8\n", t1 - t0); - t0 = t1; - } + "CREATE TRIGGER ldb_object_classes_insert_tr" + " AFTER INSERT" + " ON ldb_object_classes" + " FOR EACH ROW" + " BEGIN" + " UPDATE ldb_object_classes" + " SET tree_key = COALESCE(tree_key, " + " (" + " SELECT tree_key || " + " (SELECT base160(max_child_num + 1)" + " FROM ldb_object_classes" + " WHERE class_name = " + " new.parent_class_name)" + " FROM ldb_object_classes " + " WHERE class_name = new.parent_class_name " + " ));" + " UPDATE ldb_object_classes " + " SET max_child_num = max_child_num + 1" + " WHERE class_name = new.parent_class_name;" + " END;" - /* Also add DN attribute */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT INTO ldb_attribute_values\n" - " (eid,\n" - " attr_name,\n" - " attr_value,\n" - " attr_value_normalized) " - " VALUES " - " (%lld, 'DN', %Q, %Q);", - eid, - pPartialDN, /* FIX ME */ - pPartialNormalizedDN); + /* + * Table initialization + */ - } else if (ret != SQLITE_OK) { - UNLOCK_DB(module, "rollback"); - return -1; - } + "INSERT INTO ldb_object_classes " + " (class_name, tree_key) " + " VALUES " + " ('TOP', '0001');" - /* Save the parent EID */ - peid = eid; + ; + + /* Skip protocol indicator of url */ + if (strncmp(url, "sqlite://", 9) != 0) { + return SQLITE_MISUSE; } - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 9\n", t1 - t0); - t0 = t1; + /* Update pointer to just after the protocol indicator */ + url += 9; + + /* Try to open the (possibly empty/non-existent) database */ + if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) { + return ret; } - - /* Give 'em what they came for! */ - *pEID = eid; - return 0; -} - - -static unsigned char base160tab[161] = { - 48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */ - 58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */ - 73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 , /* I-R */ - 83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,97 ,98 , /* S-Z , a-b */ - 99 ,100,101,102,103,104,105,106,107,108, /* c-l */ - 109,110,111,112,113,114,115,116,117,118, /* m-v */ - 119,120,121,122,160,161,162,163,164,165, /* w-z, latin1 */ - 166,167,168,169,170,171,172,173,174,175, /* latin1 */ - 176,177,178,179,180,181,182,183,184,185, /* latin1 */ - 186,187,188,189,190,191,192,193,194,195, /* latin1 */ - 196,197,198,199,200,201,202,203,204,205, /* latin1 */ - 206,207,208,209,210,211,212,213,214,215, /* latin1 */ - 216,217,218,219,220,221,222,223,224,225, /* latin1 */ - 226,227,228,229,230,231,232,233,234,235, /* latin1 */ - 236,237,238,239,240,241,242,243,244,245, /* latin1 */ - 246,247,248,249,250,251,252,253,254,255, /* latin1 */ - '\0' -}; - - -/* - * base160() - * - * Convert an unsigned long integer into a base160 representation of the - * number. - * - * Parameters: - * val -- - * value to be converted - * - * result -- - * character array, 5 bytes long, into which the base160 representation - * will be placed. The result will be a four-digit representation of the - * number (with leading zeros prepended as necessary), and null - * terminated. - * - * Returns: - * Nothing - */ -static void -base160_sql(sqlite3_context * hContext, - int argc, - sqlite3_value ** argv) -{ - int i; - long long val; - char result[5]; - - val = sqlite3_value_int64(argv[0]); - - for (i = 3; i >= 0; i--) { + /* In case this is a new database, enable auto_vacuum */ + if (query_norows(lsqlite3, "PRAGMA auto_vacuum=1;") != 0) { + return -1; + } - result[i] = base160tab[val % 160]; - val /= 160; - } - - result[4] = '\0'; - - sqlite3_result_text(hContext, result, -1, SQLITE_TRANSIENT); -} - - -/* - * base160next_sql() - * - * This function enhances sqlite by adding a "base160_next()" function which is - * accessible via queries. - * - * Retrieve the next-greater number in the base160 sequence for the terminal - * tree node (the last four digits). Only one tree level (four digits) is - * operated on. - * - * Input: - * A character string: either an empty string (in which case no operation is - * performed), or a string of base160 digits with a length of a multiple of - * four digits. - * - * Output: - * Upon return, the trailing four digits (one tree level) will have been - * incremented by 1. - */ -static void -base160next_sql(sqlite3_context * hContext, - int argc, - sqlite3_value ** argv) -{ - int i; - int len; - unsigned char * pTab; - unsigned char * pBase160 = - strdup(sqlite3_value_text(argv[0])); - unsigned char * pStart = pBase160; - - /* - * We need a minimum of four digits, and we will always get a multiple - * of four digits. - */ - if (pBase160 != NULL && - (len = strlen(pBase160)) >= 4 && - len % 4 == 0) { - - if (pBase160 == NULL) { - - sqlite3_result_null(hContext); - return; - } - - pBase160 += strlen(pBase160) - 1; - - /* We only carry through four digits: one level in the tree */ - for (i = 0; i < 4; i++) { - - /* What base160 value does this digit have? */ - pTab = strchr(base160tab, *pBase160); + /* Establish a busy timeout of 30 seconds */ + if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, + 30000)) != SQLITE_OK) { + return ret; + } - /* Is there a carry? */ - if (pTab < base160tab + sizeof(base160tab) - 1) { + /* Create a function, callable from sql, to increment a tree_key */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160_next", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160next_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } - /* - * Nope. Just increment this value and we're - * done. - */ - *pBase160 = *++pTab; - break; - } else { + /* Create a function, callable from sql, to convert int to base160 */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite,/* handle */ + "base160", /* function name */ + 1, /* number of args */ + SQLITE_ANY, /* preferred text type */ + NULL, /* user data */ + base160_sql, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; + } - /* - * There's a carry. This value gets - * base160tab[0], we decrement the buffer - * pointer to get the next higher-order digit, - * and continue in the loop. - */ - *pBase160-- = base160tab[0]; + /* Begin a transaction */ + if ((ret = query_norows(lsqlite3, "BEGIN EXCLUSIVE;")) != 0) { + return ret; + } + + /* Determine if this is a new database. No tables means it is. */ + if (query_int(lsqlite3, + &queryInt, + "SELECT COUNT(*)\n" + " FROM sqlite_master\n" + " WHERE type = 'table';") != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return -1; + } + + if (queryInt == 0) { + /* + * Create the database schema + */ + for (pTail = discard_const_p(char, schema); + pTail != NULL && *pTail != '\0'; + ) { + + if ((ret = sqlite3_prepare( + lsqlite3->sqlite, + pTail, + -1, + &stmt, + &pTail)) != SQLITE_OK || + (ret = sqlite3_step(stmt)) != SQLITE_DONE || + (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { + + query_norows(lsqlite3, "ROLLBACK;"); + (void) sqlite3_close(lsqlite3->sqlite); + return ret; } } - - sqlite3_result_text(hContext, - pStart, - strlen(pStart), - free); } else { - sqlite3_result_value(hContext, argv[0]); - if (pBase160 != NULL) { - free(pBase160); + /* + * Ensure that the database we opened is one of ours + */ + if (query_int(lsqlite3, + &queryInt, + "SELECT " + " (SELECT COUNT(*) = 2" + " FROM sqlite_master " + " WHERE type = 'table' " + " AND name IN " + " (" + " 'ldb_entry', " + " 'ldb_object_classes' " + " ) " + " ) " + " AND " + " (SELECT 1 " + " FROM ldb_info " + " WHERE database_type = 'LDB' " + " AND version = '1.0'" + " );") != 0 || + queryInt != 1) { + + /* It's not one that we created. See ya! */ + query_norows(lsqlite3, "ROLLBACK;"); + (void) sqlite3_close(lsqlite3->sqlite); + return SQLITE_MISUSE; } } -} + + /* + * Create a temporary table to hold attributes requested in the result + * set of a search. + */ + query_norows(lsqlite3, "DROP TABLE " RESULT_ATTR_TABLE ";\n"); + if ((ret = + query_norows(lsqlite3, + "CREATE " TEMPTAB " TABLE " RESULT_ATTR_TABLE "\n" + " (\n" + " attr_name TEXT PRIMARY KEY\n" + " );")) != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return ret; + } + /* Commit the transaction */ + if ((ret = query_norows(lsqlite3, "COMMIT;")) != 0) { + query_norows(lsqlite3, "ROLLBACK;"); + return ret; + } + + return SQLITE_OK; +} -#ifdef DEBUG_LOCKS -static int lock_debug(struct ldb_module * module, - const char * lockname, - const char * pFileName, - int linenum) +static int +destructor(void *p) { - int ret; - struct lsqlite3_private * lsqlite3 = module->private_data; + struct lsqlite3_private *lsqlite3 = p; + + if (lsqlite3->sqlite) { + sqlite3_close(lsqlite3->sqlite); + } + return 0; +} - printf("%s(%d): LOCK (%d) ", - pFileName, linenum, lsqlite3->lock_count); - ret = lsqlite3_lock(module, lockname); - printf("got %d\n", ret); - return ret; -} - -static int unlock_debug(struct ldb_module * module, - const char * lockname, - const char * pFileName, - int linenum) +/* + * Table of operations for the sqlite3 backend + */ +static const struct ldb_module_ops lsqlite3_ops = { + .name = "sqlite", + .search = lsqlite3_search, + .search_bytree = lsqlite3_search_bytree, + .add_record = lsqlite3_add, + .modify_record = lsqlite3_modify, + .delete_record = lsqlite3_delete, + .rename_record = lsqlite3_rename, + .named_lock = lsqlite3_lock, + .named_unlock = lsqlite3_unlock, + .errstring = lsqlite3_errstring +}; + +/* + * connect to the database + */ +int lsqlite3_connect(struct ldb_context *ldb, + const char *url, + unsigned int flags, + const char *options[]) { + int i; int ret; - struct lsqlite3_private * lsqlite3 = module->private_data; - - ret = lsqlite3_unlock(module, lockname); - printf("%s(%d): UNLOCK (%d) got %d\n", - pFileName, linenum, lsqlite3->lock_count, ret); - - return ret; + struct lsqlite3_private * lsqlite3 = NULL; + + lsqlite3 = talloc(ldb, struct lsqlite3_private); + if (!lsqlite3) { + goto failed; + } + + lsqlite3->sqlite = NULL; + lsqlite3->options = NULL; + lsqlite3->lock_count = 0; + + ret = initialize(lsqlite3, url); + if (ret != SQLITE_OK) { + goto failed; + } + + talloc_set_destructor(lsqlite3, destructor); + + ldb->modules = talloc(ldb, struct ldb_module); + if (!ldb->modules) { + goto failed; + } + ldb->modules->ldb = ldb; + ldb->modules->prev = ldb->modules->next = NULL; + ldb->modules->private_data = lsqlite3; + ldb->modules->ops = &lsqlite3_ops; + + if (options) { + /* + * take a copy of the options array, so we don't have to rely + * on the caller keeping it around (it might be dynamic) + */ + for (i=0;options[i];i++) ; + + lsqlite3->options = talloc_array(lsqlite3, char *, i+1); + if (!lsqlite3->options) { + goto failed; + } + + for (i=0;options[i];i++) { + + lsqlite3->options[i+1] = NULL; + lsqlite3->options[i] = + talloc_strdup(lsqlite3->options, options[i]); + if (!lsqlite3->options[i]) { + goto failed; + } + } + } + + return 0; + +failed: + if (lsqlite3->sqlite != NULL) { + (void) sqlite3_close(lsqlite3->sqlite); + } + talloc_free(lsqlite3); + return -1; } -#endif + diff --git a/source4/lib/ldb/tests/test-sqlite3.sh b/source4/lib/ldb/tests/test-sqlite3.sh index 18e72024f3..a51ae637dc 100755 --- a/source4/lib/ldb/tests/test-sqlite3.sh +++ b/source4/lib/ldb/tests/test-sqlite3.sh @@ -1,10 +1,22 @@ #!/bin/sh -LDB_URL="sqlite://test.ldb" +LDB_URL="sqlite://sqltest.ldb" export LDB_URL +PATH=bin:$PATH +export PATH + rm -f sqltest.ldb +if [ -z "$LDBDIR" ]; then + LDBDIR="." + export LDBDIR +fi + . $LDBDIR/tests/test-generic.sh +#. $LDBDIR/tests/test-extended.sh + +#. $LDBDIR/tests/test-tdb-features.sh + -- cgit From 36d6ebf37602b1878801fdb34cea5e7c5c1197d5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Sep 2005 23:14:42 +0000 Subject: r10233: add commented PRAGMA to avoid fsyncs (This used to be commit e5d8d834600040793c1e45c7aaceb374df2b3839) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index e283e6b0c1..5cee239b5c 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1616,7 +1616,7 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) /* * Triggers */ - + "CREATE TRIGGER ldb_object_classes_insert_tr" " AFTER INSERT" " ON ldb_object_classes" @@ -1637,7 +1637,7 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) " SET max_child_num = max_child_num + 1" " WHERE class_name = new.parent_class_name;" " END;" - + /* * Table initialization */ @@ -1667,6 +1667,12 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) return -1; } + /* DANGEROUS + if (query_norows(lsqlite3, "PRAGMA synchronous = OFF;") != 0) { + return -1; + } + */ + /* Establish a busy timeout of 30 seconds */ if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, 30000)) != SQLITE_OK) { -- cgit From f77e859e484bee3ebb99dcaa2935a1a323ccfa6f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Sep 2005 07:23:15 +0000 Subject: r10236: fix (C) note (This used to be commit 466e6812c35af9096fea05520c6b59a19793c4d1) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 5cee239b5c..4a4a83090a 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -2,6 +2,7 @@ ldb database library Copyright (C) Derrell Lipman 2005 + Copyright (C) Simo Sorce 2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released -- cgit From fd619b4fb3a9a5c05df765d2cf57a042a4d5da2d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 15 Sep 2005 19:52:13 +0000 Subject: r10245: Get rid of XFILE in a few places. Add fdprintf() and vfdprintf() helper functions. (This used to be commit 6685009f6af94b088084d69a43bcea5f8335ae57) --- source4/lib/cmdline/readline.c | 4 ++-- source4/lib/credentials.c | 30 ++++++++++++------------------ source4/lib/util_file.c | 26 ++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 20 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 4970638d41..42810c8697 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -59,7 +59,7 @@ static char *smb_readline_replacement(const char *prompt, void (*callback)(void) fd_set fds; static pstring line; struct timeval timeout; - int fd = x_fileno(x_stdin); + int fd = STDIN_FILENO; char *ret; do_debug("%s", prompt); @@ -88,7 +88,7 @@ char *smb_readline(const char *prompt, void (*callback)(void), char **(completion_fn)(const char *text, int start, int end)) { #if HAVE_LIBREADLINE - if (isatty(x_fileno(x_stdin))) { + if (isatty(STDIN_FILENO)) { char *ret; /* Aargh! Readline does bizzare things with the terminal width diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index a82c01d4c9..cdef9042b8 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -671,37 +671,30 @@ BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, co BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) { - XFILE *auth; - char buf[128]; uint16_t len = 0; char *ptr, *val, *param; + char **lines; + int i, numlines; - if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL) + lines = file_lines_load(file, &numlines, NULL); + + if (lines == NULL) { /* fail if we can't open the credentials file */ d_printf("ERROR: Unable to open credentials file!\n"); return False; } - while (!x_feof(auth)) - { - /* get a line from the file */ - if (!x_fgets(buf, sizeof(buf), auth)) - continue; - len = strlen(buf); + for (i = 0; i < numlines; i++) { + len = strlen(lines[i]); - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } if (len == 0) continue; /* break up the line into parameter & value. * will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr_m (buf, '='))) + param = lines[i]; + if (!(ptr = strchr_m (lines[i], '='))) continue; val = ptr+1; @@ -720,10 +713,11 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, } else if (strwicmp("realm", param) == 0) { cli_credentials_set_realm(cred, val, obtained); } - memset(buf, 0, sizeof(buf)); + memset(lines[i], 0, len); } - x_fclose(auth); + talloc_free(lines); + return True; } diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 1330b0a70d..338b9547a5 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -397,3 +397,29 @@ BOOL file_exists(const char *path) struct stat st; return (stat(path, &st) == 0); } + +int vfdprintf(int fd, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + VA_COPY(ap2, ap); + + len = vasprintf(&p, format, ap2); + if (len <= 0) return len; + ret = write(fd, p, len); + SAFE_FREE(p); + return ret; +} + +int fdprintf(int fd, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vfdprintf(fd, format, ap); + va_end(ap); + return ret; +} -- cgit From 85263c3061a4d086c9ab92b67238477cae15584f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 15 Sep 2005 20:03:35 +0000 Subject: r10246: Remove unused function Move auth-specific file to auth/ (This used to be commit 8aa9711a306b30da905f53148ebe352462852d74) --- source4/lib/basic.mk | 3 -- source4/lib/pam_errors.c | 126 ----------------------------------------------- source4/lib/util_file.c | 90 +-------------------------------- 3 files changed, 1 insertion(+), 218 deletions(-) delete mode 100644 source4/lib/pam_errors.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 7b95632c70..86392cfc40 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -35,9 +35,6 @@ INIT_OBJ_FILES = \ # End SUBSYSTEM LIBCOMPRESION ################################################ -[SUBSYSTEM::PAM_ERRORS] -OBJ_FILES = lib/pam_errors.o - [SUBSYSTEM::GENCACHE] OBJ_FILES = \ lib/gencache.o \ diff --git a/source4/lib/pam_errors.c b/source4/lib/pam_errors.c deleted file mode 100644 index a00464e624..0000000000 --- a/source4/lib/pam_errors.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * PAM error mapping functions - * Copyright (C) Andrew Bartlett 2002 - * - * 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 - * (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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -#ifdef WITH_HAVE_SECURITY_PAM_APPL_H -#include - -#if defined(PAM_AUTHTOK_RECOVERY_ERR) && !defined(PAM_AUTHTOK_RECOVER_ERR) -#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR -#endif - -/* PAM -> NT_STATUS map */ -static const struct { - int pam_code; - NTSTATUS ntstatus; -} pam_to_nt_status_map[] = { - {PAM_OPEN_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_SYMBOL_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_SERVICE_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_SYSTEM_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_BUF_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_PERM_DENIED, NT_STATUS_ACCESS_DENIED}, - {PAM_AUTH_ERR, NT_STATUS_WRONG_PASSWORD}, - {PAM_CRED_INSUFFICIENT, NT_STATUS_INSUFFICIENT_LOGON_INFO}, /* FIXME: Is this correct? */ - {PAM_AUTHINFO_UNAVAIL, NT_STATUS_LOGON_FAILURE}, - {PAM_USER_UNKNOWN, NT_STATUS_NO_SUCH_USER}, - {PAM_MAXTRIES, NT_STATUS_REMOTE_SESSION_LIMIT}, /* FIXME: Is this correct? */ - {PAM_NEW_AUTHTOK_REQD, NT_STATUS_PASSWORD_MUST_CHANGE}, - {PAM_ACCT_EXPIRED, NT_STATUS_ACCOUNT_EXPIRED}, - {PAM_SESSION_ERR, NT_STATUS_INSUFFICIENT_RESOURCES}, - {PAM_CRED_UNAVAIL, NT_STATUS_NO_TOKEN}, /* FIXME: Is this correct? */ - {PAM_CRED_EXPIRED, NT_STATUS_PASSWORD_EXPIRED}, /* FIXME: Is this correct? */ - {PAM_CRED_ERR, NT_STATUS_UNSUCCESSFUL}, - {PAM_AUTHTOK_ERR, NT_STATUS_UNSUCCESSFUL}, -#ifdef PAM_AUTHTOK_RECOVER_ERR - {PAM_AUTHTOK_RECOVER_ERR, NT_STATUS_UNSUCCESSFUL}, -#endif - {PAM_AUTHTOK_EXPIRED, NT_STATUS_PASSWORD_EXPIRED}, - {PAM_SUCCESS, NT_STATUS_OK} -}; - -/* NT_STATUS -> PAM map */ -static const struct { - NTSTATUS ntstatus; - int pam_code; -} nt_status_to_pam_map[] = { - {NT_STATUS_UNSUCCESSFUL, PAM_SYSTEM_ERR}, - {NT_STATUS_NO_SUCH_USER, PAM_USER_UNKNOWN}, - {NT_STATUS_WRONG_PASSWORD, PAM_AUTH_ERR}, - {NT_STATUS_LOGON_FAILURE, PAM_AUTH_ERR}, - {NT_STATUS_ACCOUNT_EXPIRED, PAM_ACCT_EXPIRED}, - {NT_STATUS_PASSWORD_EXPIRED, PAM_AUTHTOK_EXPIRED}, - {NT_STATUS_PASSWORD_MUST_CHANGE, PAM_NEW_AUTHTOK_REQD}, - {NT_STATUS_OK, PAM_SUCCESS} -}; - -/***************************************************************************** -convert a PAM error to a NT status32 code - *****************************************************************************/ -NTSTATUS pam_to_nt_status(int pam_error) -{ - int i; - if (pam_error == 0) return NT_STATUS_OK; - - for (i=0; NT_STATUS_V(pam_to_nt_status_map[i].ntstatus); i++) { - if (pam_error == pam_to_nt_status_map[i].pam_code) - return pam_to_nt_status_map[i].ntstatus; - } - return NT_STATUS_UNSUCCESSFUL; -} - -/***************************************************************************** -convert an NT status32 code to a PAM error - *****************************************************************************/ -int nt_status_to_pam(NTSTATUS nt_status) -{ - int i; - if NT_STATUS_IS_OK(nt_status) return PAM_SUCCESS; - - for (i=0; NT_STATUS_V(nt_status_to_pam_map[i].ntstatus); i++) { - if (NT_STATUS_EQUAL(nt_status,nt_status_to_pam_map[i].ntstatus)) - return nt_status_to_pam_map[i].pam_code; - } - return PAM_SYSTEM_ERR; -} - -#else - -/***************************************************************************** -convert a PAM error to a NT status32 code - *****************************************************************************/ -NTSTATUS pam_to_nt_status(int pam_error) -{ - if (pam_error == 0) return NT_STATUS_OK; - return NT_STATUS_UNSUCCESSFUL; -} - -/***************************************************************************** -convert an NT status32 code to a PAM error - *****************************************************************************/ -int nt_status_to_pam(NTSTATUS nt_status) -{ - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OK)) return 0; - return 4; /* PAM_SYSTEM_ERR */ -} - -#endif - diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 338b9547a5..156d09aaf5 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -22,94 +22,6 @@ #include "system/shmem.h" #include "system/filesys.h" -/************************************************************************* - gets a line out of a file. - line is of format "xxxx:xxxxxx:xxxxx:". - lines with "#" at the front are ignored. -*************************************************************************/ -int getfileline(void *vp, char *linebuf, int linebuf_size) -{ - /* Static buffers we will return. */ - FILE *fp = (FILE *)vp; - uint8_t c; - uint8_t *p; - size_t linebuf_len; - - if (fp == NULL) - { - DEBUG(0,("getfileline: Bad file pointer.\n")); - return -1; - } - - /* - * Scan the file, a line at a time. - */ - while (!feof(fp)) - { - linebuf[0] = '\0'; - - fgets(linebuf, linebuf_size, fp); - if (ferror(fp)) - { - return -1; - } - - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - - linebuf_len = strlen(linebuf); - if (linebuf_len == 0) - { - linebuf[0] = '\0'; - return 0; - } - - if (linebuf[linebuf_len - 1] != '\n') - { - c = '\0'; - while (!ferror(fp) && !feof(fp)) - { - c = fgetc(fp); - if (c == '\n') - { - break; - } - } - } - else - { - linebuf[linebuf_len - 1] = '\0'; - } - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("getfileline: got line |%s|\n", linebuf)); -#endif - if ((linebuf[0] == 0) && feof(fp)) - { - DEBUG(4, ("getfileline: end of file reached\n")); - return 0; - } - - if (linebuf[0] == '#' || linebuf[0] == '\0') - { - DEBUG(6, ("getfileline: skipping comment or blank line\n")); - continue; - } - - p = (uint8_t *) strchr_m(linebuf, ':'); - if (p == NULL) - { - DEBUG(0, ("getfileline: malformed line entry (no :)\n")); - continue; - } - return linebuf_len; - } - return -1; -} - - /**************************************************************************** read a line from a file with possible \ continuation chars. Blanks at the start or end of a line are stripped. @@ -350,7 +262,7 @@ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) /**************************************************************************** -take a lislist of lines and modify them to produce a list where \ continues +take a list of lines and modify them to produce a list where \ continues a line ****************************************************************************/ void file_lines_slashcont(char **lines) -- cgit From 8bfcb31b0e01d42532db5837b1f0a070eb076bb1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Sep 2005 23:06:57 +0000 Subject: r10250: the comparison is caseless so we must caseless subtract otherwise we get the wrong result when comparing upper case chars with lower case chars (This used to be commit f6ea6e9382f954be819ec82e28598cdf9cf88661) --- source4/lib/ldb/common/attrib_handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 412146360c..61ca566570 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -138,7 +138,7 @@ static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, } while (*s1 == ' ') s1++; while (*s2 == ' ') s2++; - return (int)(*s1) - (int)(*s2); + return (int)(toupper(*s1)) - (int)(toupper(*s2)); } /* -- cgit From d8da5e4fb7534d2931a01bfc4b6f59bdca206c65 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Sep 2005 23:10:07 +0000 Subject: r10251: some more work on ldb_sqlite3 I must say that writing a new module is a very good way to find lot of subtle bugs laying in the code We need more tests! commit oLschema2ldif.c to keep it safe from data losses (rm -fr :-) update test generic to reflect the fix made on comparsion functions (This used to be commit 4357a2db5eadb15519ed93b957b2bad25ebf2a7d) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 467 ++++++++++++++---------------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 5 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 6 + source4/lib/ldb/tests/test-generic.sh | 25 +- source4/lib/ldb/tools/oLschema2ldif.c | 26 ++ 5 files changed, 282 insertions(+), 247 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 4a4a83090a..1a855e0850 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -237,6 +237,7 @@ static char *parsetree_to_sql(struct ldb_module *module, char *wild_card_string; char *child, *tmp; char *ret = NULL; + char *attr; int i; @@ -251,7 +252,7 @@ static char *parsetree_to_sql(struct ldb_module *module, child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); if (child == NULL) return NULL; - tmp = talloc_asprintf_append(tmp, "INTERSECT %s ", child); + tmp = talloc_asprintf_append(tmp, " INTERSECT %s ", child); if (tmp == NULL) return NULL; } @@ -269,11 +270,11 @@ static char *parsetree_to_sql(struct ldb_module *module, child = parsetree_to_sql(module, mem_ctx, t->u.list.elements[i]); if (child == NULL) return NULL; - tmp = talloc_asprintf_append(tmp, "UNION %s ", child); + tmp = talloc_asprintf_append(tmp, " UNION %s ", child); if (tmp == NULL) return NULL; } - return talloc_asprintf(mem_ctx, "SELECT * FROM ( %s )", tmp); + return talloc_asprintf(mem_ctx, "SELECT * FROM ( %s ) ", tmp); case LDB_OP_NOT: @@ -282,14 +283,16 @@ static char *parsetree_to_sql(struct ldb_module *module, return talloc_asprintf(mem_ctx, "SELECT eid FROM ldb_entry " - "WHERE eid NOT IN ( %s )", child); + "WHERE eid NOT IN ( %s ) ", child); case LDB_OP_EQUALITY: /* * For simple searches, we want to retrieve the list of EIDs that * match the criteria. */ - h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + attr = ldb_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + h = ldb_attrib_handler(module->ldb, attr); /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); @@ -327,9 +330,9 @@ static char *parsetree_to_sql(struct ldb_module *module, /* A normal query. */ return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q') " + "WHERE norm_attr_name = '%q' " "AND norm_attr_value = '%q'", - t->u.equality.attr, + attr, value.data); } @@ -342,7 +345,7 @@ static char *parsetree_to_sql(struct ldb_module *module, for (i = 0; t->u.substring.chunks[i]; i++) { wild_card_string = talloc_asprintf_append(wild_card_string, "%s*", - t->u.substring.chunks[i]); + t->u.substring.chunks[i]->data); if (wild_card_string == NULL) return NULL; } @@ -351,7 +354,9 @@ static char *parsetree_to_sql(struct ldb_module *module, wild_card_string[strlen(wild_card_string) - 1] = '\0'; } - h = ldb_attrib_handler(module->ldb, t->u.substring.attr); + attr = ldb_casefold(mem_ctx, t->u.substring.attr); + if (attr == NULL) return NULL; + h = ldb_attrib_handler(module->ldb, attr); subval.data = wild_card_string; subval.length = strlen(wild_card_string) + 1; @@ -364,13 +369,15 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q') " + "WHERE norm_attr_name = '%q' " "AND norm_attr_value GLOB '%q'", - t->u.substring.attr, + attr, value.data); case LDB_OP_GREATER: - h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + attr = ldb_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + h = ldb_attrib_handler(module->ldb, attr); /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); @@ -380,13 +387,16 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q') " - "AND norm_attr_value >= '%q'", - t->u.equality.attr, - value.data); + "WHERE norm_attr_name = '%q' " + "AND norm_attr_value LIKE '>=%q' ESCAPE '%q' ", + attr, + value.data, + attr); case LDB_OP_LESS: - h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + attr = ldb_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + h = ldb_attrib_handler(module->ldb, attr); /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); @@ -396,23 +406,29 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q') " - "AND norm_attr_value <= '%q'", - t->u.equality.attr, - value.data); + "WHERE norm_attr_name = '%q' " + "AND norm_attr_value LIKE '<=%q' ESCAPE '%q' ", + attr, + value.data, + attr); case LDB_OP_PRESENT: - if (strcasecmp(t->u.present.attr, "dn")) { + if (strcasecmp(t->u.present.attr, "dn") == 0) { return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry"); } + attr = ldb_casefold(mem_ctx, t->u.present.attr); + if (attr == NULL) return NULL; + return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q')", - t->u.present.attr); + "WHERE norm_attr_name = '%q' ", + attr); case LDB_OP_APPROX: - h = ldb_attrib_handler(module->ldb, t->u.equality.attr); + attr = ldb_casefold(mem_ctx, t->u.equality.attr); + if (attr == NULL) return NULL; + h = ldb_attrib_handler(module->ldb, attr); /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); @@ -422,10 +438,11 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " - "WHERE norm_attr_name = upper('%q') " - "AND norm_attr_value LIKE '%q'", - t->u.equality.attr, - value.data); + "WHERE norm_attr_name = '%q' " + "AND norm_attr_value LIKE '~%q' ESCAPE '%q' ", + attr, + value.data, + attr); case LDB_OP_EXTENDED: #warning "work out how to handle bitops" @@ -440,102 +457,6 @@ static char *parsetree_to_sql(struct ldb_module *module, return NULL; } - -/* - * query_norows() - * - * This function is used for queries that are not expected to return any rows, - * e.g. BEGIN, COMMIT, ROLLBACK, CREATE TABLE, INSERT, UPDATE, DELETE, etc. - * There are no provisions here for returning data from rows in a table, so do - * not pass SELECT queries to this function. - */ -static int -query_norows(const struct lsqlite3_private *lsqlite3, - const char *pSql, - ...) -{ - int ret; - int bLoop; - char * p; - sqlite3_stmt * pStmt; - va_list args; - - /* Begin access to variable argument list */ - va_start(args, pSql); - - /* Format the query */ - if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { - return -1; - } - - /* - * Prepare and execute the SQL statement. Loop allows retrying on - * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, - * requiring retrying the operation. - */ - for (bLoop = TRUE; bLoop; ) { - - /* Compile the SQL statement into sqlite virtual machine */ - if ((ret = sqlite3_prepare(lsqlite3->sqlite, - p, - -1, - &pStmt, - NULL)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - ret = -1; - break; - } - - /* No rows expected, so just step through machine code once */ - if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - (void) sqlite3_finalize(pStmt); - continue; - } else if (ret != SQLITE_DONE) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* Free the virtual machine */ - if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - if (stmtGetEID != NULL) { - sqlite3_finalize(stmtGetEID); - stmtGetEID = NULL; - } - continue; - } else if (ret != SQLITE_OK) { - (void) sqlite3_finalize(pStmt); - ret = -1; - break; - } - - /* - * Normal condition is only one time through loop. Loop is - * rerun in error conditions, via "continue", above. - */ - ret = 0; - bLoop = FALSE; - } - - /* All done with variable argument list */ - va_end(args); - - /* Free the memory we allocated for our query string */ - sqlite3_free(p); - - return ret; -} - - /* obtain a named lock */ static int lsqlite3_lock(struct ldb_module * module, @@ -683,6 +604,78 @@ query_int(const struct lsqlite3_private * lsqlite3, return ret; } +/* + * This is a bad hack to support ldap style comparisons whithin sqlite. + * This function substitues the X LIKE Y ESCAPE Z expression + * X is an expression + value to compare against (eg: ">=test") + * Y is the attribute in the row currently under test + * Z is the attribute name the value of which we want to test + */ + +static void lsqlite3_compare(sqlite3_context *ctx, int argc, + sqlite3_value **argv) +{ + struct ldb_context *ldb = (struct ldb_context *)sqlite3_user_data(ctx); + const unsigned char *X = sqlite3_value_text(argv[0]); + const unsigned char *Y = sqlite3_value_text(argv[1]); + const unsigned char *Z = sqlite3_value_text(argv[2]); + const unsigned char *p; + const struct ldb_attrib_handler *h; + struct ldb_val valX; + struct ldb_val valY; + int ret; + + switch (X[0]) { + /* greater */ + case '>': /* >= */ + p = &(X[2]); + h = ldb_attrib_handler(ldb, Z); + valX.data = p; + valX.length = strlen(p); + valY.data = Y; + valY.length = strlen(Y); + ret = h->comparison_fn(ldb, ldb, &valY, &valX); + if (ret >= 0) + sqlite3_result_int(ctx, 1); + else + sqlite3_result_int(ctx, 0); + return; + + /* lesser */ + case '<': /* <= */ + p = &(X[2]); + h = ldb_attrib_handler(ldb, Z); + valX.data = p; + valX.length = strlen(p); + valY.data = Y; + valY.length = strlen(Y); + ret = h->comparison_fn(ldb, ldb, &valY, &valX); + if (ret <= 0) + sqlite3_result_int(ctx, 1); + else + sqlite3_result_int(ctx, 0); + return; + + /* approx */ + case '~': + /* TODO */ + sqlite3_result_int(ctx, 0); + return; + + /* bitops */ + case ':': + /* TODO */ + sqlite3_result_int(ctx, 0); + return; + + default: + break; + } + + sqlite3_result_error(ctx, "Value must start with a special operation char (<>~:)!", -1); + return; +} + /* rename a record */ static int lsqlite3_safe_rollback(sqlite3 *sqlite) @@ -719,6 +712,7 @@ struct lsqlite3_msgs { int count; struct ldb_message **msgs; long long current_eid; + const char * const * attrs; TALLOC_CTX *mem_ctx; }; @@ -731,6 +725,7 @@ static int lsqlite3_search_callback(void *result, int col_num, char **cols, char struct lsqlite3_msgs *msgs = (struct lsqlite3_msgs *)result; struct ldb_message *msg; long long eid; + int i; /* eid, dn, attr_name, attr_value */ if (col_num != 4) return SQLITE_ABORT; @@ -763,6 +758,17 @@ static int lsqlite3_search_callback(void *result, int col_num, char **cols, char if (msg->dn == NULL) return SQLITE_ABORT; } + if (msgs->attrs) { + int found = 0; + for (i = 0; msgs->attrs[i]; i++) { + if (strcasecmp(cols[2], msgs->attrs[i]) == 0) { + found = 1; + break; + } + } + if (!found) return 0; + } + msg->elements = talloc_realloc(msg, msg->elements, struct ldb_message_element, @@ -862,7 +868,6 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d struct lsqlite3_private *lsqlite3 = module->private_data; struct lsqlite3_msgs msgs; char *norm_basedn; - char *attr_list; char *sqlfilter; char *errmsg; char *query; @@ -886,39 +891,6 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d /* Convert filter into a series of SQL conditions (constraints) */ sqlfilter = parsetree_to_sql(module, local_ctx, tree); - /* Initially, we don't know what the requested attributes are */ - if (attrs != NULL) { - attr_list = talloc_strdup(local_ctx, "AND norm_attr_name IN ("); - if (attr_list == NULL) goto failed; - - for (i = 0; attrs[i]; i++) { - char *norm_attr_name; - - /* If any attribute in the list is "*" then... */ - if (strcmp(attrs[i], "*") == 0) { - /* we want all attribute types */ - attr_list = talloc_strdup(local_ctx, ""); - if (attr_list == NULL) goto failed; - break; - } - - norm_attr_name = ldb_casefold(local_ctx, attrs[i]); - if (norm_attr_name == NULL) goto failed; - - attr_list = talloc_asprintf_append(attr_list, "'%q', ", - norm_attr_name); - if (attr_list == NULL) goto failed; - - } - - /* substitute the last ',' with ')' */ - attr_list[strlen(attr_list)-2] = ')'; - - } else { - attr_list = talloc_strdup(local_ctx, ""); - if (attr_list == NULL) goto failed; - } - switch(scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: @@ -942,13 +914,10 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d " (%s)\n" " )\n" - " %s\n" - " ORDER BY entry.eid ASC;", norm_basedn, norm_basedn, - sqlfilter, - attr_list); + sqlfilter); } else { query = lsqlite3_tprintf(local_ctx, "SELECT entry.eid,\n" @@ -967,11 +936,8 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d " (%s)\n" " )\n" - " %s\n" - " ORDER BY entry.eid ASC;", - sqlfilter, - attr_list); + sqlfilter); } break; @@ -995,12 +961,9 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d " (%s)\n" " )\n" - " %s\n" - " ORDER BY entry.eid ASC;", norm_basedn, - sqlfilter, - attr_list); + sqlfilter); break; case LDB_SCOPE_ONELEVEL: @@ -1022,13 +985,10 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d " AND ldb_entry.eid IN\n(%s)\n" " )\n" - " %s\n" - " ORDER BY entry.eid ASC;", norm_basedn, norm_basedn, - sqlfilter, - attr_list); + sqlfilter); break; } @@ -1037,12 +997,15 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d goto failed; } - /* printf ("%s\n", query); */ + /* * / + printf ("%s\n", query); + / * */ msgs.msgs = NULL; msgs.count = 0; msgs.current_eid = 0; msgs.mem_ctx = local_ctx; + msgs.attrs = attrs; ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, &msgs, &errmsg); if (ret != SQLITE_OK) { @@ -1137,12 +1100,13 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg goto failed; } +/* c = ldb_dn_explode(local_ctx, "@INDEXLIST"); if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { #warning "should we handle indexes somehow ?" goto failed; } - +*/ /* Others are implicitly ignored */ return 0; } @@ -1554,13 +1518,23 @@ lsqlite3_errstring(struct ldb_module *module) * Static functions */ -static int initialize(struct lsqlite3_private *lsqlite3, const char *url) +static int initialize(struct lsqlite3_private *lsqlite3, + struct ldb_context *ldb, const char *url) { - int ret; + TALLOC_CTX *local_ctx; long long queryInt; - const char *pTail; - sqlite3_stmt *stmt; - const char *schema = + int rollback = 0; + char *errmsg; + char *schema; + int ret; + + /* create a local ctx */ + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_rename local context"); + if (local_ctx == NULL) { + return -1; + } + + schema = lsqlite3_tprintf(local_ctx, "CREATE TABLE ldb_info AS " @@ -1646,9 +1620,7 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) "INSERT INTO ldb_object_classes " " (class_name, tree_key) " " VALUES " - " ('TOP', '0001');" - - ; + " ('TOP', '0001');"); /* Skip protocol indicator of url */ if (strncmp(url, "sqlite://", 9) != 0) { @@ -1664,15 +1636,26 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) } /* In case this is a new database, enable auto_vacuum */ - if (query_norows(lsqlite3, "PRAGMA auto_vacuum=1;") != 0) { - return -1; - } + ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA auto_vacuum = 1;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } - /* DANGEROUS - if (query_norows(lsqlite3, "PRAGMA synchronous = OFF;") != 0) { - return -1; - } - */ + /* DANGEROUS */ + ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA synchronous = OFF;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + + /* */ /* Establish a busy timeout of 30 seconds */ if ((ret = sqlite3_busy_timeout(lsqlite3->sqlite, @@ -1708,43 +1691,52 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) return ret; } - /* Begin a transaction */ - if ((ret = query_norows(lsqlite3, "BEGIN EXCLUSIVE;")) != 0) { - return ret; + /* Create a function, callable from sql, to perform various comparisons */ + if ((ret = + sqlite3_create_function(lsqlite3->sqlite, /* handle */ + "like", /* function name */ + 3, /* number of args */ + SQLITE_ANY, /* preferred text type */ + ldb , /* user data */ + lsqlite3_compare, /* called func */ + NULL, /* step func */ + NULL /* final func */ + )) != SQLITE_OK) { + return ret; } - + + /* Begin a transaction */ + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN EXCLUSIVE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3: initialization error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + rollback = 1; + /* Determine if this is a new database. No tables means it is. */ if (query_int(lsqlite3, &queryInt, "SELECT COUNT(*)\n" " FROM sqlite_master\n" " WHERE type = 'table';") != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return -1; + goto failed; } if (queryInt == 0) { /* * Create the database schema */ - for (pTail = discard_const_p(char, schema); - pTail != NULL && *pTail != '\0'; - ) { - - if ((ret = sqlite3_prepare( - lsqlite3->sqlite, - pTail, - -1, - &stmt, - &pTail)) != SQLITE_OK || - (ret = sqlite3_step(stmt)) != SQLITE_DONE || - (ret = sqlite3_finalize(stmt)) != SQLITE_OK) { - - query_norows(lsqlite3, "ROLLBACK;"); - (void) sqlite3_close(lsqlite3->sqlite); - return ret; - } - } + ret = sqlite3_exec(lsqlite3->sqlite, schema, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } } else { /* * Ensure that the database we opened is one of ours @@ -1770,34 +1762,26 @@ static int initialize(struct lsqlite3_private *lsqlite3, const char *url) queryInt != 1) { /* It's not one that we created. See ya! */ - query_norows(lsqlite3, "ROLLBACK;"); - (void) sqlite3_close(lsqlite3->sqlite); - return SQLITE_MISUSE; + goto failed; } } - /* - * Create a temporary table to hold attributes requested in the result - * set of a search. - */ - query_norows(lsqlite3, "DROP TABLE " RESULT_ATTR_TABLE ";\n"); - if ((ret = - query_norows(lsqlite3, - "CREATE " TEMPTAB " TABLE " RESULT_ATTR_TABLE "\n" - " (\n" - " attr_name TEXT PRIMARY KEY\n" - " );")) != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return ret; - } - /* Commit the transaction */ - if ((ret = query_norows(lsqlite3, "COMMIT;")) != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - return ret; - } - + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3: iniialization error: %s\n", errmsg); + free(errmsg); + } + goto failed; + } + return SQLITE_OK; + +failed: + if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); + sqlite3_close(lsqlite3->sqlite); + return -1; } static int @@ -1848,9 +1832,8 @@ int lsqlite3_connect(struct ldb_context *ldb, lsqlite3->sqlite = NULL; lsqlite3->options = NULL; - lsqlite3->lock_count = 0; - ret = initialize(lsqlite3, url); + ret = initialize(lsqlite3, ldb, url); if (ret != SQLITE_OK) { goto failed; } diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 46ee1e93ba..46c949a564 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -1,7 +1,6 @@ #include struct lsqlite3_private { - char ** options; - sqlite3 * sqlite; - int lock_count; + char **options; + sqlite3 *sqlite; }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 160affd4e7..ca0ae06354 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -465,6 +465,9 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, struct ltdb_private *ltdb = module->private_data; int ret; + if ((base == NULL || base->comp_num == 0) && + (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; + /* it is important that we handle dn queries this way, and not via a full db search, otherwise ldb is horribly slow */ if (tree->operation == LDB_OP_EQUALITY && @@ -516,6 +519,9 @@ int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, struct ldb_parse_tree *tree; int ret; + if ((base == NULL || base->comp_num == 0) && + (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; + /* check if we are looking for a simple dn */ if (scope == LDB_SCOPE_BASE && (expression == NULL || expression[0] == '\0')) { ret = ltdb_search_dn(module, base, attrs, res); diff --git a/source4/lib/ldb/tests/test-generic.sh b/source4/lib/ldb/tests/test-generic.sh index 0e2cb187a1..9060fe0f54 100755 --- a/source4/lib/ldb/tests/test-generic.sh +++ b/source4/lib/ldb/tests/test-generic.sh @@ -65,13 +65,13 @@ if [ $count != 3 ]; then fi echo "Testing compare" -count=`$VALGRIND ldbsearch '(cn>=U)' cn | grep '^dn' | wc -l` +count=`$VALGRIND ldbsearch '(cn>=t)' cn | grep '^dn' | wc -l` if [ $count != 2 ]; then echo returned $count records - expected 2 exit 1 fi -count=`$VALGRIND ldbsearch '(cn<=U)' cn | grep '^dn' | wc -l` +count=`$VALGRIND ldbsearch '(cn<=t)' cn | grep '^dn' | wc -l` if [ $count != 13 ]; then echo returned $count records - expected 13 exit 1 @@ -79,3 +79,24 @@ fi echo "Testing binary file attribute value" $VALGRIND ldbmodify $LDBDIR/tests/photo.ldif || exit 1 + +checkcount() { + count=$1 + scope=$2 + basedn=$3 + expression="$4" + n=`bin/ldbsearch -s "$scope" -b "$basedn" "$expression" | grep '^dn' | wc -l` + if [ $n != $count ]; then + echo "Got $n but expected $count for $expression" + bin/ldbsearch "$expression" + exit 1 + fi + echo "OK: $count $expression" +} + +checkcount 0 'base' '' '(uid=uham)' +checkcount 0 'one' '' '(uid=uham)' + +checkcount 1 'base' 'cn=Hampster Ursula,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' '(uid=uham)' +checkcount 1 'one' 'ou=Alumni Association,ou=People,o=University of Michigan,c=TEST' '(uid=uham)' + diff --git a/source4/lib/ldb/tools/oLschema2ldif.c b/source4/lib/ldb/tools/oLschema2ldif.c index 0a88ba6b71..4e1607f314 100644 --- a/source4/lib/ldb/tools/oLschema2ldif.c +++ b/source4/lib/ldb/tools/oLschema2ldif.c @@ -58,6 +58,32 @@ #define SCHEMA_SYNTAX 12 #define SCHEMA_DESC 13 +struct syntax_map { + const char *Standard_OID; + const char *AD_OID; + const char *comment; +} syntax_map[] = { + { "1.3.6.1.4.1.1466.115.121.1.12", "2.5.5.1", "Object(DS-DN) == a DN" }, + { "1.3.6.1.4.1.1466.115.121.1.38", "2.5.5.2", "OID String" }, + { "1.2.840.113556.1.4.905", "2.5.5.4", "Case Insensitive String" }, + { "1.3.6.1.4.1.1466.115.121.1.44", "2.5.5.5", "Printable String" }, + { "1.3.6.1.4.1.1466.115.121.1.36", "2.5.5.6", "Numeric String" }, + { "1.2.840.113556.1.4.903", "2.5.5.7", "OctetString: Binary+DN" }, + { "1.3.6.1.4.1.1466.115.121.1.7", "2.5.5.8", "Boolean" }, + { "1.3.6.1.4.1.1466.115.121.1.27", "2.5.5.9", "Integer" }, + { "1.3.6.1.4.1.1466.115.121.1.40", "2.5.5.10", "Octet String" }, + { "1.3.6.1.4.1.1466.115.121.1.24", "2.5.5.11", "Generalized Time" }, + { "1.3.6.1.4.1.1466.115.121.1.53", "2.5.5.11", "UTC Time" }, + { "1.3.6.1.4.1.1466.115.121.1.15", "2.5.5.12", "Directory String" }, + { "1.3.6.1.4.1.1466.115.121.1.43", "2.5.5.13", "Presentation Address" }, + { "Not Found Yet", "2.5.5.14", "OctetString: String+DN" }, + { "1.2.840.113556.1.4.907", "2.5.5.15", "NT Security Descriptor" }, + { "1.2.840.113556.1.4.906", "2.5.5.16", "Interval" }, + { "1.3.6.1.4.1.1466.115.121.1.40", "2.5.5.17", "Octet String - Security Identifier (SID)" }, + { "1.3.6.1.4.1.1466.115.121.1.26", "2.5.5.5", "IA5 String" }, + { NULL, NULL } +}; + struct schema_conv { int count; -- cgit From 0868b7c77d42efd5f361f605bfc0d8d46841db95 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 Sep 2005 03:52:42 +0000 Subject: r10253: a fairly large tdb cleanup and re-organise. Nearly all of this change just involves splitting up the core tdb.c code into separate files on logical boundaries, but there are some minor functional changes as well: - move the 'struct tdb_context' into tdb_private.h, hiding it from users. This was done to allow the structure to change without breaking code that uses tdb. - added accessor functions tdb_fd(), tdb_name(), and tdb_log_fn() to access the elements of struct tdb_context that were used by external code but are no longer visible - simplied tdb_append() to use tdb_fetch()/tdb_store(), which is just as good due to the way tdb locks work - changed some of the types (such as tdb_off to tdb_off_t) to make syntax highlighting work better - removed the old optional spinlock code. It was a bad idea. - fixed a bug in tdb_reopen_all() that caused tdbtorture to sometimes fail or report nasty looking errors. This is the only real bug fixed in this commit. Jeremy/Jerry, you might like to pickup this change for Samba3, as that could definately affect smbd in Samba3. The aim of all of these changes is to make the tdb transactions/journaling code I am working on easier to write. I started to write it on top of the existing tdb.c code and it got very messy. Splitting up the code makes it much easier to follow. There are more cleanups we could do in tdb, such as using uint32_t instead of u32 (suggested by metze). I'll leave those for another day. (This used to be commit 4673cdd0d261614e707b72a7a348bb0e7dbb2482) --- source4/lib/db_wrap.c | 3 +- source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c | 2 +- source4/lib/tdb/Makefile.in | 3 +- source4/lib/tdb/autogen.sh | 1 + source4/lib/tdb/common/dump.c | 133 +++ source4/lib/tdb/common/error.c | 56 + source4/lib/tdb/common/freelist.c | 323 ++++++ source4/lib/tdb/common/io.c | 374 ++++++ source4/lib/tdb/common/lock.c | 235 ++++ source4/lib/tdb/common/open.c | 409 +++++++ source4/lib/tdb/common/spinlock.c | 482 -------- source4/lib/tdb/common/tdb.c | 1947 ++------------------------------ source4/lib/tdb/common/tdb_private.h | 208 ++++ source4/lib/tdb/common/tdbutil.c | 154 +-- source4/lib/tdb/common/traverse.c | 274 +++++ source4/lib/tdb/config.m4 | 1 + source4/lib/tdb/config.mk | 6 +- source4/lib/tdb/configure.in | 1 + source4/lib/tdb/include/spinlock.h | 59 - source4/lib/tdb/include/tdb.h | 109 +- source4/lib/tdb/include/tdbconfig.h.in | 19 + source4/lib/tdb/include/tdbutil.h | 27 +- source4/lib/tdb/tools/tdbdump.c | 4 +- source4/lib/tdb/tools/tdbtest.c | 8 +- source4/lib/tdb/tools/tdbtool.c | 32 +- source4/lib/tdb/tools/tdbtorture.c | 16 +- 26 files changed, 2270 insertions(+), 2616 deletions(-) create mode 100644 source4/lib/tdb/common/dump.c create mode 100644 source4/lib/tdb/common/error.c create mode 100644 source4/lib/tdb/common/freelist.c create mode 100644 source4/lib/tdb/common/io.c create mode 100644 source4/lib/tdb/common/lock.c create mode 100644 source4/lib/tdb/common/open.c delete mode 100644 source4/lib/tdb/common/spinlock.c create mode 100644 source4/lib/tdb/common/tdb_private.h create mode 100644 source4/lib/tdb/common/traverse.c delete mode 100644 source4/lib/tdb/include/spinlock.h create mode 100644 source4/lib/tdb/include/tdbconfig.h.in (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index 77af27ff36..ed235761c9 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -122,7 +122,8 @@ static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, va_end(ap); if (ptr != NULL) { - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + const char *name = tdb_name(tdb); + DEBUG(level, ("tdb(%s): %s", name ? name : "unnamed", ptr)); free(ptr); } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c b/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c index f58ec7f7ff..3a18f5df88 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c @@ -92,7 +92,7 @@ struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, return NULL; } - if (fstat(w->tdb->fd, &st) != 0) { + if (fstat(tdb_fd(w->tdb), &st) != 0) { tdb_close(w->tdb); talloc_free(w); return NULL; diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index ea96dddffc..2fc77242b2 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -11,7 +11,8 @@ includedir = @includedir@ libdir = @libdir@ PROGS = bin/tdbtool bin/tdbtorture -TDB_OBJ = common/tdb.o common/spinlock.o +TDB_OBJ = common/tdb.o common/dump.o common/io.o common/lock.o \ + common/open.o common/traverse.o common/freelist.o common/error.o all: $(PROGS) diff --git a/source4/lib/tdb/autogen.sh b/source4/lib/tdb/autogen.sh index 94148edf69..89053ad9f8 100755 --- a/source4/lib/tdb/autogen.sh +++ b/source4/lib/tdb/autogen.sh @@ -1,5 +1,6 @@ #!/bin/sh +autoheader || exit 1 autoconf || exit 1 echo "Now run ./configure and then make." diff --git a/source4/lib/tdb/common/dump.c b/source4/lib/tdb/common/dump.c new file mode 100644 index 0000000000..0e203cc0d8 --- /dev/null +++ b/source4/lib/tdb/common/dump.c @@ -0,0 +1,133 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset) +{ + struct list_struct rec; + tdb_off_t tailer_ofs, tailer; + + if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(struct tdb_context *tdb, int i) +{ + tdb_off_t rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(struct tdb_context *tdb) +{ + int i; + for (i=0;iheader.hash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(struct tdb_context *tdb) +{ + int ret; + long total_free = 0; + tdb_off_t offset, rec_ptr; + struct list_struct rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + diff --git a/source4/lib/tdb/common/error.c b/source4/lib/tdb/common/error.c new file mode 100644 index 0000000000..5b7696877c --- /dev/null +++ b/source4/lib/tdb/common/error.c @@ -0,0 +1,56 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +enum TDB_ERROR tdb_error(struct tdb_context *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_NOEXIST, "Record does not exist"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(struct tdb_context *tdb) +{ + u32 i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + diff --git a/source4/lib/tdb/common/freelist.c b/source4/lib/tdb/common/freelist.c new file mode 100644 index 0000000000..018b7bc298 --- /dev/null +++ b/source4/lib/tdb/common/freelist.c @@ -0,0 +1,323 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* read a freelist record and check for simple errors */ +static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) +{ + if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + + + +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) +{ + tdb_off_t last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return tdb_ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); +} + + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, + const struct list_struct *rec) +{ + tdb_off_t totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), + &totalsize); +} + +/* Add an element into the freelist. Merge adjacent records if + neccessary. */ +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + tdb_off_t right, left; + + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); + goto fail; + } + + /* Look right first (I'm an Australian, dammit) */ + right = offset + sizeof(*rec) + rec->rec_len; + if (right + sizeof(*rec) <= tdb->map_size) { + struct list_struct r; + + if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + } + } + +left: + /* Look left */ + left = offset - sizeof(tdb_off_t); + if (left > TDB_DATA_START(tdb->header.hash_size)) { + struct list_struct l; + tdb_off_t leftsize; + + /* Read in tailer and jump back to header */ + if (tdb_ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + left = offset - leftsize; + + /* Now read in record */ + if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, left, l.next) == -1) { + TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); + goto update; + } else { + offset = left; + rec->rec_len += leftsize; + } + } + } + +update: + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + tdb_rec_write(tdb, offset, rec) == -1 || + tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + */ +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, + struct list_struct *rec, tdb_off_t last_ptr) +{ + struct list_struct newrec; + tdb_off_t newrec_ptr; + + memset(&newrec, '\0', sizeof(newrec)); + + /* found it - now possibly split it up */ + if (rec->rec_len > length + MIN_REC_SIZE) { + /* Length of left piece */ + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + /* Right piece to go on free list */ + newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); + newrec_ptr = rec_ptr + sizeof(*rec) + length; + + /* And left record is shortened */ + rec->rec_len = length; + } else { + newrec_ptr = 0; + } + + /* Remove allocated record from the free list */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* Update header: do this before we drop alloc + lock, otherwise tdb_free() might try to + merge with us, thinking we're free. + (Thanks Jeremy Allison). */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Did we create new block? */ + if (newrec_ptr) { + /* Update allocated record tailer (we + shortened it). */ + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* Free new record */ + if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { + return 0; + } + } + + /* all done - return the new record offset */ + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected list_struct within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec) +{ + tdb_off_t rec_ptr, last_ptr, newrec_ptr; + struct { + tdb_off_t rec_ptr, last_ptr; + tdb_len_t rec_len; + } bestfit; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off_t); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + bestfit.rec_ptr = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + if (rec_free_read(tdb, rec_ptr, rec) == -1) { + goto fail; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + /* consider a fit to be good enough if + we aren't wasting more than half + the space */ + if (bestfit.rec_len < 2*length) { + break; + } + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + } + + if (bestfit.rec_ptr != 0) { + if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c new file mode 100644 index 0000000000..dbcc83119c --- /dev/null +++ b/source4/lib/tdb/common/io.c @@ -0,0 +1,374 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "tdb_private.h" + +#ifndef HAVE_PREAD + static ssize_t pread(int fd, void *buf, size_t count, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) != offset) { + errno = EIO; + return -1; + } + return read(fd, buf, count); +} +#endif + +#ifndef HAVE_PWRITE + static ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + if (lseek(fd, offset, SEEK_SET) != offset) { + errno = EIO; + return -1; + } + return write(fd, buf, count); +} +#endif + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (fstat(tdb->fd, &st) == -1) { + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + if (st.st_size < (size_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) + return TDB_ERRCODE(TDB_ERR_IO, -1); + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +int tdb_write(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len) +{ + if (tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) { + memcpy(off + (char *)tdb->map_ptr, buf, len); + } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", + off, len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + return 0; +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +void *tdb_convert(void *buf, u32 size) +{ + u32 i, *p = buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} + + +/* read a lump of data at a specified offset, maybe convert */ +int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv) +{ + ssize_t ret; + + if (tdb_oob(tdb, off + len, 0) != 0) { + return -1; + } + + if (tdb->map_ptr) { + memcpy(buf, off + (char *)tdb->map_ptr, len); + } else { + ssize_t ret = pread(tdb->fd, buf, len, off); + if (ret != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d ret=%d (%s) map_size=%d\n", + off, len, ret, strerror(errno), tdb->map_size)); + return TDB_ERRCODE(TDB_ERR_IO, -1); + } + } + if (cv) + tdb_convert(buf, len); + return 0; +} + + + +/* + do an unlocked scan of the hash table heads to find the next non-zero head. The value + will then be confirmed with the lock held +*/ +void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + if (tdb->map_ptr) { + for (;h < tdb->header.hash_size;h++) { + if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + u32 off; + for (;h < tdb->header.hash_size;h++) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { + break; + } + } + } + (*chain) = h; +} + + +int tdb_munmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +void tdb_mmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED|MAP_FILE, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) +{ + char buf[1024]; + if (ftruncate(tdb->fd, size+addition) == -1) { + char b = 0; + if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { + TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } + } + + /* now fill the file with something. This ensures that the file isn't sparse, which would be + very bad if we ran out of disk. This must be done with write, not via mmap */ + memset(buf, 0x42, sizeof(buf)); + while (addition) { + int n = addition>sizeof(buf)?sizeof(buf):addition; + int ret = pwrite(tdb->fd, buf, n, size); + if (ret != n) { + TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", + n, strerror(errno))); + return -1; + } + addition -= n; + size += n; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +int tdb_expand(struct tdb_context *tdb, tdb_off_t size) +{ + struct list_struct rec; + tdb_off_t offset; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 10 more records, and round + the database up to a multiple of TDB_PAGE_SIZE */ + size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (tdb_expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); + if (!new_map_ptr) { + tdb->map_size -= size; + goto fail; + } + tdb->map_ptr = new_map_ptr; + } else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +/* read/write a tdb_off_t */ +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} + +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + tdb_off_t off = *d; + return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + + +/* read a lump of data, allocating the space for it */ +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) +{ + unsigned char *buf; + + if (!(buf = malloc(len))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return TDB_ERRCODE(TDB_ERR_OOM, buf); + } + if (tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* read/write a record */ +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, 0,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); + } + return tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} + +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) +{ + struct list_struct r = *rec; + return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c new file mode 100644 index 0000000000..596f7bfc95 --- /dev/null +++ b/source4/lib/tdb/common/lock.c @@ -0,0 +1,235 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) + return 0; + if ((rw_type == F_WRLCK) && (tdb->read_only)) { + errno = EACCES; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = 1; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); + } + /* Generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (errno != EAGAIN) { + TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", + tdb->fd, offset, rw_type, lck_type, + strerror(errno))); + } + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + } + return 0; +} + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_lock(struct tdb_context *tdb, int list, int ltype) +{ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (tdb->locked[list+1].count == 0) { + if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { + TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", + list, ltype, strerror(errno))); + return -1; + } + tdb->locked[list+1].ltype = ltype; + } + tdb->locked[list+1].count++; + return 0; +} + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +int tdb_unlock(struct tdb_context *tdb, int list, int ltype) +{ + int ret = -1; + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + if (tdb->locked[list+1].count==0) { + TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); + return ret; + } + + if (tdb->locked[list+1].count == 1) { + /* Down to last nested lock: unlock underneath */ + ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + } else { + ret = 0; + } + tdb->locked[list+1].count--; + + if (ret) + TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + + + +/* lock/unlock entire database */ +int tdb_lockall(struct tdb_context *tdb) +{ + u32 i; + + /* There are no locks on read-only dbs */ + if (tdb->read_only) + return TDB_ERRCODE(TDB_ERR_LOCK, -1); + for (i = 0; i < tdb->header.hash_size; i++) + if (tdb_lock(tdb, i, F_WRLCK)) + break; + + /* If error, release locks we have... */ + if (i < tdb->header.hash_size) { + u32 j; + + for ( j = 0; j < i; j++) + tdb_unlock(tdb, j, F_WRLCK); + return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); + } + + return 0; +} +void tdb_unlockall(struct tdb_context *tdb) +{ + u32 i; + for (i=0; i < tdb->header.hash_size; i++) + tdb_unlock(tdb, i, F_WRLCK); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + + + +/* record lock stops delete underneath */ +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; +} + +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); +} + +/* fcntl locks don't stack: avoid unlocking someone else's */ +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + u32 count = 0; + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); +} diff --git a/source4/lib/tdb/common/open.c b/source4/lib/tdb/common/open.c new file mode 100644 index 0000000000..d86ffff646 --- /dev/null +++ b/source4/lib/tdb/common/open.c @@ -0,0 +1,409 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static struct tdb_context *tdbs = NULL; + + +/* This is based on the hash algorithm from gdbm */ +static unsigned int default_tdb_hash(TDB_DATA *key) +{ + u32 value; /* Used to compute the hash value. */ + u32 i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(struct tdb_context *tdb, int hash_size) +{ + struct tdb_header *newdb; + int size, ret = -1; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); + if (!(newdb = calloc(size, 1))) + return TDB_ERRCODE(TDB_ERR_OOM, -1); + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + if (write(tdb->fd, newdb, size) != size) { + ret = -1; + } else { + ret = 0; + } + + fail: + SAFE_FREE(newdb); + return ret; +} + + + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + struct tdb_context *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); +} + +/* a default logging function */ +static void null_log_fn(struct tdb_context *tdb, int level, const char *fmt, ...) +{ +} + + +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn, + tdb_hash_func hash_fn) +{ + struct tdb_context *tdb; + struct stat st; + int rev = 0, locked = 0; + uint8_t *vp; + u32 vertest; + + if (!(tdb = calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb->fd = -1; + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + tdb->log_fn = log_fn?log_fn:null_log_fn; + tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* ensure there is only one process initialising at once */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 + || (tdb->header.version != TDB_VERSION + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { + /* its not a valid database - possibly initialise it */ + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + errno = EIO; /* ie bad format or something */ + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } + vp = (uint8_t *)&tdb->header.version; + vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | + (((u32)vp[2]) << 8) | (u32)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + tdb_convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + if (tdb->header.rwlocks != 0) { + TDB_LOG((tdb, 5, "tdb_open_ex: spinlocks no longer supported\n")); + goto fail; + } + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, (int)st.st_dev, (int)st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); + if (!tdb->locked) { + TDB_LOG((tdb, 2, "tdb_open_ex: " + "failed to allocate lock structure for %s\n", + name)); + errno = ENOMEM; + goto fail; + } + tdb_mmap(tdb); + if (locked) { + if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + /* leave this lock in place to indicate it's in use */ + if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) + goto fail; + } + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb->locked); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(struct tdb_context *tdb) +{ + struct tdb_context **i; + int ret = 0; + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + ret = close(tdb->fd); + SAFE_FREE(tdb->locked); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* register a loging function */ +void tdb_logging_function(struct tdb_context *tdb, void (*fn)(struct tdb_context *, int , const char *, ...)) +{ + tdb->log_fn = fn?fn:null_log_fn; +} + + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(struct tdb_context *tdb) +{ + struct stat st; + + if (tdb->flags & TDB_INTERNAL) + return 0; /* Nothing to do. */ + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if ((tdb->flags & TDB_CLEAR_IF_FIRST) && + (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { + TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(void) +{ + struct tdb_context *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + if (tdb_reopen(tdb) != 0) + return -1; + } + + return 0; +} diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c deleted file mode 100644 index 232cd8dfc6..0000000000 --- a/source4/lib/tdb/common/spinlock.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - trivial database library - - Copyright (C) Anton Blanchard 2001 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#if HAVE_CONFIG_H -#include -#endif - -#ifndef _SAMBA_BUILD_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tdb.h" - -#define DEBUG -#else -#include "includes.h" -#include "lib/tdb/include/tdb.h" -#include "system/filesys.h" -#endif - -#ifdef USE_SPINLOCKS - -/* - * ARCH SPECIFIC - */ - -#if defined(SPARC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - asm volatile("ldstub [%1], %0" - : "=r" (result) - : "r" (lock) - : "memory"); - - return (result == 0) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(POWERPC_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int result; - - __asm__ __volatile__( -"1: lwarx %0,0,%1\n\ - cmpwi 0,%0,0\n\ - li %0,0\n\ - bne- 2f\n\ - li %0,1\n\ - stwcx. %0,0,%1\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r"(result) - : "r"(lock) - : "cr0", "memory"); - - return (result == 1) ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("eieio":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#elif defined(INTEL_SPINLOCKS) - -static inline int __spin_trylock(spinlock_t *lock) -{ - int oldval; - - asm volatile("xchgl %0,%1" - : "=r" (oldval), "=m" (*lock) - : "0" (0) - : "memory"); - - return oldval > 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 1; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 1; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 1); -} - -#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730) - -/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See - * sync(3) for the details of the intrinsic operations. - * - * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro. - */ - -#ifndef _SAMBA_BUILD_ - -/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */ -#define inline __inline - -#endif /* _SAMBA_BUILD_ */ - -/* Returns 0 if the lock is acquired, EBUSY otherwise. */ -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int val; - val = __lock_test_and_set(lock, 1); - return val == 0 ? 0 : EBUSY; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - __lock_release(lock); -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - __lock_release(lock); -} - -/* Returns 1 if the lock is held, 0 otherwise. */ -static inline int __spin_is_locked(spinlock_t *lock) -{ - unsigned int val; - val = __add_and_fetch(lock, 0); - return val; -} - -#elif defined(MIPS_SPINLOCKS) - -static inline unsigned int load_linked(unsigned long addr) -{ - unsigned int res; - - __asm__ __volatile__("ll\t%0,(%1)" - : "=r" (res) - : "r" (addr)); - - return res; -} - -static inline unsigned int store_conditional(unsigned long addr, unsigned int value) -{ - unsigned int res; - - __asm__ __volatile__("sc\t%0,(%2)" - : "=r" (res) - : "0" (value), "r" (addr)); - return res; -} - -static inline int __spin_trylock(spinlock_t *lock) -{ - unsigned int mw; - - do { - mw = load_linked(lock); - if (mw) - return EBUSY; - } while (!store_conditional(lock, 1)); - - asm volatile("":::"memory"); - - return 0; -} - -static inline void __spin_unlock(spinlock_t *lock) -{ - asm volatile("":::"memory"); - *lock = 0; -} - -static inline void __spin_lock_init(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int __spin_is_locked(spinlock_t *lock) -{ - return (*lock != 0); -} - -#else -#error Need to implement spinlock code in spinlock.c -#endif - -/* - * OS SPECIFIC - */ - -static void yield_cpu(void) -{ - struct timespec tm; - -#ifdef USE_SCHED_YIELD - sched_yield(); -#else - /* Linux will busy loop for delays < 2ms on real time tasks */ - tm.tv_sec = 0; - tm.tv_nsec = 2000000L + 1; - nanosleep(&tm, NULL); -#endif -} - -static int this_is_smp(void) -{ -#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN) - return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0; -#else - return 0; -#endif -} - -/* - * GENERIC - */ - -static int smp_machine = 0; - -static inline void __spin_lock(spinlock_t *lock) -{ - int ntries = 0; - - while(__spin_trylock(lock)) { - while(__spin_is_locked(lock)) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __read_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (!(rwlock->count & RWLOCK_BIAS)) { - rwlock->count++; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count & RWLOCK_BIAS) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_lock(tdb_rwlock_t *rwlock) -{ - int ntries = 0; - - while(1) { - __spin_lock(&rwlock->lock); - - if (rwlock->count == 0) { - rwlock->count |= RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); - return; - } - - __spin_unlock(&rwlock->lock); - - while(rwlock->count != 0) { - if (smp_machine && ntries++ < MAX_BUSY_LOOPS) - continue; - yield_cpu(); - } - } -} - -static void __write_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!(rwlock->count & RWLOCK_BIAS)) - fprintf(stderr, "bug: write_unlock\n"); -#endif - - rwlock->count &= ~RWLOCK_BIAS; - __spin_unlock(&rwlock->lock); -} - -static void __read_unlock(tdb_rwlock_t *rwlock) -{ - __spin_lock(&rwlock->lock); - -#ifdef DEBUG - if (!rwlock->count) - fprintf(stderr, "bug: read_unlock\n"); - - if (rwlock->count & RWLOCK_BIAS) - fprintf(stderr, "bug: read_unlock\n"); -#endif - - rwlock->count--; - __spin_unlock(&rwlock->lock); -} - -/* TDB SPECIFIC */ - -/* lock a list in the database. list -1 is the alloc list */ -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_lock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_lock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* unlock the database. */ -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) -{ - tdb_rwlock_t *rwlocks; - - if (!tdb->map_ptr) return -1; - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - - switch(rw_type) { - case F_RDLCK: - __read_unlock(&rwlocks[list+1]); - break; - - case F_WRLCK: - __write_unlock(&rwlocks[list+1]); - break; - - default: - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - return 0; -} - -int tdb_create_rwlocks(int fd, unsigned int hash_size) -{ - unsigned int size, i; - tdb_rwlock_t *rwlocks; - - size = TDB_SPINLOCK_SIZE(hash_size); - rwlocks = malloc(size); - if (!rwlocks) - return -1; - - for(i = 0; i < hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - - /* Write it out (appending to end) */ - if (write(fd, rwlocks, size) != size) { - free(rwlocks); - return -1; - } - smp_machine = this_is_smp(); - free(rwlocks); - return 0; -} - -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_rwlock_t *rwlocks; - unsigned int i; - - if (tdb->header.rwlocks == 0) return 0; - if (!tdb->map_ptr) return -1; - - /* We're mmapped here */ - rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks); - for(i = 0; i < tdb->header.hash_size+1; i++) { - __spin_lock_init(&rwlocks[i].lock); - rwlocks[i].count = 0; - } - return 0; -} -#else -int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; } -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; } - -/* Non-spinlock version: remove spinlock pointer */ -int tdb_clear_spinlocks(TDB_CONTEXT *tdb) -{ - tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks - - (char *)&tdb->header); - - tdb->header.rwlocks = 0; - if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, (void *)&tdb->header.rwlocks, - sizeof(tdb->header.rwlocks)) - != sizeof(tdb->header.rwlocks)) - return -1; - return 0; -} -#endif diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 3477d7e4be..f099c2d1aa 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -3,7 +3,7 @@ trivial database library - Copyright (C) Andrew Tridgell 1999-2004 + Copyright (C) Andrew Tridgell 1999-2005 Copyright (C) Paul `Rusty' Russell 2000 Copyright (C) Jeremy Allison 2000-2003 @@ -26,1007 +26,28 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tdb_private.h" -#ifndef _SAMBA_BUILD_ -#if HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tdb.h" -#else -#include "includes.h" -#include "lib/tdb/include/tdb.h" -#include "system/time.h" -#include "system/shmem.h" -#include "system/filesys.h" -#endif - -#define TDB_MAGIC_FOOD "TDB file\n" -#define TDB_VERSION (0x26011967 + 6) -#define TDB_MAGIC (0x26011999U) -#define TDB_FREE_MAGIC (~TDB_MAGIC) -#define TDB_DEAD_MAGIC (0xFEE1DEAD) -#define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) -#define DEFAULT_HASH_SIZE 131 -#define TDB_PAGE_SIZE 0x2000 -#define FREELIST_TOP (sizeof(struct tdb_header)) -#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) -#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) -#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) -#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) -#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off)) -#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size)) - - -/* NB assumes there is a local variable called "tdb" that is the - * current context, also takes doubly-parenthesized print-style - * argument. */ -#define TDB_LOG(x) tdb->log_fn x - -/* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -#ifndef discard_const_p -# if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) -# define discard_const(ptr) ((void *)((intptr_t)(ptr))) -# else -# define discard_const(ptr) ((void *)(ptr)) -# endif -# define discard_const_p(type, ptr) ((type *)discard_const(ptr)) -#endif - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) -#endif - -#define BUCKET(hash) ((hash) % tdb->header.hash_size) TDB_DATA tdb_null; -/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ -static TDB_CONTEXT *tdbs = NULL; - -static int tdb_munmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return 0; - -#ifdef HAVE_MMAP - if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->map_size); - if (ret != 0) - return ret; - } -#endif - tdb->map_ptr = NULL; - return 0; -} - -static void tdb_mmap(TDB_CONTEXT *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return; - -#ifdef HAVE_MMAP - if (!(tdb->flags & TDB_NOMMAP)) { - tdb->map_ptr = mmap(NULL, tdb->map_size, - PROT_READ|(tdb->read_only? 0:PROT_WRITE), - MAP_SHARED|MAP_FILE, tdb->fd, 0); - - /* - * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! - */ - - if (tdb->map_ptr == MAP_FAILED) { - tdb->map_ptr = NULL; - TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", - tdb->map_size, strerror(errno))); - } - } else { - tdb->map_ptr = NULL; - } -#else - tdb->map_ptr = NULL; -#endif -} - -/* Endian conversion: we only ever deal with 4 byte quantities */ -static void *convert(void *buf, u32 size) -{ - u32 i, *p = buf; - for (i = 0; i < size / 4; i++) - p[i] = TDB_BYTEREV(p[i]); - return buf; -} -#define DOCONV() (tdb->flags & TDB_CONVERT) -#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x) - -/* the body of the database is made of one list_struct for the free space - plus a separate data list for each hash value */ -struct list_struct { - tdb_off next; /* offset of the next record in the list */ - tdb_len rec_len; /* total byte length of record */ - tdb_len key_len; /* byte length of key */ - tdb_len data_len; /* byte length of data */ - u32 full_hash; /* the full 32 bit hash of the key */ - u32 magic; /* try to catch errors */ - /* the following union is implied: - union { - char record[rec_len]; - struct { - char key[key_len]; - char data[data_len]; - } - u32 totalsize; (tailer) - } - */ -}; - -/* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset. - - On error, errno is also set so that errors are passed back properly - through tdb_open(). */ -static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, - int rw_type, int lck_type, int probe) -{ - struct flock fl; - int ret; - - if (tdb->flags & TDB_NOLOCK) - return 0; - if ((rw_type == F_WRLCK) && (tdb->read_only)) { - errno = EACCES; - return -1; - } - - fl.l_type = rw_type; - fl.l_whence = SEEK_SET; - fl.l_start = offset; - fl.l_len = 1; - fl.l_pid = 0; - - do { - ret = fcntl(tdb->fd,lck_type,&fl); - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - } - /* Generic lock error. errno set by fcntl. - * EAGAIN is an expected return from non-blocking - * locks. */ - if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, - strerror(errno))); - } - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - -/* lock a list in the database. list -1 is the alloc list */ -static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype) -{ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", - list, ltype)); - return -1; - } - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Since fcntl locks don't nest, we do a lock for the first one, - and simply bump the count for future ones */ - if (tdb->locked[list+1].count == 0) { - if (!tdb->read_only && tdb->header.rwlocks) { - if (tdb_spinlock(tdb, list, ltype)) { - TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", - list, ltype)); - return -1; - } - } else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { - TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", - list, ltype, strerror(errno))); - return -1; - } - tdb->locked[list+1].ltype = ltype; - } - tdb->locked[list+1].count++; - return 0; -} - -/* unlock the database: returns void because it's too late for errors. */ - /* changed to return int it may be interesting to know there - has been an error --simo */ -static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype) -{ - int ret = -1; - - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Sanity checks */ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); - return ret; - } - - if (tdb->locked[list+1].count==0) { - TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); - return ret; - } - - if (tdb->locked[list+1].count == 1) { - /* Down to last nested lock: unlock underneath */ - if (!tdb->read_only && tdb->header.rwlocks) { - ret = tdb_spinunlock(tdb, list, ltype); - } else { - ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); - } - } else { - ret = 0; - } - tdb->locked[list+1].count--; - - if (ret) - TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); - return ret; -} - -/* This is based on the hash algorithm from gdbm */ -static u32 default_tdb_hash(TDB_DATA *key) -{ - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) - value = (value + (key->dptr[i] << (i*5 % 24))); - - return (1103515243 * value + 12345); -} - -/* check for an out of bounds access - if it is out of bounds then - see if the database has been expanded by someone else and expand - if necessary - note that "len" is the minimum length needed for the db -*/ -static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe) -{ - struct stat st; - if (len <= tdb->map_size) - return 0; - if (tdb->flags & TDB_INTERNAL) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", - (int)len, (int)tdb->map_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (fstat(tdb->fd, &st) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - - if (st.st_size < (size_t)len) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", - (int)len, (int)st.st_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - /* Unmap, update size, remap */ - if (tdb_munmap(tdb) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - tdb->map_size = st.st_size; - tdb_mmap(tdb); - return 0; -} - -/* write a lump of data at a specified offset */ -static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(off + (char *)tdb->map_ptr, buf, len); -#ifdef HAVE_PWRITE - else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || write(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - return 0; -} - -/* read a lump of data at a specified offset, maybe convert */ -static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv) -{ - if (tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) - memcpy(buf, off + (char *)tdb->map_ptr, len); -#ifdef HAVE_PREAD - else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) { -#else - else if (lseek(tdb->fd, off, SEEK_SET) != off - || read(tdb->fd, buf, len) != (ssize_t)len) { -#endif - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - if (cv) - convert(buf, len); - return 0; -} - -/* read a lump of data, allocating the space for it */ -static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len) -{ - char *buf; - - if (!(buf = malloc(len))) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", - len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_OOM, buf); - } - if (tdb_read(tdb, offset, buf, len, 0) == -1) { - SAFE_FREE(buf); - return NULL; - } - return buf; -} - -/* read/write a tdb_off */ -static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); -} -static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d) -{ - tdb_off off = *d; - return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); -} - -/* read/write a record */ -static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - if (TDB_BAD_MAGIC(rec)) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - return tdb_oob(tdb, rec->next+sizeof(*rec), 0); -} -static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - struct list_struct r = *rec; - return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); -} - -/* read a freelist record and check for simple errors */ -static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec) -{ - if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - - if (rec->magic == TDB_MAGIC) { - /* this happens when a app is showdown while deleting a record - we should - not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", - rec->magic, off)); - rec->magic = TDB_FREE_MAGIC; - if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) - return -1; - } - - if (rec->magic != TDB_FREE_MAGIC) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", - rec->magic, off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) - return -1; - return 0; -} - -/* update a record tailer (must hold allocation lock) */ -static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset, - const struct list_struct *rec) -{ - tdb_off totalsize; - - /* Offset of tailer from record header */ - totalsize = sizeof(*rec) + rec->rec_len; - return ofs_write(tdb, offset + totalsize - sizeof(tdb_off), - &totalsize); -} - -static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset) -{ - struct list_struct rec; - tdb_off tailer_ofs, tailer; - - if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - printf("ERROR: failed to read record at %u\n", offset); - return 0; - } - - printf(" rec: offset=0x%08x next=0x%08x rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", - offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic); - - tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off); - if (ofs_read(tdb, tailer_ofs, &tailer) == -1) { - printf("ERROR: failed to read tailer at %u\n", tailer_ofs); - return rec.next; - } - - if (tailer != rec.rec_len + sizeof(rec)) { - printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); - } - return rec.next; -} - -static int tdb_dump_chain(TDB_CONTEXT *tdb, int i) -{ - tdb_off rec_ptr, top; - - top = TDB_HASH_TOP(i); - - if (tdb_lock(tdb, i, F_WRLCK) != 0) - return -1; - - if (ofs_read(tdb, top, &rec_ptr) == -1) - return tdb_unlock(tdb, i, F_WRLCK); - - if (rec_ptr) - printf("hash=%d\n", i); - - while (rec_ptr) { - rec_ptr = tdb_dump_record(tdb, rec_ptr); - } - - return tdb_unlock(tdb, i, F_WRLCK); -} - -void tdb_dump_all(TDB_CONTEXT *tdb) -{ - int i; - for (i=0;iheader.hash_size;i++) { - tdb_dump_chain(tdb, i); - } - printf("freelist:\n"); - tdb_dump_chain(tdb, -1); -} - -int tdb_printfreelist(TDB_CONTEXT *tdb) -{ - int ret; - long total_free = 0; - tdb_off offset, rec_ptr; - struct list_struct rec; - - if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) - return ret; - - offset = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, offset, &rec_ptr) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - } - - printf("freelist top=[0x%08x]\n", rec_ptr ); - while (rec_ptr) { - if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - if (rec.magic != TDB_FREE_MAGIC) { - printf("bad magic 0x%08x in free list\n", rec.magic); - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", - rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); - total_free += rec.rec_len; - - /* move to the next record */ - rec_ptr = rec.next; - } - printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, - (int)total_free); - - return tdb_unlock(tdb, -1, F_WRLCK); -} - -/* Remove an element from the freelist. Must have alloc lock. */ -static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next) -{ - tdb_off last_ptr, i; - - /* read in the freelist top */ - last_ptr = FREELIST_TOP; - while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { - if (i == off) { - /* We've found it! */ - return ofs_write(tdb, last_ptr, &next); - } - /* Follow chain (next offset is at start of record) */ - last_ptr = i; - } - TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); -} - -/* Add an element into the freelist. Merge adjacent records if - neccessary. */ -static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec) -{ - tdb_off right, left; - - /* Allocation and tailer lock */ - if (tdb_lock(tdb, -1, F_WRLCK) != 0) - return -1; - - /* set an initial tailer, so if we fail we don't leave a bogus record */ - if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); - goto fail; - } - - /* Look right first (I'm an Australian, dammit) */ - right = offset + sizeof(*rec) + rec->rec_len; - if (right + sizeof(*rec) <= tdb->map_size) { - struct list_struct r; - - if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); - goto left; - } - - /* If it's free, expand to include it. */ - if (r.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); - goto left; - } - rec->rec_len += sizeof(r) + r.rec_len; - } - } - -left: - /* Look left */ - left = offset - sizeof(tdb_off); - if (left > TDB_DATA_START(tdb->header.hash_size)) { - struct list_struct l; - tdb_off leftsize; - - /* Read in tailer and jump back to header */ - if (ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); - goto update; - } - left = offset - leftsize; - - /* Now read in record */ - if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); - goto update; - } - - /* If it's free, expand to include it. */ - if (l.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); - goto update; - } else { - offset = left; - rec->rec_len += leftsize; - } - } - } - -update: - if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); - goto fail; - } - - /* Now, prepend to free list */ - rec->magic = TDB_FREE_MAGIC; - - if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || - rec_write(tdb, offset, rec) == -1 || - ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); - goto fail; - } - - /* And we're done. */ - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* expand a file. we prefer to use ftruncate, as that is what posix - says to use for mmap expansion */ -static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) -{ - char buf[1024]; -#if HAVE_FTRUNCATE_EXTEND - if (ftruncate(tdb->fd, size+addition) != 0) { - TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#else - char b = 0; - -#ifdef HAVE_PWRITE - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { -#else - if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || - write(tdb->fd, &b, 1) != 1) { -#endif - TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } -#endif - - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ - memset(buf, 0x42, sizeof(buf)); - while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; -#ifdef HAVE_PWRITE - int ret = pwrite(tdb->fd, buf, n, size); -#else - int ret; - if (lseek(tdb->fd, size, SEEK_SET) != size) - return -1; - ret = write(tdb->fd, buf, n); -#endif - if (ret != n) { - TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); - return -1; - } - addition -= n; - size += n; - } - return 0; -} - - -/* expand the database at least size bytes by expanding the underlying - file and doing the mmap again if necessary */ -static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size) -{ - struct list_struct rec; - tdb_off offset; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); - return -1; - } - - /* must know about any previous expansions by another process */ - tdb_oob(tdb, tdb->map_size + 1, 1); - - /* always make room for at least 10 more records, and round - the database up to a multiple of TDB_PAGE_SIZE */ - size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; - - if (!(tdb->flags & TDB_INTERNAL)) - tdb_munmap(tdb); - - /* - * We must ensure the file is unmapped before doing this - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - if (expand_file(tdb, tdb->map_size, size) != 0) - goto fail; - } - - tdb->map_size += size; - - if (tdb->flags & TDB_INTERNAL) { - char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size); - if (!new_map_ptr) { - tdb->map_size -= size; - goto fail; - } - tdb->map_ptr = new_map_ptr; - } else { - /* - * We must ensure the file is remapped before adding the space - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* We're ok if the mmap fails as we'll fallback to read/write */ - tdb_mmap(tdb); - } - - /* form a new freelist record */ - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = size - sizeof(rec); - - /* link it into the free list */ - offset = tdb->map_size - size; - if (tdb_free(tdb, offset, &rec) == -1) - goto fail; - - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* - the core of tdb_allocate - called when we have decided which - free list entry to use - */ -static tdb_off tdb_allocate_ofs(TDB_CONTEXT *tdb, tdb_len length, tdb_off rec_ptr, - struct list_struct *rec, tdb_off last_ptr) -{ - struct list_struct newrec; - tdb_off newrec_ptr; - - memset(&newrec, '\0', sizeof(newrec)); - - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else { - newrec_ptr = 0; - } - - /* Remove allocated record from the free list */ - if (ofs_write(tdb, last_ptr, &rec->next) == -1) { - return 0; - } - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (rec_write(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { - return 0; - } - } - - /* all done - return the new record offset */ - return rec_ptr; -} - -/* allocate some space from the free list. The offset returned points - to a unconnected list_struct within the database with room for at - least length bytes of total data - - 0 is returned if the space could not be allocated - */ -static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length, - struct list_struct *rec) -{ - tdb_off rec_ptr, last_ptr, newrec_ptr; - struct { - tdb_off rec_ptr, last_ptr; - tdb_len rec_len; - } bestfit; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) - return 0; - - /* Extra bytes required for tailer */ - length += sizeof(tdb_off); - - again: - last_ptr = FREELIST_TOP; - - /* read in the freelist top */ - if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) - goto fail; - - bestfit.rec_ptr = 0; - - /* - this is a best fit allocation strategy. Originally we used - a first fit strategy, but it suffered from massive fragmentation - issues when faced with a slowly increasing record size. - */ - while (rec_ptr) { - if (rec_free_read(tdb, rec_ptr, rec) == -1) { - goto fail; - } - - if (rec->rec_len >= length) { - if (bestfit.rec_ptr == 0 || - rec->rec_len < bestfit.rec_len) { - bestfit.rec_len = rec->rec_len; - bestfit.rec_ptr = rec_ptr; - bestfit.last_ptr = last_ptr; - /* consider a fit to be good enough if we aren't wasting more than half the space */ - if (bestfit.rec_len < 2*length) { - break; - } - } - } - - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec->next; - } - - if (bestfit.rec_ptr != 0) { - if (rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { - goto fail; - } - - newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); - tdb_unlock(tdb, -1, F_WRLCK); - return newrec_ptr; - } - - /* we didn't find enough space. See if we can expand the - database and if we can then try again */ - if (tdb_expand(tdb, length + sizeof(*rec)) == 0) - goto again; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return 0; -} - -/* initialise a new database with a specified hash size */ -static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size) -{ - struct tdb_header *newdb; - int size, ret = -1; - - /* We make it up in memory, then write it out if not internal */ - size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off); - if (!(newdb = calloc(size, 1))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - - /* Fill in the header */ - newdb->version = TDB_VERSION; - newdb->hash_size = hash_size; -#ifdef USE_SPINLOCKS - newdb->rwlocks = size; -#endif - if (tdb->flags & TDB_INTERNAL) { - tdb->map_size = size; - tdb->map_ptr = (char *)newdb; - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Convert the `ondisk' version if asked. */ - CONVERT(*newdb); - return 0; - } - if (lseek(tdb->fd, 0, SEEK_SET) == -1) - goto fail; - - if (ftruncate(tdb->fd, 0) == -1) - goto fail; - - /* This creates an endian-converted header, as if read from disk */ - CONVERT(*newdb); - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Don't endian-convert the magic food! */ - memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); - if (write(tdb->fd, newdb, size) != size) - ret = -1; - else - ret = tdb_create_rwlocks(tdb->fd, hash_size); - - fail: - SAFE_FREE(newdb); - return ret; -} - /* Returns 0 on fail. On success, return offset of record, and fills in rec */ -static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, struct list_struct *r) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* read in the hash top */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) return 0; /* keep looking until we find the right record */ while (rec_ptr) { - if (rec_read(tdb, rec_ptr, r) == -1) + if (tdb_rec_read(tdb, rec_ptr, r) == -1) return 0; if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { - char *k; + unsigned char *k; /* a very likely hit - read the key */ k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), r->key_len); @@ -1045,8 +66,8 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, } /* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec) +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec) { u32 rec_ptr; @@ -1057,48 +78,22 @@ static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int return rec_ptr; } -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb) -{ - return tdb->ecode; -} - -static struct tdb_errname { - enum TDB_ERROR ecode; const char *estring; -} emap[] = { {TDB_SUCCESS, "Success"}, - {TDB_ERR_CORRUPT, "Corrupt database"}, - {TDB_ERR_IO, "IO Error"}, - {TDB_ERR_LOCK, "Locking error"}, - {TDB_ERR_OOM, "Out of memory"}, - {TDB_ERR_EXISTS, "Record exists"}, - {TDB_ERR_NOLOCK, "Lock exists on other keys"}, - {TDB_ERR_NOEXIST, "Record does not exist"} }; - -/* Error string for the last tdb error */ -const char *tdb_errorstr(TDB_CONTEXT *tdb) -{ - u32 i; - for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) - if (tdb->ecode == emap[i].ecode) - return emap[i].estring; - return "Invalid error code"; -} /* update an entry in place - this only works if the new data size is <= the old data size and the key exists. on failure return -1. */ - -static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) +static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) { struct list_struct rec; - tdb_off rec_ptr; + tdb_off_t rec_ptr; /* find entry */ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* must be long enough key, data and tailer */ - if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) { + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { tdb->ecode = TDB_SUCCESS; /* Not really an error */ return -1; } @@ -1110,7 +105,7 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db if (dbuf.dsize != rec.data_len) { /* update size */ rec.data_len = dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); + return tdb_rec_write(tdb, rec_ptr, &rec); } return 0; @@ -1122,10 +117,9 @@ static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA db * then the TDB_DATA will have zero length but * a non-zero pointer */ - -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; TDB_DATA ret; u32 hash; @@ -1136,385 +130,85 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) return tdb_null; ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - ret.dsize = rec.data_len; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return ret; -} - -/* check if an entry in the database exists - - note that 1 is returned if the key is found and 0 is returned if not found - this doesn't match the conventions in the rest of this module, but is - compatible with gdbm -*/ -static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) -{ - struct list_struct rec; - - if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) - return 0; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return 1; -} - -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) -{ - u32 hash = tdb->hash_fn(&key); - return tdb_exists_hash(tdb, key, hash); -} - -/* record lock stops delete underneath */ -static int lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; -} -/* - Write locks override our own fcntl readlocks, so check it here. - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - return -1; - return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); -} - -/* - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ - -static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); -} -/* fcntl locks don't stack: avoid unlocking someone else's */ -static int unlock_record(TDB_CONTEXT *tdb, tdb_off off) -{ - struct tdb_traverse_lock *i; - u32 count = 0; - - if (off == 0) - return 0; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - count++; - return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); -} - -/* actually delete an entry in the database given the offset */ -static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec) -{ - tdb_off last_ptr, i; - struct list_struct lastrec; - - if (tdb->read_only) return -1; - - if (write_lock_record(tdb, rec_ptr) == -1) { - /* Someone traversing here: mark it as dead */ - rec->magic = TDB_DEAD_MAGIC; - return rec_write(tdb, rec_ptr, rec); - } - if (write_unlock_record(tdb, rec_ptr) != 0) - return -1; - - /* find previous record in hash chain */ - if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) - return -1; - for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) - if (rec_read(tdb, i, &lastrec) == -1) - return -1; - - /* unlink it: next ptr is at start of record. */ - if (last_ptr == 0) - last_ptr = TDB_HASH_TOP(rec->full_hash); - if (ofs_write(tdb, last_ptr, &rec->next) == -1) - return -1; - - /* recover the space */ - if (tdb_free(tdb, rec_ptr, rec) == -1) - return -1; - return 0; -} - -/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ -static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, - struct list_struct *rec) -{ - int want_next = (tlock->off != 0); - - /* Lock each chain from the start one. */ - for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { - - /* this is an optimisation for the common case where - the hash chain is empty, which is particularly - common for the use of tdb with ldb, where large - hashes are used. In that case we spend most of our - time in tdb_brlock(), locking empty hash chains. - - To avoid this, we do an unlocked pre-check to see - if the hash chain is empty before starting to look - inside it. If it is empty then we can avoid that - hash chain. If it isn't empty then we can't believe - the value we get back, as we read it without a - lock, so instead we get the lock and re-fetch the - value below. - - Notice that not doing this optimisation on the - first hash chain is critical. We must guarantee - that we have done at least one fcntl lock at the - start of a search to guarantee that memory is - coherent on SMP systems. If records are added by - others during the search then thats OK, and we - could possibly miss those with this trick, but we - could miss them anyway without this trick, so the - semantics don't change. - - With a non-indexed ldb search this trick gains us a - factor of around 80 in speed on a linux 2.6.x - system (testing using ldbtest). - */ - if (!tlock->off && tlock->hash != 0) { - u32 off; - if (tdb->map_ptr) { - for (;tlock->hash < tdb->header.hash_size;tlock->hash++) { - if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) { - break; - } - } - if (tlock->hash == tdb->header.hash_size) { - continue; - } - } else { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 && - off == 0) { - continue; - } - } - } - - if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) - return -1; - - /* No previous record? Start at top of chain. */ - if (!tlock->off) { - if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), - &tlock->off) == -1) - goto fail; - } else { - /* Otherwise unlock the previous record. */ - if (unlock_record(tdb, tlock->off) != 0) - goto fail; - } - - if (want_next) { - /* We have offset of old record: grab next */ - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - tlock->off = rec->next; - } - - /* Iterate through chain */ - while( tlock->off) { - tdb_off current; - if (rec_read(tdb, tlock->off, rec) == -1) - goto fail; - - /* Detect infinite loops. From "Shlomi Yaakobovich" . */ - if (tlock->off == rec->next) { - TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); - goto fail; - } - - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } - - /* Try to clean dead ones from old traverses */ - current = tlock->off; - tlock->off = rec->next; - if (!tdb->read_only && - do_delete(tdb, current, rec) != 0) - goto fail; - } - tdb_unlock(tdb, tlock->hash, F_WRLCK); - want_next = 0; - } - /* We finished iteration without finding anything */ - return TDB_ERRCODE(TDB_SUCCESS, 0); - - fail: - tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); - return -1; + rec.data_len); + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; } -/* traverse the entire database - calling fn(tdb, key, data) on each element. - return -1 on error or the record count traversed - if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop - */ -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private) +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { - TDB_DATA key, dbuf; struct list_struct rec; - struct tdb_traverse_lock tl = { NULL, 0, 0 }; - int ret, count = 0; - - /* This was in the initializaton, above, but the IRIX compiler - * did not like it. crh - */ - tl.next = tdb->travlocks.next; - - /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = &tl; - - /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { - count++; - /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { - ret = -1; - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) - goto out; - if (unlock_record(tdb, tl.off) != 0) - TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); - goto out; - } - key.dsize = rec.key_len; - dbuf.dptr = key.dptr + rec.key_len; - dbuf.dsize = rec.data_len; - - /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { - ret = -1; - goto out; - } - if (fn && fn(tdb, key, dbuf, private)) { - /* They want us to terminate traversal */ - ret = count; - if (unlock_record(tdb, tl.off) != 0) { - TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; - ret = -1; - } - tdb->travlocks.next = tl.next; - SAFE_FREE(key.dptr); - return count; - } - SAFE_FREE(key.dptr); - } -out: - tdb->travlocks.next = tl.next; - if (ret < 0) - return -1; - else - return count; + + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; } -/* find the first entry in the database and return its key */ -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb) +int tdb_exists(struct tdb_context *tdb, TDB_DATA key) { - TDB_DATA key; - struct list_struct rec; - - /* release any old lock */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - tdb->travlocks.off = tdb->travlocks.hash = 0; - - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) - return tdb_null; - /* now read the key */ - key.dsize = rec.key_len; - key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); - if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); - return key; + u32 hash = tdb->hash_fn(&key); + return tdb_exists_hash(tdb, key, hash); } -/* find the next entry in the database, returning its key */ -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) +/* actually delete an entry in the database given the offset */ +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) { - u32 oldhash; - TDB_DATA key = tdb_null; - struct list_struct rec; - char *k = NULL; + tdb_off_t last_ptr, i; + struct list_struct lastrec; - /* Is locked key the old key? If so, traverse will be reliable. */ - if (tdb->travlocks.off) { - if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) - return tdb_null; - if (rec_read(tdb, tdb->travlocks.off, &rec) == -1 - || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), - rec.key_len)) - || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { - /* No, it wasn't: unlock it and start from scratch */ - if (unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - return tdb_null; - tdb->travlocks.off = 0; - } + if (tdb->read_only) return -1; - SAFE_FREE(k); + if (tdb_write_lock_record(tdb, rec_ptr) == -1) { + /* Someone traversing here: mark it as dead */ + rec->magic = TDB_DEAD_MAGIC; + return tdb_rec_write(tdb, rec_ptr, rec); } + if (tdb_write_unlock_record(tdb, rec_ptr) != 0) + return -1; - if (!tdb->travlocks.off) { - /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); - if (!tdb->travlocks.off) - return tdb_null; - tdb->travlocks.hash = BUCKET(rec.full_hash); - if (lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); - return tdb_null; - } - } - oldhash = tdb->travlocks.hash; + /* find previous record in hash chain */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + return -1; + for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) + if (tdb_rec_read(tdb, i, &lastrec) == -1) + return -1; - /* Grab next record: locks chain and returned record, - unlocks old record */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { - key.dsize = rec.key_len; - key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), - key.dsize); - /* Unlock the chain of this new record */ - if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - } - /* Unlock the chain of old record */ - if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - return key; + /* unlink it: next ptr is at start of record. */ + if (last_ptr == 0) + last_ptr = TDB_HASH_TOP(rec->full_hash); + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) + return -1; + + /* recover the space */ + if (tdb_free(tdb, rec_ptr, rec) == -1) + return -1; + return 0; } /* delete an entry in the database given a key */ -static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) { - tdb_off rec_ptr; + tdb_off_t rec_ptr; struct list_struct rec; int ret; if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) return -1; - ret = do_delete(tdb, rec_ptr, &rec); + ret = tdb_do_delete(tdb, rec_ptr, &rec); if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); return ret; } -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +int tdb_delete(struct tdb_context *tdb, TDB_DATA key) { u32 hash = tdb->hash_fn(&key); return tdb_delete_hash(tdb, key, hash); @@ -1525,11 +219,11 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) return 0 on success, -1 on failure */ -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) { struct list_struct rec; u32 hash; - tdb_off rec_ptr; + tdb_off_t rec_ptr; char *p = NULL; int ret = 0; @@ -1581,7 +275,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) goto fail; /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) goto fail; rec.key_len = key.dsize; @@ -1590,9 +284,9 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) rec.magic = TDB_MAGIC; /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { /* Need to tdb_unallocate() here */ goto fail; } @@ -1605,499 +299,68 @@ fail: goto out; } -/* Attempt to append data to an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. Record must be locked before calling. -*/ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) -{ - struct list_struct rec; - tdb_off rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* Append of 0 is always ok. */ - if (new_dbuf.dsize == 0) - return 0; - - /* must be long enough for key, old data + new data and tailer */ - if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) { - /* No room. */ - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len, - new_dbuf.dptr, new_dbuf.dsize) == -1) - return -1; - - /* update size */ - rec.data_len += new_dbuf.dsize; - return rec_write(tdb, rec_ptr, &rec); -} /* Append to an entry. Create if not exist. */ - -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) { - struct list_struct rec; u32 hash; - tdb_off rec_ptr; - char *p = NULL; - int ret = 0; - size_t new_data_size = 0; + TDB_DATA dbuf; + int ret = -1; /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) return -1; - /* first try in-place. */ - if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) - goto out; - - /* reset the error code potentially set by the tdb_append_inplace() */ - tdb->ecode = TDB_SUCCESS; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { - if (tdb->ecode != TDB_ERR_NOEXIST) - goto fail; + dbuf = tdb_fetch(tdb, key); - /* Not found - create. */ - - ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT); - goto out; + if (dbuf.dptr == NULL) { + dbuf.dptr = malloc(new_dbuf.dsize); + } else { + dbuf.dptr = realloc(dbuf.dptr, dbuf.dsize + new_dbuf.dsize); } - new_data_size = rec.data_len + new_dbuf.dsize; - - /* Copy key+old_value+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + new_data_size))) { + if (dbuf.dptr == NULL) { tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - /* Copy the key in place. */ - memcpy(p, key.dptr, key.dsize); - - /* Now read the old data into place. */ - if (rec.data_len && - tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1) - goto fail; - - /* Finally append the new data. */ - if (new_dbuf.dsize) - memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize); - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - - tdb_delete_hash(tdb, key, hash); - - if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) - goto fail; - - /* Read hash top into next ptr */ - if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = new_data_size; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1 - || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; - } - - out: - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; - -fail: - ret = -1; - goto out; -} - -static int tdb_already_open(dev_t device, - ino_t ino) -{ - TDB_CONTEXT *i; - - for (i = tdbs; i; i = i->next) { - if (i->device == device && i->inode == ino) { - return 1; - } - } - - return 0; -} - -/* open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the - database file. A flags value of O_WRONLY is invalid. The hash size - is advisory, use zero for a default value. - - Return is NULL on error, in which case errno is also set. Don't - try to call tdb_error or tdb_errname, just do strerror(errno). - - @param name may be NULL for internal databases. */ -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); -} - -/* a default logging function */ -static void null_log_fn(TDB_CONTEXT *tdb, int level, const char *fmt, ...) -{ -} - - -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn, - tdb_hash_func hash_fn) -{ - TDB_CONTEXT *tdb; - struct stat st; - int rev = 0, locked = 0; - uint8_t *vp; - u32 vertest; - - if (!(tdb = calloc(1, sizeof *tdb))) { - /* Can't log this */ - errno = ENOMEM; - goto fail; - } - tdb->fd = -1; - tdb->name = NULL; - tdb->map_ptr = NULL; - tdb->flags = tdb_flags; - tdb->open_flags = open_flags; - tdb->log_fn = log_fn?log_fn:null_log_fn; - tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; - - if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", - name)); - errno = EINVAL; - goto fail; - } - - if (hash_size == 0) - hash_size = DEFAULT_HASH_SIZE; - if ((open_flags & O_ACCMODE) == O_RDONLY) { - tdb->read_only = 1; - /* read only databases don't do locking or clear if first */ - tdb->flags |= TDB_NOLOCK; - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - /* internal databases don't mmap or lock, and start off cleared */ - if (tdb->flags & TDB_INTERNAL) { - tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); - goto fail; - } - goto internal; - } - - if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by open(2) */ + goto failed; } - /* ensure there is only one process initialising at once */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by tdb_brlock */ - } - - /* we need to zero database if we are the only one with it open */ - if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { - open_flags |= O_CREAT; - if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to truncate %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by ftruncate */ - } - } - - if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 - || (tdb->header.version != TDB_VERSION - && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { - /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { - errno = EIO; /* ie bad format or something */ - goto fail; - } - rev = (tdb->flags & TDB_CONVERT); - } - vp = (uint8_t *)&tdb->header.version; - vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | - (((u32)vp[2]) << 8) | (u32)vp[3]; - tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; - if (!rev) - tdb->flags &= ~TDB_CONVERT; - else { - tdb->flags |= TDB_CONVERT; - convert(&tdb->header, sizeof(tdb->header)); - } - if (fstat(tdb->fd, &st) == -1) - goto fail; - - /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "%s (%d,%d) is already open in this process\n", - name, (int)st.st_dev, (int)st.st_ino)); - errno = EBUSY; - goto fail; - } - - if (!(tdb->name = (char *)strdup(name))) { - errno = ENOMEM; - goto fail; - } - - tdb->map_size = st.st_size; - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); - if (!tdb->locked) { - TDB_LOG((tdb, 2, "tdb_open_ex: " - "failed to allocate lock structure for %s\n", - name)); - errno = ENOMEM; - goto fail; - } - tdb_mmap(tdb); - if (locked) { - if (!tdb->read_only) - if (tdb_clear_spinlocks(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to clear spinlock\n")); - goto fail; - } - if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " - "failed to take ACTIVE_LOCK on %s: %s\n", - name, strerror(errno))); - goto fail; - } - - } - - /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if - we didn't get the initial exclusive lock as we need to let all other - users know we're using it. */ - - if (tdb_flags & TDB_CLEAR_IF_FIRST) { - /* leave this lock in place to indicate it's in use */ - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) - goto fail; - } - - - internal: - /* Internal (memory-only) databases skip all the code above to - * do with disk files, and resume here by releasing their - * global lock and hooking into the active list. */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) - goto fail; - tdb->next = tdbs; - tdbs = tdb; - return tdb; - - fail: - { int save_errno = errno; + memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); + dbuf.dsize += new_dbuf.dsize; - if (!tdb) - return NULL; + ret = tdb_store(tdb, key, dbuf, 0); - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); - SAFE_FREE(tdb->locked); - SAFE_FREE(tdb); - errno = save_errno; - return NULL; - } -} - -/** - * Close a database. - * - * @returns -1 for error; 0 for success. - **/ -int tdb_close(TDB_CONTEXT *tdb) -{ - TDB_CONTEXT **i; - int ret = 0; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - ret = close(tdb->fd); - SAFE_FREE(tdb->locked); - - /* Remove from contexts list */ - for (i = &tdbs; *i; i = &(*i)->next) { - if (*i == tdb) { - *i = tdb->next; - break; - } - } - - memset(tdb, 0, sizeof(*tdb)); - SAFE_FREE(tdb); - +failed: + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbuf.dptr); return ret; } -/* lock/unlock entire database */ -int tdb_lockall(TDB_CONTEXT *tdb) -{ - u32 i; - - /* There are no locks on read-only dbs */ - if (tdb->read_only) - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - for (i = 0; i < tdb->header.hash_size; i++) - if (tdb_lock(tdb, i, F_WRLCK)) - break; - - /* If error, release locks we have... */ - if (i < tdb->header.hash_size) { - u32 j; - - for ( j = 0; j < i; j++) - tdb_unlock(tdb, j, F_WRLCK); - return TDB_ERRCODE(TDB_ERR_NOLOCK, -1); - } - - return 0; -} -void tdb_unlockall(TDB_CONTEXT *tdb) -{ - u32 i; - for (i=0; i < tdb->header.hash_size; i++) - tdb_unlock(tdb, i, F_WRLCK); -} - -/* lock/unlock one hash chain. This is meant to be used to reduce - contention - it cannot guarantee how many records will be locked */ -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} - -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} - -int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); -} - -int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); -} - -/* register a loging function */ -void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...)) +/* + return the name of the current tdb file + useful for external logging functions +*/ +const char *tdb_name(struct tdb_context *tdb) { - tdb->log_fn = fn?fn:null_log_fn; + return tdb->name; } - -/* reopen a tdb - this can be used after a fork to ensure that we have an independent - seek pointer from our parent and to re-establish locks */ -int tdb_reopen(TDB_CONTEXT *tdb) +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +int tdb_fd(struct tdb_context *tdb) { - struct stat st; - - if (tdb->flags & TDB_INTERNAL) - return 0; /* Nothing to do. */ - if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); - goto fail; - } - if (close(tdb->fd) != 0) - TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); - tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); - if (tdb->fd == -1) { - TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); - goto fail; - } - if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); - goto fail; - } - if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); - goto fail; - } - tdb_mmap(tdb); - if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { - TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); - goto fail; - } - - return 0; - -fail: - tdb_close(tdb); - return -1; + return tdb->fd; } -/* reopen all tdb's */ -int tdb_reopen_all(void) +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +tdb_log_func tdb_log_fn(struct tdb_context *tdb) { - TDB_CONTEXT *tdb; - - for (tdb=tdbs; tdb; tdb = tdb->next) { - /* Ensure no clear-if-first. */ - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_reopen(tdb) != 0) - return -1; - } - - return 0; + return tdb->log_fn; } diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h new file mode 100644 index 0000000000..8e246e3283 --- /dev/null +++ b/source4/lib/tdb/common/tdb_private.h @@ -0,0 +1,208 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library - private includes + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SAMBA_BUILD_ +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdbconfig.h" +#include "tdb.h" +#else +#include "includes.h" +#include "lib/tdb/include/tdb.h" +#include "system/time.h" +#include "system/shmem.h" +#include "system/filesys.h" +#endif + +#ifndef u32 +#define u32 unsigned +#endif + +typedef u32 tdb_len_t; +typedef u32 tdb_off_t; + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_ALIGNMENT 4 +#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) +#define DEFAULT_HASH_SIZE 131 +#define TDB_PAGE_SIZE 0x2000 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1) + + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) tdb->log_fn x + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifndef discard_const_p +# if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const(ptr) ((void *)((intptr_t)(ptr))) +# else +# define discard_const(ptr) ((void *)(ptr)) +# endif +# define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) + +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) + + +/* the body of the database is made of one list_struct for the free space + plus a separate data list for each hash value */ +struct list_struct { + tdb_off_t next; /* offset of the next record in the list */ + tdb_len_t rec_len; /* total byte length of record */ + tdb_len_t key_len; /* byte length of key */ + tdb_len_t data_len; /* byte length of data */ + u32 full_hash; /* the full 32 bit hash of the key */ + u32 magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + u32 totalsize; (tailer) + } + */ +}; + + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + u32 version; /* version of the code */ + u32 hash_size; /* number of hash entries */ + tdb_off_t rwlocks; + tdb_off_t reserved[31]; +}; + +struct tdb_lock_type { + u32 count; + u32 ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + u32 off; + u32 hash; +}; + + +struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len_t map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + struct tdb_lock_type *locked; /* array of chain locks */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + u32 flags; /* the flags passed to tdb_open */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ + unsigned int (*hash_fn)(TDB_DATA *key); + int open_flags; /* flags used in the open - needed by reopen */ + struct tdb_transaction *transaction; +}; + + +/* + internal prototypes +*/ +int tdb_munmap(struct tdb_context *tdb); +void tdb_mmap(struct tdb_context *tdb); +int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv); +int tdb_write(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len); +int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe); +int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_unlock(struct tdb_context *tdb, int list, int ltype); +int tdb_expand(struct tdb_context *tdb, tdb_off_t size); +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe); +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +void *tdb_convert(void *buf, u32 size); +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec); +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, + struct list_struct *rec); +void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain); + diff --git a/source4/lib/tdb/common/tdbutil.c b/source4/lib/tdb/common/tdbutil.c index df9ce4e238..327555db10 100644 --- a/source4/lib/tdb/common/tdbutil.c +++ b/source4/lib/tdb/common/tdbutil.c @@ -1,7 +1,9 @@ /* Unix SMB/CIFS implementation. + tdb utility functions - Copyright (C) Andrew Tridgell 1992-1998 + + Copyright (C) Andrew Tridgell 1992-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 @@ -17,6 +19,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + NOTE: these utility functions are specific to Samba, and are not part + of the core tdb code +*/ #include "includes.h" #include "lib/tdb/include/tdbutil.h" @@ -36,7 +42,7 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) { TDB_DATA ret; - ret.dptr = discard_const_p(char, dptr); + ret.dptr = discard_const_p(unsigned char, dptr); ret.dsize = dsize; return ret; } @@ -45,7 +51,7 @@ static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) Lock a chain by string. Return -1 if lock failed. ****************************************************************************/ -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -56,7 +62,7 @@ int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) Unlock a chain by string. ****************************************************************************/ -void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -67,7 +73,7 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Read lock a chain by string. Return -1 if lock failed. ****************************************************************************/ -int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) +int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -78,7 +84,7 @@ int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval) Read unlock a chain by string. ****************************************************************************/ -void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) +void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval) { TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); @@ -91,7 +97,7 @@ void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval) Output is int32_t in native byte order. ****************************************************************************/ -int32_t tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) +int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, const char *keyval, size_t len) { TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; @@ -113,7 +119,7 @@ int32_t tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len) Output is int32_t in native byte order. ****************************************************************************/ -int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr) { return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); } @@ -123,7 +129,7 @@ int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr) Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32_t v) +int tdb_store_int32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, int32_t v) { TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; @@ -141,7 +147,7 @@ int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int Input is int32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v) +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v) { return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); } @@ -151,7 +157,7 @@ int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v) Output is uint32_t in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32_t *value) +BOOL tdb_fetch_uint32_byblob(struct tdb_context *tdb, const char *keyval, size_t len, uint32_t *value) { TDB_DATA key = make_tdb_data(keyval, len); TDB_DATA data; @@ -172,7 +178,7 @@ BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, u Output is uint32_t in native byte order. ****************************************************************************/ -BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t *value) +BOOL tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value) { return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); } @@ -182,7 +188,7 @@ BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t *value) Input is uint32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32_t value) +BOOL tdb_store_uint32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, uint32_t value) { TDB_DATA key = make_tdb_data(keystr, len); TDB_DATA data; @@ -204,7 +210,7 @@ BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, u Input is uint32_t in native byte order. Output in tdb is in little-endian. ****************************************************************************/ -BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t value) +BOOL tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value) { return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); } @@ -213,7 +219,7 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t value) on failure. ****************************************************************************/ -int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -225,7 +231,7 @@ int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int free() on the result dptr. ****************************************************************************/ -TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -236,7 +242,7 @@ TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) Delete an entry using a null terminated string key. ****************************************************************************/ -int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) +int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -247,7 +253,7 @@ int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) Atomic integer change. Returns old value. To create, set initial value in *oldval. ****************************************************************************/ -int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *oldval, int32_t change_val) +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val) { int32_t val; int32_t ret = -1; @@ -288,7 +294,7 @@ int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *o Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. ****************************************************************************/ -BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) +BOOL tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) { uint32_t val; BOOL ret = False; @@ -326,6 +332,18 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32_t *ol return ret; } +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + /**************************************************************************** Useful pair of routines for packing/unpacking data consisting of integers and strings. @@ -345,6 +363,7 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) char *buf0 = buf; const char *fmt0 = fmt; int bufsize0 = bufsize; + tdb_log_func log_fn = tdb_log_fn(tdb); va_start(ap, fmt); @@ -399,8 +418,8 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) } break; default: - tdb->log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n", - c, fmt); + log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n", + c, fmt); len = 0; break; } @@ -414,8 +433,8 @@ size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_end(ap); - tdb->log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); } @@ -439,6 +458,7 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) char *buf0 = buf; const char *fmt0 = fmt; int bufsize0 = bufsize; + tdb_log_func log_fn = tdb_log_fn(tdb); va_start(ap, fmt); @@ -506,8 +526,8 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) memcpy(*b, buf+4, *i); break; default: - tdb->log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", - c, fmt); + log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + c, fmt); len = 0; break; @@ -519,91 +539,11 @@ int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) va_end(ap); - tdb->log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); return PTR_DIFF(buf, buf0); no_space: return -1; } - -/**************************************************************************** - Allow tdb_delete to be used as a tdb_traversal_fn. -****************************************************************************/ - -int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) -{ - return tdb_delete(the_tdb, key); -} - - - -/** - * Search across the whole tdb for keys that match the given pattern - * return the result as a list of keys - * - * @param tdb pointer to opened tdb file context - * @param pattern searching pattern used by fnmatch(3) functions - * - * @return list of keys found by looking up with given pattern - **/ -TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) -{ - TDB_DATA key, next; - TDB_LIST_NODE *list = NULL; - TDB_LIST_NODE *rec = NULL; - - for (key = tdb_firstkey(tdb); key.dptr; key = next) { - /* duplicate key string to ensure null-termination */ - char *key_str = (char*) strndup(key.dptr, key.dsize); -#if 0 - if (!key_str) { - tdb->log_fn(tdb, 0, "tdb_search_keys: strndup() failed!\n"); - smb_panic("strndup failed!\n"); - } -#endif - tdb->log_fn(tdb, 18, "checking %s for match to pattern %s\n", key_str, pattern); - - next = tdb_nextkey(tdb, key); - - /* do the pattern checking */ - if (fnmatch(pattern, key_str, 0) == 0) { - rec = (TDB_LIST_NODE*) malloc(sizeof(*rec)); - ZERO_STRUCTP(rec); - - rec->node_key = key; - - DLIST_ADD_END(list, rec, TDB_LIST_NODE *); - - tdb->log_fn(tdb, 18, "checking %s matched pattern %s\n", key_str, pattern); - } else { - free(key.dptr); - } - - /* free duplicated key string */ - free(key_str); - } - - return list; - -} - - -/** - * Free the list returned by tdb_search_keys - * - * @param node list of results found by tdb_search_keys - **/ -void tdb_search_list_free(TDB_LIST_NODE* node) -{ - TDB_LIST_NODE *next_node; - - while (node) { - next_node = node->next; - SAFE_FREE(node->node_key.dptr); - SAFE_FREE(node); - node = next_node; - } -} diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c new file mode 100644 index 0000000000..d14be355a2 --- /dev/null +++ b/source4/lib/tdb/common/traverse.c @@ -0,0 +1,274 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ +static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, + struct list_struct *rec) +{ + int want_next = (tlock->off != 0); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (!tlock->off && tlock->hash != 0) { + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then thats OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). + */ + tdb_next_hash_chain(tdb, &tlock->hash); + if (tlock->hash == tdb->header.hash_size) { + continue; + } + } + + if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) + return -1; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (tdb_unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off_t current; + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + + /* Detect infinite loops. From "Shlomi Yaakobovich" . */ + if (tlock->off == rec->next) { + TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); + goto fail; + } + + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (tdb_lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (!tdb->read_only && + tdb_do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, F_WRLCK); + want_next = 0; + } + /* We finished iteration without finding anything */ + return TDB_ERRCODE(TDB_SUCCESS, 0); + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); + return -1; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private) +{ + TDB_DATA key, dbuf; + struct list_struct rec; + struct tdb_traverse_lock tl = { NULL, 0, 0 }; + int ret, count = 0; + + /* This was in the initializaton, above, but the IRIX compiler + * did not like it. crh + */ + tl.next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = &tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) + goto out; + if (tdb_unlock_record(tdb, tl.off) != 0) + TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { + ret = -1; + goto out; + } + if (fn && fn(tdb, key, dbuf, private)) { + /* They want us to terminate traversal */ + ret = count; + if (tdb_unlock_record(tdb, tl.off) != 0) { + TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + tdb->travlocks.next = tl.next; + SAFE_FREE(key.dptr); + return count; + } + SAFE_FREE(key.dptr); + } +out: + tdb->travlocks.next = tl.next; + if (ret < 0) + return -1; + else + return count; +} + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(struct tdb_context *tdb) +{ + TDB_DATA key; + struct list_struct rec; + + /* release any old lock */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) + return tdb_null; + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) +{ + u32 oldhash; + TDB_DATA key = tdb_null; + struct list_struct rec; + unsigned char *k = NULL; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK)) + return tdb_null; + if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + return tdb_null; + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec); + if (!tdb->travlocks.off) + return tdb_null; + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) + TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + return key; +} + diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index cea67fe6e7..d45bbe4383 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,3 +1,4 @@ +AC_CHECK_FUNCS(mmap pread pwrite) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtdb,YES) diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index 60c41f8bb2..ddb57acf0d 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -3,9 +3,9 @@ [SUBSYSTEM::LIBTDB] INIT_OBJ_FILES = \ lib/tdb/common/tdb.o -ADD_OBJ_FILES = \ - lib/tdb/common/tdbutil.o \ - lib/tdb/common/spinlock.o +ADD_OBJ_FILES = lib/tdb/common/dump.o lib/tdb/common/io.o lib/tdb/common/lock.o \ + lib/tdb/common/open.o lib/tdb/common/traverse.o lib/tdb/common/freelist.o \ + lib/tdb/common/error.o lib/tdb/common/tdbutil.o NOPROTO=YES REQUIRED_SUBSYSTEMS = \ LIBREPLACE diff --git a/source4/lib/tdb/configure.in b/source4/lib/tdb/configure.in index b47b43f0ed..9ff8e23bf1 100644 --- a/source4/lib/tdb/configure.in +++ b/source4/lib/tdb/configure.in @@ -1,6 +1,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(include/tdb.h) +AC_CONFIG_HEADER(include/tdbconfig.h) AC_PROG_CC AC_FUNC_MMAP sinclude(config.m4) diff --git a/source4/lib/tdb/include/spinlock.h b/source4/lib/tdb/include/spinlock.h deleted file mode 100644 index 967fe37457..0000000000 --- a/source4/lib/tdb/include/spinlock.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __SPINLOCK_H__ -#define __SPINLOCK_H__ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "tdb.h" - -#ifdef USE_SPINLOCKS - -#define RWLOCK_BIAS 0x1000UL - -/* OS SPECIFIC */ -#define MAX_BUSY_LOOPS 1000 -#undef USE_SCHED_YIELD - -/* ARCH SPECIFIC */ -/* We should make sure these are padded to a cache line */ -#if defined(SPARC_SPINLOCKS) -typedef volatile char spinlock_t; -#elif defined(POWERPC_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#elif defined(INTEL_SPINLOCKS) -typedef volatile int spinlock_t; -#elif defined(MIPS_SPINLOCKS) -typedef volatile unsigned long spinlock_t; -#else -#error Need to implement spinlock code in spinlock.h -#endif - -typedef struct { - spinlock_t lock; - volatile int count; -} tdb_rwlock_t; - -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); - -#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t)) - -#else /* !USE_SPINLOCKS */ -#if 0 -#define tdb_create_rwlocks(fd, hash_size) 0 -#define tdb_spinlock(tdb, list, rw_type) (-1) -#define tdb_spinunlock(tdb, list, rw_type) (-1) -#else -int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type); -int tdb_create_rwlocks(int fd, unsigned int hash_size); -#endif -int tdb_clear_spinlocks(TDB_CONTEXT *tdb); -#define TDB_SPINLOCK_SIZE(hash_size) 0 - -#endif - -#endif diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 846b157758..cc3f3c18d8 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -53,99 +53,58 @@ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, TDB_ERR_NOEXIST}; -#ifndef u32 -#define u32 unsigned -#endif - typedef struct TDB_DATA { - char *dptr; + unsigned char *dptr; size_t dsize; } TDB_DATA; -typedef u32 tdb_len; -typedef u32 tdb_off; - -/* this is stored at the front of every database */ -struct tdb_header { - char magic_food[32]; /* for /etc/magic */ - u32 version; /* version of the code */ - u32 hash_size; /* number of hash entries */ - tdb_off rwlocks; - tdb_off reserved[31]; -}; - -struct tdb_lock_type { - u32 count; - u32 ltype; -}; - -struct tdb_traverse_lock { - struct tdb_traverse_lock *next; - u32 off; - u32 hash; -}; - #ifndef PRINTF_ATTRIBUTE #define PRINTF_ATTRIBUTE(a,b) #endif /* this is the context structure that is returned from a db open */ -typedef struct tdb_context { - char *name; /* the name of the database */ - void *map_ptr; /* where it is currently mapped */ - int fd; /* open file descriptor for the database */ - tdb_len map_size; /* how much space has been mapped */ - int read_only; /* opened read-only */ - struct tdb_lock_type *locked; /* array of chain locks */ - enum TDB_ERROR ecode; /* error code for last tdb error */ - struct tdb_header header; /* a cached copy of the header */ - u32 flags; /* the flags passed to tdb_open */ - struct tdb_traverse_lock travlocks; /* current traversal locks */ - struct tdb_context *next; /* all tdbs to avoid multiple opens */ - dev_t device; /* uniquely identifies this tdb */ - ino_t inode; /* uniquely identifies this tdb */ - void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ - u32 (*hash_fn)(TDB_DATA *key); - int open_flags; /* flags used in the open - needed by reopen */ -} TDB_CONTEXT; - -typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); -typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...); -typedef u32 (*tdb_hash_func)(TDB_DATA *key); - -TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags, +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, int , const char *, ...); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode); -TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, tdb_log_func log_fn, tdb_hash_func hash_fn); -int tdb_reopen(TDB_CONTEXT *tdb); +int tdb_reopen(struct tdb_context *tdb); int tdb_reopen_all(void); -void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func); -enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb); -const char *tdb_errorstr(TDB_CONTEXT *tdb); -TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); -int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf); -int tdb_close(TDB_CONTEXT *tdb); -TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); -TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *); -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_lockall(TDB_CONTEXT *tdb); -void tdb_unlockall(TDB_CONTEXT *tdb); +void tdb_logging_function(struct tdb_context *tdb, tdb_log_func); +enum TDB_ERROR tdb_error(struct tdb_context *tdb); +const char *tdb_errorstr(struct tdb_context *tdb); +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(struct tdb_context *tdb); +TDB_DATA tdb_firstkey(struct tdb_context *tdb); +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key); +int tdb_lockall(struct tdb_context *tdb); +void tdb_unlockall(struct tdb_context *tdb); +const char *tdb_name(struct tdb_context *tdb); +int tdb_fd(struct tdb_context *tdb); +tdb_log_func tdb_log_fn(struct tdb_context *tdb); /* Low level locking functions: use with care */ -int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key); -int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key); +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); /* Debug functions. Not used in production. */ -void tdb_dump_all(TDB_CONTEXT *tdb); -int tdb_printfreelist(TDB_CONTEXT *tdb); +void tdb_dump_all(struct tdb_context *tdb); +int tdb_printfreelist(struct tdb_context *tdb); extern TDB_DATA tdb_null; @@ -153,6 +112,4 @@ extern TDB_DATA tdb_null; } #endif -#include "spinlock.h" - #endif /* tdb.h */ diff --git a/source4/lib/tdb/include/tdbconfig.h.in b/source4/lib/tdb/include/tdbconfig.h.in new file mode 100644 index 0000000000..c4f42af803 --- /dev/null +++ b/source4/lib/tdb/include/tdbconfig.h.in @@ -0,0 +1,19 @@ +/* include/tdbconfig.h.in. Generated automatically from configure.in by autoheader 2.13. */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the mmap function. */ +#undef HAVE_MMAP + +/* Define if you have the pread function. */ +#undef HAVE_PREAD + +/* Define if you have the pwrite function. */ +#undef HAVE_PWRITE + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H diff --git a/source4/lib/tdb/include/tdbutil.h b/source4/lib/tdb/include/tdbutil.h index 2f7c0ec234..02802c958d 100644 --- a/source4/lib/tdb/include/tdbutil.h +++ b/source4/lib/tdb/include/tdbutil.h @@ -23,7 +23,6 @@ #include "tdb.h" - /* single node of a list returned by tdb_search_keys */ typedef struct keys_node { @@ -32,20 +31,20 @@ typedef struct keys_node } TDB_LIST_NODE; -TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); +TDB_LIST_NODE *tdb_search_keys(struct tdb_context*, const char*); void tdb_search_list_free(TDB_LIST_NODE*); -int32_t tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32_t *oldval, int32_t change_val); -int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval); -void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval); -int32_t tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr); -BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t value); -int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32_t v); -BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32_t *value); -int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val); +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval); +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval); +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr); +BOOL tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value); +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v); +BOOL tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value); +int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); -int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags); -TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr); -int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...); -size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...); +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags); +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr); +int tdb_unpack(struct tdb_context *tdb, char *buf, int bufsize, const char *fmt, ...); +size_t tdb_pack(struct tdb_context *tdb, char *buf, int bufsize, const char *fmt, ...); #endif /* __TDBUTIL_H__ */ diff --git a/source4/lib/tdb/tools/tdbdump.c b/source4/lib/tdb/tools/tdbdump.c index 774093dbc0..9122551a0a 100644 --- a/source4/lib/tdb/tools/tdbdump.c +++ b/source4/lib/tdb/tools/tdbdump.c @@ -57,7 +57,7 @@ static void print_data(TDB_DATA d) } } -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { printf("{\n"); printf("key = \""); @@ -72,7 +72,7 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *stat static int dump_tdb(const char *fname) { - TDB_CONTEXT *tdb; + struct tdb_context *tdb; tdb = tdb_open(fname, 0, 0, O_RDONLY, 0); if (!tdb) { diff --git a/source4/lib/tdb/tools/tdbtest.c b/source4/lib/tdb/tools/tdbtest.c index 4f7f7faafc..edf12ecfdd 100644 --- a/source4/lib/tdb/tools/tdbtest.c +++ b/source4/lib/tdb/tools/tdbtest.c @@ -28,7 +28,7 @@ #define DELETE_PROB 7 #define STORE_PROB 5 -static TDB_CONTEXT *db; +static struct tdb_context *db; static GDBM_FILE gdbm; struct timeval tp1,tp2; @@ -52,9 +52,9 @@ static void fatal(const char *why) } #ifdef PRINTF_ATTRIBUTE -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); #endif -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) { va_list ap; @@ -191,7 +191,7 @@ static void addrec_gdbm(void) free(d); } -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { #if 0 printf("[%s] [%s]\n", key.dptr, dbuf.dptr); diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 50486122bc..5a8c871699 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -59,9 +59,9 @@ typedef struct connections_data { time_t start; } connections_data; -static TDB_CONTEXT *tdb; +static struct tdb_context *tdb; -static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); +static int print_rec(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); static void print_asc(unsigned char *buf,int len) { @@ -207,9 +207,9 @@ static void insert_tdb(void) return; } - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = strlen(k)+1; - dbuf.dptr = d; + dbuf.dptr = (unsigned char *)d; dbuf.dsize = strlen(d)+1; if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) { @@ -228,9 +228,9 @@ static void store_tdb(void) return; } - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = strlen(k)+1; - dbuf.dptr = d; + dbuf.dptr = (unsigned char *)d; dbuf.dsize = strlen(d)+1; printf("Storing key:\n"); @@ -251,7 +251,7 @@ static void show_tdb(void) return; } - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = strlen(k)+1; dbuf = tdb_fetch(tdb, key); @@ -284,7 +284,7 @@ static void delete_tdb(void) return; } - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = strlen(k)+1; if (tdb_delete(tdb, key) != 0) { @@ -297,7 +297,7 @@ static void move_rec(void) char *k = get_token(1); char *file = get_token(0); TDB_DATA key, dbuf; - TDB_CONTEXT *dst_tdb; + struct tdb_context *dst_tdb; if (!k) { help(); @@ -309,7 +309,7 @@ static void move_rec(void) return; } - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = strlen(k)+1; dbuf = tdb_fetch(tdb, key); @@ -343,7 +343,7 @@ static void move_rec(void) return; } -static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +static int print_rec(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { printf("\nkey %d bytes\n", key.dsize); print_asc(key.dptr, key.dsize); @@ -352,7 +352,7 @@ static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *st return 0; } -static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +static int print_key(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { print_asc(key.dptr, key.dsize); printf("\n"); @@ -361,7 +361,7 @@ static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *st static int total_bytes; -static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +static int traverse_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { total_bytes += dbuf.dsize; return 0; @@ -389,13 +389,13 @@ static char *tdb_getline(char *prompt) return p?line:NULL; } -static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, +static int do_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { return tdb_delete(the_tdb, key); } -static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +static void first_record(struct tdb_context *the_tdb, TDB_DATA *pkey) { TDB_DATA dbuf; *pkey = tdb_firstkey(the_tdb); @@ -408,7 +408,7 @@ static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) } } -static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) +static void next_record(struct tdb_context *the_tdb, TDB_DATA *pkey) { TDB_DATA dbuf; *pkey = tdb_nextkey(the_tdb, *pkey); diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 687d304b70..0cf82fa5a5 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -39,12 +39,12 @@ #define DATALEN 100 #define LOCKLEN 20 -static TDB_CONTEXT *db; +static struct tdb_context *db; #ifdef PRINTF_ATTRIBUTE -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); #endif -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) +static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) { va_list ap; @@ -81,7 +81,7 @@ static char *randbuf(int len) return buf; } -static int cull_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, +static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { if (random() % CULL_PROB == 0) { @@ -104,13 +104,13 @@ static void addrec_db(void) d = randbuf(dlen); s = randbuf(slen); - key.dptr = k; + key.dptr = (unsigned char *)k; key.dsize = klen+1; - data.dptr = d; + data.dptr = (unsigned char *)d; data.dsize = dlen+1; - lockkey.dptr = s; + lockkey.dptr = (unsigned char *)s; lockkey.dsize = slen+1; #if REOPEN_PROB @@ -174,7 +174,7 @@ next: free(s); } -static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, +static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { tdb_delete(tdb, key); -- cgit From 48b513fd2388840454d257cd110b576b08fb2abd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 16 Sep 2005 07:24:36 +0000 Subject: r10258: Fix an unused/duplicate local variable. (This used to be commit 360be7028c2244391cdd9ed6d156cec8dab9e9e9) --- source4/lib/tdb/common/io.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index dbcc83119c..97da809bc6 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -124,8 +124,6 @@ void *tdb_convert(void *buf, u32 size) /* read a lump of data at a specified offset, maybe convert */ int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv) { - ssize_t ret; - if (tdb_oob(tdb, off + len, 0) != 0) { return -1; } -- cgit From 5c708830bc07e1b59c063ae1c04b8fdf2b972318 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 16 Sep 2005 20:54:57 +0000 Subject: r10277: do not ovverride LIKE, thanks to derrel I found out how to do the same thing with a harmless user function (This used to be commit 158693b4064bd731aa4f6cdb2fde51d7aa596cf5) --- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 50 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 1a855e0850..f136fb7072 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -388,7 +388,7 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " "WHERE norm_attr_name = '%q' " - "AND norm_attr_value LIKE '>=%q' ESCAPE '%q' ", + "AND ldap_compare(norm_attr_value, '>=', '%q', '%q') ", attr, value.data, attr); @@ -407,7 +407,7 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " "WHERE norm_attr_name = '%q' " - "AND norm_attr_value LIKE '<=%q' ESCAPE '%q' ", + "AND ldap_compare(norm_attr_value, '<=', '%q', '%q') ", attr, value.data, attr); @@ -439,7 +439,7 @@ static char *parsetree_to_sql(struct ldb_module *module, return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " "WHERE norm_attr_name = '%q' " - "AND norm_attr_value LIKE '~%q' ESCAPE '%q' ", + "AND ldap_compare(norm_attr_value, '~%', 'q', '%q') ", attr, value.data, attr); @@ -606,34 +606,33 @@ query_int(const struct lsqlite3_private * lsqlite3, /* * This is a bad hack to support ldap style comparisons whithin sqlite. - * This function substitues the X LIKE Y ESCAPE Z expression - * X is an expression + value to compare against (eg: ">=test") - * Y is the attribute in the row currently under test - * Z is the attribute name the value of which we want to test + * val is the attribute in the row currently under test + * func is the desired test "<=" ">=" "~" ":" + * cmp is the value to compare against (eg: "test") + * attr is the attribute name the value of which we want to test */ static void lsqlite3_compare(sqlite3_context *ctx, int argc, sqlite3_value **argv) { struct ldb_context *ldb = (struct ldb_context *)sqlite3_user_data(ctx); - const unsigned char *X = sqlite3_value_text(argv[0]); - const unsigned char *Y = sqlite3_value_text(argv[1]); - const unsigned char *Z = sqlite3_value_text(argv[2]); - const unsigned char *p; + const unsigned char *val = sqlite3_value_text(argv[0]); + const unsigned char *func = sqlite3_value_text(argv[1]); + const unsigned char *cmp = sqlite3_value_text(argv[2]); + const unsigned char *attr = sqlite3_value_text(argv[3]); const struct ldb_attrib_handler *h; struct ldb_val valX; struct ldb_val valY; int ret; - switch (X[0]) { + switch (func[0]) { /* greater */ case '>': /* >= */ - p = &(X[2]); - h = ldb_attrib_handler(ldb, Z); - valX.data = p; - valX.length = strlen(p); - valY.data = Y; - valY.length = strlen(Y); + h = ldb_attrib_handler(ldb, attr); + valX.data = cmp; + valX.length = strlen(cmp); + valY.data = val; + valY.length = strlen(val); ret = h->comparison_fn(ldb, ldb, &valY, &valX); if (ret >= 0) sqlite3_result_int(ctx, 1); @@ -643,12 +642,11 @@ static void lsqlite3_compare(sqlite3_context *ctx, int argc, /* lesser */ case '<': /* <= */ - p = &(X[2]); - h = ldb_attrib_handler(ldb, Z); - valX.data = p; - valX.length = strlen(p); - valY.data = Y; - valY.length = strlen(Y); + h = ldb_attrib_handler(ldb, attr); + valX.data = cmp; + valX.length = strlen(cmp); + valY.data = val; + valY.length = strlen(val); ret = h->comparison_fn(ldb, ldb, &valY, &valX); if (ret <= 0) sqlite3_result_int(ctx, 1); @@ -1694,8 +1692,8 @@ static int initialize(struct lsqlite3_private *lsqlite3, /* Create a function, callable from sql, to perform various comparisons */ if ((ret = sqlite3_create_function(lsqlite3->sqlite, /* handle */ - "like", /* function name */ - 3, /* number of args */ + "ldap_compare", /* function name */ + 4, /* number of args */ SQLITE_ANY, /* preferred text type */ ldb , /* user data */ lsqlite3_compare, /* called func */ -- cgit From 86acf90e4335f79cd34e400d687930d922332d8f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Sep 2005 13:08:49 +0000 Subject: r10294: Generate Makefile directly rather then thru Makefile.in. Autoconf substitution variables are now no longer used. This is one more step towards a (hopefully) perl-based configure (This used to be commit 6f9956a1dd870c0669c288b0fe72b7b1c8773dd0) --- source4/lib/registry/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 4cf73bf66a..87e0779007 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -18,7 +18,7 @@ INIT_OBJ_FILES = lib/registry/tdr_regf.o lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c lib/registry/tdr_regf.c: lib/registry/regf.idl - @CPP="$(CPP)" $(PERL) pidl/pidl --header --outputdir=lib/registry --tdr-header --tdr-parser -- lib/registry/regf.idl + @CPP="$(CPP)" pidl/pidl $(PIDL_ARGS) --header --outputdir=lib/registry --tdr-header --tdr-parser -- lib/registry/regf.idl ################################################ # Start MODULE registry_w95 -- cgit From 8919d6bf9a88ce9ac43dae61989c33082c984b66 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 17 Sep 2005 19:25:50 +0000 Subject: r10299: remove the public (un)lock functions and introduce a transaction based private ldb API ldb_sqlite3 is already working with this model and ldb_tdb will do as soon as tridge finishes the tdb transaction code. currently the transactions are always implicit and wrap any single ldb API call except searching, the transaction functions are currently not made public on purpose. Simo. (This used to be commit 1da4ac2cdcb7e54076f85242a93784260dced918) --- source4/lib/ldb/common/ldb.c | 54 ++++++---- source4/lib/ldb/common/ldb_modules.c | 8 +- source4/lib/ldb/include/ldb_private.h | 8 +- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 42 +++----- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 44 +++------ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 159 +++++++++++------------------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 33 +++++-- source4/lib/ldb/modules/ldb_map.c | 28 +++--- source4/lib/ldb/modules/rdn_name.c | 32 +++--- source4/lib/ldb/modules/schema.c | 28 +++--- source4/lib/ldb/modules/skel.c | 32 +++--- source4/lib/ldb/modules/timestamps.c | 32 +++--- source4/lib/ldb/tools/ldbtest.c | 7 +- 13 files changed, 232 insertions(+), 275 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 25e7bee66b..ae71f08713 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -105,6 +105,22 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co return 0; } +/* + start a transaction +*/ +static int ldb_start_trans(struct ldb_context *ldb) +{ + return ldb->modules->ops->start_transaction(ldb->modules); +} + +/* + end a transaction +*/ +static int ldb_end_trans(struct ldb_context *ldb, int status) +{ + return ldb->modules->ops->end_transaction(ldb->modules, status); +} + /* search the database given a LDAP-like search expression @@ -146,7 +162,11 @@ int ldb_search_bytree(struct ldb_context *ldb, int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->modules->ops->add_record(ldb->modules, message); + int status = ldb_start_trans(ldb); + if (status != 0) return status; + + status = ldb->modules->ops->add_record(ldb->modules, message); + return ldb_end_trans(ldb, status); } /* @@ -155,7 +175,11 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { - return ldb->modules->ops->modify_record(ldb->modules, message); + int status = ldb_start_trans(ldb); + if (status != 0) return status; + + status = ldb->modules->ops->modify_record(ldb->modules, message); + return ldb_end_trans(ldb, status); } @@ -164,7 +188,11 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) { - return ldb->modules->ops->delete_record(ldb->modules, dn); + int status = ldb_start_trans(ldb); + if (status != 0) return status; + + status = ldb->modules->ops->delete_record(ldb->modules, dn); + return ldb_end_trans(ldb, status); } /* @@ -172,23 +200,11 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) */ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { - return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); -} + int status = ldb_start_trans(ldb); + if (status != 0) return status; -/* - create a named lock -*/ -int ldb_lock(struct ldb_context *ldb, const char *lockname) -{ - return ldb->modules->ops->named_lock(ldb->modules, lockname); -} - -/* - release a named lock -*/ -int ldb_unlock(struct ldb_context *ldb, const char *lockname) -{ - return ldb->modules->ops->named_unlock(ldb->modules, lockname); + status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); + return ldb_end_trans(ldb, status); } /* diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 20e8ad061e..29bc8264e9 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -306,20 +306,20 @@ int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn return module->next->ops->rename_record(module->next, olddn, newdn); } -int ldb_next_named_lock(struct ldb_module *module, const char *lockname) +int ldb_next_start_trans(struct ldb_module *module) { if (!module->next) { return -1; } - return module->next->ops->named_lock(module->next, lockname); + return module->next->ops->start_transaction(module->next); } -int ldb_next_named_unlock(struct ldb_module *module, const char *lockname) +int ldb_next_end_trans(struct ldb_module *module, int status) { if (!module->next) { return -1; } - return module->next->ops->named_unlock(module->next, lockname); + return module->next->ops->end_transaction(module->next, status); } const char *ldb_next_errstring(struct ldb_module *module) diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index f5b50f5fc0..e55a19c28c 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -64,8 +64,8 @@ struct ldb_module_ops { int (*modify_record)(struct ldb_module *, const struct ldb_message *); int (*delete_record)(struct ldb_module *, const struct ldb_dn *); int (*rename_record)(struct ldb_module *, const struct ldb_dn *, const struct ldb_dn *); - int (*named_lock)(struct ldb_module *, const char *); - int (*named_unlock)(struct ldb_module *, const char *); + int (*start_transaction)(struct ldb_module *); + int (*end_transaction)(struct ldb_module *, int); const char * (*errstring)(struct ldb_module *); }; @@ -135,8 +135,8 @@ int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *mes int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message); int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn); int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn); -int ldb_next_named_lock(struct ldb_module *module, const char *lockname); -int ldb_next_named_unlock(struct ldb_module *module, const char *lockname); +int ldb_next_start_trans(struct ldb_module *module); +int ldb_next_end_trans(struct ldb_module *module, int status); const char *ldb_next_errstring(struct ldb_module *module); /* The following definitions come from lib/ldb/common/ldb_debug.c */ diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 3d47863067..d4239c0f72 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -362,30 +362,18 @@ static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg) return ret; } -static int ildb_lock(struct ldb_module *module, const char *lockname) +static int ildb_start_trans(struct ldb_module *module) { - int ret = 0; - - if (lockname == NULL) { - return -1; - } - /* TODO implement a local locking mechanism here */ - return ret; + return 0; } -static int ildb_unlock(struct ldb_module *module, const char *lockname) +static int ildb_end_trans(struct ldb_module *module, int status) { - int ret = 0; - - if (lockname == NULL) { - return -1; - } - - /* TODO implement a local unlocking mechanism here */ + /* TODO implement a local transaction mechanism here */ - return ret; + return status; } /* @@ -403,16 +391,16 @@ static const char *ildb_errstring(struct ldb_module *module) static const struct ldb_module_ops ildb_ops = { - .name = "ldap", - .search = ildb_search, - .search_bytree = ildb_search_bytree, - .add_record = ildb_add, - .modify_record = ildb_modify, - .delete_record = ildb_delete, - .rename_record = ildb_rename, - .named_lock = ildb_lock, - .named_unlock = ildb_unlock, - .errstring = ildb_errstring + .name = "ldap", + .search = ildb_search, + .search_bytree = ildb_search_bytree, + .add_record = ildb_add, + .modify_record = ildb_modify, + .delete_record = ildb_delete, + .rename_record = ildb_rename, + .start_transaction = ildb_start_trans, + .end_transaction = ildb_end_trans, + .errstring = ildb_errstring }; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 2da4f1af8e..39f56dba0e 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -450,30 +450,18 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) return ret; } -static int lldb_lock(struct ldb_module *module, const char *lockname) +static int lldb_start_trans(struct ldb_module *module) { - int ret = 0; - - if (lockname == NULL) { - return -1; - } + /* TODO implement a local transaction mechanism here */ - /* TODO implement a local locking mechanism here */ - - return ret; + return 0; } -static int lldb_unlock(struct ldb_module *module, const char *lockname) +static int lldb_end_trans(struct ldb_module *module, int status) { - int ret = 0; - - if (lockname == NULL) { - return -1; - } - - /* TODO implement a local unlocking mechanism here */ + /* TODO implement a local transaction mechanism here */ - return ret; + return status; } /* @@ -487,16 +475,16 @@ static const char *lldb_errstring(struct ldb_module *module) static const struct ldb_module_ops lldb_ops = { - .name = "ldap", - .search = lldb_search, - .search_bytree = lldb_search_bytree, - .add_record = lldb_add, - .modify_record = lldb_modify, - .delete_record = lldb_delete, - .rename_record = lldb_rename, - .named_lock = lldb_lock, - .named_unlock = lldb_unlock, - .errstring = lldb_errstring + .name = "ldap", + .search = lldb_search, + .search_bytree = lldb_search_bytree, + .add_record = lldb_add, + .modify_record = lldb_modify, + .delete_record = lldb_delete, + .rename_record = lldb_rename, + .start_transaction = lldb_start_trans, + .end_transaction = lldb_end_trans, + .errstring = lldb_errstring }; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index f136fb7072..c0adab7bc3 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -457,57 +457,6 @@ static char *parsetree_to_sql(struct ldb_module *module, return NULL; } -/* obtain a named lock */ -static int -lsqlite3_lock(struct ldb_module * module, - const char * lockname) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - -/* FIXME - if (lockname == NULL) { - return -1; - } - - if (strcmp(lockname, "transaction") == 0) { - if (lsqlite3->lock_count == 0) { - if (query_norows(lsqlite3, "BEGIN EXCLUSIVE;") != 0) { - return -1; - } - } - ++lsqlite3->lock_count; - } -*/ - return 0; -} - -/* release a named lock */ -static int -lsqlite3_unlock(struct ldb_module *module, - const char *lockname) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - -/* FIXME - if (lockname == NULL) { - return -1; - } - - if (strcmp(lockname, "transaction") == 0) { - if (lsqlite3->lock_count == 1) { - if (query_norows(lsqlite3, "COMMIT;") != 0) { - query_norows(lsqlite3, "ROLLBACK;"); - } - } else if (lsqlite3->lock_count > 0) { - --lsqlite3->lock_count; - } - } else if (strcmp(lockname, "rollback") == 0) { - query_norows(lsqlite3, "ROLLBACK;"); - } -*/ - return 0; -} - /* * query_int() * @@ -685,7 +634,7 @@ static int lsqlite3_safe_rollback(sqlite3 *sqlite) ret = sqlite3_exec(sqlite, "ROLLBACK;", NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_safe_rollback: Serious Error: %s\n", errmsg); + printf("lsqlite3_safe_rollback: Error: %s\n", errmsg); free(errmsg); } return -1; @@ -1078,7 +1027,6 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg char *dn, *ndn; char *errmsg; char *query; - int rollback = 0; int ret; int i; @@ -1115,8 +1063,6 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg if (dn == NULL || ndn == NULL) goto failed; query = lsqlite3_tprintf(local_ctx, - /* Begin the transaction */ - "BEGIN EXCLUSIVE; " /* Add new entry */ "INSERT OR ABORT INTO ldb_entry " "('dn', 'norm_dn') " @@ -1130,10 +1076,8 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg printf("lsqlite3_add: exec error: %s\n", errmsg); free(errmsg); } - lsqlite3_safe_rollback(lsqlite3->sqlite); goto failed; } - rollback = 1; eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, ndn); if (eid == -1) goto failed; @@ -1179,20 +1123,10 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg } } - ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_add: commit error: %s\n", errmsg); - free(errmsg); - } - goto failed; - } - talloc_free(local_ctx); return 0; failed: - if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); talloc_free(local_ctx); return -1; } @@ -1205,7 +1139,6 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * struct lsqlite3_private *lsqlite3 = module->private_data; long long eid; char *errmsg; - int rollback = 0; int ret; int i; @@ -1235,16 +1168,6 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * return 0; } - ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN EXCLUSIVE;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); - free(errmsg); - } - goto failed; - } - rollback = 1; - eid = lsqlite3_get_eid(module, msg->dn); if (eid == -1) { goto failed; @@ -1376,20 +1299,10 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * } } - ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); - free(errmsg); - } - goto failed; - } - talloc_free(local_ctx); return 0; failed: - if (rollback) lsqlite3_safe_rollback(lsqlite3->sqlite); talloc_free(local_ctx); return -1; } @@ -1419,14 +1332,10 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) if (eid == -1) goto failed; query = lsqlite3_tprintf(local_ctx, - /* Begin the transaction */ - "BEGIN EXCLUSIVE; " /* Delete entry */ "DELETE FROM ldb_entry WHERE eid = %lld; " /* Delete attributes */ - "DELETE FROM ldb_attribute_values WHERE eid = %lld; " - /* Commit */ - "COMMIT;", + "DELETE FROM ldb_attribute_values WHERE eid = %lld; ", eid, eid); if (query == NULL) goto failed; @@ -1436,7 +1345,6 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) printf("lsqlite3_delete: error getting eid: %s\n", errmsg); free(errmsg); } - lsqlite3_safe_rollback(lsqlite3->sqlite); goto failed; } @@ -1500,6 +1408,49 @@ failed: talloc_free(local_ctx); return -1; } + +static int lsqlite3_start_trans(struct ldb_module * module) +{ + int ret; + char *errmsg; + struct lsqlite3_private * lsqlite3 = module->private_data; + + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN IMMEDIATE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_start_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + + return 0; +} + +static int lsqlite3_end_trans(struct ldb_module *module, int status) +{ + int ret; + char *errmsg; + struct lsqlite3_private *lsqlite3 = module->private_data; + + if (status == 0) { + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_end_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; + } + } else { + return lsqlite3_safe_rollback(lsqlite3->sqlite); + } + + return 0; +} + + + /* return extended error information */ static const char * lsqlite3_errstring(struct ldb_module *module) @@ -1799,16 +1750,16 @@ destructor(void *p) * Table of operations for the sqlite3 backend */ static const struct ldb_module_ops lsqlite3_ops = { - .name = "sqlite", - .search = lsqlite3_search, - .search_bytree = lsqlite3_search_bytree, - .add_record = lsqlite3_add, - .modify_record = lsqlite3_modify, - .delete_record = lsqlite3_delete, - .rename_record = lsqlite3_rename, - .named_lock = lsqlite3_lock, - .named_unlock = lsqlite3_unlock, - .errstring = lsqlite3_errstring + .name = "sqlite", + .search = lsqlite3_search, + .search_bytree = lsqlite3_search_bytree, + .add_record = lsqlite3_add, + .modify_record = lsqlite3_modify, + .delete_record = lsqlite3_delete, + .rename_record = lsqlite3_rename, + .start_transaction = lsqlite3_start_trans, + .end_transaction = lsqlite3_end_trans, + .errstring = lsqlite3_errstring }; /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 61d0f9b64a..c3f59a2dbe 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -825,6 +825,19 @@ failed: return -1; } +static int ltdb_start_trans(struct ldb_module *module) +{ + /* TODO: implement transactions */ + + return 0; +} + +static int ltdb_end_trans(struct ldb_module *module, int status) +{ + /* TODO: implement transactions */ + + return status; +} /* return extended error information @@ -840,16 +853,16 @@ static const char *ltdb_errstring(struct ldb_module *module) static const struct ldb_module_ops ltdb_ops = { - .name = "tdb", - .search = ltdb_search, - .search_bytree = ltdb_search_bytree, - .add_record = ltdb_add, - .modify_record = ltdb_modify, - .delete_record = ltdb_delete, - .rename_record = ltdb_rename, - .named_lock = ltdb_lock, - .named_unlock = ltdb_unlock, - .errstring = ltdb_errstring + .name = "tdb", + .search = ltdb_search, + .search_bytree = ltdb_search_bytree, + .add_record = ltdb_add, + .modify_record = ltdb_modify, + .delete_record = ltdb_delete, + .rename_record = ltdb_rename, + .start_transaction = ltdb_start_trans, + .end_transaction = ltdb_end_trans, + .errstring = ltdb_errstring }; diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index ba98a5f495..93ae13ffc2 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1256,14 +1256,14 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) return (mp_ret == -1 || fb_ret == -1)?-1:0; } -static int map_lock(struct ldb_module *module, const char *lockname) +static int map_start_trans(struct ldb_module *module) { - return ldb_next_named_lock(module, lockname); + return ldb_next_start_trans(module); } -static int map_unlock(struct ldb_module *module, const char *lockname) +static int map_end_trans(struct ldb_module *module, int status) { - return ldb_next_named_unlock(module, lockname); + return ldb_next_end_trans(module, status); } /* @@ -1280,16 +1280,16 @@ static const char *map_errstring(struct ldb_module *module) } static const struct ldb_module_ops map_ops = { - .name = "map", - .search = map_search, - .search_bytree = map_search_bytree, - .add_record = map_add, - .modify_record = map_modify, - .delete_record = map_delete, - .rename_record = map_rename, - .named_lock = map_lock, - .named_unlock = map_unlock, - .errstring = map_errstring + .name = "map", + .search = map_search, + .search_bytree = map_search_bytree, + .add_record = map_add, + .modify_record = map_modify, + .delete_record = map_delete, + .rename_record = map_rename, + .start_transaction = map_start_trans, + .end_transaction = map_end_trans, + .errstring = map_errstring }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 09e9c72811..ed5400176c 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -217,16 +217,16 @@ static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn return ldb_next_rename_record(module, olddn, newdn); } -static int rdn_name_lock(struct ldb_module *module, const char *lockname) +static int rdn_start_trans(struct ldb_module *module) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_lock\n"); - return ldb_next_named_lock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_start_trans\n"); + return ldb_next_start_trans(module); } -static int rdn_name_unlock(struct ldb_module *module, const char *lockname) +static int rdn_end_trans(struct ldb_module *module, int status) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_unlock\n"); - return ldb_next_named_unlock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -254,16 +254,16 @@ static int rdn_name_destructor(void *module_ctx) } static const struct ldb_module_ops rdn_name_ops = { - .name = "rdn_name", - .search = rdn_name_search, - .search_bytree = rdn_name_search_bytree, - .add_record = rdn_name_add_record, - .modify_record = rdn_name_modify_record, - .delete_record = rdn_name_delete_record, - .rename_record = rdn_name_rename_record, - .named_lock = rdn_name_lock, - .named_unlock = rdn_name_unlock, - .errstring = rdn_name_errstring + .name = "rdn_name", + .search = rdn_name_search, + .search_bytree = rdn_name_search_bytree, + .add_record = rdn_name_add_record, + .modify_record = rdn_name_modify_record, + .delete_record = rdn_name_delete_record, + .rename_record = rdn_name_rename_record, + .start_transaction = rdn_start_trans, + .end_transaction = rdn_end_trans, + .errstring = rdn_name_errstring }; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index baf038de0c..9406d54ce7 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -501,12 +501,12 @@ static int schema_rename_record(struct ldb_module *module, const struct ldb_dn * return ldb_next_rename_record(module, olddn, newdn); } -static int schema_named_lock(struct ldb_module *module, const char *name) { - return ldb_next_named_lock(module, name); +static int schema_start_trans(struct ldb_module *module) { + return ldb_next_start_trans(module); } -static int schema_named_unlock(struct ldb_module *module, const char *name) { - return ldb_next_named_unlock(module, name); +static int schema_end_trans(struct ldb_module *module, int status) { + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -533,16 +533,16 @@ static int schema_destructor(void *module_ctx) } static const struct ldb_module_ops schema_ops = { - .name = "schema", - .search = schema_search, - .search_bytree = schema_search_bytree, - .add_record = schema_add_record, - .modify_record = schema_modify_record, - .delete_record = schema_delete_record, - .rename_record = schema_rename_record, - .named_lock = schema_named_lock, - .named_unlock = schema_named_unlock, - .errstring = schema_errstring, + .name = "schema", + .search = schema_search, + .search_bytree = schema_search_bytree, + .add_record = schema_add_record, + .modify_record = schema_modify_record, + .delete_record = schema_delete_record, + .rename_record = schema_rename_record, + .start_transaction = schema_start_trans, + .end_transaction = schema_end_trans, + .errstring = schema_errstring, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 57c89a6a65..37c0417c64 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -73,16 +73,16 @@ static int skel_rename_record(struct ldb_module *module, const struct ldb_dn *ol return ldb_next_rename_record(module, olddn, newdn); } -/* named_lock */ -static int skel_named_lock(struct ldb_module *module, const char *lockname) +/* start a transaction */ +static int skel_start_trans(struct ldb_module *module) { - return ldb_next_named_lock(module, lockname); + return ldb_next_start_trans(module); } -/* named_unlock */ -static int skel_named_unlock(struct ldb_module *module, const char *lockname) +/* end a transaction */ +static int skel_end_trans(struct ldb_module *module, int status) { - return ldb_next_named_unlock(module, lockname); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -101,16 +101,16 @@ static int skel_destructor(void *module_ctx) } static const struct ldb_module_ops skel_ops = { - .name = "skel", - .search = skel_search, - .search_bytree = skel_search_bytree, - .add_record = skel_add_record, - .modify_record = skel_modify_record, - .delete_record = skel_delete_record, - .rename_record = skel_rename_record, - .named_lock = skel_named_lock, - .named_unlock = skel_named_unlock, - .errstring = skel_errstring + .name = "skel", + .search = skel_search, + .search_bytree = skel_search_bytree, + .add_record = skel_add_record, + .modify_record = skel_modify_record, + .delete_record = skel_delete_record, + .rename_record = skel_rename_record, + .start_transaction = skel_start_trans, + .end_transaction = skel_end_trans, + .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index f712505211..6687b1929d 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -215,16 +215,16 @@ static int timestamps_rename_record(struct ldb_module *module, const struct ldb_ return ldb_next_rename_record(module, olddn, newdn); } -static int timestamps_lock(struct ldb_module *module, const char *lockname) +static int timestamps_start_trans(struct ldb_module *module) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_lock\n"); - return ldb_next_named_lock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_start_trans\n"); + return ldb_next_start_trans(module); } -static int timestamps_unlock(struct ldb_module *module, const char *lockname) +static int timestamps_end_trans(struct ldb_module *module, int status) { - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_unlock\n"); - return ldb_next_named_unlock(module, lockname); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); + return ldb_next_end_trans(module, status); } /* return extended error information */ @@ -252,16 +252,16 @@ static int timestamps_destructor(void *module_ctx) } static const struct ldb_module_ops timestamps_ops = { - .name = "timestamps", - .search = timestamps_search, - .search_bytree = timestamps_search_bytree, - .add_record = timestamps_add_record, - .modify_record = timestamps_modify_record, - .delete_record = timestamps_delete_record, - .rename_record = timestamps_rename_record, - .named_lock = timestamps_lock, - .named_unlock = timestamps_unlock, - .errstring = timestamps_errstring + .name = "timestamps", + .search = timestamps_search, + .search_bytree = timestamps_search_bytree, + .add_record = timestamps_add_record, + .modify_record = timestamps_modify_record, + .delete_record = timestamps_delete_record, + .rename_record = timestamps_rename_record, + .start_transaction = timestamps_start_trans, + .end_transaction = timestamps_end_trans, + .errstring = timestamps_errstring }; diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index ef295b7411..68d3ab2484 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -64,11 +64,12 @@ static void add_records(struct ldb_context *ldb, struct ldb_message msg; int i; +#if 0 if (ldb_lock(ldb, "transaction") != 0) { printf("transaction lock failed\n"); exit(1); } - +#endif for (i=0;i Date: Sun, 18 Sep 2005 10:45:03 +0000 Subject: r10301: fix standalone compiple after tdb changes (This used to be commit acfb4b928363b00346cd8991347d992c76c981d6) --- source4/lib/ldb/Makefile.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index cb1ecae3e7..b40933bc0d 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -41,7 +41,10 @@ CFLAGS = $(CFLAGS1) $(GCOV_FLAGS) @CFLAGS@ LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) @LIBS@ -TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/spinlock.o +TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/dump.o \ + $(TDBDIR)/common/io.o $(TDBDIR)/common/lock.o \ + $(TDBDIR)/common/open.o $(TDBDIR)/common/traverse.o \ + $(TDBDIR)/common/freelist.o $(TDBDIR)/common/error.o TALLOC_OBJ=$(TALLOCDIR)/talloc.o LDB_TDB_OBJ=ldb_tdb/ldb_tdb.o \ -- cgit From eebe0c269e241404b69e385fbc135018acb5cb5e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 18 Sep 2005 10:45:28 +0000 Subject: r10302: Introduce ldap like error codes (This used to be commit cbe438be6d9b1b7182ab3e63607a2e5b2d5456fb) --- source4/lib/ldb/include/ldb_errors.h | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 source4/lib/ldb/include/ldb_errors.h (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb_errors.h b/source4/lib/ldb/include/ldb_errors.h new file mode 100644 index 0000000000..38c42280d0 --- /dev/null +++ b/source4/lib/ldb/include/ldb_errors.h @@ -0,0 +1,91 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb header + * + * Description: defines error codes following RFC 2251 ldap error codes + * + * Author: Simo Sorce + */ + +#ifndef _LDB_ERRORS_H_ +#define _LDB_ERRORS_H_ 1 + +/* + * Not all error codes make sense for ldb, + * but they are keept here for reference anyway + */ + +#define LDB_ERR_SUCCESS 0 +#define LDB_ERR_OPERATIONS_ERROR 1 +#define LDB_ERR_PROTOCOL_ERROR 2 +#define LDB_ERR_TIME_LIMIT_EXCEEDED 3 +#define LDB_ERR_SIZE_LIMIT_EXCEEDED 4 +#define LDB_ERR_COMPARE_FALSE 5 +#define LDB_ERR_COMPARE_TRUE 6 +#define LDB_ERR_AUTH_METHOD_NOT_SUPPORTED 7 +#define LDB_ERR_STRONG_AUTH_REQUIRED 8 +/* 9 RESERVED */ +#define LDB_ERR_REFERRAL 10 +#define LDB_ERR_ADMIN_LIMIT_EXCEEDED 11 +#define LDB_ERR_UNAVAILABLE_CRITICAL_EXTENSION 12 +#define LDB_ERR_CONFIDENTIALITY_REQUIRED 13 +#define LDB_ERR_SASL_BIND_IN_PROGRESS 14 +#define LDB_ERR_NO_SUCH_ATTRIBUTE 16 +#define LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE 17 +#define LDB_ERR_INAPPROPRIATE_MATCHING 18 +#define LDB_ERR_CONSTRAINT_VIOLAION 19 +#define LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS 20 +#define LDB_ERR_INVALID_ATTRIBUTE_SYNTAX 21 +/* 22-31 unused */ +#define LDB_ERR_NO_SUCH_OBJECT 32 +#define LDB_ERR_ALIAS_PROBLEM 33 +#define LDB_ERR_INVALID_DN_SYNTAX 34 +/* 53 RESERVED */ +#define LDB_ERR_ALIAS_DEREFERENCING_PROBLEM 36 +/* 37-47 unused */ +#define LDB_ERR_INAPPROPRIATE_AUTHENTICATION 48 +#define LDB_ERR_INVALID_CREDENTIALS 49 +#define LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS 50 +#define LDB_ERR_BUSY 51 +#define LDB_ERR_UNAVAILABLE 52 +#define LDB_ERR_UNWILLING_TO_PERFORM 53 +#define LDB_ERR_LOOP_DETECT 54 +/* 55-63 unused */ +#define LDB_ERR_NAMING_VIOLATION 64 +#define LDB_ERR_OBJECT_CLASS_VIOLATION 65 +#define LDB_ERR_NOT_ALLOWED_ON_NON_LEAF 66 +#define LDB_ERR_NOT_ALLOWED_ON_RDN 67 +#define LDB_ERR_ENTRY_ALREADY_EXISTS 68 +#define LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED 69 +/* 70 RESERVED FOR CLDAP */ +#define LDB_ERR_AFFECTS_MULTIPLE_DSAS 71 +/* 72-79 unused */ +#define LDB_ERR_OTHER 80 +/* 81-90 RESERVED for APIs */ + +#endif /* _LDB_ERRORS_H_ */ -- cgit From bb8f5c93ee3369e112d99d4d3497dc803abdbf76 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 18 Sep 2005 10:46:21 +0000 Subject: r10303: check no attribute is given empty (This used to be commit f0ad9495e45ee0d41ef8ca182984599c8e11cabb) --- source4/lib/ldb/common/ldb_ldif.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index a5768b9796..b268cca578 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -658,6 +658,11 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, if (ret != 0) { goto failed; } + if (value.length == 0) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Error: Attribute value cannot be empty for attribute '%s'\n", el->name); + goto failed; + } if (value.data != el->values[el->num_values].data) { talloc_steal(el->values, el->values[el->num_values].data); } -- cgit From 46a8d809376cab59c579c654b0de5105727a9585 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 18 Sep 2005 10:47:03 +0000 Subject: r10304: check for basic ldb_message sanity and return appropriate LDB_ERR_ value (This used to be commit 610f5646f0816820ac9342e81d46d139e26cc918) --- source4/lib/ldb/common/ldb.c | 38 +++++++++++++++++++++++------------ source4/lib/ldb/common/ldb_msg.c | 30 +++++++++++++++++++++++++++ source4/lib/ldb/include/ldb.h | 3 +++ source4/lib/ldb/include/ldb_private.h | 2 +- 4 files changed, 59 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index ae71f08713..57fb5a81da 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" /* @@ -89,20 +90,20 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co #endif else { ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'\n", url); - return -1; + return LDB_ERR_OTHER; } - if (ret != 0) { + if (ret != LDB_ERR_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url); return ret; } - if (ldb_load_modules(ldb, options) != 0) { + if (ldb_load_modules(ldb, options) != LDB_ERR_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url); - return -1; + return LDB_ERR_OTHER; } - return 0; + return LDB_ERR_SUCCESS; } /* @@ -162,8 +163,14 @@ int ldb_search_bytree(struct ldb_context *ldb, int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { - int status = ldb_start_trans(ldb); - if (status != 0) return status; + int status; + + + status = ldb_msg_sanity_check(message); + if (status != LDB_ERR_SUCCESS) return status; + + status = ldb_start_trans(ldb); + if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->add_record(ldb->modules, message); return ldb_end_trans(ldb, status); @@ -175,8 +182,13 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { - int status = ldb_start_trans(ldb); - if (status != 0) return status; + int status; + + status = ldb_msg_sanity_check(message); + if (status != LDB_ERR_SUCCESS) return status; + + status = ldb_start_trans(ldb); + if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->modify_record(ldb->modules, message); return ldb_end_trans(ldb, status); @@ -189,7 +201,7 @@ int ldb_modify(struct ldb_context *ldb, int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) { int status = ldb_start_trans(ldb); - if (status != 0) return status; + if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->delete_record(ldb->modules, dn); return ldb_end_trans(ldb, status); @@ -201,7 +213,7 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { int status = ldb_start_trans(ldb); - if (status != 0) return status; + if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); return ldb_end_trans(ldb, status); @@ -227,13 +239,13 @@ int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) struct ldb_opaque *o = talloc(ldb, struct ldb_opaque); if (o == NULL) { ldb_oom(ldb); - return -1; + return LDB_ERR_OTHER; } o->next = ldb->opaque; o->name = name; o->value = value; ldb->opaque = o; - return 0; + return LDB_ERR_SUCCESS; } /* diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index f65c944eab..2773237b36 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" /* @@ -499,3 +500,32 @@ struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, return mod; } + +int ldb_msg_sanity_check(const struct ldb_message *msg) +{ + int i, j; + + /* basic check on DN */ + if (msg->dn == NULL) { + /* TODO: return also an error string */ + return LDB_ERR_INVALID_DN_SYNTAX; + } + if (msg->dn->comp_num == 0) { + /* root dse has empty dn */ + /* TODO: return also an error string */ + return LDB_ERR_ENTRY_ALREADY_EXISTS; + } + + /* basic syntax checks */ + for (i = 0; i < msg->num_elements; i++) { + for (j = 0; j < msg->elements[i].num_values; j++) { + if (msg->elements[i].values[j].length == 0) { + /* an attribute cannot be empty */ + /* TODO: return also an error string */ + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + } + } + + return LDB_ERR_SUCCESS; +} diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 66b0343891..008327eb05 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -3,6 +3,7 @@ Copyright (C) Andrew Tridgell 2004 Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Simo Sorce 2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -451,6 +452,8 @@ struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, struct ldb_message *msg1, struct ldb_message *msg2); +int ldb_msg_sanity_check(const struct ldb_message *msg); + struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v); /* diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index e55a19c28c..96cd458920 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -3,7 +3,7 @@ Copyright (C) Andrew Tridgell 2004 Copyright (C) Stefan Metzmacher 2004 - Copyright (C) Simo Sorce 2004 + Copyright (C) Simo Sorce 2004-2005 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released -- cgit From 16aff2a184f7fab64d718b356056070e305e99e9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 18 Sep 2005 18:49:06 +0000 Subject: r10305: start implementing better error handling changed the prioivate modules API error string are now not spread over all modules but are kept in a single place. This allows a better control of memory and error reporting. (This used to be commit 3fc676ac1d6f59d08bedbbd9377986154cf84ce4) --- source4/lib/ldb/common/ldb.c | 34 ++++- source4/lib/ldb/common/ldb_modules.c | 9 +- source4/lib/ldb/include/ldb_private.h | 6 +- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 21 +-- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 18 +-- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 216 +++++++++++++++++++----------- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 1 + source4/lib/ldb/ldb_tdb/ldb_search.c | 12 +- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 122 ++++++++--------- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 3 - source4/lib/ldb/modules/ldb_map.c | 27 +--- source4/lib/ldb/modules/rdn_name.c | 43 +----- source4/lib/ldb/modules/schema.c | 102 +++++++------- source4/lib/ldb/modules/skel.c | 13 +- source4/lib/ldb/modules/timestamps.c | 34 +---- source4/lib/ldb/tools/ldbadd.c | 3 +- 16 files changed, 310 insertions(+), 354 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 57fb5a81da..a00c2481d8 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -106,6 +106,14 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co return LDB_ERR_SUCCESS; } +static void ldb_reset_err_string(struct ldb_context *ldb) +{ + if (ldb->err_string) { + talloc_free(ldb->err_string); + ldb->err_string = NULL; + } +} + /* start a transaction */ @@ -136,6 +144,8 @@ int ldb_search(struct ldb_context *ldb, const char *expression, const char * const *attrs, struct ldb_message ***res) { + ldb_reset_err_string(ldb); + return ldb->modules->ops->search(ldb->modules, base, scope, expression, attrs, res); } @@ -153,6 +163,8 @@ int ldb_search_bytree(struct ldb_context *ldb, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { + ldb_reset_err_string(ldb); + return ldb->modules->ops->search_bytree(ldb->modules, base, scope, tree, attrs, res); } @@ -165,6 +177,7 @@ int ldb_add(struct ldb_context *ldb, { int status; + ldb_reset_err_string(ldb); status = ldb_msg_sanity_check(message); if (status != LDB_ERR_SUCCESS) return status; @@ -184,6 +197,8 @@ int ldb_modify(struct ldb_context *ldb, { int status; + ldb_reset_err_string(ldb); + status = ldb_msg_sanity_check(message); if (status != LDB_ERR_SUCCESS) return status; @@ -200,7 +215,11 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) { - int status = ldb_start_trans(ldb); + int status; + + ldb_reset_err_string(ldb); + + status = ldb_start_trans(ldb); if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->delete_record(ldb->modules, dn); @@ -212,7 +231,11 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) */ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { - int status = ldb_start_trans(ldb); + int status; + + ldb_reset_err_string(ldb); + + status = ldb_start_trans(ldb); if (status != LDB_ERR_SUCCESS) return status; status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); @@ -224,10 +247,11 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct */ const char *ldb_errstring(struct ldb_context *ldb) { - if (ldb->modules == NULL) { - return "ldb not connected"; + if (ldb->err_string) { + return ldb->err_string; } - return ldb->modules->ops->errstring(ldb->modules); + + return NULL; } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 29bc8264e9..e1f5b83083 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -322,11 +322,12 @@ int ldb_next_end_trans(struct ldb_module *module, int status) return module->next->ops->end_transaction(module->next, status); } -const char *ldb_next_errstring(struct ldb_module *module) +void ldb_set_errstring(struct ldb_module *module, char *err_string) { - if (!module->next) { - return NULL; + if (module->ldb->err_string) { + talloc_free(module->ldb->err_string); } - return module->next->ops->errstring(module->next); + + module->ldb->err_string = err_string; } diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 96cd458920..7eb2bca679 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -66,7 +66,6 @@ struct ldb_module_ops { int (*rename_record)(struct ldb_module *, const struct ldb_dn *, const struct ldb_dn *); int (*start_transaction)(struct ldb_module *); int (*end_transaction)(struct ldb_module *, int); - const char * (*errstring)(struct ldb_module *); }; @@ -104,6 +103,8 @@ struct ldb_context { } *opaque; struct ldb_schema schema; + + char *err_string; }; /* the modules init function */ @@ -137,7 +138,8 @@ int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn); int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn); int ldb_next_start_trans(struct ldb_module *module); int ldb_next_end_trans(struct ldb_module *module, int status); -const char *ldb_next_errstring(struct ldb_module *module); + +void ldb_set_errstring(struct ldb_module *module, char *err_string); /* The following definitions come from lib/ldb/common/ldb_debug.c */ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index d4239c0f72..be51a65c58 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -82,6 +82,7 @@ static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co ildb->last_rc = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True); if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); ret = -1; } @@ -111,6 +112,7 @@ static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn) ildb->last_rc = ildap_delete(ildb->ldap, del_dn); if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); ret = -1; } @@ -316,6 +318,7 @@ static int ildb_add(struct ldb_module *module, const struct ldb_message *msg) ildb->last_rc = ildap_add(ildb->ldap, dn, mods); if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); ret = -1; } @@ -354,6 +357,7 @@ static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg) ildb->last_rc = ildap_modify(ildb->ldap, dn, mods); if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); ret = -1; } @@ -376,20 +380,6 @@ static int ildb_end_trans(struct ldb_module *module, int status) return status; } -/* - return extended error information -*/ -static const char *ildb_errstring(struct ldb_module *module) -{ - struct ildb_private *ildb = talloc_get_type(module->private_data, - struct ildb_private); - if (ildb == NULL) { - return "ildap not connected"; - } - return ldap_errstr(ildb->ldap, ildb->last_rc); -} - - static const struct ldb_module_ops ildb_ops = { .name = "ldap", .search = ildb_search, @@ -399,8 +389,7 @@ static const struct ldb_module_ops ildb_ops = { .delete_record = ildb_delete, .rename_record = ildb_rename, .start_transaction = ildb_start_trans, - .end_transaction = ildb_end_trans, - .errstring = ildb_errstring + .end_transaction = ildb_end_trans }; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 39f56dba0e..2035913f2a 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -78,6 +78,7 @@ static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co lldb->last_rc = ldap_rename_s(lldb->ldap, old_dn, newrdn, parentdn, 1, NULL, NULL); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc))); ret = -1; } @@ -107,6 +108,7 @@ static int lldb_delete(struct ldb_module *module, const struct ldb_dn *edn) lldb->last_rc = ldap_delete_s(lldb->ldap, dn); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc))); ret = -1; } @@ -200,6 +202,7 @@ static int lldb_search(struct ldb_module *module, const struct ldb_dn *base, 0, &ldapres); talloc_free(search_base); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc))); return -1; } @@ -404,6 +407,7 @@ static int lldb_add(struct ldb_module *module, const struct ldb_message *msg) lldb->last_rc = ldap_add_s(lldb->ldap, dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc))); ret = -1; } @@ -442,6 +446,7 @@ static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg) lldb->last_rc = ldap_modify_s(lldb->ldap, dn, mods); if (lldb->last_rc != LDAP_SUCCESS) { + ldb_set_errstring(module, talloc_strdup(module, ldap_err2string(lldb->last_rc))); ret = -1; } @@ -464,16 +469,6 @@ static int lldb_end_trans(struct ldb_module *module, int status) return status; } -/* - return extended error information -*/ -static const char *lldb_errstring(struct ldb_module *module) -{ - struct lldb_private *lldb = module->private_data; - return ldap_err2string(lldb->last_rc); -} - - static const struct ldb_module_ops lldb_ops = { .name = "ldap", .search = lldb_search, @@ -483,8 +478,7 @@ static const struct ldb_module_ops lldb_ops = { .delete_record = lldb_delete, .rename_record = lldb_rename, .start_transaction = lldb_start_trans, - .end_transaction = lldb_end_trans, - .errstring = lldb_errstring + .end_transaction = lldb_end_trans }; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index c0adab7bc3..8742b53962 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -36,6 +36,7 @@ #include #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h" @@ -828,12 +829,17 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d if (basedn) { norm_basedn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, basedn)); - if (norm_basedn == NULL) goto failed; + if (norm_basedn == NULL) { + ret = LDB_ERR_INVALID_DN_SYNTAX; + goto failed; + } } else norm_basedn = talloc_strdup(local_ctx, ""); if (*norm_basedn == '\0' && - (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) + (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) { + ret = LDB_ERR_UNWILLING_TO_PERFORM; goto failed; + } /* Convert filter into a series of SQL conditions (constraints) */ sqlfilter = parsetree_to_sql(module, local_ctx, tree); @@ -940,7 +946,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d } if (query == NULL) { - ret = -1; + ret = LDB_ERR_OTHER; goto failed; } @@ -957,15 +963,19 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, &msgs, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_search_bytree: Fatal Error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } for (i = 0; i < msgs.count; i++) { msgs.msgs[i] = ldb_msg_canonicalize(module->ldb, msgs.msgs[i]); - if (msgs.msgs[i] == NULL) goto failed; + if (msgs.msgs[i] == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } } *res = talloc_steal(module, msgs.msgs); @@ -1033,7 +1043,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg /* create a local ctx */ local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_add local context"); if (local_ctx == NULL) { - return -1; + return LDB_ERR_OTHER; } /* See if this is an ltdb special */ @@ -1043,6 +1053,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg c = ldb_dn_explode(local_ctx, "@SUBCLASSES"); if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { #warning "insert subclasses into object class tree" + ret = LDB_ERR_UNWILLING_TO_PERFORM; goto failed; } @@ -1054,13 +1065,16 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg } */ /* Others are implicitly ignored */ - return 0; + return LDB_ERR_SUCCESS; } /* create linearized and normalized dns */ dn = ldb_dn_linearize(local_ctx, msg->dn); ndn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, msg->dn)); - if (dn == NULL || ndn == NULL) goto failed; + if (dn == NULL || ndn == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } query = lsqlite3_tprintf(local_ctx, /* Add new entry */ @@ -1068,19 +1082,26 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg "('dn', 'norm_dn') " "VALUES ('%q', '%q');", dn, ndn); - if (query == NULL) goto failed; + if (query == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_add: exec error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, ndn); - if (eid == -1) goto failed; + if (eid == -1) { + ret = LDB_ERR_OTHER; + goto failed; + } for (i = 0; i < msg->num_elements; i++) { const struct ldb_message_element *el = &msg->elements[i]; @@ -1090,7 +1111,10 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg /* Get a case-folded copy of the attribute name */ attr = ldb_casefold(local_ctx, el->name); - if (attr == NULL) goto failed; + if (attr == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } h = ldb_attrib_handler(module->ldb, el->name); @@ -1101,7 +1125,10 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); - if (value.data == NULL) goto failed; + if (value.data == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } insert = lsqlite3_tprintf(local_ctx, "INSERT OR ROLLBACK INTO ldb_attribute_values " @@ -1110,25 +1137,29 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg "VALUES ('%lld', '%q', '%q', '%q', '%q');", eid, el->name, attr, el->values[j].data, value.data); - if (insert == NULL) goto failed; + if (insert == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, insert, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_add: insert error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } } } talloc_free(local_ctx); - return 0; + return LDB_ERR_SUCCESS; failed: talloc_free(local_ctx); - return -1; + return ret; } @@ -1145,7 +1176,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * /* create a local ctx */ local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_modify local context"); if (local_ctx == NULL) { - return -1; + return LDB_ERR_OTHER; } /* See if this is an ltdb special */ @@ -1155,21 +1186,17 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * c = ldb_dn_explode(local_ctx, "@SUBCLASSES"); if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { #warning "modify subclasses into object class tree" - goto failed; - } - - c = ldb_dn_explode(local_ctx, "@INDEXLIST"); - if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) { -#warning "should we handle indexes somehow ?" + ret = LDB_ERR_UNWILLING_TO_PERFORM; goto failed; } /* Others are implicitly ignored */ - return 0; + return LDB_ERR_SUCCESS; } eid = lsqlite3_get_eid(module, msg->dn); if (eid == -1) { + ret = LDB_ERR_OTHER; goto failed; } @@ -1184,6 +1211,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * /* Get a case-folded copy of the attribute name */ attr = ldb_casefold(local_ctx, el->name); if (attr == NULL) { + ret = LDB_ERR_OTHER; goto failed; } @@ -1199,14 +1227,18 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * "WHERE eid = '%lld' " "AND norm_attr_name = '%q';", eid, attr); - if (mod == NULL) goto failed; + if (mod == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } @@ -1221,6 +1253,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); if (value.data == NULL) { + ret = LDB_ERR_OTHER; goto failed; } @@ -1232,14 +1265,18 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * eid, el->name, attr, el->values[j].data, value.data); - if (mod == NULL) goto failed; + if (mod == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } } @@ -1254,14 +1291,18 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * "WHERE eid = '%lld' " "AND norm_attr_name = '%q';", eid, attr); - if (mod == NULL) goto failed; + if (mod == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } } @@ -1273,6 +1314,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * /* Get a canonicalised copy of the data */ h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value); if (value.data == NULL) { + ret = LDB_ERR_OTHER; goto failed; } @@ -1283,14 +1325,18 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * "AND norm_attr_value = '%q';", eid, attr, value.data); - if (mod == NULL) goto failed; + if (mod == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_modify: error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } } @@ -1300,11 +1346,11 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * } talloc_free(local_ctx); - return 0; + return LDB_ERR_SUCCESS; failed: talloc_free(local_ctx); - return -1; + return ret; } /* delete a record */ @@ -1319,17 +1365,20 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) /* ignore ltdb specials */ if (ldb_dn_is_special(dn)) { - return 0; + return LDB_ERR_SUCCESS; } /* create a local ctx */ local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_delete local context"); if (local_ctx == NULL) { - return -1; + return LDB_ERR_OTHER; } eid = lsqlite3_get_eid(module, dn); - if (eid == -1) goto failed; + if (eid == -1) { + ret = LDB_ERR_OTHER; + goto failed; + } query = lsqlite3_tprintf(local_ctx, /* Delete entry */ @@ -1337,23 +1386,27 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) /* Delete attributes */ "DELETE FROM ldb_attribute_values WHERE eid = %lld; ", eid, eid); - if (query == NULL) goto failed; + if (query == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_delete: error getting eid: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } talloc_free(local_ctx); - return 0; + return LDB_ERR_SUCCESS; failed: talloc_free(local_ctx); - return -1; + return ret; } /* rename a record */ @@ -1368,45 +1421,52 @@ static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn /* ignore ltdb specials */ if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) { - return 0; + return LDB_ERR_SUCCESS; } /* create a local ctx */ local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_rename local context"); if (local_ctx == NULL) { - return -1; + return LDB_ERR_OTHER; } /* create linearized and normalized dns */ old_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, olddn)); new_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, newdn)); new_dn = ldb_dn_linearize(local_ctx, newdn); - if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) goto failed; + if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } /* build the SQL query */ query = lsqlite3_tprintf(local_ctx, "UPDATE ldb_entry SET dn = '%q', norm_dn = '%q' " "WHERE norm_dn = '%q';", new_dn, new_cdn, old_cdn); - if (query == NULL) goto failed; + if (query == NULL) { + ret = LDB_ERR_OTHER; + goto failed; + } /* execute */ ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { - printf("lsqlite3_rename: sqlite3_exec error: %s\n", errmsg); + ldb_set_errstring(module, talloc_strdup(module, errmsg)); free(errmsg); } + ret = LDB_ERR_OTHER; goto failed; } /* clean up and exit */ talloc_free(local_ctx); - return 0; + return LDB_ERR_SUCCESS; failed: talloc_free(local_ctx); - return -1; + return ret; } static int lsqlite3_start_trans(struct ldb_module * module) @@ -1415,14 +1475,18 @@ static int lsqlite3_start_trans(struct ldb_module * module) char *errmsg; struct lsqlite3_private * lsqlite3 = module->private_data; - ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN IMMEDIATE;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_start_trans: error: %s\n", errmsg); - free(errmsg); + if (lsqlite3->trans_count == 0) { + ret = sqlite3_exec(lsqlite3->sqlite, "BEGIN IMMEDIATE;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_start_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; } - return -1; - } + }; + + lsqlite3->trans_count++; return 0; } @@ -1433,36 +1497,26 @@ static int lsqlite3_end_trans(struct ldb_module *module, int status) char *errmsg; struct lsqlite3_private *lsqlite3 = module->private_data; - if (status == 0) { - ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_end_trans: error: %s\n", errmsg); - free(errmsg); + lsqlite3->trans_count--; + + if (lsqlite3->trans_count == 0) { + if (status == 0) { + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_end_trans: error: %s\n", errmsg); + free(errmsg); + } + return -1; } - return -1; + } else { + return lsqlite3_safe_rollback(lsqlite3->sqlite); } - } else { - return lsqlite3_safe_rollback(lsqlite3->sqlite); } return 0; } - - -/* return extended error information */ -static const char * -lsqlite3_errstring(struct ldb_module *module) -{ - struct lsqlite3_private * lsqlite3 = module->private_data; - - return sqlite3_errmsg(lsqlite3->sqlite); -} - - - - /* * Static functions */ @@ -1758,8 +1812,7 @@ static const struct ldb_module_ops lsqlite3_ops = { .delete_record = lsqlite3_delete, .rename_record = lsqlite3_rename, .start_transaction = lsqlite3_start_trans, - .end_transaction = lsqlite3_end_trans, - .errstring = lsqlite3_errstring + .end_transaction = lsqlite3_end_trans }; /* @@ -1781,6 +1834,7 @@ int lsqlite3_connect(struct ldb_context *ldb, lsqlite3->sqlite = NULL; lsqlite3->options = NULL; + lsqlite3->trans_count = 0; ret = initialize(lsqlite3, ldb, url); if (ret != SQLITE_OK) { diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 46c949a564..d14a1aa0e0 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -1,6 +1,7 @@ #include struct lsqlite3_private { + int trans_count; char **options; sqlite3 *sqlite; }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index ca0ae06354..fc864ac2ea 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" @@ -249,7 +250,6 @@ static int ltdb_search_dn(struct ldb_module *module, const struct ldb_dn *dn, const char * const attrs[], struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; - struct ltdb_private *ltdb = module->private_data; int ret; struct ldb_message *msg, *msg2; @@ -259,8 +259,6 @@ static int ltdb_search_dn(struct ldb_module *module, const struct ldb_dn *dn, return -1; } - ltdb->last_err_string = NULL; - if (ltdb_cache_load(module) != 0) { ltdb_unlock_read(module); return -1; @@ -462,7 +460,6 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res) { - struct ltdb_private *ltdb = module->private_data; int ret; if ((base == NULL || base->comp_num == 0) && @@ -476,7 +473,7 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, struct ldb_dn *dn; dn = ldb_dn_explode(module->ldb, tree->u.equality.value.data); if (dn == NULL) { - return -1; + return LDB_ERR_INVALID_DN_SYNTAX; } ret = ltdb_search_dn(module, dn, attrs, res); talloc_free(dn); @@ -487,8 +484,6 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, return -1; } - ltdb->last_err_string = NULL; - if (ltdb_cache_load(module) != 0) { ltdb_unlock_read(module); return -1; @@ -530,7 +525,8 @@ int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, tree = ldb_parse_tree(ltdb, expression); if (tree == NULL) { - ltdb->last_err_string = "expression parse failed"; + char *err_string = talloc_strdup(module, "expression parse failed"); + if (err_string) ldb_set_errstring(module, err_string); return -1; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index c3f59a2dbe..265e04a057 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -37,6 +37,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" @@ -235,7 +236,6 @@ int ltdb_unlock_read(struct ldb_module *module) */ int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = module->private_data; int i, j; if (! ldb_dn_is_special(msg->dn) || @@ -248,8 +248,11 @@ int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *m for (i = 0; i < msg->num_elements; i++) { for (j = 0; j < msg->elements[i].num_values; j++) { if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) { - ltdb->last_err_string = "Invalid attribute value in an @ATTRIBUTES entry"; - return -1; + char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry"); + if (err_string) { + ldb_set_errstring(module, err_string); + } + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; } } } @@ -292,17 +295,18 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg tdb_key = ltdb_key(module, msg->dn); if (!tdb_key.dptr) { - return -1; + return LDB_ERR_OTHER; } ret = ltdb_pack_data(module, msg, &tdb_data); if (ret == -1) { talloc_free(tdb_key.dptr); - return -1; + return LDB_ERR_OTHER; } ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs); if (ret == -1) { + ret = LDB_ERR_OTHER; goto done; } @@ -324,28 +328,25 @@ done: */ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = module->private_data; int ret; - ltdb->last_err_string = NULL; - ret = ltdb_check_special_dn(module, msg); - if (ret != 0) { + if (ret != LDB_ERR_SUCCESS) { return ret; } if (ltdb_lock(module, LDBLOCK) != 0) { - return -1; + return LDB_ERR_OTHER; } if (ltdb_cache_load(module) != 0) { ltdb_unlock(module, LDBLOCK); - return -1; + return LDB_ERR_OTHER; } ret = ltdb_store(module, msg, TDB_INSERT); - if (ret == 0) { + if (ret == LDB_ERR_SUCCESS) { ltdb_modified(module, msg->dn); } @@ -366,12 +367,14 @@ int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn) tdb_key = ltdb_key(module, dn); if (!tdb_key.dptr) { - return -1; + return LDB_ERR_OTHER; } ret = tdb_delete(ltdb->tdb, tdb_key); talloc_free(tdb_key.dptr); + if (ret != 0) ret = LDB_ERR_OTHER; + return ret; } @@ -380,14 +383,11 @@ int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn) */ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) { - struct ltdb_private *ltdb = module->private_data; - int ret; struct ldb_message *msg = NULL; - - ltdb->last_err_string = NULL; + int ret = LDB_ERR_OTHER; if (ltdb_lock(module, LDBLOCK) != 0) { - return -1; + return ret; } if (ltdb_cache_load(module) != 0) { @@ -404,20 +404,21 @@ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) ret = ltdb_search_dn1(module, dn, msg); if (ret != 1) { /* not finding the old record is an error */ + ret = LDB_ERR_NO_SUCH_OBJECT; goto failed; } ret = ltdb_delete_noindex(module, dn); - if (ret == -1) { + if (ret != LDB_ERR_SUCCESS) { goto failed; } /* remove any indexed attributes */ ret = ltdb_index_del(module, msg); - - if (ret == 0) { + if (ret == LDB_ERR_SUCCESS) { ltdb_modified(module, dn); - } + } else + ret = LDB_ERR_OTHER; talloc_free(msg); ltdb_unlock(module, LDBLOCK); @@ -426,7 +427,7 @@ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) failed: talloc_free(msg); ltdb_unlock(module, LDBLOCK); - return -1; + return ret; } @@ -593,26 +594,26 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms tdb_key = ltdb_key(module, msg->dn); if (!tdb_key.dptr) { - return -1; + return LDB_ERR_OTHER; } tdb_data = tdb_fetch(ltdb->tdb, tdb_key); if (!tdb_data.dptr) { talloc_free(tdb_key.dptr); - return -1; + return LDB_ERR_OTHER; } msg2 = talloc(tdb_key.dptr, struct ldb_message); if (msg2 == NULL) { talloc_free(tdb_key.dptr); - return -1; + return LDB_ERR_OTHER; } ret = ltdb_unpack_data(module, &tdb_data, msg2); if (ret == -1) { talloc_free(tdb_key.dptr); free(tdb_data.dptr); - return -1; + return LDB_ERR_OTHER; } if (!msg2->dn) { @@ -623,6 +624,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms struct ldb_message_element *el = &msg->elements[i]; struct ldb_message_element *el2; struct ldb_val *vals; + char *err_string; char *dn; switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { @@ -634,6 +636,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms if (ret == -1) { if (msg_add_element(ldb, msg2, el) != 0) { + ret = LDB_ERR_OTHER; goto failed; } continue; @@ -646,8 +649,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms for (j=0;jnum_values;j++) { if (ldb_msg_find_val(el2, &el->values[j])) { - ltdb->last_err_string = - "Type or value exists"; + err_string = talloc_strdup(module, "Type or value exists"); + if (err_string) ldb_set_errstring(module, err_string); + ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; goto failed; } } @@ -690,7 +694,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms if (msg->elements[i].num_values == 0) { if (msg_delete_attribute(module, ldb, msg2, msg->elements[i].name) != 0) { - ltdb->last_err_string = "No such attribute"; + err_string = talloc_strdup(module, "No such attribute"); + if (err_string) ldb_set_errstring(module, err_string); + ret = LDB_ERR_NO_SUCH_ATTRIBUTE; goto failed; } break; @@ -700,7 +706,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms msg2, msg->elements[i].name, &msg->elements[i].values[j]) != 0) { - ltdb->last_err_string = "No such attribute"; + err_string = talloc_strdup(module, "No such attribute"); + if (err_string) ldb_set_errstring(module, err_string); + ret = LDB_ERR_NO_SUCH_ATTRIBUTE; goto failed; } if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) { @@ -709,7 +717,9 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms } break; default: - ltdb->last_err_string = "Invalid ldb_modify flags"; + err_string = talloc_strdup(module, "Invalid ldb_modify flags"); + if (err_string) ldb_set_errstring(module, err_string); + ret = LDB_ERR_PROTOCOL_ERROR; goto failed; } } @@ -724,7 +734,7 @@ int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *ms failed: talloc_free(tdb_key.dptr); free(tdb_data.dptr); - return -1; + return ret; } /* @@ -732,11 +742,8 @@ failed: */ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) { - struct ltdb_private *ltdb = module->private_data; int ret; - ltdb->last_err_string = NULL; - ret = ltdb_check_special_dn(module, msg); if (ret != 0) { return ret; @@ -753,7 +760,7 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ret = ltdb_modify_internal(module, msg); - if (ret == 0) { + if (ret == LDB_ERR_SUCCESS) { ltdb_modified(module, msg->dn); } @@ -767,20 +774,17 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) */ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { - struct ltdb_private *ltdb = module->private_data; - int ret; struct ldb_message *msg; - const char *error_str; - - ltdb->last_err_string = NULL; + char *error_str; + int ret = LDB_ERR_OTHER; if (ltdb_lock(module, LDBLOCK) != 0) { - return -1; + return ret; } if (ltdb_cache_load(module) != 0) { ltdb_unlock(module, LDBLOCK); - return -1; + return ret; } msg = talloc(module, struct ldb_message); @@ -793,26 +797,28 @@ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co ret = ltdb_search_dn1(module, olddn, msg); if (ret != 1) { /* not finding the old record is an error */ + ret = LDB_ERR_NO_SUCH_OBJECT; goto failed; } msg->dn = ldb_dn_copy(msg, newdn); if (!msg->dn) { + ret = LDB_ERR_OTHER; goto failed; } ret = ltdb_add(module, msg); - if (ret == -1) { + if (ret != LDB_ERR_SUCCESS) { goto failed; } ret = ltdb_delete(module, olddn); - error_str = ltdb->last_err_string; - if (ret == -1) { + error_str = talloc_strdup(module, ldb_errstring(module->ldb)); + if (ret != LDB_ERR_SUCCESS) { ltdb_delete(module, newdn); } - ltdb->last_err_string = error_str; + ldb_set_errstring(module, error_str); talloc_free(msg); ltdb_unlock(module, LDBLOCK); @@ -822,14 +828,14 @@ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co failed: talloc_free(msg); ltdb_unlock(module, LDBLOCK); - return -1; + return ret; } static int ltdb_start_trans(struct ldb_module *module) { /* TODO: implement transactions */ - return 0; + return LDB_ERR_SUCCESS; } static int ltdb_end_trans(struct ldb_module *module, int status) @@ -839,19 +845,6 @@ static int ltdb_end_trans(struct ldb_module *module, int status) return status; } -/* - return extended error information -*/ -static const char *ltdb_errstring(struct ldb_module *module) -{ - struct ltdb_private *ltdb = module->private_data; - if (ltdb->last_err_string) { - return ltdb->last_err_string; - } - return tdb_errorstr(ltdb->tdb); -} - - static const struct ldb_module_ops ltdb_ops = { .name = "tdb", .search = ltdb_search, @@ -861,8 +854,7 @@ static const struct ldb_module_ops ltdb_ops = { .delete_record = ltdb_delete, .rename_record = ltdb_rename, .start_transaction = ltdb_start_trans, - .end_transaction = ltdb_end_trans, - .errstring = ltdb_errstring + .end_transaction = ltdb_end_trans }; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index f08601832c..f1da556f99 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -27,9 +27,6 @@ struct ltdb_private { int flags; } last_attribute; } *cache; - - /* error if an internal ldb+tdb error */ - const char *last_err_string; }; /* special record types */ diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 93ae13ffc2..69e021b4ee 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -97,7 +97,6 @@ static const struct ldb_map_objectclass *map_find_objectclass_remote(struct ldb_ struct map_private { struct ldb_map_context context; - const char *last_err_string; }; static struct ldb_map_context *map_get_privdat(struct ldb_module *module) @@ -807,8 +806,7 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * talloc_free(newattrs); if (mpret == -1) { - struct map_private *map_private = module->private_data; - map_private->last_err_string = ldb_errstring(privdat->mapped_ldb); + ldb_set_errstring(module, talloc_strdup(module, ldb_errstring(privdat->mapped_ldb))); return -1; } @@ -910,13 +908,12 @@ static int map_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) { - struct map_private *map = module->private_data; struct ldb_parse_tree *tree; int ret; tree = ldb_parse_tree(NULL, expression); if (tree == NULL) { - map->last_err_string = "expression parse failed"; + ldb_set_errstring(module, talloc_strdup(module, "expression parse failed")); return -1; } @@ -1121,7 +1118,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); ret = ldb_next_add_record(module, fb); if (ret == -1) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_next_errstring(module)); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_errstring(module->ldb)); return -1; } @@ -1266,19 +1263,6 @@ static int map_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* - return extended error information -*/ -static const char *map_errstring(struct ldb_module *module) -{ - struct map_private *map = module->private_data; - - if (map->last_err_string) - return map->last_err_string; - - return ldb_next_errstring(module); -} - static const struct ldb_module_ops map_ops = { .name = "map", .search = map_search, @@ -1288,8 +1272,7 @@ static const struct ldb_module_ops map_ops = { .delete_record = map_delete, .rename_record = map_rename, .start_transaction = map_start_trans, - .end_transaction = map_end_trans, - .errstring = map_errstring + .end_transaction = map_end_trans }; static char *map_find_url(struct ldb_context *ldb, const char *name) @@ -1354,8 +1337,6 @@ struct ldb_module *ldb_map_init(struct ldb_context *ldb, const struct ldb_map_at talloc_free(url); - data->last_err_string = NULL; - /* Get list of attribute maps */ j = 0; data->context.attribute_maps = NULL; diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index ed5400176c..c1a0c0852a 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -37,10 +37,6 @@ #include "ldb/include/ldb_private.h" #include -struct private_data { - const char *error_string; -}; - static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -73,8 +69,6 @@ static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_mess /* add_record: add crateTimestamp/modifyTimestamp attributes */ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; - struct ldb_message *msg2; struct ldb_message_element *attribute; struct ldb_dn_component *rdn; @@ -134,8 +128,11 @@ static int rdn_name_add_record(struct ldb_module *module, const struct ldb_messa } } if (i == attribute->num_values) { - data->error_string = talloc_asprintf(data, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); - ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", data->error_string); + char *error_string = talloc_asprintf(module, "RDN mismatch on %s: %s", ldb_dn_linearize(msg2, msg2->dn), rdn->name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s\n", error_string); + } talloc_free(msg2); return -1; } @@ -229,23 +226,6 @@ static int rdn_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *rdn_name_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int rdn_name_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -262,8 +242,7 @@ static const struct ldb_module_ops rdn_name_ops = { .delete_record = rdn_name_delete_record, .rename_record = rdn_name_rename_record, .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans, - .errstring = rdn_name_errstring + .end_transaction = rdn_end_trans }; @@ -275,20 +254,12 @@ struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *opt #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = &rdn_name_ops; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 9406d54ce7..1a2c2b8f97 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #define SCHEMA_FLAG_RESET 0 @@ -51,10 +52,6 @@ check there's only one structrual class (or a chain of structural classes) */ -struct private_data { - const char *error_string; -}; - struct schema_attribute { int flags; char *name; @@ -189,8 +186,8 @@ static int add_attribute_uniq(void *mem_ctx, struct schema_attribute_list *list, recursively get parent objectlasses attributes */ static int get_attr_list_recursive(struct ldb_module *module, struct schema_structures *schema_struct) { - struct private_data *data = (struct private_data *)module->private_data; struct ldb_message **srch; + char *error_string; int i, j; int ret; @@ -213,14 +210,20 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru if (ret <= 0) { /* Schema DB Error: Error occurred retrieving Object Class Description */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); - data->error_string = "Internal error. Error retrieving schema objectclass"; + error_string = talloc_asprintf(module, "Error retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } return -1; } if (ret > 1) { /* Schema DB Error: Too Many Records */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); - data->error_string = "Internal error. Too many records searching for schema objectclass"; + error_string = talloc_asprintf(module, "Too many records found retrieving Objectclass %s.\n", schema_struct->objectclasses.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } return -1; } @@ -297,8 +300,8 @@ static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn * /* add_record */ static int schema_add_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; + char *error_string; unsigned int i; int ret; @@ -342,13 +345,15 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The required_attrs attribute %s is missing.\n", entry_structs->required_attrs.attr[i].name); - - data->error_string = "Objectclass violation, a required attribute is missing"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* mark the attribute as checked */ @@ -365,13 +370,15 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The attribute %s is not referenced by any objectclass.\n", entry_structs->entry_attrs.attr[i].name); - - data->error_string = "Objectclass violation, an invalid attribute name was found"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } } } @@ -384,8 +391,8 @@ static int schema_add_record(struct ldb_module *module, const struct ldb_message /* modify_record */ static int schema_modify_record(struct ldb_module *module, const struct ldb_message *msg) { - struct private_data *data = (struct private_data *)module->private_data; struct schema_structures *entry_structs; + char *error_string; unsigned int i; int ret; @@ -437,25 +444,30 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess entry_structs->required_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The required_attrs attribute %s is missing.\n", entry_structs->required_attrs.attr[i].name); - - data->error_string = "Objectclass violation, a required attribute is missing"; + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* check we are not trying to delete a required attribute */ /* TODO: consider multivalued attrs */ if ((attr->flags & SCHEMA_FLAG_MOD_DELETE) != 0) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "Trying to delete the required attribute %s.\n", attr->name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } - data->error_string = "Objectclass violation, a required attribute cannot be removed"; talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* mark the attribute as checked */ @@ -472,13 +484,16 @@ static int schema_modify_record(struct ldb_module *module, const struct ldb_mess entry_structs->entry_attrs.attr[i].name); if (attr == NULL) { /* not found */ - ldb_debug(module->ldb, LDB_DEBUG_ERROR, + error_string = talloc_asprintf(module, "The attribute %s is not referenced by any objectclass.\n", entry_structs->entry_attrs.attr[i].name); + if (error_string) { + ldb_set_errstring(module, error_string); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, error_string); + } - data->error_string = "Objectclass violation, an invalid attribute name was found"; talloc_free(entry_structs); - return -1; + return LDB_ERR_OBJECT_CLASS_VIOLATION; } } } @@ -509,22 +524,6 @@ static int schema_end_trans(struct ldb_module *module, int status) { return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *schema_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int schema_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -541,8 +540,7 @@ static const struct ldb_module_ops schema_ops = { .delete_record = schema_delete_record, .rename_record = schema_rename_record, .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans, - .errstring = schema_errstring, + .end_transaction = schema_end_trans }; #ifdef HAVE_DLOPEN_DISABLED @@ -552,21 +550,13 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) { return NULL; } - data = talloc(ctx, struct private_data); - if (data == NULL) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 37c0417c64..701128cd27 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -38,7 +38,7 @@ struct private_data { - char *errstring; + char *some_private_data; }; /* search */ @@ -85,18 +85,12 @@ static int skel_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *skel_errstring(struct ldb_module *module) -{ - return ldb_next_errstring(module); -} - static int skel_destructor(void *module_ctx) { struct ldb_module *ctx = talloc_get_type(module_ctx, struct ldb_module); struct private_data *data = talloc_get_type(ctx->private_data, struct private_data); /* put your clean-up functions here */ - if (data->errstring) talloc_free(data->errstring); + if (data->some_private_data) talloc_free(data->some_private_data); return 0; } @@ -110,7 +104,6 @@ static const struct ldb_module_ops skel_ops = { .rename_record = skel_rename_record, .start_transaction = skel_start_trans, .end_transaction = skel_end_trans, - .errstring = skel_errstring }; #ifdef HAVE_DLOPEN_DISABLED @@ -132,7 +125,7 @@ struct ldb_module *skel_module_init(struct ldb_context *ldb, const char *options return NULL; } - data->errstring = NULL; + data->some_private_data = NULL; ctx->private_data = data; ctx->ldb = ldb; diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 6687b1929d..dc91937f85 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,10 +37,6 @@ #include "ldb/include/ldb_private.h" #include -struct private_data { - const char *error_string; -}; - static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_message ***res) @@ -227,23 +223,6 @@ static int timestamps_end_trans(struct ldb_module *module, int status) return ldb_next_end_trans(module, status); } -/* return extended error information */ -static const char *timestamps_errstring(struct ldb_module *module) -{ - struct private_data *data = (struct private_data *)module->private_data; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_errstring\n"); - if (data->error_string) { - const char *error; - - error = data->error_string; - data->error_string = NULL; - return error; - } - - return ldb_next_errstring(module); -} - static int timestamps_destructor(void *module_ctx) { /* struct ldb_module *ctx = module_ctx; */ @@ -260,8 +239,7 @@ static const struct ldb_module_ops timestamps_ops = { .delete_record = timestamps_delete_record, .rename_record = timestamps_rename_record, .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans, - .errstring = timestamps_errstring + .end_transaction = timestamps_end_trans }; @@ -273,20 +251,12 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o #endif { struct ldb_module *ctx; - struct private_data *data; ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; - data = talloc(ctx, struct private_data); - if (!data) { - talloc_free(ctx); - return NULL; - } - - data->error_string = NULL; - ctx->private_data = data; + ctx->private_data = NULL; ctx->ldb = ldb; ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index de6da0eb5b..ba58f782f0 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -34,6 +34,7 @@ #include "includes.h" #include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" #include "ldb/tools/cmdline.h" @@ -74,7 +75,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg); ret = ldb_add(ldb, ldif->msg); - if (ret != 0) { + if (ret != LDB_ERR_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); failures++; -- cgit From cb9d4c670724d281c5de008ffa43ac30c186d6e7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Sep 2005 09:57:39 +0000 Subject: r10312: fix compiler warning metze (This used to be commit 3309a0f4d90f01e1f6182b797e2bfe3f8380e59c) --- source4/lib/ldb/common/ldb_msg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 2773237b36..1b26d7833b 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -206,7 +206,7 @@ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, { struct ldb_val val; - val.data = discard_const_p(char, str); + val.data = discard_const_p(uint8_t, str); val.length = strlen(str); return ldb_msg_add_value(ldb, msg, attr_name, &val); -- cgit From 349294d358481e1af460d1ade97987474dad9e43 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 19 Sep 2005 12:58:43 +0000 Subject: r10315: Remove use of fstring and pstring in dynconfig.c Remove unused includes of dynconfig.h (This used to be commit 59083b7ba60d518ddb59646c4fd69938afd079b3) --- source4/lib/util.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util.c b/source4/lib/util.c index 2e0503b0d9..a1d6f85eb9 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -703,18 +703,6 @@ char *smbd_tmp_path(TALLOC_CTX *mem_ctx, const char *name) return fname; } -/** - * @brief Returns the platform specific shared library extension. - * - * @retval Pointer to a static #fstring containing the extension. - **/ - -const char *shlib_ext(void) -{ - return dyn_SHLIBEXT; -} - - void dump_data_pw(const char *msg, const uint8_t * data, size_t len) { #ifdef DEBUG_PASSWORD -- cgit From d2a666acbe04f741387ff4351e3971b24f1c3b14 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 19 Sep 2005 13:26:07 +0000 Subject: r10316: More dynconfig fixes (This used to be commit 0963ab9c148772b961f17ec779213b0eb861e1dd) --- source4/lib/cmdline/credentials.c | 1 - source4/lib/cmdline/popt_common.c | 1 - 2 files changed, 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c index f46a03b236..f164663118 100644 --- a/source4/lib/cmdline/credentials.c +++ b/source4/lib/cmdline/credentials.c @@ -20,7 +20,6 @@ #include "includes.h" #include "version.h" -#include "dynconfig.h" #include "system/filesys.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 333004e965..fe76292acb 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -22,7 +22,6 @@ #include "includes.h" #include "version.h" -#include "dynconfig.h" #include "system/filesys.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" -- cgit From 523034b9fbc1841ed63137e3d8965d52997af4e6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 19 Sep 2005 19:19:10 +0000 Subject: r10323: Add first bits required for getting compile with scons working. This does not work yet and can exist parallel with the existing build system. (This used to be commit 829568d75985e875e3363d76fb44270a0298c7f8) --- source4/lib/SConscript | 25 +++++++++++++++++++++++++ source4/lib/charset/SConscript | 3 +++ source4/lib/cmdline/SConscript | 4 ++++ source4/lib/popt/SConscript | 3 +++ source4/lib/registry/SConscript | 5 +++++ source4/lib/talloc/SConscript | 3 +++ 6 files changed, 43 insertions(+) create mode 100644 source4/lib/SConscript create mode 100644 source4/lib/charset/SConscript create mode 100644 source4/lib/cmdline/SConscript create mode 100644 source4/lib/popt/SConscript create mode 100644 source4/lib/registry/SConscript create mode 100644 source4/lib/talloc/SConscript (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript new file mode 100644 index 0000000000..57427feb71 --- /dev/null +++ b/source4/lib/SConscript @@ -0,0 +1,25 @@ +Import('hostenv') +basic = hostenv.StaticLibrary('basic', + ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'pidfile.c', + 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', + 'util_str.c', 'util_strlist.c', 'util_unistr.c', 'util_file.c', + 'data_blob.c', 'util.c', 'util_sock.c', 'substitute.c', + 'fsusage.c', 'ms_fnmatch.c', 'select.c', 'mutex.c', 'idtree.c', + 'unix_privs.c', 'db_wrap.c', 'gendb.c', 'credentials.c']) +Export('basic') + +hostenv.StaticLibrary('netif', ['netif/interface.c', 'netif/netif.c']) +hostenv.StaticLibrary('tdr', ['tdr/tdr.c']) +hostenv.StaticLibrary('crypto', + ['crypto/crc32.c','crypto/md5.c','crypto/hmacmd5.c', + 'crypto/md4.c','crypto/arcfour.c']) +hostenv.StaticLibrary('compression', ['compression/mszip.c']) +hostenv.StaticLibrary('gencache',['gencache.c']) +hostenv.StaticLibrary('pidfile',['pidfile.c']) +hostenv.StaticLibrary('unix_privs',['unix_privs.c']) + +SConscript('popt/SConscript','hostenv') +SConscript('cmdline/SConscript','hostenv') +SConscript('talloc/SConscript','hostenv') +SConscript('registry/SConscript','hostenv') +SConscript('charset/SConscript', 'hostenv') diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript new file mode 100644 index 0000000000..0b67bedb0f --- /dev/null +++ b/source4/lib/charset/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') +charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c']) +Export('charset') diff --git a/source4/lib/cmdline/SConscript b/source4/lib/cmdline/SConscript new file mode 100644 index 0000000000..7b5c14db87 --- /dev/null +++ b/source4/lib/cmdline/SConscript @@ -0,0 +1,4 @@ +Import('hostenv') +Import('basic param') +popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param]) +Export('popt_common') diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript new file mode 100644 index 0000000000..90801ffb6f --- /dev/null +++ b/source4/lib/popt/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') +popt = hostenv.StaticLibrary('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) +Export('popt') diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript new file mode 100644 index 0000000000..f63179283a --- /dev/null +++ b/source4/lib/registry/SConscript @@ -0,0 +1,5 @@ +Import('hostenv') +Import('talloc basic popt_common popt param') +registry = hostenv.StaticLibrary('registry', + [basic,talloc,'common/reg_interface.c','common/reg_util.c']) +hostenv.Program('regtree', ['tools/regtree.c',registry,talloc,basic,popt_common,popt,param]) diff --git a/source4/lib/talloc/SConscript b/source4/lib/talloc/SConscript new file mode 100644 index 0000000000..e3851afa4e --- /dev/null +++ b/source4/lib/talloc/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') +talloc = hostenv.StaticLibrary('talloc',['talloc.c']) +Export('talloc') -- cgit From 96745cbfc0e3386fa32631daa45b4096a1f80e61 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 19 Sep 2005 21:44:36 +0000 Subject: r10328: Add more emacs python-mode markers. (This used to be commit 540a3649e88690e829c17d79ecdccdc9ed464845) --- source4/lib/SConscript | 2 ++ source4/lib/charset/SConscript | 2 ++ source4/lib/cmdline/SConscript | 2 ++ source4/lib/popt/SConscript | 2 ++ source4/lib/registry/SConscript | 2 ++ source4/lib/talloc/SConscript | 2 ++ 6 files changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 57427feb71..f1bff77cd0 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') basic = hostenv.StaticLibrary('basic', ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'pidfile.c', diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index 0b67bedb0f..d73d390309 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c']) Export('charset') diff --git a/source4/lib/cmdline/SConscript b/source4/lib/cmdline/SConscript index 7b5c14db87..724dc07821 100644 --- a/source4/lib/cmdline/SConscript +++ b/source4/lib/cmdline/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') Import('basic param') popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param]) diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript index 90801ffb6f..580de92023 100644 --- a/source4/lib/popt/SConscript +++ b/source4/lib/popt/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') popt = hostenv.StaticLibrary('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) Export('popt') diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript index f63179283a..4ea4301105 100644 --- a/source4/lib/registry/SConscript +++ b/source4/lib/registry/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') Import('talloc basic popt_common popt param') registry = hostenv.StaticLibrary('registry', diff --git a/source4/lib/talloc/SConscript b/source4/lib/talloc/SConscript index e3851afa4e..37079c4156 100644 --- a/source4/lib/talloc/SConscript +++ b/source4/lib/talloc/SConscript @@ -1,3 +1,5 @@ +# tastes like -*- python -*- + Import('hostenv') talloc = hostenv.StaticLibrary('talloc',['talloc.c']) Export('talloc') -- cgit From 069e498da2a03bd253a2fcf2b7ff13f266ab63b4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 19 Sep 2005 22:01:57 +0000 Subject: r10330: Add SConscript to more subsystems. Some of the tdb tools build now. Start on custom Samba scons tools (for handling proto generation, pidl, etc) (This used to be commit 4bffe4435944fffa3f9680b5a2fe63f2bdd98003) --- source4/lib/SConscript | 8 +++----- source4/lib/basic.mk | 7 +++++-- source4/lib/charset/SConscript | 14 ++++++++++++-- source4/lib/ldb/SConscript | 29 +++++++++++++++++++++++++++++ source4/lib/popt/SConscript | 5 +++++ source4/lib/tdb/SConscript | 13 +++++++++++++ source4/lib/tdb/tools/tdbbackup.c | 2 +- 7 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 source4/lib/ldb/SConscript create mode 100644 source4/lib/tdb/SConscript (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index f1bff77cd0..a4a1f92361 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -20,8 +20,6 @@ hostenv.StaticLibrary('gencache',['gencache.c']) hostenv.StaticLibrary('pidfile',['pidfile.c']) hostenv.StaticLibrary('unix_privs',['unix_privs.c']) -SConscript('popt/SConscript','hostenv') -SConscript('cmdline/SConscript','hostenv') -SConscript('talloc/SConscript','hostenv') -SConscript('registry/SConscript','hostenv') -SConscript('charset/SConscript', 'hostenv') +SConscript(dirs=['tdb','popt','cmdline','talloc','registry','charset', + 'ldb'], + exports='hostenv') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 86392cfc40..3fa9bb354b 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -47,7 +47,6 @@ ADD_OBJ_FILES = \ lib/xfile.o \ lib/debug.o \ lib/fault.o \ - lib/pidfile.o \ lib/signal.o \ lib/system.o \ lib/time.o \ @@ -66,7 +65,6 @@ ADD_OBJ_FILES = \ lib/select.o \ lib/mutex.o \ lib/idtree.o \ - lib/unix_privs.o \ lib/db_wrap.o \ lib/gendb.o \ lib/credentials.o @@ -76,3 +74,8 @@ REQUIRED_SUBSYSTEMS = \ # End SUBSYSTEM LIBBASIC ############################## +[SUBSYSTEM::PIDFILE] +OBJ_FILES = lib/pidfile.o + +[SUBSYSTEM::UNIX_PRIVS] +OBJ_FILES = lib/unix_privs.o diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index d73d390309..7d9044d547 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -1,5 +1,15 @@ +SConscript('../../build/scons/iconv.py') # tastes like -*- python -*- - Import('hostenv') -charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c']) + +#conf = Configure(hostenv, custom_tests = { 'CheckIconv' : CheckIconv }) +#(have_iconv,iconv) = conf.CheckIconv() +#conf.Finish() + +#if not have_iconv: +# print "Install iconv for better charset compatibility" + +iconv = [] + +charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c',iconv]) Export('charset') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript new file mode 100644 index 0000000000..1698a7cff3 --- /dev/null +++ b/source4/lib/ldb/SConscript @@ -0,0 +1,29 @@ +Import('hostenv') + + +hostenv.StaticLibrary('modules/timestamps.c') +hostenv.StaticLibrary('modules/rdn_name.c') +hostenv.StaticLibrary('modules/schema.c') +hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c') +hostenv.StaticLibrary('modules/ldb_map.c') +hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') +hostenv.StaticLibrary('ldb_tdb', + ['ldb_tdb/ldb_tdb.c','ldb_tdb/ldb_search.c','ldb_tdb/ldb_pack.c', + 'ldb_tdb/ldb_index.c','ldb_tdb/ldb_cache.c','ldb_tdb/ldb_tdb_wrap.c']) + +hostenv.StaticLibrary('ldb', + ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', + 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', + 'common/ldb_debug.c','common/ldb_modules.c','common/ldb_match.c', + 'common/attrib_handlers.c','common/ldb_dn.c']) + +hostenv.StaticLibrary('samba/ldif_handlers.c') +hostenv.StaticLibrary('ldb_cmdline', 'tools/cmdline.c') + +hostenv.Program('ldbadd',['tools/ldbadd.c']) +hostenv.Program('ldbdel',['tools/ldbdel.c']) +hostenv.Program('ldbmodify',['tools/ldbmodify.c']) +hostenv.Program('ldbsearch',['tools/ldbsearch.c']) +hostenv.Program('ldbrename',['tools/ldbrename.c']) +hostenv.Program('ldbtest',['tools/ldbtest.c']) +hostenv.Program('oLschema2ldif',['tools/oLschema2ldif.c']) diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript index 580de92023..fd13edc42f 100644 --- a/source4/lib/popt/SConscript +++ b/source4/lib/popt/SConscript @@ -1,5 +1,10 @@ # tastes like -*- python -*- Import('hostenv') + +conf = Configure(hostenv) +conf.env['HAVE_EXTERNAL_POPT'] = conf.CheckLibWithHeader('popt', 'popt.h', 'c', 'poptGetArgs(NULL);') +conf.Finish() + popt = hostenv.StaticLibrary('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) Export('popt') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript new file mode 100644 index 0000000000..d2ebf7002f --- /dev/null +++ b/source4/lib/tdb/SConscript @@ -0,0 +1,13 @@ +Import('hostenv') +tdbenv = hostenv.Copy() +tdbenv.Append(CPPPATH=['include']) +tdb = tdbenv.StaticLibrary('tdb', + ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', + 'common/open.c','common/traverse.c','common/freelist.c', + 'common/error.c','common/tdbutil.c']) + +tdbtool = tdbenv.Program('tdbtool', ['tools/tdbtool.c',tdb]) +tdbtorture = tdbenv.Program('tdbtorture', ['tools/tdbtorture.c',tdb]) +tdbdump = tdbenv.Program('tdbdump', ['tools/tdbdump.c',tdb]) +tdbbackup = tdbenv.Program('tdbbackup', ['tools/tdbbackup.c',tdb]) +Default(tdbtool,tdbtorture,tdbdump,tdbbackup) diff --git a/source4/lib/tdb/tools/tdbbackup.c b/source4/lib/tdb/tools/tdbbackup.c index 4cb6a8cfdd..872ca99f0d 100644 --- a/source4/lib/tdb/tools/tdbbackup.c +++ b/source4/lib/tdb/tools/tdbbackup.c @@ -63,11 +63,11 @@ #else #include "includes.h" +#include "system/filesys.h" #endif #include "tdb.h" -#include "tdbback.h" /* see if one file is newer than another -- cgit From b1c3c66ead969ae3ab1af7cd743e893134924fec Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 19 Sep 2005 23:10:28 +0000 Subject: r10332: Fix the build - messaging uses UNIX_PRIVS (This used to be commit df4a923c64a7fffea3aa01f646b3fba7a83a1b49) --- source4/lib/messaging/config.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/config.mk b/source4/lib/messaging/config.mk index ef0ea7e6f4..c94d137d3f 100644 --- a/source4/lib/messaging/config.mk +++ b/source4/lib/messaging/config.mk @@ -6,6 +6,7 @@ INIT_OBJ_FILES = \ lib/messaging/messaging.o NOPROTO = YES REQUIRED_SUBSYSTEMS = \ - NDR_IRPC + NDR_IRPC \ + UNIX_PRIVS # End SUBSYSTEM MESSAGING ################################################ -- cgit From 6cd5ede5d5b6375cdcf6229ec612cbb3f81559f5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 19 Sep 2005 23:39:23 +0000 Subject: r10335: Build tdb tools into bin directory. (This used to be commit f35c4763d5c681a74af1f59e75a2f93e99d645cb) --- source4/lib/tdb/SConscript | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index d2ebf7002f..a8696ec367 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -6,8 +6,9 @@ tdb = tdbenv.StaticLibrary('tdb', 'common/open.c','common/traverse.c','common/freelist.c', 'common/error.c','common/tdbutil.c']) -tdbtool = tdbenv.Program('tdbtool', ['tools/tdbtool.c',tdb]) -tdbtorture = tdbenv.Program('tdbtorture', ['tools/tdbtorture.c',tdb]) -tdbdump = tdbenv.Program('tdbdump', ['tools/tdbdump.c',tdb]) -tdbbackup = tdbenv.Program('tdbbackup', ['tools/tdbbackup.c',tdb]) +tdbtool = tdbenv.Program('bin/tdbtool', ['tools/tdbtool.c',tdb]) +tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) +tdbdump = tdbenv.Program('bin/tdbdump', ['tools/tdbdump.c',tdb]) +tdbbackup = tdbenv.Program('bin/tdbbackup', ['tools/tdbbackup.c',tdb]) + Default(tdbtool,tdbtorture,tdbdump,tdbbackup) -- cgit From 5b02ee9b9d7037b385cf4f1c3eca81b28ff19690 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 20 Sep 2005 00:39:19 +0000 Subject: r10336: Add sconscript for a couple more subsystems. (This used to be commit 59d4450453c25f5cce9b67b808ff0c4433c1d194) --- source4/lib/SConscript | 4 ++-- source4/lib/ldb/SConscript | 32 ++++++++++++++++++++------------ source4/lib/messaging/SConscript | 3 +++ source4/lib/replace/SConscript | 11 +++++++++++ source4/lib/samba3/SConscript | 5 +++++ source4/lib/socket/SConscript | 6 ++++++ source4/lib/socket_wrapper/SConscript | 3 +++ source4/lib/tdb/SConscript | 1 - source4/lib/tls/SConscript | 3 +++ 9 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 source4/lib/messaging/SConscript create mode 100644 source4/lib/replace/SConscript create mode 100644 source4/lib/samba3/SConscript create mode 100644 source4/lib/socket/SConscript create mode 100644 source4/lib/socket_wrapper/SConscript create mode 100644 source4/lib/tls/SConscript (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index a4a1f92361..516537cac0 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -20,6 +20,6 @@ hostenv.StaticLibrary('gencache',['gencache.c']) hostenv.StaticLibrary('pidfile',['pidfile.c']) hostenv.StaticLibrary('unix_privs',['unix_privs.c']) -SConscript(dirs=['tdb','popt','cmdline','talloc','registry','charset', - 'ldb'], +SConscript(dirs=['replace','tdb','popt','cmdline','talloc','registry','charset', + 'ldb','tls','samba3','socket','socket_wrapper','messaging'], exports='hostenv') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index 1698a7cff3..1ef1c5f9e6 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -1,29 +1,37 @@ Import('hostenv') - +Import('talloc') hostenv.StaticLibrary('modules/timestamps.c') hostenv.StaticLibrary('modules/rdn_name.c') hostenv.StaticLibrary('modules/schema.c') hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c') hostenv.StaticLibrary('modules/ldb_map.c') -hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') + +conf = Configure(hostenv) +have_sqlite3 = conf.CheckLibWithHeader("sqlite3","sqlite3.h",'c',"sqlite3_open()") +conf.Finish() + +if have_sqlite3: + hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') + hostenv.StaticLibrary('ldb_tdb', ['ldb_tdb/ldb_tdb.c','ldb_tdb/ldb_search.c','ldb_tdb/ldb_pack.c', 'ldb_tdb/ldb_index.c','ldb_tdb/ldb_cache.c','ldb_tdb/ldb_tdb_wrap.c']) -hostenv.StaticLibrary('ldb', - ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', +ldb = hostenv.StaticLibrary('ldb', + [talloc,'common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', 'common/ldb_debug.c','common/ldb_modules.c','common/ldb_match.c', 'common/attrib_handlers.c','common/ldb_dn.c']) +Export('ldb') hostenv.StaticLibrary('samba/ldif_handlers.c') -hostenv.StaticLibrary('ldb_cmdline', 'tools/cmdline.c') +ldb_cmdline = hostenv.StaticLibrary('ldb_cmdline', 'tools/cmdline.c') -hostenv.Program('ldbadd',['tools/ldbadd.c']) -hostenv.Program('ldbdel',['tools/ldbdel.c']) -hostenv.Program('ldbmodify',['tools/ldbmodify.c']) -hostenv.Program('ldbsearch',['tools/ldbsearch.c']) -hostenv.Program('ldbrename',['tools/ldbrename.c']) -hostenv.Program('ldbtest',['tools/ldbtest.c']) -hostenv.Program('oLschema2ldif',['tools/oLschema2ldif.c']) +hostenv.Program('ldbadd',['tools/ldbadd.c',ldb,talloc,ldb_cmdline]) +hostenv.Program('ldbdel',['tools/ldbdel.c',ldb,ldb_cmdline]) +hostenv.Program('ldbmodify',['tools/ldbmodify.c',ldb,ldb_cmdline]) +hostenv.Program('ldbsearch',['tools/ldbsearch.c',ldb,ldb_cmdline]) +hostenv.Program('ldbrename',['tools/ldbrename.c',ldb,ldb_cmdline]) +hostenv.Program('ldbtest',['tools/ldbtest.c',ldb,ldb_cmdline]) +hostenv.Program('oLschema2ldif',['tools/oLschema2ldif.c',ldb]) diff --git a/source4/lib/messaging/SConscript b/source4/lib/messaging/SConscript new file mode 100644 index 0000000000..4c62ffb82e --- /dev/null +++ b/source4/lib/messaging/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') + +hostenv.StaticLibrary('messaging','messaging.c') diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript new file mode 100644 index 0000000000..f8efcc55b9 --- /dev/null +++ b/source4/lib/replace/SConscript @@ -0,0 +1,11 @@ +Import('hostenv') + +conf = Configure(hostenv) +#FIXME: conf.CheckBrokenInetNtoa() +for f in ['strtoull','__strtoull','strtouq','strtoll','__strtoll','strtoq', + 'seteuid','setresuid','setegid','setresgid']: + conf.CheckFunc(f,'c') +conf.Finish() + +hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) +hostenv.StaticLibrary('replace', ['replace.c', 'snprintf.c']) diff --git a/source4/lib/samba3/SConscript b/source4/lib/samba3/SConscript new file mode 100644 index 0000000000..7fc6e7ce37 --- /dev/null +++ b/source4/lib/samba3/SConscript @@ -0,0 +1,5 @@ +Import('hostenv') + +hostenv.StaticLibrary('samba3', + ['smbpasswd.c','tdbsam.c','policy.c','idmap.c','winsdb.c','samba3.c', + 'group.c','registry.c','secrets.c','share_info.c']) diff --git a/source4/lib/socket/SConscript b/source4/lib/socket/SConscript new file mode 100644 index 0000000000..4d81cd5696 --- /dev/null +++ b/source4/lib/socket/SConscript @@ -0,0 +1,6 @@ +Import('hostenv') + +hostenv.StaticLibrary('socket_ipv4.c') +hostenv.StaticLibrary('socket_ipv6.c') +hostenv.StaticLibrary('socket_unix.c') +hostenv.StaticLibrary('socket', ['socket.c','access.c','connect.c']) diff --git a/source4/lib/socket_wrapper/SConscript b/source4/lib/socket_wrapper/SConscript new file mode 100644 index 0000000000..fe5844d6da --- /dev/null +++ b/source4/lib/socket_wrapper/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') + +hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index a8696ec367..01f5bbe7c7 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -11,4 +11,3 @@ tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) tdbdump = tdbenv.Program('bin/tdbdump', ['tools/tdbdump.c',tdb]) tdbbackup = tdbenv.Program('bin/tdbbackup', ['tools/tdbbackup.c',tdb]) -Default(tdbtool,tdbtorture,tdbdump,tdbbackup) diff --git a/source4/lib/tls/SConscript b/source4/lib/tls/SConscript new file mode 100644 index 0000000000..88f150b9cf --- /dev/null +++ b/source4/lib/tls/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') + +hostenv.StaticLibrary('tls', ['tls.c', 'tlscert.c']) -- cgit From 6812c73534001d2dd05a9a74358d2b6d0029f1a7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 20 Sep 2005 11:59:03 +0000 Subject: r10348: Add scons scripts for remaining subsystems. Most subsystems build now, but final linking still fails (as does generating files asn1, et, idl and proto files) (This used to be commit 4f0d7f75b99c7f4388d8acb0838577d86baf68b5) --- source4/lib/SConscript | 8 ++++---- source4/lib/appweb/SConscript | 5 +++++ source4/lib/appweb/ejs/config.mk | 13 ------------- source4/lib/charset/SConscript | 4 ++-- source4/lib/cmdline/SConscript | 2 +- source4/lib/com/SConscript | 4 ++++ source4/lib/events/SConscript | 3 +++ source4/lib/messaging/SConscript | 1 - source4/lib/popt/SConscript | 5 ++--- source4/lib/registry/SConscript | 2 +- source4/lib/replace/SConscript | 2 +- source4/lib/samba3/SConscript | 1 - source4/lib/socket/SConscript | 1 - source4/lib/socket_wrapper/SConscript | 1 - source4/lib/talloc/SConscript | 2 +- source4/lib/tls/SConscript | 1 - 16 files changed, 24 insertions(+), 31 deletions(-) create mode 100644 source4/lib/appweb/SConscript delete mode 100644 source4/lib/appweb/ejs/config.mk create mode 100644 source4/lib/com/SConscript create mode 100644 source4/lib/events/SConscript (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 516537cac0..b3d949d12e 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -1,8 +1,8 @@ +Import('hostenv') # tastes like -*- python -*- -Import('hostenv') basic = hostenv.StaticLibrary('basic', - ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'pidfile.c', + ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', 'util_str.c', 'util_strlist.c', 'util_unistr.c', 'util_file.c', 'data_blob.c', 'util.c', 'util_sock.c', 'substitute.c', @@ -20,6 +20,6 @@ hostenv.StaticLibrary('gencache',['gencache.c']) hostenv.StaticLibrary('pidfile',['pidfile.c']) hostenv.StaticLibrary('unix_privs',['unix_privs.c']) -SConscript(dirs=['replace','tdb','popt','cmdline','talloc','registry','charset', - 'ldb','tls','samba3','socket','socket_wrapper','messaging'], +SConscript(dirs=['replace','tdb','popt','cmdline','talloc','registry','charset', 'ldb','tls','samba3','socket','socket_wrapper','messaging','com','events', + 'appweb'], exports='hostenv') diff --git a/source4/lib/appweb/SConscript b/source4/lib/appweb/SConscript new file mode 100644 index 0000000000..2c8238b67c --- /dev/null +++ b/source4/lib/appweb/SConscript @@ -0,0 +1,5 @@ +Import('hostenv') + +hostenv.StaticLibrary('mpr',['mpr/miniMpr.c','mpr/var.c']) +hostenv.StaticLibrary('ejs',['ejs/ejsLib.c','ejs/ejsLex.c','ejs/ejsParser.c','ejs/ejsProcs.c']) +hostenv.StaticLibrary('esp',['esp/esp.c','esp/espProcs.c']) diff --git a/source4/lib/appweb/ejs/config.mk b/source4/lib/appweb/ejs/config.mk deleted file mode 100644 index f2c0e62f1e..0000000000 --- a/source4/lib/appweb/ejs/config.mk +++ /dev/null @@ -1,13 +0,0 @@ -####################### -# Start SUBSYSTEM EJS -[SUBSYSTEM::EJS] -ADD_OBJ_FILES = \ - lib/ejs/ejsLib.o \ - lib/ejs/ejsLex.o \ - lib/ejs/ejsParser.o \ - lib/ejs/ejsProcs.o \ - lib/ejs/miniMpr.o \ - lib/ejs/var.o -NOPROTO=YES -# End SUBSYSTEM EJS -####################### diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index 7d9044d547..53e5db44bb 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -1,8 +1,8 @@ +Import('hostenv') SConscript('../../build/scons/iconv.py') # tastes like -*- python -*- -Import('hostenv') -#conf = Configure(hostenv, custom_tests = { 'CheckIconv' : CheckIconv }) +#conf = Configure( custom_tests = { 'CheckIconv' : CheckIconv }) #(have_iconv,iconv) = conf.CheckIconv() #conf.Finish() diff --git a/source4/lib/cmdline/SConscript b/source4/lib/cmdline/SConscript index 724dc07821..a99a2b4892 100644 --- a/source4/lib/cmdline/SConscript +++ b/source4/lib/cmdline/SConscript @@ -1,6 +1,6 @@ +Import('hostenv') # tastes like -*- python -*- -Import('hostenv') Import('basic param') popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param]) Export('popt_common') diff --git a/source4/lib/com/SConscript b/source4/lib/com/SConscript new file mode 100644 index 0000000000..44708bdf32 --- /dev/null +++ b/source4/lib/com/SConscript @@ -0,0 +1,4 @@ +Import('hostenv') +hostenv.StaticLibrary('com', [ 'tables.c','rot.c','main.c']) +hostenv.StaticLibrary('dcom', [ 'dcom/tables.c','dcom/main.c']) +hostenv.StaticLibrary('com_simple', ['classes/simple.c']) diff --git a/source4/lib/events/SConscript b/source4/lib/events/SConscript new file mode 100644 index 0000000000..e1ca866233 --- /dev/null +++ b/source4/lib/events/SConscript @@ -0,0 +1,3 @@ +Import('hostenv') + +hostenv.StaticLibrary('events',['events.c','events_standard.c']) diff --git a/source4/lib/messaging/SConscript b/source4/lib/messaging/SConscript index 4c62ffb82e..1d1ee5859b 100644 --- a/source4/lib/messaging/SConscript +++ b/source4/lib/messaging/SConscript @@ -1,3 +1,2 @@ Import('hostenv') - hostenv.StaticLibrary('messaging','messaging.c') diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript index fd13edc42f..78496e7e1a 100644 --- a/source4/lib/popt/SConscript +++ b/source4/lib/popt/SConscript @@ -1,8 +1,7 @@ -# tastes like -*- python -*- - Import('hostenv') +# tastes like -*- python -*- -conf = Configure(hostenv) +conf = hostenv.Configure() conf.env['HAVE_EXTERNAL_POPT'] = conf.CheckLibWithHeader('popt', 'popt.h', 'c', 'poptGetArgs(NULL);') conf.Finish() diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript index 4ea4301105..65aeb5b17a 100644 --- a/source4/lib/registry/SConscript +++ b/source4/lib/registry/SConscript @@ -1,6 +1,6 @@ +Import('hostenv') # tastes like -*- python -*- -Import('hostenv') Import('talloc basic popt_common popt param') registry = hostenv.StaticLibrary('registry', [basic,talloc,'common/reg_interface.c','common/reg_util.c']) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index f8efcc55b9..b63b544f8a 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -1,6 +1,6 @@ Import('hostenv') - conf = Configure(hostenv) + #FIXME: conf.CheckBrokenInetNtoa() for f in ['strtoull','__strtoull','strtouq','strtoll','__strtoll','strtoq', 'seteuid','setresuid','setegid','setresgid']: diff --git a/source4/lib/samba3/SConscript b/source4/lib/samba3/SConscript index 7fc6e7ce37..ba1f76b1a7 100644 --- a/source4/lib/samba3/SConscript +++ b/source4/lib/samba3/SConscript @@ -1,5 +1,4 @@ Import('hostenv') - hostenv.StaticLibrary('samba3', ['smbpasswd.c','tdbsam.c','policy.c','idmap.c','winsdb.c','samba3.c', 'group.c','registry.c','secrets.c','share_info.c']) diff --git a/source4/lib/socket/SConscript b/source4/lib/socket/SConscript index 4d81cd5696..db449592c2 100644 --- a/source4/lib/socket/SConscript +++ b/source4/lib/socket/SConscript @@ -1,5 +1,4 @@ Import('hostenv') - hostenv.StaticLibrary('socket_ipv4.c') hostenv.StaticLibrary('socket_ipv6.c') hostenv.StaticLibrary('socket_unix.c') diff --git a/source4/lib/socket_wrapper/SConscript b/source4/lib/socket_wrapper/SConscript index fe5844d6da..6ec9c338d3 100644 --- a/source4/lib/socket_wrapper/SConscript +++ b/source4/lib/socket_wrapper/SConscript @@ -1,3 +1,2 @@ Import('hostenv') - hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) diff --git a/source4/lib/talloc/SConscript b/source4/lib/talloc/SConscript index 37079c4156..ad88262f1d 100644 --- a/source4/lib/talloc/SConscript +++ b/source4/lib/talloc/SConscript @@ -1,5 +1,5 @@ +Import('hostenv') # tastes like -*- python -*- -Import('hostenv') talloc = hostenv.StaticLibrary('talloc',['talloc.c']) Export('talloc') diff --git a/source4/lib/tls/SConscript b/source4/lib/tls/SConscript index 88f150b9cf..6abcdff821 100644 --- a/source4/lib/tls/SConscript +++ b/source4/lib/tls/SConscript @@ -1,3 +1,2 @@ Import('hostenv') - hostenv.StaticLibrary('tls', ['tls.c', 'tlscert.c']) -- cgit From 920a627ba814d78a1765a6c1c7209ff29acc6153 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 20 Sep 2005 17:49:19 +0000 Subject: r10356: Make the proto generator work with scons (This used to be commit a2268f1dd441059955bee30cf2a9028656c14099) --- source4/lib/SConscript | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index b3d949d12e..8833028dbd 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -1,13 +1,13 @@ Import('hostenv') # tastes like -*- python -*- -basic = hostenv.StaticLibrary('basic', - ['version.c', 'xfile.c', 'debug.c', 'fault.c', +basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', 'util_str.c', 'util_strlist.c', 'util_unistr.c', 'util_file.c', 'data_blob.c', 'util.c', 'util_sock.c', 'substitute.c', 'fsusage.c', 'ms_fnmatch.c', 'select.c', 'mutex.c', 'idtree.c', - 'unix_privs.c', 'db_wrap.c', 'gendb.c', 'credentials.c']) + 'db_wrap.c', 'gendb.c', 'credentials.c'] +basic = hostenv.StaticLibrary('basic', basic_files) Export('basic') hostenv.StaticLibrary('netif', ['netif/interface.c', 'netif/netif.c']) -- cgit From 65d4da0ff330740788c4386a71526b6ed3e10162 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 20 Sep 2005 21:29:29 +0000 Subject: r10364: Turn gensec:gssapi on by default, except for a login of the form -Udomain\\user. This will probably break in a few configurations, so please let me know. I'll also work to have a way to inhibit kerberos/ntlmssp, as this removes -k. Andrew Bartlett (This used to be commit 3c0dc570b86e79aea5446d7c3bb9750a11bf8ca4) --- source4/lib/cmdline/popt_common.c | 11 ----------- source4/lib/credentials.c | 10 +++++++--- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index fe76292acb..43ea203b78 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -241,17 +241,7 @@ static void popt_common_credentials_callback(poptContext con, cli_credentials_set_machine_account_pending(cmdline_credentials); /* machine accounts only work with kerberos (fall though)*/ - - case 'k': -#ifndef HAVE_KRB5 - d_printf("No kerberos support compiled in\n"); - exit(1); -#else - lp_set_cmdline("gensec:krb5", "True"); -#endif break; - - } } @@ -261,7 +251,6 @@ struct poptOption popt_common_credentials[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN\\]USERNAME[%PASSWORD]" }, { "no-pass", 'N', POPT_ARG_NONE, &dont_ask, True, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, NULL, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password (implies -k)" }, diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index cdef9042b8..4650fee1af 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -121,9 +121,13 @@ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_C } if (cred->principal_obtained < cred->username_obtained) { - return talloc_asprintf(mem_ctx, "%s@%s", - cli_credentials_get_username(cred, mem_ctx), - cli_credentials_get_realm(cred)); + if (cred->domain_obtained > cred->realm_obtained) { + return NULL; + } else { + return talloc_asprintf(mem_ctx, "%s@%s", + cli_credentials_get_username(cred, mem_ctx), + cli_credentials_get_realm(cred)); + } } return talloc_reference(mem_ctx, cred->principal); } -- cgit From 8db177b652cdede2f509d6c96d1c99e875c2d284 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 20 Sep 2005 22:10:40 +0000 Subject: r10366: More scons fixes. Building et, asn1, lex and yacc files sort-of works now (This used to be commit 22f18a84242e5e68a2d57b6d7ff77c089ee7434a) --- source4/lib/SConscript | 3 +-- source4/lib/genrand.c | 1 - source4/lib/ldb/SConscript | 1 + source4/lib/registry/SConscript | 9 +++++++-- source4/lib/socket_wrapper/SConscript | 5 +++++ source4/lib/tls/SConscript | 4 ++++ 6 files changed, 18 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 8833028dbd..9c56310829 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -21,5 +21,4 @@ hostenv.StaticLibrary('pidfile',['pidfile.c']) hostenv.StaticLibrary('unix_privs',['unix_privs.c']) SConscript(dirs=['replace','tdb','popt','cmdline','talloc','registry','charset', 'ldb','tls','samba3','socket','socket_wrapper','messaging','com','events', - 'appweb'], - exports='hostenv') + 'appweb']) diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c index ca79116b6a..1149314d0b 100644 --- a/source4/lib/genrand.c +++ b/source4/lib/genrand.c @@ -167,7 +167,6 @@ static int do_reseed(BOOL use_fd, int fd) /* Add in some secret file contents */ do_filehash("/etc/shadow", &seed_inbuf[0]); - do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]); /* * Add the counter, time of day, and pid. diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index 1ef1c5f9e6..1079a441d8 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -9,6 +9,7 @@ hostenv.StaticLibrary('modules/ldb_map.c') conf = Configure(hostenv) have_sqlite3 = conf.CheckLibWithHeader("sqlite3","sqlite3.h",'c',"sqlite3_open()") +have_popt = conf.CheckLibWithHeader("popt","popt.h",'c',"poptGetArgs(NULL);") conf.Finish() if have_sqlite3: diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript index 65aeb5b17a..a90557532b 100644 --- a/source4/lib/registry/SConscript +++ b/source4/lib/registry/SConscript @@ -1,7 +1,12 @@ -Import('hostenv') +Import('hostenv paths') # tastes like -*- python -*- Import('talloc basic popt_common popt param') registry = hostenv.StaticLibrary('registry', [basic,talloc,'common/reg_interface.c','common/reg_util.c']) -hostenv.Program('regtree', ['tools/regtree.c',registry,talloc,basic,popt_common,popt,param]) +regtree = hostenv.Program('regtree', ['tools/regtree.c',registry,talloc,basic,popt_common,popt,param]) +regshell = hostenv.Program('regshell', ['tools/regshell.c',registry,talloc,basic,popt_common,popt,param]) +regpatch = hostenv.Program('regpatch', ['tools/regpatch.c',registry,talloc,basic,popt_common,popt,param]) +regdiff = hostenv.Program('regdiff', ['tools/regdiff.c',registry,talloc,basic,popt_common,popt,param]) + +hostenv.Install(paths['BINDIR'], [regtree,regshell,regpatch,regdiff]) diff --git a/source4/lib/socket_wrapper/SConscript b/source4/lib/socket_wrapper/SConscript index 6ec9c338d3..ac9e0466b2 100644 --- a/source4/lib/socket_wrapper/SConscript +++ b/source4/lib/socket_wrapper/SConscript @@ -1,2 +1,7 @@ Import('hostenv') hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) + +opts = Options(None, ARGUMENTS) +opts.AddOptions( + BoolOption('socket-wrapper','enable socket wrapper',0) +) diff --git a/source4/lib/tls/SConscript b/source4/lib/tls/SConscript index 6abcdff821..3b1a1d7d4e 100644 --- a/source4/lib/tls/SConscript +++ b/source4/lib/tls/SConscript @@ -1,2 +1,6 @@ Import('hostenv') hostenv.StaticLibrary('tls', ['tls.c', 'tlscert.c']) + +conf = hostenv.Configure() +conf.CheckLibWithHeader('gnutls', 'gnutls/gnutls.h', 'c', 'gnutls_global_init()') +conf.Finish() -- cgit From 9d44a9a351e6c830ca18a0129bb11b3f99d53c4b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 21 Sep 2005 00:38:23 +0000 Subject: r10374: Add HAVE_* defines (on command-line or in config.h file) for scons + some other minor updates (This used to be commit f142c15de1afb2f13a5e23ceb40ce70f0115c8bf) --- source4/lib/SConscript | 20 ++++++++++++++++---- source4/lib/cmdline/SConscript | 4 ++-- source4/lib/socket_wrapper/SConscript | 11 +++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 9c56310829..387f557932 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -1,13 +1,16 @@ Import('hostenv') # tastes like -*- python -*- +SConscript(dirs=['talloc','charset']) +Import('talloc dynconfig charset') + basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', 'util_str.c', 'util_strlist.c', 'util_unistr.c', 'util_file.c', 'data_blob.c', 'util.c', 'util_sock.c', 'substitute.c', 'fsusage.c', 'ms_fnmatch.c', 'select.c', 'mutex.c', 'idtree.c', - 'db_wrap.c', 'gendb.c', 'credentials.c'] -basic = hostenv.StaticLibrary('basic', basic_files) + 'db_wrap.c'] +basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files]) Export('basic') hostenv.StaticLibrary('netif', ['netif/interface.c', 'netif/netif.c']) @@ -20,5 +23,14 @@ hostenv.StaticLibrary('gencache',['gencache.c']) hostenv.StaticLibrary('pidfile',['pidfile.c']) hostenv.StaticLibrary('unix_privs',['unix_privs.c']) -SConscript(dirs=['replace','tdb','popt','cmdline','talloc','registry','charset', 'ldb','tls','samba3','socket','socket_wrapper','messaging','com','events', - 'appweb']) +SConscript(dirs=['ldb']) + +Import('ldb') +gendb = hostenv.StaticLibrary('gendb', ['gendb.c',ldb]) +Export('gendb') + +credentials = hostenv.StaticLibrary('credentials',['credentials.c',basic,gendb]) +Export('credentials') + +SConscript(dirs=['../param/','replace','tdb','popt','cmdline','registry', 'tls','samba3','socket','socket_wrapper','messaging','com','events', 'appweb']) + diff --git a/source4/lib/cmdline/SConscript b/source4/lib/cmdline/SConscript index a99a2b4892..12f4f7c11c 100644 --- a/source4/lib/cmdline/SConscript +++ b/source4/lib/cmdline/SConscript @@ -1,6 +1,6 @@ Import('hostenv') # tastes like -*- python -*- -Import('basic param') -popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param]) +Import('basic param credentials') +popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param,credentials]) Export('popt_common') diff --git a/source4/lib/socket_wrapper/SConscript b/source4/lib/socket_wrapper/SConscript index ac9e0466b2..1c0253a0d4 100644 --- a/source4/lib/socket_wrapper/SConscript +++ b/source4/lib/socket_wrapper/SConscript @@ -1,7 +1,14 @@ Import('hostenv') -hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) opts = Options(None, ARGUMENTS) opts.AddOptions( - BoolOption('socket-wrapper','enable socket wrapper',0) + BoolOption('socket_wrapper','enable socket wrapper',0) ) + +opts.Update(hostenv) + +if hostenv['socket_wrapper']: + hostenv.Append(CPPDEFINES = {'HAVE_SOCKET_WRAPPER': 1}) + socket_wrapper = hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) +else: + socket_wrapper = [] -- cgit From d191c7d9932b8e8ad96c4345a6ceca67326806ac Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 21 Sep 2005 05:39:18 +0000 Subject: r10377: Save configuration stuff to sconf.cache so it isn't annoyingly run at every single build. Run 'scons configure=1' or delete sconf.cache to force checks to be re-run. Jelmer, I think this stuff is cached in the .sconf_cache directory but the message is still displayed and it looks like it caches the compiled test object file not the actual result of the test. (This used to be commit 9d001dc083937bbf5642af90bc8a8b1a27825de0) --- source4/lib/ldb/SConscript | 13 ++++++++----- source4/lib/popt/SConscript | 10 ++++++---- source4/lib/replace/SConscript | 13 +++++++------ source4/lib/tls/SConscript | 7 ++++--- 4 files changed, 25 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index 1079a441d8..b726d0ebc9 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -1,5 +1,6 @@ Import('hostenv') Import('talloc') +Import('defines') hostenv.StaticLibrary('modules/timestamps.c') hostenv.StaticLibrary('modules/rdn_name.c') @@ -7,12 +8,14 @@ hostenv.StaticLibrary('modules/schema.c') hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c') hostenv.StaticLibrary('modules/ldb_map.c') -conf = Configure(hostenv) -have_sqlite3 = conf.CheckLibWithHeader("sqlite3","sqlite3.h",'c',"sqlite3_open()") -have_popt = conf.CheckLibWithHeader("popt","popt.h",'c',"poptGetArgs(NULL);") -conf.Finish() +if hostenv['configure']: + conf = Configure(hostenv) + if conf.CheckLibWithHeader("sqlite3","sqlite3.h",'c',"sqlite3_open()"): + defines['HAVE_SQLITE3'] = 1 + conf.CheckLibWithHeader("popt","popt.h",'c',"poptGetArgs(NULL);") + conf.Finish() -if have_sqlite3: +if defines.has_key('HAVE_SQLITE3'): hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') hostenv.StaticLibrary('ldb_tdb', diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript index 78496e7e1a..85f9c9b7e0 100644 --- a/source4/lib/popt/SConscript +++ b/source4/lib/popt/SConscript @@ -1,9 +1,11 @@ -Import('hostenv') # tastes like -*- python -*- +Import('hostenv') + -conf = hostenv.Configure() -conf.env['HAVE_EXTERNAL_POPT'] = conf.CheckLibWithHeader('popt', 'popt.h', 'c', 'poptGetArgs(NULL);') -conf.Finish() +if hostenv['configure']: + conf = hostenv.Configure() + conf.env['HAVE_EXTERNAL_POPT'] = conf.CheckLibWithHeader('popt', 'popt.h', 'c', 'poptGetArgs(NULL);') + conf.Finish() popt = hostenv.StaticLibrary('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) Export('popt') diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index b63b544f8a..84088db162 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -1,11 +1,12 @@ Import('hostenv') -conf = Configure(hostenv) -#FIXME: conf.CheckBrokenInetNtoa() -for f in ['strtoull','__strtoull','strtouq','strtoll','__strtoll','strtoq', - 'seteuid','setresuid','setegid','setresgid']: - conf.CheckFunc(f,'c') -conf.Finish() +if hostenv['configure']: + conf = Configure(hostenv) + #FIXME: conf.CheckBrokenInetNtoa() + for f in ['strtoull','__strtoull','strtouq','strtoll','__strtoll','strtoq', + 'seteuid','setresuid','setegid','setresgid']: + conf.CheckFunc(f,'c') + conf.Finish() hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) hostenv.StaticLibrary('replace', ['replace.c', 'snprintf.c']) diff --git a/source4/lib/tls/SConscript b/source4/lib/tls/SConscript index 3b1a1d7d4e..941955e9e3 100644 --- a/source4/lib/tls/SConscript +++ b/source4/lib/tls/SConscript @@ -1,6 +1,7 @@ Import('hostenv') hostenv.StaticLibrary('tls', ['tls.c', 'tlscert.c']) -conf = hostenv.Configure() -conf.CheckLibWithHeader('gnutls', 'gnutls/gnutls.h', 'c', 'gnutls_global_init()') -conf.Finish() +if hostenv['configure']: + conf = hostenv.Configure() + conf.CheckLibWithHeader('gnutls', 'gnutls/gnutls.h', 'c', 'gnutls_global_init()') + conf.Finish() -- cgit From 3e4f47aaff41b5bb6d1d86025915a3a63dc1ea73 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 21 Sep 2005 07:20:58 +0000 Subject: r10379: Add files for ldb and tdb to proto_files. The tool for building proto.h is busted though. (This used to be commit 54882f88cad1427b6adcb4c956a63e534e7d13e4) --- source4/lib/ldb/SConscript | 28 +++++++++++++++++----------- source4/lib/tdb/SConscript | 14 +++++++++----- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index b726d0ebc9..52d6b87d02 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -1,6 +1,6 @@ -Import('hostenv') -Import('talloc') -Import('defines') +# tastes like -*- python -*- + +Import('hostenv', 'talloc', 'defines', 'proto_files') hostenv.StaticLibrary('modules/timestamps.c') hostenv.StaticLibrary('modules/rdn_name.c') @@ -18,15 +18,21 @@ if hostenv['configure']: if defines.has_key('HAVE_SQLITE3'): hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') -hostenv.StaticLibrary('ldb_tdb', - ['ldb_tdb/ldb_tdb.c','ldb_tdb/ldb_search.c','ldb_tdb/ldb_pack.c', - 'ldb_tdb/ldb_index.c','ldb_tdb/ldb_cache.c','ldb_tdb/ldb_tdb_wrap.c']) +ldb_tdb_source = ['ldb_tdb/ldb_tdb.c', 'ldb_tdb/ldb_search.c', + 'ldb_tdb/ldb_pack.c', 'ldb_tdb/ldb_index.c', + 'ldb_tdb/ldb_cache.c', 'ldb_tdb/ldb_tdb_wrap.c'] + +hostenv.StaticLibrary('ldb_tdb', ldb_tdb_source) +proto_files += [File(x) for x in ldb_tdb_source] + +ldb_source = ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', + 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', + 'common/ldb_debug.c','common/ldb_modules.c','common/ldb_match.c', + 'common/attrib_handlers.c','common/ldb_dn.c'] + +ldb = hostenv.StaticLibrary('ldb', ldb_source + talloc) +proto_files += [File(x) for x in ldb_source] -ldb = hostenv.StaticLibrary('ldb', - [talloc,'common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', - 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', - 'common/ldb_debug.c','common/ldb_modules.c','common/ldb_match.c', - 'common/attrib_handlers.c','common/ldb_dn.c']) Export('ldb') hostenv.StaticLibrary('samba/ldif_handlers.c') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index 01f5bbe7c7..728160f959 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -1,10 +1,14 @@ -Import('hostenv') +Import('hostenv', 'proto_files') tdbenv = hostenv.Copy() tdbenv.Append(CPPPATH=['include']) -tdb = tdbenv.StaticLibrary('tdb', - ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', - 'common/open.c','common/traverse.c','common/freelist.c', - 'common/error.c','common/tdbutil.c']) + +tdb_files = ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', + 'common/open.c','common/traverse.c','common/freelist.c', + 'common/error.c','common/tdbutil.c'] + +tdb = tdbenv.StaticLibrary('tdb', tdb_files) + +proto_files += [File(x) for x in tdb_files] tdbtool = tdbenv.Program('bin/tdbtool', ['tools/tdbtool.c',tdb]) tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) -- cgit From 9ae24d8058ed03410ce80d0e0d825b948b2b3bd3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Sep 2005 10:45:47 +0000 Subject: r10384: add _GNU_SOURCE in tdb configure (This used to be commit 21e5c328a033a4b452b3fd696069ad8bbfa6b9cc) --- source4/lib/tdb/configure.in | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/configure.in b/source4/lib/tdb/configure.in index 9ff8e23bf1..68ea39c140 100644 --- a/source4/lib/tdb/configure.in +++ b/source4/lib/tdb/configure.in @@ -4,5 +4,6 @@ AC_INIT(include/tdb.h) AC_CONFIG_HEADER(include/tdbconfig.h) AC_PROG_CC AC_FUNC_MMAP +AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) sinclude(config.m4) AC_OUTPUT(Makefile tdb.pc) -- cgit From 8f334f69b5d5fcae4a7b2b70e18b7062c46c719e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 Sep 2005 10:46:02 +0000 Subject: r10385: removed obsolete comment (This used to be commit 40a8ad2d1eb26d1635b8f188036b04319ffd41b4) --- source4/lib/tdb/docs/README | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/docs/README b/source4/lib/tdb/docs/README index fac3eacb4d..664d65ffd9 100644 --- a/source4/lib/tdb/docs/README +++ b/source4/lib/tdb/docs/README @@ -15,7 +15,6 @@ Compilation ----------- add HAVE_MMAP=1 to use mmap instead of read/write -add TDB_DEBUG=1 for verbose debug info add NOLOCK=1 to disable locking code Testing -- cgit From 51cbc188df03f9ee38599fe5a87ec2608117a845 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 22 Sep 2005 01:50:58 +0000 Subject: r10402: Make the RPC-SAMLOGON test pass against Win2k3 SP0 again. I still have issues with Win2k3 SP1, and Samba4 doesn't pass it's own test for the moment, but I'm working on these issues :-) This required a change to the credentials API, so that the special case for NTLM logins using a principal was indeed handled as a special, not general case. Also don't set the realm from a ccache, as then it overrides --option=realm=. Andrew Bartlett (This used to be commit 194e8f07c0cb4685797c5a7a074577c62dfdebe3) --- source4/lib/cmdline/credentials.c | 3 +-- source4/lib/credentials.c | 36 ++++++++++++++++++++---------------- source4/lib/messaging/config.mk | 2 ++ 3 files changed, 23 insertions(+), 18 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/credentials.c b/source4/lib/cmdline/credentials.c index f164663118..a3d4920e6d 100644 --- a/source4/lib/cmdline/credentials.c +++ b/source4/lib/cmdline/credentials.c @@ -32,8 +32,7 @@ static const char *cmdline_get_userpassword(struct cli_credentials *credentials) const char *username; TALLOC_CTX *mem_ctx = talloc_new(NULL); - domain = cli_credentials_get_domain(credentials); - username = cli_credentials_get_username(credentials, mem_ctx); + cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain); if (domain && domain[0]) { prompt = talloc_asprintf(mem_ctx, "Password for [%s\\%s]:", domain, username); diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 4650fee1af..045047d358 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -58,23 +58,18 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) * @retval The username set on this context. * @note Return value will never be NULL except by programmer error. */ -const char *cli_credentials_get_username(struct cli_credentials *cred, TALLOC_CTX *mem_ctx) +const char *cli_credentials_get_username(struct cli_credentials *cred) { if (cred->machine_account_pending) { cli_credentials_set_machine_account(cred); } - /* If we have a principal set on this, we want to login with "" domain and user@realm */ - if (cred->username_obtained < cred->principal_obtained) { - return cli_credentials_get_principal(cred, mem_ctx); - } - if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; } - return talloc_reference(mem_ctx, cred->username); + return cred->username; } BOOL cli_credentials_set_username(struct cli_credentials *cred, @@ -122,10 +117,12 @@ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_C if (cred->principal_obtained < cred->username_obtained) { if (cred->domain_obtained > cred->realm_obtained) { - return NULL; + return talloc_asprintf(mem_ctx, "%s@%s", + cli_credentials_get_username(cred), + cli_credentials_get_domain(cred)); } else { return talloc_asprintf(mem_ctx, "%s@%s", - cli_credentials_get_username(cred, mem_ctx), + cli_credentials_get_username(cred), cli_credentials_get_realm(cred)); } } @@ -283,7 +280,6 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred, realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ); - cli_credentials_set_realm(cred, *realm, obtained); cli_credentials_set_principal(cred, name, obtained); free(name); @@ -466,11 +462,6 @@ const char *cli_credentials_get_domain(struct cli_credentials *cred) cli_credentials_set_machine_account(cred); } - /* If we have a principal set on this, we want to login with "" domain and user@realm */ - if (cred->domain_obtained < cred->principal_obtained) { - return ""; - } - if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -505,6 +496,19 @@ BOOL cli_credentials_set_domain_callback(struct cli_credentials *cred, return False; } +void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, + const char **username, + const char **domain) +{ + if (cred->principal_obtained > cred->username_obtained) { + *domain = talloc_strdup(mem_ctx, ""); + *username = cli_credentials_get_principal(cred, mem_ctx); + } else { + *domain = cli_credentials_get_domain(cred); + *username = cli_credentials_get_username(cred); + } +} + /** * Obtain the Kerberos realm for this credentials context. * @param cred credentials context @@ -1028,7 +1032,7 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) { TALLOC_CTX *tmp_ctx = talloc_new(cred); - const char *username = cli_credentials_get_username(cred, tmp_ctx); + const char *username = cli_credentials_get_username(cred); /* Yes, it is deliberate that we die if we have a NULL pointer * here - anonymous is "", not NULL, which is 'never specified, diff --git a/source4/lib/messaging/config.mk b/source4/lib/messaging/config.mk index c94d137d3f..2cba66f0a3 100644 --- a/source4/lib/messaging/config.mk +++ b/source4/lib/messaging/config.mk @@ -4,6 +4,8 @@ [SUBSYSTEM::MESSAGING] INIT_OBJ_FILES = \ lib/messaging/messaging.o +# \ +# lib/messaging/msgutil.o NOPROTO = YES REQUIRED_SUBSYSTEMS = \ NDR_IRPC \ -- cgit From cd67aa92a52c4acbb728b2ce49aad33ff53a25a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 03:51:50 +0000 Subject: r10403: fixed the basedn for testing, and add a debug showing the size of the test in ldbtest (This used to be commit 740b9f7537d60c7dbd48fe592587b12b304c52d1) --- source4/lib/ldb/tools/ldbtest.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 68d3ab2484..eeedd49e84 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -383,11 +383,14 @@ static void usage(void) talloc_steal(mem_ctx, options); if (options->basedn == NULL) { - options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=US"; + options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST"; } srandom(1); + printf("Testing with num-records=%d and num-searches=%d\n", + options->num_records, options->num_searches); + start_test(ldb, options->num_records, options->num_searches); start_test_index(&ldb); -- cgit From ede8415d61b6791114c65de1c283a4e8c11f1585 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 03:56:41 +0000 Subject: r10405: added transactions into tdb, and hook them into ldb. See my samba-technical posting for more details on the transactions design. This also adds a number of command line arguments to tdbtorture, making it more flexible, and fixes some lock deadlock conditions in the tdbtorture code. (This used to be commit 06bd8abba942ec9f1e23f5c5d546cbb71ca3a701) --- source4/lib/ldb/Makefile.in | 3 +- source4/lib/ldb/configure.in | 1 + source4/lib/ldb/ldb_tdb/ldb_tdb.c | 24 +- source4/lib/tdb/Makefile.in | 5 +- source4/lib/tdb/common/dump.c | 6 +- source4/lib/tdb/common/error.c | 1 + source4/lib/tdb/common/freelist.c | 16 +- source4/lib/tdb/common/io.c | 60 ++- source4/lib/tdb/common/lock.c | 50 +- source4/lib/tdb/common/open.c | 42 +- source4/lib/tdb/common/tdb.c | 4 +- source4/lib/tdb/common/tdb_private.h | 47 +- source4/lib/tdb/common/transaction.c | 976 +++++++++++++++++++++++++++++++++++ source4/lib/tdb/common/traverse.c | 2 +- source4/lib/tdb/config.mk | 2 +- source4/lib/tdb/configure.in | 2 +- source4/lib/tdb/docs/README | 51 ++ source4/lib/tdb/include/tdb.h | 17 +- source4/lib/tdb/tools/tdbtool.c | 26 +- source4/lib/tdb/tools/tdbtorture.c | 129 +++-- 20 files changed, 1348 insertions(+), 116 deletions(-) create mode 100644 source4/lib/tdb/common/transaction.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in index b40933bc0d..2ffe6d25b8 100644 --- a/source4/lib/ldb/Makefile.in +++ b/source4/lib/ldb/Makefile.in @@ -44,7 +44,8 @@ LIB_FLAGS=-Llib -lldb $(LDAP_LIBS) $(SQLITE3_LIBS) $(GCOV_LIBS) @LIBS@ TDB_OBJ=$(TDBDIR)/common/tdb.o $(TDBDIR)/common/dump.o \ $(TDBDIR)/common/io.o $(TDBDIR)/common/lock.o \ $(TDBDIR)/common/open.o $(TDBDIR)/common/traverse.o \ - $(TDBDIR)/common/freelist.o $(TDBDIR)/common/error.o + $(TDBDIR)/common/freelist.o $(TDBDIR)/common/error.o \ + $(TDBDIR)/common/transaction.o TALLOC_OBJ=$(TALLOCDIR)/talloc.o LDB_TDB_OBJ=ldb_tdb/ldb_tdb.o \ diff --git a/source4/lib/ldb/configure.in b/source4/lib/ldb/configure.in index 7ae339c103..8b9e599892 100644 --- a/source4/lib/ldb/configure.in +++ b/source4/lib/ldb/configure.in @@ -34,4 +34,5 @@ WITH_SQLITE3=$with_sqlite3_support AC_SUBST(WITH_SQLITE3) sinclude(config.m4) sinclude(../talloc/config.m4) +sinclude(../tdb/config.m4) AC_OUTPUT(Makefile ldb.pc) diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 265e04a057..c056bd2e2d 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -833,14 +833,28 @@ failed: static int ltdb_start_trans(struct ldb_module *module) { - /* TODO: implement transactions */ + struct ltdb_private *ltdb = module->private_data; + + if (tdb_transaction_start(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } return LDB_ERR_SUCCESS; } static int ltdb_end_trans(struct ldb_module *module, int status) { - /* TODO: implement transactions */ + struct ltdb_private *ltdb = module->private_data; + + if (status != LDB_ERR_SUCCESS) { + if (tdb_transaction_cancel(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } else { + if (tdb_transaction_commit(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } return status; } @@ -881,6 +895,12 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, tdb_flags = TDB_DEFAULT; +#if 0 + /* set this to run tdb without disk sync, but still with + transactions */ + tdb_flags |= TDB_NOSYNC; +#endif + if (flags & LDB_FLG_RDONLY) { open_flags = O_RDONLY; } else { diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index 2fc77242b2..1942d9050a 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -2,7 +2,7 @@ # Makefile for tdb directory # -CFLAGS = -DTDB_DEBUG -g -Iinclude +CFLAGS = -Iinclude @CFLAGS@ CC = @CC@ prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -12,7 +12,8 @@ libdir = @libdir@ PROGS = bin/tdbtool bin/tdbtorture TDB_OBJ = common/tdb.o common/dump.o common/io.o common/lock.o \ - common/open.o common/traverse.o common/freelist.o common/error.o + common/open.o common/traverse.o common/freelist.o common/error.o \ + common/transaction.o all: $(PROGS) diff --git a/source4/lib/tdb/common/dump.c b/source4/lib/tdb/common/dump.c index 0e203cc0d8..577f23aac6 100644 --- a/source4/lib/tdb/common/dump.c +++ b/source4/lib/tdb/common/dump.c @@ -33,7 +33,8 @@ static tdb_off_t tdb_dump_record(struct tdb_context *tdb, tdb_off_t offset) struct list_struct rec; tdb_off_t tailer_ofs, tailer; - if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { printf("ERROR: failed to read record at %u\n", offset); return 0; } @@ -107,7 +108,8 @@ int tdb_printfreelist(struct tdb_context *tdb) printf("freelist top=[0x%08x]\n", rec_ptr ); while (rec_ptr) { - if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) { + if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { tdb_unlock(tdb, -1, F_WRLCK); return -1; } diff --git a/source4/lib/tdb/common/error.c b/source4/lib/tdb/common/error.c index 5b7696877c..270a441463 100644 --- a/source4/lib/tdb/common/error.c +++ b/source4/lib/tdb/common/error.c @@ -42,6 +42,7 @@ static struct tdb_errname { {TDB_ERR_OOM, "Out of memory"}, {TDB_ERR_EXISTS, "Record exists"}, {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_EINVAL, "Invalid parameter"}, {TDB_ERR_NOEXIST, "Record does not exist"} }; /* Error string for the last tdb error */ diff --git a/source4/lib/tdb/common/freelist.c b/source4/lib/tdb/common/freelist.c index 018b7bc298..9707295ec3 100644 --- a/source4/lib/tdb/common/freelist.c +++ b/source4/lib/tdb/common/freelist.c @@ -31,7 +31,7 @@ /* read a freelist record and check for simple errors */ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) { - if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) return -1; if (rec->magic == TDB_MAGIC) { @@ -40,7 +40,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", rec->magic, off)); rec->magic = TDB_FREE_MAGIC; - if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) return -1; } @@ -51,7 +51,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str rec->magic, off)); return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); } - if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) return -1; return 0; } @@ -111,7 +111,7 @@ int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) if (right + sizeof(*rec) <= tdb->map_size) { struct list_struct r; - if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); goto left; } @@ -138,10 +138,16 @@ left: TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); goto update; } + + /* it could be uninitialised data */ + if (leftsize == 0 || leftsize == TDB_PAD_U32) { + goto update; + } + left = offset - leftsize; /* Now read in record */ - if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); goto update; } diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index 97da809bc6..f02cd1a0e1 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -56,7 +56,7 @@ if necessary note that "len" is the minimum length needed for the db */ -int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) { struct stat st; if (len <= tdb->map_size) @@ -94,9 +94,10 @@ int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) } /* write a lump of data at a specified offset */ -int tdb_write(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len) +static int tdb_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) { - if (tdb_oob(tdb, off + len, 0) != 0) + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) return -1; if (tdb->map_ptr) { @@ -122,9 +123,10 @@ void *tdb_convert(void *buf, u32 size) /* read a lump of data at a specified offset, maybe convert */ -int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv) +static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) { - if (tdb_oob(tdb, off + len, 0) != 0) { + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { return -1; } @@ -140,8 +142,9 @@ int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, i return TDB_ERRCODE(TDB_ERR_IO, -1); } } - if (cv) + if (cv) { tdb_convert(buf, len); + } return 0; } @@ -151,7 +154,7 @@ int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, i do an unlocked scan of the hash table heads to find the next non-zero head. The value will then be confirmed with the lock held */ -void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) +static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) { u32 h = *chain; if (tdb->map_ptr) { @@ -230,9 +233,10 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad } } - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ - memset(buf, 0x42, sizeof(buf)); + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ + memset(buf, TDB_PAD_BYTE, sizeof(buf)); while (addition) { int n = addition>sizeof(buf)?sizeof(buf):addition; int ret = pwrite(tdb->fd, buf, n, size); @@ -261,11 +265,11 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) } /* must know about any previous expansions by another process */ - tdb_oob(tdb, tdb->map_size + 1, 1); + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); /* always make room for at least 10 more records, and round - the database up to a multiple of TDB_PAGE_SIZE */ - size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size; + the database up to a multiple of the page size */ + size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size; if (!(tdb->flags & TDB_INTERNAL)) tdb_munmap(tdb); @@ -278,7 +282,7 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) /* expand the file itself */ if (!(tdb->flags & TDB_INTERNAL)) { - if (tdb_expand_file(tdb, tdb->map_size, size) != 0) + if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) goto fail; } @@ -321,13 +325,13 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) /* read/write a tdb_off_t */ int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) { - return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); + return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); } int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) { tdb_off_t off = *d; - return tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); + return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); } @@ -343,7 +347,7 @@ unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len len, strerror(errno))); return TDB_ERRCODE(TDB_ERR_OOM, buf); } - if (tdb_read(tdb, offset, buf, len, 0) == -1) { + if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { SAFE_FREE(buf); return NULL; } @@ -353,7 +357,7 @@ unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len /* read/write a record */ int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) { - if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) return -1; if (TDB_BAD_MAGIC(rec)) { /* Ensure ecode is set for log fn. */ @@ -361,12 +365,28 @@ int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct * TDB_LOG((tdb, 0,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); } - return tdb_oob(tdb, rec->next+sizeof(*rec), 0); + return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); } int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) { struct list_struct r = *rec; - return tdb_write(tdb, offset, CONVERT(r), sizeof(r)); + return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); } +static const struct tdb_methods io_methods = { + .tdb_read = tdb_read, + .tdb_write = tdb_write, + .next_hash_chain = tdb_next_hash_chain, + .tdb_oob = tdb_oob, + .tdb_expand_file = tdb_expand_file, + .tdb_brlock = tdb_brlock +}; + +/* + initialise the default methods table +*/ +void tdb_io_init(struct tdb_context *tdb) +{ + tdb->methods = &io_methods; +} diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 596f7bfc95..8061bab7b1 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -32,9 +32,12 @@ this functions locks/unlocks 1 byte at the specified offset. On error, errno is also set so that errors are passed back properly - through tdb_open(). */ -int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, - int rw_type, int lck_type, int probe) + through tdb_open(). + + note that a len of zero means lock to end of file +*/ +int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len) { struct flock fl; int ret; @@ -49,7 +52,7 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, fl.l_type = rw_type; fl.l_whence = SEEK_SET; fl.l_start = offset; - fl.l_len = 1; + fl.l_len = len; fl.l_pid = 0; do { @@ -57,25 +60,36 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, } while (ret == -1 && errno == EINTR); if (ret == -1) { - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); - } /* Generic lock error. errno set by fcntl. * EAGAIN is an expected return from non-blocking * locks. */ if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", + TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", tdb->fd, offset, rw_type, lck_type, strerror(errno))); + } else if (!probe && lck_type != F_SETLK) { + /* Ensure error code is set for log fun to examine. */ + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", + tdb->fd, offset, rw_type, lck_type)); } return TDB_ERRCODE(TDB_ERR_LOCK, -1); } return 0; } + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). */ +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe) +{ + return tdb_brlock_len(tdb, offset, rw_type, lck_type, probe, 1); +} + /* lock a list in the database. list -1 is the alloc list */ int tdb_lock(struct tdb_context *tdb, int list, int ltype) { @@ -90,12 +104,13 @@ int tdb_lock(struct tdb_context *tdb, int list, int ltype) /* Since fcntl locks don't nest, we do a lock for the first one, and simply bump the count for future ones */ if (tdb->locked[list+1].count == 0) { - if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { + if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", list, ltype, strerror(errno))); return -1; } tdb->locked[list+1].ltype = ltype; + tdb->num_locks++; } tdb->locked[list+1].count++; return 0; @@ -124,7 +139,8 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) if (tdb->locked[list+1].count == 1) { /* Down to last nested lock: unlock underneath */ - ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0); + tdb->num_locks--; } else { ret = 0; } @@ -194,7 +210,7 @@ int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) /* record lock stops delete underneath */ int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) { - return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; + return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0; } /* @@ -208,7 +224,7 @@ int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) for (i = &tdb->travlocks; i; i = i->next) if (i->off == off) return -1; - return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); + return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1); } /* @@ -217,7 +233,7 @@ int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) */ int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) { - return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); + return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0); } /* fcntl locks don't stack: avoid unlocking someone else's */ @@ -231,5 +247,5 @@ int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) for (i = &tdb->travlocks; i; i = i->next) if (i->off == off) count++; - return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); + return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0); } diff --git a/source4/lib/tdb/common/open.c b/source4/lib/tdb/common/open.c index d86ffff646..117152d4d9 100644 --- a/source4/lib/tdb/common/open.c +++ b/source4/lib/tdb/common/open.c @@ -144,6 +144,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, errno = ENOMEM; goto fail; } + tdb_io_init(tdb); tdb->fd = -1; tdb->name = NULL; tdb->map_ptr = NULL; @@ -152,6 +153,12 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->log_fn = log_fn?log_fn:null_log_fn; tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + /* cache the page size */ + tdb->page_size = getpagesize(); + if (tdb->page_size <= 0) { + tdb->page_size = 0x2000; + } + if ((open_flags & O_ACCMODE) == O_WRONLY) { TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", name)); @@ -186,7 +193,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } /* ensure there is only one process initialising at once */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", name, strerror(errno))); goto fail; /* errno set by tdb_brlock */ @@ -194,7 +201,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, /* we need to zero database if we are the only one with it open */ if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { + (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { open_flags |= O_CREAT; if (ftruncate(tdb->fd, 0) == -1) { TDB_LOG((tdb, 0, "tdb_open_ex: " @@ -260,7 +267,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } tdb_mmap(tdb); if (locked) { - if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { TDB_LOG((tdb, 0, "tdb_open_ex: " "failed to take ACTIVE_LOCK on %s: %s\n", name, strerror(errno))); @@ -275,15 +282,20 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, if (tdb_flags & TDB_CLEAR_IF_FIRST) { /* leave this lock in place to indicate it's in use */ - if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) goto fail; } + /* if needed, run recovery */ + if (tdb_transaction_recover(tdb) == -1) { + goto fail; + } + internal: /* Internal (memory-only) databases skip all the code above to * do with disk files, and resume here by releasing their * global lock and hooking into the active list. */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1) goto fail; tdb->next = tdbs; tdbs = tdb; @@ -322,6 +334,10 @@ int tdb_close(struct tdb_context *tdb) struct tdb_context **i; int ret = 0; + if (tdb->transaction) { + tdb_transaction_cancel(tdb); + } + if (tdb->map_ptr) { if (tdb->flags & TDB_INTERNAL) SAFE_FREE(tdb->map_ptr); @@ -360,8 +376,20 @@ int tdb_reopen(struct tdb_context *tdb) { struct stat st; - if (tdb->flags & TDB_INTERNAL) + if (tdb->flags & TDB_INTERNAL) { return 0; /* Nothing to do. */ + } + + if (tdb->num_locks != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed with locks held\n")); + goto fail; + } + + if (tdb->transaction != 0) { + TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed inside a transaction\n")); + goto fail; + } + if (tdb_munmap(tdb) != 0) { TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); goto fail; @@ -374,7 +402,7 @@ int tdb_reopen(struct tdb_context *tdb) goto fail; } if ((tdb->flags & TDB_CLEAR_IF_FIRST) && - (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { + (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); goto fail; } diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index f099c2d1aa..c37d37a4f2 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -98,7 +98,7 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_ return -1; } - if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, dbuf.dptr, dbuf.dsize) == -1) return -1; @@ -285,7 +285,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* write out and point the top of the hash chain at it */ if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 - || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { /* Need to tdb_unallocate() here */ goto fail; diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index 8e246e3283..eefcc52557 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -29,6 +29,8 @@ #include #endif +#define _XOPEN_SOURCE 500 + #include #include #include @@ -39,7 +41,7 @@ #include #include #include -#include "tdbconfig.h" +#include "config.h" #include "tdb.h" #else #include "includes.h" @@ -56,23 +58,30 @@ typedef u32 tdb_len_t; typedef u32 tdb_off_t; +#ifndef offsetof +#define offsetof(t,f) ((unsigned int)&((t *)0)->f) +#endif + #define TDB_MAGIC_FOOD "TDB file\n" #define TDB_VERSION (0x26011967 + 6) #define TDB_MAGIC (0x26011999U) #define TDB_FREE_MAGIC (~TDB_MAGIC) #define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) #define TDB_ALIGNMENT 4 #define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) #define DEFAULT_HASH_SIZE 131 -#define TDB_PAGE_SIZE 0x2000 #define FREELIST_TOP (sizeof(struct tdb_header)) #define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) #define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) #define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) #define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) #define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) #define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1) - +#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) +#define TDB_PAD_BYTE 0x42 +#define TDB_PAD_U32 0x42424242 /* NB assumes there is a local variable called "tdb" that is the * current context, also takes doubly-parenthesized print-style @@ -80,8 +89,9 @@ typedef u32 tdb_off_t; #define TDB_LOG(x) tdb->log_fn x /* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 +#define TRANSACTION_LOCK 8 #ifndef MAP_FILE #define MAP_FILE 0 @@ -138,8 +148,9 @@ struct tdb_header { char magic_food[32]; /* for /etc/magic */ u32 version; /* version of the code */ u32 hash_size; /* number of hash entries */ - tdb_off_t rwlocks; - tdb_off_t reserved[31]; + tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ + tdb_off_t recovery_start; /* offset of transaction recovery region */ + tdb_off_t reserved[30]; }; struct tdb_lock_type { @@ -154,6 +165,15 @@ struct tdb_traverse_lock { }; +struct tdb_methods { + int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); + int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); + void (*next_hash_chain)(struct tdb_context *, u32 *); + int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); + int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); + int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int); +}; + struct tdb_context { char *name; /* the name of the database */ void *map_ptr; /* where it is currently mapped */ @@ -171,7 +191,10 @@ struct tdb_context { void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ unsigned int (*hash_fn)(TDB_DATA *key); int open_flags; /* flags used in the open - needed by reopen */ + unsigned int num_locks; /* number of chain locks held */ + const struct tdb_methods *methods; struct tdb_transaction *transaction; + int page_size; }; @@ -180,13 +203,11 @@ struct tdb_context { */ int tdb_munmap(struct tdb_context *tdb); void tdb_mmap(struct tdb_context *tdb); -int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv); -int tdb_write(struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len); -int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe); int tdb_lock(struct tdb_context *tdb, int list, int ltype); int tdb_unlock(struct tdb_context *tdb, int list, int ltype); -int tdb_expand(struct tdb_context *tdb, tdb_off_t size); int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe); +int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len); int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); @@ -204,5 +225,7 @@ int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, struct list_struct *rec); -void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain); +void tdb_io_init(struct tdb_context *tdb); +int tdb_expand(struct tdb_context *tdb, tdb_off_t size); + diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c new file mode 100644 index 0000000000..b9d44a7283 --- /dev/null +++ b/source4/lib/tdb/common/transaction.c @@ -0,0 +1,976 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tdb_private.h" + +/* + transaction design: + + - only allow a single transaction at a time per database. This makes + using the transaction API simpler, as otherwise the caller would + have to cope with temporary failures in transactions that conflict + with other current transactions + + - keep the transaction recovery information in the same file as the + database, using a special 'transaction recovery' record pointed at + by the header. This removes the need for extra journal files as + used by some other databases + + - dymacially allocated the transaction recover record, re-using it + for subsequent transactions. If a larger record is needed then + tdb_free() the old record to place it on the normal tdb freelist + before allocating the new record + + - during transactions, keep a linked list of writes all that have + been performed by intercepting all tdb_write() calls. The hooked + transaction versions of tdb_read() and tdb_write() check this + linked list and try to use the elements of the list in preference + to the real database. + + - don't allow any locks to be held when a transaction starts, + otherwise we can end up with deadlock (plus lack of lock nesting + in posix locks would mean the lock is lost) + + - if the caller gains a lock during the transaction but doesn't + release it then fail the commit + + - allow for nested calls to tdb_transaction_start(), re-using the + existing transaction record. If the inner transaction is cancelled + then a subsequent commit will fail + + - keep a mirrored copy of the tdb hash chain heads to allow for the + fast hash heads scan on traverse, updating the mirrored copy in + the transaction version of tdb_write + + - allow callers to mix transaction and non-transaction use of tdb, + although once a transaction is started then an exclusive lock is + gained until the transaction is committed or cancelled + + - the commit stategy involves first saving away all modified data + into a linearised buffer in the transaction recovery area, then + marking the transaction recovery area with a magic value to + indicate a valid recovery record. In total 4 fsync/msync calls are + needed per commit to prevent race conditions. It might be possible + to reduce this to 3 or even 2 with some more work. + + - check for a valid recovery record on open of the tdb, while the + global lock is held. Automatically recover from the transaction + recovery area if needed, then continue with the open as + usual. This allows for smooth crash recovery with no administrator + intervention. + + - if TDB_NOSYNC is passed to flags in tdb_open then transactions are + still available, but no transaction recovery area is used and no + fsync/msync calls are made. + +*/ + + +/* + hold the context of any current transaction +*/ +struct tdb_transaction { + /* we keep a mirrored copy of the tdb hash heads here so + tdb_next_hash_chain() can operate efficiently */ + u32 *hash_heads; + + /* the original io methods - used to do IOs to the real db */ + const struct tdb_methods *io_methods; + + /* the list of transaction elements. We use a doubly linked + list with a last pointer to allow us to keep the list + ordered, with first element at the front of the list. It + needs to be doubly linked as the read/write traversals need + to be backwards, while the commit needs to be forwards */ + struct tdb_transaction_el { + struct tdb_transaction_el *next, *prev; + tdb_off_t offset; + tdb_len_t length; + unsigned char *data; + } *elements, *elements_last; + + /* non-zero when an internal transaction error has + occurred. All write operations will then fail until the + transaction is ended */ + int transaction_error; + + /* when inside a transaction we need to keep track of any + nested tdb_transaction_start() calls, as these are allowed, + but don't create a new transaction */ + int nesting; + + /* old file size before transaction */ + tdb_len_t old_map_size; +}; + + +/* + read while in a transaction. We need to check first if the data is in our list + of transaction elements, then if not do a real read +*/ +static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + struct tdb_transaction_el *el; + + /* we need to walk the list backwards to get the most recent data */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping read - needs to be split into up to + 2 reads and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_read(tdb, off, buf, partial, cv) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(buf, el->data + (off - el->offset), partial); + if (cv) { + tdb_convert(buf, len); + } + len -= partial; + off += partial; + buf = (void *)(partial + (char *)buf); + + if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) { + goto fail; + } + + return 0; + } + + /* its not in the transaction elements - do a real read */ + return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); + +fail: + TDB_LOG((tdb, 0, "transaction_read: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction +*/ +static int transaction_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + struct tdb_transaction_el *el; + + /* if the write is to a hash head, then update the transaction + hash heads */ + if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && + off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { + u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); + memcpy(&tdb->transaction->hash_heads[chain], buf, len); + } + + /* first see if we can replace an existing entry */ + for (el=tdb->transaction->elements_last;el;el=el->prev) { + tdb_len_t partial; + + if (off+len <= el->offset) { + continue; + } + if (off >= el->offset + el->length) { + continue; + } + + /* an overlapping write - needs to be split into up to + 2 writes and a memcpy */ + if (off < el->offset) { + partial = el->offset - off; + if (transaction_write(tdb, off, buf, partial) != 0) { + goto fail; + } + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + } + if (off + len <= el->offset + el->length) { + partial = len; + } else { + partial = el->offset + el->length - off; + } + memcpy(el->data + (off - el->offset), buf, partial); + len -= partial; + off += partial; + buf = (const void *)(partial + (const char *)buf); + + if (len != 0 && transaction_write(tdb, off, buf, len) != 0) { + goto fail; + } + + return 0; + } + + /* add a new entry at the end of the list */ + el = malloc(sizeof(*el)); + if (el == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + el->next = NULL; + el->prev = tdb->transaction->elements_last; + el->offset = off; + el->length = len; + el->data = malloc(len); + if (el->data == NULL) { + free(el); + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + if (buf) { + memcpy(el->data, buf, len); + } else { + memset(el->data, TDB_PAD_BYTE, len); + } + if (el->prev) { + el->prev->next = el; + } else { + tdb->transaction->elements = el; + } + tdb->transaction->elements_last = el; + return 0; + +fail: + TDB_LOG((tdb, 0, "transaction_write: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + +/* + accelerated hash chain head search, using the cached hash heads +*/ +static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) +{ + u32 h = *chain; + for (;h < tdb->header.hash_size;h++) { + /* the +1 takes account of the freelist */ + if (0 != tdb->transaction->hash_heads[h+1]) { + break; + } + } + (*chain) = h; +} + +/* + out of bounds check during a transaction +*/ +static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + if (len <= tdb->map_size) { + return 0; + } + return TDB_ERRCODE(TDB_ERR_IO, -1); +} + +/* + transaction version of tdb_expand(). +*/ +static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, + tdb_off_t addition) +{ + /* add a write to the transaction elements, so subsequent + reads see the zero data */ + if (transaction_write(tdb, size, NULL, addition) != 0) { + return -1; + } + + return 0; +} + +/* + brlock during a transaction - ignore them +*/ +int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe) +{ + return 0; +} + +static const struct tdb_methods transaction_methods = { + .tdb_read = transaction_read, + .tdb_write = transaction_write, + .next_hash_chain = transaction_next_hash_chain, + .tdb_oob = transaction_oob, + .tdb_expand_file = transaction_expand_file, + .tdb_brlock = transaction_brlock +}; + + +/* + start a tdb transaction. No token is returned, as only a single + transaction is allowed to be pending per tdb_context +*/ +int tdb_transaction_start(struct tdb_context *tdb) +{ + /* some sanity checks */ + if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) { + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + /* cope with nested tdb_transaction_start() calls */ + if (tdb->transaction != NULL) { + tdb->transaction->nesting++; + TDB_LOG((tdb, 0, "tdb_transaction_start: nesting %d\n", + tdb->transaction->nesting)); + return 0; + } + + if (tdb->num_locks != 0) { + /* the caller must not have any locks when starting a + transaction as otherwise we'll be screwed by lack + of nested locks in posix */ + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction with locks held\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->transaction = calloc(sizeof(struct tdb_transaction), 1); + if (tdb->transaction == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* get the transaction write lock. This is a blocking lock. As + discussed with Volker, there are a number of ways we could + make this async, which we will probably do in the future */ + if (tdb_brlock_len(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + SAFE_FREE(tdb->transaction); + return -1; + } + + /* get a write lock from the freelist to the end of file. It + would be much better to make this a read lock as it would + increase parallelism, but it could lead to deadlocks on + commit when a write lock needs to be taken. + + TODO: look at alternative locking strategies to allow this + to be a read lock + */ + if (tdb_brlock_len(tdb, FREELIST_TOP, F_WRLCK, F_SETLKW, 0, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + goto fail; + } + + /* setup a copy of the hash table heads so the hash scan in + traverse can be fast */ + tdb->transaction->hash_heads = calloc(tdb->header.hash_size+1, sizeof(tdb_off_t)); + if (tdb->transaction->hash_heads == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb), 0) != 0) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to read hash heads\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + /* make sure we know about any file expansions already done by + anyone else */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + tdb->transaction->old_map_size = tdb->map_size; + + /* finally hook the io methods, replacing them with + transaction specific methods */ + tdb->transaction->io_methods = tdb->methods; + tdb->methods = &transaction_methods; + + return 0; + +fail: + tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + return -1; +} + + +/* + cancel the current transaction +*/ +int tdb_transaction_cancel(struct tdb_context *tdb) +{ + if (tdb->transaction == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_cancel: no transaction\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->transaction_error = 1; + tdb->transaction->nesting--; + return 0; + } + + tdb->map_size = tdb->transaction->old_map_size; + + /* free all the transaction elements */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + /* remove any locks created during the transaction */ + if (tdb->num_locks != 0) { + int h; + for (h=0;hheader.hash_size+1;h++) { + if (tdb->locked[h].count != 0) { + tdb_brlock_len(tdb,FREELIST_TOP+4*h,F_UNLCK,F_SETLKW, 0, 1); + tdb->locked[h].count = 0; + } + } + tdb->num_locks = 0; + } + + /* restore the normal io methods */ + tdb->methods = tdb->transaction->io_methods; + + tdb_brlock_len(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_brlock_len(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + + return 0; +} + +/* + sync to disk +*/ +static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) +{ + if (fsync(tdb->fd) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction: fsync failed\n")); + return -1; + } +#ifdef MS_SYNC + if (tdb->map_ptr) { + tdb_off_t moffset = offset & ~(tdb->page_size-1); + if (msync(moffset + (char *)tdb->map_ptr, + length + (offset - moffset), MS_SYNC) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction: msync failed\n")); + return -1; + } + } +#endif + return 0; +} + + +/* + work out how much space the linearised recovery data will consume +*/ +static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size = 0; + + recovery_size = sizeof(u32); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= tdb->transaction->old_map_size) { + continue; + } + recovery_size += 2*sizeof(tdb_off_t) + el->length; + } + + return recovery_size; +} + +/* + allocate the recovery area, or use an existing recovery area if it is + large enough +*/ +static int tdb_recovery_allocate(struct tdb_context *tdb, + tdb_len_t *recovery_size, + tdb_off_t *recovery_offset, + tdb_len_t *recovery_max_size) +{ + struct list_struct rec; + const struct tdb_methods *methods = tdb->transaction->io_methods; + tdb_off_t recovery_head; + + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery head\n")); + return -1; + } + + rec.rec_len = 0; + + if (recovery_head != 0 && + methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery record\n")); + return -1; + } + + *recovery_size = tdb_recovery_size(tdb); + + if (recovery_head != 0 && *recovery_size <= rec.rec_len) { + /* it fits in the existing area */ + *recovery_max_size = rec.rec_len; + *recovery_offset = recovery_head; + return 0; + } + + /* we need to free up the old recovery area, then allocate a + new one at the end of the file. Note that we cannot use + tdb_allocate() to allocate the new one as that might return + us an area that is being currently used (as of the start of + the transaction) */ + if (recovery_head != 0) { + if (tdb_free(tdb, recovery_head, &rec) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to free previous recovery area\n")); + return -1; + } + } + + /* the tdb_free() call might have increased the recovery size */ + *recovery_size = tdb_recovery_size(tdb); + + /* round up to a multiple of page size */ + *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); + *recovery_offset = tdb->map_size; + recovery_head = *recovery_offset; + + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + (tdb->map_size - tdb->transaction->old_map_size) + + sizeof(rec) + *recovery_max_size) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to create recovery area\n")); + return -1; + } + + /* remap the file (if using mmap) */ + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* we have to reset the old map size so that we don't try to expand the file + again in the transaction commit, which would destroy the recovery area */ + tdb->transaction->old_map_size = tdb->map_size; + + /* write the recovery header offset and sync - we can sync without a race here + as the magic ptr in the recovery record has not been set */ + CONVERT(recovery_head); + if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, + &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + + return 0; +} + + +/* + setup the recovery data that will be used on a crash during commit +*/ +static int transaction_setup_recovery(struct tdb_context *tdb, + tdb_off_t *magic_offset) +{ + struct tdb_transaction_el *el; + tdb_len_t recovery_size; + unsigned char *data, *p; + const struct tdb_methods *methods = tdb->transaction->io_methods; + struct list_struct *rec; + tdb_off_t recovery_offset, recovery_max_size; + tdb_off_t old_map_size = tdb->transaction->old_map_size; + u32 magic; + + /* + check that the recovery area has enough space + */ + if (tdb_recovery_allocate(tdb, &recovery_size, + &recovery_offset, &recovery_max_size) == -1) { + return -1; + } + + data = malloc(recovery_size + sizeof(*rec)); + if (data == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + rec = (struct list_struct *)data; + memset(rec, 0, sizeof(*rec)); + + rec->magic = 0; + rec->data_len = recovery_size; + rec->rec_len = recovery_max_size; + rec->key_len = old_map_size; + CONVERT(rec); + + /* build the recovery data into a single blob to allow us to do a single + large write, which should be more efficient */ + p = data + sizeof(*rec); + for (el=tdb->transaction->elements;el;el=el->next) { + if (el->offset >= old_map_size) { + continue; + } + if (el->offset + el->length > tdb->transaction->old_map_size) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction data over new region boundary\n")); + free(data); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + ((u32 *)p)[0] = el->offset; + ((u32 *)p)[1] = el->length; + if (DOCONV()) { + tdb_convert(p, 8); + } + /* the recovery area contains the old data, not the + new data, so we have to call the original tdb_read + method to get it */ + if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) { + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + el->length; + } + + /* and the tailer */ + *(u32 *)p = sizeof(*rec) + recovery_max_size; + CONVERT(p); + + /* write the recovery data to the recovery area */ + if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* as we don't have ordered writes, we have to sync the recovery + data before we update the magic to indicate that the recovery + data is present */ + if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { + free(data); + return -1; + } + + free(data); + + magic = TDB_RECOVERY_MAGIC; + CONVERT(magic); + + *magic_offset = recovery_offset + offsetof(struct list_struct, magic); + + if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to write recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* ensure the recovery magic marker is on disk */ + if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { + return -1; + } + + return 0; +} + +/* + commit the current transaction +*/ +int tdb_transaction_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + tdb_off_t magic_offset; + u32 zero = 0; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: no transaction\n")); + return -1; + } + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + tdb_transaction_cancel(tdb); + TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction error pending\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->nesting--; + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->elements == NULL) { + tdb_transaction_cancel(tdb); + return 0; + } + + methods = tdb->transaction->io_methods; + + /* if there are any locks pending then the caller has not + nested their locks properly, so fail the transaction */ + if (tdb->num_locks) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, 0, "tdb_transaction_commit: locks pending on commit\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + /* get the global lock - this prevents new users attaching to the database + during the commit */ + if (tdb_brlock_len(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to get global lock\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &magic_offset) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to setup recovery data\n")); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + } + + /* expand the file to the new size if needed */ + if (tdb->map_size != tdb->transaction->old_map_size) { + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + tdb->map_size - + tdb->transaction->old_map_size) == -1) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, 0, "tdb_transaction_commit: expansion failed\n")); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb_transaction_cancel(tdb); + return -1; + } + tdb->map_size = tdb->transaction->old_map_size; + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + } + + /* perform all the writes */ + while (tdb->transaction->elements) { + struct tdb_transaction_el *el = tdb->transaction->elements; + + if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed during commit\n")); + + /* we've overwritten part of the data and + possibly expanded the file, so we need to + run the crash recovery code */ + tdb->methods = methods; + tdb_transaction_recover(tdb); + + tdb_transaction_cancel(tdb); + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed\n")); + return -1; + } + tdb->transaction->elements = el->next; + free(el->data); + free(el); + } + + if (!(tdb->flags & TDB_NOSYNC)) { + /* ensure the new data is on disk */ + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + return -1; + } + + /* remove the recovery marker */ + if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to remove recovery magic\n")); + return -1; + } + + /* ensure the recovery marker has been removed on disk */ + if (transaction_sync(tdb, magic_offset, 4) == -1) { + return -1; + } + } + + tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + + /* use a transaction cancel to free memory and remove the + transaction locks */ + tdb_transaction_cancel(tdb); + return 0; +} + + +/* + recover from an aborted transaction. Must be called with exclusive + database write access already established (including the global + lock to prevent new processes attaching) +*/ +int tdb_transaction_recover(struct tdb_context *tdb) +{ + tdb_off_t recovery_head, recovery_eof; + unsigned char *data, *p; + u32 zero = 0; + struct list_struct rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return 0; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery record\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (rec.magic != TDB_RECOVERY_MAGIC) { + /* there is no valid recovery data */ + return 0; + } + + if (tdb->read_only) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: attempt to recover read only database\n")); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + + recovery_eof = rec.key_len; + + data = malloc(rec.data_len); + if (data == NULL) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to allocate recovery data\n")); + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* read the full recovery data */ + if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, + rec.data_len, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery data\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* recover the file data */ + p = data; + while (p+8 < data + rec.data_len) { + u32 ofs, len; + if (DOCONV()) { + tdb_convert(p, 8); + } + ofs = ((u32 *)p)[0]; + len = ((u32 *)p)[1]; + + if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { + free(data); + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + len; + } + + free(data); + + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* if the recovery area is after the recovered eof then remove it */ + if (recovery_eof <= recovery_head) { + if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + } + + /* remove the recovery magic */ + if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), + &zero) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* reduce the file size to the old size */ + tdb_munmap(tdb); + if (ftruncate(tdb->fd, recovery_eof) != 0) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to reduce to recovery size\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = recovery_eof; + tdb_mmap(tdb); + + if (transaction_sync(tdb, 0, recovery_eof) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync2 recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + TDB_LOG((tdb, 0, "tdb_transaction_recover: recovered %d byte database\n", + recovery_eof)); + + /* all done */ + return 0; +} diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c index d14be355a2..7d1e99cbe8 100644 --- a/source4/lib/tdb/common/traverse.c +++ b/source4/lib/tdb/common/traverse.c @@ -65,7 +65,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc factor of around 80 in speed on a linux 2.6.x system (testing using ldbtest). */ - tdb_next_hash_chain(tdb, &tlock->hash); + tdb->methods->next_hash_chain(tdb, &tlock->hash); if (tlock->hash == tdb->header.hash_size) { continue; } diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index ddb57acf0d..bfc1900299 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -5,7 +5,7 @@ INIT_OBJ_FILES = \ lib/tdb/common/tdb.o ADD_OBJ_FILES = lib/tdb/common/dump.o lib/tdb/common/io.o lib/tdb/common/lock.o \ lib/tdb/common/open.o lib/tdb/common/traverse.o lib/tdb/common/freelist.o \ - lib/tdb/common/error.o lib/tdb/common/tdbutil.o + lib/tdb/common/error.o lib/tdb/common/transaction.o lib/tdb/common/tdbutil.o NOPROTO=YES REQUIRED_SUBSYSTEMS = \ LIBREPLACE diff --git a/source4/lib/tdb/configure.in b/source4/lib/tdb/configure.in index 68ea39c140..4e5c42c351 100644 --- a/source4/lib/tdb/configure.in +++ b/source4/lib/tdb/configure.in @@ -1,7 +1,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""]) AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""]) AC_INIT(include/tdb.h) -AC_CONFIG_HEADER(include/tdbconfig.h) +AC_CONFIG_HEADER(include/config.h) AC_PROG_CC AC_FUNC_MMAP AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) diff --git a/source4/lib/tdb/docs/README b/source4/lib/tdb/docs/README index 664d65ffd9..18b32de37f 100644 --- a/source4/lib/tdb/docs/README +++ b/source4/lib/tdb/docs/README @@ -40,6 +40,7 @@ The interface is very similar to gdbm except for the following: - no tdbm_reorganise() function - no tdbm_sync() function. No operations are cached in the library anyway - added a tdb_traverse() function for traversing the whole database +- added transactions support A general rule for using tdb is that the caller frees any returned TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA @@ -67,6 +68,19 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, memory. The filename is ignored in this case. TDB_NOLOCK - don't do any locking TDB_NOMMAP - don't use mmap + TDB_NOSYNC - don't synchronise transactions to disk + +---------------------------------------------------------------------- +TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + tdb_log_func log_fn, + tdb_hash_func hash_fn) + +This is like tdb_open(), but allows you to pass an initial logging and +hash function. Be careful when passing a hash function - all users of +the database must use the same hash function or you will get data +corruption. + ---------------------------------------------------------------------- char *tdb_error(TDB_CONTEXT *tdb); @@ -164,3 +178,40 @@ int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key); unlock one hash chain + +---------------------------------------------------------------------- +int tdb_transaction_start(TDB_CONTEXT *tdb) + + start a transaction. All operations after the transaction start can + either be committed with tdb_transaction_commit() or cancelled with + tdb_transaction_cancel(). + + If you call tdb_transaction_start() again on the same tdb context + while a transaction is in progress, then the same transaction + buffer is re-used. The number of tdb_transaction_{commit,cancel} + operations must match the number of successful + tdb_transaction_start() calls. + + Note that transactions are by default disk synchronous, and use a + recover area in the database to automatically recover the database + on the next open if the system crashes during a transaction. You + can disable the synchronous transaction recovery setup using the + TDB_NOSYNC flag, which will greatly speed up operations at the risk + of corrupting your database if the system crashes. + + Operations made within a transaction are not visible to other users + of the database until a successful commit. + +---------------------------------------------------------------------- +int tdb_transaction_cancel(TDB_CONTEXT *tdb) + + cancel a current transaction, discarding all write and lock + operations that have been made since the transaction started. + + +---------------------------------------------------------------------- +int tdb_transaction_commit(TDB_CONTEXT *tdb) + + commit a current transaction, updating the database and releasing + the transaction locks. + diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index cc3f3c18d8..3f123d814c 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -45,13 +45,14 @@ extern "C" { #define TDB_NOMMAP 8 /* don't use mmap */ #define TDB_CONVERT 16 /* convert endian (internal use) */ #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /* don't use synchronous transactions */ #define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret) /* error codes */ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, - TDB_ERR_NOEXIST}; + TDB_ERR_NOEXIST, TDB_ERR_EINVAL}; typedef struct TDB_DATA { unsigned char *dptr; @@ -59,7 +60,15 @@ typedef struct TDB_DATA { } TDB_DATA; #ifndef PRINTF_ATTRIBUTE -#define PRINTF_ATTRIBUTE(a,b) +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif #endif /* this is the context structure that is returned from a db open */ @@ -95,6 +104,10 @@ void tdb_unlockall(struct tdb_context *tdb); const char *tdb_name(struct tdb_context *tdb); int tdb_fd(struct tdb_context *tdb); tdb_log_func tdb_log_fn(struct tdb_context *tdb); +int tdb_transaction_start(struct tdb_context *tdb); +int tdb_transaction_commit(struct tdb_context *tdb); +int tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_transaction_recover(struct tdb_context *tdb); /* Low level locking functions: use with care */ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); diff --git a/source4/lib/tdb/tools/tdbtool.c b/source4/lib/tdb/tools/tdbtool.c index 5a8c871699..0941a73118 100644 --- a/source4/lib/tdb/tools/tdbtool.c +++ b/source4/lib/tdb/tools/tdbtool.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "tdb.h" /* a tdb tool for manipulating a tdb database */ @@ -77,6 +78,19 @@ static void print_asc(unsigned char *buf,int len) printf("%c",isprint(buf[i])?buf[i]:'.'); } +#ifdef PRINTF_ATTRIBUTE +static void tdb_log(struct tdb_context *t, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +#endif +static void tdb_log(struct tdb_context *t, int level, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + fflush(stdout); +} + static void print_data(unsigned char *buf,int len) { int i=0; @@ -131,7 +145,7 @@ static void help(void) "\n"); } -static void terror(char *why) +static void terror(const char *why) { printf("%s\n", why); } @@ -175,8 +189,8 @@ static void create_tdb(void) return; } if (tdb) tdb_close(tdb); - tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT | O_TRUNC, 0600); + tdb = tdb_open_ex(tok, 0, TDB_CLEAR_IF_FIRST, + O_RDWR | O_CREAT | O_TRUNC, 0600, tdb_log, NULL); if (!tdb) { printf("Could not create %s: %s\n", tok, strerror(errno)); } @@ -190,7 +204,7 @@ static void open_tdb(void) return; } if (tdb) tdb_close(tdb); - tdb = tdb_open(tok, 0, 0, O_RDWR, 0600); + tdb = tdb_open_ex(tok, 0, 0, O_RDWR, 0600, tdb_log, NULL); if (!tdb) { printf("Could not open %s: %s\n", tok, strerror(errno)); } @@ -326,7 +340,7 @@ static void move_rec(void) print_rec(tdb, key, dbuf, NULL); - dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600); + dst_tdb = tdb_open_ex(file, 0, 0, O_RDWR, 0600, tdb_log, NULL); if ( !dst_tdb ) { terror("unable to open destination tdb"); return; @@ -377,7 +391,7 @@ static void info_tdb(void) printf("%d records totalling %d bytes\n", count, total_bytes); } -static char *tdb_getline(char *prompt) +static char *tdb_getline(const char *prompt) { static char line[1024]; char *p; diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 0cf82fa5a5..b0a2e7484f 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -1,6 +1,8 @@ /* this tests tdb by doing lots of ops from several simultaneous - writers - that stresses the locking code. Build with TDB_DEBUG=1 - for best effect */ + writers - that stresses the locking code. +*/ + +#define _GNU_SOURCE #ifndef _SAMBA_BUILD_ #include @@ -28,11 +30,14 @@ #endif +#include + #define REOPEN_PROB 30 #define DELETE_PROB 8 #define STORE_PROB 4 #define APPEND_PROB 6 -#define LOCKSTORE_PROB 0 +#define TRANSACTION_PROB 10 +#define LOCKSTORE_PROB 5 #define TRAVERSE_PROB 20 #define CULL_PROB 100 #define KEYLEN 3 @@ -40,6 +45,7 @@ #define LOCKLEN 20 static struct tdb_context *db; +static int in_transaction; #ifdef PRINTF_ATTRIBUTE static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); @@ -84,25 +90,25 @@ static char *randbuf(int len) static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { +#if CULL_PROB if (random() % CULL_PROB == 0) { tdb_delete(tdb, key); } +#endif return 0; } static void addrec_db(void) { - int klen, dlen, slen; - char *k, *d, *s; - TDB_DATA key, data, lockkey; + int klen, dlen; + char *k, *d; + TDB_DATA key, data; klen = 1 + (rand() % KEYLEN); dlen = 1 + (rand() % DATALEN); - slen = 1 + (rand() % LOCKLEN); k = randbuf(klen); d = randbuf(dlen); - s = randbuf(slen); key.dptr = (unsigned char *)k; key.dsize = klen+1; @@ -110,11 +116,32 @@ static void addrec_db(void) data.dptr = (unsigned char *)d; data.dsize = dlen+1; - lockkey.dptr = (unsigned char *)s; - lockkey.dsize = slen+1; +#if TRANSACTION_PROB + if (in_transaction == 0 && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_start(db) != 0) { + fatal("tdb_transaction_start failed"); + } + in_transaction++; + goto next; + } + if (in_transaction && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_commit(db) != 0) { + fatal("tdb_transaction_commit failed"); + } + in_transaction--; + goto next; + } + if (in_transaction && random() % TRANSACTION_PROB == 0) { + if (tdb_transaction_cancel(db) != 0) { + fatal("tdb_transaction_cancel failed"); + } + in_transaction--; + goto next; + } +#endif #if REOPEN_PROB - if (random() % REOPEN_PROB == 0) { + if (in_transaction == 0 && random() % REOPEN_PROB == 0) { tdb_reopen_all(); goto next; } @@ -147,13 +174,13 @@ static void addrec_db(void) #if LOCKSTORE_PROB if (random() % LOCKSTORE_PROB == 0) { - tdb_chainlock(db, lockkey); + tdb_chainlock(db, key); data = tdb_fetch(db, key); if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } if (data.dptr) free(data.dptr); - tdb_chainunlock(db, lockkey); + tdb_chainunlock(db, key); goto next; } #endif @@ -171,7 +198,6 @@ static void addrec_db(void) next: free(k); free(d); - free(s); } static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, @@ -181,38 +207,71 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, return 0; } -#ifndef NPROC -#define NPROC 2 -#endif - -#ifndef NLOOPS -#define NLOOPS 5000 -#endif - - int main(int argc, const char *argv[]) +static void usage(void) { - int i, seed=0; - int loops = NLOOPS; - pid_t pids[NPROC]; + printf("Usage: tdbtorture [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n"); + exit(0); +} - pids[0] = getpid(); + int main(int argc, char * const *argv) +{ + int i, seed = -1; + int num_procs = 2; + int num_loops = 5000; + int hash_size = 2; + int c; + extern char *optarg; + pid_t *pids; + + while ((c = getopt(argc, argv, "n:l:s:H:h")) != -1) { + switch (c) { + case 'n': + num_procs = strtol(optarg, NULL, 0); + break; + case 'l': + num_loops = strtol(optarg, NULL, 0); + break; + case 'H': + hash_size = strtol(optarg, NULL, 0); + break; + case 's': + seed = strtol(optarg, NULL, 0); + break; + default: + usage(); + } + } unlink("torture.tdb"); - for (i=0;i Date: Thu, 22 Sep 2005 04:16:46 +0000 Subject: r10406: added --nosync option to all ldb tools, so that you can control if transactions are synchronous or not on the command line. add LDB_FLG_NOSYNC flag to ldb_connect() so we can make our temporary ldb databases non-synchronous (This used to be commit dba41164e0c52f1e4351bd9057b16661cee3a822) --- source4/lib/ldb/include/ldb.h | 1 + source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 20 +++++++++++--------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 9 ++++----- source4/lib/ldb/tools/cmdline.c | 7 ++++++- source4/lib/ldb/tools/cmdline.h | 1 + source4/lib/ldb/tools/ldbtest.c | 7 ++++++- 6 files changed, 29 insertions(+), 16 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 008327eb05..f7abd920eb 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -158,6 +158,7 @@ struct ldb_debug_ops { }; #define LDB_FLG_RDONLY 1 +#define LDB_FLG_NOSYNC 2 #ifndef PRINTF_ATTRIBUTE #define PRINTF_ATTRIBUTE(a,b) diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 8742b53962..ac706291ef 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1522,7 +1522,7 @@ static int lsqlite3_end_trans(struct ldb_module *module, int status) */ static int initialize(struct lsqlite3_private *lsqlite3, - struct ldb_context *ldb, const char *url) + struct ldb_context *ldb, const char *url, int flags) { TALLOC_CTX *local_ctx; long long queryInt; @@ -1648,14 +1648,16 @@ static int initialize(struct lsqlite3_private *lsqlite3, goto failed; } - /* DANGEROUS */ - ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA synchronous = OFF;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3 initializaion error: %s\n", errmsg); - free(errmsg); + if (flags & LDB_FLG_NOSYNC) { + /* DANGEROUS */ + ret = sqlite3_exec(lsqlite3->sqlite, "PRAGMA synchronous = OFF;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3 initializaion error: %s\n", errmsg); + free(errmsg); + } + goto failed; } - goto failed; } /* */ @@ -1836,7 +1838,7 @@ int lsqlite3_connect(struct ldb_context *ldb, lsqlite3->options = NULL; lsqlite3->trans_count = 0; - ret = initialize(lsqlite3, ldb, url); + ret = initialize(lsqlite3, ldb, url, flags); if (ret != SQLITE_OK) { goto failed; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index c056bd2e2d..a2faaa805f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -895,11 +895,10 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, tdb_flags = TDB_DEFAULT; -#if 0 - /* set this to run tdb without disk sync, but still with - transactions */ - tdb_flags |= TDB_NOSYNC; -#endif + /* check for the 'nosync' option */ + if (flags & LDB_FLG_NOSYNC) { + tdb_flags |= TDB_NOSYNC; + } if (flags & LDB_FLG_RDONLY) { open_flags = O_RDONLY; diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index fb0292b7d9..7cdecc334f 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -55,6 +55,7 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "dn=*", NULL }, + { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, { "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" }, { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" }, @@ -159,7 +160,11 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const } if (strcmp(ret->url, "NONE") != 0) { - if (ldb_connect(ldb, ret->url, 0, ret->options) != 0) { + int flags = 0; + if (options.nosync) { + flags |= LDB_FLG_NOSYNC; + } + if (ldb_connect(ldb, ret->url, flags, ret->options) != 0) { fprintf(stderr, "Failed to connect to %s - %s\n", ret->url, ldb_errstring(ldb)); goto failed; diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h index daf9c06f42..9aaf37a978 100644 --- a/source4/lib/ldb/tools/cmdline.h +++ b/source4/lib/ldb/tools/cmdline.h @@ -34,6 +34,7 @@ struct ldb_cmdline { int verbose; int recursive; int all_records; + int nosync; const char **options; int argc; const char **argv; diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index eeedd49e84..08ce99d20f 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -299,6 +299,11 @@ static void start_test_index(struct ldb_context **ldb) struct ldb_dn *indexlist; struct ldb_dn *basedn; int ret; + int flags = 0; + + if (options->nosync) { + flags |= LDB_FLG_NOSYNC; + } printf("Starting index test\n"); @@ -337,7 +342,7 @@ static void start_test_index(struct ldb_context **ldb) (*ldb) = ldb_init(options); - ret = ldb_connect(*ldb, options->url, 0, NULL); + ret = ldb_connect(*ldb, options->url, flags, NULL); if (ret != 0) { printf("failed to connect to %s\n", options->url); exit(1); -- cgit From af352b4664332416a49569618fb6a2ef4099be04 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 04:40:23 +0000 Subject: r10408: now that we are using tdb transactions we don't need any additional locking code in the ldb_tdb backend, except for a single read lock during searches to ensure searches don't cross transaction boundaries The tdb transactions code would map these extra locks to noops anyway (as locking makes no sense inside a transaction), but the work in setting up the locking keys still costs something, and it makes the code needlessly complex (This used to be commit 1b8d368a6771360fb0626127c02b3eb95f3eae59) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 36 ++++++++ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 164 ----------------------------------- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 - 3 files changed, 36 insertions(+), 166 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index fc864ac2ea..83079eab81 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -242,6 +242,42 @@ int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct l return 1; } +/* the lock key for search locking. Note that this is not a DN, its + just an arbitrary key to give to tdb. Also note that as we and + using transactions for all write operations and transactions take + care of their own locks, we don't need to do any locking anywhere + other than in ldb_search() */ +#define LDBLOCK "INT_LDBLOCK" + +/* + lock the database for read - use by ltdb_search +*/ +static int ltdb_lock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + TDB_DATA key; + + key.dptr = discard_const(LDBLOCK); + key.dsize = strlen(LDBLOCK); + + return tdb_chainlock_read(ltdb->tdb, key); +} + +/* + unlock the database after a ltdb_lock_read() +*/ +static int ltdb_unlock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + TDB_DATA key; + + key.dptr = discard_const(LDBLOCK); + key.dsize = strlen(LDBLOCK); + + return tdb_chainunlock_read(ltdb->tdb, key); +} + + /* search the database for a single simple dn diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index a2faaa805f..d8a03c3f55 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -41,9 +41,6 @@ #include "ldb/include/ldb_private.h" #include "ldb/ldb_tdb/ldb_tdb.h" -#define LDBLOCK "@INT_LDBLOCK" - - /* form a TDB_DATA for a record key caller frees @@ -95,141 +92,6 @@ failed: return key; } -/* - lock the database for write - currently a single lock is used -*/ -static int ltdb_lock(struct ldb_module *module, const char *lockname) -{ - struct ltdb_private *ltdb = module->private_data; - struct ldb_dn *lock_dn; - char *ldn; - TDB_DATA key; - int ret; - - if (lockname == NULL) { - return -1; - } - - ldn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); - if (ldn == NULL) { - return -1; - } - - lock_dn = ldb_dn_explode(module->ldb, ldn); - if (lock_dn == NULL) { - talloc_free(ldn); - return -1; - } - talloc_free(ldn); - - key = ltdb_key(module, lock_dn); - if (!key.dptr) { - talloc_free(lock_dn); - return -1; - } - - ret = tdb_chainlock(ltdb->tdb, key); - - talloc_free(key.dptr); - talloc_free(lock_dn); - - return ret; -} - -/* - unlock the database after a ltdb_lock() -*/ -static int ltdb_unlock(struct ldb_module *module, const char *lockname) -{ - struct ltdb_private *ltdb = module->private_data; - struct ldb_dn *lock_dn; - char *ldn; - TDB_DATA key; - - if (lockname == NULL) { - return -1; - } - - ldn = talloc_asprintf(module->ldb, "%s_%s", LDBLOCK, lockname); - if (ldn == NULL) { - return -1; - } - - lock_dn = ldb_dn_explode(module->ldb, ldn); - if (lock_dn == NULL) { - talloc_free(ldn); - return -1; - } - talloc_free(ldn); - - key = ltdb_key(module, lock_dn); - if (!key.dptr) { - talloc_free(lock_dn); - return -1; - } - - tdb_chainunlock(ltdb->tdb, key); - - talloc_free(key.dptr); - talloc_free(lock_dn); - - return 0; -} - - -/* - lock the database for read - use by ltdb_search -*/ -int ltdb_lock_read(struct ldb_module *module) -{ - struct ltdb_private *ltdb = module->private_data; - TDB_DATA key; - struct ldb_dn *lock_dn; - int ret; - - lock_dn = ldb_dn_explode(module, LDBLOCK); - if (lock_dn == NULL) { - return -1; - } - - key = ltdb_key(module, lock_dn); - if (!key.dptr) { - talloc_free(lock_dn); - return -1; - } - talloc_free(lock_dn); - - ret = tdb_chainlock_read(ltdb->tdb, key); - talloc_free(key.dptr); - return ret; -} - -/* - unlock the database after a ltdb_lock_read() -*/ -int ltdb_unlock_read(struct ldb_module *module) -{ - struct ltdb_private *ltdb = module->private_data; - struct ldb_dn *lock_dn; - TDB_DATA key; - - lock_dn = ldb_dn_explode(module, LDBLOCK); - if (lock_dn == NULL) { - return -1; - } - - key = ltdb_key(module, lock_dn); - if (!key.dptr) { - talloc_free(lock_dn); - return -1; - } - talloc_free(lock_dn); - - tdb_chainunlock_read(ltdb->tdb, key); - talloc_free(key.dptr); - return 0; -} - /* check special dn's have valid attributes currently only @ATTRIBUTES is checked @@ -335,12 +197,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) return ret; } - if (ltdb_lock(module, LDBLOCK) != 0) { - return LDB_ERR_OTHER; - } - if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module, LDBLOCK); return LDB_ERR_OTHER; } @@ -350,7 +207,6 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ltdb_modified(module, msg->dn); } - ltdb_unlock(module, LDBLOCK); return ret; } @@ -386,10 +242,6 @@ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) struct ldb_message *msg = NULL; int ret = LDB_ERR_OTHER; - if (ltdb_lock(module, LDBLOCK) != 0) { - return ret; - } - if (ltdb_cache_load(module) != 0) { goto failed; } @@ -421,12 +273,10 @@ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) ret = LDB_ERR_OTHER; talloc_free(msg); - ltdb_unlock(module, LDBLOCK); return ret; failed: talloc_free(msg); - ltdb_unlock(module, LDBLOCK); return ret; } @@ -749,12 +599,7 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) return ret; } - if (ltdb_lock(module, LDBLOCK) != 0) { - return -1; - } - if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module, LDBLOCK); return -1; } @@ -764,8 +609,6 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ltdb_modified(module, msg->dn); } - ltdb_unlock(module, LDBLOCK); - return ret; } @@ -778,12 +621,7 @@ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co char *error_str; int ret = LDB_ERR_OTHER; - if (ltdb_lock(module, LDBLOCK) != 0) { - return ret; - } - if (ltdb_cache_load(module) != 0) { - ltdb_unlock(module, LDBLOCK); return ret; } @@ -821,13 +659,11 @@ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co ldb_set_errstring(module, error_str); talloc_free(msg); - ltdb_unlock(module, LDBLOCK); return ret; failed: talloc_free(msg); - ltdb_unlock(module, LDBLOCK); return ret; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index f1da556f99..c16db67e1f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -96,8 +96,6 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn); int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn); int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); -int ltdb_lock_read(struct ldb_module *module); -int ltdb_unlock_read(struct ldb_module *module); int ltdb_index_del_value(struct ldb_module *module, const char *dn, struct ldb_message_element *el, int v_idx); -- cgit From 07f123b6c8292b3a7ae8a1a55c2ad56bd424c263 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 04:57:35 +0000 Subject: r10409: allow smb.conf override of ldb synchronous transactions with "ldb:nosync = yes/no" (This used to be commit 435cbcf78b70a82c2ec89fab21e4ff8af538f2f1) --- source4/lib/db_wrap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c index ed235761c9..482b6f17b5 100644 --- a/source4/lib/db_wrap.c +++ b/source4/lib/db_wrap.c @@ -90,6 +90,11 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, talloc_free(ldb); return NULL; } + + /* allow admins to force non-sync ldb for all databases */ + if (lp_parm_bool(-1, "ldb", "nosync", False)) { + flags |= LDB_FLG_NOSYNC; + } ret = ldb_connect(ldb, real_url, flags, options); if (ret == -1) { -- cgit From f08cdba2c5cfb5035e2ea6ae9f79591b8b0ad090 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 05:03:03 +0000 Subject: r10410: blindly update the scons file for tdb. I'm not sure how this works, but it definately needs transaction.c now (This used to be commit fa353a5bc562fa1ace0daf6586c42d1d5698c6e4) --- source4/lib/tdb/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index 728160f959..a7a477d7bc 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -4,7 +4,7 @@ tdbenv.Append(CPPPATH=['include']) tdb_files = ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', 'common/open.c','common/traverse.c','common/freelist.c', - 'common/error.c','common/tdbutil.c'] + 'common/error.c','common/transaction.c', 'common/tdbutil.c'] tdb = tdbenv.StaticLibrary('tdb', tdb_files) -- cgit From 7e8372f253b298cd9fd041ab7bab50323963154d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 22 Sep 2005 06:38:26 +0000 Subject: r10415: The ldb and tdb libraries are bad examples to test out the make proto code as they are marked as NOPROTO in the config.mk files. (This used to be commit 5f530eacbae073e9df6adde316404f70ecfe9122) --- source4/lib/ldb/SConscript | 6 +----- source4/lib/tdb/SConscript | 10 ++++------ 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index 52d6b87d02..ef89132ab2 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -1,6 +1,4 @@ -# tastes like -*- python -*- - -Import('hostenv', 'talloc', 'defines', 'proto_files') +Import('hostenv', 'talloc', 'defines') hostenv.StaticLibrary('modules/timestamps.c') hostenv.StaticLibrary('modules/rdn_name.c') @@ -23,7 +21,6 @@ ldb_tdb_source = ['ldb_tdb/ldb_tdb.c', 'ldb_tdb/ldb_search.c', 'ldb_tdb/ldb_cache.c', 'ldb_tdb/ldb_tdb_wrap.c'] hostenv.StaticLibrary('ldb_tdb', ldb_tdb_source) -proto_files += [File(x) for x in ldb_tdb_source] ldb_source = ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', @@ -31,7 +28,6 @@ ldb_source = ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', 'common/attrib_handlers.c','common/ldb_dn.c'] ldb = hostenv.StaticLibrary('ldb', ldb_source + talloc) -proto_files += [File(x) for x in ldb_source] Export('ldb') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index a7a477d7bc..09d0cf538a 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -1,17 +1,15 @@ -Import('hostenv', 'proto_files') +Import('hostenv') + tdbenv = hostenv.Copy() tdbenv.Append(CPPPATH=['include']) -tdb_files = ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', +tdb_source = ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', 'common/open.c','common/traverse.c','common/freelist.c', 'common/error.c','common/transaction.c', 'common/tdbutil.c'] -tdb = tdbenv.StaticLibrary('tdb', tdb_files) - -proto_files += [File(x) for x in tdb_files] +tdb = tdbenv.StaticLibrary('tdb', tdb_source) tdbtool = tdbenv.Program('bin/tdbtool', ['tools/tdbtool.c',tdb]) tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) tdbdump = tdbenv.Program('bin/tdbdump', ['tools/tdbdump.c',tdb]) tdbbackup = tdbenv.Program('bin/tdbbackup', ['tools/tdbbackup.c',tdb]) - -- cgit From 2ce3b5a00347cc3120efd12cd58d52a5c43305b3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 22 Sep 2005 09:06:37 +0000 Subject: r10419: Remove unused prototypes of locking functions (thanks Jelmer) omment about transactions (This used to be commit 33352507593875a147276841fdb70de8edd668f5) --- source4/lib/ldb/include/ldb.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index f7abd920eb..0e794c6209 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -49,6 +49,7 @@ major restrictions as compared to tdb: - no explicit locking calls + UPDATE: we have transactions now, better than locking --SSS. */ @@ -302,16 +303,6 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn); -/* - create a named lock -*/ -int ldb_lock(struct ldb_context *ldb, const char *lockname); - -/* - release a named lock -*/ -int ldb_unlock(struct ldb_context *ldb, const char *lockname); - /* delete a record from the database */ -- cgit From 05bd880626255c6547922204d7ba012aa9bc6d50 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 22 Sep 2005 12:23:44 +0000 Subject: r10420: Two minor scons fixes (This used to be commit 749b19d34f6105c696a07cc2cd39d5acecfc735b) --- source4/lib/tdb/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index 09d0cf538a..22f7f34ca5 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -12,4 +12,4 @@ tdb = tdbenv.StaticLibrary('tdb', tdb_source) tdbtool = tdbenv.Program('bin/tdbtool', ['tools/tdbtool.c',tdb]) tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) tdbdump = tdbenv.Program('bin/tdbdump', ['tools/tdbdump.c',tdb]) -tdbbackup = tdbenv.Program('bin/tdbbackup', ['tools/tdbbackup.c',tdb]) +#tdbbackup = tdbenv.Program('bin/tdbbackup', ['tools/tdbbackup.c',tdb]) -- cgit From bd310b792509f7305d7dc029eb4bec109322a4bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 13:12:46 +0000 Subject: r10421: following on discussions with simo, I have worked out a way of allowing searches to proceed while another process is in a transaction, then only upgrading the transaction lock to a write lock on commit. The solution is: - split tdb_traverse() into two calls, called tdb_traverse() and tdb_traverse_read(). The _read() version only gets read locks, and will fail any write operations made in the callback from the traverse. - the normal tdb_traverse() call allows for read or write operations in the callback, but gets the transaction lock, preventing transastions from starting inside the traverse In addition we enforce the following rule that you may not start a transaction within a traverse callback, although you can start a traverse within a transaction With these rules in place I believe all the deadlock possibilities are removed, and we can now allow for searches to happen in parallel with transactions (This used to be commit 7dd31288a701d772e45b1960ac4ce4cc1be782ed) --- source4/lib/tdb/common/error.c | 3 +- source4/lib/tdb/common/io.c | 11 ++++++ source4/lib/tdb/common/lock.c | 10 +++--- source4/lib/tdb/common/tdb.c | 5 +++ source4/lib/tdb/common/tdb_private.h | 1 + source4/lib/tdb/common/transaction.c | 29 ++++++++++----- source4/lib/tdb/common/traverse.c | 70 ++++++++++++++++++++++++++++-------- source4/lib/tdb/docs/README | 20 ++++++++++- source4/lib/tdb/include/tdb.h | 3 +- source4/lib/tdb/tools/tdbtorture.c | 10 +++++- 10 files changed, 130 insertions(+), 32 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/error.c b/source4/lib/tdb/common/error.c index 270a441463..4cf33a29ab 100644 --- a/source4/lib/tdb/common/error.c +++ b/source4/lib/tdb/common/error.c @@ -43,7 +43,8 @@ static struct tdb_errname { {TDB_ERR_EXISTS, "Record exists"}, {TDB_ERR_NOLOCK, "Lock exists on other keys"}, {TDB_ERR_EINVAL, "Invalid parameter"}, - {TDB_ERR_NOEXIST, "Record does not exist"} }; + {TDB_ERR_NOEXIST, "Record does not exist"}, + {TDB_ERR_RDONLY, "write not permitted"} }; /* Error string for the last tdb error */ const char *tdb_errorstr(struct tdb_context *tdb) diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index f02cd1a0e1..c1f6f55bc4 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -97,6 +97,11 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) static int tdb_write(struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len) { + if (tdb->read_only) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) return -1; @@ -224,6 +229,12 @@ void tdb_mmap(struct tdb_context *tdb) static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) { char buf[1024]; + + if (tdb->read_only) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + if (ftruncate(tdb->fd, size+addition) == -1) { char b = 0; if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 8061bab7b1..7a76bd3d9b 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -42,10 +42,12 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, struct flock fl; int ret; - if (tdb->flags & TDB_NOLOCK) + if (tdb->flags & TDB_NOLOCK) { return 0; + } + if ((rw_type == F_WRLCK) && (tdb->read_only)) { - errno = EACCES; + tdb->ecode = TDB_ERR_RDONLY; return -1; } @@ -64,8 +66,8 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, * EAGAIN is an expected return from non-blocking * locks. */ if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, + TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d: %s\n", + tdb->fd, offset, rw_type, lck_type, len, strerror(errno))); } else if (!probe && lck_type != F_SETLK) { /* Ensure error code is set for log fun to examine. */ diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index c37d37a4f2..2e229e88cc 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -227,6 +227,11 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) char *p = NULL; int ret = 0; + if (tdb->read_only) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + /* find which hash bucket it is in */ hash = tdb->hash_fn(&key); if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index eefcc52557..ba0a379e7f 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -162,6 +162,7 @@ struct tdb_traverse_lock { struct tdb_traverse_lock *next; u32 off; u32 hash; + int lock_rw; }; diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index b9d44a7283..75e91c56cc 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -372,6 +372,15 @@ int tdb_transaction_start(struct tdb_context *tdb) return -1; } + if (tdb->travlocks.next != NULL) { + /* you cannot use transactions inside a traverse (although you can use + traverse inside a transaction) as otherwise you can end up with + deadlock */ + TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + tdb->transaction = calloc(sizeof(struct tdb_transaction), 1); if (tdb->transaction == NULL) { tdb->ecode = TDB_ERR_OOM; @@ -388,15 +397,9 @@ int tdb_transaction_start(struct tdb_context *tdb) return -1; } - /* get a write lock from the freelist to the end of file. It - would be much better to make this a read lock as it would - increase parallelism, but it could lead to deadlocks on - commit when a write lock needs to be taken. - - TODO: look at alternative locking strategies to allow this - to be a read lock - */ - if (tdb_brlock_len(tdb, FREELIST_TOP, F_WRLCK, F_SETLKW, 0, 0) == -1) { + /* get a read lock from the freelist to the end of file. This + is upgraded to a write lock during the commit */ + if (tdb_brlock_len(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get hash locks\n")); tdb->ecode = TDB_ERR_LOCK; goto fail; @@ -763,6 +766,14 @@ int tdb_transaction_commit(struct tdb_context *tdb) return -1; } + /* upgrade the main transaction lock region to a write lock */ + if (tdb_brlock_len(tdb, FREELIST_TOP, F_WRLCK, F_SETLKW, 0, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_transaction_start: failed to upgrade hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + tdb_transaction_cancel(tdb); + return -1; + } + /* get the global lock - this prevents new users attaching to the database during the commit */ if (tdb_brlock_len(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c index 7d1e99cbe8..335dce4152 100644 --- a/source4/lib/tdb/common/traverse.c +++ b/source4/lib/tdb/common/traverse.c @@ -71,7 +71,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc } } - if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1) + if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) return -1; /* No previous record? Start at top of chain. */ @@ -118,7 +118,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc tdb_do_delete(tdb, current, rec) != 0) goto fail; } - tdb_unlock(tdb, tlock->hash, F_WRLCK); + tdb_unlock(tdb, tlock->hash, tlock->lock_rw); want_next = 0; } /* We finished iteration without finding anything */ @@ -126,7 +126,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc fail: tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0) + if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); return -1; } @@ -136,32 +136,33 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc if fn is NULL then it is not called a non-zero return value from fn() indicates that the traversal should stop */ -int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private) +static int tdb_traverse_internal(struct tdb_context *tdb, + tdb_traverse_func fn, void *private, + struct tdb_traverse_lock *tl) { TDB_DATA key, dbuf; struct list_struct rec; - struct tdb_traverse_lock tl = { NULL, 0, 0 }; int ret, count = 0; /* This was in the initializaton, above, but the IRIX compiler * did not like it. crh */ - tl.next = tdb->travlocks.next; + tl->next = tdb->travlocks.next; /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = &tl; + tdb->travlocks.next = tl; /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) { + while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) { count++; /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), + key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), rec.key_len + rec.data_len); if (!key.dptr) { ret = -1; - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) goto out; - if (tdb_unlock_record(tdb, tl.off) != 0) + if (tdb_unlock_record(tdb, tl->off) != 0) TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); goto out; } @@ -170,31 +171,70 @@ int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private) dbuf.dsize = rec.data_len; /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) { + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { ret = -1; goto out; } if (fn && fn(tdb, key, dbuf, private)) { /* They want us to terminate traversal */ ret = count; - if (tdb_unlock_record(tdb, tl.off) != 0) { + if (tdb_unlock_record(tdb, tl->off) != 0) { TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; ret = -1; } - tdb->travlocks.next = tl.next; + tdb->travlocks.next = tl->next; SAFE_FREE(key.dptr); return count; } SAFE_FREE(key.dptr); } out: - tdb->travlocks.next = tl.next; + tdb->travlocks.next = tl->next; if (ret < 0) return -1; else return count; } + +/* + a write style traverse - temporarily marks the db read only +*/ +int tdb_traverse_read(struct tdb_context *tdb, + tdb_traverse_func fn, void *private) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; + int ret, read_only = tdb->read_only; + tdb->read_only = 1; + ret = tdb_traverse_internal(tdb, fn, private, &tl); + tdb->read_only = read_only; + return ret; +} + +/* + a write style traverse - needs to get the transaction lock to + prevent deadlocks +*/ +int tdb_traverse(struct tdb_context *tdb, + tdb_traverse_func fn, void *private) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; + int ret; + + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_traverse: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + ret = tdb_traverse_internal(tdb, fn, private, &tl); + + tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0); + + return ret; +} + + /* find the first entry in the database and return its key */ TDB_DATA tdb_firstkey(struct tdb_context *tdb) { diff --git a/source4/lib/tdb/docs/README b/source4/lib/tdb/docs/README index 18b32de37f..b31ce36ab1 100644 --- a/source4/lib/tdb/docs/README +++ b/source4/lib/tdb/docs/README @@ -127,7 +127,25 @@ int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop + a non-zero return value from fn() indicates that the traversal + should stop. Traversal callbacks may not start transactions. + +---------------------------------------------------------------------- +int tdb_traverse_read(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, + TDB_DATA key, TDB_DATA dbuf, void *state), void *state); + + traverse the entire database - calling fn(tdb, key, data, state) on + each element, but marking the database read only during the + traversal, so any write operations will fail. This allows tdb to + use read locks, which increases the parallelism possible during the + traversal. + + return -1 on error or the record count traversed + + if fn is NULL then it is not called + + a non-zero return value from fn() indicates that the traversal + should stop. Traversal callbacks may not start transactions. ---------------------------------------------------------------------- TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb); diff --git a/source4/lib/tdb/include/tdb.h b/source4/lib/tdb/include/tdb.h index 3f123d814c..c116f29fc1 100644 --- a/source4/lib/tdb/include/tdb.h +++ b/source4/lib/tdb/include/tdb.h @@ -52,7 +52,7 @@ extern "C" { /* error codes */ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, - TDB_ERR_NOEXIST, TDB_ERR_EINVAL}; + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY}; typedef struct TDB_DATA { unsigned char *dptr; @@ -98,6 +98,7 @@ int tdb_close(struct tdb_context *tdb); TDB_DATA tdb_firstkey(struct tdb_context *tdb); TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); int tdb_exists(struct tdb_context *tdb, TDB_DATA key); int tdb_lockall(struct tdb_context *tdb); void tdb_unlockall(struct tdb_context *tdb); diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index b0a2e7484f..c0076a92d4 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -39,6 +39,7 @@ #define TRANSACTION_PROB 10 #define LOCKSTORE_PROB 5 #define TRAVERSE_PROB 20 +#define TRAVERSE_READ_PROB 20 #define CULL_PROB 100 #define KEYLEN 3 #define DATALEN 100 @@ -192,6 +193,13 @@ static void addrec_db(void) } #endif +#if TRAVERSE_READ_PROB + if (random() % TRAVERSE_READ_PROB == 0) { + tdb_traverse_read(db, NULL, NULL); + goto next; + } +#endif + data = tdb_fetch(db, key); if (data.dptr) free(data.dptr); @@ -273,7 +281,7 @@ static void usage(void) addrec_db(); } - tdb_traverse(db, NULL, NULL); + tdb_traverse_read(db, NULL, NULL); tdb_traverse(db, traverse_fn, NULL); tdb_traverse(db, traverse_fn, NULL); -- cgit From 1828b783cf2e975c8cfc1be3eb857d9c6fbda94b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 13:14:12 +0000 Subject: r10422: ldb_search() can now use tdb_traverse_read() to ensure it can run in parallel with any transaction (This used to be commit ddff66298f1a668c5220e24fc47f98d7dfc3068a) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 83079eab81..9af62c7754 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -472,7 +472,7 @@ static int ltdb_search_full(struct ldb_module *module, sinfo->count = 0; sinfo->failures = 0; - ret = tdb_traverse(ltdb->tdb, search_func, sinfo); + ret = tdb_traverse_read(ltdb->tdb, search_func, sinfo); if (ret == -1) { talloc_free(sinfo); -- cgit From fcb41c3bbde43c0b25aff7d6b5377301445eec00 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 13:16:23 +0000 Subject: r10423: minor changes to the ldb test suite to allow it to work correctly with a real ldap backend (such as openldap) (This used to be commit d267f8c6231664ec86edb2ae21e8585b1b51f7a1) --- source4/lib/ldb/tests/init.ldif | 15 +++++++++++++++ source4/lib/ldb/tests/test.ldif | 7 ------- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tests/init.ldif b/source4/lib/ldb/tests/init.ldif index 1e647e6521..9d89ec38ed 100644 --- a/source4/lib/ldb/tests/init.ldif +++ b/source4/lib/ldb/tests/init.ldif @@ -14,3 +14,18 @@ postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481 09 $ US telephonenumber: +1 313 764-1817 associateddomain: example.com + +dn: ou=People,o=University of Michigan,c=TEST +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +uidNumber: 0 +gidNumber: 0 + +dn: ou=Ldb Test,ou=People,o=University of Michigan,c=TEST +objectclass: organizationalUnit +objectclass: extensibleObject +ou: People +ou: Ldb Test +uidNumber: 0 +gidNumber: 0 diff --git a/source4/lib/ldb/tests/test.ldif b/source4/lib/ldb/tests/test.ldif index 66f4ba751c..7475c0969b 100644 --- a/source4/lib/ldb/tests/test.ldif +++ b/source4/lib/ldb/tests/test.ldif @@ -1,10 +1,3 @@ -dn: ou=People,o=University of Michigan,c=TEST -objectclass: organizationalUnit -objectclass: extensibleObject -ou: People -uidNumber: 0 -gidNumber: 0 - dn: ou=Groups,o=University of Michigan,c=TEST objectclass: organizationalUnit ou: Groups -- cgit From 86df9ca15a4488bb96f1d7c9244d8f9bb12912ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Sep 2005 13:20:28 +0000 Subject: r10424: for caller convenience, automatically turn a tdb_traverse() into a tdb_traverse_read() for read only databases (This used to be commit 9b53e04377d2ff652c4a9496798d2e3aa0dccab3) --- source4/lib/tdb/common/traverse.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c index 335dce4152..f8315f5770 100644 --- a/source4/lib/tdb/common/traverse.c +++ b/source4/lib/tdb/common/traverse.c @@ -220,6 +220,10 @@ int tdb_traverse(struct tdb_context *tdb, { struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; int ret; + + if (tdb->read_only) { + return tdb_traverse_read(tdb, fn, private); + } if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { TDB_LOG((tdb, 0, "tdb_traverse: failed to get transaction lock\n")); -- cgit From f3b412fbd6dd94d64eb6a63d88baef2816891c29 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 23 Sep 2005 00:38:22 +0000 Subject: r10438: Move portability functions to lib/replace/; replace now simply ensures that a given set of (working) POSIX functions are available (without prefixes to their names, etc). See lib/replace/README for a list. Functions that behave different from their POSIX specification (such as sys_select, sys_read, etc) have kept the sys_ prefix. (This used to be commit 29919a71059b29fa27a49b1f5b84bb8881de65fc) --- source4/lib/com/tables.c | 4 +- source4/lib/replace/README | 54 +++++++++++++++++++++++++++ source4/lib/replace/SConscript | 2 +- source4/lib/replace/config.m4 | 84 +++++++++++++++++++++++++++++++++++++++++- source4/lib/replace/config.mk | 4 +- source4/lib/replace/dlfcn.c | 71 +++++++++++++++++++++++++++++++++++ source4/lib/replace/replace.c | 73 ++++++++++++++++++------------------ source4/lib/replace/replace.h | 22 +++++++++++ source4/lib/signal.c | 2 +- source4/lib/system.c | 71 ----------------------------------- source4/lib/time.c | 34 +++++++++++++++++ source4/lib/util.c | 20 +--------- 12 files changed, 307 insertions(+), 134 deletions(-) create mode 100644 source4/lib/replace/README create mode 100644 source4/lib/replace/dlfcn.c (limited to 'source4/lib') diff --git a/source4/lib/com/tables.c b/source4/lib/com/tables.c index cf63e7e9a2..39bd6a6bd7 100644 --- a/source4/lib/com/tables.c +++ b/source4/lib/com/tables.c @@ -58,13 +58,13 @@ static struct IUnknown *get_com_class_so(TALLOC_CTX *mem_ctx, const struct GUID mod_name = talloc_asprintf(mem_ctx, "%s.so", clsid_str); talloc_free(clsid_str); - mod = sys_dlopen(mod_name, 0); + mod = dlopen(mod_name, 0); if (!mod) { return NULL; } - f = sys_dlsym(mod, "get_class_object"); + f = dlsym(mod, "get_class_object"); if (!f) { return NULL; diff --git a/source4/lib/replace/README b/source4/lib/replace/README new file mode 100644 index 0000000000..74b5397949 --- /dev/null +++ b/source4/lib/replace/README @@ -0,0 +1,54 @@ +This subsystem ensures that we can always use a certain core set of +functions and types, that are either provided by the OS or by replacement +functions / definitions in this subsystem. The aim is to try to stick +to POSIX functions in here as much as possible. Convenience functions +that are available on no platform at all belong in different subsystems +(such as LIBUTIL). + +The following functions are guarenteed: + +ftruncate +strlcpy +strlcat +mktime +rename +innetgr +initgroups +memmove +strdup +inet_ntoa +setlinebuf +vsyslog +timegm +setenv +strtoull +strtoll +strndup +strnlen +waitpid +seteuid +setegid +asprintf +snprintf +vasprintf +vsnprintf +opendir +readdir +telldir +seekdir +closedir +dlopen +dlclose +dlsym +dlerror +chroot +bzero +strerror +errno +mkstemp (a secure one!) + +Prerequisites: +memset (for bzero) +syslog (for vsyslog) +setnetgrent, getnetgrent, endnetgrent (for innetgr) +mktemp (for mkstemp) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index 84088db162..982120e1bf 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -9,4 +9,4 @@ if hostenv['configure']: conf.Finish() hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) -hostenv.StaticLibrary('replace', ['replace.c', 'snprintf.c']) +hostenv.StaticLibrary('replace', ['replace.c', 'snprintf.c','dlfcn.c']) diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 4dfeb5647a..88e3be5e94 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -15,5 +15,87 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) fi +dnl Provided by replace.c: +AC_CHECK_HEADERS(sys/syslog.h syslog.h) AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) -AC_CHECK_FUNCS(seteuid setresuid setegid setresgid) +AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) +AC_CHECK_FUNCS(timegm setenv vsyslog setlinebuf mktime ftruncate chsize rename) +AC_CHECK_FUNCS(waitpid strnlen strlcpy strlcat innetgr initgroups memmove strdup) +AC_HAVE_DECL(setresuid, [#include ]) +AC_HAVE_DECL(setresgid, [#include ]) +AC_HAVE_DECL(errno, [#include ]) + +AC_CACHE_CHECK([for secure mkstemp],samba_cv_HAVE_SECURE_MKSTEMP,[ +AC_TRY_RUN([#include +#include +#include +#include +main() { + struct stat st; + char tpl[20]="/tmp/test.XXXXXX"; + int fd = mkstemp(tpl); + if (fd == -1) exit(1); + unlink(tpl); + if (fstat(fd, &st) != 0) exit(1); + if ((st.st_mode & 0777) != 0600) exit(1); + exit(0); +}], +samba_cv_HAVE_SECURE_MKSTEMP=yes, +samba_cv_HAVE_SECURE_MKSTEMP=no, +samba_cv_HAVE_SECURE_MKSTEMP=cross)]) +if test x"$samba_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then + AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure]) +fi + +dnl Provided by snprintf.c: +AC_HAVE_DECL(asprintf, [#include ]) +AC_HAVE_DECL(vasprintf, [#include ]) +AC_HAVE_DECL(vsnprintf, [#include ]) +AC_HAVE_DECL(snprintf, [#include ]) +AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) + +AC_CACHE_CHECK([for C99 vsnprintf],samba_cv_HAVE_C99_VSNPRINTF,[ +AC_TRY_RUN([ +#include +#include +void foo(const char *format, ...) { + va_list ap; + int len; + char buf[20]; + long long l = 1234567890; + l *= 100; + + va_start(ap, format); + len = vsnprintf(buf, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1); + + if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(1); + + exit(0); +} +main() { foo("hello"); } +], +samba_cv_HAVE_C99_VSNPRINTF=yes,samba_cv_HAVE_C99_VSNPRINTF=no,samba_cv_HAVE_C99_VSNPRINTF=cross)]) +if test x"$samba_cv_HAVE_C99_VSNPRINTF" = x"yes"; then + AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Whether there is a C99 compliant vsnprintf]) +fi + +dnl Provided by dlfcn.c: +AC_SEARCH_LIBS_EXT(dlopen, [dl], DL_LIBS) +SMB_EXT_LIB(DL,[${DL_LIBS}],[${DL_CFLAGS}],[${DL_CPPFLAGS}],[${DL_LDFLAGS}]) +SAVE_LIBS="$LIBS" +LIBS="$LIBS $DL_LIBS" +AC_CHECK_HEADERS(dlfcn.h) +AC_CHECK_FUNCS(dlopen dlsym dlerror dlclose) +LIBS="$SAVE_LIBS" + +AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent],, + [AC_MSG_ERROR([Need syslog and memset])]) diff --git a/source4/lib/replace/config.mk b/source4/lib/replace/config.mk index 16952ea32d..2658f0e96a 100644 --- a/source4/lib/replace/config.mk +++ b/source4/lib/replace/config.mk @@ -13,7 +13,9 @@ NOPROTO = YES [SUBSYSTEM::LIBREPLACE] INIT_OBJ_FILES = lib/replace/replace.o ADD_OBJ_FILES = \ - lib/replace/snprintf.o + lib/replace/snprintf.o \ + lib/replace/dlfcn.o +NOPROTO = YES REQUIRED_SUBSYSTEMS = REPLACE_READDIR # End SUBSYSTEM LIBREPLACE ############################## diff --git a/source4/lib/replace/dlfcn.c b/source4/lib/replace/dlfcn.c new file mode 100644 index 0000000000..7a9e7230de --- /dev/null +++ b/source4/lib/replace/dlfcn.c @@ -0,0 +1,71 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#ifndef HAVE_DLOPEN +void *dlopen(const char *name, int flags) +{ + return NULL; +} +#endif + +#ifndef HAVE_DLSYM +void *dlsym(void *handle, const char *symbol) +{ + return NULL; +} +#endif + +#ifndef HAVE_DLERROR +const char *dlerror(void) +{ + return "dynamic loading of objects not supported on this platform"; +} +#endif + +#ifndef HAVE_DLCLOSE +int dlclose(void *handle) +{ + return 0; +} +#endif diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index ef8e053257..aa79f23fd0 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -361,39 +361,6 @@ duplicate a string #endif /* HAVE_SYSLOG */ #endif /* HAVE_VSYSLOG */ -/******************************************************************* -yield the difference between *A and *B, in seconds, ignoring leap seconds -********************************************************************/ -static int tm_diff(struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (1900 - 1); - int by = b->tm_year + (1900 - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; -} - -/******************************************************************* - return the UTC offset in seconds west of UTC, or 0 if it cannot be determined - ******************************************************************/ -int get_time_zone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - if (!tm) - return 0; - tm_utc = *tm; - tm = localtime(&t); - if (!tm) - return 0; - return tm_diff(&tm_utc,tm); -} #ifndef HAVE_TIMEGM /* @@ -496,14 +463,12 @@ int get_time_zone(time_t t) } #endif -int sys_waitpid(pid_t pid,int *status,int options) +#ifndef HAVE_WAITPID +int waitpid(pid_t pid,int *status,int options) { -#ifdef HAVE_WAITPID - return waitpid(pid,status,options); -#else /* USE_WAITPID */ return wait4(pid, status, options, NULL); -#endif /* USE_WAITPID */ } +#endif #ifndef HAVE_SETEUID int seteuid(uid_t euid) @@ -526,3 +491,35 @@ int sys_waitpid(pid_t pid,int *status,int options) #endif } #endif + +/******************************************************************* +os/2 also doesn't have chroot +********************************************************************/ +#ifndef HAVE_CHROOT +int chroot(const char *dname) +{ + static int done; + if (!done) { + DEBUG(1,("WARNING: no chroot!\n")); + done=1; + } + errno = ENOSYS; + return -1; +} +#endif + +/***************************************************************** + Possibly replace mkstemp if it is broken. +*****************************************************************/ + +#ifndef HAVE_SECURE_MKSTEMP +int rep_mkstemp(char *template) +{ + /* have a reasonable go at emulating it. Hope that + the system mktemp() isn't completly hopeless */ + char *p = mktemp(template); + if (!p) + return -1; + return open(p, O_CREAT|O_EXCL|O_RDWR, 0600); +} +#endif diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index f85c8de634..f906e7a2f5 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -23,6 +23,10 @@ #ifndef _replace_h #define _replace_h +#if defined(_MSC_VER) || defined(__MINGW32__) +#include "lib/replace/win32/replace.h" +#endif + #ifdef __COMPAR_FN_T #define QSORT_CAST (__compar_fn_t) #endif @@ -31,6 +35,15 @@ #define QSORT_CAST (int (*)(const void *, const void *)) #endif +#ifndef HAVE_STRERROR +extern char *sys_errlist[]; +#define strerror(i) sys_errlist[i] +#endif + +#ifndef HAVE_ERRNO_DECL +extern int errno; +#endif + #ifndef HAVE_STRDUP char *strdup(const char *s); #endif @@ -136,4 +149,13 @@ typedef unsigned char u_int8_t; #define HAVE_SOCKLEN_T 1 #endif +#ifdef HAVE_DLFCN_H +#include +#endif + +#ifndef HAVE_SECURE_MKSTEMP +#define mkstemp(path) rep_mkstemp(path) +int rep_mkstemp(char *temp); +#endif + #endif diff --git a/source4/lib/signal.c b/source4/lib/signal.c index 66d3e1f76e..6c0bb4007a 100644 --- a/source4/lib/signal.c +++ b/source4/lib/signal.c @@ -28,7 +28,7 @@ static void sig_cld(int signum) { - while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) ; /* diff --git a/source4/lib/system.c b/source4/lib/system.c index eb3799c7ca..629b2b07ff 100644 --- a/source4/lib/system.c +++ b/source4/lib/system.c @@ -23,7 +23,6 @@ #include "system/network.h" #include "system/wait.h" #include "system/filesys.h" -#include "pstring.h" /* The idea is that this file will eventually have wrappers around all @@ -77,20 +76,6 @@ int sys_usleep(long usecs) } -/******************************************************************* - System wrapper for getwd -********************************************************************/ -char *sys_getwd(char *s) -{ - char *wd; -#ifdef HAVE_GETCWD - wd = (char *)getcwd(s, sizeof (pstring)); -#else - wd = (char *)getwd(s); -#endif - return wd; -} - /******************************************************************* A read wrapper that will deal with EINTR. ********************************************************************/ @@ -121,24 +106,6 @@ ssize_t sys_write(int fd, const void *buf, size_t count) -/******************************************************************* -os/2 also doesn't have chroot -********************************************************************/ -int sys_chroot(const char *dname) -{ -#ifndef HAVE_CHROOT - static int done; - if (!done) { - DEBUG(1,("WARNING: no chroot!\n")); - done=1; - } - errno = ENOSYS; - return -1; -#else - return(chroot(dname)); -#endif -} - /************************************************************************** A wrapper for gethostbyname() that tries avoids looking up hostnames in the root domain, which can cause dial-on-demand links to come up for no @@ -181,39 +148,6 @@ struct hostent *sys_gethostbyname(const char *name) #endif /* REDUCE_ROOT_DNS_LOOKUPS */ } - - -/************************************************************************** - Wrappers for dlopen, dlsym, dlclose. -****************************************************************************/ - -void *sys_dlopen(const char *name, int flags) -{ -#if defined(HAVE_DLOPEN) - return dlopen(name, flags); -#else - return NULL; -#endif -} - -void *sys_dlsym(void *handle, const char *symbol) -{ -#if defined(HAVE_DLSYM) - return dlsym(handle, symbol); -#else - return NULL; -#endif -} - -const char *sys_dlerror(void) -{ -#if defined(HAVE_DLERROR) - return dlerror(); -#else - return NULL; -#endif -} - const char *sys_inet_ntoa(struct ipv4_addr in) { struct in_addr in2; @@ -221,11 +155,6 @@ const char *sys_inet_ntoa(struct ipv4_addr in) return inet_ntoa(in2); } -uint32_t sys_inet_addr(const char *s) -{ - return inet_addr(s); -} - struct ipv4_addr sys_inet_makeaddr(int net, int host) { struct in_addr in; diff --git a/source4/lib/time.c b/source4/lib/time.c index 61e92b8c00..5de9046c8d 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -594,3 +594,37 @@ NTTIME timeval_to_nttime(const struct timeval *tv) return 10*(tv->tv_usec + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); } + +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + +/******************************************************************* + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + ******************************************************************/ +int get_time_zone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); +} diff --git a/source4/lib/util.c b/source4/lib/util.c index a1d6f85eb9..0733103e93 100644 --- a/source4/lib/util.c +++ b/source4/lib/util.c @@ -347,7 +347,7 @@ uint32_t interpret_addr(const char *str) /* if it's in the form of an IP address then get the lib to interpret it */ if (is_ipaddress(str)) { - res = sys_inet_addr(str); + res = inet_addr(str); } else { /* otherwise assume it's a network name of some sort and use sys_gethostbyname */ @@ -518,24 +518,6 @@ void dump_data(int level, const uint8_t *buf,int len) } } -/***************************************************************** - Possibly replace mkstemp if it is broken. -*****************************************************************/ - -int smb_mkstemp(char *template) -{ -#if HAVE_SECURE_MKSTEMP - return mkstemp(template); -#else - /* have a reasonable go at emulating it. Hope that - the system mktemp() isn't completly hopeless */ - char *p = mktemp(template); - if (!p) - return -1; - return open(p, O_CREAT|O_EXCL|O_RDWR, 0600); -#endif -} - /***************************************************************** malloc that aborts with smb_panic on fail or zero size. *****************************************************************/ -- cgit From 7906d768cc05638515ff8b5e34827552425bd442 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 23 Sep 2005 07:36:09 +0000 Subject: r10444: Add LIBBASIC files to proto.h (This used to be commit 1c3748421f53f4a4e61865e1de95c53dc75d5cee) --- source4/lib/SConscript | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 387f557932..328d6233e4 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -2,7 +2,7 @@ Import('hostenv') # tastes like -*- python -*- SConscript(dirs=['talloc','charset']) -Import('talloc dynconfig charset') +Import('talloc', 'dynconfig', 'charset', 'proto_files') basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', @@ -10,6 +10,9 @@ basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'data_blob.c', 'util.c', 'util_sock.c', 'substitute.c', 'fsusage.c', 'ms_fnmatch.c', 'select.c', 'mutex.c', 'idtree.c', 'db_wrap.c'] + +proto_files += [File(x) for x in basic_files] + basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files]) Export('basic') -- cgit From aba4d018b4b9091789a47d1e40fc15c5e848794b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Sep 2005 07:53:58 +0000 Subject: r10449: remove double copyright header metze (This used to be commit f6bd76fa154de6ed7f7ef3257be9572f13f3ec48) --- source4/lib/replace/dlfcn.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/dlfcn.c b/source4/lib/replace/dlfcn.c index 7a9e7230de..6df57cd60c 100644 --- a/source4/lib/replace/dlfcn.c +++ b/source4/lib/replace/dlfcn.c @@ -19,27 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - Unix SMB/CIFS implementation. - Samba system utilities - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1998-2002 - - 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 - (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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - #include "includes.h" #ifndef HAVE_DLOPEN -- cgit From b85f7857dc82ca1dbde1a91463cfe83cbcbee5f7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 23 Sep 2005 14:09:38 +0000 Subject: r10452: Couple of small scons updates - ignore .sconsign files (This used to be commit b2d2b4f23393c727ae3feeaf4b4b65bc03a673f7) --- source4/lib/replace/README | 3 +++ source4/lib/replace/config.m4 | 1 + source4/lib/socket/config.m4 | 13 ------------- 3 files changed, 4 insertions(+), 13 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/README b/source4/lib/replace/README index 74b5397949..6575112eff 100644 --- a/source4/lib/replace/README +++ b/source4/lib/replace/README @@ -47,6 +47,9 @@ strerror errno mkstemp (a secure one!) +Types: +socklen_t + Prerequisites: memset (for bzero) syslog (for vsyslog) diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 88e3be5e94..3dbb5e4cf1 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -16,6 +16,7 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then fi dnl Provided by replace.c: +AC_HAVE_TYPE([socklen_t], [#include ]) AC_CHECK_HEADERS(sys/syslog.h syslog.h) AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index 786d6c72bc..daa85803dc 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -1,18 +1,5 @@ AC_CHECK_HEADERS(sys/socket.h sys/sockio.h sys/un.h) -AC_CACHE_CHECK([for socklen_t type],samba_cv_socklen_t, [ - AC_TRY_COMPILE([ -#include -#if STDC_HEADERS -#include -#include -#endif -#include ],[socklen_t i = 0], - samba_cv_socklen_t=yes,samba_cv_socklen_t=no)]) -if test x"$samba_cv_socklen_t" = x"yes"; then - AC_DEFINE(HAVE_SOCKLEN_T_TYPE,1,[Whether we have the variable type socklen_t]) -fi - AC_CACHE_CHECK([for sin_len in sock],samba_cv_HAVE_SOCK_SIN_LEN,[ AC_TRY_COMPILE([#include #include -- cgit From da46c9252ee887602b3e629065ca87b9ed11466f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 23 Sep 2005 15:08:17 +0000 Subject: r10453: Fix the build (This used to be commit 7be3ec4dbb919752477e1d995df9f7d295b67687) --- source4/lib/replace/config.m4 | 2 +- source4/lib/replace/replace.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 3dbb5e4cf1..ac4db9ed5b 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -16,7 +16,7 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then fi dnl Provided by replace.c: -AC_HAVE_TYPE([socklen_t], [#include ]) +AC_CHECK_TYPE([socklen_t], int) AC_CHECK_HEADERS(sys/syslog.h syslog.h) AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index f906e7a2f5..28a6392eb3 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -144,11 +144,6 @@ typedef unsigned short u_int16_t; typedef unsigned char u_int8_t; #endif -#ifndef HAVE_SOCKLEN_T -#define socklen_t int -#define HAVE_SOCKLEN_T 1 -#endif - #ifdef HAVE_DLFCN_H #include #endif -- cgit From 4be0ae794e4af2354d678fddd7bf1e822ffa9148 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 23 Sep 2005 16:32:52 +0000 Subject: r10456: More SCons fixes: - Add framework for fallback generating code - Move pread / pwrite replacement functions to libreplace - Support pidl builds correctly - Support asn1 builds correctly - Move OS-specific checks to lib/replace/SConscript (This used to be commit fbbfad0a1f7dedbf48e835a864f8285f283d72f3) --- source4/lib/charset/SConscript | 92 +++++++++++++++++++++++++++++++++++++---- source4/lib/registry/SConscript | 8 ++++ source4/lib/replace/README | 2 + source4/lib/replace/SConscript | 28 +++++++++++-- source4/lib/replace/config.m4 | 1 + source4/lib/replace/replace.c | 22 ++++++++++ source4/lib/socket/SConscript | 59 ++++++++++++++++++++++++++ 7 files changed, 200 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index 53e5db44bb..b3305579e1 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -1,15 +1,91 @@ +#!/usr/bin/env python +# tastes like -*- python -*- + Import('hostenv') -SConscript('../../build/scons/iconv.py') -# tastes like -*- python -*- -#conf = Configure( custom_tests = { 'CheckIconv' : CheckIconv }) -#(have_iconv,iconv) = conf.CheckIconv() -#conf.Finish() +def _CheckIconvPath(context,path): + # Some systems have iconv in libc, some have it in libiconv (OSF/1 and + # those with the standalone portable libiconv installed). + context.Message("checking for iconv in " + path + " ... ") + + main = """ +int main() +{ + iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + return 0; +}""" + + have_giconv_iconv = context.TryLink(""" +#include +#include +""" + main, '.c') + if have_giconv_iconv: + context.Result(1) + return ("giconv.h", "") + + have_iconv_iconv = context.TryLink(""" +#include +#include +""" + main, '.c') + + if have_iconv_iconv: + context.Result(1) + return ("iconv.h", "") + + #FIXME: Add -lgiconv + have_giconv_lib_iconv = context.TryLink(""" +#include +#include +""" + main, '.c') + if have_giconv_lib_iconv: + context.Result(1) + return ("giconv.h", "-lgiconv") + + #FIXME: Add -liconv + have_iconv_lib_iconv = context.TryLink(""" +#include +#include +"""+main,'.c') + + if have_iconv_lib_iconv: + context.Result(1) + return ("iconv.h", "-liconv") + + return None + +def CheckIconv(context): + context.Message("checking for iconv ... ") + + look_dirs = ['/usr','/usr/local','/sw'] + + for p in look_dirs: + _CheckIconvPath(context,p) #FIXME: Handle return value + + if context.TryRun(""" +#include +main() { + iconv_t cd = iconv_open("ASCII", "UCS-2LE"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} +""", '.c'): + context.Result(1) + return (1,[]) + + context.Result(0) + return (0,[]) -#if not have_iconv: -# print "Install iconv for better charset compatibility" +if hostenv['configure']: + conf = hostenv.Configure( custom_tests = { 'CheckIconv' : CheckIconv }) + (have_iconv,iconv) = conf.CheckIconv() + conf.Finish() -iconv = [] + if not have_iconv: + print "Install iconv for better charset compatibility" +else: + iconv = [] # FIXME charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c',iconv]) Export('charset') diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript index a90557532b..aa2d587260 100644 --- a/source4/lib/registry/SConscript +++ b/source4/lib/registry/SConscript @@ -9,4 +9,12 @@ regshell = hostenv.Program('regshell', ['tools/regshell.c',registry,talloc,basic regpatch = hostenv.Program('regpatch', ['tools/regpatch.c',registry,talloc,basic,popt_common,popt,param]) regdiff = hostenv.Program('regdiff', ['tools/regdiff.c',registry,talloc,basic,popt_common,popt,param]) +hostenv.StaticLibrary('reg_backend_dir.c') +hostenv.StaticLibrary('reg_backend_gconf.c') +hostenv.StaticLibrary('reg_backend_ldb.c') +hostenv.StaticLibrary('reg_backend_nt4', ['reg_backend_nt4.c',hostenv.TdrMarshaller('regf.idl')]) +hostenv.StaticLibrary('reg_backend_rpc.c') +hostenv.StaticLibrary('reg_backend_w95.c') +hostenv.StaticLibrary('reg_backend_wine.c') + hostenv.Install(paths['BINDIR'], [regtree,regshell,regpatch,regdiff]) diff --git a/source4/lib/replace/README b/source4/lib/replace/README index 6575112eff..eb3360b74a 100644 --- a/source4/lib/replace/README +++ b/source4/lib/replace/README @@ -46,6 +46,8 @@ bzero strerror errno mkstemp (a secure one!) +pread +pwrite Types: socklen_t diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index 982120e1bf..a2b3a30e10 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -1,11 +1,31 @@ -Import('hostenv') +#!/usr/bin/env python +Import('hostenv defines') if hostenv['configure']: conf = Configure(hostenv) - #FIXME: conf.CheckBrokenInetNtoa() + for f in ['memset','syslog','setnetgrent','getnetgrent','endnetgrent', \ + 'mktemp']: + if not conf.CheckFunc(f,'c'): + print "Required function `%s' not found" % f + exit(1) + for f in ['strtoull','__strtoull','strtouq','strtoll','__strtoll','strtoq', - 'seteuid','setresuid','setegid','setresgid']: - conf.CheckFunc(f,'c') + 'seteuid','setresuid','setegid','setresgid','dlsym','dlopen', + 'dlerror','dlclose','waitpid','getcwd','strdup','strndup', + 'strnlen','strerror','bzero','chroot','strlcpy','strlcat', + 'memmove','vsnprintf','asprintf','snprintf','vasprintf', + 'innetgr','mktime','rename','ftruncate','chsize','setlinebuf', + 'setenv','vsyslog','pread','pwrite']: + if conf.CheckFunc(f,'c'): + defines['HAVE_' + f.upper()] = 1 + + for h in ['dlfcn.h']: + if conf.CheckCHeader('dlfcn.h'): + defines['HAVE_' + h.upper().replace('.','_').replace('/','_')] = 1 + + if not conf.CheckType('socklen_t'): + defines['socklen_t'] = 'int' + conf.Finish() hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index ac4db9ed5b..07fbed9d91 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -22,6 +22,7 @@ AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) AC_CHECK_FUNCS(timegm setenv vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid strnlen strlcpy strlcat innetgr initgroups memmove strdup) +AC_CHECK_FUNCS(pread pwrite) AC_HAVE_DECL(setresuid, [#include ]) AC_HAVE_DECL(setresgid, [#include ]) AC_HAVE_DECL(errno, [#include ]) diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index aa79f23fd0..c53b5a5727 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -523,3 +523,25 @@ int rep_mkstemp(char *template) return open(p, O_CREAT|O_EXCL|O_RDWR, 0600); } #endif + +#ifndef HAVE_PREAD +static ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return read(__fd, __buf, __nbytes); +} +#endif + +#ifndef HAVE_PWRITE +static ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return write(__fd, __buf, __nbytes); +} +#endif + + diff --git a/source4/lib/socket/SConscript b/source4/lib/socket/SConscript index db449592c2..c4e791467a 100644 --- a/source4/lib/socket/SConscript +++ b/source4/lib/socket/SConscript @@ -1,5 +1,64 @@ +#!/usr/bin/env python Import('hostenv') + +if hostenv['configure']: + conf = hostenv.Configure() + conf.CheckCHeader('sys/socket.h') + conf.CheckCHeader('sys/sockio.h') + conf.CheckCHeader('sys/un.h') + #HAVE_SOCK_SIN_LEN + conf.TryCompile(""" +#include +#include +#include + +int main(void) +{ + struct sockaddr_in sock; sock.sin_len = sizeof(sock); + return 0; +}""", '.c') + + #HAVE_UNIXSOCKET + conf.TryCompile(""" +#include +#include +#include +#include +#include ], + +int main(void) +{ + struct sockaddr_un sunaddr; + sunaddr.sun_family = AF_UNIX; + return 0; +}""", '.c') + + # HAVE_IPV6 + conf.CheckFunc('gethostbyname2') + + # The following test taken from the cvs sources + # If we can't find connect, try looking in -lsocket, -lnsl, and -linet. + # The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has + # libsocket.so which has a bad implementation of gethostbyname (it + # only looks in /etc/hosts), so we only look for -lsocket if we need + # it. + + connect_libs = [] + + if not conf.CheckFunc('connect'): + for l in ['nsl_s','nsl','socket','inet']: + if conf.CheckLib(l, 'connect'): + connect_libs.append(l) + break + + # HAVE_WORKING_AF_LOCAL + # FIXME: Try compiling build/tests/unixsock.c + + + conf.Finish() + hostenv.StaticLibrary('socket_ipv4.c') hostenv.StaticLibrary('socket_ipv6.c') hostenv.StaticLibrary('socket_unix.c') hostenv.StaticLibrary('socket', ['socket.c','access.c','connect.c']) + -- cgit From 036b27c8e4f8bdd61049c5f3b78573937badbdd6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 02:31:43 +0000 Subject: r10459: fixed some portability problems (This used to be commit 03942dd54b31e7a4cf9c6270b26ccf68a3234b40) --- source4/lib/tdb/common/tdb_private.h | 2 ++ source4/lib/tdb/config.m4 | 1 + source4/lib/tdb/tools/tdbtorture.c | 3 +++ 3 files changed, 6 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index ba0a379e7f..9eeaea4cb0 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -33,7 +33,9 @@ #include #include +#ifdef HAVE_STDINT_H #include +#endif #include #include #include diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index d45bbe4383..2ebd29993d 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,4 +1,5 @@ AC_CHECK_FUNCS(mmap pread pwrite) +AC_CHECK_HEADERS(getopt.h) if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtdb,YES) diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index c0076a92d4..591fdab2f7 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -30,7 +30,10 @@ #endif +#ifdef HAVE_GETOPT_H #include +#endif + #define REOPEN_PROB 30 #define DELETE_PROB 8 -- cgit From c0e6586405d2ceb8af9b4252ced83dea931ab8aa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 02:37:22 +0000 Subject: r10460: fixed portability of transaction code to systems with integer alignment constraints (like sparc) (This used to be commit bce35ad237a55376b6af98416eec92a7c4b422a6) --- source4/lib/tdb/common/transaction.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index 75e91c56cc..5f281ca4da 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -628,7 +628,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, struct list_struct *rec; tdb_off_t recovery_offset, recovery_max_size; tdb_off_t old_map_size = tdb->transaction->old_map_size; - u32 magic; + u32 magic, tailer; /* check that the recovery area has enough space @@ -666,8 +666,8 @@ static int transaction_setup_recovery(struct tdb_context *tdb, tdb->ecode = TDB_ERR_CORRUPT; return -1; } - ((u32 *)p)[0] = el->offset; - ((u32 *)p)[1] = el->length; + memcpy(p, &el->offset, 4); + memcpy(p+4, &el->length, 4); if (DOCONV()) { tdb_convert(p, 8); } @@ -683,7 +683,8 @@ static int transaction_setup_recovery(struct tdb_context *tdb, } /* and the tailer */ - *(u32 *)p = sizeof(*rec) + recovery_max_size; + tailer = sizeof(*rec) + recovery_max_size; + memcpy(p, &tailer, 4); CONVERT(p); /* write the recovery data to the recovery area */ @@ -926,8 +927,8 @@ int tdb_transaction_recover(struct tdb_context *tdb) if (DOCONV()) { tdb_convert(p, 8); } - ofs = ((u32 *)p)[0]; - len = ((u32 *)p)[1]; + memcpy(&ofs, p, 4); + memcpy(&len, p+4, 4); if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { free(data); -- cgit From 5540712156872cc55ea7502d836553a59a812033 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 02:39:09 +0000 Subject: r10461: fixed tdb build on systems without stdint.h (This used to be commit 83168c7e76c7e3adcdb0eec1611827d4db09f858) --- source4/lib/tdb/common/open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/open.c b/source4/lib/tdb/common/open.c index 117152d4d9..7ebc067175 100644 --- a/source4/lib/tdb/common/open.c +++ b/source4/lib/tdb/common/open.c @@ -136,7 +136,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, struct tdb_context *tdb; struct stat st; int rev = 0, locked = 0; - uint8_t *vp; + unsigned char *vp; u32 vertest; if (!(tdb = calloc(1, sizeof *tdb))) { @@ -222,7 +222,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } rev = (tdb->flags & TDB_CONVERT); } - vp = (uint8_t *)&tdb->header.version; + vp = (unsigned char *)&tdb->header.version; vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | (((u32)vp[2]) << 8) | (u32)vp[3]; tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; -- cgit From 36cfc9c4acb17ac2a380a36c55cb444eff891db6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 03:28:10 +0000 Subject: r10462: cope better with compilers that don't put the object file in the same directory as the source (This used to be commit 312491b2511039f3d6308e70c849810c35a3259c) --- source4/lib/tdb/Makefile.in | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/Makefile.in b/source4/lib/tdb/Makefile.in index 1942d9050a..8b64315a83 100644 --- a/source4/lib/tdb/Makefile.in +++ b/source4/lib/tdb/Makefile.in @@ -17,6 +17,10 @@ TDB_OBJ = common/tdb.o common/dump.o common/io.o common/lock.o \ all: $(PROGS) +.c.o: + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $< -o $@ + install: all mkdir -p $(bindir) mkdir -p $(includedir) -- cgit From fbc2dbbb41e1ed5fe1ca778c24fef81f480a2322 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 03:29:50 +0000 Subject: r10463: consider it an error if tdbtorture produces any log messages (This used to be commit d9ee0e8b59ee52ed1e41865cffe97e32b504e7e7) --- source4/lib/tdb/tools/tdbtorture.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 591fdab2f7..3fc395ba98 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -50,6 +50,7 @@ static struct tdb_context *db; static int in_transaction; +static int log_count; #ifdef PRINTF_ATTRIBUTE static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); @@ -58,6 +59,8 @@ static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) { va_list ap; + log_count++; + va_start(ap, format); vfprintf(stdout, format, ap); va_end(ap); @@ -304,7 +307,13 @@ static void usage(void) exit(1); } } - printf("OK\n"); + if (log_count == 0) { + printf("OK\n"); + } + } + + if (log_count != 0) { + exit(1); } return 0; -- cgit From 5860aef9cd53da572bef1b86a62a3a5e86da84b0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 03:43:02 +0000 Subject: r10465: separate out a read_only db from a read-only traversal to ensure we don't end up doing a mmap read only (This used to be commit 294ccfd46a0c4e1af9365d028acdabec03c41ad3) --- source4/lib/tdb/common/io.c | 4 ++-- source4/lib/tdb/common/lock.c | 4 ++-- source4/lib/tdb/common/tdb.c | 4 ++-- source4/lib/tdb/common/tdb_private.h | 1 + source4/lib/tdb/common/transaction.c | 2 +- source4/lib/tdb/common/traverse.c | 10 +++++----- 6 files changed, 13 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index c1f6f55bc4..a276a8c291 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -97,7 +97,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) static int tdb_write(struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len) { - if (tdb->read_only) { + if (tdb->read_only || tdb->traverse_read) { tdb->ecode = TDB_ERR_RDONLY; return -1; } @@ -230,7 +230,7 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad { char buf[1024]; - if (tdb->read_only) { + if (tdb->read_only || tdb->traverse_read) { tdb->ecode = TDB_ERR_RDONLY; return -1; } diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 7a76bd3d9b..703cfe9dc5 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -46,7 +46,7 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, return 0; } - if ((rw_type == F_WRLCK) && (tdb->read_only)) { + if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { tdb->ecode = TDB_ERR_RDONLY; return -1; } @@ -161,7 +161,7 @@ int tdb_lockall(struct tdb_context *tdb) u32 i; /* There are no locks on read-only dbs */ - if (tdb->read_only) + if (tdb->read_only || tdb->traverse_read) return TDB_ERRCODE(TDB_ERR_LOCK, -1); for (i = 0; i < tdb->header.hash_size; i++) if (tdb_lock(tdb, i, F_WRLCK)) diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c index 2e229e88cc..4b0d4a31c5 100644 --- a/source4/lib/tdb/common/tdb.c +++ b/source4/lib/tdb/common/tdb.c @@ -164,7 +164,7 @@ int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct tdb_off_t last_ptr, i; struct list_struct lastrec; - if (tdb->read_only) return -1; + if (tdb->read_only || tdb->traverse_read) return -1; if (tdb_write_lock_record(tdb, rec_ptr) == -1) { /* Someone traversing here: mark it as dead */ @@ -227,7 +227,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) char *p = NULL; int ret = 0; - if (tdb->read_only) { + if (tdb->read_only || tdb->traverse_read) { tdb->ecode = TDB_ERR_RDONLY; return -1; } diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index 9eeaea4cb0..2b2d6de411 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -183,6 +183,7 @@ struct tdb_context { int fd; /* open file descriptor for the database */ tdb_len_t map_size; /* how much space has been mapped */ int read_only; /* opened read-only */ + int traverse_read; /* read-only traversal */ struct tdb_lock_type *locked; /* array of chain locks */ enum TDB_ERROR ecode; /* error code for last tdb error */ struct tdb_header header; /* a cached copy of the header */ diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index 5f281ca4da..a01f8307e9 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -349,7 +349,7 @@ static const struct tdb_methods transaction_methods = { int tdb_transaction_start(struct tdb_context *tdb) { /* some sanity checks */ - if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) { + if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); tdb->ecode = TDB_ERR_EINVAL; return -1; diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c index f8315f5770..9271b75aa8 100644 --- a/source4/lib/tdb/common/traverse.c +++ b/source4/lib/tdb/common/traverse.c @@ -114,7 +114,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc /* Try to clean dead ones from old traverses */ current = tlock->off; tlock->off = rec->next; - if (!tdb->read_only && + if (!(tdb->read_only || tdb->traverse_read) && tdb_do_delete(tdb, current, rec) != 0) goto fail; } @@ -204,10 +204,10 @@ int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *private) { struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; - int ret, read_only = tdb->read_only; - tdb->read_only = 1; + int ret; + tdb->traverse_read++; ret = tdb_traverse_internal(tdb, fn, private, &tl); - tdb->read_only = read_only; + tdb->traverse_read--; return ret; } @@ -221,7 +221,7 @@ int tdb_traverse(struct tdb_context *tdb, struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; int ret; - if (tdb->read_only) { + if (tdb->read_only || tdb->traverse_read) { return tdb_traverse_read(tdb, fn, private); } -- cgit From d98b913aa9a0dd40a9373d65882f1cb742d033af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 04:56:51 +0000 Subject: r10466: work around missing pread/pwrite declaration on openbsd (This used to be commit e615f36733966f9992670e3650fbe9b20d7d218c) --- source4/lib/tdb/aclocal.m4 | 12 ++++++++++++ source4/lib/tdb/common/tdb_private.h | 8 ++++++++ source4/lib/tdb/config.m4 | 3 +++ 3 files changed, 23 insertions(+) create mode 100644 source4/lib/tdb/aclocal.m4 (limited to 'source4/lib') diff --git a/source4/lib/tdb/aclocal.m4 b/source4/lib/tdb/aclocal.m4 new file mode 100644 index 0000000000..cdc2a2fa52 --- /dev/null +++ b/source4/lib/tdb/aclocal.m4 @@ -0,0 +1,12 @@ +dnl see if a declaration exists for a function or variable +dnl defines HAVE_function_DECL if it exists +dnl AC_HAVE_DECL(var, includes) +AC_DEFUN(AC_HAVE_DECL, +[ + AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[ + AC_TRY_COMPILE([$2],[int i = (int)$1], + ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)]) + if test x"$ac_cv_have_$1_decl" = x"yes"; then + AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available]) + fi +]) diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index 2b2d6de411..a451dff0af 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -45,6 +45,14 @@ #include #include "config.h" #include "tdb.h" + +#ifndef HAVE_PREAD_DECL +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +#endif +#ifndef HAVE_PWRITE_DECL +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); +#endif + #else #include "includes.h" #include "lib/tdb/include/tdb.h" diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 2ebd29993d..31c33552ea 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,6 +1,9 @@ AC_CHECK_FUNCS(mmap pread pwrite) AC_CHECK_HEADERS(getopt.h) +AC_HAVE_DECL(pread, [#include ]) +AC_HAVE_DECL(pwrite, [#include ]) + if test x"$experimental" = x"yes"; then SMB_LIBRARY_ENABLE(libtdb,YES) fi -- cgit From 6e4ebbed8928d618f56c06bfc0802891c3d939ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 05:02:02 +0000 Subject: r10467: aix doesn't like zero length malloc :( (This used to be commit 0177c6ca3e9baa223b5f7b29adc12d862dcb19d8) --- source4/lib/tdb/common/io.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index a276a8c291..e9d4e87ac8 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -351,6 +351,11 @@ unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len { unsigned char *buf; + /* some systems don't like zero length malloc */ + if (len == 0) { + len = 1; + } + if (!(buf = malloc(len))) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_OOM; -- cgit From 3bcfc68e0d158b272e0ef87bf585f79a570136ba Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 06:49:28 +0000 Subject: r10468: - terminate tdbtorture quickly when an error is detected - more workarounds for aix not handling malloc of size 0 (This used to be commit c2b1739c6389503854f55fa8407c55071781eff4) --- source4/lib/tdb/common/io.c | 4 +++ source4/lib/tdb/common/transaction.c | 4 +++ source4/lib/tdb/tools/tdbtorture.c | 64 +++++++++++++++++++++++------------- 3 files changed, 49 insertions(+), 23 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index e9d4e87ac8..355f76962f 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -97,6 +97,10 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) static int tdb_write(struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len) { + if (len == 0) { + return 0; + } + if (tdb->read_only || tdb->traverse_read) { tdb->ecode = TDB_ERR_RDONLY; return -1; diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index a01f8307e9..73c0587a40 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -196,6 +196,10 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len) { struct tdb_transaction_el *el; + + if (len == 0) { + return 0; + } /* if the write is to a hash head, then update the transaction hash heads */ diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 3fc395ba98..eded561106 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -50,7 +50,7 @@ static struct tdb_context *db; static int in_transaction; -static int log_count; +static int error_count; #ifdef PRINTF_ATTRIBUTE static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); @@ -59,7 +59,7 @@ static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) { va_list ap; - log_count++; + error_count++; va_start(ap, format); vfprintf(stdout, format, ap); @@ -78,7 +78,7 @@ static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) static void fatal(const char *why) { perror(why); - exit(1); + error_count++; } static char *randbuf(int len) @@ -283,37 +283,55 @@ static void usage(void) srand(seed + i); srandom(seed + i); - for (i=0;i Date: Sat, 24 Sep 2005 06:53:24 +0000 Subject: r10469: use the older style of structure initialisation for tdb to make it more portable. tdb is used in more than just Samba4, and I think the portability/readability balance is a bit different (This used to be commit fc692dc61f06d61cb9126d2a8ccc240cecd11da6) --- source4/lib/tdb/common/io.c | 12 ++++++------ source4/lib/tdb/common/transaction.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/io.c b/source4/lib/tdb/common/io.c index 355f76962f..0a910270c9 100644 --- a/source4/lib/tdb/common/io.c +++ b/source4/lib/tdb/common/io.c @@ -395,12 +395,12 @@ int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct } static const struct tdb_methods io_methods = { - .tdb_read = tdb_read, - .tdb_write = tdb_write, - .next_hash_chain = tdb_next_hash_chain, - .tdb_oob = tdb_oob, - .tdb_expand_file = tdb_expand_file, - .tdb_brlock = tdb_brlock + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_oob, + tdb_expand_file, + tdb_brlock }; /* diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index 73c0587a40..fdcba110c2 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -337,12 +337,12 @@ int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, } static const struct tdb_methods transaction_methods = { - .tdb_read = transaction_read, - .tdb_write = transaction_write, - .next_hash_chain = transaction_next_hash_chain, - .tdb_oob = transaction_oob, - .tdb_expand_file = transaction_expand_file, - .tdb_brlock = transaction_brlock + transaction_read, + transaction_write, + transaction_next_hash_chain, + transaction_oob, + transaction_expand_file, + transaction_brlock }; -- cgit From c72afc39f08cca1937cb41d406e66bcc4dbdd80a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 07:07:22 +0000 Subject: r10470: solaris8 has a problem with tdbtorture with 3 processes. To see if this is just a solaris issue this patch changes the default to 3, and I'll see how many build farm boxes break (This used to be commit c85836bafc9c042deac2a02ef6fddbfeaa5f47f1) --- source4/lib/tdb/tools/tdbtorture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index eded561106..96f8c16dfb 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -230,7 +230,7 @@ static void usage(void) int main(int argc, char * const *argv) { int i, seed = -1; - int num_procs = 2; + int num_procs = 3; int num_loops = 5000; int hash_size = 2; int c; -- cgit From 60a455dd449acdad9bdb21fbe68a15e2b584a5d2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 07:30:20 +0000 Subject: r10471: stratos doesn't have getpagesize(), so guess 8k on systems that don't have it. Overestimating is harmless. (This used to be commit ab953c8c72060c496876b6f39d388ad2f7e3c7e0) --- source4/lib/tdb/common/tdb_private.h | 4 ++++ source4/lib/tdb/config.m4 | 2 +- source4/lib/tdb/tools/tdbtorture.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index a451dff0af..bfd8d04448 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -65,6 +65,10 @@ ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); #define u32 unsigned #endif +#ifndef HAVE_GETPAGESIZE +#define getpagesize() 0x2000 +#endif + typedef u32 tdb_len_t; typedef u32 tdb_off_t; diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 31c33552ea..52daf7a8ea 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,4 +1,4 @@ -AC_CHECK_FUNCS(mmap pread pwrite) +AC_CHECK_FUNCS(mmap pread pwrite getpagesize) AC_CHECK_HEADERS(getopt.h) AC_HAVE_DECL(pread, [#include ]) diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index 96f8c16dfb..c6298167fd 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -319,7 +319,7 @@ static void usage(void) if (pids[j] == pid) break; } if (j == num_procs) { - printf("unknown child %d exited!?\n", pid); + printf("unknown child %d exited!?\n", (int)pid); exit(1); } if (WEXITSTATUS(status) != 0) { -- cgit From ebf07796086b1b9c03550326c3a3da437d4e7af3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Sep 2005 08:24:55 +0000 Subject: r10472: Check for strndup (This used to be commit 8335aa056fd8a414feaffa707dc0bc20ac27388f) --- source4/lib/replace/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 07fbed9d91..26a2cae56d 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -22,7 +22,7 @@ AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) AC_CHECK_FUNCS(timegm setenv vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid strnlen strlcpy strlcat innetgr initgroups memmove strdup) -AC_CHECK_FUNCS(pread pwrite) +AC_CHECK_FUNCS(pread pwrite strndup) AC_HAVE_DECL(setresuid, [#include ]) AC_HAVE_DECL(setresgid, [#include ]) AC_HAVE_DECL(errno, [#include ]) -- cgit From 2a9b65cd17b271ff88fca6bda0bddc6230c2b319 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 13:10:19 +0000 Subject: r10475: make sure we report failures in tdbtorture (ie. get the exit status right) (This used to be commit a795fc0aa141c08af6e37af07c88164bad3db35b) --- source4/lib/tdb/tools/tdbtorture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/tools/tdbtorture.c b/source4/lib/tdb/tools/tdbtorture.c index c6298167fd..840397b73b 100644 --- a/source4/lib/tdb/tools/tdbtorture.c +++ b/source4/lib/tdb/tools/tdbtorture.c @@ -334,5 +334,5 @@ static void usage(void) printf("OK\n"); } - return 0; + return error_count; } -- cgit From 70b52b02a77c695d32aa57daaeb5689cd6857eba Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 Sep 2005 14:58:18 +0000 Subject: r10476: Move some more types to libreplace. Fix missing strndup errors for heimdal (This used to be commit e09ffdfb1dba289b79ac7e5a638bf5322d45ddc0) --- source4/lib/replace/README | 4 ++++ source4/lib/replace/SConscript | 25 ++++++++++++++++++++++++- source4/lib/replace/config.m4 | 17 +++++++++++++++-- source4/lib/replace/replace.h | 12 ------------ 4 files changed, 43 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/README b/source4/lib/replace/README index eb3360b74a..45c8bccf13 100644 --- a/source4/lib/replace/README +++ b/source4/lib/replace/README @@ -51,6 +51,10 @@ pwrite Types: socklen_t +u_int{8,16,32}_t +uint_t +uint{8,16,32,64}_t +int{8,16,32,64}_t Prerequisites: memset (for bzero) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index a2b3a30e10..60652b0b15 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -4,7 +4,7 @@ Import('hostenv defines') if hostenv['configure']: conf = Configure(hostenv) for f in ['memset','syslog','setnetgrent','getnetgrent','endnetgrent', \ - 'mktemp']: + 'mktemp', 'memcpy']: if not conf.CheckFunc(f,'c'): print "Required function `%s' not found" % f exit(1) @@ -26,6 +26,29 @@ if hostenv['configure']: if not conf.CheckType('socklen_t'): defines['socklen_t'] = 'int' + needed_types = { + 'uint_t': 'unsigned int', + 'int8_t': 'signed char', + 'uint8_t': 'unsigned char', + 'u_int8_t': 'unsigned char', + 'int16_t': 'short', + 'uint16_t': 'unsigned short', + 'u_int16_t': 'unsigned short', + 'int32_t': 'long', + 'uint32_t': 'unsigned long', + 'u_int32_t': 'unsigned long', + 'int64_t': 'long long', + 'uint64_t': 'unsigned long long', + } + + type_headers = """ +#include +#include +""" + for t in needed_types: + if not conf.CheckType(t,type_headers): + defines[t] = needed_types[t] + conf.Finish() hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 26a2cae56d..2b8d4ca3d1 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -1,3 +1,16 @@ +AC_CHECK_TYPE(uint_t, unsigned int) +AC_CHECK_TYPE(int8_t, signed char) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(int32_t, long) +AC_CHECK_TYPE(uint32_t, unsigned long) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint64_t, unsigned long long) +AC_CHECK_TYPE(u_int32_t, unsigned long) +AC_CHECK_TYPE(u_int16_t, unsigned short) +AC_CHECK_TYPE(u_int8_t, unsigned char) + AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ AC_TRY_RUN([ #include @@ -99,5 +112,5 @@ AC_CHECK_HEADERS(dlfcn.h) AC_CHECK_FUNCS(dlopen dlsym dlerror dlclose) LIBS="$SAVE_LIBS" -AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent],, - [AC_MSG_ERROR([Need syslog and memset])]) +AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent memcpy],, + [AC_MSG_ERROR([Required function not found])]) diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 28a6392eb3..3ad348517d 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -132,18 +132,6 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); typedef int (*comparison_fn_t)(const void *, const void *); #endif -#ifndef HAVE_U_INT32_T -typedef unsigned u_int32_t; -#endif - -#ifndef HAVE_U_INT16_T -typedef unsigned short u_int16_t; -#endif - -#ifndef HAVE_U_INT8_T -typedef unsigned char u_int8_t; -#endif - #ifdef HAVE_DLFCN_H #include #endif -- cgit From 63b43dd12fb579aaaccedd07aaa630cb1cd7aa88 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 24 Sep 2005 15:42:15 +0000 Subject: r10477: expose transactions outside ldb and change the API once more do not autostart transactions on ldb operations if a transaction is already in place test transactions on winsdb all my tests passes so far tridge please confirm this is ok for you (This used to be commit c2bb2a36bdbe0ec7519697a9a9ba7526a0defac2) --- source4/lib/ldb/common/ldb.c | 104 ++++++++++++++++++++++-------- source4/lib/ldb/common/ldb_modules.c | 12 +++- source4/lib/ldb/common/ldb_msg.c | 2 +- source4/lib/ldb/include/ldb.h | 15 +++++ source4/lib/ldb/include/ldb_errors.h | 2 +- source4/lib/ldb/include/ldb_private.h | 8 ++- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 14 +++- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 14 +++- source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 56 ++++++++++------ source4/lib/ldb/ldb_tdb/ldb_tdb.c | 44 +++++++------ source4/lib/ldb/modules/ldb_map.c | 12 +++- source4/lib/ldb/modules/rdn_name.c | 13 +++- source4/lib/ldb/modules/schema.c | 11 +++- source4/lib/ldb/modules/skel.c | 11 +++- source4/lib/ldb/modules/timestamps.c | 13 +++- source4/lib/ldb/tools/ldbadd.c | 2 +- 16 files changed, 239 insertions(+), 94 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index a00c2481d8..a743b2f584 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -93,17 +93,17 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co return LDB_ERR_OTHER; } - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url); return ret; } - if (ldb_load_modules(ldb, options) != LDB_ERR_SUCCESS) { + if (ldb_load_modules(ldb, options) != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url); return LDB_ERR_OTHER; } - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } static void ldb_reset_err_string(struct ldb_context *ldb) @@ -117,17 +117,45 @@ static void ldb_reset_err_string(struct ldb_context *ldb) /* start a transaction */ -static int ldb_start_trans(struct ldb_context *ldb) +int ldb_transaction_start(struct ldb_context *ldb) { - return ldb->modules->ops->start_transaction(ldb->modules); + ldb->transaction_active++; + + ldb_reset_err_string(ldb); + + return ldb->modules->ops->start_transaction(ldb->modules); } /* - end a transaction + commit a transaction */ -static int ldb_end_trans(struct ldb_context *ldb, int status) +int ldb_transaction_commit(struct ldb_context *ldb) { - return ldb->modules->ops->end_transaction(ldb->modules, status); + if (ldb->transaction_active > 0) { + ldb->transaction_active--; + } else { + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_reset_err_string(ldb); + + return ldb->modules->ops->end_transaction(ldb->modules); +} + +/* + cancel a transaction +*/ +int ldb_transaction_cancel(struct ldb_context *ldb) +{ + if (ldb->transaction_active > 0) { + ldb->transaction_active--; + } else { + return LDB_ERR_OPERATIONS_ERROR; + } + + ldb_reset_err_string(ldb); + + return ldb->modules->ops->del_transaction(ldb->modules); } /* @@ -180,13 +208,18 @@ int ldb_add(struct ldb_context *ldb, ldb_reset_err_string(ldb); status = ldb_msg_sanity_check(message); - if (status != LDB_ERR_SUCCESS) return status; + if (status != LDB_SUCCESS) return status; - status = ldb_start_trans(ldb); - if (status != LDB_ERR_SUCCESS) return status; + if (! ldb->transaction_active) { + status = ldb_transaction_start(ldb); + if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->add_record(ldb->modules, message); - return ldb_end_trans(ldb, status); + status = ldb->modules->ops->add_record(ldb->modules, message); + if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); + return ldb_transaction_commit(ldb); + } + + return ldb->modules->ops->add_record(ldb->modules, message); } /* @@ -200,13 +233,18 @@ int ldb_modify(struct ldb_context *ldb, ldb_reset_err_string(ldb); status = ldb_msg_sanity_check(message); - if (status != LDB_ERR_SUCCESS) return status; + if (status != LDB_SUCCESS) return status; + + if (! ldb->transaction_active) { + status = ldb_transaction_start(ldb); + if (status != LDB_SUCCESS) return status; - status = ldb_start_trans(ldb); - if (status != LDB_ERR_SUCCESS) return status; + status = ldb->modules->ops->modify_record(ldb->modules, message); + if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); + return ldb_transaction_commit(ldb); + } - status = ldb->modules->ops->modify_record(ldb->modules, message); - return ldb_end_trans(ldb, status); + return ldb->modules->ops->modify_record(ldb->modules, message); } @@ -219,11 +257,16 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) ldb_reset_err_string(ldb); - status = ldb_start_trans(ldb); - if (status != LDB_ERR_SUCCESS) return status; + if (! ldb->transaction_active) { + status = ldb_transaction_start(ldb); + if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->delete_record(ldb->modules, dn); - return ldb_end_trans(ldb, status); + status = ldb->modules->ops->delete_record(ldb->modules, dn); + if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); + return ldb_transaction_commit(ldb); + } + + return ldb->modules->ops->delete_record(ldb->modules, dn); } /* @@ -235,13 +278,20 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_reset_err_string(ldb); - status = ldb_start_trans(ldb); - if (status != LDB_ERR_SUCCESS) return status; + if (! ldb->transaction_active) { + status = ldb_transaction_start(ldb); + if (status != LDB_SUCCESS) return status; + + status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); + if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); + return ldb_transaction_commit(ldb); + } - status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); - return ldb_end_trans(ldb, status); + return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); } + + /* return extended error information */ @@ -269,7 +319,7 @@ int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) o->name = name; o->value = value; ldb->opaque = o; - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } /* diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index e1f5b83083..6802cc8955 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -314,12 +314,20 @@ int ldb_next_start_trans(struct ldb_module *module) return module->next->ops->start_transaction(module->next); } -int ldb_next_end_trans(struct ldb_module *module, int status) +int ldb_next_end_trans(struct ldb_module *module) { if (!module->next) { return -1; } - return module->next->ops->end_transaction(module->next, status); + return module->next->ops->end_transaction(module->next); +} + +int ldb_next_del_trans(struct ldb_module *module) +{ + if (!module->next) { + return -1; + } + return module->next->ops->del_transaction(module->next); } void ldb_set_errstring(struct ldb_module *module, char *err_string) diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 1b26d7833b..c2f40f308a 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -527,5 +527,5 @@ int ldb_msg_sanity_check(const struct ldb_message *msg) } } - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 0e794c6209..f371c340cc 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -308,6 +308,21 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct */ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn); +/* + start a transaction +*/ +int ldb_transaction_start(struct ldb_context *ldb); + +/* + commit a transaction +*/ +int ldb_transaction_commit(struct ldb_context *ldb); + +/* + cancel a transaction +*/ +int ldb_transaction_cancel(struct ldb_context *ldb); + /* return extended error information from the last call diff --git a/source4/lib/ldb/include/ldb_errors.h b/source4/lib/ldb/include/ldb_errors.h index 38c42280d0..f59b39f92a 100644 --- a/source4/lib/ldb/include/ldb_errors.h +++ b/source4/lib/ldb/include/ldb_errors.h @@ -40,7 +40,7 @@ * but they are keept here for reference anyway */ -#define LDB_ERR_SUCCESS 0 +#define LDB_SUCCESS 0 #define LDB_ERR_OPERATIONS_ERROR 1 #define LDB_ERR_PROTOCOL_ERROR 2 #define LDB_ERR_TIME_LIMIT_EXCEEDED 3 diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 7eb2bca679..2a9139df40 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -65,7 +65,8 @@ struct ldb_module_ops { int (*delete_record)(struct ldb_module *, const struct ldb_dn *); int (*rename_record)(struct ldb_module *, const struct ldb_dn *, const struct ldb_dn *); int (*start_transaction)(struct ldb_module *); - int (*end_transaction)(struct ldb_module *, int); + int (*end_transaction)(struct ldb_module *); + int (*del_transaction)(struct ldb_module *); }; @@ -105,6 +106,8 @@ struct ldb_context { struct ldb_schema schema; char *err_string; + + int transaction_active; }; /* the modules init function */ @@ -137,7 +140,8 @@ int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message * int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn); int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn); int ldb_next_start_trans(struct ldb_module *module); -int ldb_next_end_trans(struct ldb_module *module, int status); +int ldb_next_end_trans(struct ldb_module *module); +int ldb_next_del_trans(struct ldb_module *module); void ldb_set_errstring(struct ldb_module *module, char *err_string); diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index be51a65c58..ffb812acd0 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -373,11 +373,18 @@ static int ildb_start_trans(struct ldb_module *module) return 0; } -static int ildb_end_trans(struct ldb_module *module, int status) +static int ildb_end_trans(struct ldb_module *module) { /* TODO implement a local transaction mechanism here */ - return status; + return 0; +} + +static int ildb_del_trans(struct ldb_module *module) +{ + /* TODO implement a local locking mechanism here */ + + return 0; } static const struct ldb_module_ops ildb_ops = { @@ -389,7 +396,8 @@ static const struct ldb_module_ops ildb_ops = { .delete_record = ildb_delete, .rename_record = ildb_rename, .start_transaction = ildb_start_trans, - .end_transaction = ildb_end_trans + .end_transaction = ildb_end_trans, + .del_transaction = ildb_del_trans }; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 2035913f2a..1d1dd66e84 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -462,11 +462,18 @@ static int lldb_start_trans(struct ldb_module *module) return 0; } -static int lldb_end_trans(struct ldb_module *module, int status) +static int lldb_end_trans(struct ldb_module *module) { /* TODO implement a local transaction mechanism here */ - return status; + return 0; +} + +static int lldb_del_trans(struct ldb_module *module) +{ + /* TODO implement a local transaction mechanism here */ + + return 0; } static const struct ldb_module_ops lldb_ops = { @@ -478,7 +485,8 @@ static const struct ldb_module_ops lldb_ops = { .delete_record = lldb_delete, .rename_record = lldb_rename, .start_transaction = lldb_start_trans, - .end_transaction = lldb_end_trans + .end_transaction = lldb_end_trans, + .del_transaction = lldb_del_trans }; diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index ac706291ef..052b10f245 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -1065,7 +1065,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg } */ /* Others are implicitly ignored */ - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } /* create linearized and normalized dns */ @@ -1155,7 +1155,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg } talloc_free(local_ctx); - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; failed: talloc_free(local_ctx); @@ -1191,7 +1191,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * } /* Others are implicitly ignored */ - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } eid = lsqlite3_get_eid(module, msg->dn); @@ -1346,7 +1346,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message * } talloc_free(local_ctx); - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; failed: talloc_free(local_ctx); @@ -1365,7 +1365,7 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) /* ignore ltdb specials */ if (ldb_dn_is_special(dn)) { - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } /* create a local ctx */ @@ -1402,7 +1402,7 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn) } talloc_free(local_ctx); - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; failed: talloc_free(local_ctx); @@ -1421,7 +1421,7 @@ static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn /* ignore ltdb specials */ if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) { - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } /* create a local ctx */ @@ -1462,7 +1462,7 @@ static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn /* clean up and exit */ talloc_free(local_ctx); - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; failed: talloc_free(local_ctx); @@ -1491,32 +1491,45 @@ static int lsqlite3_start_trans(struct ldb_module * module) return 0; } -static int lsqlite3_end_trans(struct ldb_module *module, int status) +static int lsqlite3_end_trans(struct ldb_module *module) { int ret; char *errmsg; struct lsqlite3_private *lsqlite3 = module->private_data; - lsqlite3->trans_count--; + if (lsqlite3->trans_count > 0) { + lsqlite3->trans_count--; + } else return -1; if (lsqlite3->trans_count == 0) { - if (status == 0) { - ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - if (errmsg) { - printf("lsqlite3_end_trans: error: %s\n", errmsg); - free(errmsg); - } - return -1; + ret = sqlite3_exec(lsqlite3->sqlite, "COMMIT;", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + if (errmsg) { + printf("lsqlite3_end_trans: error: %s\n", errmsg); + free(errmsg); } - } else { - return lsqlite3_safe_rollback(lsqlite3->sqlite); + return -1; } } return 0; } +static int lsqlite3_del_trans(struct ldb_module *module) +{ + struct lsqlite3_private *lsqlite3 = module->private_data; + + if (lsqlite3->trans_count > 0) { + lsqlite3->trans_count--; + } else return -1; + + if (lsqlite3->trans_count == 0) { + return lsqlite3_safe_rollback(lsqlite3->sqlite); + } + + return -1; +} + /* * Static functions */ @@ -1814,7 +1827,8 @@ static const struct ldb_module_ops lsqlite3_ops = { .delete_record = lsqlite3_delete, .rename_record = lsqlite3_rename, .start_transaction = lsqlite3_start_trans, - .end_transaction = lsqlite3_end_trans + .end_transaction = lsqlite3_end_trans, + .del_transaction = lsqlite3_del_trans }; /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index d8a03c3f55..701ed602ce 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -193,7 +193,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) int ret; ret = ltdb_check_special_dn(module, msg); - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { return ret; } @@ -203,7 +203,7 @@ static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg) ret = ltdb_store(module, msg, TDB_INSERT); - if (ret == LDB_ERR_SUCCESS) { + if (ret == LDB_SUCCESS) { ltdb_modified(module, msg->dn); } @@ -261,13 +261,13 @@ static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn) } ret = ltdb_delete_noindex(module, dn); - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { goto failed; } /* remove any indexed attributes */ ret = ltdb_index_del(module, msg); - if (ret == LDB_ERR_SUCCESS) { + if (ret == LDB_SUCCESS) { ltdb_modified(module, dn); } else ret = LDB_ERR_OTHER; @@ -605,7 +605,7 @@ static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg) ret = ltdb_modify_internal(module, msg); - if (ret == LDB_ERR_SUCCESS) { + if (ret == LDB_SUCCESS) { ltdb_modified(module, msg->dn); } @@ -646,13 +646,13 @@ static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, co } ret = ltdb_add(module, msg); - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { goto failed; } ret = ltdb_delete(module, olddn); error_str = talloc_strdup(module, ldb_errstring(module->ldb)); - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { ltdb_delete(module, newdn); } @@ -675,24 +675,29 @@ static int ltdb_start_trans(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } - return LDB_ERR_SUCCESS; + return LDB_SUCCESS; } -static int ltdb_end_trans(struct ldb_module *module, int status) +static int ltdb_end_trans(struct ldb_module *module) { struct ltdb_private *ltdb = module->private_data; - if (status != LDB_ERR_SUCCESS) { - if (tdb_transaction_cancel(ltdb->tdb) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - } else { - if (tdb_transaction_commit(ltdb->tdb) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } + if (tdb_transaction_commit(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int ltdb_del_trans(struct ldb_module *module) +{ + struct ltdb_private *ltdb = module->private_data; + + if (tdb_transaction_cancel(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; } - return status; + return LDB_SUCCESS; } static const struct ldb_module_ops ltdb_ops = { @@ -704,7 +709,8 @@ static const struct ldb_module_ops ltdb_ops = { .delete_record = ltdb_delete, .rename_record = ltdb_rename, .start_transaction = ltdb_start_trans, - .end_transaction = ltdb_end_trans + .end_transaction = ltdb_end_trans, + .del_transaction = ltdb_del_trans }; diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 69e021b4ee..1133991ac4 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1258,9 +1258,14 @@ static int map_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int map_end_trans(struct ldb_module *module, int status) +static int map_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int map_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); } static const struct ldb_module_ops map_ops = { @@ -1272,7 +1277,8 @@ static const struct ldb_module_ops map_ops = { .delete_record = map_delete, .rename_record = map_rename, .start_transaction = map_start_trans, - .end_transaction = map_end_trans + .end_transaction = map_end_trans, + .del_transaction = map_del_trans }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index c1a0c0852a..3e3fbd544f 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -220,10 +220,16 @@ static int rdn_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int rdn_end_trans(struct ldb_module *module, int status) +static int rdn_end_trans(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int rdn_del_trans(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_del_trans\n"); + return ldb_next_del_trans(module); } static int rdn_name_destructor(void *module_ctx) @@ -242,7 +248,8 @@ static const struct ldb_module_ops rdn_name_ops = { .delete_record = rdn_name_delete_record, .rename_record = rdn_name_rename_record, .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans + .end_transaction = rdn_end_trans, + .del_transaction = rdn_del_trans }; diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 1a2c2b8f97..e882f72bd4 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -520,8 +520,12 @@ static int schema_start_trans(struct ldb_module *module) { return ldb_next_start_trans(module); } -static int schema_end_trans(struct ldb_module *module, int status) { - return ldb_next_end_trans(module, status); +static int schema_end_trans(struct ldb_module *module) { + return ldb_next_end_trans(module); +} + +static int schema_del_trans(struct ldb_module *module) { + return ldb_next_del_trans(module); } static int schema_destructor(void *module_ctx) @@ -540,7 +544,8 @@ static const struct ldb_module_ops schema_ops = { .delete_record = schema_delete_record, .rename_record = schema_rename_record, .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans + .end_transaction = schema_end_trans, + .del_transaction = schema_del_trans }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 701128cd27..5d14a27a7b 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -80,9 +80,15 @@ static int skel_start_trans(struct ldb_module *module) } /* end a transaction */ -static int skel_end_trans(struct ldb_module *module, int status) +static int skel_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +/* delete a transaction */ +static int skel_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); } static int skel_destructor(void *module_ctx) @@ -104,6 +110,7 @@ static const struct ldb_module_ops skel_ops = { .rename_record = skel_rename_record, .start_transaction = skel_start_trans, .end_transaction = skel_end_trans, + .del_transaction = skel_del_trans, }; #ifdef HAVE_DLOPEN_DISABLED diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index dc91937f85..01e5c2c37c 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -217,10 +217,16 @@ static int timestamps_start_trans(struct ldb_module *module) return ldb_next_start_trans(module); } -static int timestamps_end_trans(struct ldb_module *module, int status) +static int timestamps_end_trans(struct ldb_module *module) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); - return ldb_next_end_trans(module, status); + return ldb_next_end_trans(module); +} + +static int timestamps_del_trans(struct ldb_module *module) +{ + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_del_trans\n"); + return ldb_next_del_trans(module); } static int timestamps_destructor(void *module_ctx) @@ -239,7 +245,8 @@ static const struct ldb_module_ops timestamps_ops = { .delete_record = timestamps_delete_record, .rename_record = timestamps_rename_record, .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans + .end_transaction = timestamps_end_trans, + .del_transaction = timestamps_del_trans }; diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index ba58f782f0..058f4dc751 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -75,7 +75,7 @@ static int process_file(struct ldb_context *ldb, FILE *f) ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg); ret = ldb_add(ldb, ldif->msg); - if (ret != LDB_ERR_SUCCESS) { + if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: \"%s\" on DN %s\n", ldb_errstring(ldb), ldb_dn_linearize(ldb, ldif->msg->dn)); failures++; -- cgit From 3d4ea18d4dd9031adc16348c16595d6c216b2d84 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 24 Sep 2005 16:23:41 +0000 Subject: r10478: More work on proto headers; we now generate a couple of smaller ones that are then included by include/proto.h (This used to be commit 703ffbaaaca11f3d8781cfe9e7542fcaa626d991) --- source4/lib/SConscript | 14 ++++++++++---- source4/lib/replace/SConscript | 10 ++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index 328d6233e4..caeeea5712 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -2,7 +2,7 @@ Import('hostenv') # tastes like -*- python -*- SConscript(dirs=['talloc','charset']) -Import('talloc', 'dynconfig', 'charset', 'proto_files') +Import('talloc', 'dynconfig', 'charset') basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'signal.c', 'system.c', 'time.c', 'genrand.c', 'dprintf.c', @@ -11,7 +11,7 @@ basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', 'fsusage.c', 'ms_fnmatch.c', 'select.c', 'mutex.c', 'idtree.c', 'db_wrap.c'] -proto_files += [File(x) for x in basic_files] +proto_files = basic_files basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files]) Export('basic') @@ -29,11 +29,17 @@ hostenv.StaticLibrary('unix_privs',['unix_privs.c']) SConscript(dirs=['ldb']) Import('ldb') -gendb = hostenv.StaticLibrary('gendb', ['gendb.c',ldb]) +gendb_files = ['gendb.c'] +proto_files += gendb_files +gendb = hostenv.StaticLibrary('gendb', [gendb_files,ldb]) Export('gendb') -credentials = hostenv.StaticLibrary('credentials',['credentials.c',basic,gendb]) +credentials_files = ['credentials.c'] +proto_files += credentials_files +credentials = hostenv.StaticLibrary('credentials',[credentials_files,basic,gendb]) Export('credentials') +hostenv.proto_headers += hostenv.CProtoHeader('proto.h', proto_files) + SConscript(dirs=['../param/','replace','tdb','popt','cmdline','registry', 'tls','samba3','socket','socket_wrapper','messaging','com','events', 'appweb']) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index 60652b0b15..48abf2c081 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -19,6 +19,16 @@ if hostenv['configure']: if conf.CheckFunc(f,'c'): defines['HAVE_' + f.upper()] = 1 + # Check for errno declaration + if conf.TryCompile(""" +#include + +int main() { + int i = (int)errno; + return 0; +}""", '.c'): + defines['HAVE_ERRNO_DECL'] = 1 + for h in ['dlfcn.h']: if conf.CheckCHeader('dlfcn.h'): defines['HAVE_' + h.upper().replace('.','_').replace('/','_')] = 1 -- cgit From cb6a4b280fc98994a4d764480d5b10be4f2d085c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Sep 2005 17:49:33 +0000 Subject: r10479: Apply some const (This used to be commit 3e10e8e6618c568f7f55348d829b433e10df472b) --- source4/lib/data_blob.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/data_blob.c b/source4/lib/data_blob.c index 049210e8ee..afd9262274 100644 --- a/source4/lib/data_blob.c +++ b/source4/lib/data_blob.c @@ -185,9 +185,11 @@ DATA_BLOB data_blob_const(const void *p, size_t length) /* append some data to a data blob */ -NTSTATUS data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, void *p, size_t length) +NTSTATUS data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + const void *p, size_t length) { - blob->data = talloc_realloc_size(mem_ctx, blob->data, blob->length + length); + blob->data = talloc_realloc_size(mem_ctx, blob->data, + blob->length + length); NT_STATUS_HAVE_NO_MEMORY(blob->data); memcpy(blob->data + blob->length, p, length); blob->length += length; -- cgit From 6e99b959dedcd8da444fca04832011ffa744b619 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 24 Sep 2005 23:52:30 +0000 Subject: r10483: fixed some uninitialised variables warnings (This used to be commit 315653cf1ecc11c435ee35b20e6cf9c73a67fa68) --- source4/lib/tdb/common/freelist.c | 2 ++ source4/lib/tdb/common/transaction.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/freelist.c b/source4/lib/tdb/common/freelist.c index 9707295ec3..3483751164 100644 --- a/source4/lib/tdb/common/freelist.c +++ b/source4/lib/tdb/common/freelist.c @@ -277,6 +277,8 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st goto fail; bestfit.rec_ptr = 0; + bestfit.last_ptr = 0; + bestfit.rec_len = 0; /* this is a best fit allocation strategy. Originally we used diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index fdcba110c2..cf0f378dce 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -734,7 +734,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, int tdb_transaction_commit(struct tdb_context *tdb) { const struct tdb_methods *methods; - tdb_off_t magic_offset; + tdb_off_t magic_offset = 0; u32 zero = 0; if (tdb->transaction == NULL) { -- cgit From ea801d6520287fed76c3aa3a3d1a729f649baa16 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Sep 2005 00:13:25 +0000 Subject: r10484: try to fix the pread/pwrite declaration problems (This used to be commit 196995ea38414ce5a57031c4cdf61b3ed548196a) --- source4/lib/tdb/common/tdb_private.h | 8 +------- source4/lib/tdb/config.m4 | 2 ++ source4/lib/tdb/configure.in | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index bfd8d04448..d7471537d8 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -25,12 +25,7 @@ */ #ifndef _SAMBA_BUILD_ -#if HAVE_CONFIG_H -#include -#endif - -#define _XOPEN_SOURCE 500 - +#include "config.h" #include #include #ifdef HAVE_STDINT_H @@ -43,7 +38,6 @@ #include #include #include -#include "config.h" #include "tdb.h" #ifndef HAVE_PREAD_DECL diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 52daf7a8ea..58fdc02eb9 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,6 +1,8 @@ AC_CHECK_FUNCS(mmap pread pwrite getpagesize) AC_CHECK_HEADERS(getopt.h) +AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) + AC_HAVE_DECL(pread, [#include ]) AC_HAVE_DECL(pwrite, [#include ]) diff --git a/source4/lib/tdb/configure.in b/source4/lib/tdb/configure.in index 4e5c42c351..ba988b5061 100644 --- a/source4/lib/tdb/configure.in +++ b/source4/lib/tdb/configure.in @@ -4,6 +4,5 @@ AC_INIT(include/tdb.h) AC_CONFIG_HEADER(include/config.h) AC_PROG_CC AC_FUNC_MMAP -AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) sinclude(config.m4) AC_OUTPUT(Makefile tdb.pc) -- cgit From 2fe7c3a34a922b5a590ed3b7ebdd17759b4af6b2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Sep 2005 00:14:45 +0000 Subject: r10485: run autoheader before autoconf (This used to be commit 9456ed3db3b28e4a467e8685f2f1285cf57ce14b) --- source4/lib/ldb/autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/autogen.sh b/source4/lib/ldb/autogen.sh index e118019a39..89053ad9f8 100755 --- a/source4/lib/ldb/autogen.sh +++ b/source4/lib/ldb/autogen.sh @@ -1,7 +1,7 @@ #!/bin/sh -autoconf || exit 1 autoheader || exit 1 +autoconf || exit 1 echo "Now run ./configure and then make." exit 0 -- cgit From 87f71eb8ad90cdf9ed7d3cd79d6211908a7d2d92 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Sep 2005 13:01:26 +0000 Subject: r10489: added the ability for irpc server to defer replies instead of replying immediately. They set m->defer_reply = True; (This used to be commit 3dcd800a5d3340d0f4855f9f08e73896ad8c3d83) --- source4/lib/messaging/irpc.h | 10 +++ source4/lib/messaging/messaging.c | 125 +++++++++++++++++++++++--------------- 2 files changed, 86 insertions(+), 49 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index f015215940..aa06a2de06 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -20,12 +20,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "librpc/gen_ndr/irpc.h" + /* an incoming irpc message */ struct irpc_message { uint32_t from; void *private; + struct irpc_header header; + struct ndr_pull *ndr; + BOOL defer_reply; + struct messaging_context *msg_ctx; + struct irpc_list *irpc; + void *data; }; /* don't allow calls to take too long */ @@ -100,4 +108,6 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *name); void irpc_remove_name(struct messaging_context *msg_ctx, const char *name); +NTSTATUS irpc_send_reply(struct irpc_message *m); + diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 6cabb4c63b..9fcfd58972 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -488,21 +488,20 @@ NTSTATUS irpc_register(struct messaging_context *msg_ctx, /* handle an incoming irpc reply message */ -static void irpc_handler_reply(struct messaging_context *msg_ctx, - struct ndr_pull *ndr, struct irpc_header *header) +static void irpc_handler_reply(struct messaging_context *msg_ctx, struct irpc_message *m) { struct irpc_request *irpc; - irpc = idr_find(msg_ctx->idr, header->callid); + irpc = idr_find(msg_ctx->idr, m->header.callid); if (irpc == NULL) return; /* parse the reply data */ - irpc->status = irpc->table->calls[irpc->callnum].ndr_pull(ndr, NDR_OUT, irpc->r); + irpc->status = irpc->table->calls[irpc->callnum].ndr_pull(m->ndr, NDR_OUT, irpc->r); if (NT_STATUS_IS_OK(irpc->status)) { - irpc->status = header->status; - talloc_steal(irpc->mem_ctx, ndr); + irpc->status = m->header.status; + talloc_steal(irpc->mem_ctx, m); } else { - talloc_steal(irpc, ndr); + talloc_steal(irpc, m); } irpc->done = True; if (irpc->async.fn) { @@ -510,68 +509,93 @@ static void irpc_handler_reply(struct messaging_context *msg_ctx, } } +/* + send a irpc reply +*/ +NTSTATUS irpc_send_reply(struct irpc_message *m) +{ + struct ndr_push *push; + NTSTATUS status; + DATA_BLOB packet; + + /* setup the reply */ + push = ndr_push_init_ctx(m->ndr); + if (push == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + + m->header.flags |= IRPC_FLAG_REPLY; + + /* construct the packet */ + status = ndr_push_irpc_header(push, NDR_SCALARS|NDR_BUFFERS, &m->header); + if (!NT_STATUS_IS_OK(status)) goto failed; + + status = m->irpc->table->calls[m->irpc->callnum].ndr_push(push, NDR_OUT, m->data); + if (!NT_STATUS_IS_OK(status)) goto failed; + + /* send the reply message */ + packet = ndr_push_blob(push); + status = messaging_send(m->msg_ctx, m->from, MSG_IRPC, &packet); + if (!NT_STATUS_IS_OK(status)) goto failed; + +failed: + talloc_free(m); + return status; +} /* handle an incoming irpc request message */ static void irpc_handler_request(struct messaging_context *msg_ctx, - struct ndr_pull *ndr, struct irpc_header *header, - uint32_t src) + struct irpc_message *m) { struct irpc_list *i; void *r; NTSTATUS status; - struct irpc_message m; - struct ndr_push *push; - DATA_BLOB packet; for (i=msg_ctx->irpc; i; i=i->next) { - if (GUID_equal(&i->uuid, &header->uuid) && - i->table->if_version == header->if_version && - i->callnum == header->callnum) { + if (GUID_equal(&i->uuid, &m->header.uuid) && + i->table->if_version == m->header.if_version && + i->callnum == m->header.callnum) { break; } } if (i == NULL) { /* no registered handler for this message */ + talloc_free(m); return; } /* allocate space for the structure */ - r = talloc_zero_size(ndr, i->table->calls[header->callnum].struct_size); + r = talloc_zero_size(m->ndr, i->table->calls[m->header.callnum].struct_size); if (r == NULL) goto failed; /* parse the request data */ - status = i->table->calls[i->callnum].ndr_pull(ndr, NDR_IN, r); + status = i->table->calls[i->callnum].ndr_pull(m->ndr, NDR_IN, r); if (!NT_STATUS_IS_OK(status)) goto failed; /* make the call */ - m.from = src; - m.private = i->private; - header->status = i->fn(&m, r); + m->private = i->private; + m->defer_reply = False; + m->msg_ctx = msg_ctx; + m->irpc = i; + m->data = r; - /* setup the reply */ - push = ndr_push_init_ctx(ndr); - if (push == NULL) goto failed; - - header->flags |= IRPC_FLAG_REPLY; + m->header.status = i->fn(m, r); - /* construct the packet */ - status = ndr_push_irpc_header(push, NDR_SCALARS|NDR_BUFFERS, header); - if (!NT_STATUS_IS_OK(status)) goto failed; - - status = i->table->calls[i->callnum].ndr_push(push, NDR_OUT, r); - if (!NT_STATUS_IS_OK(status)) goto failed; + if (m->defer_reply) { + /* the server function has asked to defer the reply to later */ + talloc_steal(msg_ctx, m); + return; + } - /* send the reply message */ - packet = ndr_push_blob(push); - status = messaging_send(msg_ctx, src, MSG_IRPC, &packet); - if (!NT_STATUS_IS_OK(status)) goto failed; + irpc_send_reply(m); + return; failed: - /* nothing to clean up */ - return; + talloc_free(m); } /* @@ -580,28 +604,31 @@ failed: static void irpc_handler(struct messaging_context *msg_ctx, void *private, uint32_t msg_type, uint32_t src, DATA_BLOB *packet) { - struct irpc_header header; - struct ndr_pull *ndr; + struct irpc_message *m; NTSTATUS status; - ndr = ndr_pull_init_blob(packet, msg_ctx); - if (ndr == NULL) goto failed; + m = talloc(msg_ctx, struct irpc_message); + if (m == NULL) goto failed; + + m->from = src; - ndr->flags |= LIBNDR_FLAG_REF_ALLOC; + m->ndr = ndr_pull_init_blob(packet, m); + if (m->ndr == NULL) goto failed; - status = ndr_pull_irpc_header(ndr, NDR_BUFFERS|NDR_SCALARS, &header); + m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC; + + status = ndr_pull_irpc_header(m->ndr, NDR_BUFFERS|NDR_SCALARS, &m->header); if (!NT_STATUS_IS_OK(status)) goto failed; - if (header.flags & IRPC_FLAG_REPLY) { - irpc_handler_reply(msg_ctx, ndr, &header); + if (m->header.flags & IRPC_FLAG_REPLY) { + irpc_handler_reply(msg_ctx, m); } else { - irpc_handler_request(msg_ctx, ndr, &header, src); - talloc_free(ndr); + irpc_handler_request(msg_ctx, m); } return; failed: - talloc_free(ndr); + talloc_free(m); } @@ -761,7 +788,7 @@ NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name) } rec = tdb_fetch_bystring(t->tdb, name); count = rec.dsize / sizeof(uint32_t); - rec.dptr = (char *)realloc_p(rec.dptr, uint32_t, count+1); + rec.dptr = (unsigned char *)realloc_p(rec.dptr, uint32_t, count+1); rec.dsize += sizeof(uint32_t); if (rec.dptr == NULL) { tdb_unlock_bystring(t->tdb, name); -- cgit From 06085e7bc09e46c74fbe050633203fab619d501c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 25 Sep 2005 13:17:03 +0000 Subject: r10490: - allow deferred irpc replies to set the status - add an example of deferred reply for echodata in LOCAL-IRPC (This used to be commit 858a757a6d0a614b8f13bfb6217034e8a8b69554) --- source4/lib/messaging/irpc.h | 3 ++- source4/lib/messaging/messaging.c | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/messaging/irpc.h b/source4/lib/messaging/irpc.h index aa06a2de06..e83e7dce65 100644 --- a/source4/lib/messaging/irpc.h +++ b/source4/lib/messaging/irpc.h @@ -34,6 +34,7 @@ struct irpc_message { struct messaging_context *msg_ctx; struct irpc_list *irpc; void *data; + struct event_context *ev; }; /* don't allow calls to take too long */ @@ -108,6 +109,6 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx, NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); uint32_t *irpc_servers_byname(struct messaging_context *msg_ctx, const char *name); void irpc_remove_name(struct messaging_context *msg_ctx, const char *name); -NTSTATUS irpc_send_reply(struct irpc_message *m); +NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status); diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 9fcfd58972..c3d3ba7899 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -512,12 +512,13 @@ static void irpc_handler_reply(struct messaging_context *msg_ctx, struct irpc_me /* send a irpc reply */ -NTSTATUS irpc_send_reply(struct irpc_message *m) +NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status) { struct ndr_push *push; - NTSTATUS status; DATA_BLOB packet; + m->header.status = status; + /* setup the reply */ push = ndr_push_init_ctx(m->ndr); if (push == NULL) { @@ -582,6 +583,7 @@ static void irpc_handler_request(struct messaging_context *msg_ctx, m->msg_ctx = msg_ctx; m->irpc = i; m->data = r; + m->ev = msg_ctx->event.ev; m->header.status = i->fn(m, r); @@ -591,7 +593,7 @@ static void irpc_handler_request(struct messaging_context *msg_ctx, return; } - irpc_send_reply(m); + irpc_send_reply(m, m->header.status); return; failed: -- cgit From be27946d84dbf9155d9505d00abe91089a9b8125 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Sep 2005 01:12:12 +0000 Subject: r10492: work around a bug in solaris which cases lock upgrades to fail with EDEADLK even when progress can be made. This is not a good solution, but I can't find anything better. (This used to be commit 980dd17f7d0a622cd772afc9ba15e50007ad9c6e) --- source4/lib/tdb/common/lock.c | 26 ++++++++++++++++++++++++++ source4/lib/tdb/common/tdb_private.h | 1 + source4/lib/tdb/common/transaction.c | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 703cfe9dc5..04135a2274 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -81,6 +81,32 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, } +/* + upgrade a read lock to a write lock. This needs to be handled in a + special way as some OSes (such as solaris) have too conservative + deadlock detection and claim a deadlock when progress can be + made. For those OSes we may loop for a while. +*/ +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) +{ + int count = 1000; + while (count--) { + struct timeval tv; + if (tdb_brlock_len(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + return -1; +} + + /* a byte range locking function - return 0 on success this functions locks/unlocks 1 byte at the specified offset. diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index d7471537d8..ce105a2a56 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -216,6 +216,7 @@ void tdb_mmap(struct tdb_context *tdb); int tdb_lock(struct tdb_context *tdb, int list, int ltype); int tdb_unlock(struct tdb_context *tdb, int list, int ltype); int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe); +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index cf0f378dce..9d37046116 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -772,7 +772,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) } /* upgrade the main transaction lock region to a write lock */ - if (tdb_brlock_len(tdb, FREELIST_TOP, F_WRLCK, F_SETLKW, 0, 0) == -1) { + if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { TDB_LOG((tdb, 0, "tdb_transaction_start: failed to upgrade hash locks\n")); tdb->ecode = TDB_ERR_LOCK; tdb_transaction_cancel(tdb); -- cgit From 66ad3ab652c6a7c48b32327698e0f2f946f7a7df Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Sep 2005 01:28:49 +0000 Subject: r10493: we need sys/select.h to enable select() in the solaris workaround (This used to be commit 144cc3da5eadf0dcb28ef722feeed813c033e08a) --- source4/lib/tdb/common/tdb_private.h | 3 +++ source4/lib/tdb/config.m4 | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index ce105a2a56..cd0505217c 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -38,6 +38,9 @@ #include #include #include +#ifdef HAVE_SYS_SELECT_H +#include +#endif #include "tdb.h" #ifndef HAVE_PREAD_DECL diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 58fdc02eb9..e37662fe52 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,5 +1,5 @@ AC_CHECK_FUNCS(mmap pread pwrite getpagesize) -AC_CHECK_HEADERS(getopt.h) +AC_CHECK_HEADERS(getopt.h sys/select.h) AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) -- cgit From 10de5cc72dcaf0607f080ee7f744f65fb680f3db Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Sep 2005 01:37:46 +0000 Subject: r10494: - don't generate a tdb log message for any type of failed lock probe - if the lock upgrade loop ever fails then log a warning (This used to be commit 1b03c4e6c7e89452a835ef5ff39c07f58b715a22) --- source4/lib/tdb/common/lock.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 04135a2274..750d34ea31 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -65,11 +65,7 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, /* Generic lock error. errno set by fcntl. * EAGAIN is an expected return from non-blocking * locks. */ - if (errno != EAGAIN) { - TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d: %s\n", - tdb->fd, offset, rw_type, lck_type, len, - strerror(errno))); - } else if (!probe && lck_type != F_SETLK) { + if (!probe && lck_type != F_SETLK) { /* Ensure error code is set for log fun to examine. */ tdb->ecode = TDB_ERR_LOCK; TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", @@ -103,6 +99,7 @@ int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) tv.tv_usec = 1; select(0, NULL, NULL, NULL, &tv); } + TDB_LOG((tdb, 5,"tdb_brlock_upgrade failed at offset %d\n", offset)); return -1; } -- cgit From f2e9db908a88b94fcf642b96382072d0de9009d1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Sep 2005 01:46:02 +0000 Subject: r10495: older redhat boxes need sys/time.h for select() (This used to be commit a11762e7bc139b0280e457e682722d955b81d8e5) --- source4/lib/tdb/common/tdb_private.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index cd0505217c..f3338babfb 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -41,6 +41,9 @@ #ifdef HAVE_SYS_SELECT_H #include #endif +#ifdef HAVE_SYS_TIME_H +#include +#endif #include "tdb.h" #ifndef HAVE_PREAD_DECL -- cgit From 3545e513f53340c504e55e5f496ad3067989ab09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 Sep 2005 02:03:06 +0000 Subject: r10496: - added configure test for sys/time.h - print length of failed locks (This used to be commit 11739ad31d7b3e1cf94ebf395608647e341257c4) --- source4/lib/tdb/common/lock.c | 4 ++-- source4/lib/tdb/config.m4 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/lock.c b/source4/lib/tdb/common/lock.c index 750d34ea31..976cf2cfa0 100644 --- a/source4/lib/tdb/common/lock.c +++ b/source4/lib/tdb/common/lock.c @@ -68,8 +68,8 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, if (!probe && lck_type != F_SETLK) { /* Ensure error code is set for log fun to examine. */ tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", - tdb->fd, offset, rw_type, lck_type)); + TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", + tdb->fd, offset, rw_type, lck_type, len)); } return TDB_ERRCODE(TDB_ERR_LOCK, -1); } diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index e37662fe52..23784f3723 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,5 +1,5 @@ AC_CHECK_FUNCS(mmap pread pwrite getpagesize) -AC_CHECK_HEADERS(getopt.h sys/select.h) +AC_CHECK_HEADERS(getopt.h sys/select.h sys/time.h) AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) -- cgit From 0d46be147a1e755bdd6f21a5ddc83b5c39585529 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 26 Sep 2005 07:36:26 +0000 Subject: r10500: More progress to getting ldb tools building. Create a list of ldb modules to link in. There's still a whole lot of random other junk (dcerpc, gensec, ndr stuff, lp_foo - what a mess). (This used to be commit b78cf1270bd7eda1aa84d238136a83e64ff3c088) --- source4/lib/ldb/SConscript | 76 +++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 28 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index ef89132ab2..6dfb53f789 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -1,43 +1,63 @@ -Import('hostenv', 'talloc', 'defines') +# tastes like -*- python -*- -hostenv.StaticLibrary('modules/timestamps.c') -hostenv.StaticLibrary('modules/rdn_name.c') -hostenv.StaticLibrary('modules/schema.c') -hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c') -hostenv.StaticLibrary('modules/ldb_map.c') +Import('hostenv', 'talloc', 'defines', 'basic', 'cli_ldap') + +# Configure stuff if hostenv['configure']: - conf = Configure(hostenv) - if conf.CheckLibWithHeader("sqlite3","sqlite3.h",'c',"sqlite3_open()"): - defines['HAVE_SQLITE3'] = 1 - conf.CheckLibWithHeader("popt","popt.h",'c',"poptGetArgs(NULL);") - conf.Finish() + conf = Configure(hostenv) + if conf.CheckLibWithHeader('sqlite3','sqlite3.h','c','sqlite3_open()'): + defines['HAVE_SQLITE3'] = 1 + conf.CheckLibWithHeader('popt','popt.h','c','poptGetArgs(NULL);') + conf.Finish() if defines.has_key('HAVE_SQLITE3'): - hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') + hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') + +# LDB modules + +modules = [] -ldb_tdb_source = ['ldb_tdb/ldb_tdb.c', 'ldb_tdb/ldb_search.c', - 'ldb_tdb/ldb_pack.c', 'ldb_tdb/ldb_index.c', - 'ldb_tdb/ldb_cache.c', 'ldb_tdb/ldb_tdb_wrap.c'] +modules.append(hostenv.StaticLibrary('modules/timestamps.c')) +modules.append(hostenv.StaticLibrary('modules/rdn_name.c')) +modules.append(hostenv.StaticLibrary('modules/schema.c')) +modules.append(hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c')) +#modules.append(hostenv.StaticLibrary('modules/ldb_map.c')) -hostenv.StaticLibrary('ldb_tdb', ldb_tdb_source) +Import('dsdb_ldb_modules') +modules += dsdb_ldb_modules -ldb_source = ['common/ldb.c','common/ldb_ldif.c','common/ldb_parse.c', - 'common/ldb_parse.c','common/ldb_msg.c','common/ldb_utf8.c', - 'common/ldb_debug.c','common/ldb_modules.c','common/ldb_match.c', - 'common/attrib_handlers.c','common/ldb_dn.c'] +modules.append(hostenv.StaticLibrary( + 'ldb_tdb', + ['ldb_tdb/ldb_tdb.c', 'ldb_tdb/ldb_search.c', 'ldb_tdb/ldb_pack.c', + 'ldb_tdb/ldb_index.c', 'ldb_tdb/ldb_cache.c', 'ldb_tdb/ldb_tdb_wrap.c'])) + +#modules.append(hostenv.StaticLibrary('ldb_ildap', ['ldb_ildap/ldb_ildap.c'])) -ldb = hostenv.StaticLibrary('ldb', ldb_source + talloc) +# Export the ldb base plus modules for other parts of the build system +# to enjoy. + +ldb = hostenv.StaticLibrary( + 'ldb', + ['common/ldb.c', 'common/ldb_ldif.c', 'common/ldb_parse.c', + 'common/ldb_parse.c', 'common/ldb_msg.c', 'common/ldb_utf8.c', + 'common/ldb_debug.c', 'common/ldb_modules.c', 'common/ldb_match.c', + 'common/ldb_attributes.c', 'common/attrib_handlers.c', 'common/ldb_dn.c']) Export('ldb') hostenv.StaticLibrary('samba/ldif_handlers.c') ldb_cmdline = hostenv.StaticLibrary('ldb_cmdline', 'tools/cmdline.c') -hostenv.Program('ldbadd',['tools/ldbadd.c',ldb,talloc,ldb_cmdline]) -hostenv.Program('ldbdel',['tools/ldbdel.c',ldb,ldb_cmdline]) -hostenv.Program('ldbmodify',['tools/ldbmodify.c',ldb,ldb_cmdline]) -hostenv.Program('ldbsearch',['tools/ldbsearch.c',ldb,ldb_cmdline]) -hostenv.Program('ldbrename',['tools/ldbrename.c',ldb,ldb_cmdline]) -hostenv.Program('ldbtest',['tools/ldbtest.c',ldb,ldb_cmdline]) -hostenv.Program('oLschema2ldif',['tools/oLschema2ldif.c',ldb]) +# Tools + +ldbenv = hostenv.Copy() +ldbenv.Append(LIBS = ['popt']) + +ldbenv.Program('ldbadd',['tools/ldbadd.c',ldb,modules,ldb_cmdline,cli_ldap,talloc,basic]) +ldbenv.Program('ldbdel',['tools/ldbdel.c',ldb,ldb_cmdline,basic]) +ldbenv.Program('ldbmodify',['tools/ldbmodify.c',ldb,ldb_cmdline]) +ldbenv.Program('ldbsearch',['tools/ldbsearch.c',ldb,ldb_cmdline]) +ldbenv.Program('ldbrename',['tools/ldbrename.c',ldb,ldb_cmdline]) +ldbenv.Program('ldbtest',['tools/ldbtest.c',ldb,ldb_cmdline]) +ldbenv.Program('oLschema2ldif',['tools/oLschema2ldif.c',ldb]) -- cgit From e337caeed1459f876449611ae1684616d0ea8f55 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 15:15:50 +0000 Subject: r10509: Some more sconscript fixes. Now getting to link stage for smbclient (This used to be commit 6df956edbab7ad5e72b2f20e74ab0f0d62528932) --- source4/lib/SConscript | 3 +- source4/lib/charset/SConscript | 69 ++++++++++++------------------------ source4/lib/cmdline/readline.c | 19 ---------- source4/lib/netif/SConscript | 22 ++++++++++++ source4/lib/replace/SConscript | 11 ++++-- source4/lib/replace/win32/SConscript | 22 ++++++++++++ source4/lib/socket/SConscript | 8 ++--- 7 files changed, 79 insertions(+), 75 deletions(-) create mode 100644 source4/lib/netif/SConscript create mode 100644 source4/lib/replace/win32/SConscript (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index caeeea5712..c41b6ea067 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -16,7 +16,6 @@ proto_files = basic_files basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files]) Export('basic') -hostenv.StaticLibrary('netif', ['netif/interface.c', 'netif/netif.c']) hostenv.StaticLibrary('tdr', ['tdr/tdr.c']) hostenv.StaticLibrary('crypto', ['crypto/crc32.c','crypto/md5.c','crypto/hmacmd5.c', @@ -41,5 +40,5 @@ Export('credentials') hostenv.proto_headers += hostenv.CProtoHeader('proto.h', proto_files) -SConscript(dirs=['../param/','replace','tdb','popt','cmdline','registry', 'tls','samba3','socket','socket_wrapper','messaging','com','events', 'appweb']) +SConscript(dirs=['../param/','replace','tdb','popt','cmdline','registry', 'tls','samba3','socket','socket_wrapper','messaging','com','events', 'appweb', 'netif']) diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index b3305579e1..5ef640d2dc 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -6,62 +6,39 @@ Import('hostenv') def _CheckIconvPath(context,path): # Some systems have iconv in libc, some have it in libiconv (OSF/1 and # those with the standalone portable libiconv installed). - context.Message("checking for iconv in " + path + " ... ") + if path: + context.Message("checking for iconv in " + path + " ... ") + context.env.Append(LIBPATH=path) + else: + context.Message("checking for iconv in default path ... ") + + for l in [None,'giconv','iconv']: + for h in ['giconv.h','iconv.h']: + if l: + context.env['LIBS'] = [l] + if context.TryLink(""" +#include +#include <%s> - main = """ int main() { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); return 0; -}""" - - have_giconv_iconv = context.TryLink(""" -#include -#include -""" + main, '.c') - if have_giconv_iconv: - context.Result(1) - return ("giconv.h", "") - - have_iconv_iconv = context.TryLink(""" -#include -#include -""" + main, '.c') - - if have_iconv_iconv: - context.Result(1) - return ("iconv.h", "") - - #FIXME: Add -lgiconv - have_giconv_lib_iconv = context.TryLink(""" -#include -#include -""" + main, '.c') - if have_giconv_lib_iconv: - context.Result(1) - return ("giconv.h", "-lgiconv") - - #FIXME: Add -liconv - have_iconv_lib_iconv = context.TryLink(""" -#include -#include -"""+main,'.c') - - if have_iconv_lib_iconv: - context.Result(1) - return ("iconv.h", "-liconv") - - return None +}""" % h, '.c'): + context.Result(1) + return True + + context.Result(0) + return False def CheckIconv(context): - context.Message("checking for iconv ... ") - - look_dirs = ['/usr','/usr/local','/sw'] + look_dirs = [None, '/usr','/usr/local','/sw'] for p in look_dirs: - _CheckIconvPath(context,p) #FIXME: Handle return value + if _CheckIconvPath(context,p): + break if context.TryRun(""" #include @@ -71,10 +48,8 @@ main() { return 0; } """, '.c'): - context.Result(1) return (1,[]) - context.Result(0) return (0,[]) if hostenv['configure']: diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 42810c8697..7928b8db2e 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -140,23 +140,4 @@ void smb_readline_ca_char(char c) } -/**************************************************************************** -history -****************************************************************************/ -int cmd_history(const char **cmd_ptr) -{ -#if defined(HAVE_LIBREADLINE) - HIST_ENTRY **hlist; - int i; - - hlist = history_list(); - - for (i = 0; hlist && hlist[i]; i++) { - DEBUG(0, ("%d: %s\n", i, hlist[i]->line)); - } -#else - DEBUG(0,("no history without readline support\n")); -#endif - return 0; -} diff --git a/source4/lib/netif/SConscript b/source4/lib/netif/SConscript new file mode 100644 index 0000000000..3e36fc55fe --- /dev/null +++ b/source4/lib/netif/SConscript @@ -0,0 +1,22 @@ +Import('hostenv defines') + +if hostenv['configure']: + conf = Configure(hostenv) + + for h in ['arpa/inet.h','net/if.h','netdb.h','netinet/in.h','netinet/ip.h','netinet/tcp.h','netinet/in_systm.h','netinet/in_ip.h']: + if conf.CheckCHeader(h): + defines['HAVE_' + h.upper().replace('.','_').replace('/','_')] = 1 + + for d in ['HAVE_IFACE_IFCONF','HAVE_IFACE_AIX','HAVE_IFACE_IFREQ']: + if conf.TryRun(""" +#define %s 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "netif.c" +""" % d, '.c'): + defines[d] = 1 + break + + conf.Finish() + +hostenv.StaticLibrary('netif', ['interface.c', 'netif.c']) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index 48abf2c081..47bfa481f2 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -1,6 +1,8 @@ #!/usr/bin/env python Import('hostenv defines') +rep_files = ['replace.c', 'snprintf.c','dlfcn.c'] + if hostenv['configure']: conf = Configure(hostenv) for f in ['memset','syslog','setnetgrent','getnetgrent','endnetgrent', \ @@ -33,7 +35,7 @@ int main() { if conf.CheckCHeader('dlfcn.h'): defines['HAVE_' + h.upper().replace('.','_').replace('/','_')] = 1 - if not conf.CheckType('socklen_t'): + if not conf.CheckType('socklen_t', "#include "): defines['socklen_t'] = 'int' needed_types = { @@ -59,7 +61,10 @@ int main() { if not conf.CheckType(t,type_headers): defines[t] = needed_types[t] + if not conf.TryRun(open("../../build/tests/os2_delete.c").read(), '.c'): + rep_files += ['repdir/repdir.c'] + conf.Finish() -hostenv.StaticLibrary('repdir', ['repdir/repdir.c']) -hostenv.StaticLibrary('replace', ['replace.c', 'snprintf.c','dlfcn.c']) +hostenv.StaticLibrary('replace', rep_files) +SConscript(dirs=['win32']) diff --git a/source4/lib/replace/win32/SConscript b/source4/lib/replace/win32/SConscript new file mode 100644 index 0000000000..a23fb6a878 --- /dev/null +++ b/source4/lib/replace/win32/SConscript @@ -0,0 +1,22 @@ +Import('hostenv defines') + +if hostenv['configure']: + conf = Configure(hostenv) + for h in ['direct.h','windows.h','winsock2.h','ws2tcpip.h']: + if conf.CheckCHeader(h): + defines['HAVE_' + h.upper().replace('.','_')] = 1 + conf.TryCompile(""" +#include +#ifdef HAVE_DIRECT_H +#include +#endif + +int main() +{ + mkdir("foo",0777); + return 0; +} +""", '.c') + + conf.Finish() + diff --git a/source4/lib/socket/SConscript b/source4/lib/socket/SConscript index c4e791467a..26c8bf444c 100644 --- a/source4/lib/socket/SConscript +++ b/source4/lib/socket/SConscript @@ -1,11 +1,11 @@ #!/usr/bin/env python -Import('hostenv') +Import('hostenv defines') if hostenv['configure']: conf = hostenv.Configure() - conf.CheckCHeader('sys/socket.h') - conf.CheckCHeader('sys/sockio.h') - conf.CheckCHeader('sys/un.h') + for h in ['sys/socket.h','sys/sockio.h','sys/un.h']: + if conf.CheckCHeader(h): + defines['HAVE_' + h.upper().replace('/','_').replace('.','_')] = 1 #HAVE_SOCK_SIN_LEN conf.TryCompile(""" #include -- cgit From f801ad359290c51d3216c755fb2a8344babb484f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 15:59:43 +0000 Subject: r10510: Decrease the amount of data included by includes.h a bit (This used to be commit 03647e1321cf6c9bd6ced3945265f635e9468973) --- source4/lib/SConscript | 2 +- source4/lib/cmdline/popt_common.c | 1 + source4/lib/cmdline/readline.c | 26 +------------------------- source4/lib/credentials.c | 1 + source4/lib/replace/SConscript | 1 + source4/lib/replace/config.m4 | 1 + source4/lib/replace/win32/replace.h | 12 ++++++++++++ source4/lib/samba3/secrets.c | 1 + 8 files changed, 19 insertions(+), 26 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index c41b6ea067..a184eecd10 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -13,7 +13,7 @@ basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', proto_files = basic_files -basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files]) +basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files,charset]) Export('basic') hostenv.StaticLibrary('tdr', ['tdr/tdr.c']) diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 43ea203b78..76c8a537e3 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -25,6 +25,7 @@ #include "system/filesys.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" +#include "credentials.h" /* Handle command line options: * -d,--debuglevel diff --git a/source4/lib/cmdline/readline.c b/source4/lib/cmdline/readline.c index 7928b8db2e..52f45eb759 100644 --- a/source4/lib/cmdline/readline.c +++ b/source4/lib/cmdline/readline.c @@ -23,31 +23,7 @@ #include "pstring.h" #include - -#ifdef HAVE_LIBREADLINE -# ifdef HAVE_READLINE_READLINE_H -# include -# ifdef HAVE_READLINE_HISTORY_H -# include -# endif -# else -# ifdef HAVE_READLINE_H -# include -# ifdef HAVE_HISTORY_H -# include -# endif -# else -# undef HAVE_LIBREADLINE -# endif -# endif -#endif - -#ifdef HAVE_NEW_LIBREADLINE -# define RL_COMPLETION_CAST (rl_completion_func_t *) -#else -/* This type is missing from libreadline<4.0 (approximately) */ -# define RL_COMPLETION_CAST -#endif /* HAVE_NEW_LIBREADLINE */ +#include "system/readline.h" /**************************************************************************** Display the prompt and wait for input. Call callback() regularly diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 045047d358..166d60b00d 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -27,6 +27,7 @@ #include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */ #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" +#include "include/credentials.h" /** diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index 47bfa481f2..f45d0e7d5a 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -51,6 +51,7 @@ int main() { 'u_int32_t': 'unsigned long', 'int64_t': 'long long', 'uint64_t': 'unsigned long long', + 'ssize_t': 'int' } type_headers = """ diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 2b8d4ca3d1..0b95079b24 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -10,6 +10,7 @@ AC_CHECK_TYPE(uint64_t, unsigned long long) AC_CHECK_TYPE(u_int32_t, unsigned long) AC_CHECK_TYPE(u_int16_t, unsigned short) AC_CHECK_TYPE(u_int8_t, unsigned char) +AC_CHECK_TYPE(ssize_t, int) AC_CACHE_CHECK([for broken inet_ntoa],samba_cv_REPLACE_INET_NTOA,[ AC_TRY_RUN([ diff --git a/source4/lib/replace/win32/replace.h b/source4/lib/replace/win32/replace.h index 94fa140681..185d448d95 100644 --- a/source4/lib/replace/win32/replace.h +++ b/source4/lib/replace/win32/replace.h @@ -1,6 +1,18 @@ #ifndef _WIN32_REPLACE_H #define _WIN32_REPLACE_H +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + /* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */ #define EAFNOSUPPORT WSAEAFNOSUPPORT diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 0f3cc0c581..0981a7a6ec 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -30,6 +30,7 @@ #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" #include "lib/tdb/include/tdbutil.h" +#include "credentials.h" /** * Unpack SID into a pointer -- cgit From 49839f356f493d0de1b719c8c3bfdee4713c0728 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 16:57:08 +0000 Subject: r10513: Reduce some use of pstring. The main reason some parts of the code still use pstring is next_token() now. (This used to be commit a5b88bcd420eb7ae42283293541519e142be36e3) --- source4/lib/cmdline/popt_common.h | 1 - source4/lib/pidfile.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index 28676de56b..785a50ae70 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -22,7 +22,6 @@ #define _POPT_COMMON_H #include "popt.h" -#include "pstring.h" /* Common popt structures */ extern struct poptOption popt_common_samba[]; diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index b1866ee6af..54d2c81d2e 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -21,7 +21,6 @@ */ #include "includes.h" -#include "pstring.h" #include "system/filesys.h" #ifndef O_NONBLOCK @@ -35,11 +34,13 @@ pid_t pidfile_pid(const char *name) int fd; char pidstr[20]; uint_t ret; - pstring pidFile; + char *pidFile; - slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); + asprintf(&pidFile, "%s/%s.pid", lp_piddir(), name); fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644); + SAFE_FREE(pidFile); + if (fd == -1) { return 0; } @@ -75,10 +76,10 @@ void pidfile_create(const char *name) { int fd; char buf[20]; - pstring pidFile; + char *pidFile; pid_t pid; - slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); + asprintf(&pidFile, "%s/%s.pid", lp_piddir(), name); pid = pidfile_pid(name); if (pid != 0) { @@ -107,5 +108,7 @@ void pidfile_create(const char *name) pidFile, strerror(errno))); exit(1); } + /* Leave pid file open & locked for the duration... */ + SAFE_FREE(pidFile); } -- cgit From 85abc86b214518b9b4d0728f3f0174bee0154c3c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 17:42:12 +0000 Subject: r10514: Add str_list_make_shell() and str_list_join_shell() (This used to be commit 8b86a5da73d38764deb8c1f639322b2911736f97) --- source4/lib/util_strlist.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 8efa1f92d2..7aff027d66 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 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 @@ -70,6 +71,63 @@ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char * return ret; } +/* build a null terminated list of strings from an argv-like input string + Entries are seperated by spaces and can be enclosed by quotes. + Does NOT support escaping + */ +const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string) +{ + int num_elements = 0; + const char **ret = NULL; + + ret = talloc_array(mem_ctx, const char *, 1); + if (ret == NULL) { + return NULL; + } + + while (string && *string) { + size_t len = strcspn(string, " "); + char *element; + const char **ret2; + + if (len == 0) { + string += strspn(string, " "); + continue; + } + + if (*string == '\"') { + string++; + len = strcspn(string, "\""); + element = talloc_strndup(ret, string, len); + string += len + 1; + } else { + element = talloc_strndup(ret, string, len); + string += len; + } + + if (element == NULL) { + talloc_free(ret); + return NULL; + } + + ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = ret2; + + ret[num_elements] = element; + + num_elements++; + } + + ret[num_elements] = NULL; + + return ret; + +} + /* join a list back to one string */ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) { @@ -88,6 +146,30 @@ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) return ret; } +/* join a list back to one (shell-like) string; entries + * seperated by spaces, using quotes where necessary */ +char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + if (strchr(list[0], ' ') || strlen(list[0]) == 0) + ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]); + else + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + if (strchr(list[i], ' ') || strlen(list[i]) == 0) + ret = talloc_asprintf_append(ret, " \"%s\"", list[i]); + else + ret = talloc_asprintf_append(ret, " %s", list[i]); + } + + return ret; +} /* return the number of elements in a string list -- cgit From 01319b8462aa8ebf3b5be4598e7317aa08f40350 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 18:16:23 +0000 Subject: r10516: Add seperator argument to str_list_{make,join}_shell() (This used to be commit 0a5c9197f28e5451406d422e0a8ff84c1b20faae) --- source4/lib/util_strlist.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_strlist.c b/source4/lib/util_strlist.c index 7aff027d66..ec6c58162f 100644 --- a/source4/lib/util_strlist.c +++ b/source4/lib/util_strlist.c @@ -75,7 +75,7 @@ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char * Entries are seperated by spaces and can be enclosed by quotes. Does NOT support escaping */ -const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string) +const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep) { int num_elements = 0; const char **ret = NULL; @@ -85,13 +85,16 @@ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string) return NULL; } + if (sep == NULL) + sep = " \t\n\r"; + while (string && *string) { - size_t len = strcspn(string, " "); + size_t len = strcspn(string, sep); char *element; const char **ret2; if (len == 0) { - string += strspn(string, " "); + string += strspn(string, sep); continue; } @@ -148,7 +151,7 @@ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) /* join a list back to one (shell-like) string; entries * seperated by spaces, using quotes where necessary */ -char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list) +char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) { char *ret = NULL; int i; @@ -163,9 +166,9 @@ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list) for (i = 1; list[i]; i++) { if (strchr(list[i], ' ') || strlen(list[i]) == 0) - ret = talloc_asprintf_append(ret, " \"%s\"", list[i]); + ret = talloc_asprintf_append(ret, "%c\"%s\"", sep, list[i]); else - ret = talloc_asprintf_append(ret, " %s", list[i]); + ret = talloc_asprintf_append(ret, "%c%s", sep, list[i]); } return ret; -- cgit From 7f7a2d133dc2191e0a08f6f99f3bda914a29ac44 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 26 Sep 2005 18:16:38 +0000 Subject: r10517: Get rid of use of next_token() in lib/samba3/ (This used to be commit 811a6e28cca1ba09a95a89c344f4640b3d1dd74e) --- source4/lib/samba3/group.c | 14 +++++++------- source4/lib/samba3/winsdb.c | 44 ++++++++++++-------------------------------- 2 files changed, 19 insertions(+), 39 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index 220f206e99..78a04b3ff8 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -24,7 +24,6 @@ #include "lib/samba3/samba3.h" #include "lib/tdb/include/tdbutil.h" #include "system/filesys.h" -#include "pstring.h" #define DATABASE_VERSION_V1 1 /* native byte format. */ #define DATABASE_VERSION_V2 2 /* le format. */ @@ -108,8 +107,8 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g } else if (strncmp(kbuf.dptr, MEMBEROF_PREFIX, strlen(MEMBEROF_PREFIX)) == 0) { struct samba3_alias alias; - pstring alias_string; - const char *p; + char **member_strlist; + int i; dbuf = tdb_fetch(tdb, kbuf); if (!dbuf.dptr) @@ -119,15 +118,16 @@ NTSTATUS samba3_read_grouptdb(const char *file, TALLOC_CTX *ctx, struct samba3_g alias.member_count = 0; alias.members = NULL; - p = dbuf.dptr; - while (next_token(&p, alias_string, " ", sizeof(alias_string))) { + member_strlist = str_list_make_shell(ctx, dbuf.dptr, " "); + for (i = 0; member_strlist[i]; i++) { alias.members = talloc_realloc(ctx, alias.members, struct dom_sid *, alias.member_count+1); - alias.members[alias.member_count] = dom_sid_parse_talloc(ctx, alias_string); + alias.members[alias.member_count] = dom_sid_parse_talloc(ctx, member_strlist[i]); alias.member_count++; - } + talloc_free(member_strlist); + db->aliases = talloc_realloc(ctx, db->aliases, struct samba3_alias, db->alias_count+1); db->aliases[db->alias_count] = alias; db->alias_count++; diff --git a/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c index f543ebd3f0..cd052ca437 100644 --- a/source4/lib/samba3/winsdb.c +++ b/source4/lib/samba3/winsdb.c @@ -23,7 +23,6 @@ #include "includes.h" #include "system/filesys.h" -#include "pstring.h" #include "lib/samba3/samba3.h" #define WINS_VERSION 1 @@ -44,11 +43,9 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins while (!x_feof(fp)) { struct samba3_winsdb_entry entry; - pstring name_str, ip_str, ttl_str, nb_flags_str; - const char *ptr; + const char *name_str, *ttl_str, *nb_flags_str; + const char **args; char *p; - BOOL got_token; - BOOL was_ip; int i; unsigned int hash; int version; @@ -77,7 +74,7 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins continue; } - ptr = line; + args = str_list_make_shell(ctx, line, NULL); /* * Now we handle multiple IP addresses per name we need @@ -86,13 +83,15 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins * time to actually parse them into the ip_list array. */ - if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { + name_str = args[0]; + if (!name_str) { DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); SAFE_FREE(line); continue; } - if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { + ttl_str = args[1]; + if (!ttl_str) { DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); SAFE_FREE(line); continue; @@ -102,15 +101,7 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins * Determine the number of IP addresses per line. */ entry.ip_count = 0; - do { - got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); - was_ip = False; - - if(got_token && strchr(ip_str, '.')) { - entry.ip_count++; - was_ip = True; - } - } while( got_token && was_ip); + for (i = 2; args[i] && strchr(args[i], '.'); i++) entry.ip_count++; if(entry.ip_count == 0) { DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); @@ -118,12 +109,6 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins continue; } - if(!got_token) { - DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); - SAFE_FREE(line); - continue; - } - /* Allocate the space for the ip_list. */ if((entry.ips = talloc_array ( ctx, struct ipv4_addr, entry.ip_count)) == NULL) { DEBUG(0,("initialise_wins: Malloc fail !\n")); @@ -132,14 +117,12 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins } /* Reset and re-parse the line. */ - ptr = line; - next_token(&ptr,name_str,NULL,sizeof(name_str)); - next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); for(i = 0; i < entry.ip_count; i++) { - next_token(&ptr, ip_str, NULL, sizeof(ip_str)); - entry.ips[i] = interpret_addr2(ip_str); + entry.ips[i] = interpret_addr2(args[i+2]); } - next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); + nb_flags_str = args[2 + entry.ip_count]; + + SMB_ASSERT(nb_flags_str); /* * Deal with SELF or REGISTER name encoding. Default is REGISTER @@ -153,9 +136,6 @@ NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_wins continue; } - if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') - nb_flags_str[strlen(nb_flags_str)-1] = '\0'; - /* Netbios name. # divides the name from the type (hex): netbios#xx */ entry.name = talloc_strdup(ctx, name_str); -- cgit From 691aff270bc2f0bfee0632d426e2f6ba06f69f89 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 27 Sep 2005 00:11:21 +0000 Subject: r10521: Also check sys/socket.h for definition of socklen_t (needed for AIX) (This used to be commit 42eb14060d53dbcbc381ecc781f121279190b08e) --- source4/lib/replace/config.m4 | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 0b95079b24..98c491fd38 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -30,7 +30,16 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then fi dnl Provided by replace.c: -AC_CHECK_TYPE([socklen_t], int) +AC_TRY_COMPILE([ +#include +#if STDC_HEADERS +#include +#include +#endif +#include ], +[socklen_t foo;],, +[AC_DEFINE(socklen_t, int,[Socket length type])]) + AC_CHECK_HEADERS(sys/syslog.h syslog.h) AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) -- cgit From 251aaafe3a9213118ac3a92def9ab2104c40d12a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Sep 2005 01:26:34 +0000 Subject: r10522: finally got the locking working on solaris10. This adds a read lock on the transaction lock in tdb_traverse_read(). This prevents a pattern of locks which triggers the deadlock detection code in solaris10. I suspect solaris10 is trying to prevent lock starvation by granting locks in the order they were requested, which makes it much easier to produce deadlocks. (This used to be commit 54203aacd138c30826d54c5d9b6cc8d6e9e270f8) --- source4/lib/tdb/common/traverse.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/traverse.c b/source4/lib/tdb/common/traverse.c index 9271b75aa8..00fe5be923 100644 --- a/source4/lib/tdb/common/traverse.c +++ b/source4/lib/tdb/common/traverse.c @@ -205,9 +205,21 @@ int tdb_traverse_read(struct tdb_context *tdb, { struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; int ret; + + /* we need to get a read lock on the transaction lock here to + cope with the lock ordering semantics of solaris10 */ + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_traverse_read: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + tdb->traverse_read++; ret = tdb_traverse_internal(tdb, fn, private, &tl); tdb->traverse_read--; + + tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0); + return ret; } -- cgit From a2dffe109bc989c5a610d610a2f1a31f10d65968 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Sep 2005 02:36:56 +0000 Subject: r10523: fixed timegm() to not depend on get_time_zone(), so it works in lib/replace/ the old timegm() replacement was also broken (it returned the wrong value) (This used to be commit 342489a1d4d5cc4b16cf2e5ff7e671326f0cb3d5) --- source4/lib/replace/replace.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index c53b5a5727..5e60252a67 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -369,18 +369,8 @@ duplicate a string */ time_t timegm(struct tm *tm) { - struct tm tm2, tm3; - time_t t; - - tm2 = *tm; - - t = mktime(&tm2); - tm3 = *localtime(&t); - tm2 = *tm; - tm2.tm_isdst = tm3.tm_isdst; - t = mktime(&tm2); - t -= get_time_zone(t); - + time_t t = mktime(tm); + t -= mktime(gmtime(&t)) - (int)mktime(localtime(&t)); return t; } #endif -- cgit From f895df9772a49bc1e3ff0d2078f2e9d3dc2b7f4a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Sep 2005 03:09:38 +0000 Subject: r10524: SAFE_FREE() in tdb does not need the discard_const_p() the discard_const_p() was causing problems on openbsd where intptr_t is not defined (This used to be commit f02a92787b179a4070227d87e37b7ac092d9e6eb) --- source4/lib/tdb/common/tdb_private.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/tdb_private.h b/source4/lib/tdb/common/tdb_private.h index f3338babfb..d7193b2b67 100644 --- a/source4/lib/tdb/common/tdb_private.h +++ b/source4/lib/tdb/common/tdb_private.h @@ -115,18 +115,9 @@ typedef u32 tdb_off_t; #define MAP_FAILED ((void *)-1) #endif -#ifndef discard_const_p -# if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) -# define discard_const(ptr) ((void *)((intptr_t)(ptr))) -# else -# define discard_const(ptr) ((void *)(ptr)) -# endif -# define discard_const_p(type, ptr) ((type *)discard_const(ptr)) -#endif - /* free memory if the pointer is valid and zero the pointer */ #ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) #endif #define BUCKET(hash) ((hash) % tdb->header.hash_size) -- cgit From 675f81eed3086682faeca34e56d441c6e38bd800 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Sep 2005 03:11:08 +0000 Subject: r10525: change from AC_CHECK_TYPES() to AC_CHECK_TYPE() for intptr_t, so the type is always available, which means we need less #ifdefs (This used to be commit d4af4b11ae69a63fa3b2048e6d576055d86d2bb4) --- source4/lib/ldb/include/includes.h | 4 ---- source4/lib/talloc/config.m4 | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index 8b513e20c7..4372d6b3f9 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -26,9 +26,5 @@ #include "ldb_private.h" #include "talloc.h" -#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) #define discard_const(ptr) ((void *)((intptr_t)(ptr))) -#else -#define discard_const(ptr) ((void *)(ptr)) -#endif #define discard_const_p(type, ptr) ((type *)discard_const(ptr)) diff --git a/source4/lib/talloc/config.m4 b/source4/lib/talloc/config.m4 index 70fedade4a..824eb6d1ff 100644 --- a/source4/lib/talloc/config.m4 +++ b/source4/lib/talloc/config.m4 @@ -6,5 +6,5 @@ if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) fi -AC_CHECK_TYPES(intptr_t) +AC_CHECK_TYPE(intptr_t, unsigned long long) AC_CHECK_HEADERS(stdint.h stdarg.h unistd.h sys/types.h) -- cgit From 42b81d7c3e8ac9ad4c35d5377decbdd5ab18ffbb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 27 Sep 2005 10:00:27 +0000 Subject: r10528: Add credentials.h back into includes.h as some compilers don't seem to be able to handle incomplete enum types. (This used to be commit 540155fad3c8e3d79fb631bb3f14273f82130a73) --- source4/lib/cmdline/popt_common.c | 1 - source4/lib/credentials.c | 1 - source4/lib/samba3/secrets.c | 1 - 3 files changed, 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 76c8a537e3..43ea203b78 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -25,7 +25,6 @@ #include "system/filesys.h" #include "system/passwd.h" #include "lib/cmdline/popt_common.h" -#include "credentials.h" /* Handle command line options: * -d,--debuglevel diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index 166d60b00d..045047d358 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -27,7 +27,6 @@ #include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */ #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" -#include "include/credentials.h" /** diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index 0981a7a6ec..0f3cc0c581 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -30,7 +30,6 @@ #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" #include "lib/tdb/include/tdbutil.h" -#include "credentials.h" /** * Unpack SID into a pointer -- cgit From d345bab9c0ea4838c31c502d769e042936ce980b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 27 Sep 2005 10:32:49 +0000 Subject: r10531: (hopefully) improve detection of socket-related functions in external libraries (This used to be commit 20a1aba500c64dc530271a96af8d557bc54af960) --- source4/lib/socket/config.m4 | 23 ++++------------------- source4/lib/socket/config.mk | 3 --- 2 files changed, 4 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index daa85803dc..01cd28baa3 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -18,32 +18,17 @@ fi # it. AC_CHECK_FUNCS(connect) if test x"$ac_cv_func_connect" = x"no"; then - case "$LIBS $SOCKET_LIBS" in - *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl_s, SOCKET_LIBS, printf) ;; - esac - case "$LIBS $SOCKET_LIBS" in - *-lnsl*) ;; - *) AC_CHECK_LIB_EXT(nsl, SOCKET_LIBS, printf) ;; - esac - case "$LIBS $SOCKET_LIBS" in - *-lsocket*) ;; - *) AC_CHECK_LIB_EXT(socket, SOCKET_LIBS, connect) ;; - esac - case "$LIBS $SOCKET_LIBS" in - *-linet*) ;; - *) AC_CHECK_LIB_EXT(inet, SOCKET_LIBS, connect) ;; - esac + AC_CHECK_LIB(nsl_s, printf) + AC_CHECK_LIB(nsl, printf) + AC_CHECK_LIB(socket, connect) + AC_CHECK_LIB_EXT(inet, connect) dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value dnl has been cached. if test x"$ac_cv_lib_ext_socket_connect" = x"yes" || test x"$ac_cv_lib_ext_inet_connect" = x"yes"; then - # ac_cv_func_connect=yes - # don't! it would cause AC_CHECK_FUNC to succeed next time configure is run AC_DEFINE(HAVE_CONNECT,1,[Whether the system has connect()]) fi fi -SMB_EXT_LIB(SOCKET,[${SOCKET_LIBS}],[${SOCKET_CFLAGS}],[${SOCKET_CPPFLAGS}],[${SOCKET_LDFLAGS}]) ############################################ # check for unix domain sockets diff --git a/source4/lib/socket/config.mk b/source4/lib/socket/config.mk index e007b01725..13fe584373 100644 --- a/source4/lib/socket/config.mk +++ b/source4/lib/socket/config.mk @@ -6,7 +6,6 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv4.o NOPROTO=YES -REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_ipv4 ################################################ @@ -17,7 +16,6 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_ipv6.o NOPROTO=YES -REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_ipv6 ################################################ @@ -28,7 +26,6 @@ SUBSYSTEM = SOCKET INIT_OBJ_FILES = \ lib/socket/socket_unix.o NOPROTO=YES -REQUIRED_SUBSYSTEMS = EXT_LIB_SOCKET # End MODULE socket_unix ################################################ -- cgit From 04b7fb64e1e84f6c2cf987eb6497e2d25727a59d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 27 Sep 2005 11:10:57 +0000 Subject: r10533: Eliminate another use of next_token() (This used to be commit cff17c6ac7e4fad730b6ef05e09499fff32c694a) --- source4/lib/util_sock.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index d60fbb3451..be968666a7 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -21,20 +21,16 @@ #include "includes.h" #include "system/network.h" -#include "pstring.h" - enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; -typedef struct smb_socket_option { +static const struct { const char *name; int level; int option; int value; int opttype; -} smb_socket_option; - -static const smb_socket_option socket_options[] = { +} socket_options[] = { {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, @@ -76,9 +72,11 @@ static const smb_socket_option socket_options[] = { ****************************************************************************/ void set_socket_options(int fd, const char *options) { - fstring tok; + const char **options_list = str_list_make(NULL, options, " \t,"); + int j; - while (next_token(&options,tok," \t,", sizeof(tok))) { + for (j = 0; options_list[j]; j++) { + const char *tok = options_list[j]; int ret=0,i; int value = 1; char *p; @@ -121,5 +119,7 @@ void set_socket_options(int fd, const char *options) if (ret != 0) DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); } + + talloc_free(options_list); } -- cgit From 82ae72a0cf0ee3aee89573d79f1baffda3612593 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 Sep 2005 11:59:39 +0000 Subject: r10535: fixed the pidfile code (it didn't survive the recent pstring changes) (This used to be commit 1b9e6579931c9ff367ab032d0d2aadf95dcb3e63) --- source4/lib/pidfile.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/pidfile.c b/source4/lib/pidfile.c index 54d2c81d2e..9a7c197f70 100644 --- a/source4/lib/pidfile.c +++ b/source4/lib/pidfile.c @@ -39,9 +39,9 @@ pid_t pidfile_pid(const char *name) asprintf(&pidFile, "%s/%s.pid", lp_piddir(), name); fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644); - SAFE_FREE(pidFile); if (fd == -1) { + SAFE_FREE(pidFile); return 0; } @@ -63,11 +63,13 @@ pid_t pidfile_pid(const char *name) } close(fd); + SAFE_FREE(pidFile); return (pid_t)ret; noproc: close(fd); unlink(pidFile); + SAFE_FREE(pidFile); return 0; } -- cgit From 38e43be7b89673282f8853ffedf726d84ef5ce30 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Sep 2005 12:54:08 +0000 Subject: r10537: - we now use a much nicer way to handle talloc_free(timed_event) the events code replaces a destructor to one that returns allways -1 while it's calling the event handler - we don't need the composite and winsrepl specific fixes any more - this also fixes the problem with smbcli, dcerpc, cldap, ldap and nbt request timeouts metze (This used to be commit 495996cfc49a1c6eefde6ff04fc75e0739be3aab) --- source4/lib/events/events_liboop.c | 13 ++++++++++++- source4/lib/events/events_standard.c | 18 +++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_liboop.c b/source4/lib/events/events_liboop.c index ad7c43cd4e..54cb8d5a52 100644 --- a/source4/lib/events/events_liboop.c +++ b/source4/lib/events/events_liboop.c @@ -172,12 +172,23 @@ static void oop_event_set_fd_flags(struct fd_event *fde, uint16_t flags) fde->flags = flags; } +static int oop_event_timed_destructor(void *ptr); +static int oop_event_timed_deny_destructor(void *ptr) +{ + return -1; +} + static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr) { struct timed_event *te = ptr; + /* deny the handler to free the event */ + talloc_set_destructor(te, oop_event_timed_deny_destructor); te->handler(te->event_ctx, te, t, te->private_data); + talloc_set_destructor(te, oop_event_timed_destructor); + talloc_free(te); + return OOP_CONTINUE; } @@ -218,7 +229,7 @@ static struct timed_event *oop_event_add_timed(struct event_context *ev, TALLOC_ te->private_data = private_data; te->additional_data = NULL; - oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); + oop->on_time(oop, te->next_event, oop_event_timed_handler, te); talloc_set_destructor(te, oop_event_timed_destructor); diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 810e8bbca3..8fe8d009bf 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -284,6 +284,11 @@ static int std_event_timed_destructor(void *ptr) return 0; } +static int std_event_timed_deny_destructor(void *ptr) +{ + return -1; +} + /* add a timed event return NULL on failure (memory allocation error) @@ -340,17 +345,12 @@ static void std_event_loop_timer(struct event_context *ev) return; } - te->next_event = timeval_zero(); - + /* deny the handler to free the event */ + talloc_set_destructor(te, std_event_timed_deny_destructor); te->handler(ev, te, t, te->private_data); - /* note the care taken to prevent referencing a event - that could have been freed by the handler */ - if (std_ev->timed_events) { - if (timeval_is_zero(&std_ev->timed_events->next_event)) { - talloc_free(te); - } - } + talloc_set_destructor(te, std_event_timed_destructor); + talloc_free(te); } #if WITH_EPOLL -- cgit From 5a1cf98998fb81c8b7bdab28d36cea04f7c22edc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 28 Sep 2005 14:12:09 +0000 Subject: r10579: str_list_make() can return NULL (This used to be commit f547ab4644fd1c8ae2e44a25e874abf35e02d986) --- source4/lib/util_sock.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index be968666a7..8a65a27d02 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -75,6 +75,9 @@ void set_socket_options(int fd, const char *options) const char **options_list = str_list_make(NULL, options, " \t,"); int j; + if (!options_list) + return; + for (j = 0; options_list[j]; j++) { const char *tok = options_list[j]; int ret=0,i; -- cgit From 5058f4b9e82ca8b9f2405930db3a46b8c37f06ed Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 28 Sep 2005 18:18:09 +0000 Subject: r10586: Add MergedObject() builder. Default to Library() rather then StaticLibrary() (This used to be commit b53313dc517986c69a4e4cb8fe3885b696f8faa1) --- source4/lib/SConscript | 18 +++++++++--------- source4/lib/appweb/SConscript | 6 +++--- source4/lib/charset/SConscript | 2 +- source4/lib/cmdline/SConscript | 2 +- source4/lib/com/SConscript | 6 +++--- source4/lib/events/SConscript | 2 +- source4/lib/ldb/SConscript | 22 +++++++++++----------- source4/lib/messaging/SConscript | 2 +- source4/lib/netif/SConscript | 2 +- source4/lib/popt/SConscript | 2 +- source4/lib/registry/SConscript | 16 ++++++++-------- source4/lib/replace/SConscript | 2 +- source4/lib/samba3/SConscript | 2 +- source4/lib/socket/SConscript | 8 ++++---- source4/lib/socket_wrapper/SConscript | 2 +- source4/lib/talloc/SConscript | 2 +- source4/lib/tdb/SConscript | 2 +- source4/lib/tls/SConscript | 2 +- 18 files changed, 50 insertions(+), 50 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/SConscript b/source4/lib/SConscript index a184eecd10..be77e8621d 100644 --- a/source4/lib/SConscript +++ b/source4/lib/SConscript @@ -13,29 +13,29 @@ basic_files = ['version.c', 'xfile.c', 'debug.c', 'fault.c', proto_files = basic_files -basic = hostenv.StaticLibrary('basic', [dynconfig,charset,talloc,basic_files,charset]) +basic = hostenv.Library('basic', [dynconfig,charset,talloc,basic_files]) Export('basic') -hostenv.StaticLibrary('tdr', ['tdr/tdr.c']) -hostenv.StaticLibrary('crypto', +hostenv.Library('tdr', ['tdr/tdr.c']) +hostenv.Library('crypto', ['crypto/crc32.c','crypto/md5.c','crypto/hmacmd5.c', 'crypto/md4.c','crypto/arcfour.c']) -hostenv.StaticLibrary('compression', ['compression/mszip.c']) -hostenv.StaticLibrary('gencache',['gencache.c']) -hostenv.StaticLibrary('pidfile',['pidfile.c']) -hostenv.StaticLibrary('unix_privs',['unix_privs.c']) +hostenv.Library('compression', ['compression/mszip.c']) +hostenv.Library('gencache',['gencache.c']) +hostenv.Library('pidfile',['pidfile.c']) +hostenv.Library('unix_privs',['unix_privs.c']) SConscript(dirs=['ldb']) Import('ldb') gendb_files = ['gendb.c'] proto_files += gendb_files -gendb = hostenv.StaticLibrary('gendb', [gendb_files,ldb]) +gendb = hostenv.Library('gendb', [gendb_files,ldb]) Export('gendb') credentials_files = ['credentials.c'] proto_files += credentials_files -credentials = hostenv.StaticLibrary('credentials',[credentials_files,basic,gendb]) +credentials = hostenv.Library('credentials',[credentials_files,basic,gendb]) Export('credentials') hostenv.proto_headers += hostenv.CProtoHeader('proto.h', proto_files) diff --git a/source4/lib/appweb/SConscript b/source4/lib/appweb/SConscript index 2c8238b67c..6ffcaa23ec 100644 --- a/source4/lib/appweb/SConscript +++ b/source4/lib/appweb/SConscript @@ -1,5 +1,5 @@ Import('hostenv') -hostenv.StaticLibrary('mpr',['mpr/miniMpr.c','mpr/var.c']) -hostenv.StaticLibrary('ejs',['ejs/ejsLib.c','ejs/ejsLex.c','ejs/ejsParser.c','ejs/ejsProcs.c']) -hostenv.StaticLibrary('esp',['esp/esp.c','esp/espProcs.c']) +hostenv.Library('mpr',['mpr/miniMpr.c','mpr/var.c']) +hostenv.Library('ejs',['ejs/ejsLib.c','ejs/ejsLex.c','ejs/ejsParser.c','ejs/ejsProcs.c']) +hostenv.Library('esp',['esp/esp.c','esp/espProcs.c']) diff --git a/source4/lib/charset/SConscript b/source4/lib/charset/SConscript index 5ef640d2dc..9bc474ff48 100644 --- a/source4/lib/charset/SConscript +++ b/source4/lib/charset/SConscript @@ -62,5 +62,5 @@ if hostenv['configure']: else: iconv = [] # FIXME -charset = hostenv.StaticLibrary('charset',['iconv.c','charcnv.c',iconv]) +charset = hostenv.Library('charset',['iconv.c','charcnv.c',iconv]) Export('charset') diff --git a/source4/lib/cmdline/SConscript b/source4/lib/cmdline/SConscript index 12f4f7c11c..4a2047f071 100644 --- a/source4/lib/cmdline/SConscript +++ b/source4/lib/cmdline/SConscript @@ -2,5 +2,5 @@ Import('hostenv') # tastes like -*- python -*- Import('basic param credentials') -popt_common = hostenv.StaticLibrary('popt_common',['popt_common.c',basic,param,credentials]) +popt_common = hostenv.Library('popt_common',['popt_common.c',basic,param,credentials]) Export('popt_common') diff --git a/source4/lib/com/SConscript b/source4/lib/com/SConscript index 44708bdf32..797cd37620 100644 --- a/source4/lib/com/SConscript +++ b/source4/lib/com/SConscript @@ -1,4 +1,4 @@ Import('hostenv') -hostenv.StaticLibrary('com', [ 'tables.c','rot.c','main.c']) -hostenv.StaticLibrary('dcom', [ 'dcom/tables.c','dcom/main.c']) -hostenv.StaticLibrary('com_simple', ['classes/simple.c']) +hostenv.Library('com', [ 'tables.c','rot.c','main.c']) +hostenv.Library('dcom', [ 'dcom/tables.c','dcom/main.c']) +hostenv.Library('com_simple', ['classes/simple.c']) diff --git a/source4/lib/events/SConscript b/source4/lib/events/SConscript index e1ca866233..a8a6c08657 100644 --- a/source4/lib/events/SConscript +++ b/source4/lib/events/SConscript @@ -1,3 +1,3 @@ Import('hostenv') -hostenv.StaticLibrary('events',['events.c','events_standard.c']) +hostenv.Library('events',['events.c','events_standard.c']) diff --git a/source4/lib/ldb/SConscript b/source4/lib/ldb/SConscript index 6dfb53f789..8e246d1961 100644 --- a/source4/lib/ldb/SConscript +++ b/source4/lib/ldb/SConscript @@ -12,32 +12,32 @@ if hostenv['configure']: conf.Finish() if defines.has_key('HAVE_SQLITE3'): - hostenv.StaticLibrary('ldb_sqlite3/ldb_sqlite3.c') + hostenv.Library('ldb_sqlite3/ldb_sqlite3.c') # LDB modules modules = [] -modules.append(hostenv.StaticLibrary('modules/timestamps.c')) -modules.append(hostenv.StaticLibrary('modules/rdn_name.c')) -modules.append(hostenv.StaticLibrary('modules/schema.c')) -modules.append(hostenv.StaticLibrary('ldb_ildap/ldb_ildap.c')) -#modules.append(hostenv.StaticLibrary('modules/ldb_map.c')) +modules.append(hostenv.Library('modules/timestamps.c')) +modules.append(hostenv.Library('modules/rdn_name.c')) +modules.append(hostenv.Library('modules/schema.c')) +modules.append(hostenv.Library('ldb_ildap/ldb_ildap.c')) +#modules.append(hostenv.Library('modules/ldb_map.c')) Import('dsdb_ldb_modules') modules += dsdb_ldb_modules -modules.append(hostenv.StaticLibrary( +modules.append(hostenv.Library( 'ldb_tdb', ['ldb_tdb/ldb_tdb.c', 'ldb_tdb/ldb_search.c', 'ldb_tdb/ldb_pack.c', 'ldb_tdb/ldb_index.c', 'ldb_tdb/ldb_cache.c', 'ldb_tdb/ldb_tdb_wrap.c'])) -#modules.append(hostenv.StaticLibrary('ldb_ildap', ['ldb_ildap/ldb_ildap.c'])) +#modules.append(hostenv.Library('ldb_ildap', ['ldb_ildap/ldb_ildap.c'])) # Export the ldb base plus modules for other parts of the build system # to enjoy. -ldb = hostenv.StaticLibrary( +ldb = hostenv.Library( 'ldb', ['common/ldb.c', 'common/ldb_ldif.c', 'common/ldb_parse.c', 'common/ldb_parse.c', 'common/ldb_msg.c', 'common/ldb_utf8.c', @@ -46,8 +46,8 @@ ldb = hostenv.StaticLibrary( Export('ldb') -hostenv.StaticLibrary('samba/ldif_handlers.c') -ldb_cmdline = hostenv.StaticLibrary('ldb_cmdline', 'tools/cmdline.c') +hostenv.Library('samba/ldif_handlers.c') +ldb_cmdline = hostenv.Library('ldb_cmdline', 'tools/cmdline.c') # Tools diff --git a/source4/lib/messaging/SConscript b/source4/lib/messaging/SConscript index 1d1ee5859b..7e060f0851 100644 --- a/source4/lib/messaging/SConscript +++ b/source4/lib/messaging/SConscript @@ -1,2 +1,2 @@ Import('hostenv') -hostenv.StaticLibrary('messaging','messaging.c') +hostenv.Library('messaging','messaging.c') diff --git a/source4/lib/netif/SConscript b/source4/lib/netif/SConscript index 3e36fc55fe..7630d13236 100644 --- a/source4/lib/netif/SConscript +++ b/source4/lib/netif/SConscript @@ -19,4 +19,4 @@ if hostenv['configure']: conf.Finish() -hostenv.StaticLibrary('netif', ['interface.c', 'netif.c']) +hostenv.Library('netif', ['interface.c', 'netif.c']) diff --git a/source4/lib/popt/SConscript b/source4/lib/popt/SConscript index 85f9c9b7e0..d9a576a031 100644 --- a/source4/lib/popt/SConscript +++ b/source4/lib/popt/SConscript @@ -7,5 +7,5 @@ if hostenv['configure']: conf.env['HAVE_EXTERNAL_POPT'] = conf.CheckLibWithHeader('popt', 'popt.h', 'c', 'poptGetArgs(NULL);') conf.Finish() -popt = hostenv.StaticLibrary('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) +popt = hostenv.Library('popt', ['findme.c','popt.c','poptconfig.c','popthelp.c','poptparse.c']) Export('popt') diff --git a/source4/lib/registry/SConscript b/source4/lib/registry/SConscript index aa2d587260..f2fa526a67 100644 --- a/source4/lib/registry/SConscript +++ b/source4/lib/registry/SConscript @@ -2,19 +2,19 @@ Import('hostenv paths') # tastes like -*- python -*- Import('talloc basic popt_common popt param') -registry = hostenv.StaticLibrary('registry', +registry = hostenv.Library('registry', [basic,talloc,'common/reg_interface.c','common/reg_util.c']) regtree = hostenv.Program('regtree', ['tools/regtree.c',registry,talloc,basic,popt_common,popt,param]) regshell = hostenv.Program('regshell', ['tools/regshell.c',registry,talloc,basic,popt_common,popt,param]) regpatch = hostenv.Program('regpatch', ['tools/regpatch.c',registry,talloc,basic,popt_common,popt,param]) regdiff = hostenv.Program('regdiff', ['tools/regdiff.c',registry,talloc,basic,popt_common,popt,param]) -hostenv.StaticLibrary('reg_backend_dir.c') -hostenv.StaticLibrary('reg_backend_gconf.c') -hostenv.StaticLibrary('reg_backend_ldb.c') -hostenv.StaticLibrary('reg_backend_nt4', ['reg_backend_nt4.c',hostenv.TdrMarshaller('regf.idl')]) -hostenv.StaticLibrary('reg_backend_rpc.c') -hostenv.StaticLibrary('reg_backend_w95.c') -hostenv.StaticLibrary('reg_backend_wine.c') +hostenv.Library('reg_backend_dir.c') +hostenv.Library('reg_backend_gconf.c') +hostenv.Library('reg_backend_ldb.c') +hostenv.Library('reg_backend_nt4', ['reg_backend_nt4.c',hostenv.TdrMarshaller('regf.idl')]) +hostenv.Library('reg_backend_rpc.c') +hostenv.Library('reg_backend_w95.c') +hostenv.Library('reg_backend_wine.c') hostenv.Install(paths['BINDIR'], [regtree,regshell,regpatch,regdiff]) diff --git a/source4/lib/replace/SConscript b/source4/lib/replace/SConscript index f45d0e7d5a..cf28102175 100644 --- a/source4/lib/replace/SConscript +++ b/source4/lib/replace/SConscript @@ -67,5 +67,5 @@ int main() { conf.Finish() -hostenv.StaticLibrary('replace', rep_files) +hostenv.Library('replace', rep_files) SConscript(dirs=['win32']) diff --git a/source4/lib/samba3/SConscript b/source4/lib/samba3/SConscript index ba1f76b1a7..3fa9ea947b 100644 --- a/source4/lib/samba3/SConscript +++ b/source4/lib/samba3/SConscript @@ -1,4 +1,4 @@ Import('hostenv') -hostenv.StaticLibrary('samba3', +hostenv.Library('samba3', ['smbpasswd.c','tdbsam.c','policy.c','idmap.c','winsdb.c','samba3.c', 'group.c','registry.c','secrets.c','share_info.c']) diff --git a/source4/lib/socket/SConscript b/source4/lib/socket/SConscript index 26c8bf444c..73c7eeeeac 100644 --- a/source4/lib/socket/SConscript +++ b/source4/lib/socket/SConscript @@ -57,8 +57,8 @@ int main(void) conf.Finish() -hostenv.StaticLibrary('socket_ipv4.c') -hostenv.StaticLibrary('socket_ipv6.c') -hostenv.StaticLibrary('socket_unix.c') -hostenv.StaticLibrary('socket', ['socket.c','access.c','connect.c']) +hostenv.Library('socket_ipv4.c') +hostenv.Library('socket_ipv6.c') +hostenv.Library('socket_unix.c') +hostenv.Library('socket', ['socket.c','access.c','connect.c']) diff --git a/source4/lib/socket_wrapper/SConscript b/source4/lib/socket_wrapper/SConscript index 1c0253a0d4..248922bcd7 100644 --- a/source4/lib/socket_wrapper/SConscript +++ b/source4/lib/socket_wrapper/SConscript @@ -9,6 +9,6 @@ opts.Update(hostenv) if hostenv['socket_wrapper']: hostenv.Append(CPPDEFINES = {'HAVE_SOCKET_WRAPPER': 1}) - socket_wrapper = hostenv.StaticLibrary('socket_wrapper',['socket_wrapper.c']) + socket_wrapper = hostenv.Library('socket_wrapper',['socket_wrapper.c']) else: socket_wrapper = [] diff --git a/source4/lib/talloc/SConscript b/source4/lib/talloc/SConscript index ad88262f1d..222a00e001 100644 --- a/source4/lib/talloc/SConscript +++ b/source4/lib/talloc/SConscript @@ -1,5 +1,5 @@ Import('hostenv') # tastes like -*- python -*- -talloc = hostenv.StaticLibrary('talloc',['talloc.c']) +talloc = hostenv.Library('talloc',['talloc.c']) Export('talloc') diff --git a/source4/lib/tdb/SConscript b/source4/lib/tdb/SConscript index 22f7f34ca5..9eb347f3ac 100644 --- a/source4/lib/tdb/SConscript +++ b/source4/lib/tdb/SConscript @@ -7,7 +7,7 @@ tdb_source = ['common/tdb.c','common/dump.c','common/io.c','common/lock.c', 'common/open.c','common/traverse.c','common/freelist.c', 'common/error.c','common/transaction.c', 'common/tdbutil.c'] -tdb = tdbenv.StaticLibrary('tdb', tdb_source) +tdb = tdbenv.Library('tdb', tdb_source) tdbtool = tdbenv.Program('bin/tdbtool', ['tools/tdbtool.c',tdb]) tdbtorture = tdbenv.Program('bin/tdbtorture', ['tools/tdbtorture.c',tdb]) diff --git a/source4/lib/tls/SConscript b/source4/lib/tls/SConscript index 941955e9e3..452eaeeddc 100644 --- a/source4/lib/tls/SConscript +++ b/source4/lib/tls/SConscript @@ -1,5 +1,5 @@ Import('hostenv') -hostenv.StaticLibrary('tls', ['tls.c', 'tlscert.c']) +hostenv.Library('tls', ['tls.c', 'tlscert.c']) if hostenv['configure']: conf = hostenv.Configure() -- cgit From 4abb4797613868e518baafb5f3618e78f67ac05c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 28 Sep 2005 19:56:21 +0000 Subject: r10588: Remove more unused files, macros (This used to be commit d2f80c0457f7404b2cac9df59a400130e9ad025f) --- source4/lib/registry/tools/regpatch.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 887f53df37..98e6c0ff5d 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -156,10 +156,13 @@ static void print_line(struct cmd_line *cl) */ static struct cmd_line *get_cmd_line(int fd) { - CMD_LINE *cl = smb_xmalloc_p(CMD_LINE); + CMD_LINE *cl = malloc_p(CMD_LINE); int i = 0, rc; uint8_t ch; + if (!cl) + return NULL; + cl->len = INIT_ALLOC; /* @@ -447,7 +450,9 @@ static CMD *regedit4_get_cmd(int fd) struct cmd_line *cl = NULL; struct val_spec_list *vl = NULL; - cmd = smb_xmalloc_p(struct command_s); + cmd = malloc_p(struct command_s); + if (!cmd) + return NULL; cmd->cmd = CMD_NONE; cmd->key = NULL; @@ -490,7 +495,9 @@ static CMD *regedit4_get_cmd(int fd) * There could be a \ on the end which we need to * handle at some time */ - vl = smb_xmalloc_p(struct val_spec_list); + vl = malloc_p(struct val_spec_list); + if (!vl) + return NULL; vl->next = NULL; vl->val = NULL; vl->name = parse_value(cl, &vl->type, &vl->val); @@ -609,7 +616,9 @@ static CMD_FILE *cmd_file_create(const char *file) return NULL; } - tmp = smb_xmalloc_p(CMD_FILE); + tmp = malloc_p(CMD_FILE); + if (!tmp) + return NULL; /* * Let's fill in some of the fields; -- cgit From 87af8061c760b7d1eaa596183ac1635af73524b4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 28 Sep 2005 21:54:29 +0000 Subject: r10592: Add "adfgets()" function, which allocates and reads a line from a fd. Also add torture tests for this function and file_{load,save}. I've hardcoded a file name here.. should I handle that neater somehow? (This used to be commit 8fa383f182f1c4479979455968dd690edc0117ea) --- source4/lib/util_file.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 156d09aaf5..77066e78cc 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -2,6 +2,8 @@ * Unix SMB/CIFS implementation. * SMB parameters and setup * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. + * + * Added afdgets() Jelmer Vernooij 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 @@ -96,6 +98,52 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f) return(s); } +/* Read one line (data until next newline or eof) and allocate it */ +char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint) +{ + char *data = NULL; + ssize_t alloc_size = 0, offset = 0, ret; + int p; + + if (hint <= 0) hint = 0x100; + + do { + alloc_size += hint; + + data = talloc_realloc(mem_ctx, data, char, alloc_size); + + if (!data) + return NULL; + + ret = read(fd, data + offset, hint); + + if (ret == -1) { + talloc_free(data); + return NULL; + } + + /* Find newline */ + for (p = 0; p < ret; p++) { + if (data[offset + p] == '\n') + break; + } + + if (p < ret) { + data[offset + p] = '\0'; + + /* Go back to position of newline */ + lseek(fd, p - ret + 1, SEEK_CUR); + return data; + } + + offset += ret; + + } while (ret == hint); + + data[offset] = '\0'; + + return data; +} /**************************************************************************** @@ -287,7 +335,7 @@ void file_lines_slashcont(char **lines) /* save a lump of data into a file. Mostly used for debugging */ -BOOL file_save(const char *fname, void *packet, size_t length) +BOOL file_save(const char *fname, const void *packet, size_t length) { int fd; fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644); -- cgit From 40e214e919f8be01d1a2e83968577ecfee85dfb9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 28 Sep 2005 22:16:08 +0000 Subject: r10593: Add printf attribute Andrew Bartlett (This used to be commit ba11061b96e26900fd09c32b95c2af934c1e2070) --- source4/lib/util_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index 77066e78cc..203eccd0cf 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -358,7 +358,7 @@ BOOL file_exists(const char *path) return (stat(path, &st) == 0); } -int vfdprintf(int fd, const char *format, va_list ap) +int vfdprintf(int fd, const char *format, va_list ap) _PRINTF_ATTRIBUTE(2,0) { char *p; int len, ret; -- cgit From a12a6686ba7301c464e8db857c73bfd1061dbf93 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 29 Sep 2005 00:02:38 +0000 Subject: r10596: Move the credentials code into it's own subsystem, and push it under auth/ Andrew Bartlett (This used to be commit 2e76a4b8efd59c496d64241d654538d3222545c6) --- source4/lib/basic.mk | 3 +- source4/lib/cmdline/config.mk | 1 + source4/lib/credentials.c | 1047 ----------------------------------------- 3 files changed, 2 insertions(+), 1049 deletions(-) delete mode 100644 source4/lib/credentials.c (limited to 'source4/lib') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 3fa9bb354b..18f6f3aeb9 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -66,8 +66,7 @@ ADD_OBJ_FILES = \ lib/mutex.o \ lib/idtree.o \ lib/db_wrap.o \ - lib/gendb.o \ - lib/credentials.o + lib/gendb.o REQUIRED_SUBSYSTEMS = \ LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC \ SOCKET_WRAPPER CONFIG diff --git a/source4/lib/cmdline/config.mk b/source4/lib/cmdline/config.mk index 831461b7f3..643fa9f1af 100644 --- a/source4/lib/cmdline/config.mk +++ b/source4/lib/cmdline/config.mk @@ -3,5 +3,6 @@ [SUBSYSTEM::LIBCMDLINE_CREDENTIALS] ADD_OBJ_FILES = lib/cmdline/getsmbpass.o \ lib/cmdline/credentials.o +REQUIRED_SUBSYSTEMS = CREDENTIALS # End SUBSYSTEM LIBCMDLINE_CREDENTIALS ############################## diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c deleted file mode 100644 index 045047d358..0000000000 --- a/source4/lib/credentials.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Jelmer Vernooij 2005 - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "include/secrets.h" -#include "lib/ldb/include/ldb.h" -#include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */ -#include "system/kerberos.h" -#include "auth/kerberos/kerberos.h" - - -/** - * Create a new credentials structure - * @param mem_ctx TALLOC_CTX parent for credentials structure - */ -struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) -{ - struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials); - if (!cred) { - return cred; - } - - cred->netlogon_creds = NULL; - cred->machine_account_pending = False; - cred->workstation_obtained = CRED_UNINITIALISED; - cred->username_obtained = CRED_UNINITIALISED; - cred->password_obtained = CRED_UNINITIALISED; - cred->domain_obtained = CRED_UNINITIALISED; - cred->realm_obtained = CRED_UNINITIALISED; - cred->ccache_obtained = CRED_UNINITIALISED; - cred->principal_obtained = CRED_UNINITIALISED; - return cred; -} - -/** - * Obtain the username for this credentials context. - * @param cred credentials context - * @retval The username set on this context. - * @note Return value will never be NULL except by programmer error. - */ -const char *cli_credentials_get_username(struct cli_credentials *cred) -{ - if (cred->machine_account_pending) { - cli_credentials_set_machine_account(cred); - } - - if (cred->username_obtained == CRED_CALLBACK) { - cred->username = cred->username_cb(cred); - cred->username_obtained = CRED_SPECIFIED; - } - - return cred->username; -} - -BOOL cli_credentials_set_username(struct cli_credentials *cred, - const char *val, enum credentials_obtained obtained) -{ - if (obtained >= cred->username_obtained) { - cred->username = talloc_strdup(cred, val); - cred->username_obtained = obtained; - return True; - } - - return False; -} - -BOOL cli_credentials_set_username_callback(struct cli_credentials *cred, - const char *(*username_cb) (struct cli_credentials *)) -{ - if (cred->username_obtained < CRED_CALLBACK) { - cred->username_cb = username_cb; - cred->username_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - - - -/** - * Obtain the client principal for this credentials context. - * @param cred credentials context - * @retval The username set on this context. - * @note Return value will never be NULL except by programmer error. - */ -const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx) -{ - if (cred->machine_account_pending) { - cli_credentials_set_machine_account(cred); - } - - if (cred->principal_obtained == CRED_CALLBACK) { - cred->principal = cred->principal_cb(cred); - cred->principal_obtained = CRED_SPECIFIED; - } - - if (cred->principal_obtained < cred->username_obtained) { - if (cred->domain_obtained > cred->realm_obtained) { - return talloc_asprintf(mem_ctx, "%s@%s", - cli_credentials_get_username(cred), - cli_credentials_get_domain(cred)); - } else { - return talloc_asprintf(mem_ctx, "%s@%s", - cli_credentials_get_username(cred), - cli_credentials_get_realm(cred)); - } - } - return talloc_reference(mem_ctx, cred->principal); -} - -BOOL cli_credentials_set_principal(struct cli_credentials *cred, - const char *val, - enum credentials_obtained obtained) -{ - if (obtained >= cred->principal_obtained) { - cred->principal = talloc_strdup(cred, val); - cred->principal_obtained = obtained; - return True; - } - - return False; -} - -BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred, - const char *(*principal_cb) (struct cli_credentials *)) -{ - if (cred->principal_obtained < CRED_CALLBACK) { - cred->principal_cb = principal_cb; - cred->principal_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - -BOOL cli_credentials_authentication_requested(struct cli_credentials *cred) -{ - if (cred->principal_obtained >= CRED_SPECIFIED) { - return True; - } - if (cred->username_obtained >= CRED_SPECIFIED) { - return True; - } - return False; -} - -/** - * Obtain the password for this credentials context. - * @param cred credentials context - * @retval If set, the cleartext password, otherwise NULL - */ -const char *cli_credentials_get_password(struct cli_credentials *cred) -{ - if (cred->machine_account_pending) { - cli_credentials_set_machine_account(cred); - } - - if (cred->password_obtained == CRED_CALLBACK) { - cred->password = cred->password_cb(cred); - cred->password_obtained = CRED_SPECIFIED; - } - - return cred->password; -} - -BOOL cli_credentials_set_password(struct cli_credentials *cred, - const char *val, - enum credentials_obtained obtained) -{ - if (obtained >= cred->password_obtained) { - cred->password = talloc_strdup(cred, val); - cred->password_obtained = obtained; - - cred->nt_hash = NULL; - return True; - } - - return False; -} - -BOOL cli_credentials_set_password_callback(struct cli_credentials *cred, - const char *(*password_cb) (struct cli_credentials *)) -{ - if (cred->password_obtained < CRED_CALLBACK) { - cred->password_cb = password_cb; - cred->password_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - -/** - * Obtain the password for this credentials context. - * @param cred credentials context - * @retval If set, the cleartext password, otherwise NULL - */ -const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, - TALLOC_CTX *mem_ctx) -{ - const char *password = cli_credentials_get_password(cred); - - if (password) { - struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password); - if (!nt_hash) { - return NULL; - } - - E_md4hash(password, nt_hash->hash); - - return nt_hash; - } else { - return cred->nt_hash; - } -} - -BOOL cli_credentials_set_nt_hash(struct cli_credentials *cred, - const struct samr_Password *nt_hash, - enum credentials_obtained obtained) -{ - if (obtained >= cred->password_obtained) { - cli_credentials_set_password(cred, NULL, obtained); - cred->nt_hash = talloc(cred, struct samr_Password); - *cred->nt_hash = *nt_hash; - return True; - } - - return False; -} - -int cli_credentials_set_from_ccache(struct cli_credentials *cred, - enum credentials_obtained obtained) -{ - - krb5_principal princ; - krb5_error_code ret; - char *name; - char **realm; - - ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, - cred->ccache->ccache, &princ); - - if (ret) { - char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred); - DEBUG(1,("failed to get principal from ccache: %s\n", - err_mess)); - talloc_free(err_mess); - return ret; - } - - ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name); - if (ret) { - char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred); - DEBUG(1,("failed to unparse principal from ccache: %s\n", - err_mess)); - talloc_free(err_mess); - return ret; - } - - realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ); - - cli_credentials_set_principal(cred, name, obtained); - - free(name); - - krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ); - - cred->ccache_obtained = obtained; - - return 0; -} - - -static int free_mccache(void *ptr) { - struct ccache_container *ccc = ptr; - krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache); - - return 0; -} - -static int free_dccache(void *ptr) { - struct ccache_container *ccc = ptr; - krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache); - - return 0; -} - -static int cli_credentials_set_ccache(struct cli_credentials *cred, - const char *name, - enum credentials_obtained obtained) -{ - krb5_error_code ret; - krb5_principal princ; - struct ccache_container *ccc = talloc(cred, struct ccache_container); - if (!ccc) { - return ENOMEM; - } - - ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); - if (ret) { - talloc_free(ccc); - return ret; - } - if (name) { - ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); - if (ret) { - DEBUG(1,("failed to read krb5 ccache: %s: %s\n", - name, - smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); - talloc_free(ccc); - return ret; - } - } else { - ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); - if (ret) { - DEBUG(3,("failed to read default krb5 ccache: %s\n", - smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); - talloc_free(ccc); - return ret; - } - } - - talloc_set_destructor(ccc, free_dccache); - - ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); - - if (ret) { - DEBUG(3,("failed to get principal from default ccache: %s\n", - smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); - talloc_free(ccc); - return ret; - } - - krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ); - - cred->ccache = ccc; - talloc_steal(cred, ccc); - - ret = cli_credentials_set_from_ccache(cred, obtained); - - if (ret) { - return ret; - } - - return 0; -} - - -int cli_credentials_new_ccache(struct cli_credentials *cred) -{ - krb5_error_code ret; - char *rand_string; - struct ccache_container *ccc = talloc(cred, struct ccache_container); - char *ccache_name; - if (!ccc) { - return ENOMEM; - } - - rand_string = generate_random_str(NULL, 16); - if (!rand_string) { - talloc_free(ccc); - return ENOMEM; - } - - ccache_name = talloc_asprintf(ccc, "MEMORY:%s", - rand_string); - talloc_free(rand_string); - - if (!ccache_name) { - talloc_free(ccc); - return ENOMEM; - } - - ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context); - if (ret) { - talloc_free(ccache_name); - talloc_free(ccc); - return ret; - } - - ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache); - if (ret) { - DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", - ccache_name, - smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc))); - talloc_free(ccache_name); - talloc_free(ccc); - return ret; - } - - talloc_set_destructor(ccc, free_mccache); - - cred->ccache = ccc; - talloc_steal(cred, ccc); - talloc_free(ccache_name); - - return ret; -} - -int cli_credentials_get_ccache(struct cli_credentials *cred, - struct ccache_container **ccc) -{ - krb5_error_code ret; - - if (cred->ccache_obtained >= (MAX(cred->principal_obtained, - cred->username_obtained))) { - *ccc = cred->ccache; - return 0; - } - if (cli_credentials_is_anonymous(cred)) { - return EINVAL; - } - - ret = cli_credentials_new_ccache(cred); - if (ret) { - return ret; - } - ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache); - if (ret) { - return ret; - } - ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained); - - if (ret) { - return ret; - } - *ccc = cred->ccache; - return ret; -} - - -/** - * Obtain the 'short' or 'NetBIOS' domain for this credentials context. - * @param cred credentials context - * @retval The domain set on this context. - * @note Return value will never be NULL except by programmer error. - */ -const char *cli_credentials_get_domain(struct cli_credentials *cred) -{ - if (cred->machine_account_pending) { - cli_credentials_set_machine_account(cred); - } - - if (cred->domain_obtained == CRED_CALLBACK) { - cred->domain = cred->domain_cb(cred); - cred->domain_obtained = CRED_SPECIFIED; - } - - return cred->domain; -} - - -BOOL cli_credentials_set_domain(struct cli_credentials *cred, - const char *val, - enum credentials_obtained obtained) -{ - if (obtained >= cred->domain_obtained) { - cred->domain = talloc_strdup(cred, val); - cred->domain_obtained = obtained; - return True; - } - - return False; -} - -BOOL cli_credentials_set_domain_callback(struct cli_credentials *cred, - const char *(*domain_cb) (struct cli_credentials *)) -{ - if (cred->domain_obtained < CRED_CALLBACK) { - cred->domain_cb = domain_cb; - cred->domain_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - -void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, - const char **username, - const char **domain) -{ - if (cred->principal_obtained > cred->username_obtained) { - *domain = talloc_strdup(mem_ctx, ""); - *username = cli_credentials_get_principal(cred, mem_ctx); - } else { - *domain = cli_credentials_get_domain(cred); - *username = cli_credentials_get_username(cred); - } -} - -/** - * Obtain the Kerberos realm for this credentials context. - * @param cred credentials context - * @retval The realm set on this context. - * @note Return value will never be NULL except by programmer error. - */ -const char *cli_credentials_get_realm(struct cli_credentials *cred) -{ - if (cred->machine_account_pending) { - cli_credentials_set_machine_account(cred); - } - - if (cred->realm_obtained == CRED_CALLBACK) { - cred->realm = cred->realm_cb(cred); - cred->realm_obtained = CRED_SPECIFIED; - } - - return cred->realm; -} - -/** - * Set the realm for this credentials context, and force it to - * uppercase for the sainity of our local kerberos libraries - */ -BOOL cli_credentials_set_realm(struct cli_credentials *cred, - const char *val, - enum credentials_obtained obtained) -{ - if (obtained >= cred->realm_obtained) { - cred->realm = strupper_talloc(cred, val); - cred->realm_obtained = obtained; - return True; - } - - return False; -} - -BOOL cli_credentials_set_realm_callback(struct cli_credentials *cred, - const char *(*realm_cb) (struct cli_credentials *)) -{ - if (cred->realm_obtained < CRED_CALLBACK) { - cred->realm_cb = realm_cb; - cred->realm_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - -/** - * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context. - * - * @param cred credentials context - * @retval The workstation name set on this context. - * @note Return value will never be NULL except by programmer error. - */ -const char *cli_credentials_get_workstation(struct cli_credentials *cred) -{ - if (cred->workstation_obtained == CRED_CALLBACK) { - cred->workstation = cred->workstation_cb(cred); - cred->workstation_obtained = CRED_SPECIFIED; - } - - return cred->workstation; -} - -BOOL cli_credentials_set_workstation(struct cli_credentials *cred, - const char *val, - enum credentials_obtained obtained) -{ - if (obtained >= cred->workstation_obtained) { - cred->workstation = talloc_strdup(cred, val); - cred->workstation_obtained = obtained; - return True; - } - - return False; -} - -BOOL cli_credentials_set_workstation_callback(struct cli_credentials *cred, - const char *(*workstation_cb) (struct cli_credentials *)) -{ - if (cred->workstation_obtained < CRED_CALLBACK) { - cred->workstation_cb = workstation_cb; - cred->workstation_obtained = CRED_CALLBACK; - return True; - } - - return False; -} - -/** - * Read a file descriptor, and parse it for a password (eg from a file or stdin) - * - * @param credentials Credentials structure on which to set the password - * @param fd open file descriptor to read the password from - * @param obtained This enum describes how 'specified' this password is - */ - -BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, - int fd, enum credentials_obtained obtained) -{ - char *p; - char pass[128]; - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n"); - return False; - } - - default: - fprintf(stderr, "Error reading password from file descriptor %d: %s\n", - fd, strerror(errno)); - return False; - } - } - - cli_credentials_set_password(credentials, pass, obtained); - return True; -} - -/** - * Read a named file, and parse it for a password - * - * @param credentials Credentials structure on which to set the password - * @param file a named file to read the password from - * @param obtained This enum describes how 'specified' this password is - */ - -BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained) -{ - int fd = open(file, O_RDONLY, 0); - BOOL ret; - - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - file, strerror(errno)); - return False; - } - - ret = cli_credentials_parse_password_fd(credentials, fd, obtained); - - close(fd); - - return ret; -} - -/** - * Read a named file, and parse it for username, domain, realm and password - * - * @param credentials Credentials structure on which to set the password - * @param file a named file to read the details from - * @param obtained This enum describes how 'specified' this password is - */ - -BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) -{ - uint16_t len = 0; - char *ptr, *val, *param; - char **lines; - int i, numlines; - - lines = file_lines_load(file, &numlines, NULL); - - if (lines == NULL) - { - /* fail if we can't open the credentials file */ - d_printf("ERROR: Unable to open credentials file!\n"); - return False; - } - - for (i = 0; i < numlines; i++) { - len = strlen(lines[i]); - - if (len == 0) - continue; - - /* break up the line into parameter & value. - * will need to eat a little whitespace possibly */ - param = lines[i]; - if (!(ptr = strchr_m (lines[i], '='))) - continue; - - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) { - cli_credentials_set_password(cred, val, obtained); - } else if (strwicmp("username", param) == 0) { - cli_credentials_set_username(cred, val, obtained); - } else if (strwicmp("domain", param) == 0) { - cli_credentials_set_domain(cred, val, obtained); - } else if (strwicmp("realm", param) == 0) { - cli_credentials_set_realm(cred, val, obtained); - } - memset(lines[i], 0, len); - } - - talloc_free(lines); - - return True; -} - - -/** - * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields - * - * The format accepted is [domain\\]user[%password] or user[@realm][%password] - * - * @param credentials Credentials structure on which to set the password - * @param data the string containing the username, password etc - * @param obtained This enum describes how 'specified' this password is - */ - -void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained) -{ - char *uname, *p; - - if (strcmp("%",data) == 0) { - cli_credentials_set_anonymous(credentials); - return; - } - - uname = talloc_strdup(credentials, data); - if ((p = strchr_m(uname,'%'))) { - *p = 0; - cli_credentials_set_password(credentials, p+1, obtained); - } - - if ((p = strchr_m(uname,'@'))) { - cli_credentials_set_principal(credentials, uname, obtained); - *p = 0; - cli_credentials_set_realm(credentials, p+1, obtained); - return; - } else if ((p = strchr_m(uname,'\\')) || (p = strchr_m(uname, '/'))) { - *p = 0; - cli_credentials_set_domain(credentials, uname, obtained); - uname = p+1; - } - cli_credentials_set_username(credentials, uname, obtained); -} - -/** - * Specifies default values for domain, workstation and realm - * from the smb.conf configuration file - * - * @param cred Credentials structure to fill in - */ -void cli_credentials_set_conf(struct cli_credentials *cred) -{ - cli_credentials_set_username(cred, "", CRED_UNINITIALISED); - cli_credentials_set_domain(cred, lp_workgroup(), CRED_UNINITIALISED); - cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_UNINITIALISED); - cli_credentials_set_realm(cred, lp_realm(), CRED_UNINITIALISED); -} - -/** - * Guess defaults for credentials from environment variables, - * and from the configuration file - * - * @param cred Credentials structure to fill in - */ -void cli_credentials_guess(struct cli_credentials *cred) -{ - char *p; - - cli_credentials_set_conf(cred); - - if (getenv("LOGNAME")) { - cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESS_ENV); - } - - if (getenv("USER")) { - cli_credentials_parse_string(cred, getenv("USER"), CRED_GUESS_ENV); - if ((p = strchr_m(getenv("USER"),'%'))) { - memset(p,0,strlen(cred->password)); - } - } - - if (getenv("DOMAIN")) { - cli_credentials_set_domain(cred, getenv("DOMAIN"), CRED_GUESS_ENV); - } - - if (getenv("PASSWD")) { - cli_credentials_set_password(cred, getenv("PASSWD"), CRED_GUESS_ENV); - } - - if (getenv("PASSWD_FD")) { - cli_credentials_parse_password_fd(cred, atoi(getenv("PASSWD_FD")), CRED_GUESS_FILE); - } - - if (getenv("PASSWD_FILE")) { - cli_credentials_parse_password_file(cred, getenv("PASSWD_FILE"), CRED_GUESS_FILE); - } - - cli_credentials_set_ccache(cred, NULL, CRED_GUESS_FILE); -} - -/** - * Fill in credentials for the machine trust account, from the secrets database. - * - * @param cred Credentials structure to fill in - * @retval NTSTATUS error detailing any failure - */ -NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) -{ - TALLOC_CTX *mem_ctx; - - struct ldb_context *ldb; - int ldb_ret; - struct ldb_message **msgs; - const char *attrs[] = { - "secret", - "samAccountName", - "flatname", - "realm", - "secureChannelType", - "ntPwdHash", - "msDS-KeyVersionNumber", - NULL - }; - - const char *machine_account; - const char *password; - const char *domain; - const char *realm; - enum netr_SchannelType sct; - - /* ok, we are going to get it now, don't recurse back here */ - cred->machine_account_pending = False; - - mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password"); - /* Local secrets are stored in secrets.ldb */ - ldb = secrets_db_connect(mem_ctx); - if (!ldb) { - DEBUG(1, ("Could not open secrets.ldb\n")); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* search for the secret record */ - ldb_ret = gendb_search(ldb, - mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), - &msgs, attrs, - SECRETS_PRIMARY_DOMAIN_FILTER, - cli_credentials_get_domain(cred)); - if (ldb_ret == 0) { - DEBUG(1, ("Could not find join record to domain: %s\n", - cli_credentials_get_domain(cred))); - talloc_free(mem_ctx); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } else if (ldb_ret != 1) { - DEBUG(1, ("Found more than one (%d) join records to domain: %s\n", - ldb_ret, cli_credentials_get_domain(cred))); - talloc_free(mem_ctx); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - password = ldb_msg_find_string(msgs[0], "secret", NULL); - - machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); - - if (!machine_account) { - DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", - cli_credentials_get_domain(cred))); - talloc_free(mem_ctx); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0); - if (!sct) { - DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n", - machine_account)); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - if (!password) { - const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash"); - struct samr_Password hash; - ZERO_STRUCT(hash); - if (nt_password_hash) { - memcpy(hash.hash, nt_password_hash->data, - MIN(nt_password_hash->length, sizeof(hash.hash))); - - cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED); - } else { - - DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", - cli_credentials_get_domain(cred))); - talloc_free(mem_ctx); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - } - - cli_credentials_set_secure_channel_type(cred, sct); - - domain = ldb_msg_find_string(msgs[0], "flatname", NULL); - if (domain) { - cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); - } - - realm = ldb_msg_find_string(msgs[0], "realm", NULL); - if (realm) { - cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); - } - - cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); - if (password) { - cli_credentials_set_password(cred, password, CRED_SPECIFIED); - } - - cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0)); - - talloc_free(mem_ctx); - - return NT_STATUS_OK; -} - -/** - * Ask that when required, the credentials system will be filled with - * machine trust account, from the secrets database. - * - * @param cred Credentials structure to fill in - * @note This function is used to call the above function after, rather - * than during, popt processing. - * - */ -void cli_credentials_set_machine_account_pending(struct cli_credentials *cred) -{ - cred->machine_account_pending = True; -} - -/** - * Attach NETLOGON credentials for use with SCHANNEL - */ - -void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, - struct creds_CredentialState *netlogon_creds) -{ - cred->netlogon_creds = talloc_reference(cred, netlogon_creds); -} - -/** - * Return attached NETLOGON credentials - */ - -struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) -{ - return cred->netlogon_creds; -} - -/** - * Set NETLOGON secure channel type - */ - -void cli_credentials_set_secure_channel_type(struct cli_credentials *cred, - enum netr_SchannelType secure_channel_type) -{ - cred->secure_channel_type = secure_channel_type; -} - -/** - * Return NETLOGON secure chanel type - */ - -enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred) -{ - return cred->secure_channel_type; -} - -/** - * Set Kerberos KVNO - */ - -void cli_credentials_set_kvno(struct cli_credentials *cred, - int kvno) -{ - cred->kvno = kvno; -} - -/** - * Return Kerberos KVNO - */ - -int cli_credentials_get_kvno(struct cli_credentials *cred) -{ - return cred->kvno; -} - -/** - * Fill in a credentials structure as the anonymous user - */ -void cli_credentials_set_anonymous(struct cli_credentials *cred) -{ - cli_credentials_set_username(cred, "", CRED_SPECIFIED); - cli_credentials_set_domain(cred, "", CRED_SPECIFIED); - cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); -} - -/** - * Describe a credentials context as anonymous or authenticated - * @retval True if anonymous, False if a username is specified - */ - -BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) -{ - TALLOC_CTX *tmp_ctx = talloc_new(cred); - const char *username = cli_credentials_get_username(cred); - - /* Yes, it is deliberate that we die if we have a NULL pointer - * here - anonymous is "", not NULL, which is 'never specified, - * never guessed', ie programmer bug */ - if (!username[0]) { - talloc_free(tmp_ctx); - return True; - } - - talloc_free(tmp_ctx); - return False; -} -- cgit From 0e90afb4e7737d60d902aee1df4cbeb85a7b693d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 29 Sep 2005 10:18:26 +0000 Subject: r10603: neaten up the ldb module initialisation code (This used to be commit 8e7c4c98a7b4fd814f298fba1b6b686cb58339f8) --- source4/lib/ldb/common/ldb_modules.c | 92 ++++++++++++------------------------ source4/lib/ldb/include/ldb.h | 4 ++ 2 files changed, 33 insertions(+), 63 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 6802cc8955..9c536789b9 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -122,6 +122,20 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { char **modules = NULL; int i; + struct { + const char *name; + ldb_module_init_t init; + } well_known_modules[] = { + { "schema", schema_module_init }, + { "timestamps", timestamps_module_init }, + { "rdn_name", rdn_name_module_init }, +#ifdef _SAMBA_BUILD_ + { "objectguid", objectguid_module_init }, + { "samldb", samldb_module_init }, + { "samba3sam", ldb_samba3sam_module_init }, +#endif + { NULL, NULL } + }; /* find out which modules we are requested to activate */ @@ -161,7 +175,8 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return -1; } - modules = ldb_modules_list_from_string(ldb, msg[0]->elements[0].values[0].data); + modules = ldb_modules_list_from_string(ldb, + (const char *)msg[0]->elements[0].values[0].data); } @@ -175,71 +190,22 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) for (i = 0; modules[i] != NULL; i++) { struct ldb_module *current; - - if (strcmp(modules[i], "schema") == 0) { - current = schema_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; - } - - if (strcmp(modules[i], "timestamps") == 0) { - current = timestamps_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; + int m; + for (m=0;well_known_modules[m].name;m++) { + if (strcmp(modules[i], well_known_modules[m].name) == 0) { + current = well_known_modules[m].init(ldb, options); + if (current == NULL) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); + return -1; + } + DLIST_ADD(ldb->modules, current); + break; } - DLIST_ADD(ldb->modules, current); - continue; } - - if (strcmp(modules[i], "rdn_name") == 0) { - current = rdn_name_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; + if (well_known_modules[m].name == NULL) { + ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", + modules[i]); } - -#ifdef _SAMBA_BUILD_ - if (strcmp(modules[i], "objectguid") == 0) { - current = objectguid_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; - } - - if (strcmp(modules[i], "samldb") == 0) { - current = samldb_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; - } - - if (strcmp(modules[i], "samba3sam") == 0) { - current = ldb_samba3sam_module_init(ldb, options); - if (!current) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]); - return -1; - } - DLIST_ADD(ldb->modules, current); - continue; - } - -#endif - - ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", modules[i]); } talloc_free(modules); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index f371c340cc..73bac2088a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -143,6 +143,10 @@ typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *) struct ldb_module; +/* module initialisation function */ +typedef struct ldb_module *(*ldb_module_init_t)(struct ldb_context *, const char **); + + /* debugging uses one of the following levels */ enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, LDB_DEBUG_WARNING, LDB_DEBUG_TRACE}; -- cgit From 5e7a0fb5349422cfb782c0348f98505011d27391 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 29 Sep 2005 11:51:06 +0000 Subject: r10604: Put in the new registry "patchfile" code (similar to ldif for LDB); not finished yet. (This used to be commit b405b27ba4bf4ddbaff9ca58926d94d1b2fd09f6) --- source4/lib/registry/TODO | 5 +- source4/lib/registry/common/reg_util.c | 40 +- source4/lib/registry/config.mk | 3 +- source4/lib/registry/registry.h | 23 + source4/lib/registry/tools/regdiff.c | 128 +----- source4/lib/registry/tools/regpatch.c | 741 +-------------------------------- source4/lib/registry/tools/regshell.c | 6 +- 7 files changed, 72 insertions(+), 874 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO index 3f48d031e1..518edf6795 100644 --- a/source4/lib/registry/TODO +++ b/source4/lib/registry/TODO @@ -24,12 +24,11 @@ reg_backend_wine.c: regshell: - support for security descriptors - regdiff: - - fix - gregedit.c: - support for editing values / adding values / deleting values - support for adding/deleting keys - support for security descriptors - pass parsed paths around rather then strings (i.e. just a list of strings) +- integrate various registry tools ? +- finish new patchfile code diff --git a/source4/lib/registry/common/reg_util.c b/source4/lib/registry/common/reg_util.c index ae30839cca..75f9d3cf00 100644 --- a/source4/lib/registry/common/reg_util.c +++ b/source4/lib/registry/common/reg_util.c @@ -46,27 +46,27 @@ const char *str_regtype(int type) return "Unknown"; } -char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) +char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data) { char *ret = NULL; - if(v->data.length == 0) return talloc_strdup(mem_ctx, ""); + if(data->length == 0) return talloc_strdup(mem_ctx, ""); - switch (v->data_type) { + switch (type) { case REG_EXPAND_SZ: case REG_SZ: - convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data.data, v->data.length, (void **)&ret); + convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret); return ret; case REG_BINARY: - ret = data_blob_hex_string(mem_ctx, &v->data); + ret = data_blob_hex_string(mem_ctx, data); return ret; case REG_DWORD: - if (*(int *)v->data.data == 0) + if (*(int *)data->data == 0) return talloc_strdup(mem_ctx, "0"); - return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data.data); + return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data); case REG_MULTI_SZ: /* FIXME */ @@ -81,47 +81,51 @@ char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v) char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) { - return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val)); + return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val->data_type, &val->data)); } -BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value) +BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data) { int i; - *value = talloc(mem_ctx, struct registry_value); - (*value)->data_type = -1; + *type = -1; /* Find the correct type */ for (i = 0; reg_value_types[i].name; i++) { if (!strcmp(reg_value_types[i].name, type_str)) { - (*value)->data_type = reg_value_types[i].id; + *type = reg_value_types[i].id; break; } } - if ((*value)->data_type == -1) + if (*type == -1) return False; /* Convert data appropriately */ - switch ((*value)->data_type) + switch (*type) { case REG_SZ: case REG_EXPAND_SZ: - (*value)->data.length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&(*value)->data.data); + data->length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&data->data); break; case REG_DWORD: { uint32_t tmp = strtol(data_str, NULL, 0); - (*value)->data = data_blob_talloc(mem_ctx, &tmp, 4); + *data = data_blob_talloc(mem_ctx, &tmp, 4); } break; case REG_NONE: - ZERO_STRUCT((*value)->data); + ZERO_STRUCT(data); break; + case REG_BINARY: + *data = strhex_to_data_blob(data_str); + talloc_steal(mem_ctx, data->data); + break; + default: - case REG_BINARY: /* FIXME */ + /* FIXME */ return False; } return True; diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index 87e0779007..8a579d4564 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -83,7 +83,8 @@ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ lib/registry/common/reg_util.o \ - lib/registry/reg_samba.o + lib/registry/reg_samba.o \ + lib/registry/patchfile.o REQUIRED_SUBSYSTEMS = \ LIBBASIC # End MODULE registry_ldb diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index 69f3606736..ebfb2caf5c 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -138,4 +138,27 @@ struct reg_init_function_entry { struct reg_init_function_entry *prev, *next; }; +struct reg_diff_value +{ + char *name; + enum { REG_DIFF_DEL_VAL, REG_DIFF_SET_VAL } changetype; + uint32_t type; + DATA_BLOB data; +}; + +struct reg_diff_key +{ + char *name; + enum { REG_DIFF_CHANGE_KEY, REG_DIFF_DEL_KEY } changetype; + uint32_t numvalues; + struct reg_diff_value *values; +}; + +struct reg_diff +{ + char *format; + uint32_t numkeys; + struct reg_diff_key *keys; +}; + #endif /* _REGISTRY_H */ diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 3d8201330e..92fe53ff67 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. simple registry frontend - Copyright (C) Jelmer Vernooij 2004 + Copyright (C) Jelmer Vernooij 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 @@ -24,101 +24,15 @@ #include "lib/registry/registry.h" #include "lib/cmdline/popt_common.h" -static void writediff(struct registry_key *oldkey, struct registry_key *newkey, FILE *out) -{ - int i; - struct registry_key *t1, *t2; - struct registry_value *v1, *v2; - WERROR error1, error2; - TALLOC_CTX *mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2); - if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "-%s\n", t1->path+1); - } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); - return; - } - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) { - error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2); - if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\n[%s]\n", t1->path+1); - } else if(!W_ERROR_IS_OK(error2)) { - DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); - } - writediff(t2, t1, out); - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); - return; - } - - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); - if ((W_ERROR_IS_OK(error2) && data_blob_equal(&v1->data, &v2->data)) - || W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=%s:%s\n", v1->name, str_regtype(v1->data_type), reg_val_data_string(mem_ctx, v1)); - } - - if(!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); - return; - } - - mem_ctx = talloc_init("writediff"); - - for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) { - error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2); - if(W_ERROR_IS_OK(error2)) { - } else if(W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { - fprintf(out, "\"%s\"=-\n", v1->name); - } else { - DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); - } - } - - talloc_free(mem_ctx); - - if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); - return; - } -} - - int main(int argc, char **argv) +int main(int argc, char **argv) { int opt; poptContext pc; char *outputfile = NULL; - FILE *fd = stdout; struct registry_context *h1 = NULL, *h2 = NULL; int from_null = 0; - int i; - WERROR error, error2; + WERROR error; + struct reg_diff *diff; struct poptOption long_options[] = { POPT_AUTOHELP {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, @@ -159,37 +73,13 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, poptFreeContext(pc); - if(outputfile) { - fd = fopen(outputfile, "w+"); - if(!fd) { - fprintf(stderr, "Unable to open '%s'\n", outputfile); - return 1; - } - } - - fprintf(fd, "REGEDIT4\n\n"); - fprintf(fd, "; Generated using regdiff, part of Samba\n"); - - error2 = error = WERR_OK; - - for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) { - struct registry_key *r1, *r2; - error = reg_get_predefined_key(h1, i, &r1); - if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i))); - continue; - } - - error = reg_get_predefined_key(h2, i, &r2); - if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i))); - continue; - } - - writediff(r1, r2, fd); + diff = reg_generate_diff(NULL, h1, h2); + if (!diff) { + fprintf(stderr, "Unable to generate diff between keys\n"); + return -1; } - fclose(fd); + reg_diff_save(diff, outputfile); return 0; } diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index 98e6c0ff5d..eca14741a5 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -2,8 +2,7 @@ Unix SMB/CIFS implementation. simple registry frontend - Copyright (C) 2002, Richard Sharpe, rsharpe@richardsharpe.com - Copyright (C) 2004, Jelmer Vernooij, jelmer@samba.org + Copyright (C) 2004-2005 Jelmer Vernooij, jelmer@samba.org 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 @@ -27,737 +26,14 @@ #include "system/filesys.h" #include "librpc/gen_ndr/winreg.h" -/* - * Routines to parse a REGEDIT4 file - * - * The file consists of: - * - * REGEDIT4 - * \[[-]key-path\]\n - * * - * - * Format: - * [cmd:]name=type:value - * - * cmd = a|d|c|add|delete|change|as|ds|cs - * - * There can be more than one key-path and value-spec. - * - * Since we want to support more than one type of file format, we - * construct a command-file structure that keeps info about the command file - */ - -#define FMT_UNREC -1 -#define FMT_REGEDIT4 0 -#define FMT_EDITREG1_1 1 - -#define FMT_STRING_REGEDIT4 "REGEDIT4" -#define FMT_STRING_EDITREG1_0 "EDITREG1.0" - -#define CMD_NONE 0 -#define CMD_ADD_KEY 1 -#define CMD_DEL_KEY 2 - -#define CMD_KEY 1 -#define CMD_VAL 2 - -typedef struct val_spec_list { - struct val_spec_list *next; - char *name; - int type; - char *val; /* Kept as a char string, really? */ -} VAL_SPEC_LIST; - -typedef struct command_s { - int cmd; - char *key; - int val_count; - VAL_SPEC_LIST *val_spec_list, *val_spec_last; -} CMD; - -typedef struct cmd_line { - int len, line_len; - char *line; -} CMD_LINE; - -static void free_val_spec_list(VAL_SPEC_LIST *vl) -{ - if (!vl) return; - if (vl->name) free(vl->name); - if (vl->val) free(vl->val); - free(vl); - -} - -/* - * Some routines to handle lines of info in the command files - */ -static void skip_to_eol(int fd) -{ - int rc; - char ch = 0; - - while ((rc = read(fd, &ch, 1)) == 1) { - if (ch == 0x0A) return; - } - if (rc < 0) { - DEBUG(0, ("Could not read file descriptor: %d, %s\n", - fd, strerror(errno))); - exit(1); - } -} - -static void free_cmd(CMD *cmd) -{ - if (!cmd) return; - - while (cmd->val_spec_list) { - VAL_SPEC_LIST *tmp; - - tmp = cmd->val_spec_list; - cmd->val_spec_list = tmp->next; - free(tmp); - } - - free(cmd); - -} - -static void free_cmd_line(CMD_LINE *cmd_line) -{ - if (cmd_line) { - if (cmd_line->line) free(cmd_line->line); - free(cmd_line); - } -} - -static void print_line(struct cmd_line *cl) -{ - char *pl; - - if (!cl) return; - - pl = smb_xmalloc(cl->line_len + 1); - - strncpy(pl, cl->line, cl->line_len); - pl[cl->line_len] = 0; - - fprintf(stdout, "%s\n", pl); - free(pl); -} - -#define INIT_ALLOC 10 - -/* - * Read a line from the input file. - * NULL returned when EOF and no chars read - * Otherwise we return a cmd_line * - * Exit if other errors - */ -static struct cmd_line *get_cmd_line(int fd) -{ - CMD_LINE *cl = malloc_p(CMD_LINE); - int i = 0, rc; - uint8_t ch; - - if (!cl) - return NULL; - - cl->len = INIT_ALLOC; - - /* - * Allocate some space for the line. We extend later if needed. - */ - - cl->line = (char *)smb_xmalloc(INIT_ALLOC); - - /* - * Now read in the chars to EOL. Don't store the EOL in the - * line. What about CR? - */ - - while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') { - if (ch == '\r') continue; /* skip CR */ - if (i == cl->len-1) { - /* - * Allocate some more memory - */ - if ((cl->line = realloc(cl->line, cl->len + INIT_ALLOC)) == NULL) { - DEBUG(0, ("Unable to realloc space for line: %s\n", - strerror(errno))); - exit(1); - } - cl->len += INIT_ALLOC; - } - cl->line[i] = ch; - i++; - } - - /* read 0 and we were at loc'n 0, return NULL */ - if (rc == 0 && i == 0) { - free_cmd_line(cl); - return NULL; - } - - cl->line[i] = '\0'; - cl->line_len = i; - - return cl; - -} - -/* - * parse_value: parse out a value. We pull it apart as: - * - * ::= =: - * - * ::= char-string-without-spaces | '"' char-string '"' - * - * If it parsed OK, return the as a string, and the - * value type and value-string in parameters. - * - * The value name can be empty. There can only be one empty name in - * a list of values. A value of - removes the value entirely. - */ - -static char *parse_name(char *nstr) -{ - int len = 0, start = 0; - if (!nstr) return NULL; - - len = strlen(nstr); - - while (len && nstr[len - 1] == ' ') len--; - - nstr[len] = 0; /* Trim any spaces ... if there were none, doesn't matter */ - - /* - * Beginning and end should be '"' or neither should be so - */ - if ((nstr[0] == '"' && nstr[len - 1] != '"') || - (nstr[0] != '"' && nstr[len - 1] == '"')) - return NULL; - - if (nstr[0] == '"') { - start = 1; - len -= 2; - } - - return strndup(&nstr[start], len); -} - -static int parse_value_type(char *tstr) -{ - int len = strlen(tstr); - - while (len && tstr[len - 1] == ' ') len--; - tstr[len] = 0; - - if (strcmp(tstr, "REG_DWORD") == 0) - return REG_DWORD; - else if (strcmp(tstr, "dword") == 0) - return REG_DWORD; - else if (strcmp(tstr, "REG_EXPAND_SZ") == 0) - return REG_EXPAND_SZ; - else if (strcmp(tstr, "REG_BIN") == 0) - return REG_BINARY; - else if (strcmp(tstr, "REG_SZ") == 0) - return REG_SZ; - else if (strcmp(tstr, "REG_MULTI_SZ") == 0) - return REG_MULTI_SZ; - else if (strcmp(tstr, "-") == 0) - return REG_DELETE; - - return 0; -} - -static char *parse_val_str(char *vstr) -{ - - return strndup(vstr, strlen(vstr)); - -} - -static char *parse_value(struct cmd_line *cl, int *vtype, char **val) -{ - char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL; - - if (!cl || !vtype || !val) return NULL; - if (!cl->line[0]) return NULL; - - p1 = strdup(cl->line); - /* FIXME: Better return codes etc ... */ - if (!p1) return NULL; - p2 = strchr(p1, '='); - if (!p2) return NULL; - - *p2 = 0; p2++; /* Split into two strings at p2 */ - - /* Now, parse the name ... */ - - nstr = parse_name(p1); - if (!nstr) goto error; - - /* Now, split the remainder and parse on type and val ... */ - - tstr = p2; - while (*tstr == ' ') tstr++; /* Skip leading white space */ - p2 = strchr(p2, ':'); - - if (p2) { - *p2 = 0; p2++; /* split on the : */ - } - - *vtype = parse_value_type(tstr); - - if (!vtype) goto error; - - if (!p2 || !*p2) return nstr; - - /* Now, parse the value string. It should return a newly malloc'd string */ - - while (*p2 == ' ') p2++; /* Skip leading space */ - vstr = parse_val_str(p2); - - if (!vstr) goto error; - - *val = vstr; - - return nstr; - - error: - if (p1) free(p1); - if (nstr) free(nstr); - if (vstr) free(vstr); - return NULL; -} - -/* - * Parse out a key. Look for a correctly formatted key [...] - * and whether it is a delete or add? A delete is signalled - * by a - in front of the key. - * Assumes that there are no leading and trailing spaces - */ - -static char *parse_key(struct cmd_line *cl, int *cmd) -{ - int start = 1; - char *tmp; - - if (cl->line[0] != '[' || - cl->line[cl->line_len - 1] != ']') return NULL; - if (cl->line_len == 2) return NULL; - *cmd = CMD_ADD_KEY; - if (cl->line[1] == '-') { - if (cl->line_len == 3) return NULL; - start = 2; - *cmd = CMD_DEL_KEY; - } - tmp = smb_xmalloc(cl->line_len - 1 - start + 1); - strncpy(tmp, &cl->line[start], cl->line_len - 1 - start); - tmp[cl->line_len - 1 - start] = 0; - return tmp; -} - -/* - * Parse a line to determine if we have a key or a value - * We only check for key or val ... - */ - -static int parse_line(struct cmd_line *cl) -{ - - if (!cl || cl->len == 0) return 0; - - if (cl->line[0] == '[') /* No further checking for now */ - return CMD_KEY; - else - return CMD_VAL; -} - -/* - * We seek to offset 0, read in the required number of bytes, - * and compare to the correct value. - * We then seek back to the original location - */ -static int regedit4_file_type(int fd) -{ - int cur_ofs = 0; - char desc[9]; - - cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ - if (cur_ofs < 0) { - DEBUG(0, ("Unable to get current offset: (%d) %s\n", cur_ofs, strerror(errno))); - exit(1); /* FIXME */ - } - - if (cur_ofs) { - lseek(fd, 0, SEEK_SET); - } - - if (read(fd, desc, 8) < 8) { - DEBUG(0, ("Unable to read command file format\n")); - exit(2); /* FIXME */ - } - - desc[8] = 0; - - if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) { - if (cur_ofs) { - lseek(fd, cur_ofs, SEEK_SET); - } else { - skip_to_eol(fd); - } - return FMT_REGEDIT4; - } - - return FMT_UNREC; -} - -/* - * Run though the data in the line and strip anything after a comment - * char. - */ -static void strip_comment(struct cmd_line *cl) -{ - int i; - - if (!cl) return; - - for (i = 0; i < cl->line_len; i++) { - if (cl->line[i] == ';') { - cl->line[i] = '\0'; - cl->line_len = i; - return; - } - } -} - -/* - * Get a command ... This consists of possibly multiple lines: - * [key] - * values* - * possibly Empty line - * - * value ::= =':' - * is some path, possibly enclosed in quotes ... - * We alctually look for the next key to terminate a previous key - * if == '-', then it is a delete type. - */ -static CMD *regedit4_get_cmd(int fd) -{ - struct command_s *cmd = NULL; - struct cmd_line *cl = NULL; - struct val_spec_list *vl = NULL; - - cmd = malloc_p(struct command_s); - if (!cmd) - return NULL; - - cmd->cmd = CMD_NONE; - cmd->key = NULL; - cmd->val_count = 0; - cmd->val_spec_list = cmd->val_spec_last = NULL; - while ((cl = get_cmd_line(fd))) { - - /* - * If it is an empty command line, and we already have a key - * then exit from here ... FIXME: Clean up the parser - */ - - if (cl->line_len == 0 && cmd->key) { - free_cmd_line(cl); - break; - } - - strip_comment(cl); /* remove anything beyond a comment char */ - trim_string(cl->line, " \t", " \t"); - - if (!cl->line[0]) { /* An empty line */ - free_cmd_line(cl); - } - else { /* Else, non-empty ... */ - /* - * Parse out the bits ... - */ - switch (parse_line(cl)) { - case CMD_KEY: - if ((cmd->key = parse_key(cl, &cmd->cmd)) == NULL) { - DEBUG(0, ("Error parsing key from line: ")); - print_line(cl); - DEBUG(0, ("\n")); - } - break; - - case CMD_VAL: - /* - * We need to add the value stuff to the list - * There could be a \ on the end which we need to - * handle at some time - */ - vl = malloc_p(struct val_spec_list); - if (!vl) - return NULL; - vl->next = NULL; - vl->val = NULL; - vl->name = parse_value(cl, &vl->type, &vl->val); - if (!vl->name) goto error; - if (cmd->val_spec_list == NULL) { - cmd->val_spec_list = cmd->val_spec_last = vl; - } - else { - cmd->val_spec_last->next = vl; - cmd->val_spec_last = vl; - } - cmd->val_count++; - break; - - default: - DEBUG(0, ("Unrecognized line in command file: \n")); - print_line(cl); - break; - } - } - - } - if (!cmd->cmd) goto error; /* End of file ... */ - - return cmd; - - error: - if (vl) free(vl); - if (cmd) free_cmd(cmd); - return NULL; -} - -static int regedit4_exec_cmd(CMD *cmd) -{ - - return 0; -} - -static int editreg_1_0_file_type(int fd) -{ - int cur_ofs = 0; - char desc[11]; - - cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ - if (cur_ofs < 0) { - DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); - exit(1); /* FIXME */ - } - - if (cur_ofs) { - lseek(fd, 0, SEEK_SET); - } - - if (read(fd, desc, 10) < 10) { - DEBUG(0, ("Unable to read command file format\n")); - exit(2); /* FIXME */ - } - - desc[10] = 0; - - if (strcmp(desc, FMT_STRING_EDITREG1_0) == 0) { - lseek(fd, cur_ofs, SEEK_SET); - return FMT_REGEDIT4; - } - - return FMT_UNREC; -} - -static CMD *editreg_1_0_get_cmd(int fd) +int main(int argc, char **argv) { - return NULL; -} - -static int editreg_1_0_exec_cmd(CMD *cmd) -{ - - return -1; -} - -typedef struct command_ops_s { - int type; - int (*file_type)(int fd); - CMD *(*get_cmd)(int fd); - int (*exec_cmd)(CMD *cmd); -} CMD_OPS; - -static CMD_OPS default_cmd_ops[] = { - {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd}, - {1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd}, - {-1, NULL, NULL, NULL} -}; - -typedef struct command_file_s { - char *name; - int type, fd; - CMD_OPS cmd_ops; -} CMD_FILE; - -/* - * Create a new command file structure - */ - -static CMD_FILE *cmd_file_create(const char *file) -{ - CMD_FILE *tmp; - struct stat sbuf; - int i = 0; - - /* - * Let's check if the file exists ... - * No use creating the cmd_file structure if the file does not exist - */ - - if (stat(file, &sbuf) < 0) { /* Not able to access file */ - DEBUG(0,("Stat on %s failed\n", file)); - return NULL; - } - - tmp = malloc_p(CMD_FILE); - if (!tmp) - return NULL; - - /* - * Let's fill in some of the fields; - */ - - tmp->name = strdup(file); - - if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) { - DEBUG(0,("Error opening %s\n", file)); - free(tmp); - return NULL; - } - - /* - * Now, try to find the format by indexing through the table - */ - while (default_cmd_ops[i].type != -1) { - if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) { - tmp->cmd_ops = default_cmd_ops[i]; - return tmp; - } - i++; - } - - /* - * If we got here, return NULL, as we could not figure out the type - * of command file. - * - * What about errors? - */ - - free(tmp); - DEBUG(0,("Unknown type\n")); - return NULL; -} - -/* - * Extract commands from the command file, and execute them. - * We pass a table of command callbacks for that - */ - -/* FIXME */ - -/* - * Main code from here on ... - */ - -/* - * key print function here ... - */ - -/* - * Sec Desc print functions - */ - -char *str_type(uint8_t type); - -static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd_file_name) -{ - CMD *cmd; - BOOL modified = False; - CMD_FILE *cmd_file = NULL; - TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file"); - struct registry_key *tmp = NULL; - WERROR error; - cmd_file = cmd_file_create(cmd_file_name); - - while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) { - - /* - * Now, apply the requests to the tree ... - */ - switch (cmd->cmd) { - case CMD_ADD_KEY: - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - - /* If we found it, apply the other bits, else create such a key */ - if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) { - DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); - continue; - } - modified = True; - } - - while (cmd->val_count) { - VAL_SPEC_LIST *val = cmd->val_spec_list; - - if (val->type == REG_DELETE) { - error = reg_del_value(tmp, val->name); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error removing value '%s'\n", val->name)); - } - modified = True; - } else { - DATA_BLOB blob; - blob.data = (uint8_t *)val->val; - blob.length = strlen(val->val); - if(!W_ERROR_IS_OK(reg_val_set(tmp, val->name, val->type, blob))) { - DEBUG(0, ("Error adding new value '%s'\n", val->name)); - continue; - } - modified = True; - } - - cmd->val_spec_list = val->next; - free_val_spec_list(val); - cmd->val_count--; - } - - break; - - case CMD_DEL_KEY: - /* - * Any value does not matter ... - * Find the key if it exists, and delete it ... - */ - - error = reg_key_del_abs(r, cmd->key); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to delete key '%s'\n", cmd->key)); - continue; - } - modified = True; - break; - } - } - free_cmd(cmd); - - return modified; -} - - int main(int argc, char **argv) -{ - int opt; + int opt; poptContext pc; const char *patch; struct registry_context *h; const char *remote = NULL; + struct reg_diff *diff; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP @@ -786,10 +62,15 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd } patch = poptGetArg(pc); - if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); - nt_apply_reg_command_file(h, patch); + diff = reg_diff_load(NULL, patch); + if (!diff) { + fprintf(stderr, "Unable to load registry patch from `%s'\n", patch); + return 1; + } + + reg_diff_apply(diff, h); return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 24979943b3..cd67f09c33 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -92,7 +92,7 @@ static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context fprintf(stderr, "Usage: set value-name type value\n"); } else { struct registry_value *val; - if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val)) { + if (reg_string_to_val(mem_ctx, argv[2], argv[3], &val->data_type, &val->data)) { WERROR error = reg_val_set(cur, argv[1], val->data_type, val->data); if (!W_ERROR_IS_OK(error)) { fprintf(stderr, "Error setting value: %s\n", win_errstr(error)); @@ -140,7 +140,7 @@ static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_conte return NULL; } - printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); + printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data)); return NULL; } @@ -159,7 +159,7 @@ static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context } for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) { - printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value)); + printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data)); } return NULL; -- cgit From 9cbafc42ee5cbaae9dfb9d147eefd0e59ff953d0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 29 Sep 2005 12:00:49 +0000 Subject: r10605: Forgot one file... (This used to be commit 441419a08f0845af2b4c8023e1e5bcfda24a6d62) --- source4/lib/registry/patchfile.c | 416 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 source4/lib/registry/patchfile.c (limited to 'source4/lib') diff --git a/source4/lib/registry/patchfile.c b/source4/lib/registry/patchfile.c new file mode 100644 index 0000000000..cdf35c7b70 --- /dev/null +++ b/source4/lib/registry/patchfile.c @@ -0,0 +1,416 @@ +/* + Unix SMB/CIFS implementation. + Reading .REG files + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dynconfig.h" +#include "lib/registry/registry.h" +#include "lib/cmdline/popt_common.h" +#include "system/filesys.h" + +#define DEFAULT_IDENT_STRING "SAMBA4 REGISTRY" + +static struct reg_diff_key *diff_find_add_key(struct reg_diff *diff, const char *path) +{ + int i; + + for (i = 0; diff->numkeys; i++) { + if (!strcasecmp(diff->keys[i].name, path)) + return &diff->keys[i]; + } + + diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2); + diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, path); + diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY; + diff->keys[diff->numkeys].numvalues = 0; + diff->keys[diff->numkeys].values = NULL; + + diff->numkeys++; + return NULL; +} + +/* + * Generate difference between two keys + */ +static WERROR reg_generate_diff_key(struct reg_diff *diff, struct registry_key *oldkey, struct registry_key *newkey) +{ + int i; + struct registry_key *t1, *t2; + struct registry_value *v1, *v2; + WERROR error1, error2; + TALLOC_CTX *mem_ctx = talloc_init("writediff"); + + /* Subkeys that were deleted */ + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2); + + if (W_ERROR_IS_OK(error2)) + continue; + + if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); + return error2; + } + + /* newkey didn't have such a subkey, add del diff */ + diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2); + diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path); + diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY; + diff->numkeys++; + } + + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); + talloc_free(mem_ctx); + return error1; + } + + /* Subkeys that were added */ + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) { + error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2); + + if (W_ERROR_IS_OK(error2)) + continue; + + if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2))); + return error2; + } + + /* oldkey didn't have such a subkey, add add diff */ + diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2); + diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path); + diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY; + diff->keys[diff->numkeys].numvalues = 0; + diff->keys[diff->numkeys].values = NULL; + diff->numkeys++; + + reg_generate_diff_key(diff, t1, t2); + } + + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1))); + talloc_free(mem_ctx); + return error1; + } + + /* Values that were changed */ + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) { + struct reg_diff_key *thiskey = NULL; + error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2); + + if(!W_ERROR_IS_OK(error2) && + !W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); + return error2; + } + + if (W_ERROR_IS_OK(error2) && data_blob_equal(&v1->data, &v2->data)) + continue; + + thiskey = diff_find_add_key(diff, oldkey->path); + thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2); + thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name); + thiskey->values[thiskey->numvalues].type = v2->data_type; + thiskey->values[thiskey->numvalues].changetype = REG_DIFF_SET_VAL; + thiskey->values[thiskey->numvalues].data = data_blob_dup_talloc(thiskey->values, &v2->data); + thiskey->numvalues++; + } + + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); + talloc_free(mem_ctx); + return error1; + } + + /* Values that were deleted */ + for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) { + struct reg_diff_key *thiskey = NULL; + error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2); + + if (W_ERROR_IS_OK(error2)) + continue; + + if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) { + DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2))); + return error2; + } + + thiskey = diff_find_add_key(diff, oldkey->path); + thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2); + thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name); + thiskey->values[thiskey->numvalues].changetype = REG_DIFF_DEL_VAL; + thiskey->numvalues++; + } + + if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) { + DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1))); + talloc_free(mem_ctx); + return error1; + } + + talloc_free(mem_ctx); + return WERR_OK; +} + +/* + * Generate diff between two registry contexts + */ +struct reg_diff *reg_generate_diff(TALLOC_CTX *mem_ctx, struct registry_context *ctx1, struct registry_context *ctx2) +{ + struct reg_diff *diff = talloc_zero(mem_ctx, struct reg_diff); + int i; + WERROR error; + + for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) { + struct registry_key *r1, *r2; + error = reg_get_predefined_key(ctx1, i, &r1); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i))); + continue; + } + + error = reg_get_predefined_key(ctx2, i, &r2); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i))); + continue; + } + + reg_generate_diff_key(diff, r1, r2); + } + + return diff; +} + +/* + * Save registry diff + */ +WERROR reg_diff_save(const struct reg_diff *diff, const char *filename) +{ + int xf, i, j; + + if (filename) { + xf = open(filename, O_CREAT, 0755); + if (xf == -1) { + DEBUG(0, ("Unable to open %s\n", filename)); + return WERR_BADFILE; + } + } else + xf = STDIN_FILENO; + + fdprintf(xf, "%s\n\n", diff->format?diff->format:DEFAULT_IDENT_STRING); + + for (i = 0; i < diff->numkeys; i++) { + if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) { + fdprintf(xf, "-%s\n\n", diff->keys[i].name); + continue; + } + + fdprintf(xf, "[%s]\n", diff->keys[i].name); + + for (j = 0; j < diff->keys[i].numvalues; j++) { + fdprintf(xf, "\"%s\"=", diff->keys[i].values[j].name); + switch (diff->keys[i].values[j].changetype) { + case REG_DIFF_DEL_VAL: + fdprintf(xf, "-\n"); + break; + case REG_DIFF_SET_VAL: + fdprintf(xf, "%s:%s\n", + str_regtype(diff->keys[i].values[j].type), + reg_val_data_string(NULL, + diff->keys[i].values[j].type, + &diff->keys[i].values[j].data)); + break; + } + } + + fdprintf(xf, "\n"); + } + + close(xf); + + return WERR_OK; +} + +/* + * Load diff file + */ +struct reg_diff *reg_diff_load(TALLOC_CTX *ctx, const char *fn) +{ + struct reg_diff *diff; + int fd; + char *line, *p, *q; + struct reg_diff_key *curkey; + struct reg_diff_value *curval; + + fd = open(fn, O_RDONLY, 0); + if (fd == -1) { + DEBUG(0, ("Error opening registry patch file `%s'\n", fn)); + return NULL; + } + + diff = talloc_zero(ctx, struct reg_diff); + if (diff == NULL) { + close(fd); + return NULL; + } + + diff->format = afdgets(fd, diff, 0); + if (!diff->format) { + talloc_free(diff); + close(fd); + return NULL; + } + + while ((line = afdgets(fd, diff, 0))) { + /* Ignore comments and empty lines */ + if (strlen(line) == 0 || line[0] == ';') { + curkey = NULL; + talloc_free(line); + continue; + } + + /* Start of key */ + if (line[0] == '[') { + p = strchr_m(line, ']'); + if (p[strlen(p)-2] != ']') { + DEBUG(0, ("Malformed line\n")); + return NULL; + } + diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2); + diff->keys[diff->numkeys].name = talloc_strndup(diff->keys, line+1, strlen(line)-2); + diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY; + diff->keys[diff->numkeys].numvalues = 0; + diff->keys[diff->numkeys].values = NULL; + curkey = &diff->keys[diff->numkeys]; + diff->numkeys++; + talloc_free(line); + continue; + } + + /* Deleting key */ + if (line[0] == '-') { + diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2); + diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, line+1); + diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY; + diff->numkeys++; + talloc_free(line); + continue; + } + + /* Deleting/Changing value */ + p = strchr_m(line, '='); + if (p == NULL) { + DEBUG(0, ("Malformed line\n")); + talloc_free(line); + continue; + } + + *p = '\0'; p++; + + if (curkey == NULL) { + DEBUG(0, ("Value change without key\n")); + talloc_free(line); + continue; + } + + curkey->values = talloc_realloc(diff->keys, curkey->values, struct reg_diff_value, curkey->numvalues+2); + curval = &curkey->values[curkey->numvalues]; + curkey->numvalues++; + curval->name = talloc_strdup(curkey->values, line); + + /* Delete value */ + if (strcmp(p, "-")) { + curval->changetype = REG_DIFF_DEL_VAL; + talloc_free(line); + continue; + } + + q = strchr_m(p, ':'); + if (q) { + *q = '\0'; + q++; + } + + curval->changetype = REG_DIFF_SET_VAL; + reg_string_to_val(curkey->values, q?p:"REG_SZ", q?q:p, &curval->type, &curval->data); + + talloc_free(line); + } + + close(fd); + + return diff; +} + +/* + * Apply diff to a registry context + */ +BOOL reg_diff_apply (const struct reg_diff *diff, struct registry_context *ctx) +{ + TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file"); + struct registry_key *tmp = NULL; + WERROR error; + int i, j; + + for (i = 0; i < diff->numkeys; i++) { + if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) { + error = reg_key_del_abs(ctx, diff->keys[i].name); + + if(!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to delete key '%s'\n", diff->keys[i].name)); + return False; + } + + continue; + } + + /* Add / change key */ + error = reg_open_key_abs(mem_ctx, ctx, diff->keys[i].name, &tmp); + + /* If we found it, apply the other bits, else create such a key */ + if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { + if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, ctx, diff->keys[i].name, 0, NULL, &tmp))) { + DEBUG(0, ("Error adding new key '%s'\n", diff->keys[i].name)); + return False; + } + } + + for (j = 0; j < diff->keys[i].numvalues; j++) { + if (diff->keys[i].values[j].changetype == REG_DIFF_DEL_VAL) { + error = reg_del_value(tmp, diff->keys[i].values[j].name); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error deleting value '%s'\n", diff->keys[i].values[j].name)); + return False; + } + + error = reg_val_set(tmp, diff->keys[i].values[j].name, + diff->keys[i].values[j].type, + diff->keys[i].values[j].data); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Error setting value '%s'\n", diff->keys[i].values[j].name)); + return False; + } + } + } + } + + return True; +} -- cgit From 588abdba90c9abae3c8ecf5eb45764bbc447b229 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 30 Sep 2005 03:42:07 +0000 Subject: r10641: fixed the error handling on search errors in the ildap backend (This used to be commit e80d42933fe3cbc18cb229e47fffb9ca8068aca5) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index ffb812acd0..499ce054d0 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -166,6 +166,7 @@ static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, 0, &ldapres); talloc_free(search_base); if (!NT_STATUS_IS_OK(ildb->last_rc)) { + ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); return -1; } -- cgit From ecbf28630ef0fbd91838001e03f8c6d29a8d4232 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 30 Sep 2005 23:10:20 +0000 Subject: r10664: Include limits.h in replace.h for HOST_NAME_MAX (This used to be commit dc3dc796746de672dbf3ad0e4715e8b30ae4afb7) --- source4/lib/replace/replace.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 3ad348517d..572113af8c 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -80,6 +80,14 @@ unsigned long strtoul(const char *nptr, char **endptr, int base); int setenv(const char *name, const char *value, int overwrite); #endif +#ifndef HAVE_RENAME +int rename(const char *zfrom, const char *zto); +#endif + +#ifndef HAVE_FTRUNCATE +int ftruncate(int f,long l); +#endif + #ifndef HAVE_VASPRINTF_DECL int vasprintf(char **ptr, const char *format, va_list ap); #endif @@ -132,13 +140,26 @@ int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); typedef int (*comparison_fn_t)(const void *, const void *); #endif +/* Load header file for dynamic linking stuff */ #ifdef HAVE_DLFCN_H #include #endif +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + #ifndef HAVE_SECURE_MKSTEMP #define mkstemp(path) rep_mkstemp(path) int rep_mkstemp(char *temp); #endif +#ifdef HAVE_LIMITS_H +#include +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 64 +#endif + #endif -- cgit From b1ee0c2fa4c4e0a044694a03002dbe320ec8977e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 30 Sep 2005 23:14:30 +0000 Subject: r10665: fixed some crash errors and an error encoding AND and OR operations in the expression parsing code (This used to be commit 0d4a900ce5705856d61c6dd4ccb8fdbd049d22b7) --- source4/lib/ldb/common/ldb_parse.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 83fcc73941..f43d7a7c7a 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -354,6 +354,11 @@ static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char **s) switch (filtertype) { + case LDB_OP_PRESENT: + ret->operation = LDB_OP_PRESENT; + ret->u.present.attr = attr; + break; + case LDB_OP_EQUALITY: if (strcmp(value, "*") == 0) { @@ -615,6 +620,11 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) */ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) { + /* allowing NULL makes the _bytree() searches easier */ + if (s == NULL) { + return NULL; + } + while (isspace((unsigned char)*s)) s++; if (*s == '(') { @@ -633,10 +643,14 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) char *s, *s2, *ret; int i; + if (tree == NULL) { + return NULL; + } + switch (tree->operation) { case LDB_OP_AND: case LDB_OP_OR: - ret = talloc_asprintf(mem_ctx, "(%c", (char)tree->operation); + ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|'); if (ret == NULL) return NULL; for (i=0;iu.list.num_elements;i++) { s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]); @@ -707,8 +721,7 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) talloc_free(s); return ret; case LDB_OP_PRESENT: - ret = talloc_strdup(mem_ctx, "*"); - if (ret == NULL) return NULL; + ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr); return ret; case LDB_OP_APPROX: s = ldb_binary_encode(mem_ctx, tree->u.equality.value); -- cgit From a788d01b871a7e5813ac3934bcb0ba33fe711aa2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 30 Sep 2005 23:46:41 +0000 Subject: r10666: - reverse the ildap ldb backend so tree based searches go through directly, and expression based searches are converted to trees. This makes for less conversions. - allow the caller to supply a set of credentials via the ldb opaque name 'credentials'. I will be using this in my ldb proxy module. (This used to be commit af24f3d7faac6ef74feef73a23345d8c484da07c) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 50 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 499ce054d0..5ea49a8216 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -125,11 +125,11 @@ static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn) static void ildb_rootdse(struct ldb_module *module); /* - search for matching records + search for matching records using a ldb_parse_tree */ -static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) +static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { struct ildb_private *ildb = module->private_data; int count, i; @@ -158,12 +158,8 @@ static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, return -1; } - if (expression == NULL || expression[0] == '\0') { - expression = "objectClass=*"; - } - - ildb->last_rc = ildap_search(ildb->ldap, search_base, scope, expression, attrs, - 0, &ldapres); + ildb->last_rc = ildap_search_bytree(ildb->ldap, search_base, scope, tree, attrs, + 0, &ldapres); talloc_free(search_base); if (!NT_STATUS_IS_OK(ildb->last_rc)) { ldb_set_errstring(module, talloc_strdup(module, ldap_errstr(ildb->ldap, ildb->last_rc))); @@ -217,22 +213,25 @@ failed: /* - search for matching records using a ldb_parse_tree + search for matching records */ -static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) +static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, const char *expression, + const char * const *attrs, struct ldb_message ***res) { struct ildb_private *ildb = module->private_data; - char *expression; int ret; + struct ldb_parse_tree *tree; - expression = ldb_filter_from_tree(ildb, tree); - if (expression == NULL) { - return -1; + if (expression == NULL || expression[0] == '\0') { + expression = "objectClass=*"; } - ret = ildb_search(module, base, scope, expression, attrs, res); - talloc_free(expression); + + tree = ldb_parse_tree(ildb, expression); + + ret = ildb_search_bytree(module, base, scope, tree, attrs, res); + + talloc_free(tree); return ret; } @@ -428,6 +427,7 @@ int ildb_connect(struct ldb_context *ldb, const char *url, { struct ildb_private *ildb = NULL; NTSTATUS status; + struct cli_credentials *creds; ildb = talloc(ldb, struct ildb_private); if (!ildb) { @@ -460,8 +460,14 @@ int ildb_connect(struct ldb_context *ldb, const char *url, ldb->modules->private_data = ildb; ldb->modules->ops = &ildb_ops; - if (cmdline_credentials != NULL && cli_credentials_authentication_requested(cmdline_credentials)) { - status = ldap_bind_sasl(ildb->ldap, cmdline_credentials); + /* caller can optionally setup credentials using the opaque token 'credentials' */ + creds = ldb_get_opaque(ldb, "credentials"); + if (creds == NULL) { + creds = cmdline_credentials; + } + + if (creds != NULL && cli_credentials_authentication_requested(creds)) { + status = ldap_bind_sasl(ildb->ldap, creds); if (!NT_STATUS_IS_OK(status)) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n", ldap_errstr(ildb->ldap, status)); -- cgit From 5ed07022b04bdbb42b7404146c7978b5de0745c0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 30 Sep 2005 23:47:40 +0000 Subject: r10667: cope with a NULL tree for base searches in ldb_search() (This used to be commit 26ff53857802ae4a63f2b6e46c9caa7ca2fbbe89) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 9af62c7754..574d9485f8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -501,6 +501,17 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, if ((base == NULL || base->comp_num == 0) && (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; + /* check if we are looking for a simple dn */ + if (scope == LDB_SCOPE_BASE && tree == NULL) { + return ltdb_search_dn(module, base, attrs, res); + } + + if (tree == NULL) { + char *err_string = talloc_strdup(module, "expression parse failed"); + if (err_string) ldb_set_errstring(module, err_string); + return -1; + } + /* it is important that we handle dn queries this way, and not via a full db search, otherwise ldb is horribly slow */ if (tree->operation == LDB_OP_EQUALITY && @@ -553,18 +564,7 @@ int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, if ((base == NULL || base->comp_num == 0) && (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; - /* check if we are looking for a simple dn */ - if (scope == LDB_SCOPE_BASE && (expression == NULL || expression[0] == '\0')) { - ret = ltdb_search_dn(module, base, attrs, res); - return ret; - } - tree = ldb_parse_tree(ltdb, expression); - if (tree == NULL) { - char *err_string = talloc_strdup(module, "expression parse failed"); - if (err_string) ldb_set_errstring(module, err_string); - return -1; - } ret = ltdb_search_bytree(module, base, scope, tree, attrs, res); talloc_free(tree); -- cgit From e264c8b6dd207862a618627ef288e3ca0a33fe0f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Oct 2005 14:29:08 +0000 Subject: r10678: Add debug helper Fix push for non-fixed length strings (This used to be commit 821b0bb56f6d6b9df7bbdeeddc206505f3f0a7c2) --- source4/lib/tdr/tdr.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index 34611683e2..4a8d05a8ab 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -170,6 +170,10 @@ NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, { ssize_t ret, required; + if (length == -1) { + length = strlen(*v) + 1; /* Extra element for null character */ + } + required = el_size * length; TDR_PUSH_NEED_BYTES(tdr, required); @@ -392,3 +396,21 @@ NTSTATUS tdr_push_to_fd(int fd, tdr_push_fn_t push_fn, const void *p) return NT_STATUS_OK; } + +void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) +{ + va_list ap; + char *s = NULL; + int i; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + for (i=0;ilevel;i++) { + DEBUG(0,(" ")); + } + + DEBUG(0,("%s\n", s)); + free(s); +} -- cgit From faf2ad667a8f973a6422c44fa7431c2fb6e4d82d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 3 Oct 2005 14:24:53 +0000 Subject: r10684: Add a nasty hack for the failure case of wbinfo -t. Tridge has a proper fix for it pending. Also fix a bug with timed events: Don't call the same event recursively in the handler's inner semi-async event loop. Volker (This used to be commit e38e50127a3414461578421e676a9c58c106c272) --- source4/lib/events/events_standard.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 8fe8d009bf..146dbc6b22 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -347,9 +347,17 @@ static void std_event_loop_timer(struct event_context *ev) /* deny the handler to free the event */ talloc_set_destructor(te, std_event_timed_deny_destructor); + + /* We need to remove the timer from the list before calling the + * handler because in a semi-async inner event loop called from the + * handler we don't want to come across this event again -- vl */ + DLIST_REMOVE(std_ev->timed_events, te); + te->handler(ev, te, t, te->private_data); - talloc_set_destructor(te, std_event_timed_destructor); + /* The destructor isn't necessary anymore, we've already removed the + * event from the list. */ + talloc_free(te); } -- cgit From 4a34e81ccc609366089d9a3f6c3a04c228cac8b3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 3 Oct 2005 17:36:10 +0000 Subject: r10690: Fix a bug that metze pointed out: Leaving the "rejecting" destructor around prevents the memory from being freed. Thanks, Volker (This used to be commit df8eeb01f498568207a4a8d5d12348c473f41799) --- source4/lib/events/events_standard.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 146dbc6b22..d521ffa344 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -357,6 +357,7 @@ static void std_event_loop_timer(struct event_context *ev) /* The destructor isn't necessary anymore, we've already removed the * event from the list. */ + talloc_set_destructor(te, NULL); talloc_free(te); } -- cgit From 1a3651693517332c0c15111b871c65f2411a35ae Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 3 Oct 2005 23:39:59 +0000 Subject: r10695: strupper() of NULL should be NULL, not panic. Andrew Bartlett (This used to be commit b1bcc0dc0b3c6d4d931100dee21ba16cb5521978) --- source4/lib/util_str.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c index 685cc52c65..ba952df9f6 100644 --- a/source4/lib/util_str.c +++ b/source4/lib/util_str.c @@ -705,6 +705,10 @@ char *strupper_talloc(TALLOC_CTX *ctx, const char *src) { size_t size=0; char *dest; + + if (!src) { + return NULL; + } /* this takes advantage of the fact that upper/lower can't change the length of a character by more than 1 byte */ -- cgit From 63d4cb48029e8bd607604e40bbbc46d20d917d80 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Oct 2005 05:41:05 +0000 Subject: r10708: a bit more error checking in the idap ldb backend (This used to be commit 63ebaad393e38b28c8f97f33e2b22f2445733405) --- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 5ea49a8216..4ff8723d44 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -155,6 +155,11 @@ static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *ba search_base = ldb_dn_linearize(ildb, base); } if (search_base == NULL) { + ldb_set_errstring(module, talloc_asprintf(module, "Unable to determine baseDN")); + return -1; + } + if (tree == NULL) { + ldb_set_errstring(module, talloc_asprintf(module, "Invalid expression parse tree")); return -1; } -- cgit From 7838e13e917041fa3786eaa442765ab88b9f0039 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 5 Oct 2005 06:32:00 +0000 Subject: r10726: fix to talloc_parent() from Michael O'Brien (This used to be commit f31a2376f3fef1cc2b40b37fb4d94a4b67eec6d4) --- source4/lib/talloc/talloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 6af08a2ac9..d2de2ecde0 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -162,7 +162,7 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr) void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return TC_PTR_FROM_CHUNK(tc); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } /* -- cgit From 5fd031c97daaa1bf09a7ad80550753acd434075f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 05:24:46 +0000 Subject: r10753: don't require every ldb module to implement both a search_bytree() and a search() function, instead each module now only implements the bytree method, and the expression based search is handled generically by the modules code. This makes for more consistency and less code duplication. fixed the tdb backend to handle BASE searches much more efficiently. They now always only lookup one record, regardless of the search expression (This used to be commit 7e44f9153c5578624e2fca04cdc0a00af0fd9eb4) --- source4/lib/ldb/common/ldb.c | 16 ++++++++-- source4/lib/ldb/common/ldb_modules.c | 34 +++++++++++++-------- source4/lib/ldb/common/ldb_parse.c | 5 ++- source4/lib/ldb/include/ldb_private.h | 10 +++--- source4/lib/ldb/ldb_ildap/ldb_ildap.c | 29 ++---------------- source4/lib/ldb/ldb_ldap/ldb_ldap.c | 51 +++++++++++++------------------ source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 40 +----------------------- source4/lib/ldb/ldb_tdb/ldb_index.c | 16 ++++++++-- source4/lib/ldb/ldb_tdb/ldb_search.c | 35 +-------------------- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 1 - source4/lib/ldb/ldb_tdb/ldb_tdb.h | 3 -- source4/lib/ldb/modules/ldb_map.c | 37 +++++----------------- source4/lib/ldb/modules/rdn_name.c | 13 ++------ source4/lib/ldb/modules/schema.c | 8 ----- source4/lib/ldb/modules/skel.c | 7 ++--- source4/lib/ldb/modules/timestamps.c | 9 ------ 16 files changed, 95 insertions(+), 219 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index a743b2f584..29ee323ad4 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -172,13 +172,23 @@ int ldb_search(struct ldb_context *ldb, const char *expression, const char * const *attrs, struct ldb_message ***res) { - ldb_reset_err_string(ldb); + struct ldb_parse_tree *tree; + int ret; + + tree = ldb_parse_tree(ldb, expression); + if (tree == NULL) { + ldb_set_errstring(ldb->modules, talloc_strdup(ldb, "Unable to parse search expression")); + return -1; + } + + ret = ldb_search_bytree(ldb, base, scope, tree, attrs, res); + talloc_free(tree); - return ldb->modules->ops->search(ldb->modules, base, scope, expression, attrs, res); + return ret; } /* - search the database given a LDAP-like search expression + search the database given a search tree return the number of records found, or -1 on error diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 9c536789b9..2885d46b37 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -133,6 +133,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { "objectguid", objectguid_module_init }, { "samldb", samldb_module_init }, { "samba3sam", ldb_samba3sam_module_init }, + { "proxy", proxy_module_init }, #endif { NULL, NULL } }; @@ -170,7 +171,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return -1; } if (ret > 1) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n"); + ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out\n", ret); talloc_free(msg); return -1; } @@ -215,6 +216,17 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) /* helper functions to call the next module in chain */ +int ldb_next_search_bytree(struct ldb_module *module, + const struct ldb_dn *base, + enum ldb_scope scope, + struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) +{ + if (!module->next) { + return -1; + } + return module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); +} int ldb_next_search(struct ldb_module *module, const struct ldb_dn *base, @@ -222,24 +234,22 @@ int ldb_next_search(struct ldb_module *module, const char *expression, const char * const *attrs, struct ldb_message ***res) { + struct ldb_parse_tree *tree; + int ret; if (!module->next) { return -1; } - return module->next->ops->search(module->next, base, scope, expression, attrs, res); -} - -int ldb_next_search_bytree(struct ldb_module *module, - const struct ldb_dn *base, - enum ldb_scope scope, - struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - if (!module->next) { + tree = ldb_parse_tree(module, expression); + if (tree == NULL) { + ldb_set_errstring(module, talloc_strdup(module, "Unable to parse search expression")); return -1; } - return module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); + ret = module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); + talloc_free(tree); + return ret; } + int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message) { if (!module->next) { diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index f43d7a7c7a..95110bfd00 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -620,9 +620,8 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) */ struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) { - /* allowing NULL makes the _bytree() searches easier */ - if (s == NULL) { - return NULL; + if (s == NULL || *s == 0) { + s = "(|(objectClass=*)(dn=*))"; } while (isspace((unsigned char)*s)) s++; diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 2a9139df40..9777ad0d92 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -56,8 +56,6 @@ struct ldb_module { */ struct ldb_module_ops { const char *name; - int (*search)(struct ldb_module *, const struct ldb_dn *, enum ldb_scope, - const char *, const char * const [], struct ldb_message ***); int (*search_bytree)(struct ldb_module *, const struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const [], struct ldb_message ***); int (*add_record)(struct ldb_module *, const struct ldb_message *); @@ -126,10 +124,10 @@ typedef struct ldb_module *(*ldb_module_init_function)(struct ldb_context *ldb, int ldb_load_modules(struct ldb_context *ldb, const char *options[]); int ldb_next_search(struct ldb_module *module, - const struct ldb_dn *base, - enum ldb_scope scope, - const char *expression, - const char * const *attrs, struct ldb_message ***res); + const struct ldb_dn *base, + enum ldb_scope scope, + const char *expression, + const char * const *attrs, struct ldb_message ***res); int ldb_next_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 4ff8723d44..ad316bb0a2 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -217,30 +217,6 @@ failed: } -/* - search for matching records -*/ -static int ildb_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - struct ildb_private *ildb = module->private_data; - int ret; - struct ldb_parse_tree *tree; - - if (expression == NULL || expression[0] == '\0') { - expression = "objectClass=*"; - } - - tree = ldb_parse_tree(ildb, expression); - - ret = ildb_search_bytree(module, base, scope, tree, attrs, res); - - talloc_free(tree); - return ret; -} - - /* convert a ldb_message structure to a list of ldap_mod structures ready for ildap_add() or ildap_modify() @@ -394,7 +370,6 @@ static int ildb_del_trans(struct ldb_module *module) static const struct ldb_module_ops ildb_ops = { .name = "ldap", - .search = ildb_search, .search_bytree = ildb_search_bytree, .add_record = ildb_add, .modify_record = ildb_modify, @@ -415,7 +390,9 @@ static void ildb_rootdse(struct ldb_module *module) struct ldb_message **res = NULL; struct ldb_dn *empty_dn = ldb_dn_new(ildb); int ret; - ret = ildb_search(module, empty_dn, LDB_SCOPE_BASE, "dn=dc=rootDSE", NULL, &res); + ret = ildb_search_bytree(module, empty_dn, LDB_SCOPE_BASE, + ldb_parse_tree(empty_dn, "dn=dc=rootDSE"), + NULL, &res); if (ret == 1) { ildb->rootDSE = talloc_steal(ildb, res[0]); } diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 1d1dd66e84..268e2b0291 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -174,15 +174,16 @@ static int lldb_add_msg_attr(struct ldb_context *ldb, /* search for matching records */ -static int lldb_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) +static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { struct ldb_context *ldb = module->ldb; struct lldb_private *lldb = module->private_data; - int count, msg_count; + int count, msg_count, ldap_scope; char *search_base; LDAPMessage *ldapres, *msg; + char *expression; search_base = ldb_dn_linearize(ldb, base); if (base == NULL) { @@ -192,11 +193,25 @@ static int lldb_search(struct ldb_module *module, const struct ldb_dn *base, return -1; } - if (expression == NULL || expression[0] == '\0') { - expression = "objectClass=*"; + expression = ldb_filter_from_tree(search_base, tree); + if (expression == NULL) { + talloc_free(search_base); + return -1; + } + + switch (scope) { + case LDB_SCOPE_BASE: + ldap_scope = LDAP_SCOPE_BASE; + break; + case LDB_SCOPE_ONELEVEL: + ldap_scope = LDAP_SCOPE_ONELEVEL; + break; + default: + ldap_scope = LDAP_SCOPE_SUBTREE; + break; } - lldb->last_rc = ldap_search_s(lldb->ldap, search_base, (int)scope, + lldb->last_rc = ldap_search_s(lldb->ldap, search_base, ldap_scope, expression, discard_const_p(char *, attrs), 0, &ldapres); @@ -287,27 +302,6 @@ failed: } -/* - search for matching records using a ldb_parse_tree -*/ -static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) -{ - struct lldb_private *lldb = module->private_data; - char *expression; - int ret; - - expression = ldb_filter_from_tree(lldb, tree); - if (expression == NULL) { - return -1; - } - ret = lldb_search(module, base, scope, expression, attrs, res); - talloc_free(expression); - return ret; -} - - /* convert a ldb_message structure to a list of LDAPMod structures ready for ldap_add() or ldap_modify() @@ -478,7 +472,6 @@ static int lldb_del_trans(struct ldb_module *module) static const struct ldb_module_ops lldb_ops = { .name = "ldap", - .search = lldb_search, .search_bytree = lldb_search_bytree, .add_record = lldb_add, .modify_record = lldb_modify, diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 052b10f245..1054722178 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -822,7 +822,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d int ret, i; /* create a local ctx */ - local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_search_by_tree local context"); + local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_search_bytree local context"); if (local_ctx == NULL) { return -1; } @@ -990,43 +990,6 @@ failed: return -1; } -/* search for matching records, by expression */ -static int lsqlite3_search(struct ldb_module * module, const struct ldb_dn *basedn, - enum ldb_scope scope, const char * expression, - const char * const *attrs, struct ldb_message *** res) -{ - struct ldb_parse_tree * tree; - int ret; - - /* Handle tdb specials */ - if (ldb_dn_is_special(basedn)) { -#warning "handle tdb specials" - return 0; - } - -#if 0 -/* (|(objectclass=*)(dn=*)) is passed by the command line tool now instead */ - /* Handle the special case of requesting all */ - if (pExpression != NULL && *pExpression == '\0') { - pExpression = "dn=*"; - } -#endif - - /* Parse the filter expression into a tree we can work with */ - if ((tree = ldb_parse_tree(module->ldb, expression)) == NULL) { - return -1; - } - - /* Now use the bytree function for the remainder of processing */ - ret = lsqlite3_search_bytree(module, basedn, scope, tree, attrs, res); - - /* Free the parse tree */ - talloc_free(tree); - - /* All done. */ - return ret; -} - /* add a record */ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg) @@ -1820,7 +1783,6 @@ destructor(void *p) */ static const struct ldb_module_ops lsqlite3_ops = { .name = "sqlite", - .search = lsqlite3_search, .search_bytree = lsqlite3_search_bytree, .add_record = lsqlite3_add, .modify_record = lsqlite3_modify, diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index f78d840206..c2a4fb1ea8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -676,7 +676,8 @@ int ltdb_search_indexed(struct ldb_module *module, struct dn_list *dn_list; int ret; - if (ltdb->cache->indexlist->num_elements == 0) { + if (ltdb->cache->indexlist->num_elements == 0 && + scope != LDB_SCOPE_BASE) { /* no index list? must do full search */ return -1; } @@ -686,7 +687,18 @@ int ltdb_search_indexed(struct ldb_module *module, return -1; } - ret = ltdb_index_dn(module, tree, ltdb->cache->indexlist, dn_list); + if (scope == LDB_SCOPE_BASE) { + /* with BASE searches only one DN can match */ + char *dn = ldb_dn_linearize(dn_list, base); + if (dn == NULL) { + return -1; + } + dn_list->count = 1; + dn_list->dn = &dn; + ret = 1; + } else { + ret = ltdb_index_dn(module, tree, ltdb->cache->indexlist, dn_list); + } if (ret == 1) { /* we've got a candidate list - now filter by the full tree diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 574d9485f8..eb89753007 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -95,7 +95,7 @@ static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *r for (i=0;inum_elements;i++) { const struct ldb_attrib_handler *h; h = ldb_attrib_handler(ldb, msg->elements[i].name); - if (ldb_dn_is_special(msg->dn) && (h->flags & LDB_ATTR_FLAG_HIDDEN)) { + if (h->flags & LDB_ATTR_FLAG_HIDDEN) { continue; } if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { @@ -501,17 +501,6 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, if ((base == NULL || base->comp_num == 0) && (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; - /* check if we are looking for a simple dn */ - if (scope == LDB_SCOPE_BASE && tree == NULL) { - return ltdb_search_dn(module, base, attrs, res); - } - - if (tree == NULL) { - char *err_string = talloc_strdup(module, "expression parse failed"); - if (err_string) ldb_set_errstring(module, err_string); - return -1; - } - /* it is important that we handle dn queries this way, and not via a full db search, otherwise ldb is horribly slow */ if (tree->operation == LDB_OP_EQUALITY && @@ -549,25 +538,3 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, } -/* - search the database with a LDAP-like expression. - choses a search method -*/ -int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const attrs[], struct ldb_message ***res) -{ - struct ltdb_private *ltdb = module->private_data; - struct ldb_parse_tree *tree; - int ret; - - if ((base == NULL || base->comp_num == 0) && - (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; - - tree = ldb_parse_tree(ltdb, expression); - - ret = ltdb_search_bytree(module, base, scope, tree, attrs, res); - talloc_free(tree); - return ret; -} - diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 701ed602ce..22360ffb1c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -702,7 +702,6 @@ static int ltdb_del_trans(struct ldb_module *module) static const struct ldb_module_ops ltdb_ops = { .name = "tdb", - .search = ltdb_search, .search_bytree = ltdb_search_bytree, .add_record = ltdb_add, .modify_record = ltdb_modify, diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index c16db67e1f..2819d865d3 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -83,9 +83,6 @@ int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg, const char * const attrs[], int *count, struct ldb_message ***res); -int ltdb_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const attrs[], struct ldb_message ***res); int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const attrs[], struct ldb_message ***res); diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 1133991ac4..1da1ef661a 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -744,9 +744,9 @@ static int map_delete(struct ldb_module *module, const struct ldb_dn *dn) } /* search fallback database */ -static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) +static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { int ret; struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; @@ -771,7 +771,7 @@ static int map_search_bytree_fb(struct ldb_module *module, const struct ldb_dn * } /* Search in the database against which we are mapping */ -static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn *base, +static int map_search_mp(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { @@ -869,14 +869,14 @@ static int map_search_bytree_mp(struct ldb_module *module, const struct ldb_dn * search for matching records using a ldb_parse_tree */ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { struct ldb_message **fbres, **mpres = NULL; int i; int ret_fb, ret_mp; - ret_fb = map_search_bytree_fb(module, base, scope, tree, attrs, &fbres); + ret_fb = map_search_fb(module, base, scope, tree, attrs, &fbres); if (ret_fb == -1) return -1; @@ -886,7 +886,7 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas return ret_fb; } - ret_mp = map_search_bytree_mp(module, base, scope, tree, attrs, &mpres); + ret_mp = map_search_mp(module, base, scope, tree, attrs, &mpres); if (ret_mp == -1) { return -1; } @@ -901,26 +901,6 @@ static int map_search_bytree(struct ldb_module *module, const struct ldb_dn *bas return ret_fb + ret_mp; } -/* - search for matching records -*/ -static int map_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - struct ldb_parse_tree *tree; - int ret; - - tree = ldb_parse_tree(NULL, expression); - if (tree == NULL) { - ldb_set_errstring(module, talloc_strdup(module, "expression parse failed")); - return -1; - } - - ret = map_search_bytree(module, base, scope, tree, attrs, res); - talloc_free(tree); - return ret; -} static int msg_contains_objectclass(const struct ldb_message *msg, const char *name) { @@ -1270,7 +1250,6 @@ static int map_del_trans(struct ldb_module *module) static const struct ldb_module_ops map_ops = { .name = "map", - .search = map_search, .search_bytree = map_search_bytree, .add_record = map_add, .modify_record = map_modify, diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 3e3fbd544f..0275952780 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -37,17 +37,9 @@ #include "ldb/include/ldb_private.h" #include -static int rdn_name_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, struct ldb_parse_tree *tree, - const char * const *attrs, struct ldb_message ***res) + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, struct ldb_message ***res) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n"); return ldb_next_search_bytree(module, base, scope, tree, attrs, res); @@ -241,7 +233,6 @@ static int rdn_name_destructor(void *module_ctx) static const struct ldb_module_ops rdn_name_ops = { .name = "rdn_name", - .search = rdn_name_search, .search_bytree = rdn_name_search_bytree, .add_record = rdn_name_add_record, .modify_record = rdn_name_modify_record, diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index e882f72bd4..7c1753b215 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -283,13 +283,6 @@ static int get_attr_list_recursive(struct ldb_module *module, struct schema_stru } /* search */ -static int schema_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int schema_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -537,7 +530,6 @@ static int schema_destructor(void *module_ctx) static const struct ldb_module_ops schema_ops = { .name = "schema", - .search = schema_search, .search_bytree = schema_search_bytree, .add_record = schema_add_record, .modify_record = schema_modify_record, diff --git a/source4/lib/ldb/modules/skel.c b/source4/lib/ldb/modules/skel.c index 5d14a27a7b..f882a840e1 100644 --- a/source4/lib/ldb/modules/skel.c +++ b/source4/lib/ldb/modules/skel.c @@ -43,10 +43,10 @@ struct private_data { /* search */ static int skel_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, + enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - return ldb_next_search(module, base, scope, expression, attrs, res); + return ldb_next_search(module, base, scope, tree, attrs, res); } /* add_record */ @@ -102,8 +102,7 @@ static int skel_destructor(void *module_ctx) static const struct ldb_module_ops skel_ops = { .name = "skel", - .search = skel_search, - .search_bytree = skel_search_bytree, + .search_bytree = skel_search_bytree, .add_record = skel_add_record, .modify_record = skel_modify_record, .delete_record = skel_delete_record, diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 01e5c2c37c..5a1e54486a 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -37,14 +37,6 @@ #include "ldb/include/ldb_private.h" #include -static int timestamps_search(struct ldb_module *module, const struct ldb_dn *base, - enum ldb_scope scope, const char *expression, - const char * const *attrs, struct ldb_message ***res) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_search\n"); - return ldb_next_search(module, base, scope, expression, attrs, res); -} - static int timestamps_search_bytree(struct ldb_module *module, const struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) @@ -238,7 +230,6 @@ static int timestamps_destructor(void *module_ctx) static const struct ldb_module_ops timestamps_ops = { .name = "timestamps", - .search = timestamps_search, .search_bytree = timestamps_search_bytree, .add_record = timestamps_add_record, .modify_record = timestamps_modify_record, -- cgit From 12399c9b5e9b66ab95bd67142d181ccaecb067e2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 05:41:32 +0000 Subject: r10755: fixed the construction of expressions from subtrees for SUBSTRING searches (This used to be commit 71c06778d4a3ac1ca4198071ae3351acdc0656d9) --- source4/lib/ldb/common/ldb_parse.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 95110bfd00..110361d2b7 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -686,7 +686,8 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) talloc_free(s); return ret; case LDB_OP_SUBSTRING: - ret = talloc_strdup(mem_ctx, (tree->u.substring.start_with_wildcard)?"*":""); + ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr, + tree->u.substring.start_with_wildcard?"*":""); if (ret == NULL) return NULL; for (i = 0; tree->u.substring.chunks[i]; i++) { s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i])); @@ -704,6 +705,12 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) if ( ! tree->u.substring.end_with_wildcard ) { ret[strlen(ret) - 1] = '\0'; /* remove last wildcard */ } + s = talloc_asprintf_append(ret, ")"); + if (s == NULL) { + talloc_free(ret); + return NULL; + } + ret = s; return ret; case LDB_OP_GREATER: s = ldb_binary_encode(mem_ctx, tree->u.equality.value); -- cgit From 3cb96c8db92dc3059244f0977a79599b897a59b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 05:53:46 +0000 Subject: r10756: another fix for the construction of expressions from subtrees for SUBSTRING searches. This time fix multi-part substring searches. (This used to be commit bf5cef6f00466fc1dc3c2864a109f1ccd92681b0) --- source4/lib/ldb/common/ldb_parse.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 110361d2b7..27f9e1ec25 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -695,16 +695,18 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) talloc_free(ret); return NULL; } - s = talloc_asprintf_append(ret, "%s*", s2); + if (tree->u.substring.chunks[i+1] || + tree->u.substring.end_with_wildcard) { + s = talloc_asprintf_append(ret, "%s*", s2); + } else { + s = talloc_asprintf_append(ret, "%s", s2); + } if (s == NULL) { talloc_free(ret); return NULL; } ret = s; } - if ( ! tree->u.substring.end_with_wildcard ) { - ret[strlen(ret) - 1] = '\0'; /* remove last wildcard */ - } s = talloc_asprintf_append(ret, ")"); if (s == NULL) { talloc_free(ret); -- cgit From 01e6c562086b42a59fc1ac6aa1a3359747b96fe6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 06:01:56 +0000 Subject: r10757: remove the proxy module (it is not complete yet) (This used to be commit 3c5f3032fcb092545580b986e0ce58bb49e4d9cb) --- source4/lib/ldb/common/ldb_modules.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 2885d46b37..955e46b91a 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -133,7 +133,6 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { "objectguid", objectguid_module_init }, { "samldb", samldb_module_init }, { "samba3sam", ldb_samba3sam_module_init }, - { "proxy", proxy_module_init }, #endif { NULL, NULL } }; -- cgit From 78d0e79c9f9263e7f3798aa2e174a347ea1a3df1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Oct 2005 06:57:09 +0000 Subject: r10759: make modules easier to write by allowing modules to only implement the functions they care about, instead of all functions. This also makes it more likely that future changes to ldb will not break existing modules (This used to be commit 45f0c967b58e7c1b2e900a4d74cfde2a2c527dfa) --- source4/lib/ldb/common/ldb.c | 54 ++++++++++++++++++++++------- source4/lib/ldb/common/ldb_modules.c | 66 ++++++++++++++++-------------------- source4/lib/ldb/modules/ldb_map.c | 20 +---------- source4/lib/ldb/modules/rdn_name.c | 39 +-------------------- source4/lib/ldb/modules/schema.c | 26 +------------- source4/lib/ldb/modules/timestamps.c | 45 +----------------------- 6 files changed, 76 insertions(+), 174 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 29ee323ad4..725044d3f4 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -114,16 +114,25 @@ static void ldb_reset_err_string(struct ldb_context *ldb) } } +#define FIRST_OP(ldb, op) do { \ + module = ldb->modules; \ + while (module && module->ops->op == NULL) module = module->next; \ + if (module == NULL) return -1; \ +} while (0) + /* start a transaction */ int ldb_transaction_start(struct ldb_context *ldb) { + struct ldb_module *module; + FIRST_OP(ldb, start_transaction); + ldb->transaction_active++; ldb_reset_err_string(ldb); - return ldb->modules->ops->start_transaction(ldb->modules); + return module->ops->start_transaction(module); } /* @@ -131,6 +140,9 @@ int ldb_transaction_start(struct ldb_context *ldb) */ int ldb_transaction_commit(struct ldb_context *ldb) { + struct ldb_module *module; + FIRST_OP(ldb, end_transaction); + if (ldb->transaction_active > 0) { ldb->transaction_active--; } else { @@ -139,7 +151,7 @@ int ldb_transaction_commit(struct ldb_context *ldb) ldb_reset_err_string(ldb); - return ldb->modules->ops->end_transaction(ldb->modules); + return module->ops->end_transaction(module); } /* @@ -147,6 +159,9 @@ int ldb_transaction_commit(struct ldb_context *ldb) */ int ldb_transaction_cancel(struct ldb_context *ldb) { + struct ldb_module *module; + FIRST_OP(ldb, del_transaction); + if (ldb->transaction_active > 0) { ldb->transaction_active--; } else { @@ -155,7 +170,7 @@ int ldb_transaction_cancel(struct ldb_context *ldb) ldb_reset_err_string(ldb); - return ldb->modules->ops->del_transaction(ldb->modules); + return module->ops->del_transaction(module); } /* @@ -201,9 +216,12 @@ int ldb_search_bytree(struct ldb_context *ldb, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { + struct ldb_module *module; + FIRST_OP(ldb, search_bytree); + ldb_reset_err_string(ldb); - return ldb->modules->ops->search_bytree(ldb->modules, base, scope, tree, attrs, res); + return module->ops->search_bytree(module, base, scope, tree, attrs, res); } /* @@ -213,8 +231,11 @@ int ldb_search_bytree(struct ldb_context *ldb, int ldb_add(struct ldb_context *ldb, const struct ldb_message *message) { + struct ldb_module *module; int status; + FIRST_OP(ldb, add_record); + ldb_reset_err_string(ldb); status = ldb_msg_sanity_check(message); @@ -224,12 +245,12 @@ int ldb_add(struct ldb_context *ldb, status = ldb_transaction_start(ldb); if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->add_record(ldb->modules, message); + status = module->ops->add_record(module, message); if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); return ldb_transaction_commit(ldb); } - return ldb->modules->ops->add_record(ldb->modules, message); + return module->ops->add_record(module, message); } /* @@ -238,8 +259,11 @@ int ldb_add(struct ldb_context *ldb, int ldb_modify(struct ldb_context *ldb, const struct ldb_message *message) { + struct ldb_module *module; int status; + FIRST_OP(ldb, modify_record); + ldb_reset_err_string(ldb); status = ldb_msg_sanity_check(message); @@ -249,12 +273,12 @@ int ldb_modify(struct ldb_context *ldb, status = ldb_transaction_start(ldb); if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->modify_record(ldb->modules, message); + status = module->ops->modify_record(module, message); if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); return ldb_transaction_commit(ldb); } - return ldb->modules->ops->modify_record(ldb->modules, message); + return module->ops->modify_record(module, message); } @@ -263,20 +287,23 @@ int ldb_modify(struct ldb_context *ldb, */ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) { + struct ldb_module *module; int status; + FIRST_OP(ldb, delete_record); + ldb_reset_err_string(ldb); if (! ldb->transaction_active) { status = ldb_transaction_start(ldb); if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->delete_record(ldb->modules, dn); + status = module->ops->delete_record(module, dn); if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); return ldb_transaction_commit(ldb); } - return ldb->modules->ops->delete_record(ldb->modules, dn); + return module->ops->delete_record(module, dn); } /* @@ -284,20 +311,23 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn) */ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { + struct ldb_module *module; int status; + FIRST_OP(ldb, rename_record); + ldb_reset_err_string(ldb); if (! ldb->transaction_active) { status = ldb_transaction_start(ldb); if (status != LDB_SUCCESS) return status; - status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); + status = module->ops->rename_record(module, olddn, newdn); if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb); return ldb_transaction_commit(ldb); } - return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn); + return module->ops->rename_record(module, olddn, newdn); } diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 955e46b91a..b0ede9893b 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -212,6 +212,18 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) return 0; } +/* + by using this we allow ldb modules to only implement the functions they care about, + which makes writing a module simpler, and makes it more likely to keep working + when ldb is extended +*/ +#define FIND_OP(module, op) do { \ + module = module->next; \ + while (module && module->ops->op == NULL) module = module->next; \ + if (module == NULL) return -1; \ +} while (0) + + /* helper functions to call the next module in chain */ @@ -221,10 +233,8 @@ int ldb_next_search_bytree(struct ldb_module *module, struct ldb_parse_tree *tree, const char * const *attrs, struct ldb_message ***res) { - if (!module->next) { - return -1; - } - return module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); + FIND_OP(module, search_bytree); + return module->ops->search_bytree(module, base, scope, tree, attrs, res); } int ldb_next_search(struct ldb_module *module, @@ -235,15 +245,13 @@ int ldb_next_search(struct ldb_module *module, { struct ldb_parse_tree *tree; int ret; - if (!module->next) { - return -1; - } + FIND_OP(module, search_bytree); tree = ldb_parse_tree(module, expression); if (tree == NULL) { ldb_set_errstring(module, talloc_strdup(module, "Unable to parse search expression")); return -1; } - ret = module->next->ops->search_bytree(module->next, base, scope, tree, attrs, res); + ret = module->ops->search_bytree(module, base, scope, tree, attrs, res); talloc_free(tree); return ret; } @@ -251,58 +259,44 @@ int ldb_next_search(struct ldb_module *module, int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message) { - if (!module->next) { - return -1; - } - return module->next->ops->add_record(module->next, message); + FIND_OP(module, add_record); + return module->ops->add_record(module, message); } int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message) { - if (!module->next) { - return -1; - } - return module->next->ops->modify_record(module->next, message); + FIND_OP(module, modify_record); + return module->ops->modify_record(module, message); } int ldb_next_delete_record(struct ldb_module *module, const struct ldb_dn *dn) { - if (!module->next) { - return -1; - } - return module->next->ops->delete_record(module->next, dn); + FIND_OP(module, delete_record); + return module->ops->delete_record(module, dn); } int ldb_next_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { - if (!module->next) { - return -1; - } - return module->next->ops->rename_record(module->next, olddn, newdn); + FIND_OP(module, rename_record); + return module->ops->rename_record(module, olddn, newdn); } int ldb_next_start_trans(struct ldb_module *module) { - if (!module->next) { - return -1; - } - return module->next->ops->start_transaction(module->next); + FIND_OP(module, start_transaction); + return module->ops->start_transaction(module); } int ldb_next_end_trans(struct ldb_module *module) { - if (!module->next) { - return -1; - } - return module->next->ops->end_transaction(module->next); + FIND_OP(module, end_transaction); + return module->ops->end_transaction(module); } int ldb_next_del_trans(struct ldb_module *module) { - if (!module->next) { - return -1; - } - return module->next->ops->del_transaction(module->next); + FIND_OP(module, del_transaction); + return module->ops->del_transaction(module); } void ldb_set_errstring(struct ldb_module *module, char *err_string) diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 1da1ef661a..246fc5709d 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -1233,31 +1233,13 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) return (mp_ret == -1 || fb_ret == -1)?-1:0; } -static int map_start_trans(struct ldb_module *module) -{ - return ldb_next_start_trans(module); -} - -static int map_end_trans(struct ldb_module *module) -{ - return ldb_next_end_trans(module); -} - -static int map_del_trans(struct ldb_module *module) -{ - return ldb_next_del_trans(module); -} - static const struct ldb_module_ops map_ops = { .name = "map", .search_bytree = map_search_bytree, .add_record = map_add, .modify_record = map_modify, .delete_record = map_delete, - .rename_record = map_rename, - .start_transaction = map_start_trans, - .end_transaction = map_end_trans, - .del_transaction = map_del_trans + .rename_record = map_rename }; static char *map_find_url(struct ldb_context *ldb, const char *name) diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c index 0275952780..40ff75744e 100644 --- a/source4/lib/ldb/modules/rdn_name.c +++ b/source4/lib/ldb/modules/rdn_name.c @@ -194,53 +194,18 @@ static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_me return ret; } -static int rdn_name_delete_record(struct ldb_module *module, const struct ldb_dn *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) { ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n"); return ldb_next_rename_record(module, olddn, newdn); } -static int rdn_start_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_start_trans\n"); - return ldb_next_start_trans(module); -} - -static int rdn_end_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_end_trans\n"); - return ldb_next_end_trans(module); -} - -static int rdn_del_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_del_trans\n"); - return ldb_next_del_trans(module); -} - -static int rdn_name_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - static const struct ldb_module_ops rdn_name_ops = { .name = "rdn_name", .search_bytree = rdn_name_search_bytree, .add_record = rdn_name_add_record, .modify_record = rdn_name_modify_record, - .delete_record = rdn_name_delete_record, - .rename_record = rdn_name_rename_record, - .start_transaction = rdn_start_trans, - .end_transaction = rdn_end_trans, - .del_transaction = rdn_del_trans + .rename_record = rdn_name_rename_record }; @@ -262,7 +227,5 @@ struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *opt ctx->prev = ctx->next = NULL; ctx->ops = &rdn_name_ops; - talloc_set_destructor (ctx, rdn_name_destructor); - return ctx; } diff --git a/source4/lib/ldb/modules/schema.c b/source4/lib/ldb/modules/schema.c index 7c1753b215..0cae110487 100644 --- a/source4/lib/ldb/modules/schema.c +++ b/source4/lib/ldb/modules/schema.c @@ -509,35 +509,13 @@ static int schema_rename_record(struct ldb_module *module, const struct ldb_dn * return ldb_next_rename_record(module, olddn, newdn); } -static int schema_start_trans(struct ldb_module *module) { - return ldb_next_start_trans(module); -} - -static int schema_end_trans(struct ldb_module *module) { - return ldb_next_end_trans(module); -} - -static int schema_del_trans(struct ldb_module *module) { - return ldb_next_del_trans(module); -} - -static int schema_destructor(void *module_ctx) -{ -/* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} - static const struct ldb_module_ops schema_ops = { .name = "schema", .search_bytree = schema_search_bytree, .add_record = schema_add_record, .modify_record = schema_modify_record, .delete_record = schema_delete_record, - .rename_record = schema_rename_record, - .start_transaction = schema_start_trans, - .end_transaction = schema_end_trans, - .del_transaction = schema_del_trans + .rename_record = schema_rename_record }; #ifdef HAVE_DLOPEN_DISABLED @@ -558,7 +536,5 @@ struct ldb_module *schema_module_init(struct ldb_context *ldb, const char *optio ctx->prev = ctx->next = NULL; ctx->ops = &schema_ops; - talloc_set_destructor (ctx, schema_destructor); - return ctx; } diff --git a/source4/lib/ldb/modules/timestamps.c b/source4/lib/ldb/modules/timestamps.c index 5a1e54486a..13e9c2ccc4 100644 --- a/source4/lib/ldb/modules/timestamps.c +++ b/source4/lib/ldb/modules/timestamps.c @@ -191,53 +191,12 @@ static int timestamps_modify_record(struct ldb_module *module, const struct ldb_ return ret; } -static int timestamps_delete_record(struct ldb_module *module, const struct ldb_dn *dn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_delete_record\n"); - return ldb_next_delete_record(module, dn); -} - -static int timestamps_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_rename_record\n"); - return ldb_next_rename_record(module, olddn, newdn); -} - -static int timestamps_start_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_start_trans\n"); - return ldb_next_start_trans(module); -} - -static int timestamps_end_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_end_trans\n"); - return ldb_next_end_trans(module); -} - -static int timestamps_del_trans(struct ldb_module *module) -{ - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "timestamps_del_trans\n"); - return ldb_next_del_trans(module); -} - -static int timestamps_destructor(void *module_ctx) -{ - /* struct ldb_module *ctx = module_ctx; */ - /* put your clean-up functions here */ - return 0; -} static const struct ldb_module_ops timestamps_ops = { .name = "timestamps", .search_bytree = timestamps_search_bytree, .add_record = timestamps_add_record, - .modify_record = timestamps_modify_record, - .delete_record = timestamps_delete_record, - .rename_record = timestamps_rename_record, - .start_transaction = timestamps_start_trans, - .end_transaction = timestamps_end_trans, - .del_transaction = timestamps_del_trans + .modify_record = timestamps_modify_record }; @@ -259,7 +218,5 @@ struct ldb_module *timestamps_module_init(struct ldb_context *ldb, const char *o ctx->prev = ctx->next = NULL; ctx->ops = ×tamps_ops; - talloc_set_destructor (ctx, timestamps_destructor); - return ctx; } -- cgit From f6a09fb8f81048891da589337d5bdeb3fc9959c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Oct 2005 00:40:29 +0000 Subject: r10790: allow updating of existing ldb opaque values (thanks to abartlet for spotting this) (This used to be commit ef13569ca94da00cc410318e61505e70f3606674) --- source4/lib/ldb/common/ldb.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 725044d3f4..d34ddb4c8a 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -350,7 +350,17 @@ const char *ldb_errstring(struct ldb_context *ldb) */ int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value) { - struct ldb_opaque *o = talloc(ldb, struct ldb_opaque); + struct ldb_opaque *o; + + /* allow updating an existing value */ + for (o=ldb->opaque;o;o=o->next) { + if (strcmp(o->name, name) == 0) { + o->value = value; + return LDB_SUCCESS; + } + } + + o = talloc(ldb, struct ldb_opaque); if (o == NULL) { ldb_oom(ldb); return LDB_ERR_OTHER; -- cgit From 1377cca5f4beb43cf67fcc65eed79f14178d6349 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 7 Oct 2005 11:31:45 +0000 Subject: r10810: This adds the hooks required to communicate the current user from the authenticated session down into LDB. This associates a session info structure with the open LDB, allowing a future ldb_ntacl module to allow/deny operations on that basis. Along the way, I cleaned up a few things, and added new helper functions to assist. In particular the LSA pipe uses simpler queries for some of the setup. In ldap_server, I have removed the 'ldasrv:hacked' module, which hasn't been worked on (other than making it continue to compile) since January, and I think the features of this module are being put into ldb anyway. I have also changed the partitions in ldap_server to be initialised after the connection, with the private pointer used to associate the ldb with the incoming session. Andrew Bartlett (This used to be commit fd7203789a2c0929eecea8125b57b833a67fed71) --- source4/lib/ldb/tools/cmdline.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 7cdecc334f..642ad127d8 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -75,6 +75,11 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const if (r != 0) { goto failed; } + + if (ldb_set_opaque(ldb, "securityToken", system_session(ldb))) { + goto failed; + } + #endif ret = talloc_zero(ldb, struct ldb_cmdline); -- cgit From 0b1b8704bdb7c8a37738db722d3b2ac2d2a3e298 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 8 Oct 2005 07:41:57 +0000 Subject: r10830: we should use the same name in all places:-) metze (This used to be commit fbe8fd06b700b78f02b7f01fc2ad45eee419d216) --- source4/lib/ldb/tools/cmdline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 642ad127d8..2428306f39 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -76,7 +76,7 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const goto failed; } - if (ldb_set_opaque(ldb, "securityToken", system_session(ldb))) { + if (ldb_set_opaque(ldb, "sessionInfo", system_session(ldb))) { goto failed; } -- cgit From 4785cf6fd1c5a702062e9b1db0f2d3e55727bc65 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Oct 2005 23:29:26 +0000 Subject: r10856: we need aclocal.m4 in ldb for standalone configure (This used to be commit b2551e76e8b0edf99483343d687df3a6cecff1f5) --- source4/lib/ldb/aclocal.m4 | 12 ++++++++++++ source4/lib/ldb/tests/slapd.conf | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 source4/lib/ldb/aclocal.m4 (limited to 'source4/lib') diff --git a/source4/lib/ldb/aclocal.m4 b/source4/lib/ldb/aclocal.m4 new file mode 100644 index 0000000000..cdc2a2fa52 --- /dev/null +++ b/source4/lib/ldb/aclocal.m4 @@ -0,0 +1,12 @@ +dnl see if a declaration exists for a function or variable +dnl defines HAVE_function_DECL if it exists +dnl AC_HAVE_DECL(var, includes) +AC_DEFUN(AC_HAVE_DECL, +[ + AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[ + AC_TRY_COMPILE([$2],[int i = (int)$1], + ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)]) + if test x"$ac_cv_have_$1_decl" = x"yes"; then + AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available]) + fi +]) diff --git a/source4/lib/ldb/tests/slapd.conf b/source4/lib/ldb/tests/slapd.conf index 332b3f9063..fc9d659b0b 100644 --- a/source4/lib/ldb/tests/slapd.conf +++ b/source4/lib/ldb/tests/slapd.conf @@ -14,8 +14,8 @@ access to * by * write allow update_anon bind_anon_dn -#modulepath /usr/lib/ldap -#moduleload back_bdb +modulepath /usr/lib/ldap +moduleload back_bdb defaultsearchbase "o=University of Michigan,c=TEST" -- cgit From a3b33d6fa811dd1277e51e17ba4a4c3954457397 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 04:34:15 +0000 Subject: r10889: make searches for dn's less of a special case, and much faster when part of more complex expressions (This used to be commit 40d304140b4cf22559d6b55c8cbaf1b984baf62f) --- source4/lib/ldb/ldb_tdb/ldb_index.c | 7 +++++++ source4/lib/ldb/ldb_tdb/ldb_search.c | 15 --------------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index c2a4fb1ea8..7c920dd78b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -319,6 +319,13 @@ static int ltdb_index_dn_leaf(struct ldb_module *module, if (ldb_attr_cmp(tree->u.equality.attr, LTDB_OBJECTCLASS) == 0) { return ltdb_index_dn_objectclass(module, tree, index_list, list); } + if (ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0 || + ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { + char *dn = talloc_strdup(list, (char *)tree->u.equality.value.data); + list->count = 1; + list->dn = &dn; + return 1; + } return ltdb_index_dn_simple(module, tree, index_list, list); } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index eb89753007..74046475e0 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -501,21 +501,6 @@ int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base, if ((base == NULL || base->comp_num == 0) && (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1; - /* it is important that we handle dn queries this way, and not - via a full db search, otherwise ldb is horribly slow */ - if (tree->operation == LDB_OP_EQUALITY && - (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0 || - ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0)) { - struct ldb_dn *dn; - dn = ldb_dn_explode(module->ldb, tree->u.equality.value.data); - if (dn == NULL) { - return LDB_ERR_INVALID_DN_SYNTAX; - } - ret = ltdb_search_dn(module, dn, attrs, res); - talloc_free(dn); - return ret; - } - if (ltdb_lock_read(module) != 0) { return -1; } -- cgit From 5d1bc4fe31192503621cce704d24c0c5e11d24fc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 05:01:52 +0000 Subject: r10891: I noticed that the secrets.db was not being backed up on my system due to msync/mmap not changing the mtime of the file. This patch ensures that for successfully completed transactions we update the mtime. I don't do this on all tdb writes as its too expensive, but doing it just on transactions is bearable, as those cost quite a lot anyway. (This used to be commit b2934732dd62f705f59c124f19460c5436a9a422) --- source4/lib/tdb/common/transaction.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/lib') diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c index 9d37046116..becc6cd059 100644 --- a/source4/lib/tdb/common/transaction.c +++ b/source4/lib/tdb/common/transaction.c @@ -857,6 +857,15 @@ int tdb_transaction_commit(struct tdb_context *tdb) tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + /* on some systems (like Linux 2.6.x) changes via mmap/msync + don't change the mtime of the file, this means the file may + not be backed up (as tdb rounding to block sizes means that + file size changes are quite rare too). The following forces + mtime changes when a transaction completes */ +#ifdef HAVE_UTIME + utime(tdb->name, NULL); +#endif + /* use a transaction cancel to free memory and remove the transaction locks */ tdb_transaction_cancel(tdb); -- cgit From 39a504699bc1e9514fbfc0b8cea8da8933e3a2af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 06:21:07 +0000 Subject: r10892: - improved the handling of the special distinguishedName attribute - ensure we don't add attributes twice, should a user ask for the attribute twice. Do this in such a way that we don't become O(n^2) - removed some unused code (This used to be commit 7684cdb47b4ae516f066afb249d5f88032152ec9) --- source4/lib/ldb/ldb_tdb/ldb_search.c | 128 ++++++++++++----------------------- 1 file changed, 43 insertions(+), 85 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 74046475e0..e0a62962c7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -42,11 +42,18 @@ add one element to a message */ static int msg_add_element(struct ldb_context *ldb, - struct ldb_message *ret, const struct ldb_message_element *el) + struct ldb_message *ret, + const struct ldb_message_element *el, + int check_duplicates) { unsigned int i; struct ldb_message_element *e2, *elnew; + if (check_duplicates && ldb_msg_find_element(ret, el->name)) { + /* its already there */ + return 0; + } + e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1); if (!e2) { return -1; @@ -83,6 +90,30 @@ static int msg_add_element(struct ldb_context *ldb, return 0; } +/* + add the special distinguishedName element +*/ +static int msg_add_distinguished_name(struct ldb_module *module, struct ldb_message *msg) +{ + struct ldb_message_element el; + struct ldb_val val; + int ret; + + el.flags = 0; + el.name = talloc_strdup(msg, "distinguishedName"); + if (!el.name) { + return -1; + } + el.num_values = 1; + el.values = &val; + val.data = ldb_dn_linearize(msg, msg->dn); + val.length = strlen(val.data); + + ret = msg_add_element(module->ldb, msg, &el, 1); + talloc_free(el.name); + return ret; +} + /* add all elements from one message into another */ @@ -91,6 +122,11 @@ static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *r { struct ldb_context *ldb = module->ldb; unsigned int i; + int check_duplicates = (ret->num_elements != 0); + + if (msg_add_distinguished_name(module, ret) != 0) { + return -1; + } for (i=0;inum_elements;i++) { const struct ldb_attrib_handler *h; @@ -98,7 +134,8 @@ static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *r if (h->flags & LDB_ATTR_FLAG_HIDDEN) { continue; } - if (msg_add_element(ldb, ret, &msg->elements[i]) != 0) { + if (msg_add_element(ldb, ret, &msg->elements[i], + check_duplicates) != 0) { return -1; } } @@ -151,27 +188,10 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, continue; } - if (ldb_attr_cmp(attrs[i], "dn") == 0 || - ldb_attr_cmp(attrs[i], "distinguishedName") == 0) { - struct ldb_message_element el2; - struct ldb_val val; - - el2.flags = 0; - el2.name = talloc_strdup(ret, attrs[i]); - if (!el2.name) { - talloc_free(ret); - return NULL; - } - el2.num_values = 1; - el2.values = &val; - val.data = ldb_dn_linearize(ret, ret->dn); - val.length = strlen(val.data); - - if (msg_add_element(ldb, ret, &el2) != 0) { - talloc_free(ret); - return NULL; + if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) { + if (msg_add_distinguished_name(module, ret) != 0) { + return -1; } - talloc_free(discard_const_p(char, el2.name)); continue; } @@ -179,7 +199,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, if (!el) { continue; } - if (msg_add_element(ldb, ret, el) != 0) { + if (msg_add_element(ldb, ret, el, 1) != 0) { talloc_free(ret); return NULL; } @@ -277,68 +297,6 @@ static int ltdb_unlock_read(struct ldb_module *module) return tdb_chainunlock_read(ltdb->tdb, key); } - - -/* - search the database for a single simple dn -*/ -static int ltdb_search_dn(struct ldb_module *module, const struct ldb_dn *dn, - const char * const attrs[], struct ldb_message ***res) -{ - struct ldb_context *ldb = module->ldb; - int ret; - struct ldb_message *msg, *msg2; - - *res = NULL; - - if (ltdb_lock_read(module) != 0) { - return -1; - } - - if (ltdb_cache_load(module) != 0) { - ltdb_unlock_read(module); - return -1; - } - - *res = talloc_array(ldb, struct ldb_message *, 2); - if (! *res) { - goto failed; - } - - msg = talloc(*res, struct ldb_message); - if (msg == NULL) { - goto failed; - } - - ret = ltdb_search_dn1(module, dn, msg); - if (ret != 1) { - talloc_free(*res); - *res = NULL; - ltdb_unlock_read(module); - return 0; - } - - msg2 = ltdb_pull_attrs(module, msg, attrs); - - talloc_free(msg); - if (!msg2) { - goto failed; - } - - (*res)[0] = talloc_steal(*res, msg2); - (*res)[1] = NULL; - - ltdb_unlock_read(module); - - return 1; - -failed: - talloc_free(*res); - ltdb_unlock_read(module); - return -1; -} - - /* add a set of attributes from a record to a set of results return 0 on success, -1 on failure -- cgit From 87255dc743970cdfbccfe66c31504d518512da30 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 10:53:28 +0000 Subject: r10893: add configure test for utime (needed for the previous utime patch) (This used to be commit ef020d599fd2336cbf879920fe3505b97783dfc8) --- source4/lib/tdb/config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib') diff --git a/source4/lib/tdb/config.m4 b/source4/lib/tdb/config.m4 index 23784f3723..f1aa95df54 100644 --- a/source4/lib/tdb/config.m4 +++ b/source4/lib/tdb/config.m4 @@ -1,4 +1,4 @@ -AC_CHECK_FUNCS(mmap pread pwrite getpagesize) +AC_CHECK_FUNCS(mmap pread pwrite getpagesize utime) AC_CHECK_HEADERS(getopt.h sys/select.h sys/time.h) AC_DEFINE([_GNU_SOURCE],[],[Pull in GNU extensions]) -- cgit From 36d73b0e71eb3fbbe8d660b7609806b0355bd09c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 11:00:16 +0000 Subject: r10894: make the handling of dn/distinguishedName much closer to real ldap. Also ensure we put a objectclass on our private ldb's, so they have some chance of being stored in ldap if you want to (This used to be commit 1af2cc067f70f6654d08387fc28def67229bb06a) --- source4/lib/gendb.c | 2 +- source4/lib/ldb/common/ldb_match.c | 7 ++++++- source4/lib/ldb/common/ldb_parse.c | 2 +- source4/lib/ldb/tools/cmdline.c | 2 +- source4/lib/ldb/tools/ldbdel.c | 4 ++-- source4/lib/ldb/tools/ldbedit.c | 2 +- source4/lib/ldb/tools/ldbsearch.c | 2 +- 7 files changed, 13 insertions(+), 8 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/gendb.c b/source4/lib/gendb.c index a5fe7c3bce..e0fb9662bb 100644 --- a/source4/lib/gendb.c +++ b/source4/lib/gendb.c @@ -90,7 +90,7 @@ int gendb_search_dn(struct ldb_context *ldb, struct ldb_message ***res, const char * const *attrs) { - return gendb_search(ldb, mem_ctx, dn, res, attrs, "dn=%s", ldb_dn_linearize(mem_ctx, dn)); + return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); } /* diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 1269d99a0f..78e4304f6c 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -88,7 +88,7 @@ static int ldb_match_present(struct ldb_context *ldb, enum ldb_scope scope) { - if (ldb_attr_cmp(tree->u.present.attr, "dn") == 0) { + if (ldb_attr_cmp(tree->u.present.attr, "distinguishedName") == 0) { return 1; } @@ -151,8 +151,13 @@ static int ldb_match_equality(struct ldb_context *ldb, struct ldb_dn *valuedn; int ret; + /* catch the old method of dn matching */ if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, "attempt to match on 'dn' - should use distinguishedName"); + return 0; + } + if (ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0) { valuedn = ldb_dn_explode_casefold(ldb, tree->u.equality.value.data); if (valuedn == NULL) { return 0; diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 27f9e1ec25..e61511ebec 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -621,7 +621,7 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s) struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s) { if (s == NULL || *s == 0) { - s = "(|(objectClass=*)(dn=*))"; + s = "(|(objectClass=*)(distinguishedName=*))"; } while (isspace((unsigned char)*s)) s++; diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 2428306f39..ca9d3847e8 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -54,7 +54,7 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL }, { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, - { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "dn=*", NULL }, + { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "objectClass=*", NULL }, { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, { "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" }, diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 6082931e22..bd40fccbdb 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -44,10 +44,10 @@ static int ldb_delete_recursive(struct ldb_context *ldb, const struct ldb_dn *dn) { int ret, i, total=0; - const char *attrs[] = { "dn", NULL }; + const char *attrs[] = { NULL }; struct ldb_message **res; - ret = ldb_search(ldb, dn, LDB_SCOPE_SUBTREE, "dn=*", attrs, &res); + ret = ldb_search(ldb, dn, LDB_SCOPE_SUBTREE, "distinguishedName=*", attrs, &res); if (ret <= 0) return -1; for (i=0;i Date: Tue, 11 Oct 2005 12:25:55 +0000 Subject: r10895: allow 'dn=string' searches to work again. Windows doesn't allow these, but they are so very useful for things like dn=@MODULES that I think its worth supporting them (This used to be commit e2e3193a98b0f81c7bdb02c98db375ca0449022a) --- source4/lib/ldb/common/ldb_match.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 78e4304f6c..14031a6dd1 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -151,13 +151,8 @@ static int ldb_match_equality(struct ldb_context *ldb, struct ldb_dn *valuedn; int ret; - /* catch the old method of dn matching */ - if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "attempt to match on 'dn' - should use distinguishedName"); - return 0; - } - - if (ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0) { + if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0 || + ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0) { valuedn = ldb_dn_explode_casefold(ldb, tree->u.equality.value.data); if (valuedn == NULL) { return 0; -- cgit From 1584f64920431d15276dd44c59fc35dc5506c0e7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 12:30:34 +0000 Subject: r10896: added a strcasestr() replacement function (This used to be commit 4483d275e12006e5acc72ae143c0a01da01bd00d) --- source4/lib/replace/config.m4 | 2 +- source4/lib/replace/replace.c | 16 +++++++++++++++- source4/lib/replace/replace.h | 4 ++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'source4/lib') diff --git a/source4/lib/replace/config.m4 b/source4/lib/replace/config.m4 index 98c491fd38..70d13e40fd 100644 --- a/source4/lib/replace/config.m4 +++ b/source4/lib/replace/config.m4 @@ -45,7 +45,7 @@ AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror) AC_CHECK_FUNCS(timegm setenv vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid strnlen strlcpy strlcat innetgr initgroups memmove strdup) -AC_CHECK_FUNCS(pread pwrite strndup) +AC_CHECK_FUNCS(pread pwrite strndup strcasestr) AC_HAVE_DECL(setresuid, [#include ]) AC_HAVE_DECL(setresgid, [#include ]) AC_HAVE_DECL(errno, [#include ]) diff --git a/source4/lib/replace/replace.c b/source4/lib/replace/replace.c index 5e60252a67..d87a009e8c 100644 --- a/source4/lib/replace/replace.c +++ b/source4/lib/replace/replace.c @@ -22,6 +22,7 @@ #include "system/wait.h" #include "system/time.h" #include "system/network.h" +#include "system/iconv.h" void replace_dummy(void); void replace_dummy(void) {} @@ -534,4 +535,17 @@ static ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offs } #endif - +#ifndef HAVE_STRCASESTR +char *strcasestr(const char *haystack, const char *needle) +{ + const char *s; + size_t nlen = strlen(needle); + for (s=haystack;*s;s++) { + if (toupper(*needle) == toupper(*s) && + strncasecmp(s, needle, nlen) == 0) { + return discard_const_p(char, s); + } + } + return NULL; +} +#endif diff --git a/source4/lib/replace/replace.h b/source4/lib/replace/replace.h index 572113af8c..e3eef56eeb 100644 --- a/source4/lib/replace/replace.h +++ b/source4/lib/replace/replace.h @@ -84,6 +84,10 @@ int setenv(const char *name, const char *value, int overwrite); int rename(const char *zfrom, const char *zto); #endif +#ifndef HAVE_STRCASESTR +char *strcasestr(const char *haystack, const char *needle); +#endif + #ifndef HAVE_FTRUNCATE int ftruncate(int f,long l); #endif -- cgit From 860ffba4e147b7c27b416df60bec587eb61ea148 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 11 Oct 2005 12:31:31 +0000 Subject: r10897: added in a hackish ldb proxy module that I am using to experiment with mmc management support (This used to be commit 99a5b088810e8e2f4e28b99a4a0e5e7dc9301594) --- source4/lib/ldb/common/ldb_modules.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index b0ede9893b..5ca666c194 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -133,6 +133,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { "objectguid", objectguid_module_init }, { "samldb", samldb_module_init }, { "samba3sam", ldb_samba3sam_module_init }, + { "proxy", proxy_module_init }, #endif { NULL, NULL } }; -- cgit From a599edf04cbdeef9014923ba0d3713b8ff84f266 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Oct 2005 06:10:23 +0000 Subject: r10913: This patch isn't as big as it looks ... most of the changes are fixes to make all the ldb code compile without warnings on gcc4. Unfortunately That required a lot of casts :-( I have also added the start of an 'operational' module, which will replace the timestamp module, plus add support for some other operational attributes In ldb_msg_*() I added some new utility functions to make the operational module sane, and remove the 'ldb' argument from the ldb_msg_add_*() functions. That argument was only needed back in the early days of ldb when we didn't use the hierarchical talloc and thus needed a place to get the allocation function from. Now its just a pain to pass around everywhere. Also added a ldb_debug_set() function that calls ldb_debug() plus sets the result using ldb_set_errstring(). That saves on some awkward coding in a few places. (This used to be commit f6818daecca95760c12f79fd307770cbe3346f57) --- source4/lib/ldb/common/attrib_handlers.c | 26 ++-- source4/lib/ldb/common/ldb_debug.c | 18 +++ source4/lib/ldb/common/ldb_dn.c | 19 +-- source4/lib/ldb/common/ldb_ldif.c | 14 +- source4/lib/ldb/common/ldb_match.c | 21 +-- source4/lib/ldb/common/ldb_msg.c | 111 ++++++++++++---- source4/lib/ldb/common/ldb_parse.c | 48 +++++++ source4/lib/ldb/common/ldb_utf8.c | 1 - source4/lib/ldb/config.mk | 9 ++ source4/lib/ldb/include/ldb.h | 44 ++++--- source4/lib/ldb/include/ldb_private.h | 2 + source4/lib/ldb/ldb_tdb/ldb_cache.c | 13 +- source4/lib/ldb/ldb_tdb/ldb_index.c | 28 ++-- source4/lib/ldb/ldb_tdb/ldb_pack.c | 14 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 16 +-- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 +- source4/lib/ldb/modules/ldb_map.c | 37 +++--- source4/lib/ldb/modules/operational.c | 217 +++++++++++++++++++++++++++++++ source4/lib/ldb/modules/rdn_name.c | 6 +- source4/lib/ldb/modules/schema.c | 81 ++++-------- source4/lib/ldb/modules/timestamps.c | 2 +- source4/lib/ldb/tools/ldbtest.c | 42 +++--- source4/lib/ldb/tools/oLschema2ldif.c | 12 +- source4/lib/registry/reg_backend_ldb.c | 12 +- 24 files changed, 570 insertions(+), 225 deletions(-) create mode 100644 source4/lib/ldb/modules/operational.c (limited to 'source4/lib') diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 61ca566570..d073203b3c 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -53,7 +53,7 @@ static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { uint8_t *s1, *s2; - out->data = talloc_size(mem_ctx, strlen(in->data)+1); + out->data = talloc_size(mem_ctx, strlen((char *)in->data)+1); if (out->data == NULL) { ldb_oom(ldb); return -1; @@ -69,7 +69,7 @@ static int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx, s2++; s1++; } *s2 = 0; - out->length = strlen(out->data); + out->length = strlen((char *)out->data); return 0; } @@ -82,15 +82,15 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { char *end; - long long i = strtoll(in->data, &end, 0); + long long i = strtoll((char *)in->data, &end, 0); if (*end != 0) { return -1; } - out->data = talloc_asprintf(mem_ctx, "%lld", i); + out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i); if (out->data == NULL) { return -1; } - out->length = strlen(out->data); + out->length = strlen((char *)out->data); return 0; } @@ -100,7 +100,7 @@ static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx, static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { - return strtoll(v1->data, NULL, 0) - strtoll(v2->data, NULL, 0); + return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0); } /* @@ -123,7 +123,7 @@ int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx, static int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *v1, const struct ldb_val *v2) { - const char *s1=v1->data, *s2=v2->data; + const char *s1=(const char *)v1->data, *s2=(const char *)v2->data; while (*s1 == ' ') s1++; while (*s2 == ' ') s2++; /* TODO: make utf8 safe, possibly with helper function from application */ @@ -153,16 +153,16 @@ static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx, out->length = 0; out->data = NULL; - dn = ldb_dn_explode_casefold(ldb, in->data); + dn = ldb_dn_explode_casefold(ldb, (char *)in->data); if (dn == NULL) { return -1; } - out->data = ldb_dn_linearize(mem_ctx, dn); + out->data = (uint8_t *)ldb_dn_linearize(mem_ctx, dn); if (out->data == NULL) { goto done; } - out->length = strlen(out->data); + out->length = strlen((char *)out->data); ret = 0; @@ -181,10 +181,10 @@ static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx, struct ldb_dn *dn1 = NULL, *dn2 = NULL; int ret; - dn1 = ldb_dn_explode_casefold(mem_ctx, v1->data); + dn1 = ldb_dn_explode_casefold(mem_ctx, (char *)v1->data); if (dn1 == NULL) return -1; - dn2 = ldb_dn_explode_casefold(mem_ctx, v2->data); + dn2 = ldb_dn_explode_casefold(mem_ctx, (char *)v2->data); if (dn2 == NULL) { talloc_free(dn1); return -1; @@ -209,7 +209,7 @@ static int ldb_comparison_objectclass(struct ldb_context *ldb, void *mem_ctx, if (ret == 0) { return 0; } - subclasses = ldb_subclass_list(ldb, v1->data); + subclasses = ldb_subclass_list(ldb, (char *)v1->data); if (subclasses == NULL) { return ret; } diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c index 59f00ccc96..d046c8cd1f 100644 --- a/source4/lib/ldb/common/ldb_debug.c +++ b/source4/lib/ldb/common/ldb_debug.c @@ -86,3 +86,21 @@ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char * va_end(ap); } + +/* + log a message, and set the ldb error string to the same message +*/ +void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level, + const char *fmt, ...) +{ + va_list ap; + char *msg; + va_start(ap, fmt); + msg = talloc_vasprintf(ldb, fmt, ap); + va_end(ap); + if (msg != NULL) { + ldb_set_errstring(ldb->modules, msg); + ldb_debug(ldb, level, "%s", msg); + } +} + diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 2cd7d590fe..92e06025d5 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -54,7 +54,7 @@ int ldb_dn_check_special(const struct ldb_dn *dn, const char *check) { if (dn == NULL || dn->comp_num != 1) return 0; - return ! strcmp(dn->components[0].value.data, check); + return ! strcmp((char *)dn->components[0].value.data, check); } static int ldb_dn_is_valid_attribute_name(const char *name) @@ -163,7 +163,7 @@ static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src) } value.length = end - dst; - value.data = dst; + value.data = (uint8_t *)dst; return value; failed: @@ -367,7 +367,7 @@ struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn) if (edn->components == NULL) goto failed; edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL); if (edn->components[0].name == NULL) goto failed; - edn->components[0].value.data = talloc_strdup(edn->components, dn); + edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn); if (edn->components[0].value.data== NULL) goto failed; edn->components[0].value.length = strlen(dn); return edn; @@ -425,7 +425,7 @@ char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn) /* Special DNs */ if (ldb_dn_is_special(edn)) { - dn = talloc_strdup(mem_ctx, edn->components[0].value.data); + dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data); return dn; } @@ -598,7 +598,7 @@ char *ldb_dn_linearize_casefold(struct ldb_context *ldb, const struct ldb_dn *ed /* Special DNs */ if (ldb_dn_is_special(edn)) { - dn = talloc_strdup(ldb, edn->components[0].value.data); + dn = talloc_strdup(ldb, (char *)edn->components[0].value.data); return dn; } @@ -703,7 +703,7 @@ struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr, return NULL; } - dc->value.data = talloc_strdup(dc, val); + dc->value.data = (uint8_t *)talloc_strdup(dc, val); if (dc->value.data == NULL) { talloc_free(dc); return NULL; @@ -736,9 +736,9 @@ struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr, new->components[0].name = talloc_strdup(new->components, attr); LDB_DN_NULL_FAILED(new->components[0].name); - new->components[0].value.data = talloc_strdup(new->components, value); + new->components[0].value.data = (uint8_t *)talloc_strdup(new->components, value); LDB_DN_NULL_FAILED(new->components[0].value.data); - new->components[0].value.length = strlen(new->components[0].value.data); + new->components[0].value.length = strlen((char *)new->components[0].value.data); return new; @@ -753,7 +753,8 @@ struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *c { if (component == NULL) return NULL; - return ldb_dn_build_child(mem_ctx, component->name, component->value.data, base); + return ldb_dn_build_child(mem_ctx, component->name, + (char *)component->value.data, base); } struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2) diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index b268cca578..7ba6a00147 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -55,7 +55,7 @@ static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value) int ret; int f; - f = open(value->data, O_RDONLY); + f = open((const char *)value->data, O_RDONLY); if (f == -1) { return -1; } @@ -79,7 +79,7 @@ static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value) count = 0; size = statbuf.st_size; - buf = value->data; + buf = (char *)value->data; while (count < statbuf.st_size) { bytes = read(f, buf, size); if (bytes == -1) { @@ -325,7 +325,7 @@ int ldb_ldif_write(struct ldb_context *ldb, msg->elements[i].name); CHECK_RET; ret = base64_encode_f(ldb, fprintf_fn, private_data, - v.data, v.length, + (char *)v.data, v.length, strlen(msg->elements[i].name)+3); CHECK_RET; ret = fprintf_fn(private_data, "\n"); @@ -334,7 +334,7 @@ int ldb_ldif_write(struct ldb_context *ldb, ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name); CHECK_RET; ret = fold_string(fprintf_fn, private_data, - v.data, v.length, + (char *)v.data, v.length, strlen(msg->elements[i].name)+2); CHECK_RET; ret = fprintf_fn(private_data, "\n"); @@ -461,7 +461,7 @@ static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val p++; } - value->data = p; + value->data = (uint8_t *)p; p = strchr(p, '\n'); @@ -475,7 +475,7 @@ static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val } if (base64_encoded) { - int len = ldb_base64_decode(value->data); + int len = ldb_base64_decode((char *)value->data); if (len == -1) { /* it wasn't valid base64 data */ return -1; @@ -588,7 +588,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb, goto failed; } - msg->dn = ldb_dn_explode(msg, value.data); + msg->dn = ldb_dn_explode(msg, (char *)value.data); if (msg->dn == NULL) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c index 14031a6dd1..7573cfc808 100644 --- a/source4/lib/ldb/common/ldb_match.c +++ b/source4/lib/ldb/common/ldb_match.c @@ -153,7 +153,8 @@ static int ldb_match_equality(struct ldb_context *ldb, if (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0 || ldb_attr_cmp(tree->u.equality.attr, "distinguishedName") == 0) { - valuedn = ldb_dn_explode_casefold(ldb, tree->u.equality.value.data); + valuedn = ldb_dn_explode_casefold(ldb, + (char *)tree->u.equality.value.data); if (valuedn == NULL) { return 0; } @@ -194,7 +195,7 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, struct ldb_val cnk; struct ldb_val *chunk; char *p, *g; - char *save_p = NULL; + uint8_t *save_p = NULL; int c = 0; h = ldb_attrib_handler(ldb, tree->u.substring.attr); @@ -211,7 +212,7 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed; /* FIXME: case of embedded nulls */ - if (strncmp(val.data, cnk.data, cnk.length) != 0) goto failed; + if (strncmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed; val.length -= cnk.length; val.data += cnk.length; c++; @@ -225,16 +226,16 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, if(h->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed; /* FIXME: case of embedded nulls */ - p = strstr(val.data, cnk.data); + p = strstr((char *)val.data, (char *)cnk.data); if (p == NULL) goto failed; if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { do { /* greedy */ - g = strstr(p + cnk.length, cnk.data); + g = strstr((char *)p + cnk.length, (char *)cnk.data); if (g) p = g; } while(g); } val.length = val.length - (p - (char *)(val.data)) - cnk.length; - val.data = p + cnk.length; + val.data = (uint8_t *)(p + cnk.length); c++; talloc_free(cnk.data); cnk.data = NULL; @@ -282,8 +283,8 @@ static int ldb_match_substring(struct ldb_context *ldb, static int ldb_comparator_and(struct ldb_val *v1, struct ldb_val *v2) { uint64_t i1, i2; - i1 = strtoull(v1->data, NULL, 0); - i2 = strtoull(v2->data, NULL, 0); + i1 = strtoull((char *)v1->data, NULL, 0); + i2 = strtoull((char *)v2->data, NULL, 0); return ((i1 & i2) == i2); } @@ -293,8 +294,8 @@ static int ldb_comparator_and(struct ldb_val *v1, struct ldb_val *v2) static int ldb_comparator_or(struct ldb_val *v1, struct ldb_val *v2) { uint64_t i1, i2; - i1 = strtoull(v1->data, NULL, 0); - i2 = strtoull(v2->data, NULL, 0); + i1 = strtoull((char *)v1->data, NULL, 0); + i2 = strtoull((char *)v2->data, NULL, 0); return ((i1 & i2) != 0); } diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index c2f40f308a..01941f5728 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -107,7 +107,7 @@ struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v) /* the +1 is to cope with buggy C library routines like strndup that look one byte beyond */ - v2.data = talloc_array(mem_ctx, char, v->length+1); + v2.data = talloc_array(mem_ctx, uint8_t, v->length+1); if (!v2.data) { v2.length = 0; return v2; @@ -121,13 +121,12 @@ struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v) /* add an empty element to a message */ -int ldb_msg_add_empty(struct ldb_context *ldb, - struct ldb_message *msg, const char *attr_name, int flags) +int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) { struct ldb_message_element *els; els = talloc_realloc(msg, msg->elements, - struct ldb_message_element, msg->num_elements+1); + struct ldb_message_element, msg->num_elements+1); if (!els) { errno = ENOMEM; return -1; @@ -150,12 +149,11 @@ int ldb_msg_add_empty(struct ldb_context *ldb, /* add an empty element to a message */ -int ldb_msg_add(struct ldb_context *ldb, - struct ldb_message *msg, +int ldb_msg_add(struct ldb_message *msg, const struct ldb_message_element *el, int flags) { - if (ldb_msg_add_empty(ldb, msg, el->name, flags) != 0) { + if (ldb_msg_add_empty(msg, el->name, flags) != 0) { return -1; } @@ -168,8 +166,7 @@ int ldb_msg_add(struct ldb_context *ldb, /* add a value to a message */ -int ldb_msg_add_value(struct ldb_context *ldb, - struct ldb_message *msg, +int ldb_msg_add_value(struct ldb_message *msg, const char *attr_name, const struct ldb_val *val) { @@ -178,7 +175,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, el = ldb_msg_find_element(msg, attr_name); if (!el) { - ldb_msg_add_empty(ldb, msg, attr_name, 0); + ldb_msg_add_empty(msg, attr_name, 0); el = ldb_msg_find_element(msg, attr_name); } if (!el) { @@ -201,7 +198,7 @@ int ldb_msg_add_value(struct ldb_context *ldb, /* add a string element to a message */ -int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, +int ldb_msg_add_string(struct ldb_message *msg, const char *attr_name, const char *str) { struct ldb_val val; @@ -209,13 +206,13 @@ int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, val.data = discard_const_p(uint8_t, str); val.length = strlen(str); - return ldb_msg_add_value(ldb, msg, attr_name, &val); + return ldb_msg_add_value(msg, attr_name, &val); } /* add a printf formatted element to a message */ -int ldb_msg_add_fmt(struct ldb_context *ldb, struct ldb_message *msg, +int ldb_msg_add_fmt(struct ldb_message *msg, const char *attr_name, const char *fmt, ...) { struct ldb_val val; @@ -228,10 +225,10 @@ int ldb_msg_add_fmt(struct ldb_context *ldb, struct ldb_message *msg, if (str == NULL) return -1; - val.data = str; + val.data = (uint8_t *)str; val.length = strlen(str); - return ldb_msg_add_value(ldb, msg, attr_name, &val); + return ldb_msg_add_value(msg, attr_name, &val); } /* @@ -287,7 +284,7 @@ int ldb_msg_find_int(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return strtol(v->data, NULL, 0); + return strtol((const char *)v->data, NULL, 0); } unsigned int ldb_msg_find_uint(const struct ldb_message *msg, @@ -298,7 +295,7 @@ unsigned int ldb_msg_find_uint(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return strtoul(v->data, NULL, 0); + return strtoul((const char *)v->data, NULL, 0); } int64_t ldb_msg_find_int64(const struct ldb_message *msg, @@ -309,7 +306,7 @@ int64_t ldb_msg_find_int64(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return strtoll(v->data, NULL, 0); + return strtoll((const char *)v->data, NULL, 0); } uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, @@ -320,7 +317,7 @@ uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return strtoull(v->data, NULL, 0); + return strtoull((const char *)v->data, NULL, 0); } double ldb_msg_find_double(const struct ldb_message *msg, @@ -331,7 +328,7 @@ double ldb_msg_find_double(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return strtod(v->data, NULL); + return strtod((const char *)v->data, NULL); } const char *ldb_msg_find_string(const struct ldb_message *msg, @@ -342,7 +339,7 @@ const char *ldb_msg_find_string(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } - return v->data; + return (const char *)v->data; } /* @@ -479,7 +476,7 @@ struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, continue; } - if (ldb_msg_add(ldb, mod, + if (ldb_msg_add(mod, &msg2->elements[i], el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { return NULL; @@ -490,7 +487,7 @@ struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, for (i=0;inum_elements;i++) { el = ldb_msg_find_element(msg2, msg1->elements[i].name); if (!el) { - if (ldb_msg_add_empty(ldb, mod, + if (ldb_msg_add_empty(mod, msg1->elements[i].name, LDB_FLAG_MOD_DELETE) != 0) { return NULL; @@ -529,3 +526,71 @@ int ldb_msg_sanity_check(const struct ldb_message *msg) return LDB_SUCCESS; } + + + + +/* + copy an attribute list. This only copies the array, not the elements + (ie. the elements are left as the same pointers) +*/ +const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs) +{ + const char **ret; + int i; + for (i=0;attrs[i];i++) /* noop */ ; + ret = talloc_array(mem_ctx, const char *, i+1); + if (ret == NULL) { + return NULL; + } + for (i=0;attrs[i];i++) { + ret[i] = attrs[i]; + } + ret[i] = attrs[i]; + return ret; +} + + +/* + return 1 if an attribute is in a list of attributes, or 0 otherwise +*/ +int ldb_attr_in_list(const char * const *attrs, const char *attr) +{ + int i; + for (i=0;attrs[i];i++) { + if (ldb_attr_cmp(attrs[i], attr) == 0) { + return 1; + } + } + return 0; +} + + +/* + rename the specified attribute in a search result +*/ +void ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr); + if (el != NULL) { + el->name = replace; + } +} + + +/* + copy the specified attribute in a search result to a new attribute +*/ +int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace) +{ + struct ldb_message_element *el = ldb_msg_find_element(msg, attr); + if (el == NULL) { + return 0; + } + if (ldb_msg_add(msg, el, 0) != 0) { + return -1; + } + ldb_msg_rename_attr(msg, attr, replace); + return 0; +} + diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index e61511ebec..5824a8d003 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -753,3 +753,51 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree) return NULL; } + + +/* + replace any occurances of an attribute name in the parse tree with a + new name +*/ +void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, + const char *attr, + const char *replace) +{ + int i; + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ldb_parse_tree_attr_replace(tree->u.list.elements[i], + attr, replace); + } + break; + case LDB_OP_NOT: + ldb_parse_tree_attr_replace(tree->u.isnot.child, attr, replace); + break; + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) { + tree->u.equality.attr = replace; + } + break; + case LDB_OP_SUBSTRING: + if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) { + tree->u.substring.attr = replace; + } + break; + case LDB_OP_PRESENT: + if (ldb_attr_cmp(tree->u.present.attr, attr) == 0) { + tree->u.present.attr = replace; + } + break; + case LDB_OP_EXTENDED: + if (tree->u.extended.attr && + ldb_attr_cmp(tree->u.extended.attr, attr) == 0) { + tree->u.extended.attr = replace; + } + break; + } +} diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index cd68180f77..69faeb46d3 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -80,4 +80,3 @@ int ldb_attr_cmp(const char *attr1, const char *attr2) { return ldb_caseless_cmp(attr1, attr2); } - diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index f75964c44f..cdb0e171e5 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -7,6 +7,15 @@ INIT_OBJ_FILES = \ # End MODULE libldb_timestamps ################################################ +################################################ +# Start MODULE libldb_operational +[MODULE::libldb_operational] +SUBSYSTEM = LIBLDB +INIT_OBJ_FILES = \ + lib/ldb/modules/operational.o +# End MODULE libldb_operational +################################################ + ################################################ # Start MODULE libldb_rdn_name [MODULE::libldb_rdn_name] diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 73bac2088a..d75ca4fe86 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -182,24 +182,24 @@ struct ldb_parse_tree { struct ldb_parse_tree *child; } isnot; struct { - char *attr; + const char *attr; struct ldb_val value; } equality; struct { - char *attr; + const char *attr; int start_with_wildcard; int end_with_wildcard; struct ldb_val **chunks; } substring; struct { - char *attr; + const char *attr; } present; struct { - char *attr; + const char *attr; struct ldb_val value; } comparison; struct { - char *attr; + const char *attr; int dnAttributes; char *rule_id; struct ldb_val value; @@ -241,7 +241,10 @@ struct ldb_attrib_handler { ldb_attr_comparison_t comparison_fn; }; -#define LDB_ATTR_FLAG_HIDDEN (1<<0) +#define LDB_ATTR_FLAG_HIDDEN (1<<0) /* the attribute is not returned by default */ +#define LDB_ATTR_FLAG_CONSTRUCTED (1<<1) /* the attribute is constructed from other attributes */ +#define LDB_ATTR_FLAG_CONSTRUCTED (1<<1) /* the attribute is constructed from other attributes */ + /* well-known ldap attribute syntaxes - see rfc2252 section 4.3.2 */ #define LDB_SYNTAX_DN "1.3.6.1.4.1.1466.115.121.1.12" @@ -383,7 +386,7 @@ struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component, const struct ldb_dn *base); struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2); -struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...); +struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...) PRINTF_ATTRIBUTE(3,4); struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn); /* useful functions for ldb_message structure manipulation */ @@ -406,22 +409,19 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, struct ldb_val *val); /* add a new empty element to a ldb_message */ -int ldb_msg_add_empty(struct ldb_context *ldb, - struct ldb_message *msg, const char *attr_name, int flags); +int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags); /* add a element to a ldb_message */ -int ldb_msg_add(struct ldb_context *ldb, - struct ldb_message *msg, +int ldb_msg_add(struct ldb_message *msg, const struct ldb_message_element *el, int flags); -int ldb_msg_add_value(struct ldb_context *ldb, - struct ldb_message *msg, +int ldb_msg_add_value(struct ldb_message *msg, const char *attr_name, const struct ldb_val *val); -int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, +int ldb_msg_add_string(struct ldb_message *msg, const char *attr_name, const char *str); -int ldb_msg_add_fmt(struct ldb_context *ldb, struct ldb_message *msg, - const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); +int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); /* compare two message elements - return 0 on match */ int ldb_msg_element_compare(struct ldb_message_element *el1, @@ -485,4 +485,16 @@ void *ldb_get_opaque(struct ldb_context *ldb, const char *name); const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb, const char *attrib); + +const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs); +int ldb_attr_in_list(const char * const *attrs, const char *attr); + + +void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, + const char *attr, + const char *replace); + +void ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace); +int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace); + #endif diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 9777ad0d92..2367d6c3f8 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -145,6 +145,8 @@ void ldb_set_errstring(struct ldb_module *module, char *err_string); /* The following definitions come from lib/ldb/common/ldb_debug.c */ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); /* The following definitions come from lib/ldb/common/ldb_ldif.c */ int ldb_should_b64_encode(const struct ldb_val *val); diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c index 5e40b8fd3f..01f9338009 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_cache.c +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -95,7 +95,7 @@ static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v) int j; for (j=0;ltdb_valid_attr_flags[j].name;j++) { if (strcmp(ltdb_valid_attr_flags[j].name, - el->values[i].data) == 0) { + (char *)el->values[i].data) == 0) { value |= ltdb_valid_attr_flags[j].value; break; } @@ -197,7 +197,8 @@ static int ltdb_subclasses_load(struct ldb_module *module) for (i=0;inum_elements;i++) { struct ldb_message_element *el = &msg->elements[i]; for (j=0;jnum_values;j++) { - if (ldb_subclass_add(module->ldb, el->name, el->values[j].data) != 0) { + if (ldb_subclass_add(module->ldb, el->name, + (char *)el->values[j].data) != 0) { goto failed; } } @@ -268,7 +269,7 @@ static int ltdb_baseinfo_init(struct ldb_module *module) el.values = &val; el.num_values = 1; el.flags = 0; - val.data = talloc_strdup(msg, initial_sequence_number); + val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number); if (!val.data) { goto failed; } @@ -446,7 +447,7 @@ int ltdb_increase_sequence_number(struct ldb_module *module) el.values = &val; el.num_values = 1; el.flags = LDB_FLAG_MOD_REPLACE; - val.data = s; + val.data = (uint8_t *)s; val.length = strlen(s); ret = ltdb_modify_internal(module, msg); @@ -495,7 +496,7 @@ int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name) for (i = 0; i < attr_el->num_values; i++) { for (j=0; ltdb_valid_attr_flags[j].name; j++) { if (strcmp(ltdb_valid_attr_flags[j].name, - attr_el->values[i].data) == 0) { + (char *)attr_el->values[i].data) == 0) { ret |= ltdb_valid_attr_flags[j].value; } } @@ -514,7 +515,7 @@ int ltdb_check_at_attributes_values(const struct ldb_val *value) int i; for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) { - if ((strcmp(ltdb_valid_attr_flags[i].name, value->data) == 0)) { + if ((strcmp(ltdb_valid_attr_flags[i].name, (char *)value->data) == 0)) { return 0; } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 7c920dd78b..e80cf74c62 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -120,7 +120,7 @@ static struct ldb_dn *ldb_dn_key(struct ldb_context *ldb, return NULL; } if (ldb_should_b64_encode(&v)) { - char *vstr = ldb_base64_encode(ldb, v.data, v.length); + char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length); if (!vstr) return NULL; dn = talloc_asprintf(ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); talloc_free(vstr); @@ -261,7 +261,7 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, struct ldb_context *ldb = module->ldb; unsigned int i; int ret; - const char *target = tree->u.equality.value.data; + const char *target = (const char *)tree->u.equality.value.data; const char **subclasses; list->count = 0; @@ -279,17 +279,19 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, struct ldb_parse_tree tree2; struct dn_list *list2; tree2.operation = LDB_OP_EQUALITY; - tree2.u.equality.attr = talloc_strdup(list, LTDB_OBJECTCLASS); + tree2.u.equality.attr = LTDB_OBJECTCLASS; if (!tree2.u.equality.attr) { return -1; } - tree2.u.equality.value.data = talloc_strdup(tree2.u.equality.attr, subclasses[i]); + tree2.u.equality.value.data = + (uint8_t *)talloc_strdup(list, subclasses[i]); if (tree2.u.equality.value.data == NULL) { return -1; } tree2.u.equality.value.length = strlen(subclasses[i]); list2 = talloc(list, struct dn_list); if (list2 == NULL) { + talloc_free(tree2.u.equality.value.data); return -1; } if (ltdb_index_dn_objectclass(module, &tree2, @@ -302,7 +304,7 @@ static int ltdb_index_dn_objectclass(struct ldb_module *module, talloc_free(list2); } } - talloc_free(tree2.u.equality.attr); + talloc_free(tree2.u.equality.value.data); } return ret; @@ -747,7 +749,7 @@ static int ltdb_index_add1_new(struct ldb_context *ldb, return -1; } msg->elements[msg->num_elements].values[0].length = strlen(dn); - msg->elements[msg->num_elements].values[0].data = dn; + msg->elements[msg->num_elements].values[0].data = (uint8_t *)dn; msg->elements[msg->num_elements].num_values = 1; msg->num_elements++; @@ -770,7 +772,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, /* for multi-valued attributes we can end up with repeats */ for (i=0;ielements[idx].num_values;i++) { - if (strcmp(dn, msg->elements[idx].values[i].data) == 0) { + if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) { return 0; } } @@ -784,7 +786,7 @@ static int ltdb_index_add1_add(struct ldb_context *ldb, msg->elements[idx].values = v2; msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn); - msg->elements[idx].values[msg->elements[idx].num_values].data = dn; + msg->elements[idx].values[msg->elements[idx].num_values].data = (uint8_t *)dn; msg->elements[idx].num_values++; return 0; @@ -1027,7 +1029,7 @@ int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { const char *dn = "DN=" LTDB_INDEX ":"; - if (strncmp(key.dptr, dn, strlen(dn)) == 0) { + if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) { return tdb_delete(tdb, key); } return 0; @@ -1044,8 +1046,8 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * int ret; TDB_DATA key2; - if (strncmp(key.dptr, "DN=@", 4) == 0 || - strncmp(key.dptr, "DN=", 3) != 0) { + if (strncmp((char *)key.dptr, "DN=@", 4) == 0 || + strncmp((char *)key.dptr, "DN=", 3) != 0) { return 0; } @@ -1070,14 +1072,14 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * talloc_free(msg); return 0; } - if (strcmp(key2.dptr, key.dptr) != 0) { + if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) { tdb_delete(tdb, key); tdb_store(tdb, key2, data, 0); } talloc_free(key2.dptr); if (msg->dn == NULL) { - dn = key.dptr + 3; + dn = (char *)key.dptr + 3; } else { dn = ldb_dn_linearize(msg->dn, msg->dn); } diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 332dbf03df..bf57aa904c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -75,7 +75,7 @@ int ltdb_pack_data(struct ldb_module *module, unsigned int i, j, real_elements=0; size_t size; char *dn; - char *p; + uint8_t *p; size_t len; dn = ldb_dn_linearize(ldb, message->dn); @@ -106,7 +106,7 @@ int ltdb_pack_data(struct ldb_module *module, } /* allocate it */ - data->dptr = talloc_array(ldb, char, size); + data->dptr = talloc_array(ldb, uint8_t, size); if (!data->dptr) { talloc_free(dn); errno = ENOMEM; @@ -157,7 +157,7 @@ int ltdb_unpack_data(struct ldb_module *module, struct ldb_message *message) { struct ldb_context *ldb = module->ldb; - char *p; + uint8_t *p; unsigned int remaining; unsigned int i, j; unsigned format; @@ -183,12 +183,12 @@ int ltdb_unpack_data(struct ldb_module *module, break; case LTDB_PACKING_FORMAT: - len = strnlen(p, remaining); + len = strnlen((char *)p, remaining); if (len == remaining) { errno = EIO; goto failed; } - message->dn = ldb_dn_explode(message, p); + message->dn = ldb_dn_explode(message, (char *)p); if (message->dn == NULL) { errno = ENOMEM; goto failed; @@ -226,13 +226,13 @@ int ltdb_unpack_data(struct ldb_module *module, errno = EIO; goto failed; } - len = strnlen(p, remaining-6); + len = strnlen((char *)p, remaining-6); if (len == remaining-6) { errno = EIO; goto failed; } message->elements[i].flags = 0; - message->elements[i].name = p; + message->elements[i].name = (char *)p; remaining -= len + 1; p += len + 1; message->elements[i].num_values = pull_uint32(p, 0); diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index e0a62962c7..97f8a7d0be 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -100,17 +100,13 @@ static int msg_add_distinguished_name(struct ldb_module *module, struct ldb_mess int ret; el.flags = 0; - el.name = talloc_strdup(msg, "distinguishedName"); - if (!el.name) { - return -1; - } + el.name = "distinguishedName"; el.num_values = 1; el.values = &val; - val.data = ldb_dn_linearize(msg, msg->dn); - val.length = strlen(val.data); + val.data = (uint8_t *)ldb_dn_linearize(msg, msg->dn); + val.length = strlen((char *)val.data); ret = msg_add_element(module->ldb, msg, &el, 1); - talloc_free(el.name); return ret; } @@ -190,7 +186,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) { if (msg_add_distinguished_name(module, ret) != 0) { - return -1; + return NULL; } continue; } @@ -358,7 +354,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi int ret; if (key.dsize < 4 || - strncmp(key.dptr, "DN=", 3) != 0) { + strncmp((char *)key.dptr, "DN=", 3) != 0) { return 0; } @@ -376,7 +372,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi } if (!msg->dn) { - msg->dn = ldb_dn_explode(msg, key.dptr + 3); + msg->dn = ldb_dn_explode(msg, (char *)key.dptr + 3); if (msg->dn == NULL) { talloc_free(msg); return -1; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 22360ffb1c..b9404a557b 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -80,7 +80,7 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn) goto failed; } - key.dptr = key_str; + key.dptr = (uint8_t *)key_str; key.dsize = strlen(key_str) + 1; return key; diff --git a/source4/lib/ldb/modules/ldb_map.c b/source4/lib/ldb/modules/ldb_map.c index 246fc5709d..48aa7e2ef5 100644 --- a/source4/lib/ldb/modules/ldb_map.c +++ b/source4/lib/ldb/modules/ldb_map.c @@ -625,7 +625,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c for (j = 0; j < oldelm->num_values; j++) elm->values[j] = ldb_val_dup(elm, &oldelm->values[j]); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_CONVERT: @@ -642,7 +642,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c for (j = 0; j < oldelm->num_values; j++) elm->values[j] = attr->u.convert.convert_remote(module, elm, &oldelm->values[j]); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_KEEP: @@ -659,7 +659,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c elm->name = talloc_strdup(elm, oldelm->name); - ldb_msg_add(module->ldb, msg, elm, oldelm->flags); + ldb_msg_add(msg, elm, oldelm->flags); break; case MAP_GENERATE: @@ -671,7 +671,7 @@ static struct ldb_message *ldb_map_message_incoming(struct ldb_module *module, c if (!elm) continue; - ldb_msg_add(module->ldb, msg, elm, elm->flags); + ldb_msg_add(msg, elm, elm->flags); break; default: ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Unknown attr->type for %s", attr->local_name); @@ -750,9 +750,11 @@ static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, { int ret; struct ldb_parse_tree t_and, t_not, t_present, *childs[2]; + char *ismapped; t_present.operation = LDB_OP_PRESENT; - t_present.u.present.attr = talloc_strdup(NULL, "isMapped"); + ismapped = talloc_strdup(module, "isMapped"); + t_present.u.present.attr = ismapped; t_not.operation = LDB_OP_NOT; t_not.u.isnot.child = &t_present; @@ -765,7 +767,7 @@ static int map_search_fb(struct ldb_module *module, const struct ldb_dn *base, ret = ldb_next_search_bytree(module, base, scope, &t_and, attrs, res); - talloc_free(t_present.u.present.attr); + talloc_free(ismapped); return ret; } @@ -847,7 +849,7 @@ static int map_search_mp(struct ldb_module *module, const struct ldb_dn *base, int j; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Extra data found for remote DN: %s", ldb_dn_linearize(merged, merged->dn)); for (j = 0; j < extrares[0]->num_elements; j++) { - ldb_msg_add(module->ldb, merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); + ldb_msg_add(merged, &(extrares[0]->elements[j]), extrares[0]->elements[j].flags); } } @@ -941,7 +943,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) fb->dn = talloc_reference(fb, msg->dn); /* We add objectClass, so 'top' should be no problem */ - ldb_msg_add_string(module->ldb, mp, "objectClass", "top"); + ldb_msg_add_string(mp, "objectClass", "top"); /* make a list of remote objectclasses that can be used * given the attributes that are available and add to @@ -971,7 +973,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) /* Apparently, it contains all required elements */ if (has_musts && has_baseclasses) { - ldb_msg_add_string(module->ldb, mp, "objectClass", privdat->objectclass_maps[i].remote_name); + ldb_msg_add_string(mp, "objectClass", privdat->objectclass_maps[i].remote_name); ldb_debug(module->ldb, LDB_DEBUG_TRACE, "map_add: Adding objectClass %s", privdat->objectclass_maps[i].remote_name); } } @@ -1071,7 +1073,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) continue; } - ldb_msg_add(module->ldb, mp, elm, 0); + ldb_msg_add(mp, elm, 0); mapped++; } @@ -1083,7 +1085,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, fb, elm, 0); + ldb_msg_add(fb, elm, 0); } } @@ -1095,7 +1097,7 @@ static int map_add(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added mapped record"); - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ldb_msg_add_string(fb, "isMapped", "TRUE"); ret = ldb_next_add_record(module, fb); if (ret == -1) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_errstring(module->ldb)); @@ -1159,7 +1161,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = msg->elements[i].values[j]; } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1176,7 +1178,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]); } - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1191,7 +1193,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, mp, elm, msg->elements[i].flags); + ldb_msg_add(mp, elm, msg->elements[i].flags); mapped++; continue; @@ -1209,8 +1211,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) elm->values = talloc_reference(elm, msg->elements[i].values); elm->name = talloc_strdup(elm, msg->elements[i].name); - ldb_msg_add(module->ldb, fb, elm, msg->elements[i].flags); - + ldb_msg_add(fb, elm, msg->elements[i].flags); } } @@ -1218,7 +1219,7 @@ static int map_modify(struct ldb_module *module, const struct ldb_message *msg) ldb_debug(module->ldb, LDB_DEBUG_TRACE, "Modifying fallback record with %d elements", fb->num_elements); fb_ret = ldb_next_modify_record(module, fb); if (fb_ret == -1) { - ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE"); + ldb_msg_add_string(fb, "isMapped", "TRUE"); fb_ret = ldb_next_add_record(module, fb); } } else fb_ret = 0; diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c new file mode 100644 index 0000000000..911bc087ca --- /dev/null +++ b/source4/lib/ldb/modules/operational.c @@ -0,0 +1,217 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + handle operational attributes + */ + +/* + createTimestamp: HIDDEN, searchable, ldaptime, alias for whenCreated + modifyTimestamp: HIDDEN, searchable, ldaptime, alias for whenChanged + + for the above two, we do the search as normal, and if + createTimestamp or modifyTimestamp is asked for, then do + additional searches for whenCreated and whenChanged and fill in + the resulting values + + we also need to replace these with the whenCreated/whenChanged + equivalent in the search expression trees + + whenCreated: not-HIDDEN, CONSTRUCTED, SEARCHABLE + whenChanged: not-HIDDEN, CONSTRUCTED, SEARCHABLE + + on init we need to setup attribute handlers for these so + comparisons are done correctly. The resolution is 1 second. + + on add we need to add both the above, for current time + + on modify we need to change whenChanged + + + subschemaSubentry: HIDDEN, not-searchable, + points at DN CN=Aggregate,CN=Schema,CN=Configuration,$BASEDN + + for this one we do the search as normal, then add the static + value if requested. How do we work out the $BASEDN from inside a + module? + + + structuralObjectClass: HIDDEN, CONSTRUCTED, not-searchable. always same as objectclass? + + for this one we do the search as normal, then if requested ask + for objectclass, change the attribute name, and add it + + attributeTypes: in schema only + objectClasses: in schema only + matchingRules: in schema only + matchingRuleUse: in schema only + creatorsName: not supported by w2k3? + modifiersName: not supported by w2k3? +*/ + + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_private.h" +#include + +/* + a list of attribute names that should be substituted in the parse + tree before the search is done +*/ +static const struct { + const char *attr; + const char *replace; +} parse_tree_sub[] = { + { "createTimestamp", "whenCreated" }, + { "modifyTimestamp", "whenChanged" } +}; + +/* + a list of attribute names that are hidden, but can be searched for + using another (non-hidden) name to produce the correct result +*/ +static const struct { + const char *attr; + const char *replace; +} search_sub[] = { + { "createTimestamp", "whenCreated" }, + { "modifyTimestamp", "whenChanged" }, + { "structuralObjectClass", "objectClass" } +}; + +/* + hook search operations +*/ +static int operational_search_bytree(struct ldb_module *module, + const struct ldb_dn *base, + enum ldb_scope scope, struct ldb_parse_tree *tree, + const char * const *attrs, + struct ldb_message ***res) +{ + int i, r, a; + int ret; + const char **search_attrs = NULL; + + /* replace any attributes in the parse tree that are + searchable, but are stored using a different name in the + backend */ + for (i=0;i